linux-omap-pm 2.6.29: add omap3-touchbook support
authorKoen Kooi <koen@openembedded.org>
Fri, 25 Sep 2009 09:13:34 +0000 (11:13 +0200)
committerKoen Kooi <koen@openembedded.org>
Fri, 25 Sep 2009 09:13:34 +0000 (11:13 +0200)
32 files changed:
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/accelerometer-mma7455l.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/accelerometer-touchscreen-mux-spi.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-1.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-2.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-3.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-squashfs-mount-to-avoid-initramfs.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-1.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-2.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery2-bq27200-gpio-charged.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery2-bq27200-no-error-message.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/beagle-asoc.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/board-omap3beagle.c [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/boot-no-power-message.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/defconfig [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/defconfig.orig [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dspbridge.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-blank-rotate-accessible-by-user.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-export-status.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-fix-XY-coordinates-when-rotating.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-fix-scaling-when-rotating.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/ehci.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/logo_linux_clut224.ppm [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/memory-move-malloc-end.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/screen-backlight-accessible-by-user.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/screen-backlight.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/sound-headphone-detection.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/tincantools-puppy.diff [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/touchscreen-ads7846-export-settings.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/touchscreen-ads7846-rotation-support.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/usb-lower-current-consumption-upon-insertion.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/usb-otg-pc-connection.patch [new file with mode: 0644]
recipes/linux/linux-omap-pm_2.6.29.bb

diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/accelerometer-mma7455l.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/accelerometer-mma7455l.patch
new file mode 100644 (file)
index 0000000..f6d522e
--- /dev/null
@@ -0,0 +1,677 @@
+From 0b60175d1b7db1301e2ad3ad4d64fb0c8d121c0a Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Sat, 11 Apr 2009 13:05:21 -0700
+Subject: [PATCH] MMA7455L driver.
+
+---
+ drivers/input/misc/Kconfig    |    9 +
+ drivers/input/misc/Makefile   |    1 +
+ drivers/input/misc/mma7455l.c |  614 +++++++++++++++++++++++++++++++++++++++++
+ include/linux/mma7455l.h      |   11 +
+ 4 files changed, 635 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
+index 6fa9e38..05dca18 100644
+--- a/drivers/input/misc/Kconfig
++++ b/drivers/input/misc/Kconfig
+@@ -237,4 +237,13 @@ config INPUT_PCF50633_PMU
+        Say Y to include support for delivering  PMU events via  input
+        layer on NXP PCF50633.
++config INPUT_MMA7455L
++      tristate "Freescale MMA7455L 3-axis accelerometer"
++      depends on SPI_MASTER
++      help
++        SPI driver for the Freescale MMA7455L 3-axis accelerometer.
++
++        The userspace interface is a 3-axis (X/Y/Z) relative movement
++        Linux input device, reporting REL_[XYZ] events.
++
+ endif
+diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
+index 2fabcdb..e355d82 100644
+--- a/drivers/input/misc/Makefile
++++ b/drivers/input/misc/Makefile
+@@ -23,3 +23,4 @@ obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON)        += twl4030-pwrbutton.o
+ obj-$(CONFIG_INPUT_APANEL)            += apanel.o
+ obj-$(CONFIG_INPUT_SGI_BTNS)          += sgi_btns.o
+ obj-$(CONFIG_INPUT_PCF50633_PMU)      += pcf50633-input.o
++obj-$(CONFIG_INPUT_MMA7455L)          += mma7455l.o
+diff --git a/drivers/input/misc/mma7455l.c b/drivers/input/misc/mma7455l.c
+new file mode 100644
+index 0000000..b33c513
+--- /dev/null
++++ b/drivers/input/misc/mma7455l.c
+@@ -0,0 +1,614 @@
++/* Linux kernel driver for the Freescale MMA7455L 3-axis accelerometer
++ *
++ * Copyright (C) 2009 by Always Innovating, Inc.
++ * Author: Gregoire Gentil <gregoire@gentil.com>
++ * Author: Tim Yamin <plasm@roo.me.uk>
++ * All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ *
++ */
++
++/*
++ * What this driver doesn't yet support:
++ *
++ * - I2C
++ * - INT2 handling
++ * - Pulse detection (and the sysctls to control it)
++ * - 10-bit measurement
++ */
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++#include <linux/input.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/sysfs.h>
++#include <linux/gpio.h>
++
++#include <linux/mma7455l.h>
++#include <linux/spi/spi.h>
++
++#define MMA7455L_WHOAMI_MAGIC         0x55
++
++enum mma7455l_reg {
++      MMA7455L_REG_XOUTL              = 0x00,
++      MMA7455L_REG_XOUTH              = 0x01,
++      MMA7455L_REG_YOUTL              = 0x02,
++      MMA7455L_REG_YOUTH              = 0x03,
++      MMA7455L_REG_ZOUTL              = 0x04,
++      MMA7455L_REG_ZOUTH              = 0x05,
++      MMA7455L_REG_XOUT8              = 0x06,
++      MMA7455L_REG_YOUT8              = 0x07,
++      MMA7455L_REG_ZOUT8              = 0x08,
++      MMA7455L_REG_STATUS             = 0x09,
++      MMA7455L_REG_DETSRC             = 0x0a,
++      MMA7455L_REG_TOUT               = 0x0b,
++      MMA7455L_REG_RESERVED1          = 0x0c,
++      MMA7455L_REG_I2CAD              = 0x0d,
++      MMA7455L_REG_USRINF             = 0x0e,
++      MMA7455L_REG_WHOAMI             = 0x0f,
++      MMA7455L_REG_XOFFL              = 0x10,
++      MMA7455L_REG_XOFFH              = 0x11,
++      MMA7455L_REG_YOFFL              = 0x12,
++      MMA7455L_REG_YOFFH              = 0x13,
++      MMA7455L_REG_ZOFFL              = 0x14,
++      MMA7455L_REG_ZOFFH              = 0x15,
++      MMA7455L_REG_MCTL               = 0x16,
++      MMA7455L_REG_INTRST             = 0x17,
++      MMA7455L_REG_CTL1               = 0x18,
++      MMA7455L_REG_CTL2               = 0x19,
++      MMA7455L_REG_LDTH               = 0x1a,
++      MMA7455L_REG_PDTH               = 0x1b,
++      MMA7455L_REG_PW                 = 0x1c,
++      MMA7455L_REG_LT                 = 0x1d,
++      MMA7455L_REG_TW                 = 0x1e,
++      MMA7455L_REG_RESERVED2          = 0x1f,
++};
++
++enum mma7455l_reg_status {
++      MMA7455L_STATUS_XDA             = 0x08,
++      MMA7455L_STATUS_YDA             = 0x10,
++      MMA7455L_STATUS_ZDA             = 0x20,
++};
++
++enum mma7455l_mode {
++      MMA7455L_MODE_STANDBY           = 0,
++      MMA7455L_MODE_MEASUREMENT       = 1,
++      MMA7455L_MODE_LEVELDETECTION    = 0x42, /* Set DRPD to on */
++      MMA7455L_MODE_PULSEDETECTION    = 0x43, /* Set DRPD to on */
++      MMA7455L_MODE_MASK              = 0x43,
++};
++
++enum mma7455l_gselect {
++      MMA7455L_GSELECT_8              = 0x0,
++      MMA7455L_GSELECT_2              = 0x4,
++      MMA7455L_GSELECT_4              = 0x8,
++      MMA7455L_GSELECT_MASK           = 0xC,
++};
++
++/* FIXME */
++#define MMA7455L_F_FS                 0x0020  /* ADC full scale */
++
++struct mma7455l_info {
++      struct spi_device *spi_dev;
++      struct input_dev *input_dev;
++      struct mutex lock;
++      struct delayed_work work;
++
++      u8 mode;
++      u8 gSelect;
++
++      u8 flags;
++      u8 working;
++};
++
++/* lowlevel register access functions */
++
++#define WRITE_BIT     (1 << 7)
++#define ADDR_SHIFT    1
++
++static inline u_int8_t __reg_read(struct mma7455l_info *mma, u_int8_t reg)
++{
++      int rc;
++      u_int8_t cmd;
++
++      cmd = ((reg & 0x3f) << ADDR_SHIFT);
++      rc = spi_w8r8(mma->spi_dev, cmd);
++
++      return rc;
++}
++
++static u_int8_t reg_read(struct mma7455l_info *mma, u_int8_t reg)
++{
++      u_int8_t ret;
++
++      mutex_lock(&mma->lock);
++      ret = __reg_read(mma, reg);
++      mutex_unlock(&mma->lock);
++
++      return ret;
++}
++
++static s16 __reg_read_10(struct mma7455l_info *mma, u8 reg1, u8 reg2)
++{
++      u8 v1, v2;
++
++      v1 = __reg_read(mma, reg1);
++      v2 = __reg_read(mma, reg2);
++
++      return (v2 & 0x4) << 13 | (v2 & 0x3) << 8 | v1;
++}
++
++static inline int __reg_write(struct mma7455l_info *mma, u_int8_t reg, u_int8_t val)
++{
++      u_int8_t buf[2];
++
++      buf[0] = ((reg & 0x3f) << ADDR_SHIFT) | WRITE_BIT;
++      buf[1] = val;
++
++      return spi_write(mma->spi_dev, buf, sizeof(buf));
++}
++
++static int reg_write(struct mma7455l_info *mma, u_int8_t reg, u_int8_t val)
++{
++      int ret;
++
++      mutex_lock(&mma->lock);
++      ret = __reg_write(mma, reg, val);
++      mutex_unlock(&mma->lock);
++
++      return ret;
++}
++
++static s16 __reg_write_10(struct mma7455l_info *mma, u8 reg1, u8 reg2, s16 value)
++{
++      int ret;
++      u8 v1, v2;
++
++      v1 = value & 0xFF;
++      if(value < 0)
++              v2 = ((value >> 8) & 0x3) | 0x4;
++      else
++              v2 = 0;
++
++      ret = __reg_write(mma, reg1, v1);
++      ret = __reg_write(mma, reg2, v2);
++      return ret;
++}
++
++static void mma7455l_work(struct work_struct *work)
++{
++      struct mma7455l_info *mma =
++                      container_of(work, struct mma7455l_info, work.work);
++
++      s8 val;
++      mma->working = 1;
++
++      /* FIXME: 10 bit accuracy? */
++      if (!(mma->flags & MMA7455L_STATUS_XDA)) {
++              val = reg_read(mma, MMA7455L_REG_XOUT8);
++              input_report_abs(mma->input_dev, ABS_X, val);
++      }
++      if (!(mma->flags & MMA7455L_STATUS_YDA)) {
++              val = reg_read(mma, MMA7455L_REG_YOUT8);
++              input_report_abs(mma->input_dev, ABS_Y, val);
++      }
++      if (!(mma->flags & MMA7455L_STATUS_ZDA)) {
++              val = reg_read(mma, MMA7455L_REG_ZOUT8);
++              input_report_abs(mma->input_dev, ABS_Z, val);
++      }
++
++      mma->working = 0;
++      input_sync(mma->input_dev);
++      put_device(&mma->spi_dev->dev);
++
++      /* Enable IRQ and clear out interrupt */
++      reg_write(mma, MMA7455L_REG_INTRST, 0x3);
++      reg_write(mma, MMA7455L_REG_INTRST, 0x0);
++      enable_irq(mma->spi_dev->irq);
++}
++
++static void mma7455l_schedule_work(struct mma7455l_info *mma)
++{
++      int status;
++
++      get_device(&mma->spi_dev->dev);
++      status = schedule_delayed_work(&mma->work, HZ / 10);
++}
++
++static irqreturn_t mma7455l_interrupt(int irq, void *_mma)
++{
++      struct mma7455l_info *mma = _mma;
++      mma7455l_schedule_work(mma);
++
++      /* Disable any further interrupts until we have processed
++       * the current one */
++      disable_irq(mma->spi_dev->irq);
++      return IRQ_HANDLED;
++}
++
++/* sysfs */ 
++
++static void get_mode(struct mma7455l_info *mma, u8 *mode, u8 *gSelect)
++{
++      u8 tmp = reg_read(mma, MMA7455L_REG_MCTL);
++
++      *mode = tmp & MMA7455L_MODE_MASK;
++      *gSelect = tmp & MMA7455L_GSELECT_MASK;
++}
++
++static void set_mode(struct mma7455l_info *mma, u8 mode, u8 gSelect)
++{
++      reg_write(mma, MMA7455L_REG_MCTL, mode | gSelect);
++}
++
++static void update_mode(struct mma7455l_info *mma, u8 mode, u8 gSelect)
++{
++      mma->mode = mode;
++      mma->gSelect = gSelect;
++
++      reg_write(mma, MMA7455L_REG_MCTL, mma->mode | mma->gSelect);
++}
++
++static ssize_t show_measure(struct device *dev, struct device_attribute *attr, char *buf)
++{
++      struct mma7455l_info *mma = dev_get_drvdata(dev);
++      s8 x, y, z;
++      u8 old_Mode, old_gSelect;
++
++      get_mode(mma, &old_Mode, &old_gSelect);
++      set_mode(mma, MMA7455L_MODE_MEASUREMENT, MMA7455L_GSELECT_2);
++
++      while (reg_read(mma, MMA7455L_REG_STATUS) == 0) {
++              msleep(10);
++      }
++
++      x = reg_read(mma, MMA7455L_REG_XOUT8);
++      y = reg_read(mma, MMA7455L_REG_YOUT8);
++      z = reg_read(mma, MMA7455L_REG_ZOUT8);
++
++      set_mode(mma, old_Mode, old_gSelect);
++      return sprintf(buf, "%d %d %d\n", x, y, z);
++}
++
++static ssize_t show_mode(struct device *dev, struct device_attribute *attr, char *buf)
++{
++      struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++      switch(mma->mode)
++      {
++              case MMA7455L_MODE_STANDBY:
++                      return sprintf(buf, "Standby\n");
++                      break;
++              case MMA7455L_MODE_MEASUREMENT:
++                      return sprintf(buf, "Measurement\n");
++                      break;
++              case MMA7455L_MODE_LEVELDETECTION:
++                      return sprintf(buf, "Level Detection\n");
++                      break;
++              case MMA7455L_MODE_PULSEDETECTION:
++                      return sprintf(buf, "Pulse Detection\n");
++                      break;
++      }
++
++      return sprintf(buf, "Unknown mode!\n");
++}
++
++static ssize_t show_gSelect(struct device *dev, struct device_attribute *attr, char *buf)
++{
++      struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++      switch(mma->gSelect)
++      {
++              case MMA7455L_GSELECT_8:
++                      return sprintf(buf, "8\n");
++                      break;
++              case MMA7455L_GSELECT_4:
++                      return sprintf(buf, "4\n");
++                      break;
++              case MMA7455L_GSELECT_2:
++                      return sprintf(buf, "2\n");
++                      break;
++      }
++
++      return sprintf(buf, "Unknown gSelect!\n");
++}
++
++static ssize_t show_level_threshold(struct device *dev, struct device_attribute *attr, char *buf)
++{
++      struct mma7455l_info *mma = dev_get_drvdata(dev);
++      return sprintf(buf, "%u\n", reg_read(mma, MMA7455L_REG_LDTH));
++}
++
++static ssize_t show_calibration(struct device *dev, struct device_attribute *attr, char *buf)
++{
++      s16 x, y, z;
++      struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++      mutex_lock(&mma->lock);
++      x = __reg_read_10(mma, MMA7455L_REG_XOFFL, MMA7455L_REG_XOFFH);
++      y = __reg_read_10(mma, MMA7455L_REG_YOFFL, MMA7455L_REG_YOFFH);
++      z = __reg_read_10(mma, MMA7455L_REG_ZOFFL, MMA7455L_REG_ZOFFH);
++      mutex_unlock(&mma->lock);
++
++      return sprintf(buf, "%d %d %d\n", x, y, z);
++}
++
++static ssize_t write_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++      struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++      if (!strncmp(buf, "Standby", count))
++              update_mode(mma, MMA7455L_MODE_STANDBY, mma->gSelect);
++      else if (!strncmp(buf, "Measurement", count))
++              update_mode(mma, MMA7455L_MODE_MEASUREMENT, mma->gSelect);
++      else if (!strncmp(buf, "Level Detection", count))
++              update_mode(mma, MMA7455L_MODE_LEVELDETECTION, mma->gSelect);
++      else if (!strncmp(buf, "Pulse Detection", count))
++              update_mode(mma, MMA7455L_MODE_PULSEDETECTION, mma->gSelect);
++
++      return count;
++}
++
++static ssize_t write_gSelect(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++      unsigned long v;
++      struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++      if(strict_strtoul(buf, 10, &v) == 0)
++      {
++              switch(v)
++              {
++                      case 8:
++                              update_mode(mma, mma->mode, MMA7455L_GSELECT_8);
++                              break;
++                      case 4:
++                              update_mode(mma, mma->mode, MMA7455L_GSELECT_4);
++                              break;
++                      case 2:
++                              update_mode(mma, mma->mode, MMA7455L_GSELECT_2);
++                              break;
++                      default:
++                              return -EINVAL;
++                              break;
++              }
++              return count;
++      }
++
++      return -EINVAL;
++}
++
++static ssize_t write_level_threshold(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++      unsigned long v;
++      struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++      if(strict_strtoul(buf, 10, &v) == 0)
++      {
++              if(v <= 0xFF) {
++                      reg_write(mma, MMA7455L_REG_LDTH, v);
++                      return count;
++              } else
++                      return -EINVAL;
++      }
++
++      return -EINVAL;
++}
++
++static ssize_t write_calibration(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++      int x, y, z;
++      struct mma7455l_info *mma = dev_get_drvdata(dev);
++
++      if (sscanf(buf, "%d %d %d", &x, &y, &z) == 3)
++      {
++              mutex_lock(&mma->lock);
++              __reg_write_10(mma, MMA7455L_REG_XOFFL, MMA7455L_REG_XOFFH, x);
++              __reg_write_10(mma, MMA7455L_REG_YOFFL, MMA7455L_REG_YOFFH, y);
++              __reg_write_10(mma, MMA7455L_REG_ZOFFL, MMA7455L_REG_ZOFFH, z);
++              mutex_unlock(&mma->lock);
++
++              return count;
++      }
++
++      return -EINVAL;
++}
++
++static DEVICE_ATTR(measure, S_IRUGO, show_measure, NULL);
++static DEVICE_ATTR(mode, S_IRUGO | S_IWUGO, show_mode, write_mode);
++static DEVICE_ATTR(gSelect, S_IRUGO | S_IWUGO, show_gSelect, write_gSelect);
++static DEVICE_ATTR(level_threshold, S_IRUGO | S_IWUGO, show_level_threshold, write_level_threshold);
++static DEVICE_ATTR(calibration, S_IRUGO | S_IWUGO, show_calibration, write_calibration);
++
++static struct attribute *mma7455l_sysfs_entries[] = {
++        &dev_attr_measure.attr,
++      &dev_attr_mode.attr,
++      &dev_attr_gSelect.attr,
++      &dev_attr_level_threshold.attr,
++      &dev_attr_calibration.attr,
++      NULL
++};
++
++static struct attribute_group mma7455l_attr_group = {
++        .attrs  = mma7455l_sysfs_entries,
++};
++
++/* input device handling and driver core interaction */
++static int mma7455l_input_open(struct input_dev *inp)
++{
++      struct mma7455l_info *mma = input_get_drvdata(inp);
++      if(mma->mode == MMA7455L_MODE_STANDBY)
++              update_mode(mma, MMA7455L_MODE_MEASUREMENT, mma->gSelect);
++
++      return 0;
++}
++
++static void mma7455l_input_close(struct input_dev *inp)
++{
++      struct mma7455l_info *mma = input_get_drvdata(inp);
++      update_mode(mma, MMA7455L_MODE_STANDBY, MMA7455L_GSELECT_2);
++}
++
++static int __devinit mma7455l_probe(struct spi_device *spi)
++{
++      int rc;
++      struct mma7455l_info *mma;
++      struct mma7455l_platform_data *pdata = spi->dev.platform_data;
++      u_int8_t wai;
++
++      mma = kzalloc(sizeof(*mma), GFP_KERNEL);
++      if (!mma)
++              return -ENOMEM;
++
++      mutex_init(&mma->lock);
++      INIT_DELAYED_WORK(&mma->work, mma7455l_work);
++      mma->spi_dev = spi;
++      mma->flags = mma->working = 0;
++
++      spi_set_drvdata(spi, mma);
++
++      rc = spi_setup(spi);
++      if (rc < 0) {
++              printk(KERN_ERR "mma7455l error durign spi_setup of mma7455l driver\n");
++              dev_set_drvdata(&spi->dev, NULL);
++              kfree(mma);
++              return rc;
++      }
++
++      wai = reg_read(mma, MMA7455L_REG_WHOAMI);
++      if (wai != MMA7455L_WHOAMI_MAGIC) {
++              printk(KERN_ERR "mma7455l unknown whoami signature 0x%02x\n", wai);
++              dev_set_drvdata(&spi->dev, NULL);
++              kfree(mma);
++              return -ENODEV;
++      }
++
++      rc = request_irq(mma->spi_dev->irq, mma7455l_interrupt, IRQF_TRIGGER_HIGH,
++                       "mma7455l", mma);
++      if (rc < 0) {
++              dev_err(&spi->dev, "mma7455l error requesting IRQ %d\n",
++                      mma->spi_dev->irq);
++              /* FIXME */
++              return rc;
++      }
++
++        rc = sysfs_create_group(&spi->dev.kobj, &mma7455l_attr_group);
++        if (rc) {
++                dev_err(&spi->dev, "error creating sysfs group\n");
++                return rc;
++        }
++
++      /* initialize input layer details */
++      mma->input_dev = input_allocate_device();
++      if (!mma->input_dev) {
++              dev_err(&spi->dev, "mma7455l Unable to allocate input device\n");
++              /* FIXME */
++      }
++
++      set_bit(EV_ABS, mma->input_dev->evbit);
++      set_bit(ABS_X, mma->input_dev->absbit);
++      set_bit(ABS_Y, mma->input_dev->absbit);
++      set_bit(ABS_Z, mma->input_dev->absbit);
++
++      input_set_drvdata(mma->input_dev, mma);
++      mma->input_dev->name = "MMA7455L";
++      mma->input_dev->open = mma7455l_input_open;
++      mma->input_dev->close = mma7455l_input_close;
++
++      rc = input_register_device(mma->input_dev);
++      if(!rc)
++      {
++              update_mode(mma, MMA7455L_MODE_STANDBY, MMA7455L_GSELECT_2);
++
++              mutex_lock(&mma->lock);
++              __reg_write_10(mma, MMA7455L_REG_XOFFL, MMA7455L_REG_XOFFH, pdata->calibration_x);
++              __reg_write_10(mma, MMA7455L_REG_YOFFL, MMA7455L_REG_YOFFH, pdata->calibration_y);
++              __reg_write_10(mma, MMA7455L_REG_ZOFFL, MMA7455L_REG_ZOFFH, pdata->calibration_z);
++              mutex_unlock(&mma->lock);
++
++              return 0;
++      }
++
++      input_free_device(mma->input_dev);
++      return rc;
++}
++
++static int __devexit mma7455l_remove(struct spi_device *spi)
++{
++      struct mma7455l_info *mma = dev_get_drvdata(&spi->dev);
++
++        sysfs_remove_group(&spi->dev.kobj, &mma7455l_attr_group);
++      input_unregister_device(mma->input_dev);
++      dev_set_drvdata(&spi->dev, NULL);
++      kfree(mma);
++
++      return 0;
++}
++
++#ifdef CONFIG_PM
++static int mma7455l_suspend(struct spi_device *spi, pm_message_t message)
++{
++      struct mma7455l_info *mma = dev_get_drvdata(&spi->dev);
++      get_mode(mma, &mma->mode, &mma->gSelect);
++      set_mode(mma, MMA7455L_MODE_STANDBY, MMA7455L_GSELECT_2);
++
++      return 0;
++}
++
++static int mma7455l_resume(struct spi_device *spi)
++{
++      struct mma7455l_info *mma = dev_get_drvdata(&spi->dev);
++      update_mode(mma, mma->mode, mma->gSelect);
++
++      return 0;
++}
++#else
++#define mma7455l_suspend NULL
++#define mma7455l_resume  NULL
++#endif
++
++static struct spi_driver mma7455l_driver = {
++      .driver = {
++              .name   = "mma7455l",
++              .owner  = THIS_MODULE,
++      },
++
++      .probe   = mma7455l_probe,
++      .remove  = __devexit_p(mma7455l_remove),
++      .suspend = mma7455l_suspend,
++      .resume  = mma7455l_resume,
++};
++
++static int __init mma7455l_init(void)
++{
++      return spi_register_driver(&mma7455l_driver);
++}
++
++static void __exit mma7455l_exit(void)
++{
++      spi_unregister_driver(&mma7455l_driver);
++}
++
++MODULE_AUTHOR("Gregoire Gentil <gregoire@gentil.com>");
++MODULE_LICENSE("GPL");
++
++module_init(mma7455l_init);
++module_exit(mma7455l_exit);
+diff --git a/include/linux/mma7455l.h b/include/linux/mma7455l.h
+new file mode 100644
+index 0000000..12ab50a
+--- /dev/null
++++ b/include/linux/mma7455l.h
+@@ -0,0 +1,11 @@
++#ifndef _LINUX_MMA7455L_H
++#define _LINUX_MMA7455L_H
++
++struct mma7455l_platform_data {
++      /* Calibration offsets */
++      s16 calibration_x;
++      s16 calibration_y;
++      s16 calibration_z;
++};
++
++#endif /* _LINUX_MMA7455L_H */
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/accelerometer-touchscreen-mux-spi.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/accelerometer-touchscreen-mux-spi.patch
new file mode 100644 (file)
index 0000000..57bb419
--- /dev/null
@@ -0,0 +1,64 @@
+--- a/arch/arm/mach-omap2/devices.c    2009-02-17 21:15:12.000000000 -0800
++++ b/arch/arm/mach-omap2/devices.c    2009-02-17 22:30:26.000000000 -0800
+@@ -15,6 +15,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+ #include <linux/clk.h>
++#include <linux/spi/spi_gpio.h> 
+ #include <mach/hardware.h>
+ #include <asm/mach-types.h>
+@@ -347,6 +348,37 @@
+               .platform_data = &omap2_mcspi4_config,
+       },
+ };
++
++static struct spi_gpio_platform_data spi3_gpio_platform_data = {
++       .miso           = 132,
++       .mosi           = 131,
++       .sck            = 130,
++       .num_chipselect = 1,
++};
++
++static struct platform_device spi3_gpio = {
++       .name           = "spi_gpio",
++       .id             = 3,
++       .dev            = {
++               .platform_data = &spi3_gpio_platform_data,
++       },
++};
++ 
++static struct spi_gpio_platform_data spi4_gpio_platform_data = {
++       .miso           = 159,
++       .mosi           = 158,
++       .sck            = 156,
++       .num_chipselect = 1,
++};
++
++static struct platform_device spi4_gpio = {
++       .name           = "spi_gpio",
++       .id             = 4,
++       .dev            = {
++               .platform_data = &spi4_gpio_platform_data,
++       },
++};
++ 
+ #endif
+ static void omap_init_mcspi(void)
+--- a/drivers/input/touchscreen/ads7846.c      2009-04-07 10:04:12.000000000 -0700
++++ b/drivers/input/touchscreen/ads7846.c      2009-04-11 12:39:51.000000000 -0700
+@@ -887,13 +919,6 @@
+               return 0;
+       }
+-      err = gpio_request(pdata->gpio_pendown, "ads7846_pendown");
+-      if (err) {
+-              dev_err(&spi->dev, "failed to request pendown GPIO%d\n",
+-                              pdata->gpio_pendown);
+-              return err;
+-      }
+-
+       ts->gpio_pendown = pdata->gpio_pendown;
+       return 0;
+ }
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-1.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-1.patch
new file mode 100644 (file)
index 0000000..3b54e71
--- /dev/null
@@ -0,0 +1,35 @@
+aufs2 kbuild patch for linux-2.6.29
+
+diff --git a/fs/Kconfig b/fs/Kconfig
+index 93945dd..75156dd 100644
+--- a/fs/Kconfig
++++ b/fs/Kconfig
+@@ -222,6 +222,7 @@ source "fs/qnx4/Kconfig"
+ source "fs/romfs/Kconfig"
+ source "fs/sysv/Kconfig"
+ source "fs/ufs/Kconfig"
++source "fs/aufs/Kconfig"
+ endif # MISC_FILESYSTEMS
+diff --git a/fs/Makefile b/fs/Makefile
+index dc20db3..a4e9a65 100644
+--- a/fs/Makefile
++++ b/fs/Makefile
+@@ -124,3 +124,4 @@ obj-$(CONFIG_DEBUG_FS)             += debugfs/
+ obj-$(CONFIG_OCFS2_FS)                += ocfs2/
+ obj-$(CONFIG_BTRFS_FS)                += btrfs/
+ obj-$(CONFIG_GFS2_FS)           += gfs2/
++obj-$(CONFIG_AUFS_FS)           += aufs/
+diff --git a/include/linux/Kbuild b/include/linux/Kbuild
+index 106c3ba..d0c7262 100644
+--- a/include/linux/Kbuild
++++ b/include/linux/Kbuild
+@@ -34,6 +34,7 @@ header-y += atmppp.h
+ header-y += atmsap.h
+ header-y += atmsvc.h
+ header-y += atm_zatm.h
++header-y += aufs_type.h
+ header-y += auto_fs4.h
+ header-y += ax25.h
+ header-y += b1lli.h
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-2.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-2.patch
new file mode 100644 (file)
index 0000000..bc3d5d8
--- /dev/null
@@ -0,0 +1,285 @@
+aufs2 standalone patch for linux-2.6.29
+
+diff --git a/fs/namei.c b/fs/namei.c
+index bbc15c2..f446c65 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -335,6 +335,9 @@ int deny_write_access(struct file * file)
+       return 0;
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(deny_write_access);
++#endif
+ /**
+  * path_get - get a reference to a path
+@@ -1196,7 +1199,7 @@ out:
+  * needs parent already locked. Doesn't follow mounts.
+  * SMP-safe.
+  */
+-static struct dentry *lookup_hash(struct nameidata *nd)
++struct dentry *lookup_hash(struct nameidata *nd)
+ {
+       int err;
+@@ -1205,8 +1208,11 @@ static struct dentry *lookup_hash(struct nameidata *nd)
+               return ERR_PTR(err);
+       return __lookup_hash(&nd->last, nd->path.dentry, nd);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(lookup_hash);
++#endif
+-static int __lookup_one_len(const char *name, struct qstr *this,
++int __lookup_one_len(const char *name, struct qstr *this,
+               struct dentry *base, int len)
+ {
+       unsigned long hash;
+@@ -1227,6 +1233,9 @@ static int __lookup_one_len(const char *name, struct qstr *this,
+       this->hash = end_name_hash(hash);
+       return 0;
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(__lookup_one_len);
++#endif
+ /**
+  * lookup_one_len - filesystem helper to lookup single pathname component
+diff --git a/fs/namespace.c b/fs/namespace.c
+index 06f8e63..dcdc4ff 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -37,6 +37,9 @@
+ /* spinlock for vfsmount related operations, inplace of dcache_lock */
+ __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
++#if defined(CONFIG_AUFS_FS_MODULE) && defined(CONFIG_AUFS_EXPORT)
++EXPORT_SYMBOL(vfsmount_lock);
++#endif
+ static int event;
+ static DEFINE_IDA(mnt_id_ida);
+diff --git a/fs/open.c b/fs/open.c
+index a3a78ce..7d70245 100644
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -220,6 +220,9 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
+       mutex_unlock(&dentry->d_inode->i_mutex);
+       return err;
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(do_truncate);
++#endif
+ static long do_sys_truncate(const char __user *pathname, loff_t length)
+ {
+diff --git a/fs/splice.c b/fs/splice.c
+index 4ed0ba4..a110d76 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -888,8 +888,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
+ /*
+  * Attempt to initiate a splice from pipe to file.
+  */
+-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+-                         loff_t *ppos, size_t len, unsigned int flags)
++long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
++                  loff_t *ppos, size_t len, unsigned int flags)
+ {
+       int ret;
+@@ -908,13 +908,16 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+       return out->f_op->splice_write(pipe, out, ppos, len, flags);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(do_splice_from);
++#endif
+ /*
+  * Attempt to initiate a splice from a file to a pipe.
+  */
+-static long do_splice_to(struct file *in, loff_t *ppos,
+-                       struct pipe_inode_info *pipe, size_t len,
+-                       unsigned int flags)
++long do_splice_to(struct file *in, loff_t *ppos,
++                struct pipe_inode_info *pipe, size_t len,
++                unsigned int flags)
+ {
+       int ret;
+@@ -930,6 +933,9 @@ static long do_splice_to(struct file *in, loff_t *ppos,
+       return in->f_op->splice_read(in, ppos, pipe, len, flags);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(do_splice_to);
++#endif
+ /**
+  * splice_direct_to_actor - splices data directly between two non-pipes
+diff --git a/fs/super.c b/fs/super.c
+index 6ce5014..95eefb9 100644
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -287,6 +287,9 @@ int fsync_super(struct super_block *sb)
+       __fsync_super(sb);
+       return sync_blockdev(sb->s_bdev);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(fsync_super);
++#endif
+ /**
+  *    generic_shutdown_super  -       common helper for ->kill_sb()
+diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
+index 23bf02f..49e5b47 100644
+--- a/include/linux/lockdep.h
++++ b/include/linux/lockdep.h
+@@ -58,7 +58,7 @@ enum lock_usage_bit
+ #define LOCKF_USED_IN_IRQ_READ \
+               (LOCKF_USED_IN_HARDIRQ_READ | LOCKF_USED_IN_SOFTIRQ_READ)
+-#define MAX_LOCKDEP_SUBCLASSES                8UL
++#define MAX_LOCKDEP_SUBCLASSES                12UL
+ /*
+  * Lock-classes are keyed via unique addresses, by embedding the
+diff --git a/include/linux/namei.h b/include/linux/namei.h
+index fc2e035..182d43b 100644
+--- a/include/linux/namei.h
++++ b/include/linux/namei.h
+@@ -75,6 +75,9 @@ extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry
+ extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
+ extern void release_open_intent(struct nameidata *);
++extern struct dentry *lookup_hash(struct nameidata *nd);
++extern int __lookup_one_len(const char *name, struct qstr *this,
++                          struct dentry *base, int len);
+ extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
+ extern struct dentry *lookup_one_noperm(const char *, struct dentry *);
+diff --git a/include/linux/splice.h b/include/linux/splice.h
+index 528dcb9..5123bc6 100644
+--- a/include/linux/splice.h
++++ b/include/linux/splice.h
+@@ -71,4 +71,10 @@ extern ssize_t splice_to_pipe(struct pipe_inode_info *,
+ extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *,
+                                     splice_direct_actor *);
++extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
++                         loff_t *ppos, size_t len, unsigned int flags);
++extern long do_splice_to(struct file *in, loff_t *ppos,
++                       struct pipe_inode_info *pipe, size_t len,
++                       unsigned int flags);
++
+ #endif
+diff --git a/security/device_cgroup.c b/security/device_cgroup.c
+index 3aacd0f..76c8876 100644
+--- a/security/device_cgroup.c
++++ b/security/device_cgroup.c
+@@ -507,6 +507,9 @@ acc_check:
+       return -EPERM;
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(devcgroup_inode_permission);
++#endif
+ int devcgroup_inode_mknod(int mode, dev_t dev)
+ {
+diff --git a/security/security.c b/security/security.c
+index c3586c0..f8798f8 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -389,6 +389,9 @@ int security_path_mkdir(struct path *path, struct dentry *dentry, int mode)
+               return 0;
+       return security_ops->path_mkdir(path, dentry, mode);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_mkdir);
++#endif
+ int security_path_rmdir(struct path *path, struct dentry *dentry)
+ {
+@@ -396,6 +399,9 @@ int security_path_rmdir(struct path *path, struct dentry *dentry)
+               return 0;
+       return security_ops->path_rmdir(path, dentry);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_rmdir);
++#endif
+ int security_path_unlink(struct path *path, struct dentry *dentry)
+ {
+@@ -403,6 +409,9 @@ int security_path_unlink(struct path *path, struct dentry *dentry)
+               return 0;
+       return security_ops->path_unlink(path, dentry);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_unlink);
++#endif
+ int security_path_symlink(struct path *path, struct dentry *dentry,
+                         const char *old_name)
+@@ -411,6 +420,9 @@ int security_path_symlink(struct path *path, struct dentry *dentry,
+               return 0;
+       return security_ops->path_symlink(path, dentry, old_name);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_symlink);
++#endif
+ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
+                      struct dentry *new_dentry)
+@@ -419,6 +431,9 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
+               return 0;
+       return security_ops->path_link(old_dentry, new_dir, new_dentry);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_link);
++#endif
+ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
+                        struct path *new_dir, struct dentry *new_dentry)
+@@ -429,6 +444,9 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
+       return security_ops->path_rename(old_dir, old_dentry, new_dir,
+                                        new_dentry);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_rename);
++#endif
+ int security_path_truncate(struct path *path, loff_t length,
+                          unsigned int time_attrs)
+@@ -437,6 +455,9 @@ int security_path_truncate(struct path *path, loff_t length,
+               return 0;
+       return security_ops->path_truncate(path, length, time_attrs);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_path_truncate);
++#endif
+ #endif
+ int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
+@@ -506,6 +527,9 @@ int security_inode_readlink(struct dentry *dentry)
+               return 0;
+       return security_ops->inode_readlink(dentry);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_inode_readlink);
++#endif
+ int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
+ {
+@@ -520,6 +544,9 @@ int security_inode_permission(struct inode *inode, int mask)
+               return 0;
+       return security_ops->inode_permission(inode, mask);
+ }
++#ifdef CONFIG_AUFS_FS_MODULE
++EXPORT_SYMBOL(security_inode_permission);
++#endif
+ int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
+ {
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-3.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-3.patch
new file mode 100644 (file)
index 0000000..34a035a
--- /dev/null
@@ -0,0 +1,23604 @@
+diff -Naur a/Documentation/ABI/testing/debugfs-aufs b/Documentation/ABI/testing/debugfs-aufs
+--- a/Documentation/ABI/testing/debugfs-aufs   1969-12-31 16:00:00.000000000 -0800
++++ b/Documentation/ABI/testing/debugfs-aufs   2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,40 @@
++What:         /debug/aufs/si_<id>/
++Date:         March 2009
++Contact:      J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++              Under /debug/aufs, a directory named si_<id> is created
++              per aufs mount, where <id> is a unique id generated
++              internally.
++
++What:         /debug/aufs/si_<id>/xib
++Date:         March 2009
++Contact:      J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++              It shows the consumed blocks by xib (External Inode Number
++              Bitmap), its block size and file size.
++              When the aufs mount option 'noxino' is specified, it
++              will be empty. About XINO files, see
++              Documentation/filesystems/aufs/aufs.5 in detail.
++
++What:         /debug/aufs/si_<id>/xino0, xino1 ... xinoN
++Date:         March 2009
++Contact:      J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++              It shows the consumed blocks by xino (External Inode Number
++              Translation Table), its link count, block size and file
++              size.
++              When the aufs mount option 'noxino' is specified, it
++              will be empty. About XINO files, see
++              Documentation/filesystems/aufs/aufs.5 in detail.
++
++What:         /debug/aufs/si_<id>/xigen
++Date:         March 2009
++Contact:      J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++              It shows the consumed blocks by xigen (External Inode
++              Generation Table), its block size and file size.
++              If CONFIG_AUFS_EXPORT is disabled, this entry will not
++              be created.
++              When the aufs mount option 'noxino' is specified, it
++              will be empty. About XINO files, see
++              Documentation/filesystems/aufs/aufs.5 in detail.
+diff -Naur a/Documentation/ABI/testing/sysfs-aufs b/Documentation/ABI/testing/sysfs-aufs
+--- a/Documentation/ABI/testing/sysfs-aufs     1969-12-31 16:00:00.000000000 -0800
++++ b/Documentation/ABI/testing/sysfs-aufs     2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,25 @@
++What:         /sys/fs/aufs/si_<id>/
++Date:         March 2009
++Contact:      J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++              Under /sys/fs/aufs, a directory named si_<id> is created
++              per aufs mount, where <id> is a unique id generated
++              internally.
++
++What:         /sys/fs/aufs/si_<id>/br0, br1 ... brN
++Date:         March 2009
++Contact:      J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++              It shows the abolute path of a member directory (which
++              is called branch) in aufs, and its permission.
++
++What:         /sys/fs/aufs/si_<id>/xi_path
++Date:         March 2009
++Contact:      J. R. Okajima <hooanon05@yahoo.co.jp>
++Description:
++              It shows the abolute path of XINO (External Inode Number
++              Bitmap, Translation Table and Generation Table) file
++              even if it is the default path.
++              When the aufs mount option 'noxino' is specified, it
++              will be empty. About XINO files, see
++              Documentation/filesystems/aufs/aufs.5 in detail.
+diff -Naur a/fs/aufs/aufs.h b/fs/aufs/aufs.h
+--- a/fs/aufs/aufs.h   1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/aufs.h   2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,51 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * all header files
++ */
++
++#ifndef __AUFS_H__
++#define __AUFS_H__
++
++#ifdef __KERNEL__
++
++#include "debug.h"
++
++#include "branch.h"
++#include "cpup.h"
++#include "dcsub.h"
++#include "dbgaufs.h"
++#include "dentry.h"
++#include "dir.h"
++#include "file.h"
++#include "fstype.h"
++#include "inode.h"
++#include "loop.h"
++#include "module.h"
++#include "opts.h"
++#include "rwsem.h"
++#include "spl.h"
++#include "super.h"
++#include "sysaufs.h"
++#include "vfsub.h"
++#include "whout.h"
++#include "wkq.h"
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_H__ */
+diff -Naur a/fs/aufs/branch.c b/fs/aufs/branch.c
+--- a/fs/aufs/branch.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/branch.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,956 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * branch management
++ */
++
++#include <linux/file.h>
++#include "aufs.h"
++
++/*
++ * free a single branch
++ */
++static void au_br_do_free(struct au_branch *br)
++{
++      int i;
++      struct au_wbr *wbr;
++
++      if (br->br_xino.xi_file)
++              fput(br->br_xino.xi_file);
++      mutex_destroy(&br->br_xino.xi_nondir_mtx);
++
++      AuDebugOn(atomic_read(&br->br_count));
++
++      wbr = br->br_wbr;
++      if (wbr) {
++              for (i = 0; i < AuBrWh_Last; i++)
++                      dput(wbr->wbr_wh[i]);
++              AuDebugOn(atomic_read(&wbr->wbr_wh_running));
++              au_rwsem_destroy(&wbr->wbr_wh_rwsem);
++      }
++
++      /* some filesystems acquire extra lock */
++      lockdep_off();
++      mntput(br->br_mnt);
++      lockdep_on();
++
++      kfree(wbr);
++      kfree(br);
++}
++
++/*
++ * frees all branches
++ */
++void au_br_free(struct au_sbinfo *sbinfo)
++{
++      aufs_bindex_t bmax;
++      struct au_branch **br;
++
++      bmax = sbinfo->si_bend + 1;
++      br = sbinfo->si_branch;
++      while (bmax--)
++              au_br_do_free(*br++);
++}
++
++/*
++ * find the index of a branch which is specified by @br_id.
++ */
++int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
++{
++      aufs_bindex_t bindex, bend;
++
++      bend = au_sbend(sb);
++      for (bindex = 0; bindex <= bend; bindex++)
++              if (au_sbr_id(sb, bindex) == br_id)
++                      return bindex;
++      return -1;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * add a branch
++ */
++
++static int test_overlap(struct super_block *sb, struct dentry *h_d1,
++                      struct dentry *h_d2)
++{
++      if (unlikely(h_d1 == h_d2))
++              return 1;
++      return !!au_test_subdir(h_d1, h_d2)
++              || !!au_test_subdir(h_d2, h_d1)
++              || au_test_loopback_overlap(sb, h_d1, h_d2)
++              || au_test_loopback_overlap(sb, h_d2, h_d1);
++}
++
++/*
++ * returns a newly allocated branch. @new_nbranch is a number of branches
++ * after adding a branch.
++ */
++static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
++                                   int perm)
++{
++      struct au_branch *add_branch;
++      struct dentry *root;
++
++      root = sb->s_root;
++      add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
++      if (unlikely(!add_branch))
++              goto out;
++
++      add_branch->br_wbr = NULL;
++      if (au_br_writable(perm)) {
++              /* may be freed separately at changing the branch permission */
++              add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
++                                           GFP_NOFS);
++              if (unlikely(!add_branch->br_wbr))
++                      goto out_br;
++      }
++
++      if (unlikely(au_sbr_realloc(au_sbi(sb), new_nbranch)
++                   || au_di_realloc(au_di(root), new_nbranch)
++                   || au_ii_realloc(au_ii(root->d_inode), new_nbranch)))
++              goto out_wbr;
++      return add_branch; /* success */
++
++ out_wbr:
++      kfree(add_branch->br_wbr);
++ out_br:
++      kfree(add_branch);
++ out:
++      return ERR_PTR(-ENOMEM);
++}
++
++/*
++ * test if the branch permission is legal or not.
++ */
++static int test_br(struct inode *inode, int brperm, char *path)
++{
++      int err;
++
++      err = 0;
++      if (unlikely(au_br_writable(brperm) && IS_RDONLY(inode))) {
++              AuErr("write permission for readonly mount or inode, %s\n",
++                    path);
++              err = -EINVAL;
++      }
++
++      return err;
++}
++
++/*
++ * returns:
++ * 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 au_opt_add *add, int remount)
++{
++      int err;
++      aufs_bindex_t bend, bindex;
++      struct dentry *root;
++      struct inode *inode, *h_inode;
++
++      root = sb->s_root;
++      bend = au_sbend(sb);
++      if (unlikely(bend >= 0
++                   && au_find_dbindex(root, add->path.dentry) >= 0)) {
++              err = 1;
++              if (!remount) {
++                      err = -EINVAL;
++                      AuErr("%s duplicated\n", add->pathname);
++              }
++              goto out;
++      }
++
++      err = -ENOSPC; /* -E2BIG; */
++      if (unlikely(AUFS_BRANCH_MAX <= add->bindex
++                   || AUFS_BRANCH_MAX - 1 <= bend)) {
++              AuErr("number of branches exceeded %s\n", add->pathname);
++              goto out;
++      }
++
++      err = -EDOM;
++      if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
++              AuErr("bad index %d\n", add->bindex);
++              goto out;
++      }
++
++      inode = add->path.dentry->d_inode;
++      err = -ENOENT;
++      if (unlikely(!inode->i_nlink)) {
++              AuErr("no existence %s\n", add->pathname);
++              goto out;
++      }
++
++      err = -EINVAL;
++      if (unlikely(inode->i_sb == sb)) {
++              AuErr("%s must be outside\n", add->pathname);
++              goto out;
++      }
++
++      if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
++              AuErr("unsupported filesystem, %s (%s)\n",
++                    add->pathname, au_sbtype(inode->i_sb));
++              goto out;
++      }
++
++      err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
++      if (unlikely(err))
++              goto out;
++
++      if (bend < 0)
++              return 0; /* success */
++
++      err = -EINVAL;
++      for (bindex = 0; bindex <= bend; bindex++)
++              if (unlikely(test_overlap(sb, add->path.dentry,
++                                        au_h_dptr(root, bindex)))) {
++                      AuErr("%s is overlapped\n", add->pathname);
++                      goto out;
++              }
++
++      err = 0;
++      if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
++              h_inode = au_h_dptr(root, 0)->d_inode;
++              if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
++                  || h_inode->i_uid != inode->i_uid
++                  || h_inode->i_gid != inode->i_gid)
++                      AuWarn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
++                             add->pathname,
++                             inode->i_uid, inode->i_gid,
++                             (inode->i_mode & S_IALLUGO),
++                             h_inode->i_uid, h_inode->i_gid,
++                             (h_inode->i_mode & S_IALLUGO));
++      }
++
++ out:
++      return err;
++}
++
++/*
++ * initialize or clean the whiteouts for an adding branch
++ */
++static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
++                       int new_perm, struct dentry *h_root)
++{
++      int err, old_perm;
++      aufs_bindex_t bindex;
++      struct mutex *h_mtx;
++      struct au_wbr *wbr;
++      struct au_hinode *hdir;
++
++      wbr = br->br_wbr;
++      old_perm = br->br_perm;
++      br->br_perm = new_perm;
++      hdir = NULL;
++      h_mtx = NULL;
++      bindex = au_br_index(sb, br->br_id);
++      if (0 <= bindex) {
++              hdir = au_hi(sb->s_root->d_inode, bindex);
++              au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++      } else {
++              h_mtx = &h_root->d_inode->i_mutex;
++              mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
++      }
++      if (!wbr)
++              err = au_wh_init(h_root, br, sb);
++      else {
++              wbr_wh_write_lock(wbr);
++              err = au_wh_init(h_root, br, sb);
++              wbr_wh_write_unlock(wbr);
++      }
++      if (hdir)
++              au_hin_imtx_unlock(hdir);
++      else
++              mutex_unlock(h_mtx);
++      br->br_perm = old_perm;
++
++      if (!err && wbr && !au_br_writable(new_perm)) {
++              kfree(wbr);
++              br->br_wbr = NULL;
++      }
++
++      return err;
++}
++
++static int au_wbr_init(struct au_branch *br, struct super_block *sb,
++                     int perm, struct path *path)
++{
++      int err;
++      struct au_wbr *wbr;
++
++      wbr = br->br_wbr;
++      init_rwsem(&wbr->wbr_wh_rwsem);
++      memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
++      atomic_set(&wbr->wbr_wh_running, 0);
++      wbr->wbr_bytes = 0;
++
++      err = au_br_init_wh(sb, br, perm, path->dentry);
++
++      return err;
++}
++
++/* intialize a new branch */
++static int au_br_init(struct au_branch *br, struct super_block *sb,
++                    struct au_opt_add *add)
++{
++      int err;
++
++      err = 0;
++      memset(&br->br_xino, 0, sizeof(br->br_xino));
++      mutex_init(&br->br_xino.xi_nondir_mtx);
++      br->br_perm = add->perm;
++      br->br_mnt = add->path.mnt; /* set first, mntget() later */
++      atomic_set(&br->br_count, 0);
++      br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
++      atomic_set(&br->br_xino_running, 0);
++      br->br_id = au_new_br_id(sb);
++
++      if (au_br_writable(add->perm)) {
++              err = au_wbr_init(br, sb, add->perm, &add->path);
++              if (unlikely(err))
++                      goto out;
++      }
++
++      if (au_opt_test(au_mntflags(sb), XINO)) {
++              err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
++                               au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
++              if (unlikely(err)) {
++                      AuDebugOn(br->br_xino.xi_file);
++                      goto out;
++              }
++      }
++
++      sysaufs_br_init(br);
++      mntget(add->path.mnt);
++
++ out:
++      return err;
++}
++
++static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
++                           struct au_branch *br, aufs_bindex_t bend,
++                           aufs_bindex_t amount)
++{
++      struct au_branch **brp;
++
++      brp = sbinfo->si_branch + bindex;
++      memmove(brp + 1, brp, sizeof(*brp) * amount);
++      *brp = br;
++      sbinfo->si_bend++;
++      if (unlikely(bend < 0))
++              sbinfo->si_bend = 0;
++}
++
++static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
++                           aufs_bindex_t bend, aufs_bindex_t amount)
++{
++      struct au_hdentry *hdp;
++
++      hdp = dinfo->di_hdentry + bindex;
++      memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
++      au_h_dentry_init(hdp);
++      dinfo->di_bend++;
++      if (unlikely(bend < 0))
++              dinfo->di_bstart = 0;
++}
++
++static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
++                           aufs_bindex_t bend, aufs_bindex_t amount)
++{
++      struct au_hinode *hip;
++
++      hip = iinfo->ii_hinode + bindex;
++      memmove(hip + 1, hip, sizeof(*hip) * amount);
++      hip->hi_inode = NULL;
++      au_hin_init(hip, NULL);
++      iinfo->ii_bend++;
++      if (unlikely(bend < 0))
++              iinfo->ii_bstart = 0;
++}
++
++static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
++                       struct au_branch *br, aufs_bindex_t bindex)
++{
++      struct dentry *root;
++      struct inode *root_inode;
++      aufs_bindex_t bend, amount;
++
++      root = sb->s_root;
++      root_inode = root->d_inode;
++      au_plink_block_maintain(sb);
++      bend = au_sbend(sb);
++      amount = bend + 1 - bindex;
++      au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
++      au_br_do_add_hdp(au_di(root), bindex, bend, amount);
++      au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
++      au_set_h_dptr(root, bindex, dget(h_dentry));
++      au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
++                    /*flags*/0);
++}
++
++int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
++{
++      int err;
++      unsigned long long maxb;
++      aufs_bindex_t bend, add_bindex;
++      struct dentry *root, *h_dentry;
++      struct inode *root_inode;
++      struct au_branch *add_branch;
++
++      root = sb->s_root;
++      root_inode = root->d_inode;
++      IMustLock(root_inode);
++      err = test_add(sb, add, remount);
++      if (unlikely(err < 0))
++              goto out;
++      if (err) {
++              err = 0;
++              goto out; /* success */
++      }
++
++      bend = au_sbend(sb);
++      add_branch = au_br_alloc(sb, bend + 2, add->perm);
++      err = PTR_ERR(add_branch);
++      if (IS_ERR(add_branch))
++              goto out;
++
++      err = au_br_init(add_branch, sb, add);
++      if (unlikely(err)) {
++              au_br_do_free(add_branch);
++              goto out;
++      }
++
++      add_bindex = add->bindex;
++      h_dentry = add->path.dentry;
++      if (!remount)
++              au_br_do_add(sb, h_dentry, add_branch, add_bindex);
++      else {
++              sysaufs_brs_del(sb, add_bindex);
++              au_br_do_add(sb, h_dentry, add_branch, add_bindex);
++              sysaufs_brs_add(sb, add_bindex);
++      }
++
++      if (!add_bindex)
++              au_cpup_attr_all(root_inode, /*force*/1);
++      else
++              au_add_nlink(root_inode, h_dentry->d_inode);
++      maxb = h_dentry->d_sb->s_maxbytes;
++      if (sb->s_maxbytes < maxb)
++              sb->s_maxbytes = maxb;
++
++      /*
++       * this test/set prevents aufs from handling unnecesary inotify events
++       * of xino files, in a case of re-adding a writable branch which was
++       * once detached from aufs.
++       */
++      if (au_xino_brid(sb) < 0
++          && au_br_writable(add_branch->br_perm)
++          && !au_test_fs_bad_xino(h_dentry->d_sb)
++          && add_branch->br_xino.xi_file
++          && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
++              au_xino_brid_set(sb, add_branch->br_id);
++
++ out:
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * delete a branch
++ */
++
++/* to show the line number, do not make it inlined function */
++#define AuVerbose(do_info, fmt, args...) do { \
++      if (do_info) \
++              AuInfo(fmt, ##args); \
++} while (0)
++
++/*
++ * test if the branch is deletable or not.
++ */
++static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
++                          unsigned int sigen)
++{
++      int err, i, j, ndentry;
++      aufs_bindex_t bstart, bend;
++      unsigned char verbose;
++      struct au_dcsub_pages dpages;
++      struct au_dpage *dpage;
++      struct dentry *d;
++      struct inode *inode;
++
++      err = au_dpages_init(&dpages, GFP_NOFS);
++      if (unlikely(err))
++              goto out;
++      err = au_dcsub_pages(&dpages, root, NULL, NULL);
++      if (unlikely(err))
++              goto out_dpages;
++
++      verbose = !!au_opt_test(au_mntflags(root->d_sb), VERBOSE);
++      for (i = 0; !err && i < dpages.ndpage; i++) {
++              dpage = dpages.dpages + i;
++              ndentry = dpage->ndentry;
++              for (j = 0; !err && j < ndentry; j++) {
++                      d = dpage->dentries[j];
++                      AuDebugOn(!atomic_read(&d->d_count));
++                      inode = d->d_inode;
++                      if (au_digen(d) == sigen && au_iigen(inode) == sigen)
++                              di_read_lock_child(d, AuLock_IR);
++                      else {
++                              di_write_lock_child(d);
++                              err = au_reval_dpath(d, sigen);
++                              if (!err)
++                                      di_downgrade_lock(d, AuLock_IR);
++                              else {
++                                      di_write_unlock(d);
++                                      break;
++                              }
++                      }
++
++                      bstart = au_dbstart(d);
++                      bend = au_dbend(d);
++                      if (bstart <= bindex
++                          && bindex <= bend
++                          && au_h_dptr(d, bindex)
++                          && (!S_ISDIR(inode->i_mode) || bstart == bend)) {
++                              err = -EBUSY;
++                              AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
++                      }
++                      di_read_unlock(d, AuLock_IR);
++              }
++      }
++
++ out_dpages:
++      au_dpages_free(&dpages);
++ out:
++      return err;
++}
++
++static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
++                         unsigned int sigen)
++{
++      int err;
++      struct inode *i;
++      aufs_bindex_t bstart, bend;
++      unsigned char verbose;
++
++      err = 0;
++      verbose = !!au_opt_test(au_mntflags(sb), VERBOSE);
++      list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
++              AuDebugOn(!atomic_read(&i->i_count));
++              if (!list_empty(&i->i_dentry))
++                      continue;
++
++              if (au_iigen(i) == sigen)
++                      ii_read_lock_child(i);
++              else {
++                      ii_write_lock_child(i);
++                      err = au_refresh_hinode_self(i, /*do_attr*/1);
++                      if (!err)
++                              ii_downgrade_lock(i);
++                      else {
++                              ii_write_unlock(i);
++                              break;
++                      }
++              }
++
++              bstart = au_ibstart(i);
++              bend = au_ibend(i);
++              if (bstart <= bindex
++                  && bindex <= bend
++                  && au_h_iptr(i, bindex)
++                  && (!S_ISDIR(i->i_mode) || bstart == bend)) {
++                      err = -EBUSY;
++                      AuVerbose(verbose, "busy i%lu\n", i->i_ino);
++                      ii_read_unlock(i);
++                      break;
++              }
++              ii_read_unlock(i);
++      }
++
++      return err;
++}
++
++static int test_children_busy(struct dentry *root, aufs_bindex_t bindex)
++{
++      int err;
++      unsigned int sigen;
++
++      sigen = au_sigen(root->d_sb);
++      DiMustNoWaiters(root);
++      IiMustNoWaiters(root->d_inode);
++      di_write_unlock(root);
++      err = test_dentry_busy(root, bindex, sigen);
++      if (!err)
++              err = test_inode_busy(root->d_sb, bindex, sigen);
++      di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
++
++      return err;
++}
++
++static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
++                           const aufs_bindex_t bindex,
++                           const aufs_bindex_t bend)
++{
++      struct au_branch **brp, **p;
++
++      brp = sbinfo->si_branch + bindex;
++      if (bindex < bend)
++              memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
++      sbinfo->si_branch[0 + bend] = NULL;
++      sbinfo->si_bend--;
++
++      p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
++      if (p)
++              sbinfo->si_branch = p;
++}
++
++static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
++                           const aufs_bindex_t bend)
++{
++      struct au_hdentry *hdp, *p;
++
++      hdp = dinfo->di_hdentry + bindex;
++      if (bindex < bend)
++              memmove(hdp, hdp + 1, sizeof(*hdp) * (bend - bindex));
++      dinfo->di_hdentry[0 + bend].hd_dentry = NULL;
++      dinfo->di_bend--;
++
++      p = krealloc(dinfo->di_hdentry, sizeof(*p) * bend, GFP_NOFS);
++      if (p)
++              dinfo->di_hdentry = p;
++}
++
++static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
++                           const aufs_bindex_t bend)
++{
++      struct au_hinode *hip, *p;
++
++      hip = iinfo->ii_hinode + bindex;
++      if (bindex < bend)
++              memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
++      iinfo->ii_hinode[0 + bend].hi_inode = NULL;
++      au_hin_init(iinfo->ii_hinode + bend, NULL);
++      iinfo->ii_bend--;
++
++      p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
++      if (p)
++              iinfo->ii_hinode = p;
++}
++
++static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
++                       struct au_branch *br)
++{
++      aufs_bindex_t bend;
++      struct au_sbinfo *sbinfo;
++      struct dentry *root;
++      struct inode *inode;
++
++      root = sb->s_root;
++      inode = root->d_inode;
++      au_plink_block_maintain(sb);
++      sbinfo = au_sbi(sb);
++      bend = sbinfo->si_bend;
++
++      dput(au_h_dptr(root, bindex));
++      au_hiput(au_hi(inode, bindex));
++      au_br_do_free(br);
++
++      au_br_do_del_brp(sbinfo, bindex, bend);
++      au_br_do_del_hdp(au_di(root), bindex, bend);
++      au_br_do_del_hip(au_ii(inode), bindex, bend);
++}
++
++int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
++{
++      int err, rerr, i;
++      unsigned int mnt_flags;
++      aufs_bindex_t bindex, bend, br_id;
++      unsigned char do_wh, verbose;
++      struct au_branch *br;
++      struct au_wbr *wbr;
++
++      err = 0;
++      bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
++      if (bindex < 0) {
++              if (remount)
++                      goto out; /* success */
++              err = -ENOENT;
++              AuErr("%s no such branch\n", del->pathname);
++              goto out;
++      }
++      AuDbg("bindex b%d\n", bindex);
++
++      err = -EBUSY;
++      mnt_flags = au_mntflags(sb);
++      verbose = !!au_opt_test(mnt_flags, VERBOSE);
++      bend = au_sbend(sb);
++      if (unlikely(!bend)) {
++              AuVerbose(verbose, "no more branches left\n");
++              goto out;
++      }
++      br = au_sbr(sb, bindex);
++      i = atomic_read(&br->br_count);
++      if (unlikely(i)) {
++              AuVerbose(verbose, "%d file(s) opened\n", i);
++              goto out;
++      }
++
++      wbr = br->br_wbr;
++      do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
++      if (do_wh) {
++              for (i = 0; i < AuBrWh_Last; i++) {
++                      dput(wbr->wbr_wh[i]);
++                      wbr->wbr_wh[i] = NULL;
++              }
++      }
++
++      err = test_children_busy(sb->s_root, bindex);
++      if (unlikely(err)) {
++              if (do_wh)
++                      goto out_wh;
++              goto out;
++      }
++
++      err = 0;
++      br_id = br->br_id;
++      if (!remount)
++              au_br_do_del(sb, bindex, br);
++      else {
++              sysaufs_brs_del(sb, bindex);
++              au_br_do_del(sb, bindex, br);
++              sysaufs_brs_add(sb, bindex);
++      }
++
++      if (!bindex)
++              au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
++      else
++              au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
++      if (au_opt_test(mnt_flags, PLINK))
++              au_plink_half_refresh(sb, br_id);
++
++      if (sb->s_maxbytes == del->h_path.dentry->d_sb->s_maxbytes) {
++              bend--;
++              sb->s_maxbytes = 0;
++              for (bindex = 0; bindex <= bend; bindex++) {
++                      unsigned long long maxb;
++
++                      maxb = au_sbr_sb(sb, bindex)->s_maxbytes;
++                      if (sb->s_maxbytes < maxb)
++                              sb->s_maxbytes = maxb;
++              }
++      }
++
++      if (au_xino_brid(sb) == br->br_id)
++              au_xino_brid_set(sb, -1);
++      goto out; /* success */
++
++ out_wh:
++      /* revert */
++      rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
++      if (rerr)
++              AuWarn("failed re-creating base whiteout, %s. (%d)\n",
++                     del->pathname, rerr);
++ out:
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * change a branch permission
++ */
++
++static int do_need_sigen_inc(int a, int b)
++{
++      return au_br_whable(a) && !au_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);
++}
++
++static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
++{
++      int err;
++      unsigned long n, ul, bytes, files;
++      aufs_bindex_t bstart;
++      struct file *file, *hf, **a;
++      const int step_bytes = 1024, /* memory allocation unit */
++              step_files = step_bytes / sizeof(*a);
++
++      err = -ENOMEM;
++      n = 0;
++      bytes = step_bytes;
++      files = step_files;
++      a = kmalloc(bytes, GFP_NOFS);
++      if (unlikely(!a))
++              goto out;
++
++      /* no need file_list_lock() since sbinfo is locked? defered? */
++      list_for_each_entry(file, &sb->s_files, f_u.fu_list) {
++              if (special_file(file->f_dentry->d_inode->i_mode))
++                      continue;
++
++              AuDbg("%.*s\n", AuDLNPair(file->f_dentry));
++              fi_read_lock(file);
++              if (unlikely(au_test_mmapped(file))) {
++                      err = -EBUSY;
++                      FiMustNoWaiters(file);
++                      fi_read_unlock(file);
++                      goto out_free;
++              }
++
++              bstart = au_fbstart(file);
++              if (!S_ISREG(file->f_dentry->d_inode->i_mode)
++                  || !(file->f_mode & FMODE_WRITE)
++                  || bstart != bindex) {
++                      FiMustNoWaiters(file);
++                      fi_read_unlock(file);
++                      continue;
++              }
++
++              hf = au_h_fptr(file, bstart);
++              FiMustNoWaiters(file);
++              fi_read_unlock(file);
++
++              if (n < files)
++                      a[n++] = hf;
++              else {
++                      void *p;
++
++                      err = -ENOMEM;
++                      bytes += step_bytes;
++                      files += step_files;
++                      p = krealloc(a, bytes, GFP_NOFS);
++                      if (p) {
++                              a = p;
++                              a[n++] = hf;
++                      } else
++                              goto out_free;
++              }
++      }
++
++      err = 0;
++      for (ul = 0; ul < n; ul++) {
++              /* todo: already flushed? */
++              /* cf. fs/super.c:mark_files_ro() */
++              hf = a[ul];
++              hf->f_mode &= ~FMODE_WRITE;
++              if (!file_check_writeable(hf)) {
++                      file_release_write(hf);
++                      mnt_drop_write(hf->f_vfsmnt);
++              }
++      }
++
++ out_free:
++      kfree(a);
++ out:
++      return err;
++}
++
++int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
++            int *do_update)
++{
++      int err, rerr;
++      aufs_bindex_t bindex;
++      struct dentry *root;
++      struct au_branch *br;
++
++      root = sb->s_root;
++      au_plink_block_maintain(sb);
++      bindex = au_find_dbindex(root, mod->h_root);
++      if (bindex < 0) {
++              if (remount)
++                      return 0; /* success */
++              err = -ENOENT;
++              AuErr("%s no such branch\n", mod->path);
++              goto out;
++      }
++      AuDbg("bindex b%d\n", bindex);
++
++      err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
++      if (unlikely(err))
++              goto out;
++
++      br = au_sbr(sb, bindex);
++      if (br->br_perm == mod->perm)
++              return 0; /* success */
++
++      if (au_br_writable(br->br_perm)) {
++              /* remove whiteout base */
++              err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
++              if (unlikely(err))
++                      goto out;
++
++              if (!au_br_writable(mod->perm)) {
++                      /* rw --> ro, file might be mmapped */
++                      DiMustNoWaiters(root);
++                      IiMustNoWaiters(root->d_inode);
++                      di_write_unlock(root);
++                      err = au_br_mod_files_ro(sb, bindex);
++                      /* aufs_write_lock() calls ..._child() */
++                      di_write_lock_child(root);
++
++                      if (unlikely(err)) {
++                              rerr = -ENOMEM;
++                              br->br_wbr = kmalloc(sizeof(*br->br_wbr),
++                                                   GFP_NOFS);
++                              if (br->br_wbr)
++                                      rerr = au_br_init_wh
++                                              (sb, br, br->br_perm,
++                                               mod->h_root);
++                              if (unlikely(rerr)) {
++                                      AuIOErr("nested error %d (%d)\n",
++                                              rerr, err);
++                                      br->br_perm = mod->perm;
++                              }
++                      }
++              }
++      } else if (au_br_writable(mod->perm)) {
++              /* ro --> rw */
++              err = -ENOMEM;
++              br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
++              if (br->br_wbr) {
++                      struct path path = {
++                              .mnt    = br->br_mnt,
++                              .dentry = mod->h_root
++                      };
++
++                      err = au_wbr_init(br, sb, mod->perm, &path);
++                      if (unlikely(err)) {
++                              kfree(br->br_wbr);
++                              br->br_wbr = NULL;
++                      }
++              }
++      }
++
++      if (!err) {
++              *do_update |= need_sigen_inc(br->br_perm, mod->perm);
++              br->br_perm = mod->perm;
++      }
++
++ out:
++      return err;
++}
+diff -Naur a/fs/aufs/branch.h b/fs/aufs/branch.h
+--- a/fs/aufs/branch.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/branch.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,215 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * branch filesystems and xino for them
++ */
++
++#ifndef __AUFS_BRANCH_H__
++#define __AUFS_BRANCH_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/mount.h>
++#include <linux/aufs_type.h>
++#include "rwsem.h"
++#include "super.h"
++
++/* ---------------------------------------------------------------------- */
++
++/* a xino file */
++struct au_xino_file {
++      struct file             *xi_file;
++      struct mutex            xi_nondir_mtx;
++
++      /* todo: make xino files an array to support huge inode number */
++
++#ifdef CONFIG_DEBUG_FS
++      struct dentry            *xi_dbgaufs;
++#endif
++};
++
++/* members for writable branch only */
++enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
++struct au_wbr {
++      struct rw_semaphore     wbr_wh_rwsem;
++      struct dentry           *wbr_wh[AuBrWh_Last];
++      atomic_t                wbr_wh_running;
++#define wbr_whbase            wbr_wh[AuBrWh_BASE]     /* whiteout base */
++#define wbr_plink             wbr_wh[AuBrWh_PLINK]    /* pseudo-link dir */
++#define wbr_orph              wbr_wh[AuBrWh_ORPH]     /* dir for orphans */
++
++      /* mfs mode */
++      unsigned long long      wbr_bytes;
++};
++
++/* protected by superblock rwsem */
++struct au_branch {
++      struct au_xino_file     br_xino;
++
++      aufs_bindex_t           br_id;
++
++      int                     br_perm;
++      struct vfsmount         *br_mnt;
++      atomic_t                br_count;
++
++      struct au_wbr           *br_wbr;
++
++      /* xino truncation */
++      blkcnt_t                br_xino_upper;  /* watermark in blocks */
++      atomic_t                br_xino_running;
++
++#ifdef CONFIG_SYSFS
++      /* an entry under sysfs per mount-point */
++      char                    br_name[8];
++      struct attribute        br_attr;
++#endif
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* branch permission and attribute */
++enum {
++      AuBrPerm_RW,            /* writable, linkable wh */
++      AuBrPerm_RO,            /* readonly, no wh */
++      AuBrPerm_RR,            /* natively readonly, no wh */
++
++      AuBrPerm_RWNoLinkWH,    /* un-linkable whiteouts */
++
++      AuBrPerm_ROWH,          /* whiteout-able */
++      AuBrPerm_RRWH,          /* whiteout-able */
++
++      AuBrPerm_Last
++};
++
++static inline int au_br_writable(int brperm)
++{
++      return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
++}
++
++static inline int au_br_whable(int brperm)
++{
++      return brperm == AuBrPerm_RW
++              || brperm == AuBrPerm_ROWH
++              || brperm == AuBrPerm_RRWH;
++}
++
++static inline int au_br_rdonly(struct au_branch *br)
++{
++      return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
++              || !au_br_writable(br->br_perm))
++              ? -EROFS : 0;
++}
++
++static inline int au_br_hinotifyable(int brperm __maybe_unused)
++{
++#ifdef CONFIG_AUFS_HINOTIFY
++      return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
++#else
++      return 0;
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* branch.c */
++struct au_sbinfo;
++void au_br_free(struct au_sbinfo *sinfo);
++int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
++struct au_opt_add;
++int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
++struct au_opt_del;
++int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
++struct au_opt_mod;
++int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
++            int *do_update);
++
++/* xino.c */
++static const loff_t au_loff_max = LLONG_MAX;
++
++int au_xib_trunc(struct super_block *sb);
++ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
++                 loff_t *pos);
++ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
++                  loff_t *pos);
++struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
++struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
++ino_t au_xino_new_ino(struct super_block *sb);
++int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++                 ino_t ino);
++int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++                ino_t ino);
++int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++               ino_t *ino);
++int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
++             struct file *base_file, int do_test);
++int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
++
++struct au_opt_xino;
++int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
++void au_xino_clr(struct super_block *sb);
++struct file *au_xino_def(struct super_block *sb);
++int au_xino_path(struct seq_file *seq, struct file *file);
++
++/* ---------------------------------------------------------------------- */
++
++/* Superblock to branch */
++static inline
++aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
++{
++      return au_sbr(sb, bindex)->br_id;
++}
++
++static inline
++struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
++{
++      return au_sbr(sb, bindex)->br_mnt;
++}
++
++static inline
++struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
++{
++      return au_sbr_mnt(sb, bindex)->mnt_sb;
++}
++
++static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
++{
++      atomic_dec(&au_sbr(sb, bindex)->br_count);
++}
++
++static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
++{
++      return au_sbr(sb, bindex)->br_perm;
++}
++
++static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
++{
++      return au_br_whable(au_sbr_perm(sb, bindex));
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * wbr_wh_read_lock, wbr_wh_write_lock
++ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
++ */
++AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_BRANCH_H__ */
+diff -Naur a/fs/aufs/cpup.c b/fs/aufs/cpup.c
+--- a/fs/aufs/cpup.c   1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/cpup.c   2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,1039 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * copy-up functions, see wbr_policy.c for copy-down
++ */
++
++#include <linux/file.h>
++#include <linux/fs_stack.h>
++#include <linux/mm.h>
++#include <linux/uaccess.h>
++#include "aufs.h"
++
++void au_cpup_attr_flags(struct inode *dst, struct inode *src)
++{
++      const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
++              | S_NOATIME | S_NOCMTIME;
++
++      dst->i_flags |= src->i_flags & ~mask;
++      if (au_test_fs_notime(dst->i_sb))
++              dst->i_flags |= S_NOATIME | S_NOCMTIME;
++}
++
++void au_cpup_attr_timesizes(struct inode *inode)
++{
++      struct inode *h_inode;
++
++      h_inode = au_h_iptr(inode, au_ibstart(inode));
++      fsstack_copy_attr_times(inode, h_inode);
++      vfsub_copy_inode_size(inode, h_inode);
++}
++
++void au_cpup_attr_nlink(struct inode *inode, int force)
++{
++      struct inode *h_inode;
++      struct super_block *sb;
++      aufs_bindex_t bindex, bend;
++
++      sb = inode->i_sb;
++      bindex = au_ibstart(inode);
++      h_inode = au_h_iptr(inode, bindex);
++      if (!force
++          && !S_ISDIR(h_inode->i_mode)
++          && au_opt_test(au_mntflags(sb), PLINK)
++          && au_plink_test(inode))
++              return;
++
++      inode->i_nlink = h_inode->i_nlink;
++
++      /*
++       * fewer nlink makes find(1) noisy, but larger nlink doesn't.
++       * it may includes whplink directory.
++       */
++      if (S_ISDIR(h_inode->i_mode)) {
++              bend = au_ibend(inode);
++              for (bindex++; bindex <= bend; bindex++) {
++                      h_inode = au_h_iptr(inode, bindex);
++                      if (h_inode)
++                              au_add_nlink(inode, h_inode);
++              }
++      }
++}
++
++void au_cpup_attr_changeable(struct inode *inode)
++{
++      struct inode *h_inode;
++
++      h_inode = au_h_iptr(inode, au_ibstart(inode));
++      inode->i_mode = h_inode->i_mode;
++      inode->i_uid = h_inode->i_uid;
++      inode->i_gid = h_inode->i_gid;
++      au_cpup_attr_timesizes(inode);
++      au_cpup_attr_flags(inode, h_inode);
++}
++
++void au_cpup_igen(struct inode *inode, struct inode *h_inode)
++{
++      struct au_iinfo *iinfo = au_ii(inode);
++
++      iinfo->ii_higen = h_inode->i_generation;
++      iinfo->ii_hsb1 = h_inode->i_sb;
++}
++
++void au_cpup_attr_all(struct inode *inode, int force)
++{
++      struct inode *h_inode;
++
++      h_inode = au_h_iptr(inode, au_ibstart(inode));
++      au_cpup_attr_changeable(inode);
++      if (inode->i_nlink > 0)
++              au_cpup_attr_nlink(inode, force);
++      inode->i_rdev = h_inode->i_rdev;
++      inode->i_blkbits = h_inode->i_blkbits;
++      au_cpup_igen(inode, h_inode);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
++
++/* keep the timestamps of the parent dir when cpup */
++void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
++                  struct path *h_path)
++{
++      struct inode *h_inode;
++
++      dt->dt_dentry = dentry;
++      dt->dt_h_path = *h_path;
++      h_inode = h_path->dentry->d_inode;
++      dt->dt_atime = h_inode->i_atime;
++      dt->dt_mtime = h_inode->i_mtime;
++      /* smp_mb(); */
++}
++
++void au_dtime_revert(struct au_dtime *dt)
++{
++      struct iattr attr;
++      int err;
++
++      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;
++
++      err = vfsub_notify_change(&dt->dt_h_path, &attr);
++      if (unlikely(err))
++              AuWarn("restoring timestamps failed(%d). ignored\n", err);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static noinline_for_stack
++int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
++{
++      int err, sbits;
++      struct iattr ia;
++      struct path h_path;
++      struct inode *h_isrc;
++
++      h_path.dentry = au_h_dptr(dst, bindex);
++      h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
++      h_isrc = h_src->d_inode;
++      ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID
++              | ATTR_ATIME | ATTR_MTIME
++              | ATTR_ATIME_SET | ATTR_MTIME_SET;
++      ia.ia_mode = h_isrc->i_mode;
++      ia.ia_uid = h_isrc->i_uid;
++      ia.ia_gid = h_isrc->i_gid;
++      ia.ia_atime = h_isrc->i_atime;
++      ia.ia_mtime = h_isrc->i_mtime;
++      sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
++      au_cpup_attr_flags(h_path.dentry->d_inode, h_isrc);
++      err = vfsub_notify_change(&h_path, &ia);
++
++      /* is this nfs only? */
++      if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
++              ia.ia_valid = ATTR_FORCE | ATTR_MODE;
++              ia.ia_mode = h_isrc->i_mode;
++              err = vfsub_notify_change(&h_path, &ia);
++      }
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
++                         char *buf, unsigned long blksize)
++{
++      int err;
++      size_t sz, rbytes, wbytes;
++      unsigned char all_zero;
++      char *p, *zp;
++      struct mutex *h_mtx;
++      /* reduce stack usage */
++      struct iattr *ia;
++
++      zp = page_address(ZERO_PAGE(0));
++      if (unlikely(!zp))
++              return -ENOMEM; /* possible? */
++
++      err = 0;
++      all_zero = 0;
++      while (len) {
++              AuDbg("len %lld\n", len);
++              sz = blksize;
++              if (len < blksize)
++                      sz = len;
++
++              rbytes = 0;
++              /* todo: signal_pending? */
++              while (!rbytes || err == -EAGAIN || err == -EINTR) {
++                      rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
++                      err = rbytes;
++              }
++              if (unlikely(err < 0))
++                      break;
++
++              all_zero = 0;
++              if (len >= rbytes && rbytes == blksize)
++                      all_zero = !memcmp(buf, zp, rbytes);
++              if (!all_zero) {
++                      wbytes = rbytes;
++                      p = buf;
++                      while (wbytes) {
++                              size_t b;
++
++                              b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
++                              err = b;
++                              /* todo: signal_pending? */
++                              if (unlikely(err == -EAGAIN || err == -EINTR))
++                                      continue;
++                              if (unlikely(err < 0))
++                                      break;
++                              wbytes -= b;
++                              p += b;
++                      }
++              } else {
++                      loff_t res;
++
++                      AuLabel(hole);
++                      res = vfsub_llseek(dst, rbytes, SEEK_CUR);
++                      err = res;
++                      if (unlikely(res < 0))
++                              break;
++              }
++              len -= rbytes;
++              err = 0;
++      }
++
++      /* the last block may be a hole */
++      if (!err && all_zero) {
++              AuLabel(last hole);
++
++              err = 1;
++              if (au_test_nfs(dst->f_dentry->d_sb)) {
++                      /* nfs requires this step to make last hole */
++                      /* is this only nfs? */
++                      do {
++                              /* todo: signal_pending? */
++                              err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
++                      } while (err == -EAGAIN || err == -EINTR);
++                      if (err == 1)
++                              dst->f_pos--;
++              }
++
++              if (err == 1) {
++                      ia = (void *)buf;
++                      ia->ia_size = dst->f_pos;
++                      ia->ia_valid = ATTR_SIZE | ATTR_FILE;
++                      ia->ia_file = dst;
++                      h_mtx = &dst->f_dentry->d_inode->i_mutex;
++                      mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
++                      err = vfsub_notify_change(&dst->f_path, ia);
++                      mutex_unlock(h_mtx);
++              }
++      }
++
++      return err;
++}
++
++int au_copy_file(struct file *dst, struct file *src, loff_t len)
++{
++      int err;
++      unsigned long blksize;
++      unsigned char do_kfree;
++      char *buf;
++
++      err = -ENOMEM;
++      blksize = dst->f_dentry->d_sb->s_blocksize;
++      if (!blksize || PAGE_SIZE < blksize)
++              blksize = PAGE_SIZE;
++      AuDbg("blksize %lu\n", blksize);
++      do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
++      if (do_kfree)
++              buf = kmalloc(blksize, GFP_NOFS);
++      else
++              buf = (void *)__get_free_page(GFP_NOFS);
++      if (unlikely(!buf))
++              goto out;
++
++      if (len > (1 << 22))
++              AuDbg("copying a large file %lld\n", (long long)len);
++
++      src->f_pos = 0;
++      dst->f_pos = 0;
++      err = au_do_copy_file(dst, src, len, buf, blksize);
++      if (do_kfree)
++              kfree(buf);
++      else
++              free_page((unsigned long)buf);
++
++ out:
++      return err;
++}
++
++/*
++ * to support a sparse file which is opened with O_APPEND,
++ * we need to close the file.
++ */
++static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
++                      aufs_bindex_t bsrc, loff_t len)
++{
++      int err, i;
++      enum { SRC, DST };
++      struct {
++              aufs_bindex_t bindex;
++              unsigned int flags;
++              struct dentry *dentry;
++              struct file *file;
++              void *label, *label_file;
++      } *f, file[] = {
++              {
++                      .bindex = bsrc,
++                      .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
++                      .file = NULL,
++                      .label = &&out,
++                      .label_file = &&out_src
++              },
++              {
++                      .bindex = bdst,
++                      .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
++                      .file = NULL,
++                      .label = &&out_src,
++                      .label_file = &&out_dst
++              }
++      };
++      struct super_block *sb;
++
++      /* bsrc branch can be ro/rw. */
++      sb = dentry->d_sb;
++      f = file;
++      for (i = 0; i < 2; i++, f++) {
++              f->dentry = au_h_dptr(dentry, f->bindex);
++              f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
++              err = PTR_ERR(f->file);
++              if (IS_ERR(f->file))
++                      goto *f->label;
++              err = -EINVAL;
++              if (unlikely(!f->file->f_op))
++                      goto *f->label_file;
++      }
++
++      /* try stopping to update while we copyup */
++      IMustLock(file[SRC].dentry->d_inode);
++      err = au_copy_file(file[DST].file, file[SRC].file, len);
++
++ out_dst:
++      fput(file[DST].file);
++      au_sbr_put(sb, file[DST].bindex);
++ out_src:
++      fput(file[SRC].file);
++      au_sbr_put(sb, file[SRC].bindex);
++ out:
++      return err;
++}
++
++static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
++                            aufs_bindex_t bsrc, loff_t len,
++                            struct inode *h_dir, struct path *h_path)
++{
++      int err, rerr;
++      loff_t l;
++
++      err = 0;
++      l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
++      if (len == -1 || l < len)
++              len = l;
++      if (len)
++              err = au_cp_regular(dentry, bdst, bsrc, len);
++      if (!err)
++              goto out; /* success */
++
++      rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
++      if (rerr) {
++              AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
++                      AuDLNPair(h_path->dentry), err, rerr);
++              err = -EIO;
++      }
++
++ out:
++      return err;
++}
++
++static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
++                            struct inode *h_dir)
++{
++      int err, symlen;
++      mm_segment_t old_fs;
++      char *sym;
++
++      err = -ENOSYS;
++      if (unlikely(!h_src->d_inode->i_op->readlink))
++              goto out;
++
++      err = -ENOMEM;
++      sym = __getname();
++      if (unlikely(!sym))
++              goto out;
++
++      old_fs = get_fs();
++      set_fs(KERNEL_DS);
++      symlen = h_src->d_inode->i_op->readlink(h_src, (char __user *)sym,
++                                              PATH_MAX);
++      err = symlen;
++      set_fs(old_fs);
++
++      if (symlen > 0) {
++              sym[symlen] = 0;
++              err = vfsub_symlink(h_dir, h_path, sym);
++      }
++      __putname(sym);
++
++ out:
++      return err;
++}
++
++/* return with the lower dst inode is locked */
++static noinline_for_stack
++int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
++             aufs_bindex_t bsrc, loff_t len, unsigned int flags,
++             struct dentry *dst_parent)
++{
++      int err;
++      umode_t mode;
++      unsigned int mnt_flags;
++      unsigned char isdir;
++      const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
++      struct au_dtime dt;
++      struct path h_path;
++      struct dentry *h_src, *h_dst, *h_parent;
++      struct inode *h_inode, *h_dir;
++      struct super_block *sb;
++
++      /* bsrc branch can be ro/rw. */
++      h_src = au_h_dptr(dentry, bsrc);
++      h_inode = h_src->d_inode;
++      AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
++
++      /* try stopping to be referenced while we are creating */
++      h_dst = au_h_dptr(dentry, bdst);
++      h_parent = h_dst->d_parent; /* dir inode is locked */
++      h_dir = h_parent->d_inode;
++      IMustLock(h_dir);
++      AuDebugOn(h_parent != h_dst->d_parent);
++
++      sb = dentry->d_sb;
++      h_path.mnt = au_sbr_mnt(sb, bdst);
++      if (do_dt) {
++              h_path.dentry = h_parent;
++              au_dtime_store(&dt, dst_parent, &h_path);
++      }
++      h_path.dentry = h_dst;
++
++      isdir = 0;
++      mode = h_inode->i_mode;
++      switch (mode & S_IFMT) {
++      case S_IFREG:
++              /* try stopping to update while we are referencing */
++              IMustLock(h_inode);
++              err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
++              if (!err)
++                      err = au_do_cpup_regular
++                              (dentry, bdst, bsrc, len,
++                               au_h_iptr(dst_parent->d_inode, bdst), &h_path);
++              break;
++      case S_IFDIR:
++              isdir = 1;
++              err = vfsub_mkdir(h_dir, &h_path, mode);
++              if (!err) {
++                      /*
++                       * strange behaviour from the users view,
++                       * particularry setattr case
++                       */
++                      if (au_ibstart(dst_parent->d_inode) == bdst)
++                              au_cpup_attr_nlink(dst_parent->d_inode,
++                                                 /*force*/1);
++                      au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
++              }
++              break;
++      case S_IFLNK:
++              err = au_do_cpup_symlink(&h_path, h_src, h_dir);
++              break;
++      case S_IFCHR:
++      case S_IFBLK:
++              AuDebugOn(!capable(CAP_MKNOD));
++              /*FALLTHROUGH*/
++      case S_IFIFO:
++      case S_IFSOCK:
++              err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
++              break;
++      default:
++              AuIOErr("Unknown inode type 0%o\n", mode);
++              err = -EIO;
++      }
++
++      mnt_flags = au_mntflags(sb);
++      if (!au_opt_test(mnt_flags, UDBA_NONE)
++          && !isdir
++          && au_opt_test(mnt_flags, XINO)
++          && h_inode->i_nlink == 1
++          /* todo: unnecessary? */
++          /* && dentry->d_inode->i_nlink == 1 */
++          && bdst < bsrc
++          && !au_ftest_cpup(flags, KEEPLINO))
++              au_xino_write0(sb, bsrc, h_inode->i_ino, /*ino*/0);
++              /* ignore this error */
++
++      if (do_dt)
++              au_dtime_revert(&dt);
++      return err;
++}
++
++/*
++ * copyup the @dentry from @bsrc to @bdst.
++ * the caller must set the both of lower dentries.
++ * @len is for truncating when it is -1 copyup the entire file.
++ * in link/rename cases, @dst_parent may be different from the real one.
++ */
++static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
++                        aufs_bindex_t bsrc, loff_t len, unsigned int flags,
++                        struct dentry *dst_parent)
++{
++      int err, rerr;
++      aufs_bindex_t old_ibstart;
++      unsigned char isdir, plink;
++      struct au_dtime dt;
++      struct path h_path;
++      struct dentry *h_src, *h_dst, *h_parent;
++      struct inode *dst_inode, *h_dir, *inode;
++      struct super_block *sb;
++
++      AuDebugOn(bsrc <= bdst);
++
++      sb = dentry->d_sb;
++      h_path.mnt = au_sbr_mnt(sb, bdst);
++      h_dst = au_h_dptr(dentry, bdst);
++      h_parent = h_dst->d_parent; /* dir inode is locked */
++      h_dir = h_parent->d_inode;
++      IMustLock(h_dir);
++
++      h_src = au_h_dptr(dentry, bsrc);
++      inode = dentry->d_inode;
++
++      if (!dst_parent)
++              dst_parent = dget_parent(dentry);
++      else
++              dget(dst_parent);
++
++      plink = !!au_opt_test(au_mntflags(sb), PLINK);
++      dst_inode = au_h_iptr(inode, bdst);
++      if (dst_inode) {
++              if (unlikely(!plink)) {
++                      err = -EIO;
++                      AuIOErr("i%lu exists on a upper branch "
++                              "but plink is disabled\n", inode->i_ino);
++                      goto out;
++              }
++
++              if (dst_inode->i_nlink) {
++                      const int do_dt = au_ftest_cpup(flags, DTIME);
++
++                      h_src = au_plink_lkup(inode, bdst);
++                      err = PTR_ERR(h_src);
++                      if (IS_ERR(h_src))
++                              goto out;
++                      if (unlikely(!h_src->d_inode)) {
++                              err = -EIO;
++                              AuIOErr("i%lu exists on a upper branch "
++                                      "but plink is broken\n", inode->i_ino);
++                              dput(h_src);
++                              goto out;
++                      }
++
++                      if (do_dt) {
++                              h_path.dentry = h_parent;
++                              au_dtime_store(&dt, dst_parent, &h_path);
++                      }
++                      h_path.dentry = h_dst;
++                      err = vfsub_link(h_src, h_dir, &h_path);
++                      if (do_dt)
++                              au_dtime_revert(&dt);
++                      dput(h_src);
++                      goto out;
++              } else
++                      /* todo: cpup_wh_file? */
++                      /* udba work */
++                      au_update_brange(inode, 1);
++      }
++
++      old_ibstart = au_ibstart(inode);
++      err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
++      if (unlikely(err))
++              goto out;
++      dst_inode = h_dst->d_inode;
++      mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
++
++      err = cpup_iattr(dentry, bdst, h_src);
++      isdir = S_ISDIR(dst_inode->i_mode);
++      if (!err) {
++              if (bdst < old_ibstart)
++                      au_set_ibstart(inode, bdst);
++              au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
++                            au_hi_flags(inode, isdir));
++              mutex_unlock(&dst_inode->i_mutex);
++              if (!isdir
++                  && h_src->d_inode->i_nlink > 1
++                  && plink)
++                      au_plink_append(inode, bdst, h_dst);
++              goto out; /* success */
++      }
++
++      /* revert */
++      h_path.dentry = h_parent;
++      mutex_unlock(&dst_inode->i_mutex);
++      au_dtime_store(&dt, dst_parent, &h_path);
++      h_path.dentry = h_dst;
++      if (!isdir)
++              rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
++      else
++              rerr = vfsub_rmdir(h_dir, &h_path);
++      au_dtime_revert(&dt);
++      if (rerr) {
++              AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
++              err = -EIO;
++      }
++
++ out:
++      dput(dst_parent);
++      return err;
++}
++
++struct au_cpup_single_args {
++      int *errp;
++      struct dentry *dentry;
++      aufs_bindex_t bdst, bsrc;
++      loff_t len;
++      unsigned int flags;
++      struct dentry *dst_parent;
++};
++
++static void au_call_cpup_single(void *args)
++{
++      struct au_cpup_single_args *a = args;
++      *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
++                                a->flags, a->dst_parent);
++}
++
++int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
++                     aufs_bindex_t bsrc, loff_t len, unsigned int flags,
++                     struct dentry *dst_parent)
++{
++      int err, wkq_err;
++      umode_t mode;
++      struct dentry *h_dentry;
++
++      h_dentry = au_h_dptr(dentry, bsrc);
++      mode = h_dentry->d_inode->i_mode & S_IFMT;
++      if ((mode != S_IFCHR && mode != S_IFBLK)
++          || capable(CAP_MKNOD))
++              err = au_cpup_single(dentry, bdst, bsrc, len, flags,
++                                   dst_parent);
++      else {
++              struct au_cpup_single_args args = {
++                      .errp           = &err,
++                      .dentry         = dentry,
++                      .bdst           = bdst,
++                      .bsrc           = bsrc,
++                      .len            = len,
++                      .flags          = flags,
++                      .dst_parent     = dst_parent
++              };
++              wkq_err = au_wkq_wait(au_call_cpup_single, &args);
++              if (unlikely(wkq_err))
++                      err = wkq_err;
++      }
++
++      return err;
++}
++
++/*
++ * copyup the @dentry from the first active lower branch to @bdst,
++ * using au_cpup_single().
++ */
++static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++                        unsigned int flags)
++{
++      int err;
++      aufs_bindex_t bsrc, bend;
++
++      bend = au_dbend(dentry);
++      for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
++              if (au_h_dptr(dentry, bsrc))
++                      break;
++
++      err = au_lkup_neg(dentry, bdst);
++      if (!err) {
++              err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
++              if (!err)
++                      return 0; /* success */
++
++              /* revert */
++              au_set_h_dptr(dentry, bdst, NULL);
++              au_set_dbstart(dentry, bsrc);
++      }
++
++      return err;
++}
++
++struct au_cpup_simple_args {
++      int *errp;
++      struct dentry *dentry;
++      aufs_bindex_t bdst;
++      loff_t len;
++      unsigned int flags;
++};
++
++static void au_call_cpup_simple(void *args)
++{
++      struct au_cpup_simple_args *a = args;
++      *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
++}
++
++int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++                     unsigned int flags)
++{
++      int err, wkq_err;
++      unsigned char do_sio;
++      struct dentry *parent;
++      struct inode *h_dir;
++
++      parent = dget_parent(dentry);
++      h_dir = au_h_iptr(parent->d_inode, bdst);
++      do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
++      if (!do_sio) {
++              /*
++               * testing CAP_MKNOD is for generic fs,
++               * but CAP_FSETID is for xfs only, currently.
++               */
++              umode_t mode = dentry->d_inode->i_mode;
++              do_sio = (((mode & (S_IFCHR | S_IFBLK))
++                         && !capable(CAP_MKNOD))
++                        || ((mode & (S_ISUID | S_ISGID))
++                            && !capable(CAP_FSETID)));
++      }
++      if (!do_sio)
++              err = au_cpup_simple(dentry, bdst, len, flags);
++      else {
++              struct au_cpup_simple_args args = {
++                      .errp           = &err,
++                      .dentry         = dentry,
++                      .bdst           = bdst,
++                      .len            = len,
++                      .flags          = flags
++              };
++              wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
++              if (unlikely(wkq_err))
++                      err = wkq_err;
++      }
++
++      dput(parent);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * copyup the deleted file for writing.
++ */
++static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
++                       struct dentry *wh_dentry, struct file *file,
++                       loff_t len)
++{
++      int err;
++      aufs_bindex_t bstart;
++      struct au_dinfo *dinfo;
++      struct dentry *h_d_dst, *h_d_start;
++
++      dinfo = au_di(dentry);
++      bstart = dinfo->di_bstart;
++      h_d_dst = dinfo->di_hdentry[0 + bdst].hd_dentry;
++      dinfo->di_bstart = bdst;
++      dinfo->di_hdentry[0 + bdst].hd_dentry = wh_dentry;
++      h_d_start = dinfo->di_hdentry[0 + bstart].hd_dentry;
++      if (file)
++              dinfo->di_hdentry[0 + bstart].hd_dentry
++                      = au_h_fptr(file, au_fbstart(file))->f_dentry;
++      err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
++                           /*h_parent*/NULL);
++      if (!err && file) {
++              err = au_reopen_nondir(file);
++              dinfo->di_hdentry[0 + bstart].hd_dentry = h_d_start;
++      }
++      dinfo->di_hdentry[0 + bdst].hd_dentry = h_d_dst;
++      dinfo->di_bstart = bstart;
++
++      return err;
++}
++
++static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++                    struct file *file)
++{
++      int err;
++      struct au_dtime dt;
++      struct dentry *parent, *h_parent, *wh_dentry;
++      struct au_branch *br;
++      struct path h_path;
++
++      br = au_sbr(dentry->d_sb, bdst);
++      parent = dget_parent(dentry);
++      h_parent = au_h_dptr(parent, bdst);
++      wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
++      err = PTR_ERR(wh_dentry);
++      if (IS_ERR(wh_dentry))
++              goto out;
++
++      h_path.dentry = h_parent;
++      h_path.mnt = br->br_mnt;
++      au_dtime_store(&dt, parent, &h_path);
++      err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
++      if (unlikely(err))
++              goto out_wh;
++
++      dget(wh_dentry);
++      h_path.dentry = wh_dentry;
++      err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
++      if (unlikely(err)) {
++              AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
++                      AuDLNPair(wh_dentry), err);
++              err = -EIO;
++      }
++      au_dtime_revert(&dt);
++      au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
++
++ out_wh:
++      dput(wh_dentry);
++ out:
++      dput(parent);
++      return err;
++}
++
++struct au_cpup_wh_args {
++      int *errp;
++      struct dentry *dentry;
++      aufs_bindex_t bdst;
++      loff_t len;
++      struct file *file;
++};
++
++static void au_call_cpup_wh(void *args)
++{
++      struct au_cpup_wh_args *a = args;
++      *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
++}
++
++int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++                 struct file *file)
++{
++      int err, wkq_err;
++      struct dentry *parent, *h_orph, *h_parent, *h_dentry;
++      struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
++      struct au_wbr *wbr;
++
++      parent = dget_parent(dentry);
++      dir = parent->d_inode;
++      h_orph = NULL;
++      h_parent = NULL;
++      h_dir = au_igrab(au_h_iptr(dir, bdst));
++      h_tmpdir = h_dir;
++      if (!h_dir->i_nlink) {
++              wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
++              h_orph = wbr->wbr_orph;
++
++              h_parent = dget(au_h_dptr(parent, bdst));
++              au_set_h_dptr(parent, bdst, NULL);
++              au_set_h_dptr(parent, bdst, dget(h_orph));
++              h_tmpdir = h_orph->d_inode;
++              au_set_h_iptr(dir, bdst, NULL, 0);
++              au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
++
++              /* this temporary unlock is safe */
++              if (file)
++                      h_dentry = au_h_fptr(file, au_fbstart(file))->f_dentry;
++              else
++                      h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
++              h_inode = h_dentry->d_inode;
++              IMustLock(h_inode);
++              mutex_unlock(&h_inode->i_mutex);
++              mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT2);
++              mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++      }
++
++      if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
++              err = au_cpup_wh(dentry, bdst, len, file);
++      else {
++              struct au_cpup_wh_args args = {
++                      .errp   = &err,
++                      .dentry = dentry,
++                      .bdst   = bdst,
++                      .len    = len,
++                      .file   = file
++              };
++              wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
++              if (unlikely(wkq_err))
++                      err = wkq_err;
++      }
++
++      if (h_orph) {
++              mutex_unlock(&h_tmpdir->i_mutex);
++              au_set_h_iptr(dir, bdst, NULL, 0);
++              au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
++              au_set_h_dptr(parent, bdst, NULL);
++              au_set_h_dptr(parent, bdst, h_parent);
++      }
++      iput(h_dir);
++      dput(parent);
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * generic routine for both of copy-up and copy-down.
++ */
++/* cf. revalidate function in file.c */
++int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
++             int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
++                       struct dentry *h_parent, void *arg),
++             void *arg)
++{
++      int err;
++      struct au_pin pin;
++      struct dentry *d, *parent, *h_parent, *real_parent;
++
++      err = 0;
++      parent = dget_parent(dentry);
++      if (IS_ROOT(parent))
++              goto out;
++
++      au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
++                  au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
++
++      /* do not use au_dpage */
++      real_parent = parent;
++      while (1) {
++              dput(parent);
++              parent = dget_parent(dentry);
++              h_parent = au_h_dptr(parent, bdst);
++              if (h_parent)
++                      goto out; /* success */
++
++              /* find top dir which is necessary to cpup */
++              do {
++                      d = parent;
++                      dput(parent);
++                      parent = dget_parent(d);
++                      di_read_lock_parent3(parent, !AuLock_IR);
++                      h_parent = au_h_dptr(parent, bdst);
++                      di_read_unlock(parent, !AuLock_IR);
++              } while (!h_parent);
++
++              if (d != real_parent)
++                      di_write_lock_child3(d);
++
++              /* somebody else might create while we were sleeping */
++              if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
++                      if (au_h_dptr(d, bdst))
++                              au_update_dbstart(d);
++
++                      au_pin_set_dentry(&pin, d);
++                      err = au_do_pin(&pin);
++                      if (!err) {
++                              err = cp(d, bdst, h_parent, arg);
++                              au_unpin(&pin);
++                      }
++              }
++
++              if (d != real_parent)
++                      di_write_unlock(d);
++              if (unlikely(err))
++                      break;
++      }
++
++ out:
++      dput(parent);
++      return err;
++}
++
++static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
++                     struct dentry *h_parent __maybe_unused ,
++                     void *arg __maybe_unused)
++{
++      return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
++}
++
++int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
++{
++      return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
++}
++
++int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
++{
++      int err;
++      struct dentry *parent;
++      struct inode *dir;
++
++      parent = dget_parent(dentry);
++      dir = parent->d_inode;
++      err = 0;
++      if (au_h_iptr(dir, bdst))
++              goto out;
++
++      di_read_unlock(parent, AuLock_IR);
++      di_write_lock_parent(parent);
++      /* someone else might change our inode while we were sleeping */
++      if (!au_h_iptr(dir, bdst))
++              err = au_cpup_dirs(dentry, bdst);
++      di_downgrade_lock(parent, AuLock_IR);
++
++ out:
++      dput(parent);
++      return err;
++}
+diff -Naur a/fs/aufs/cpup.h b/fs/aufs/cpup.h
+--- a/fs/aufs/cpup.h   1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/cpup.h   2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,81 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * copy-up/down functions
++ */
++
++#ifndef __AUFS_CPUP_H__
++#define __AUFS_CPUP_H__
++
++#ifdef __KERNEL__
++
++#include <linux/path.h>
++#include <linux/time.h>
++#include <linux/aufs_type.h>
++
++struct inode;
++struct file;
++
++void au_cpup_attr_flags(struct inode *dst, struct inode *src);
++void au_cpup_attr_timesizes(struct inode *inode);
++void au_cpup_attr_nlink(struct inode *inode, int force);
++void au_cpup_attr_changeable(struct inode *inode);
++void au_cpup_igen(struct inode *inode, struct inode *h_inode);
++void au_cpup_attr_all(struct inode *inode, int force);
++
++/* ---------------------------------------------------------------------- */
++
++/* cpup flags */
++#define AuCpup_DTIME  1               /* do dtime_store/revert */
++#define AuCpup_KEEPLINO       (1 << 1)        /* do not clear the lower xino,
++                                         for link(2) */
++#define au_ftest_cpup(flags, name)    ((flags) & AuCpup_##name)
++#define au_fset_cpup(flags, name)     { (flags) |= AuCpup_##name; }
++#define au_fclr_cpup(flags, name)     { (flags) &= ~AuCpup_##name; }
++
++int au_copy_file(struct file *dst, struct file *src, loff_t len);
++int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
++                     aufs_bindex_t bsrc, loff_t len, unsigned int flags,
++                     struct dentry *dst_parent);
++int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++                     unsigned int flags);
++int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
++                 struct file *file);
++
++int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
++             int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
++                       struct dentry *h_parent, void *arg),
++             void *arg);
++int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
++int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
++
++/* ---------------------------------------------------------------------- */
++
++/* keep timestamps when copyup */
++struct au_dtime {
++      struct dentry *dt_dentry;
++      struct path dt_h_path;
++      struct timespec dt_atime, dt_mtime;
++};
++void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
++                  struct path *h_path);
++void au_dtime_revert(struct au_dtime *dt);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_CPUP_H__ */
+diff -Naur a/fs/aufs/dbgaufs.c b/fs/aufs/dbgaufs.c
+--- a/fs/aufs/dbgaufs.c        1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dbgaufs.c        2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,313 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * debugfs interface
++ */
++
++#include <linux/debugfs.h>
++#include "aufs.h"
++
++#ifndef CONFIG_SYSFS
++#error DEBUG_FS depends upon SYSFS
++#endif
++
++static struct dentry *dbgaufs;
++static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
++
++/* 20 is max digits length of ulong 64 */
++struct dbgaufs_arg {
++      int n;
++      char a[20 * 4];
++};
++
++/*
++ * common function for all XINO files
++ */
++static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
++                            struct file *file)
++{
++      kfree(file->private_data);
++      return 0;
++}
++
++static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
++{
++      int err;
++      struct kstat st;
++      struct dbgaufs_arg *p;
++
++      err = -ENOMEM;
++      p = kmalloc(sizeof(*p), GFP_NOFS);
++      if (unlikely(!p))
++              goto out;
++
++      err = 0;
++      p->n = 0;
++      file->private_data = p;
++      if (!xf)
++              goto out;
++
++      err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
++      if (!err) {
++              if (do_fcnt)
++                      p->n = snprintf
++                              (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
++                               (long)file_count(xf), st.blocks, st.blksize,
++                               (long long)st.size);
++              else
++                      p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
++                                      st.blocks, st.blksize,
++                                      (long long)st.size);
++              AuDebugOn(p->n >= sizeof(p->a));
++      } else {
++              p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
++              err = 0;
++      }
++
++ out:
++      return err;
++
++}
++
++static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
++                             size_t count, loff_t *ppos)
++{
++      struct dbgaufs_arg *p;
++
++      p = file->private_data;
++      return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int dbgaufs_xib_open(struct inode *inode, struct file *file)
++{
++      int err;
++      struct au_sbinfo *sbinfo;
++      struct super_block *sb;
++
++      sbinfo = inode->i_private;
++      sb = sbinfo->si_sb;
++      si_noflush_read_lock(sb);
++      err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
++      si_read_unlock(sb);
++      return err;
++}
++
++static const struct file_operations dbgaufs_xib_fop = {
++      .open           = dbgaufs_xib_open,
++      .release        = dbgaufs_xi_release,
++      .read           = dbgaufs_xi_read
++};
++
++/* ---------------------------------------------------------------------- */
++
++#define DbgaufsXi_PREFIX "xi"
++
++static int dbgaufs_xino_open(struct inode *inode, struct file *file)
++{
++      int err;
++      long l;
++      struct au_sbinfo *sbinfo;
++      struct super_block *sb;
++      struct file *xf;
++      struct qstr *name;
++
++      err = -ENOENT;
++      xf = NULL;
++      name = &file->f_dentry->d_name;
++      if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
++                   || memcmp(name->name, DbgaufsXi_PREFIX,
++                             sizeof(DbgaufsXi_PREFIX) - 1)))
++              goto out;
++      err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
++      if (unlikely(err))
++              goto out;
++
++      sbinfo = inode->i_private;
++      sb = sbinfo->si_sb;
++      si_noflush_read_lock(sb);
++      if (l <= au_sbend(sb)) {
++              xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
++              err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
++      } else
++              err = -ENOENT;
++      si_read_unlock(sb);
++
++ out:
++      return err;
++}
++
++static const struct file_operations dbgaufs_xino_fop = {
++      .open           = dbgaufs_xino_open,
++      .release        = dbgaufs_xi_release,
++      .read           = dbgaufs_xi_read
++};
++
++void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
++{
++      aufs_bindex_t bend;
++      struct au_branch *br;
++      struct au_xino_file *xi;
++
++      if (!au_sbi(sb)->si_dbgaufs)
++              return;
++
++      bend = au_sbend(sb);
++      for (; bindex <= bend; bindex++) {
++              br = au_sbr(sb, bindex);
++              xi = &br->br_xino;
++              if (xi->xi_dbgaufs) {
++                      debugfs_remove(xi->xi_dbgaufs);
++                      xi->xi_dbgaufs = NULL;
++              }
++      }
++}
++
++void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
++{
++      struct au_sbinfo *sbinfo;
++      struct dentry *parent;
++      struct au_branch *br;
++      struct au_xino_file *xi;
++      aufs_bindex_t bend;
++      char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
++
++      sbinfo = au_sbi(sb);
++      parent = sbinfo->si_dbgaufs;
++      if (!parent)
++              return;
++
++      bend = au_sbend(sb);
++      for (; bindex <= bend; bindex++) {
++              snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
++              br = au_sbr(sb, bindex);
++              xi = &br->br_xino;
++              AuDebugOn(xi->xi_dbgaufs);
++              xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
++                                                   sbinfo, &dbgaufs_xino_fop);
++              /* ignore an error */
++              if (unlikely(!xi->xi_dbgaufs))
++                      AuWarn1("failed %s under debugfs\n", name);
++      }
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_EXPORT
++static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
++{
++      int err;
++      struct au_sbinfo *sbinfo;
++      struct super_block *sb;
++
++      sbinfo = inode->i_private;
++      sb = sbinfo->si_sb;
++      si_noflush_read_lock(sb);
++      err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
++      si_read_unlock(sb);
++      return err;
++}
++
++static const struct file_operations dbgaufs_xigen_fop = {
++      .open           = dbgaufs_xigen_open,
++      .release        = dbgaufs_xi_release,
++      .read           = dbgaufs_xi_read
++};
++
++static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
++{
++      int err;
++
++      err = -EIO;
++      sbinfo->si_dbgaufs_xigen = debugfs_create_file
++              ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
++               &dbgaufs_xigen_fop);
++      if (sbinfo->si_dbgaufs_xigen)
++              err = 0;
++
++      return err;
++}
++#else
++static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
++{
++      return 0;
++}
++#endif /* CONFIG_AUFS_EXPORT */
++
++/* ---------------------------------------------------------------------- */
++
++void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
++{
++      debugfs_remove_recursive(sbinfo->si_dbgaufs);
++      sbinfo->si_dbgaufs = NULL;
++      kobject_put(&sbinfo->si_kobj);
++}
++
++int dbgaufs_si_init(struct au_sbinfo *sbinfo)
++{
++      int err;
++      char name[SysaufsSiNameLen];
++
++      err = -ENOENT;
++      if (!dbgaufs) {
++              AuErr1("/debug/aufs is uninitialized\n");
++              goto out;
++      }
++
++      err = -EIO;
++      sysaufs_name(sbinfo, name);
++      sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
++      if (unlikely(!sbinfo->si_dbgaufs))
++              goto out;
++      kobject_get(&sbinfo->si_kobj);
++
++      sbinfo->si_dbgaufs_xib = debugfs_create_file
++              ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
++               &dbgaufs_xib_fop);
++      if (unlikely(!sbinfo->si_dbgaufs_xib))
++              goto out_dir;
++
++      err = dbgaufs_xigen_init(sbinfo);
++      if (!err)
++              goto out; /* success */
++
++ out_dir:
++      dbgaufs_si_fin(sbinfo);
++ out:
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void dbgaufs_fin(void)
++{
++      debugfs_remove(dbgaufs);
++}
++
++int __init dbgaufs_init(void)
++{
++      int err;
++
++      err = -EIO;
++      dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
++      if (dbgaufs)
++              err = 0;
++      return err;
++}
+diff -Naur a/fs/aufs/dbgaufs.h b/fs/aufs/dbgaufs.h
+--- a/fs/aufs/dbgaufs.h        1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dbgaufs.h        2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,79 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * debugfs interface
++ */
++
++#ifndef __DBGAUFS_H__
++#define __DBGAUFS_H__
++
++#ifdef __KERNEL__
++
++#include <linux/init.h>
++#include <linux/aufs_type.h>
++
++struct super_block;
++struct au_sbinfo;
++
++#ifdef CONFIG_DEBUG_FS
++/* dbgaufs.c */
++void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
++void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
++void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
++int dbgaufs_si_init(struct au_sbinfo *sbinfo);
++void dbgaufs_fin(void);
++int __init dbgaufs_init(void);
++
++#else
++
++static inline
++void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
++{
++      /* empty */
++}
++
++static inline
++void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
++{
++      /* empty */
++}
++
++static inline
++void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
++{
++      /* empty */
++}
++
++static inline
++int dbgaufs_si_init(struct au_sbinfo *sbinfo)
++{
++      return 0;
++}
++
++#define dbgaufs_fin() do {} while (0)
++
++static inline
++int __init dbgaufs_init(void)
++{
++      return 0;
++}
++#endif /* CONFIG_DEBUG_FS */
++
++#endif /* __KERNEL__ */
++#endif /* __DBGAUFS_H__ */
+diff -Naur a/fs/aufs/dcsub.c b/fs/aufs/dcsub.c
+--- a/fs/aufs/dcsub.c  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dcsub.c  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,223 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * sub-routines for dentry cache
++ */
++
++#include "aufs.h"
++
++static void au_dpage_free(struct au_dpage *dpage)
++{
++      int i;
++      struct dentry **p;
++
++      p = dpage->dentries;
++      for (i = 0; i < dpage->ndentry; i++)
++              dput(*p++);
++      free_page((unsigned long)dpage->dentries);
++}
++
++int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
++{
++      int err;
++      void *p;
++
++      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:
++      return err;
++}
++
++void au_dpages_free(struct au_dcsub_pages *dpages)
++{
++      int i;
++      struct au_dpage *p;
++
++      p = dpages->dpages;
++      for (i = 0; i < dpages->ndpage; i++)
++              au_dpage_free(p++);
++      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;
++
++      dpage = dpages->dpages + dpages->ndpage - 1;
++      sz = PAGE_SIZE / sizeof(dentry);
++      if (unlikely(dpage->ndentry >= sz)) {
++              AuLabel(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;
++
++              dpages->dpages = p;
++              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:
++      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;
++
++      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_u.d_child);
++              next = tmp->next;
++              if (/*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_u.d_child.next;
++              this_parent = this_parent->d_parent; /* dcache_lock is locked */
++              goto resume;
++      }
++ out:
++      spin_unlock(&dcache_lock);
++      return err;
++}
++
++int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
++                     int do_include, au_dpages_test test, void *arg)
++{
++      int err;
++
++      err = 0;
++      spin_lock(&dcache_lock);
++      if (do_include && (!test || test(dentry, arg))) {
++              err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
++              if (unlikely(err))
++                      goto out;
++      }
++      while (!IS_ROOT(dentry)) {
++              dentry = dentry->d_parent; /* dcache_lock is locked */
++              if (!test || test(dentry, arg)) {
++                      err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
++                      if (unlikely(err))
++                              break;
++              }
++      }
++
++ out:
++      spin_unlock(&dcache_lock);
++
++      return err;
++}
++
++struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2)
++{
++      struct dentry *trap, **dentries;
++      int err, i, j;
++      struct au_dcsub_pages dpages;
++      struct au_dpage *dpage;
++
++      trap = ERR_PTR(-ENOMEM);
++      err = au_dpages_init(&dpages, GFP_NOFS);
++      if (unlikely(err))
++              goto out;
++      err = au_dcsub_pages_rev(&dpages, d1, /*do_include*/1, NULL, NULL);
++      if (unlikely(err))
++              goto out_dpages;
++
++      trap = d1;
++      for (i = 0; !err && i < dpages.ndpage; i++) {
++              dpage = dpages.dpages + i;
++              dentries = dpage->dentries;
++              for (j = 0; !err && j < dpage->ndentry; j++) {
++                      struct dentry *d;
++
++                      d = dentries[j];
++                      err = (d == d2);
++                      if (!err)
++                              trap = d;
++              }
++      }
++      if (!err)
++              trap = NULL;
++
++ out_dpages:
++      au_dpages_free(&dpages);
++ out:
++      return trap;
++}
+diff -Naur a/fs/aufs/dcsub.h b/fs/aufs/dcsub.h
+--- a/fs/aufs/dcsub.h  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dcsub.h  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,54 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * sub-routines for dentry cache
++ */
++
++#ifndef __AUFS_DCSUB_H__
++#define __AUFS_DCSUB_H__
++
++#ifdef __KERNEL__
++
++#include <linux/types.h>
++
++struct dentry;
++
++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);
++int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
++                     int do_include, au_dpages_test test, void *arg);
++struct dentry *au_test_subdir(struct dentry *d1, struct dentry *d2);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DCSUB_H__ */
+diff -Naur a/fs/aufs/debug.c b/fs/aufs/debug.c
+--- a/fs/aufs/debug.c  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/debug.c  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,427 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * debug print functions
++ */
++
++#include <linux/module.h>
++#include <linux/vt_kern.h>
++#include "aufs.h"
++
++int aufs_debug;
++MODULE_PARM_DESC(debug, "debug print");
++module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
++
++char *au_plevel = KERN_DEBUG;
++#define dpri(fmt, arg...) do { \
++      if (au_debug_test()) \
++              printk("%s" fmt, au_plevel, ##arg); \
++} while (0)
++
++/* ---------------------------------------------------------------------- */
++
++void au_dpri_whlist(struct au_nhash *whlist)
++{
++      unsigned long ul, n;
++      struct hlist_head *head;
++      struct au_vdir_wh *tpos;
++      struct hlist_node *pos;
++
++      n = whlist->nh_num;
++      head = whlist->nh_head;
++      for (ul = 0; ul < n; ul++) {
++              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);
++              head++;
++      }
++}
++
++void au_dpri_vdir(struct au_vdir *vdir)
++{
++      unsigned long ul;
++      union au_vdir_deblk_p p;
++      unsigned char *o;
++
++      if (!vdir || IS_ERR(vdir)) {
++              dpri("err %ld\n", PTR_ERR(vdir));
++              return;
++      }
++
++      dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
++           vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
++           vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
++      for (ul = 0; ul < vdir->vd_nblk; ul++) {
++              p.deblk = vdir->vd_deblk[ul];
++              o = p.deblk;
++              dpri("[%lu]: %p\n", ul, o);
++      }
++}
++
++static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
++                      struct dentry *wh)
++{
++      char *n = NULL;
++      int l = 0;
++
++      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));
++      if (wh) {
++              n = (void *)wh->d_name.name;
++              l = wh->d_name.len;
++      }
++
++      dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
++           " ct %lld, np %lu, st 0x%lx, f 0x%x, g %x%s%.*s\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), (unsigned long long)inode->i_blocks,
++           (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
++           inode->i_mapping ? inode->i_mapping->nrpages : 0,
++           inode->i_state, inode->i_flags, inode->i_generation,
++           l ? ", wh " : "", l, n);
++      return 0;
++}
++
++void au_dpri_inode(struct inode *inode)
++{
++      struct au_iinfo *iinfo;
++      aufs_bindex_t bindex;
++      int err;
++
++      err = do_pri_inode(-1, inode, NULL);
++      if (err || !au_test_aufs(inode->i_sb))
++              return;
++
++      iinfo = au_ii(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,
++                           iinfo->ii_hinode[0 + bindex].hi_whdentry);
++}
++
++static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
++{
++      struct dentry *wh = NULL;
++
++      if (!dentry || IS_ERR(dentry)) {
++              dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
++              return -1;
++      }
++      /* do not call dget_parent() here */
++      dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
++           bindex,
++           AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
++           dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
++           atomic_read(&dentry->d_count), dentry->d_flags);
++      if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
++              struct au_iinfo *iinfo = au_ii(dentry->d_inode);
++              if (iinfo)
++                      wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
++      }
++      do_pri_inode(bindex, dentry->d_inode, wh);
++      return 0;
++}
++
++void au_dpri_dentry(struct dentry *dentry)
++{
++      struct au_dinfo *dinfo;
++      aufs_bindex_t bindex;
++      int err;
++
++      err = do_pri_dentry(-1, dentry);
++      if (err || !au_test_aufs(dentry->d_sb))
++              return;
++
++      dinfo = au_di(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 < 0
++          && file->f_dentry
++          && au_test_aufs(file->f_dentry->d_sb)
++          && au_fi(file))
++              snprintf(a, sizeof(a), ", mmapped %d", au_test_mmapped(file));
++      dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, pos %llu%s\n",
++           bindex, file->f_mode, file->f_flags, (long)file_count(file),
++           file->f_pos, a);
++      if (file->f_dentry)
++              do_pri_dentry(bindex, file->f_dentry);
++      return 0;
++}
++
++void au_dpri_file(struct file *file)
++{
++      struct au_finfo *finfo;
++      aufs_bindex_t bindex;
++      int err;
++
++      err = do_pri_file(-1, file);
++      if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
++              return;
++
++      finfo = au_fi(file);
++      if (!finfo)
++              return;
++      if (finfo->fi_bstart < 0)
++              return;
++      for (bindex = finfo->fi_bstart; bindex <= finfo->fi_bend; bindex++) {
++              struct au_hfile *hf;
++
++              hf = finfo->fi_hfile + bindex;
++              do_pri_file(bindex, hf ? hf->hf_file : NULL);
++      }
++}
++
++static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
++{
++      struct vfsmount *mnt;
++      struct super_block *sb;
++
++      if (!br || IS_ERR(br))
++              goto out;
++      mnt = br->br_mnt;
++      if (!mnt || IS_ERR(mnt))
++              goto out;
++      sb = mnt->mnt_sb;
++      if (!sb || IS_ERR(sb))
++              goto out;
++
++      dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
++           "%s, dev 0x%02x%02x, flags 0x%lx, cnt(BIAS) %d, active %d, "
++           "xino %d\n",
++           bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
++           au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
++           sb->s_flags, sb->s_count - S_BIAS,
++           atomic_read(&sb->s_active), !!br->br_xino.xi_file);
++      return 0;
++
++ out:
++      dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
++      return -1;
++}
++
++void au_dpri_sb(struct super_block *sb)
++{
++      struct au_sbinfo *sbinfo;
++      aufs_bindex_t bindex;
++      int err;
++      /* to reuduce stack size */
++      struct {
++              struct vfsmount mnt;
++              struct au_branch fake;
++      } *a;
++
++      /* this function can be called from magic sysrq */
++      a = kzalloc(sizeof(*a), GFP_ATOMIC);
++      if (unlikely(!a)) {
++              dpri("no memory\n");
++              return;
++      }
++
++      a->mnt.mnt_sb = sb;
++      a->fake.br_perm = 0;
++      a->fake.br_mnt = &a->mnt;
++      a->fake.br_xino.xi_file = NULL;
++      atomic_set(&a->fake.br_count, 0);
++      smp_mb(); /* atomic_set */
++      err = do_pri_br(-1, &a->fake);
++      kfree(a);
++      dpri("dev 0x%x\n", sb->s_dev);
++      if (err || !au_test_aufs(sb))
++              return;
++
++      sbinfo = au_sbi(sb);
++      if (!sbinfo)
++              return;
++      dpri("nw %d, gen %u, kobj %d\n",
++           atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
++           atomic_read(&sbinfo->si_kobj.kref.refcount));
++      for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
++              do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_dbg_sleep_jiffy(int jiffy)
++{
++      while (jiffy)
++              jiffy = schedule_timeout_uninterruptible(jiffy);
++}
++
++void au_dbg_iattr(struct iattr *ia)
++{
++#define AuBit(name)   if (ia->ia_valid & ATTR_ ## name) \
++                              dpri(#name "\n")
++      AuBit(MODE);
++      AuBit(UID);
++      AuBit(GID);
++      AuBit(SIZE);
++      AuBit(ATIME);
++      AuBit(MTIME);
++      AuBit(CTIME);
++      AuBit(ATIME_SET);
++      AuBit(MTIME_SET);
++      AuBit(FORCE);
++      AuBit(ATTR_FLAG);
++      AuBit(KILL_SUID);
++      AuBit(KILL_SGID);
++      AuBit(FILE);
++      AuBit(KILL_PRIV);
++      AuBit(OPEN);
++      AuBit(TIMES_SET);
++#undef        AuBit
++      dpri("ia_file %p\n", ia->ia_file);
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
++{
++      struct dentry *parent;
++
++      parent = dget_parent(dentry);
++      AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode)
++                || IS_ROOT(dentry)
++                || au_digen(parent) != sigen);
++      dput(parent);
++}
++
++void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
++{
++      struct dentry *parent;
++
++      parent = dget_parent(dentry);
++      AuDebugOn(S_ISDIR(dentry->d_inode->i_mode)
++                || au_digen(parent) != sigen);
++      dput(parent);
++}
++
++void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
++{
++      int err, i, j;
++      struct au_dcsub_pages dpages;
++      struct au_dpage *dpage;
++      struct dentry **dentries;
++
++      err = au_dpages_init(&dpages, GFP_NOFS);
++      AuDebugOn(err);
++      err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL, NULL);
++      AuDebugOn(err);
++      for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
++              dpage = dpages.dpages + i;
++              dentries = dpage->dentries;
++              for (j = dpage->ndentry - 1; !err && j >= 0; j--)
++                      AuDebugOn(au_digen(dentries[j]) != sigen);
++      }
++      au_dpages_free(&dpages);
++}
++
++void au_dbg_verify_hf(struct au_finfo *finfo)
++{
++      struct au_hfile *hf;
++      aufs_bindex_t bend, bindex;
++
++      if (finfo->fi_bstart >= 0) {
++              bend = finfo->fi_bend;
++              for (bindex = finfo->fi_bstart; bindex <= bend; bindex++) {
++                      hf = finfo->fi_hfile + bindex;
++                      AuDebugOn(hf->hf_file || hf->hf_br);
++              }
++      }
++}
++
++void au_dbg_verify_kthread(void)
++{
++      if (au_test_wkq(current)) {
++              au_dbg_blocked();
++              BUG();
++      }
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
++{
++#ifdef AuForceNoPlink
++      au_opt_clr(sbinfo->si_mntflags, PLINK);
++#endif
++#ifdef AuForceNoXino
++      au_opt_clr(sbinfo->si_mntflags, XINO);
++#endif
++#ifdef AuForceNoRefrof
++      au_opt_clr(sbinfo->si_mntflags, REFROF);
++#endif
++#ifdef AuForceHinotify
++      au_opt_set_udba(sbinfo->si_mntflags, UDBA_HINOTIFY);
++#endif
++}
++
++int __init au_debug_init(void)
++{
++      aufs_bindex_t bindex;
++      struct au_vdir_destr destr;
++
++      bindex = -1;
++      AuDebugOn(bindex >= 0);
++
++      destr.len = -1;
++      AuDebugOn(destr.len < NAME_MAX);
++
++#ifdef CONFIG_4KSTACKS
++      AuWarn("CONFIG_4KSTACKS is defined.\n");
++#endif
++
++#ifdef AuForceNoBrs
++      sysaufs_brs = 0;
++#endif
++
++      return 0;
++}
+diff -Naur a/fs/aufs/debug.h b/fs/aufs/debug.h
+--- a/fs/aufs/debug.h  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/debug.h  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,260 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * debug print functions
++ */
++
++#ifndef __AUFS_DEBUG_H__
++#define __AUFS_DEBUG_H__
++
++#ifdef __KERNEL__
++
++#include <linux/bug.h>
++/* #include <linux/err.h> */
++/* #include <linux/init.h> */
++/* #include <linux/kernel.h> */
++#include <linux/delay.h>
++/* #include <linux/kd.h> */
++/* #include <linux/vt_kern.h> */
++#include <linux/sysrq.h>
++#include <linux/aufs_type.h>
++
++#ifdef CONFIG_AUFS_DEBUG
++#define AuDebugOn(a)          BUG_ON(a)
++
++/* module parameter */
++extern int aufs_debug;
++static inline void au_debug(int n)
++{
++      aufs_debug = n;
++      smp_mb();
++}
++
++static inline int au_debug_test(void)
++{
++      return aufs_debug;
++}
++#else
++#define AuDebugOn(a)          do {} while (0)
++#define au_debug()            do {} while (0)
++static inline int au_debug_test(void)
++{
++      return 0;
++}
++#endif /* CONFIG_AUFS_DEBUG */
++
++/* ---------------------------------------------------------------------- */
++
++/* debug print */
++
++#define AuDpri(lvl, fmt, arg...) \
++      printk(lvl AUFS_NAME " %s:%d:%s[%d]: " fmt, \
++             __func__, __LINE__, current->comm, current->pid, ##arg)
++#define AuDbg(fmt, arg...) do { \
++      if (au_debug_test()) \
++              AuDpri(KERN_DEBUG, fmt, ##arg); \
++} while (0)
++#define AuLabel(l)            AuDbg(#l "\n")
++#define AuInfo(fmt, arg...)   AuDpri(KERN_INFO, fmt, ##arg)
++#define AuWarn(fmt, arg...)   AuDpri(KERN_WARNING, fmt, ##arg)
++#define AuErr(fmt, arg...)    AuDpri(KERN_ERR, fmt, ##arg)
++#define AuIOErr(fmt, arg...)  AuErr("I/O Error, " fmt, ##arg)
++#define AuWarn1(fmt, arg...) do { \
++      static unsigned char _c; \
++      if (!_c++) \
++              AuWarn(fmt, ##arg); \
++} while (0)
++
++#define AuErr1(fmt, arg...) do { \
++      static unsigned char _c; \
++      if (!_c++) \
++              AuErr(fmt, ##arg); \
++} while (0)
++
++#define AuIOErr1(fmt, arg...) do { \
++      static unsigned char _c; \
++      if (!_c++) \
++              AuIOErr(fmt, ##arg); \
++} while (0)
++
++#define AuUnsupportMsg        "This operation is not supported." \
++                      " Please report this application to aufs-users ML."
++#define AuUnsupport(fmt, args...) do { \
++      AuErr(AuUnsupportMsg "\n" fmt, ##args); \
++      dump_stack(); \
++} while (0)
++
++#define AuTraceErr(e) do { \
++      if (unlikely((e) < 0)) \
++              AuDbg("err %d\n", (int)(e)); \
++} while (0)
++
++#define AuTraceErrPtr(p) do { \
++      if (IS_ERR(p)) \
++              AuDbg("err %ld\n", PTR_ERR(p)); \
++} while (0)
++
++/* dirty macros for debug print, use with "%.*s" and caution */
++#define AuLNPair(qstr)                (qstr)->len, (qstr)->name
++#define AuDLNPair(d)          AuLNPair(&(d)->d_name)
++
++/* ---------------------------------------------------------------------- */
++
++struct au_sbinfo;
++struct au_finfo;
++struct dentry;
++#ifdef CONFIG_AUFS_DEBUG
++extern char *au_plevel;
++struct au_nhash;
++void au_dpri_whlist(struct au_nhash *whlist);
++struct au_vdir;
++void au_dpri_vdir(struct au_vdir *vdir);
++struct inode;
++void au_dpri_inode(struct inode *inode);
++void au_dpri_dentry(struct dentry *dentry);
++struct file;
++void au_dpri_file(struct file *filp);
++struct super_block;
++void au_dpri_sb(struct super_block *sb);
++
++void au_dbg_sleep_jiffy(int jiffy);
++struct iattr;
++void au_dbg_iattr(struct iattr *ia);
++
++void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
++void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
++void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
++void au_dbg_verify_hf(struct au_finfo *finfo);
++void au_dbg_verify_kthread(void);
++
++int __init au_debug_init(void);
++void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
++#define AuDbgWhlist(w) do { \
++      AuDbg(#w "\n"); \
++      au_dpri_whlist(w); \
++} while (0)
++
++#define AuDbgVdir(v) do { \
++      AuDbg(#v "\n"); \
++      au_dpri_vdir(v); \
++} while (0)
++
++#define AuDbgInode(i) do { \
++      AuDbg(#i "\n"); \
++      au_dpri_inode(i); \
++} while (0)
++
++#define AuDbgDentry(d) do { \
++      AuDbg(#d "\n"); \
++      au_dpri_dentry(d); \
++} while (0)
++
++#define AuDbgFile(f) do { \
++      AuDbg(#f "\n"); \
++      au_dpri_file(f); \
++} while (0)
++
++#define AuDbgSb(sb) do { \
++      AuDbg(#sb "\n"); \
++      au_dpri_sb(sb); \
++} while (0)
++
++#define AuDbgSleep(sec) do { \
++      AuDbg("sleep %d sec\n", sec); \
++      ssleep(sec); \
++} while (0)
++
++#define AuDbgSleepJiffy(jiffy) do { \
++      AuDbg("sleep %d jiffies\n", jiffy); \
++      au_dbg_sleep_jiffy(jiffy); \
++} while (0)
++
++#define AuDbgIAttr(ia) do { \
++      AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
++      au_dbg_iattr(ia); \
++} while (0)
++#else
++static inline void au_dbg_verify_dir_parent(struct dentry *dentry,
++                                          unsigned int sigen)
++{
++      /* empty */
++}
++static inline void au_dbg_verify_nondir_parent(struct dentry *dentry,
++                                             unsigned int sigen)
++{
++      /* empty */
++}
++static inline void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
++{
++      /* empty */
++}
++static inline void au_dbg_verify_hf(struct au_finfo *finfo)
++{
++      /* empty */
++}
++static inline void au_dbg_verify_kthread(void)
++{
++      /* empty */
++}
++
++static inline int au_debug_init(void)
++{
++      return 0;
++}
++static inline void au_debug_sbinfo_init(struct au_sbinfo *sbinfo)
++{
++      /* empty */
++}
++#define AuDbgWhlist(w)                do {} while (0)
++#define AuDbgVdir(v)          do {} while (0)
++#define AuDbgInode(i)         do {} while (0)
++#define AuDbgDentry(d)                do {} while (0)
++#define AuDbgFile(f)          do {} while (0)
++#define AuDbgSb(sb)           do {} while (0)
++#define AuDbgSleep(sec)               do {} while (0)
++#define AuDbgSleepJiffy(jiffy)        do {} while (0)
++#define AuDbgIAttr(ia)                do {} while (0)
++#endif /* CONFIG_AUFS_DEBUG */
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_MAGIC_SYSRQ
++int __init au_sysrq_init(void);
++void au_sysrq_fin(void);
++
++#ifdef CONFIG_HW_CONSOLE
++#define au_dbg_blocked() do { \
++      WARN_ON(1); \
++      handle_sysrq('w', vc_cons[fg_console].d->vc_tty); \
++} while (0)
++#else
++#define au_dbg_blocked()      do {} while (0)
++#endif
++
++#else
++static inline int au_sysrq_init(void)
++{
++      return 0;
++}
++#define au_sysrq_fin()                do {} while (0)
++#define au_dbg_blocked()      do {} while (0)
++#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DEBUG_H__ */
+diff -Naur a/fs/aufs/dentry.c b/fs/aufs/dentry.c
+--- a/fs/aufs/dentry.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dentry.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,876 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * lookup and dentry operations
++ */
++
++#include <linux/namei.h>
++#include "aufs.h"
++
++static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
++{
++      if (nd) {
++              *h_nd = *nd;
++
++              /*
++               * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
++               * due to whiteout and branch permission.
++               */
++              h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
++                               | LOOKUP_FOLLOW);
++              /* unnecessary? */
++              h_nd->intent.open.file = NULL;
++      } else
++              memset(h_nd, 0, sizeof(*h_nd));
++}
++
++struct au_lkup_one_args {
++      struct dentry **errp;
++      struct qstr *name;
++      struct dentry *h_parent;
++      struct au_branch *br;
++      struct nameidata *nd;
++};
++
++struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
++                         struct au_branch *br, struct nameidata *nd)
++{
++      struct dentry *h_dentry;
++      int err;
++      struct nameidata h_nd;
++
++      if (au_test_fs_null_nd(h_parent->d_sb))
++              return vfsub_lookup_one_len(name->name, h_parent, name->len);
++
++      au_h_nd(&h_nd, nd);
++      h_nd.path.dentry = h_parent;
++      h_nd.path.mnt = br->br_mnt;
++
++      err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len);
++      h_dentry = ERR_PTR(err);
++      if (!err) {
++              path_get(&h_nd.path);
++              h_dentry = vfsub_lookup_hash(&h_nd);
++              path_put(&h_nd.path);
++      }
++
++      return h_dentry;
++}
++
++static void au_call_lkup_one(void *args)
++{
++      struct au_lkup_one_args *a = args;
++      *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
++}
++
++#define AuLkup_ALLOW_NEG      1
++#define au_ftest_lkup(flags, name)    ((flags) & AuLkup_##name)
++#define au_fset_lkup(flags, name)     { (flags) |= AuLkup_##name; }
++#define au_fclr_lkup(flags, name)     { (flags) &= ~AuLkup_##name; }
++
++struct au_do_lookup_args {
++      unsigned int            flags;
++      mode_t                  type;
++      struct nameidata        *nd;
++};
++
++/*
++ * returns positive/negative dentry, NULL or an error.
++ * NULL means whiteout-ed or not-found.
++ */
++static struct dentry*
++au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
++           aufs_bindex_t bindex, struct qstr *wh_name,
++           struct au_do_lookup_args *args)
++{
++      struct dentry *h_dentry;
++      struct inode *h_inode, *inode;
++      struct qstr *name;
++      struct au_branch *br;
++      int wh_found, opq;
++      unsigned char wh_able;
++      const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
++
++      name = &dentry->d_name;
++      wh_found = 0;
++      br = au_sbr(dentry->d_sb, bindex);
++      wh_able = !!au_br_whable(br->br_perm);
++      if (wh_able)
++              wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
++      h_dentry = ERR_PTR(wh_found);
++      if (!wh_found)
++              goto real_lookup;
++      if (unlikely(wh_found < 0))
++              goto out;
++
++      /* We found a whiteout */
++      /* au_set_dbend(dentry, bindex); */
++      au_set_dbwh(dentry, bindex);
++      if (!allow_neg)
++              return NULL; /* success */
++
++ real_lookup:
++      h_dentry = au_lkup_one(name, h_parent, br, args->nd);
++      if (IS_ERR(h_dentry))
++              goto out;
++
++      h_inode = h_dentry->d_inode;
++      if (!h_inode) {
++              if (!allow_neg)
++                      goto out_neg;
++      } else if (wh_found
++                 || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
++              goto out_neg;
++
++      if (au_dbend(dentry) <= bindex)
++              au_set_dbend(dentry, bindex);
++      if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
++              au_set_dbstart(dentry, bindex);
++      au_set_h_dptr(dentry, bindex, h_dentry);
++
++      inode = dentry->d_inode;
++      if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
++          || (inode && !S_ISDIR(inode->i_mode)))
++              goto out; /* success */
++
++      mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++      opq = au_diropq_test(h_dentry, br);
++      mutex_unlock(&h_inode->i_mutex);
++      if (opq > 0)
++              au_set_dbdiropq(dentry, bindex);
++      else if (unlikely(opq < 0)) {
++              au_set_h_dptr(dentry, bindex, NULL);
++              h_dentry = ERR_PTR(opq);
++      }
++      goto out;
++
++ out_neg:
++      dput(h_dentry);
++      h_dentry = NULL;
++ out:
++      return h_dentry;
++}
++
++static int au_test_shwh(struct super_block *sb, const struct qstr *name)
++{
++      if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
++                   && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
++              return -EPERM;
++      return 0;
++}
++
++/*
++ * returns the number of lower positive dentries,
++ * otherwise an error.
++ * can be called at unlinking with @type is zero.
++ */
++int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
++                 struct nameidata *nd)
++{
++      int npositive, err;
++      aufs_bindex_t bindex, btail, bdiropq;
++      unsigned char isdir;
++      struct qstr whname;
++      struct au_do_lookup_args args = {
++              .flags  = 0,
++              .type   = type,
++              .nd     = nd
++      };
++      const struct qstr *name = &dentry->d_name;
++      struct dentry *parent;
++      struct inode *inode;
++
++      parent = dget_parent(dentry);
++      err = au_test_shwh(dentry->d_sb, name);
++      if (unlikely(err))
++              goto out;
++
++      err = au_wh_name_alloc(&whname, name);
++      if (unlikely(err))
++              goto out;
++
++      inode = dentry->d_inode;
++      isdir = !!(inode && S_ISDIR(inode->i_mode));
++      if (!type)
++              au_fset_lkup(args.flags, ALLOW_NEG);
++
++      npositive = 0;
++      btail = au_dbtaildir(parent);
++      for (bindex = bstart; bindex <= btail; bindex++) {
++              struct dentry *h_parent, *h_dentry;
++              struct inode *h_inode, *h_dir;
++
++              h_dentry = au_h_dptr(dentry, bindex);
++              if (h_dentry) {
++                      if (h_dentry->d_inode)
++                              npositive++;
++                      if (type != S_IFDIR)
++                              break;
++                      continue;
++              }
++              h_parent = au_h_dptr(parent, bindex);
++              if (!h_parent)
++                      continue;
++              h_dir = h_parent->d_inode;
++              if (!h_dir || !S_ISDIR(h_dir->i_mode))
++                      continue;
++
++              mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
++              h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
++                                      &args);
++              mutex_unlock(&h_dir->i_mutex);
++              err = PTR_ERR(h_dentry);
++              if (IS_ERR(h_dentry))
++                      goto out_wh;
++              au_fclr_lkup(args.flags, ALLOW_NEG);
++
++              if (au_dbwh(dentry) >= 0)
++                      break;
++              if (!h_dentry)
++                      continue;
++              h_inode = h_dentry->d_inode;
++              if (!h_inode)
++                      continue;
++              npositive++;
++              if (!args.type)
++                      args.type = h_inode->i_mode & S_IFMT;
++              if (args.type != S_IFDIR)
++                      break;
++              else if (isdir) {
++                      /* the type of lower may be different */
++                      bdiropq = au_dbdiropq(dentry);
++                      if (bdiropq >= 0 && bdiropq <= bindex)
++                              break;
++              }
++      }
++
++      if (npositive) {
++              AuLabel(positive);
++              au_update_dbstart(dentry);
++      }
++      err = npositive;
++      if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
++                   && au_dbstart(dentry) < 0))
++              /* both of real entry and whiteout found */
++              err = -EIO;
++
++ out_wh:
++      kfree(whname.name);
++ out:
++      dput(parent);
++      return err;
++}
++
++struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
++                             struct au_branch *br)
++{
++      struct dentry *dentry;
++      int wkq_err;
++
++      if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
++              dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
++      else {
++              struct au_lkup_one_args args = {
++                      .errp           = &dentry,
++                      .name           = name,
++                      .h_parent       = parent,
++                      .br             = br,
++                      .nd             = NULL
++              };
++
++              wkq_err = au_wkq_wait(au_call_lkup_one, &args);
++              if (unlikely(wkq_err))
++                      dentry = ERR_PTR(wkq_err);
++      }
++
++      return dentry;
++}
++
++/*
++ * lookup @dentry on @bindex which should be negative.
++ */
++int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
++{
++      int err;
++      struct dentry *parent, *h_parent, *h_dentry;
++      struct qstr *name;
++
++      name = &dentry->d_name;
++      parent = dget_parent(dentry);
++      h_parent = au_h_dptr(parent, bindex);
++      h_dentry = au_sio_lkup_one(name, h_parent,
++                                 au_sbr(dentry->d_sb, bindex));
++      err = PTR_ERR(h_dentry);
++      if (IS_ERR(h_dentry))
++              goto out;
++      if (unlikely(h_dentry->d_inode)) {
++              err = -EIO;
++              AuIOErr("b%d %.*s should be negative.\n",
++                      bindex, AuDLNPair(h_dentry));
++              dput(h_dentry);
++              goto out;
++      }
++
++      if (bindex < au_dbstart(dentry))
++              au_set_dbstart(dentry, bindex);
++      if (au_dbend(dentry) < bindex)
++              au_set_dbend(dentry, bindex);
++      au_set_h_dptr(dentry, bindex, h_dentry);
++      err = 0;
++
++ out:
++      dput(parent);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* subset of struct inode */
++struct au_iattr {
++      unsigned long           i_ino;
++      /* unsigned int         i_nlink; */
++      uid_t                   i_uid;
++      gid_t                   i_gid;
++      u64                     i_version;
++/*
++      loff_t                  i_size;
++      blkcnt_t                i_blocks;
++*/
++      umode_t                 i_mode;
++};
++
++static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
++{
++      ia->i_ino = h_inode->i_ino;
++      /* ia->i_nlink = h_inode->i_nlink; */
++      ia->i_uid = h_inode->i_uid;
++      ia->i_gid = h_inode->i_gid;
++      ia->i_version = h_inode->i_version;
++/*
++      ia->i_size = h_inode->i_size;
++      ia->i_blocks = h_inode->i_blocks;
++*/
++      ia->i_mode = (h_inode->i_mode & S_IFMT);
++}
++
++static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
++{
++      return ia->i_ino != h_inode->i_ino
++              /* || ia->i_nlink != h_inode->i_nlink */
++              || ia->i_uid != h_inode->i_uid
++              || ia->i_gid != h_inode->i_gid
++              || ia->i_version != h_inode->i_version
++/*
++              || ia->i_size != h_inode->i_size
++              || ia->i_blocks != h_inode->i_blocks
++*/
++              || ia->i_mode != (h_inode->i_mode & S_IFMT);
++}
++
++static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
++                            struct au_branch *br)
++{
++      int err;
++      struct au_iattr ia;
++      struct inode *h_inode;
++      struct dentry *h_d;
++      struct super_block *h_sb;
++
++      err = 0;
++      memset(&ia, -1, sizeof(ia));
++      h_sb = h_dentry->d_sb;
++      h_inode = h_dentry->d_inode;
++      if (h_inode)
++              au_iattr_save(&ia, h_inode);
++      else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
++              /* nfs d_revalidate may return 0 for negative dentry */
++              /* fuse d_revalidate always return 0 for negative dentry */
++              goto out;
++
++      /* main purpose is namei.c:cached_lookup() and d_revalidate */
++      h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
++      err = PTR_ERR(h_d);
++      if (IS_ERR(h_d))
++              goto out;
++
++      err = 0;
++      if (unlikely(h_d != h_dentry
++                   || h_d->d_inode != h_inode
++                   || (h_inode && au_iattr_test(&ia, h_inode))))
++              err = au_busy_or_stale();
++      dput(h_d);
++
++ out:
++      AuTraceErr(err);
++      return err;
++}
++
++int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
++              struct dentry *h_parent, struct au_branch *br)
++{
++      int err;
++
++      err = 0;
++      if (udba == AuOpt_UDBA_REVAL) {
++              IMustLock(h_dir);
++              err = (h_dentry->d_parent->d_inode != h_dir);
++      } else if (udba == AuOpt_UDBA_HINOTIFY)
++              err = au_h_verify_dentry(h_dentry, h_parent, br);
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void au_do_refresh_hdentry(struct au_hdentry *p, struct au_dinfo *dinfo,
++                                struct dentry *parent)
++{
++      struct dentry *h_d, *h_dp;
++      struct au_hdentry tmp, *q;
++      struct super_block *sb;
++      aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
++
++      bend = dinfo->di_bend;
++      bwh = dinfo->di_bwh;
++      bdiropq = dinfo->di_bdiropq;
++      for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
++              h_d = p->hd_dentry;
++              if (!h_d)
++                      continue;
++
++              h_dp = dget_parent(h_d);
++              if (h_dp == au_h_dptr(parent, bindex)) {
++                      dput(h_dp);
++                      continue;
++              }
++
++              new_bindex = au_find_dbindex(parent, h_dp);
++              dput(h_dp);
++              if (dinfo->di_bwh == bindex)
++                      bwh = new_bindex;
++              if (dinfo->di_bdiropq == bindex)
++                      bdiropq = new_bindex;
++              if (new_bindex < 0) {
++                      au_hdput(p);
++                      p->hd_dentry = NULL;
++                      continue;
++              }
++
++              /* swap two lower dentries, and loop again */
++              q = dinfo->di_hdentry + new_bindex;
++              tmp = *q;
++              *q = *p;
++              *p = tmp;
++              if (tmp.hd_dentry) {
++                      bindex--;
++                      p--;
++              }
++      }
++
++      sb = parent->d_sb;
++      dinfo->di_bwh = -1;
++      if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
++              dinfo->di_bwh = bwh;
++
++      dinfo->di_bdiropq = -1;
++      if (bdiropq >= 0
++          && bdiropq <= au_sbend(sb)
++          && au_sbr_whable(sb, bdiropq))
++              dinfo->di_bdiropq = bdiropq;
++
++      bend = au_dbend(parent);
++      p = dinfo->di_hdentry;
++      for (bindex = 0; bindex <= bend; bindex++, p++)
++              if (p->hd_dentry) {
++                      dinfo->di_bstart = bindex;
++                      break;
++              }
++
++      p = dinfo->di_hdentry + bend;
++      for (bindex = bend; bindex >= 0; bindex--, p--)
++              if (p->hd_dentry) {
++                      dinfo->di_bend = bindex;
++                      break;
++              }
++}
++
++/*
++ * returns the number of found lower positive dentries,
++ * otherwise an error.
++ */
++int au_refresh_hdentry(struct dentry *dentry, mode_t type)
++{
++      int npositive, err;
++      unsigned int sigen;
++      aufs_bindex_t bstart;
++      struct au_dinfo *dinfo;
++      struct super_block *sb;
++      struct dentry *parent;
++
++      sb = dentry->d_sb;
++      AuDebugOn(IS_ROOT(dentry));
++      sigen = au_sigen(sb);
++      parent = dget_parent(dentry);
++      AuDebugOn(au_digen(parent) != sigen
++                || au_iigen(parent->d_inode) != sigen);
++
++      dinfo = au_di(dentry);
++      err = au_di_realloc(dinfo, au_sbend(sb) + 1);
++      npositive = err;
++      if (unlikely(err))
++              goto out;
++      au_do_refresh_hdentry(dinfo->di_hdentry + dinfo->di_bstart, dinfo,
++                            parent);
++
++      npositive = 0;
++      bstart = au_dbstart(parent);
++      if (type != S_IFDIR && dinfo->di_bstart == bstart)
++              goto out_dgen; /* success */
++
++      npositive = au_lkup_dentry(dentry, bstart, type, /*nd*/NULL);
++      if (npositive < 0)
++              goto out;
++      if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart)
++              d_drop(dentry);
++
++ out_dgen:
++      au_update_digen(dentry);
++ out:
++      dput(parent);
++      AuTraceErr(npositive);
++      return npositive;
++}
++
++static noinline_for_stack
++int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
++                  struct dentry *dentry, aufs_bindex_t bindex)
++{
++      int err, valid;
++      int (*reval)(struct dentry *, struct nameidata *);
++
++      err = 0;
++      reval = NULL;
++      if (h_dentry->d_op)
++              reval = h_dentry->d_op->d_revalidate;
++      if (!reval)
++              goto out;
++
++      AuDbg("b%d\n", bindex);
++      if (au_test_fs_null_nd(h_dentry->d_sb))
++              /* it may return tri-state */
++              valid = reval(h_dentry, NULL);
++      else {
++              struct nameidata h_nd;
++              int locked;
++              struct dentry *parent;
++
++              au_h_nd(&h_nd, nd);
++              parent = nd->path.dentry;
++              locked = (nd && nd->path.dentry != dentry);
++              if (locked)
++                      di_read_lock_parent(parent, AuLock_IR);
++              BUG_ON(bindex > au_dbend(parent));
++              h_nd.path.dentry = au_h_dptr(parent, bindex);
++              BUG_ON(!h_nd.path.dentry);
++              h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
++              path_get(&h_nd.path);
++              valid = reval(h_dentry, &h_nd);
++              path_put(&h_nd.path);
++              if (locked)
++                      di_read_unlock(parent, AuLock_IR);
++      }
++
++      if (unlikely(valid < 0))
++              err = valid;
++      else if (!valid)
++              err = -EINVAL;
++
++ out:
++      AuTraceErr(err);
++      return err;
++}
++
++/* todo: remove this */
++static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
++                        struct nameidata *nd, int do_udba)
++{
++      int err;
++      umode_t mode, h_mode;
++      aufs_bindex_t bindex, btail, bstart, ibs, ibe;
++      unsigned char plus, unhashed, is_root, h_plus;
++      struct inode *first, *h_inode, *h_cached_inode;
++      struct dentry *h_dentry;
++      struct qstr *name, *h_name;
++
++      err = 0;
++      plus = 0;
++      mode = 0;
++      first = NULL;
++      ibs = -1;
++      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, au_ibstart(inode));
++              ibs = au_ibstart(inode);
++              ibe = au_ibend(inode);
++      }
++
++      bstart = au_dbstart(dentry);
++      btail = bstart;
++      if (inode && S_ISDIR(inode->i_mode))
++              btail = au_dbtaildir(dentry);
++      for (bindex = bstart; bindex <= btail; bindex++) {
++              h_dentry = au_h_dptr(dentry, bindex);
++              if (!h_dentry)
++                      continue;
++
++              AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
++              h_name = &h_dentry->d_name;
++              if (unlikely(do_udba
++                           && !is_root
++                           && (unhashed != !!d_unhashed(h_dentry)
++                               || name->len != h_name->len
++                               || memcmp(name->name, h_name->name, name->len))
++                          )) {
++                      AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
++                                unhashed, d_unhashed(h_dentry),
++                                AuDLNPair(dentry), AuDLNPair(h_dentry));
++                      goto err;
++              }
++
++              err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
++              if (unlikely(err))
++                      /* do not goto err, to keep the errno */
++                      break;
++
++              /* todo: plink too? */
++              if (!do_udba)
++                      continue;
++
++              /* UDBA tests */
++              h_inode = h_dentry->d_inode;
++              if (unlikely(!!inode != !!h_inode))
++                      goto err;
++
++              h_plus = plus;
++              h_mode = mode;
++              h_cached_inode = h_inode;
++              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(inode, bindex);
++
++              if (unlikely(plus != h_plus
++                           || mode != h_mode
++                           || h_cached_inode != h_inode))
++                      goto err;
++              continue;
++
++      err:
++              err = -EINVAL;
++              break;
++      }
++
++      return err;
++}
++
++static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
++{
++      int err;
++      struct dentry *parent;
++      struct inode *inode;
++
++      inode = dentry->d_inode;
++      if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
++              return 0;
++
++      parent = dget_parent(dentry);
++      di_read_lock_parent(parent, AuLock_IR);
++      AuDebugOn(au_digen(parent) != sigen
++                || au_iigen(parent->d_inode) != sigen);
++      au_dbg_verify_gen(parent, sigen);
++
++      /* returns a number of positive dentries */
++      err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
++      if (err >= 0)
++              err = au_refresh_hinode(inode, dentry);
++
++      di_read_unlock(parent, AuLock_IR);
++      dput(parent);
++      return err;
++}
++
++int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
++{
++      int err;
++      struct dentry *d, *parent;
++      struct inode *inode;
++
++      if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS))
++              return simple_reval_dpath(dentry, sigen);
++
++      /* slow loop, keep it simple and stupid */
++      /* cf: au_cpup_dirs() */
++      err = 0;
++      parent = NULL;
++      while (au_digen(dentry) != sigen
++             || au_iigen(dentry->d_inode) != sigen) {
++              d = dentry;
++              while (1) {
++                      dput(parent);
++                      parent = dget_parent(d);
++                      if (au_digen(parent) == sigen
++                          && au_iigen(parent->d_inode) == sigen)
++                              break;
++                      d = parent;
++              }
++
++              inode = d->d_inode;
++              if (d != dentry)
++                      di_write_lock_child(d);
++
++              /* someone might update our dentry while we were sleeping */
++              if (au_digen(d) != sigen || au_iigen(d->d_inode) != sigen) {
++                      di_read_lock_parent(parent, AuLock_IR);
++                      /* returns a number of positive dentries */
++                      err = au_refresh_hdentry(d, inode->i_mode & S_IFMT);
++                      if (err >= 0)
++                              err = au_refresh_hinode(inode, d);
++                      di_read_unlock(parent, AuLock_IR);
++              }
++
++              if (d != dentry)
++                      di_write_unlock(d);
++              dput(parent);
++              if (unlikely(err))
++                      break;
++      }
++
++      return err;
++}
++
++/*
++ * if valid returns 1, otherwise 0.
++ */
++static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
++{
++      int valid, err;
++      unsigned int sigen;
++      unsigned char do_udba;
++      struct super_block *sb;
++      struct inode *inode;
++
++      err = -EINVAL;
++      sb = dentry->d_sb;
++      inode = dentry->d_inode;
++      aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW);
++      sigen = au_sigen(sb);
++      if (au_digen(dentry) != sigen) {
++              AuDebugOn(IS_ROOT(dentry));
++              if (inode)
++                      err = au_reval_dpath(dentry, sigen);
++              if (unlikely(err))
++                      goto out_dgrade;
++              AuDebugOn(au_digen(dentry) != sigen);
++      }
++      if (inode && au_iigen(inode) != sigen) {
++              AuDebugOn(IS_ROOT(dentry));
++              err = au_refresh_hinode(inode, dentry);
++              if (unlikely(err))
++                      goto out_dgrade;
++              AuDebugOn(au_iigen(inode) != sigen);
++      }
++      di_downgrade_lock(dentry, AuLock_IR);
++
++      AuDebugOn(au_digen(dentry) != sigen);
++      AuDebugOn(inode && au_iigen(inode) != sigen);
++      err = -EINVAL;
++      do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
++      if (do_udba && inode) {
++              aufs_bindex_t bstart = au_ibstart(inode);
++
++              if (bstart >= 0
++                  && au_test_higen(inode, au_h_iptr(inode, bstart)))
++                      goto out;
++      }
++
++      err = h_d_revalidate(dentry, inode, nd, do_udba);
++      if (unlikely(!err && do_udba && au_dbstart(dentry) < 0))
++              /* both of real entry and whiteout found */
++              err = -EIO;
++      goto out;
++
++ out_dgrade:
++      di_downgrade_lock(dentry, AuLock_IR);
++ out:
++      au_store_oflag(nd, inode);
++      aufs_read_unlock(dentry, AuLock_IR);
++      AuTraceErr(err);
++      valid = !err;
++      if (!valid)
++              AuDbg("%.*s invalid\n", AuDLNPair(dentry));
++      return valid;
++}
++
++static void aufs_d_release(struct dentry *dentry)
++{
++      struct au_dinfo *dinfo;
++      aufs_bindex_t bend, bindex;
++
++      dinfo = dentry->d_fsdata;
++      if (!dinfo)
++              return;
++
++      /* dentry may not be revalidated */
++      bindex = dinfo->di_bstart;
++      if (bindex >= 0) {
++              struct au_hdentry *p;
++
++              bend = dinfo->di_bend;
++              p = dinfo->di_hdentry + bindex;
++              while (bindex++ <= bend) {
++                      if (p->hd_dentry)
++                              au_hdput(p);
++                      p++;
++              }
++      }
++      kfree(dinfo->di_hdentry);
++      au_rwsem_destroy(&dinfo->di_rwsem);
++      au_cache_free_dinfo(dinfo);
++      au_hin_di_reinit(dentry);
++}
++
++struct dentry_operations aufs_dop = {
++      .d_revalidate   = aufs_d_revalidate,
++      .d_release      = aufs_d_release
++};
+diff -Naur a/fs/aufs/dentry.h b/fs/aufs/dentry.h
+--- a/fs/aufs/dentry.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dentry.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,221 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * lookup and dentry operations
++ */
++
++#ifndef __AUFS_DENTRY_H__
++#define __AUFS_DENTRY_H__
++
++#ifdef __KERNEL__
++
++#include <linux/dcache.h>
++#include <linux/aufs_type.h>
++#include "rwsem.h"
++
++/* make a single member structure for future use */
++/* todo: remove this structure */
++struct au_hdentry {
++      struct dentry           *hd_dentry;
++};
++
++struct au_dinfo {
++      atomic_t                di_generation;
++
++      struct rw_semaphore     di_rwsem;
++      aufs_bindex_t           di_bstart, di_bend, di_bwh, di_bdiropq;
++      struct au_hdentry       *di_hdentry;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* dentry.c */
++extern struct dentry_operations aufs_dop;
++struct au_branch;
++struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
++                         struct au_branch *br, struct nameidata *nd);
++struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
++                             struct au_branch *br);
++int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
++              struct dentry *h_parent, struct au_branch *br);
++
++int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
++                 struct nameidata *nd);
++int au_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, unsigned int sigen);
++
++/* dinfo.c */
++int au_alloc_dinfo(struct dentry *dentry);
++int au_di_realloc(struct au_dinfo *dinfo, int nbr);
++
++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);
++
++struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
++aufs_bindex_t au_dbtail(struct dentry *dentry);
++aufs_bindex_t au_dbtaildir(struct dentry *dentry);
++
++void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
++                 struct dentry *h_dentry);
++void au_update_digen(struct dentry *dentry);
++void au_update_dbrange(struct dentry *dentry, int do_put_zero);
++void au_update_dbstart(struct dentry *dentry);
++void au_update_dbend(struct dentry *dentry);
++int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct au_dinfo *au_di(struct dentry *dentry)
++{
++      return dentry->d_fsdata;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* 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 AuReadLockFunc(name, lsc) \
++static inline void di_read_lock_##name(struct dentry *d, int flags) \
++{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
++
++#define AuWriteLockFunc(name, lsc) \
++static inline void di_write_lock_##name(struct dentry *d) \
++{ di_write_lock(d, AuLsc_DI_##lsc); }
++
++#define AuRWLockFuncs(name, lsc) \
++      AuReadLockFunc(name, lsc) \
++      AuWriteLockFunc(name, lsc)
++
++AuRWLockFuncs(child, CHILD);
++AuRWLockFuncs(child2, CHILD2);
++AuRWLockFuncs(child3, CHILD3);
++AuRWLockFuncs(parent, PARENT);
++AuRWLockFuncs(parent2, PARENT2);
++AuRWLockFuncs(parent3, PARENT3);
++
++#undef AuReadLockFunc
++#undef AuWriteLockFunc
++#undef AuRWLockFuncs
++
++#define DiMustNoWaiters(d)    AuRwMustNoWaiters(&au_di(d)->di_rwsem)
++
++/* ---------------------------------------------------------------------- */
++
++/* todo: memory barrier? */
++static inline unsigned int au_digen(struct dentry *d)
++{
++      return atomic_read(&au_di(d)->di_generation);
++}
++
++static inline void au_h_dentry_init(struct au_hdentry *hdentry)
++{
++      hdentry->hd_dentry = NULL;
++}
++
++static inline void au_hdput(struct au_hdentry *hd)
++{
++      dput(hd->hd_dentry);
++}
++
++static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
++{
++      return au_di(dentry)->di_bstart;
++}
++
++static inline aufs_bindex_t au_dbend(struct dentry *dentry)
++{
++      return au_di(dentry)->di_bend;
++}
++
++static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
++{
++      return au_di(dentry)->di_bwh;
++}
++
++static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
++{
++      return au_di(dentry)->di_bdiropq;
++}
++
++/* todo: hard/soft set? */
++static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
++{
++      au_di(dentry)->di_bstart = bindex;
++}
++
++static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
++{
++      au_di(dentry)->di_bend = bindex;
++}
++
++static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
++{
++      /* dbwh can be outside of bstart - bend range */
++      au_di(dentry)->di_bwh = bindex;
++}
++
++static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
++{
++      au_di(dentry)->di_bdiropq = bindex;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_HINOTIFY
++static inline void au_digen_dec(struct dentry *d)
++{
++      atomic_dec(&au_di(d)->di_generation);
++}
++
++static inline void au_hin_di_reinit(struct dentry *dentry)
++{
++      dentry->d_fsdata = NULL;
++}
++#else
++static inline void au_hin_di_reinit(struct dentry *dentry __maybe_unused)
++{
++      /* empty */
++}
++#endif /* CONFIG_AUFS_HINOTIFY */
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DENTRY_H__ */
+diff -Naur a/fs/aufs/dinfo.c b/fs/aufs/dinfo.c
+--- a/fs/aufs/dinfo.c  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dinfo.c  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,360 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * dentry private data
++ */
++
++#include "aufs.h"
++
++int au_alloc_dinfo(struct dentry *dentry)
++{
++      struct au_dinfo *dinfo;
++      struct super_block *sb;
++      int nbr;
++
++      dinfo = au_cache_alloc_dinfo();
++      if (unlikely(!dinfo))
++              goto out;
++
++      sb = dentry->d_sb;
++      nbr = au_sbend(sb) + 1;
++      if (nbr <= 0)
++              nbr = 1;
++      dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
++      if (unlikely(!dinfo->di_hdentry))
++              goto out_dinfo;
++
++      atomic_set(&dinfo->di_generation, au_sigen(sb));
++      /* smp_mb(); */ /* atomic_set */
++      init_rwsem(&dinfo->di_rwsem);
++      down_write_nested(&dinfo->di_rwsem, AuLsc_DI_CHILD);
++      dinfo->di_bstart = -1;
++      dinfo->di_bend = -1;
++      dinfo->di_bwh = -1;
++      dinfo->di_bdiropq = -1;
++
++      dentry->d_fsdata = dinfo;
++      dentry->d_op = &aufs_dop;
++      return 0; /* success */
++
++ out_dinfo:
++      au_cache_free_dinfo(dinfo);
++ out:
++      return -ENOMEM;
++}
++
++int au_di_realloc(struct au_dinfo *dinfo, int nbr)
++{
++      int err, sz;
++      struct au_hdentry *hdp;
++
++      err = -ENOMEM;
++      sz = sizeof(*hdp) * (dinfo->di_bend + 1);
++      if (!sz)
++              sz = sizeof(*hdp);
++      hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
++      if (hdp) {
++              dinfo->di_hdentry = hdp;
++              err = 0;
++      }
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++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)
++{
++      down_read_nested(&au_di(d)->di_rwsem, lsc);
++      if (d->d_inode) {
++              if (au_ftest_lock(flags, IW))
++                      do_ii_write_lock(d->d_inode, lsc);
++              else if (au_ftest_lock(flags, IR))
++                      do_ii_read_lock(d->d_inode, lsc);
++      }
++}
++
++void di_read_unlock(struct dentry *d, int flags)
++{
++      if (d->d_inode) {
++              if (au_ftest_lock(flags, IW))
++                      ii_write_unlock(d->d_inode);
++              else if (au_ftest_lock(flags, IR))
++                      ii_read_unlock(d->d_inode);
++      }
++      up_read(&au_di(d)->di_rwsem);
++}
++
++void di_downgrade_lock(struct dentry *d, int flags)
++{
++      downgrade_write(&au_di(d)->di_rwsem);
++      if (d->d_inode && au_ftest_lock(flags, IR))
++              ii_downgrade_lock(d->d_inode);
++}
++
++void di_write_lock(struct dentry *d, unsigned int lsc)
++{
++      down_write_nested(&au_di(d)->di_rwsem, lsc);
++      if (d->d_inode)
++              do_ii_write_lock(d->d_inode, lsc);
++}
++
++void di_write_unlock(struct dentry *d)
++{
++      if (d->d_inode)
++              ii_write_unlock(d->d_inode);
++      up_write(&au_di(d)->di_rwsem);
++}
++
++void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
++{
++      AuDebugOn(d1 == d2
++                || d1->d_inode == d2->d_inode
++                || d1->d_sb != d2->d_sb);
++
++      if (isdir && au_test_subdir(d1, d2)) {
++              di_write_lock_child(d1);
++              di_write_lock_child2(d2);
++      } else {
++              /* there should be no races */
++              di_write_lock_child(d2);
++              di_write_lock_child2(d1);
++      }
++}
++
++void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
++{
++      AuDebugOn(d1 == d2
++                || d1->d_inode == d2->d_inode
++                || d1->d_sb != d2->d_sb);
++
++      if (isdir && au_test_subdir(d1, d2)) {
++              di_write_lock_parent(d1);
++              di_write_lock_parent2(d2);
++      } else {
++              /* there should be no races */
++              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)
++              up_write(&au_di(d2)->di_rwsem);
++      else
++              di_write_unlock(d2);
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
++{
++      struct dentry *d;
++
++      if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
++              return NULL;
++      AuDebugOn(bindex < 0);
++      d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
++      AuDebugOn(d && (atomic_read(&d->d_count) <= 0));
++      return d;
++}
++
++aufs_bindex_t au_dbtail(struct dentry *dentry)
++{
++      aufs_bindex_t bend, bwh;
++
++      bend = au_dbend(dentry);
++      if (0 <= bend) {
++              bwh = au_dbwh(dentry);
++              if (!bwh)
++                      return bwh;
++              if (0 < bwh && bwh < bend)
++                      return bwh - 1;
++      }
++      return bend;
++}
++
++aufs_bindex_t au_dbtaildir(struct dentry *dentry)
++{
++      aufs_bindex_t bend, bopq;
++
++      bend = au_dbtail(dentry);
++      if (0 <= bend) {
++              bopq = au_dbdiropq(dentry);
++              if (0 <= bopq && bopq < bend)
++                      bend = bopq;
++      }
++      return bend;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
++                 struct dentry *h_dentry)
++{
++      struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
++
++      if (hd->hd_dentry)
++              au_hdput(hd);
++      hd->hd_dentry = h_dentry;
++}
++
++void au_update_digen(struct dentry *dentry)
++{
++      atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
++      /* smp_mb(); */ /* atomic_set */
++}
++
++void au_update_dbrange(struct dentry *dentry, int do_put_zero)
++{
++      struct au_dinfo *dinfo;
++      struct dentry *h_d;
++
++      dinfo = au_di(dentry);
++      if (!dinfo || dinfo->di_bstart < 0)
++              return;
++
++      if (do_put_zero) {
++              aufs_bindex_t bindex, bend;
++
++              bend = dinfo->di_bend;
++              for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
++                      h_d = dinfo->di_hdentry[0 + bindex].hd_dentry;
++                      if (h_d && !h_d->d_inode)
++                              au_set_h_dptr(dentry, bindex, NULL);
++              }
++      }
++
++      dinfo->di_bstart = -1;
++      while (++dinfo->di_bstart <= dinfo->di_bend)
++              if (dinfo->di_hdentry[0 + dinfo->di_bstart].hd_dentry)
++                      break;
++      if (dinfo->di_bstart > dinfo->di_bend) {
++              dinfo->di_bstart = -1;
++              dinfo->di_bend = -1;
++              return;
++      }
++
++      dinfo->di_bend++;
++      while (0 <= --dinfo->di_bend)
++              if (dinfo->di_hdentry[0 + dinfo->di_bend].hd_dentry)
++                      break;
++      AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
++}
++
++void au_update_dbstart(struct dentry *dentry)
++{
++      aufs_bindex_t bindex, bend;
++      struct dentry *h_dentry;
++
++      bend = au_dbend(dentry);
++      for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
++              h_dentry = au_h_dptr(dentry, bindex);
++              if (!h_dentry)
++                      continue;
++              if (h_dentry->d_inode) {
++                      au_set_dbstart(dentry, bindex);
++                      return;
++              }
++              au_set_h_dptr(dentry, bindex, NULL);
++      }
++}
++
++void au_update_dbend(struct dentry *dentry)
++{
++      aufs_bindex_t bindex, bstart;
++      struct dentry *h_dentry;
++
++      bstart = au_dbstart(dentry);
++      for (bindex = au_dbend(dentry); bindex <= bstart; bindex--) {
++              h_dentry = au_h_dptr(dentry, bindex);
++              if (!h_dentry)
++                      continue;
++              if (h_dentry->d_inode) {
++                      au_set_dbend(dentry, bindex);
++                      return;
++              }
++              au_set_h_dptr(dentry, bindex, NULL);
++      }
++}
++
++int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
++{
++      aufs_bindex_t bindex, bend;
++
++      bend = au_dbend(dentry);
++      for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
++              if (au_h_dptr(dentry, bindex) == h_dentry)
++                      return bindex;
++      return -1;
++}
+diff -Naur a/fs/aufs/dir.c b/fs/aufs/dir.c
+--- a/fs/aufs/dir.c    1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dir.c    2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,532 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * directory operations
++ */
++
++#include <linux/file.h>
++#include <linux/fs_stack.h>
++#include "aufs.h"
++
++void au_add_nlink(struct inode *dir, struct inode *h_dir)
++{
++      AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
++
++      dir->i_nlink += h_dir->i_nlink - 2;
++      if (h_dir->i_nlink < 2)
++              dir->i_nlink += 2;
++}
++
++void au_sub_nlink(struct inode *dir, struct inode *h_dir)
++{
++      AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
++
++      dir->i_nlink -= h_dir->i_nlink - 2;
++      if (h_dir->i_nlink < 2)
++              dir->i_nlink -= 2;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int reopen_dir(struct file *file)
++{
++      int err;
++      unsigned int flags;
++      aufs_bindex_t bindex, btail, bstart;
++      struct dentry *dentry, *h_dentry;
++      struct file *h_file;
++
++      /* open all lower dirs */
++      dentry = file->f_dentry;
++      bstart = au_dbstart(dentry);
++      for (bindex = au_fbstart(file); bindex < bstart; bindex++)
++              au_set_h_fptr(file, bindex, NULL);
++      au_set_fbstart(file, bstart);
++
++      btail = au_dbtaildir(dentry);
++      for (bindex = au_fbend(file); btail < bindex; bindex--)
++              au_set_h_fptr(file, bindex, NULL);
++      au_set_fbend(file, btail);
++
++      flags = file->f_flags;
++      for (bindex = bstart; bindex <= btail; bindex++) {
++              h_dentry = au_h_dptr(dentry, bindex);
++              if (!h_dentry)
++                      continue;
++              h_file = au_h_fptr(file, bindex);
++              if (h_file)
++                      continue;
++
++              h_file = au_h_open(dentry, bindex, flags, file);
++              err = PTR_ERR(h_file);
++              if (IS_ERR(h_file))
++                      goto out; /* close all? */
++              au_set_h_fptr(file, bindex, h_file);
++      }
++      au_update_figen(file);
++      /* todo: necessary? */
++      /* file->f_ra = h_file->f_ra; */
++      err = 0;
++
++ out:
++      return err;
++}
++
++static int do_open_dir(struct file *file, int flags)
++{
++      int err;
++      aufs_bindex_t bindex, btail;
++      struct dentry *dentry, *h_dentry;
++      struct file *h_file;
++
++      err = 0;
++      dentry = file->f_dentry;
++      au_set_fvdir_cache(file, NULL);
++      au_fi(file)->fi_maintain_plink = 0;
++      file->f_version = dentry->d_inode->i_version;
++      bindex = au_dbstart(dentry);
++      au_set_fbstart(file, bindex);
++      btail = au_dbtaildir(dentry);
++      au_set_fbend(file, btail);
++      for (; !err && bindex <= btail; bindex++) {
++              h_dentry = au_h_dptr(dentry, bindex);
++              if (!h_dentry)
++                      continue;
++
++              h_file = au_h_open(dentry, bindex, flags, file);
++              if (IS_ERR(h_file)) {
++                      err = PTR_ERR(h_file);
++                      break;
++              }
++              au_set_h_fptr(file, bindex, h_file);
++      }
++      au_update_figen(file);
++      /* todo: necessary? */
++      /* file->f_ra = h_file->f_ra; */
++      if (!err)
++              return 0; /* success */
++
++      /* close all */
++      for (bindex = au_fbstart(file); bindex <= btail; bindex++)
++              au_set_h_fptr(file, bindex, NULL);
++      au_set_fbstart(file, -1);
++      au_set_fbend(file, -1);
++      return err;
++}
++
++static int aufs_open_dir(struct inode *inode __maybe_unused,
++                       struct file *file)
++{
++      return au_do_open(file, do_open_dir);
++}
++
++static int aufs_release_dir(struct inode *inode __maybe_unused,
++                          struct file *file)
++{
++      struct au_vdir *vdir_cache;
++      struct super_block *sb;
++      struct au_sbinfo *sbinfo;
++
++      sb = file->f_dentry->d_sb;
++      si_noflush_read_lock(sb);
++      fi_write_lock(file);
++      vdir_cache = au_fvdir_cache(file);
++      if (vdir_cache)
++              au_vdir_free(vdir_cache);
++      if (au_fi(file)->fi_maintain_plink) {
++              sbinfo = au_sbi(sb);
++              au_fclr_si(sbinfo, MAINTAIN_PLINK);
++              wake_up_all(&sbinfo->si_plink_wq);
++      }
++      fi_write_unlock(file);
++      au_finfo_fin(file);
++      si_read_unlock(sb);
++      return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
++{
++      int err;
++      aufs_bindex_t bend, bindex;
++      struct inode *inode;
++      struct super_block *sb;
++
++      err = 0;
++      sb = dentry->d_sb;
++      inode = dentry->d_inode;
++      IMustLock(inode);
++      bend = au_dbend(dentry);
++      for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
++              struct path h_path;
++              struct inode *h_inode;
++
++              if (au_test_ro(sb, bindex, inode))
++                      continue;
++              h_path.dentry = au_h_dptr(dentry, bindex);
++              if (!h_path.dentry)
++                      continue;
++              h_inode = h_path.dentry->d_inode;
++              if (!h_inode)
++                      continue;
++
++              /* no mnt_want_write() */
++              /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
++              /* todo: inotiry fired? */
++              h_path.mnt = au_sbr_mnt(sb, bindex);
++              mutex_lock(&h_inode->i_mutex);
++              err = filemap_fdatawrite(h_inode->i_mapping);
++              AuDebugOn(!h_inode->i_fop);
++              if (!err && h_inode->i_fop->fsync)
++                      err = h_inode->i_fop->fsync(NULL, h_path.dentry,
++                                                  datasync);
++              if (!err)
++                      err = filemap_fdatawrite(h_inode->i_mapping);
++              if (!err)
++                      vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
++              mutex_unlock(&h_inode->i_mutex);
++      }
++
++      return err;
++}
++
++static int au_do_fsync_dir(struct file *file, int datasync)
++{
++      int err;
++      aufs_bindex_t bend, bindex;
++      struct file *h_file;
++      struct super_block *sb;
++      struct inode *inode;
++      struct mutex *h_mtx;
++
++      err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
++      if (unlikely(err))
++              goto out;
++
++      sb = file->f_dentry->d_sb;
++      inode = file->f_dentry->d_inode;
++      bend = au_fbend(file);
++      for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
++              h_file = au_h_fptr(file, bindex);
++              if (!h_file || au_test_ro(sb, bindex, inode))
++                      continue;
++
++              err = vfs_fsync(h_file, h_file->f_dentry, datasync);
++              if (!err) {
++                      h_mtx = &h_file->f_dentry->d_inode->i_mutex;
++                      mutex_lock(h_mtx);
++                      vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
++                      /*ignore*/
++                      mutex_unlock(h_mtx);
++              }
++      }
++
++ out:
++      return err;
++}
++
++/*
++ * @file may be NULL
++ */
++static int aufs_fsync_dir(struct file *file, struct dentry *dentry,
++                        int datasync)
++{
++      int err;
++      struct super_block *sb;
++
++      IMustLock(dentry->d_inode);
++
++      err = 0;
++      sb = dentry->d_sb;
++      si_noflush_read_lock(sb);
++      if (file)
++              err = au_do_fsync_dir(file, datasync);
++      else {
++              di_write_lock_child(dentry);
++              err = au_do_fsync_dir_no_file(dentry, datasync);
++      }
++      au_cpup_attr_timesizes(dentry->d_inode);
++      di_write_unlock(dentry);
++      if (file)
++              fi_write_unlock(file);
++
++      si_read_unlock(sb);
++      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;
++      inode = dentry->d_inode;
++      IMustLock(inode);
++
++      sb = dentry->d_sb;
++      si_read_lock(sb, AuLock_FLUSH);
++      err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
++      if (unlikely(err))
++              goto out;
++      err = au_vdir_init(file);
++      di_downgrade_lock(dentry, AuLock_IR);
++      if (unlikely(err))
++              goto out_unlock;
++
++      if (!au_test_nfsd(current)) {
++              err = au_vdir_fill_de(file, dirent, filldir);
++              fsstack_copy_attr_atime(inode,
++                                      au_h_iptr(inode, au_ibstart(inode)));
++      } else {
++              /*
++               * nfsd filldir may call lookup_one_len(), vfs_getattr(),
++               * encode_fh() and others.
++               */
++              struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
++
++              di_read_unlock(dentry, AuLock_IR);
++              si_read_unlock(sb);
++              lockdep_off();
++              err = au_vdir_fill_de(file, dirent, filldir);
++              lockdep_on();
++              fsstack_copy_attr_atime(inode, h_inode);
++              fi_write_unlock(file);
++
++              AuTraceErr(err);
++              return err;
++      }
++
++ out_unlock:
++      di_read_unlock(dentry, AuLock_IR);
++      fi_write_unlock(file);
++ out:
++      si_read_unlock(sb);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#define AuTestEmpty_WHONLY    1
++#define AuTestEmpty_CALLED    (1 << 1)
++#define AuTestEmpty_SHWH      (1 << 2)
++#define au_ftest_testempty(flags, name)       ((flags) & AuTestEmpty_##name)
++#define au_fset_testempty(flags, name)        { (flags) |= AuTestEmpty_##name; }
++#define au_fclr_testempty(flags, name)        { (flags) &= ~AuTestEmpty_##name; }
++
++#ifndef CONFIG_AUFS_SHWH
++#undef AuTestEmpty_SHWH
++#define AuTestEmpty_SHWH      0
++#endif
++
++struct test_empty_arg {
++      struct au_nhash whlist;
++      unsigned int flags;
++      int err;
++      aufs_bindex_t bindex;
++};
++
++static int test_empty_cb(void *__arg, const char *__name, int namelen,
++                       loff_t offset __maybe_unused, u64 ino,
++                       unsigned int d_type)
++{
++      struct test_empty_arg *arg = __arg;
++      char *name = (void *)__name;
++
++      arg->err = 0;
++      au_fset_testempty(arg->flags, CALLED);
++      /* smp_mb(); */
++      if (name[0] == '.'
++          && (namelen == 1 || (name[1] == '.' && namelen == 2)))
++              goto out; /* success */
++
++      if (namelen <= AUFS_WH_PFX_LEN
++          || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
++              if (au_ftest_testempty(arg->flags, WHONLY)
++                  && !au_nhash_test_known_wh(&arg->whlist, name, namelen))
++                      arg->err = -ENOTEMPTY;
++              goto out;
++      }
++
++      name += AUFS_WH_PFX_LEN;
++      namelen -= AUFS_WH_PFX_LEN;
++      if (!au_nhash_test_known_wh(&arg->whlist, name, namelen))
++              arg->err = au_nhash_append_wh
++                      (&arg->whlist, name, namelen, ino, d_type, arg->bindex,
++                       au_ftest_testempty(arg->flags, SHWH));
++
++ out:
++      /* smp_mb(); */
++      AuTraceErr(arg->err);
++      return arg->err;
++}
++
++static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
++{
++      int err;
++      struct file *h_file;
++
++      h_file = au_h_open(dentry, arg->bindex,
++                         O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
++                         /*file*/NULL);
++      err = PTR_ERR(h_file);
++      if (IS_ERR(h_file))
++              goto out;
++
++      err = 0;
++      if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
++          && !h_file->f_dentry->d_inode->i_nlink)
++              goto out_put;
++
++      do {
++              arg->err = 0;
++              au_fclr_testempty(arg->flags, CALLED);
++              /* smp_mb(); */
++              err = vfsub_readdir(h_file, test_empty_cb, arg);
++              if (err >= 0)
++                      err = arg->err;
++      } while (!err && au_ftest_testempty(arg->flags, CALLED));
++
++ out_put:
++      fput(h_file);
++      au_sbr_put(dentry->d_sb, arg->bindex);
++ out:
++      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, wkq_err;
++      struct dentry *h_dentry;
++      struct inode *h_inode;
++
++      h_dentry = au_h_dptr(dentry, arg->bindex);
++      h_inode = h_dentry->d_inode;
++      mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++      err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
++      mutex_unlock(&h_inode->i_mutex);
++      if (!err)
++              err = do_test_empty(dentry, arg);
++      else {
++              struct do_test_empty_args args = {
++                      .errp   = &err,
++                      .dentry = dentry,
++                      .arg    = arg
++              };
++              unsigned int flags = arg->flags;
++
++              wkq_err = au_wkq_wait(call_do_test_empty, &args);
++              if (unlikely(wkq_err))
++                      err = wkq_err;
++              arg->flags = flags;
++      }
++
++      return err;
++}
++
++int au_test_empty_lower(struct dentry *dentry)
++{
++      int err;
++      aufs_bindex_t bindex, bstart, btail;
++      struct test_empty_arg arg;
++
++      err = au_nhash_alloc(&arg.whlist, au_sbi(dentry->d_sb)->si_rdhash,
++                           GFP_NOFS);
++      if (unlikely(err))
++              goto out;
++
++      bstart = au_dbstart(dentry);
++      arg.flags = 0;
++      if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
++              au_fset_testempty(arg.flags, SHWH);
++      arg.bindex = bstart;
++      err = do_test_empty(dentry, &arg);
++      if (unlikely(err))
++              goto out_whlist;
++
++      au_fset_testempty(arg.flags, WHONLY);
++      btail = au_dbtaildir(dentry);
++      for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
++              struct dentry *h_dentry;
++
++              h_dentry = au_h_dptr(dentry, bindex);
++              if (h_dentry && h_dentry->d_inode) {
++                      arg.bindex = bindex;
++                      err = do_test_empty(dentry, &arg);
++              }
++      }
++
++ out_whlist:
++      au_nhash_wh_free(&arg.whlist);
++ out:
++      return err;
++}
++
++int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
++{
++      int err;
++      struct test_empty_arg arg;
++      aufs_bindex_t bindex, btail;
++
++      err = 0;
++      arg.whlist = *whlist;
++      arg.flags = AuTestEmpty_WHONLY;
++      if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
++              au_fset_testempty(arg.flags, SHWH);
++      btail = au_dbtaildir(dentry);
++      for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
++              struct dentry *h_dentry;
++
++              h_dentry = au_h_dptr(dentry, bindex);
++              if (h_dentry && h_dentry->d_inode) {
++                      arg.bindex = bindex;
++                      err = sio_test_empty(dentry, &arg);
++              }
++      }
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++const struct file_operations aufs_dir_fop = {
++      .read           = generic_read_dir,
++      .readdir        = aufs_readdir,
++      .unlocked_ioctl = aufs_ioctl_dir,
++      .open           = aufs_open_dir,
++      .release        = aufs_release_dir,
++      .flush          = aufs_flush,
++      .fsync          = aufs_fsync_dir
++};
+diff -Naur a/fs/aufs/dir.h b/fs/aufs/dir.h
+--- a/fs/aufs/dir.h    1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/dir.h    2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,114 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * directory operations
++ */
++
++#ifndef __AUFS_DIR_H__
++#define __AUFS_DIR_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/aufs_type.h>
++
++/* ---------------------------------------------------------------------- */
++
++/* need to be faster and smaller */
++
++struct au_nhash {
++      unsigned int            nh_num;
++      struct hlist_head       *nh_head;
++};
++
++struct au_vdir_destr {
++      unsigned char   len;
++      unsigned char   name[0];
++} __packed;
++
++struct au_vdir_dehstr {
++      struct hlist_node       hash;
++      struct au_vdir_destr    *str;
++};
++
++struct au_vdir_de {
++      ino_t                   de_ino;
++      unsigned char           de_type;
++      /* caution: packed */
++      struct au_vdir_destr    de_str;
++} __packed;
++
++struct au_vdir_wh {
++      struct hlist_node       wh_hash;
++#ifdef CONFIG_AUFS_SHWH
++      ino_t                   wh_ino;
++      aufs_bindex_t           wh_bindex;
++      unsigned char           wh_type;
++#else
++      aufs_bindex_t           wh_bindex;
++#endif
++      /* caution: packed */
++      struct au_vdir_destr    wh_str;
++} __packed;
++
++union au_vdir_deblk_p {
++      unsigned char           *deblk;
++      struct au_vdir_de       *de;
++};
++
++struct au_vdir {
++      unsigned char   **vd_deblk;
++      unsigned long   vd_nblk;
++      struct {
++              unsigned long           ul;
++              union au_vdir_deblk_p   p;
++      } vd_last;
++
++      unsigned long   vd_version;
++      unsigned int    vd_deblk_sz;
++      unsigned long   vd_jiffy;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* dir.c */
++extern const struct file_operations aufs_dir_fop;
++void au_add_nlink(struct inode *dir, struct inode *h_dir);
++void au_sub_nlink(struct inode *dir, struct inode *h_dir);
++int au_test_empty_lower(struct dentry *dentry);
++int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
++
++/* vdir.c */
++int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
++void au_nhash_wh_free(struct au_nhash *whlist);
++int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
++                          int limit);
++int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
++int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
++                     unsigned int d_type, aufs_bindex_t bindex,
++                     unsigned char shwh);
++void au_vdir_free(struct au_vdir *vdir);
++int au_vdir_init(struct file *file);
++int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
++
++/* ioctl.c */
++long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_DIR_H__ */
+diff -Naur a/fs/aufs/export.c b/fs/aufs/export.c
+--- a/fs/aufs/export.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/export.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,736 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * export via nfs
++ */
++
++#include <linux/exportfs.h>
++#include <linux/file.h>
++#include <linux/mnt_namespace.h>
++#include <linux/namei.h>
++#include <linux/random.h>
++#include "aufs.h"
++
++union conv {
++#ifdef CONFIG_AUFS_INO_T_64
++      __u32 a[2];
++#else
++      __u32 a[1];
++#endif
++      ino_t ino;
++};
++
++static ino_t decode_ino(__u32 *a)
++{
++      union conv u;
++
++      BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
++      u.a[0] = a[0];
++#ifdef CONFIG_AUFS_INO_T_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];
++#ifdef CONFIG_AUFS_INO_T_64
++      a[1] = u.a[1];
++#endif
++}
++
++/* NFS file handle */
++enum {
++      Fh_br_id,
++      Fh_sigen,
++#ifdef CONFIG_AUFS_INO_T_64
++      /* support 64bit inode number */
++      Fh_ino1,
++      Fh_ino2,
++      Fh_dir_ino1,
++      Fh_dir_ino2,
++#else
++      Fh_ino1,
++      Fh_dir_ino1,
++#endif
++      Fh_igen,
++      Fh_h_type,
++      Fh_tail,
++
++      Fh_ino = Fh_ino1,
++      Fh_dir_ino = Fh_dir_ino1
++};
++
++static int au_test_anon(struct dentry *dentry)
++{
++      return !!(dentry->d_flags & DCACHE_DISCONNECTED);
++}
++
++/* ---------------------------------------------------------------------- */
++/* inode generation external table */
++
++int au_xigen_inc(struct inode *inode)
++{
++      int err;
++      loff_t pos;
++      ssize_t sz;
++      __u32 igen;
++      struct super_block *sb;
++      struct au_sbinfo *sbinfo;
++
++      err = 0;
++      sb = inode->i_sb;
++      if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
++              goto out;
++
++      pos = inode->i_ino;
++      pos *= sizeof(igen);
++      igen = inode->i_generation + 1;
++      sbinfo = au_sbi(sb);
++      sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
++                       sizeof(igen), &pos);
++      if (sz == sizeof(igen))
++              goto out; /* success */
++
++      err = sz;
++      if (unlikely(sz >= 0)) {
++              err = -EIO;
++              AuIOErr("xigen error (%zd)\n", sz);
++      }
++
++ out:
++      return err;
++}
++
++int au_xigen_new(struct inode *inode)
++{
++      int err;
++      loff_t pos;
++      ssize_t sz;
++      struct super_block *sb;
++      struct au_sbinfo *sbinfo;
++      struct file *file;
++
++      err = 0;
++      /* todo: dirty, at mount time */
++      if (inode->i_ino == AUFS_ROOT_INO)
++              goto out;
++      sb = inode->i_sb;
++      if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
++              goto out;
++
++      err = -EFBIG;
++      pos = inode->i_ino;
++      if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
++              AuIOErr1("too large i%lld\n", pos);
++              goto out;
++      }
++      pos *= sizeof(inode->i_generation);
++
++      err = 0;
++      sbinfo = au_sbi(sb);
++      file = sbinfo->si_xigen;
++      BUG_ON(!file);
++
++      if (i_size_read(file->f_dentry->d_inode)
++          < pos + sizeof(inode->i_generation)) {
++              inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
++              sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
++                               sizeof(inode->i_generation), &pos);
++      } else
++              sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
++                              sizeof(inode->i_generation), &pos);
++      if (sz == sizeof(inode->i_generation))
++              goto out; /* success */
++
++      err = sz;
++      if (unlikely(sz >= 0)) {
++              err = -EIO;
++              AuIOErr("xigen error (%zd)\n", sz);
++      }
++
++ out:
++      return err;
++}
++
++int au_xigen_set(struct super_block *sb, struct file *base)
++{
++      int err;
++      struct au_sbinfo *sbinfo;
++      struct file *file;
++
++      sbinfo = au_sbi(sb);
++      file = au_xino_create2(base, sbinfo->si_xigen);
++      err = PTR_ERR(file);
++      if (IS_ERR(file))
++              goto out;
++      err = 0;
++      if (sbinfo->si_xigen)
++              fput(sbinfo->si_xigen);
++      sbinfo->si_xigen = file;
++
++ out:
++      return err;
++}
++
++void au_xigen_clr(struct super_block *sb)
++{
++      struct au_sbinfo *sbinfo;
++
++      sbinfo = au_sbi(sb);
++      if (sbinfo->si_xigen) {
++              fput(sbinfo->si_xigen);
++              sbinfo->si_xigen = NULL;
++      }
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
++                                  ino_t dir_ino)
++{
++      struct dentry *dentry, *d;
++      struct inode *inode;
++      unsigned int sigen;
++
++      dentry = NULL;
++      inode = ilookup(sb, ino);
++      if (!inode)
++              goto out;
++
++      dentry = ERR_PTR(-ESTALE);
++      sigen = au_sigen(sb);
++      if (unlikely(is_bad_inode(inode)
++                   || IS_DEADDIR(inode)
++                   || sigen != au_iigen(inode)))
++              goto out_iput;
++
++      dentry = NULL;
++      if (!dir_ino || S_ISDIR(inode->i_mode))
++              dentry = d_find_alias(inode);
++      else {
++              spin_lock(&dcache_lock);
++              list_for_each_entry(d, &inode->i_dentry, d_alias)
++                      if (!au_test_anon(d)
++                          && d->d_parent->d_inode->i_ino == dir_ino) {
++                              dentry = dget_locked(d);
++                              break;
++                      }
++              spin_unlock(&dcache_lock);
++      }
++      if (unlikely(dentry && sigen != au_digen(dentry))) {
++              dput(dentry);
++              dentry = ERR_PTR(-ESTALE);
++      }
++
++ out_iput:
++      iput(inode);
++ out:
++      return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* todo: dirty? */
++/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
++static struct vfsmount *au_mnt_get(struct super_block *sb)
++{
++      struct mnt_namespace *ns;
++      struct vfsmount *pos, *mnt;
++
++      spin_lock(&vfsmount_lock);
++      /* no get/put ?? */
++      AuDebugOn(!current->nsproxy);
++      ns = current->nsproxy->mnt_ns;
++      AuDebugOn(!ns);
++      mnt = NULL;
++      /* the order (reverse) will not be a problem */
++      list_for_each_entry(pos, &ns->list, mnt_list)
++              if (pos->mnt_sb == sb) {
++                      mnt = mntget(pos);
++                      break;
++              }
++      spin_unlock(&vfsmount_lock);
++      AuDebugOn(!mnt);
++
++      return mnt;
++}
++
++struct au_nfsd_si_lock {
++      const unsigned int sigen;
++      const aufs_bindex_t br_id;
++      unsigned char force_lock;
++};
++
++static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb,
++                                     struct au_nfsd_si_lock *nsi_lock)
++{
++      aufs_bindex_t bindex;
++
++      si_read_lock(sb, AuLock_FLUSH);
++
++      /* branch id may be wrapped around */
++      bindex = au_br_index(sb, nsi_lock->br_id);
++      if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
++              goto out; /* success */
++
++      if (!nsi_lock->force_lock)
++              si_read_unlock(sb);
++      bindex = -1;
++
++ out:
++      return bindex;
++}
++
++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,
++               u64 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 *au_lkup_by_ino(struct path *path, ino_t ino,
++                                   struct au_nfsd_si_lock *nsi_lock)
++{
++      struct dentry *dentry, *parent;
++      struct file *file;
++      struct inode *dir;
++      struct find_name_by_ino arg;
++      int err;
++
++      parent = path->dentry;
++      if (nsi_lock)
++              si_read_unlock(parent->d_sb);
++      path_get(path);
++      file = dentry_open(parent, path->mnt, au_dir_roflags, current_cred());
++      dentry = (void *)file;
++      if (IS_ERR(file))
++              goto out;
++
++      dentry = ERR_PTR(-ENOMEM);
++      arg.name = __getname();
++      if (unlikely(!arg.name))
++              goto out_file;
++      arg.ino = ino;
++      arg.found = 0;
++      do {
++              arg.called = 0;
++              /* smp_mb(); */
++              err = vfsub_readdir(file, find_name_by_ino, &arg);
++      } while (!err && !arg.found && arg.called);
++      dentry = ERR_PTR(err);
++      if (unlikely(err))
++              goto out_name;
++      dentry = ERR_PTR(-ENOENT);
++      if (!arg.found)
++              goto out_name;
++
++      /* do not call au_lkup_one() */
++      dir = parent->d_inode;
++      mutex_lock(&dir->i_mutex);
++      dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
++      mutex_unlock(&dir->i_mutex);
++      AuTraceErrPtr(dentry);
++      if (IS_ERR(dentry))
++              goto out_name;
++      AuDebugOn(au_test_anon(dentry));
++      if (unlikely(!dentry->d_inode)) {
++              dput(dentry);
++              dentry = ERR_PTR(-ENOENT);
++      }
++
++ out_name:
++      __putname(arg.name);
++ out_file:
++      fput(file);
++ out:
++      if (unlikely(nsi_lock
++                   && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
++              if (!IS_ERR(dentry)) {
++                      dput(dentry);
++                      dentry = ERR_PTR(-ESTALE);
++              }
++      AuTraceErrPtr(dentry);
++      return dentry;
++}
++
++static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
++                                      ino_t dir_ino,
++                                      struct au_nfsd_si_lock *nsi_lock)
++{
++      struct dentry *dentry;
++      struct path path;
++
++      if (dir_ino != AUFS_ROOT_INO) {
++              path.dentry = decode_by_ino(sb, dir_ino, 0);
++              dentry = path.dentry;
++              if (!path.dentry || IS_ERR(path.dentry))
++                      goto out;
++              AuDebugOn(au_test_anon(path.dentry));
++      } else
++              path.dentry = dget(sb->s_root);
++
++      path.mnt = au_mnt_get(sb);
++      dentry = au_lkup_by_ino(&path, ino, nsi_lock);
++      path_put(&path);
++
++ out:
++      AuTraceErrPtr(dentry);
++      return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int h_acceptable(void *expv, struct dentry *dentry)
++{
++      return 1;
++}
++
++static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
++                         char *buf, int len, struct super_block *sb)
++{
++      char *p;
++      int n;
++      struct path path;
++
++      p = d_path(h_rootpath, buf, len);
++      if (IS_ERR(p))
++              goto out;
++      n = strlen(p);
++
++      path.mnt = h_rootpath->mnt;
++      path.dentry = h_parent;
++      p = d_path(&path, buf, len);
++      if (IS_ERR(p))
++              goto out;
++      if (n != 1)
++              p += n;
++
++      path.mnt = au_mnt_get(sb);
++      path.dentry = sb->s_root;
++      p = d_path(&path, buf, len - strlen(p));
++      mntput(path.mnt);
++      if (IS_ERR(p))
++              goto out;
++      if (n != 1)
++              p[strlen(p)] = '/';
++
++ out:
++      AuTraceErrPtr(p);
++      return p;
++}
++
++static
++struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex,
++                            ino_t ino, __u32 *fh, int fh_len,
++                            struct au_nfsd_si_lock *nsi_lock)
++{
++      struct dentry *dentry, *h_parent, *root;
++      struct super_block *h_sb;
++      char *pathname, *p;
++      struct vfsmount *h_mnt;
++      struct au_branch *br;
++      int err;
++      struct path path;
++
++      br = au_sbr(sb, bindex);
++      /* au_br_get(br); */
++      h_mnt = br->br_mnt;
++      h_sb = h_mnt->mnt_sb;
++      /* todo: call lower fh_to_dentry()? fh_to_parent()? */
++      h_parent = exportfs_decode_fh(h_mnt, (void *)(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))) {
++              AuWarn1("%s decode_fh failed, %ld\n",
++                      au_sbtype(h_sb), PTR_ERR(h_parent));
++              goto out;
++      }
++      dentry = NULL;
++      if (unlikely(au_test_anon(h_parent))) {
++              AuWarn1("%s decode_fh returned a disconnected dentry\n",
++                      au_sbtype(h_sb));
++              goto out_h_parent;
++      }
++
++      dentry = ERR_PTR(-ENOMEM);
++      pathname = (void *)__get_free_page(GFP_NOFS);
++      if (unlikely(!pathname))
++              goto out_h_parent;
++
++      root = sb->s_root;
++      path.mnt = h_mnt;
++      di_read_lock_parent(root, !AuLock_IR);
++      path.dentry = au_h_dptr(root, bindex);
++      di_read_unlock(root, !AuLock_IR);
++      p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
++      dentry = (void *)p;
++      if (IS_ERR(p))
++              goto out_pathname;
++
++      si_read_unlock(sb);
++      err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
++      dentry = ERR_PTR(err);
++      if (unlikely(err))
++              goto out_relock;
++
++      dentry = ERR_PTR(-ENOENT);
++      AuDebugOn(au_test_anon(path.dentry));
++      if (unlikely(!path.dentry->d_inode))
++              goto out_path;
++
++      if (ino != path.dentry->d_inode->i_ino)
++              dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
++      else
++              dentry = dget(path.dentry);
++
++ out_path:
++      path_put(&path);
++ out_relock:
++      if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
++              if (!IS_ERR(dentry)) {
++                      dput(dentry);
++                      dentry = ERR_PTR(-ESTALE);
++              }
++ out_pathname:
++      free_page((unsigned long)pathname);
++ out_h_parent:
++      dput(h_parent);
++ out:
++      /* au_br_put(br); */
++      AuTraceErrPtr(dentry);
++      return dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct dentry *
++aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
++                int fh_type)
++{
++      struct dentry *dentry;
++      __u32 *fh = fid->raw;
++      ino_t ino, dir_ino;
++      aufs_bindex_t bindex;
++      struct au_nfsd_si_lock nsi_lock = {
++              .sigen          = fh[Fh_sigen],
++              .br_id          = fh[Fh_br_id],
++              .force_lock     = 0
++      };
++
++      AuDebugOn(fh_len < Fh_tail);
++
++      dentry = ERR_PTR(-ESTALE);
++      /* branch id may be wrapped around */
++      bindex = si_nfsd_read_lock(sb, &nsi_lock);
++      if (unlikely(bindex < 0))
++              goto out;
++      nsi_lock.force_lock = 1;
++
++      /* is this inode still cached? */
++      ino = decode_ino(fh + Fh_ino);
++      AuDebugOn(ino == AUFS_ROOT_INO);
++      dir_ino = decode_ino(fh + Fh_dir_ino);
++      dentry = decode_by_ino(sb, ino, dir_ino);
++      if (IS_ERR(dentry))
++              goto out_unlock;
++      if (dentry)
++              goto accept;
++
++      /* is the parent dir cached? */
++      dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
++      if (IS_ERR(dentry))
++              goto out_unlock;
++      if (dentry)
++              goto accept;
++
++      /* lookup path */
++      dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock);
++      if (IS_ERR(dentry))
++              goto out_unlock;
++      if (unlikely(!dentry))
++              /* todo?: make it ESTALE */
++              goto out_unlock;
++
++ accept:
++      if (dentry->d_inode->i_generation == fh[Fh_igen])
++              goto out_unlock; /* success */
++
++      dput(dentry);
++      dentry = ERR_PTR(-ESTALE);
++ out_unlock:
++      si_read_unlock(sb);
++ out:
++      AuTraceErrPtr(dentry);
++      return dentry;
++}
++
++#if 0 /* reserved for future use */
++/* support subtreecheck option */
++static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
++                                      int fh_len, int fh_type)
++{
++      struct dentry *parent;
++      __u32 *fh = fid->raw;
++      ino_t dir_ino;
++
++      dir_ino = decode_ino(fh + Fh_dir_ino);
++      parent = decode_by_ino(sb, dir_ino, 0);
++      if (IS_ERR(parent))
++              goto out;
++      if (!parent)
++              parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
++                                      dir_ino, fh, fh_len);
++
++ out:
++      AuTraceErrPtr(parent);
++      return parent;
++}
++#endif
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
++                        int connectable)
++{
++      int err;
++      aufs_bindex_t bindex, bend;
++      struct super_block *sb, *h_sb;
++      struct inode *inode;
++      struct dentry *parent, *h_parent;
++      struct au_branch *br;
++
++      AuDebugOn(au_test_anon(dentry));
++
++      parent = NULL;
++      err = -ENOSPC;
++      if (unlikely(*max_len <= Fh_tail)) {
++              AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
++              goto out;
++      }
++
++      err = FILEID_ROOT;
++      if (IS_ROOT(dentry)) {
++              AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
++              goto out;
++      }
++
++      err = -EIO;
++      h_parent = NULL;
++      sb = dentry->d_sb;
++      aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR);
++      parent = dget_parent(dentry);
++      di_read_lock_parent(parent, !AuLock_IR);
++      inode = dentry->d_inode;
++      AuDebugOn(!inode);
++#ifdef CONFIG_AUFS_DEBUG
++      if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
++              AuWarn1("NFS-exporting requires xino\n");
++#endif
++
++      bend = au_dbtaildir(parent);
++      for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
++              h_parent = au_h_dptr(parent, bindex);
++              if (h_parent) {
++                      dget(h_parent);
++                      break;
++              }
++      }
++      if (unlikely(!h_parent))
++              goto out_unlock;
++
++      err = -EPERM;
++      br = au_sbr(sb, bindex);
++      h_sb = br->br_mnt->mnt_sb;
++      if (unlikely(!h_sb->s_export_op)) {
++              AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
++              goto out_dput;
++      }
++
++      fh[Fh_br_id] = br->br_id;
++      fh[Fh_sigen] = au_sigen(sb);
++      encode_ino(fh + Fh_ino, inode->i_ino);
++      encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
++      fh[Fh_igen] = inode->i_generation;
++
++      *max_len -= Fh_tail;
++      fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
++                                         max_len,
++                                         /*connectable or subtreecheck*/0);
++      err = fh[Fh_h_type];
++      *max_len += Fh_tail;
++      /* todo: macros? */
++      if (err != 255)
++              err = 99;
++      else
++              AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
++
++ out_dput:
++      dput(h_parent);
++ out_unlock:
++      di_read_unlock(parent, !AuLock_IR);
++      dput(parent);
++      aufs_read_unlock(dentry, AuLock_IR);
++ out:
++      if (unlikely(err < 0))
++              err = 255;
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct export_operations aufs_export_op = {
++      .fh_to_dentry   = aufs_fh_to_dentry,
++      /* .fh_to_parent        = aufs_fh_to_parent, */
++      .encode_fh      = aufs_encode_fh
++};
++
++void au_export_init(struct super_block *sb)
++{
++      struct au_sbinfo *sbinfo;
++      __u32 u;
++
++      sb->s_export_op = &aufs_export_op;
++      sbinfo = au_sbi(sb);
++      sbinfo->si_xigen = NULL;
++      get_random_bytes(&u, sizeof(u));
++      BUILD_BUG_ON(sizeof(u) != sizeof(int));
++      atomic_set(&sbinfo->si_xigen_next, u);
++}
+diff -Naur a/fs/aufs/file.c b/fs/aufs/file.c
+--- a/fs/aufs/file.c   1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/file.c   2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,568 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * handling file/dir, and address_space operation
++ */
++
++#include <linux/file.h>
++#include <linux/fsnotify.h>
++#include <linux/namei.h>
++#include <linux/pagemap.h>
++#include "aufs.h"
++
++/*
++ * a dirty trick for handling deny_write_access().
++ * because FMODE_EXEC flag is not passed to f_op->open(),
++ * set it to file->private_data temporary.
++ */
++void au_store_oflag(struct nameidata *nd, struct inode *inode)
++{
++      if (nd
++          /* && !(nd->flags & LOOKUP_CONTINUE) */
++          && (nd->flags & LOOKUP_OPEN)
++          && (nd->intent.open.flags & vfsub_fmode_to_uint(FMODE_EXEC))
++          && inode
++          && S_ISREG(inode->i_mode)) {
++              /* suppress a warning in lp64 */
++              unsigned long flags = nd->intent.open.flags;
++              nd->intent.open.file->private_data = (void *)flags;
++              /* smp_mb(); */
++      }
++}
++
++/* 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 *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
++                     struct file *file)
++{
++      struct file *h_file;
++      struct dentry *h_dentry;
++      struct inode *h_inode;
++      struct super_block *sb;
++      struct au_branch *br;
++      int err;
++
++      h_dentry = au_h_dptr(dentry, bindex);
++      h_inode = h_dentry->d_inode;
++      /* a race condition can happen between open and unlink/rmdir */
++      h_file = ERR_PTR(-ENOENT);
++      if (unlikely((!d_unhashed(dentry) && d_unhashed(h_dentry))
++                   || !h_inode))
++              goto out;
++
++      sb = dentry->d_sb;
++      br = au_sbr(sb, bindex);
++      h_file = ERR_PTR(-EACCES);
++      if (file && (file->f_mode & FMODE_EXEC)
++          && (br->br_mnt->mnt_flags & MNT_NOEXEC))
++              goto out;
++
++      /* drop flags for writing */
++      if (au_test_ro(sb, bindex, dentry->d_inode))
++              flags = au_file_roflags(flags);
++      flags &= ~O_CREAT;
++      atomic_inc(&br->br_count);
++      h_file = dentry_open(dget(h_dentry), mntget(br->br_mnt), flags,
++                           current_cred());
++      if (IS_ERR(h_file))
++              goto out_br;
++
++      if (file && (file->f_mode & FMODE_EXEC)) {
++              h_file->f_mode |= FMODE_EXEC;
++              err = deny_write_access(h_file);
++              if (unlikely(err)) {
++                      fput(h_file);
++                      h_file = ERR_PTR(err);
++                      goto out_br;
++              }
++      }
++      fsnotify_open(h_dentry);
++      goto out; /* success */
++
++ out_br:
++      atomic_dec(&br->br_count);
++ out:
++      return h_file;
++}
++
++int au_do_open(struct file *file, int (*open)(struct file *file, int flags))
++{
++      int err;
++      struct dentry *dentry;
++      struct super_block *sb;
++
++      dentry = file->f_dentry;
++      sb = dentry->d_sb;
++      si_read_lock(sb, AuLock_FLUSH);
++      err = au_finfo_init(file);
++      if (unlikely(err))
++              goto out;
++
++      di_read_lock_child(dentry, AuLock_IR);
++      err = open(file, file->f_flags);
++      di_read_unlock(dentry, AuLock_IR);
++
++      fi_write_unlock(file);
++      if (unlikely(err))
++              au_finfo_fin(file);
++ out:
++      si_read_unlock(sb);
++      return err;
++}
++
++int au_reopen_nondir(struct file *file)
++{
++      int err;
++      aufs_bindex_t bstart, bindex, bend;
++      struct dentry *dentry;
++      struct file *h_file, *h_file_tmp;
++
++      dentry = file->f_dentry;
++      bstart = au_dbstart(dentry);
++      h_file_tmp = NULL;
++      if (au_fbstart(file) == bstart) {
++              h_file = au_h_fptr(file, bstart);
++              if (file->f_mode == h_file->f_mode)
++                      return 0; /* success */
++              h_file_tmp = h_file;
++              get_file(h_file_tmp);
++              au_set_h_fptr(file, bstart, NULL);
++      }
++      AuDebugOn(au_fbstart(file) < bstart
++                || au_fi(file)->fi_hfile[0 + bstart].hf_file);
++
++      h_file = au_h_open(dentry, bstart, file->f_flags & ~O_TRUNC, file);
++      err = PTR_ERR(h_file);
++      if (IS_ERR(h_file))
++              goto out; /* todo: close all? */
++
++      err = 0;
++      au_set_fbstart(file, bstart);
++      au_set_h_fptr(file, bstart, h_file);
++      au_update_figen(file);
++      /* todo: necessary? */
++      /* file->f_ra = h_file->f_ra; */
++
++      /* close lower files */
++      bend = au_fbend(file);
++      for (bindex = bstart + 1; bindex <= bend; bindex++)
++              au_set_h_fptr(file, bindex, NULL);
++      au_set_fbend(file, bstart);
++
++ out:
++      if (h_file_tmp)
++              fput(h_file_tmp);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
++                      struct dentry *hi_wh)
++{
++      int err;
++      aufs_bindex_t bstart;
++      struct au_dinfo *dinfo;
++      struct dentry *h_dentry;
++
++      dinfo = au_di(file->f_dentry);
++      bstart = dinfo->di_bstart;
++      dinfo->di_bstart = btgt;
++      h_dentry = dinfo->di_hdentry[0 + btgt].hd_dentry;
++      dinfo->di_hdentry[0 + btgt].hd_dentry = hi_wh;
++      err = au_reopen_nondir(file);
++      dinfo->di_hdentry[0 + btgt].hd_dentry = h_dentry;
++      dinfo->di_bstart = bstart;
++
++      return err;
++}
++
++static int au_ready_to_write_wh(struct file *file, loff_t len,
++                              aufs_bindex_t bcpup)
++{
++      int err;
++      struct inode *inode;
++      struct dentry *dentry, *hi_wh;
++      struct super_block *sb;
++
++      dentry = file->f_dentry;
++      inode = dentry->d_inode;
++      hi_wh = au_hi_wh(inode, bcpup);
++      if (!hi_wh)
++              err = au_sio_cpup_wh(dentry, bcpup, len, file);
++      else
++              /* already copied-up after unlink */
++              err = au_reopen_wh(file, bcpup, hi_wh);
++
++      sb = dentry->d_sb;
++      if (!err && inode->i_nlink > 1 && au_opt_test(au_mntflags(sb), PLINK))
++              au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
++
++      return err;
++}
++
++/*
++ * prepare the @file for writing.
++ */
++int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
++{
++      int err;
++      aufs_bindex_t bstart, bcpup;
++      struct dentry *dentry, *parent, *h_dentry;
++      struct inode *h_inode, *inode;
++      struct super_block *sb;
++
++      dentry = file->f_dentry;
++      sb = dentry->d_sb;
++      bstart = au_fbstart(file);
++      inode = dentry->d_inode;
++      err = au_test_ro(sb, bstart, inode);
++      if (!err && (au_h_fptr(file, bstart)->f_mode & FMODE_WRITE)) {
++              err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
++              goto out;
++      }
++
++      /* need to cpup */
++      parent = dget_parent(dentry);
++      di_write_lock_parent(parent);
++      err = AuWbrCopyup(au_sbi(sb), dentry);
++      bcpup = err;
++      if (unlikely(err < 0))
++              goto out_dgrade;
++      err = 0;
++
++      if (!au_h_dptr(parent, bcpup)) {
++              err = au_cpup_dirs(dentry, bcpup);
++              if (unlikely(err))
++                      goto out_dgrade;
++      }
++
++      err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
++                   AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++      if (unlikely(err))
++              goto out_dgrade;
++
++      h_dentry = au_h_fptr(file, bstart)->f_dentry;
++      h_inode = h_dentry->d_inode;
++      mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++      if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */
++          /* || !h_inode->i_nlink */) {
++              err = au_ready_to_write_wh(file, len, bcpup);
++              di_downgrade_lock(parent, AuLock_IR);
++      } else {
++              di_downgrade_lock(parent, AuLock_IR);
++              if (!au_h_dptr(dentry, bcpup))
++                      err = au_sio_cpup_simple(dentry, bcpup, len,
++                                               AuCpup_DTIME);
++              if (!err)
++                      err = au_reopen_nondir(file);
++      }
++      mutex_unlock(&h_inode->i_mutex);
++
++      if (!err) {
++              au_pin_set_parent_lflag(pin, /*lflag*/0);
++              goto out_dput; /* success */
++      }
++      au_unpin(pin);
++      goto out_unlock;
++
++ out_dgrade:
++      di_downgrade_lock(parent, AuLock_IR);
++ out_unlock:
++      di_read_unlock(parent, AuLock_IR);
++ out_dput:
++      dput(parent);
++ out:
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
++{
++      int err;
++      aufs_bindex_t bstart;
++      struct au_pin pin;
++      struct au_finfo *finfo;
++      struct dentry *dentry, *parent, *hi_wh;
++      struct inode *inode;
++      struct super_block *sb;
++
++      err = 0;
++      finfo = au_fi(file);
++      dentry = file->f_dentry;
++      sb = dentry->d_sb;
++      inode = dentry->d_inode;
++      bstart = au_ibstart(inode);
++      if (bstart == finfo->fi_bstart)
++              goto out;
++
++      parent = dget_parent(dentry);
++      if (au_test_ro(sb, bstart, inode)) {
++              di_read_lock_parent(parent, !AuLock_IR);
++              err = AuWbrCopyup(au_sbi(sb), dentry);
++              bstart = err;
++              di_read_unlock(parent, !AuLock_IR);
++              if (unlikely(err < 0))
++                      goto out_parent;
++              err = 0;
++      }
++
++      di_read_lock_parent(parent, AuLock_IR);
++      hi_wh = au_hi_wh(inode, bstart);
++      if (au_opt_test(au_mntflags(sb), PLINK)
++          && au_plink_test(inode)
++          && !d_unhashed(dentry)) {
++              err = au_test_and_cpup_dirs(dentry, bstart);
++              if (unlikely(err))
++                      goto out_unlock;
++
++              /* always superio. */
++              err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
++                           AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++              if (!err)
++                      err = au_sio_cpup_simple(dentry, bstart, -1,
++                                               AuCpup_DTIME);
++              au_unpin(&pin);
++      } else if (hi_wh) {
++              /* already copied-up after unlink */
++              err = au_reopen_wh(file, bstart, hi_wh);
++              *need_reopen = 0;
++      }
++
++ out_unlock:
++      di_read_unlock(parent, AuLock_IR);
++ out_parent:
++      dput(parent);
++ out:
++      return err;
++}
++
++static void au_do_refresh_file(struct file *file)
++{
++      aufs_bindex_t bindex, bend, new_bindex, brid;
++      struct au_hfile *p, tmp, *q;
++      struct au_finfo *finfo;
++      struct super_block *sb;
++
++      sb = file->f_dentry->d_sb;
++      finfo = au_fi(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++) {
++              if (!p->hf_file)
++                      continue;
++
++              new_bindex = au_br_index(sb, p->hf_br->br_id);
++              if (new_bindex == bindex)
++                      continue;
++              if (new_bindex < 0) {
++                      au_set_h_fptr(file, bindex, NULL);
++                      continue;
++              }
++
++              /* swap two lower inode, and loop again */
++              q = finfo->fi_hfile + new_bindex;
++              tmp = *q;
++              *q = *p;
++              *p = tmp;
++              if (tmp.hf_file) {
++                      bindex--;
++                      p--;
++              }
++      }
++
++      p = finfo->fi_hfile;
++      if (!au_test_mmapped(file) && !d_unhashed(file->f_dentry)) {
++              bend = au_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, file);
++                      }
++      } else {
++              bend = au_br_index(sb, brid);
++              for (finfo->fi_bstart = 0; finfo->fi_bstart < bend;
++                   finfo->fi_bstart++, p++)
++                      if (p->hf_file)
++                              au_hfput(p, file);
++              bend = au_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, file);
++              }
++      AuDebugOn(finfo->fi_bend < finfo->fi_bstart);
++}
++
++/*
++ * after branch manipulating, refresh the file.
++ */
++static int refresh_file(struct file *file, int (*reopen)(struct file *file))
++{
++      int err, need_reopen;
++      struct dentry *dentry;
++      aufs_bindex_t bend, bindex;
++
++      dentry = file->f_dentry;
++      err = au_fi_realloc(au_fi(file), au_sbend(dentry->d_sb) + 1);
++      if (unlikely(err))
++              goto out;
++      au_do_refresh_file(file);
++
++      err = 0;
++      need_reopen = 1;
++      if (!au_test_mmapped(file))
++              err = au_file_refresh_by_inode(file, &need_reopen);
++      if (!err && need_reopen && !d_unhashed(dentry))
++              err = reopen(file);
++      if (!err) {
++              au_update_figen(file);
++              return 0; /* success */
++      }
++
++      /* error, close all lower files */
++      bend = au_fbend(file);
++      for (bindex = au_fbstart(file); bindex <= bend; bindex++)
++              au_set_h_fptr(file, bindex, NULL);
++
++ out:
++      return err;
++}
++
++/* common function to regular file and dir */
++int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
++                        int wlock)
++{
++      int err;
++      unsigned int sigen, figen;
++      aufs_bindex_t bstart;
++      unsigned char pseudo_link;
++      struct dentry *dentry;
++
++      err = 0;
++      dentry = file->f_dentry;
++      sigen = au_sigen(dentry->d_sb);
++      fi_write_lock(file);
++      figen = au_figen(file);
++      di_write_lock_child(dentry);
++      bstart = au_dbstart(dentry);
++      pseudo_link = (bstart != au_ibstart(dentry->d_inode));
++      if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
++              if (!wlock) {
++                      di_downgrade_lock(dentry, AuLock_IR);
++                      fi_downgrade_lock(file);
++              }
++              goto out; /* success */
++      }
++
++      AuDbg("sigen %d, figen %d\n", sigen, figen);
++      if (sigen != au_digen(dentry)
++          || sigen != au_iigen(dentry->d_inode)) {
++              err = au_reval_dpath(dentry, sigen);
++              if (unlikely(err < 0))
++                      goto out;
++              AuDebugOn(au_digen(dentry) != sigen
++                        || au_iigen(dentry->d_inode) != sigen);
++      }
++
++      err = refresh_file(file, reopen);
++      if (!err) {
++              if (!wlock) {
++                      di_downgrade_lock(dentry, AuLock_IR);
++                      fi_downgrade_lock(file);
++              }
++      } else {
++              di_write_unlock(dentry);
++              fi_write_unlock(file);
++      }
++
++ out:
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* cf. aufs_nopage() */
++/* for madvise(2) */
++static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
++{
++      unlock_page(page);
++      return 0;
++}
++
++/* they will never be called. */
++#ifdef CONFIG_AUFS_DEBUG
++static int aufs_write_begin(struct file *file, struct address_space *mapping,
++                          loff_t pos, unsigned len, unsigned flags,
++                          struct page **pagep, void **fsdata)
++{ AuUnsupport(); return 0; }
++static int aufs_write_end(struct file *file, struct address_space *mapping,
++                        loff_t pos, unsigned len, unsigned copied,
++                        struct page *page, void *fsdata)
++{ AuUnsupport(); return 0; }
++static int aufs_writepage(struct page *page, struct writeback_control *wbc)
++{ AuUnsupport(); return 0; }
++static void aufs_sync_page(struct page *page)
++{ AuUnsupport(); }
++
++static int aufs_set_page_dirty(struct page *page)
++{ AuUnsupport(); return 0; }
++static void aufs_invalidatepage(struct page *page, unsigned long offset)
++{ AuUnsupport(); }
++static int aufs_releasepage(struct page *page, gfp_t gfp)
++{ AuUnsupport(); return 0; }
++static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
++                            const struct iovec *iov, loff_t offset,
++                            unsigned long nr_segs)
++{ AuUnsupport(); return 0; }
++#endif /* CONFIG_AUFS_DEBUG */
++
++struct address_space_operations aufs_aop = {
++      .readpage       = aufs_readpage,
++#ifdef CONFIG_AUFS_DEBUG
++      .writepage      = aufs_writepage,
++      .sync_page      = aufs_sync_page,
++      .set_page_dirty = aufs_set_page_dirty,
++      .write_begin    = aufs_write_begin,
++      .write_end      = aufs_write_end,
++      .invalidatepage = aufs_invalidatepage,
++      .releasepage    = aufs_releasepage,
++      .direct_IO      = aufs_direct_IO,
++#endif /* CONFIG_AUFS_DEBUG */
++};
+diff -Naur a/fs/aufs/file.h b/fs/aufs/file.h
+--- a/fs/aufs/file.h   1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/file.h   2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,159 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * file operations
++ */
++
++#ifndef __AUFS_FILE_H__
++#define __AUFS_FILE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/aufs_type.h>
++#include "rwsem.h"
++
++struct au_branch;
++struct au_hfile {
++      struct file             *hf_file;
++      struct au_branch        *hf_br;
++};
++
++struct au_vdir;
++struct au_finfo {
++      atomic_t                fi_generation;
++
++      struct rw_semaphore     fi_rwsem;
++      struct au_hfile         *fi_hfile;
++      aufs_bindex_t           fi_bstart, fi_bend;
++
++      union {
++              /* non-dir only */
++              struct {
++                      struct vm_operations_struct     *fi_h_vm_ops;
++                      struct vm_operations_struct     *fi_vm_ops;
++              };
++
++              /* dir only */
++              struct {
++                      struct au_vdir          *fi_vdir_cache;
++                      int                     fi_maintain_plink;
++              };
++      };
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* file.c */
++extern struct address_space_operations aufs_aop;
++void au_store_oflag(struct nameidata *nd, struct inode *inode);
++unsigned int au_file_roflags(unsigned int flags);
++struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
++                     struct file *file);
++int au_do_open(struct file *file, int (*open)(struct file *file, int flags));
++int au_reopen_nondir(struct file *file);
++struct au_pin;
++int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
++int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
++                        int wlock);
++
++/* f_op.c */
++extern const struct file_operations aufs_file_fop;
++int aufs_flush(struct file *file, fl_owner_t id);
++
++/* finfo.c */
++void au_hfput(struct au_hfile *hf, struct file *file);
++void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
++                 struct file *h_file);
++
++void au_update_figen(struct file *file);
++
++void au_finfo_fin(struct file *file);
++int au_finfo_init(struct file *file);
++int au_fi_realloc(struct au_finfo *finfo, int nbr);
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct au_finfo *au_fi(struct file *file)
++{
++      return file->private_data;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * fi_read_lock, fi_write_lock,
++ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
++ */
++AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
++
++#define FiMustNoWaiters(f)    AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
++
++/* ---------------------------------------------------------------------- */
++
++/* todo: hard/soft set? */
++static inline aufs_bindex_t au_fbstart(struct file *file)
++{
++      return au_fi(file)->fi_bstart;
++}
++
++static inline aufs_bindex_t au_fbend(struct file *file)
++{
++      return au_fi(file)->fi_bend;
++}
++
++static inline struct au_vdir *au_fvdir_cache(struct file *file)
++{
++      return au_fi(file)->fi_vdir_cache;
++}
++
++static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
++{
++      au_fi(file)->fi_bstart = bindex;
++}
++
++static inline void au_set_fbend(struct file *file, aufs_bindex_t bindex)
++{
++      au_fi(file)->fi_bend = bindex;
++}
++
++static inline void au_set_fvdir_cache(struct file *file,
++                                    struct au_vdir *vdir_cache)
++{
++      au_fi(file)->fi_vdir_cache = vdir_cache;
++}
++
++static inline struct file *au_h_fptr(struct file *file, aufs_bindex_t bindex)
++{
++      return au_fi(file)->fi_hfile[0 + bindex].hf_file;
++}
++
++/* todo: memory barrier? */
++static inline unsigned int au_figen(struct file *f)
++{
++      return atomic_read(&au_fi(f)->fi_generation);
++}
++
++static inline int au_test_mmapped(struct file *f)
++{
++      return !!(au_fi(f)->fi_h_vm_ops);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_FILE_H__ */
+diff -Naur a/fs/aufs/finfo.c b/fs/aufs/finfo.c
+--- a/fs/aufs/finfo.c  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/finfo.c  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,134 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * file private data
++ */
++
++#include <linux/file.h>
++#include "aufs.h"
++
++void au_hfput(struct au_hfile *hf, struct file *file)
++{
++      if (file->f_mode & FMODE_EXEC)
++              allow_write_access(hf->hf_file);
++      fput(hf->hf_file);
++      hf->hf_file = NULL;
++      atomic_dec(&hf->hf_br->br_count);
++      hf->hf_br = NULL;
++}
++
++void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
++{
++      struct au_finfo *finfo = au_fi(file);
++      struct au_hfile *hf;
++
++      hf = finfo->fi_hfile + bindex;
++      if (hf->hf_file)
++              au_hfput(hf, file);
++      if (val) {
++              hf->hf_file = val;
++              hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
++      }
++}
++
++void au_update_figen(struct file *file)
++{
++      atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
++      /* smp_mb(); */ /* atomic_set */
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_finfo_fin(struct file *file)
++{
++      struct au_finfo *finfo;
++      aufs_bindex_t bindex, bend;
++
++      fi_write_lock(file);
++      bend = au_fbend(file);
++      bindex = au_fbstart(file);
++      if (bindex >= 0)
++              /*
++               * calls fput() instead of filp_close(),
++               * since no dnotify or lock for the lower file.
++               */
++              for (; bindex <= bend; bindex++)
++                      au_set_h_fptr(file, bindex, NULL);
++
++      finfo = au_fi(file);
++      au_dbg_verify_hf(finfo);
++      kfree(finfo->fi_hfile);
++      fi_write_unlock(file);
++      au_rwsem_destroy(&finfo->fi_rwsem);
++      au_cache_free_finfo(finfo);
++}
++
++int au_finfo_init(struct file *file)
++{
++      struct au_finfo *finfo;
++      struct dentry *dentry;
++      unsigned long ul;
++
++      dentry = file->f_dentry;
++      finfo = au_cache_alloc_finfo();
++      if (unlikely(!finfo))
++              goto out;
++
++      finfo->fi_hfile = kcalloc(au_sbend(dentry->d_sb) + 1,
++                                sizeof(*finfo->fi_hfile), GFP_NOFS);
++      if (unlikely(!finfo->fi_hfile))
++              goto out_finfo;
++
++      init_rwsem(&finfo->fi_rwsem);
++      down_write(&finfo->fi_rwsem);
++      finfo->fi_bstart = -1;
++      finfo->fi_bend = -1;
++      atomic_set(&finfo->fi_generation, au_digen(dentry));
++      /* smp_mb(); */ /* atomic_set */
++
++      /* cf. au_store_oflag() */
++      /* suppress a warning in lp64 */
++      ul = (unsigned long)file->private_data;
++      file->f_mode |= (vfsub_uint_to_fmode(ul) & FMODE_EXEC);
++      file->private_data = finfo;
++      return 0; /* success */
++
++ out_finfo:
++      au_cache_free_finfo(finfo);
++ out:
++      return -ENOMEM;
++}
++
++int au_fi_realloc(struct au_finfo *finfo, int nbr)
++{
++      int err, sz;
++      struct au_hfile *hfp;
++
++      err = -ENOMEM;
++      sz = sizeof(*hfp) * (finfo->fi_bend + 1);
++      if (!sz)
++              sz = sizeof(*hfp);
++      hfp = au_kzrealloc(finfo->fi_hfile, sz, sizeof(*hfp) * nbr, GFP_NOFS);
++      if (hfp) {
++              finfo->fi_hfile = hfp;
++              err = 0;
++      }
++
++      return err;
++}
+diff -Naur a/fs/aufs/f_op.c b/fs/aufs/f_op.c
+--- a/fs/aufs/f_op.c   1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/f_op.c   2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,648 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * file and vm operations
++ */
++
++#include <linux/fs_stack.h>
++#include <linux/mm.h>
++#include <linux/poll.h>
++#include "aufs.h"
++
++/* common function to regular file and dir */
++int aufs_flush(struct file *file, fl_owner_t id)
++{
++      int err;
++      aufs_bindex_t bindex, bend;
++      struct dentry *dentry;
++      struct file *h_file;
++
++      dentry = file->f_dentry;
++      si_noflush_read_lock(dentry->d_sb);
++      fi_read_lock(file);
++      di_read_lock_child(dentry, AuLock_IW);
++
++      err = 0;
++      bend = au_fbend(file);
++      for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
++              h_file = au_h_fptr(file, bindex);
++              if (!h_file || !h_file->f_op || !h_file->f_op->flush)
++                      continue;
++
++              err = h_file->f_op->flush(h_file, id);
++              if (!err)
++                      vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
++              /*ignore*/
++      }
++      au_cpup_attr_timesizes(dentry->d_inode);
++
++      di_read_unlock(dentry, AuLock_IW);
++      fi_read_unlock(file);
++      si_read_unlock(dentry->d_sb);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int do_open_nondir(struct file *file, int flags)
++{
++      int err;
++      aufs_bindex_t bindex;
++      struct file *h_file;
++      struct dentry *dentry;
++      struct au_finfo *finfo;
++
++      err = 0;
++      dentry = file->f_dentry;
++      finfo = au_fi(file);
++      finfo->fi_h_vm_ops = NULL;
++      finfo->fi_vm_ops = NULL;
++      bindex = au_dbstart(dentry);
++      /* O_TRUNC is processed already */
++      BUG_ON(au_test_ro(dentry->d_sb, bindex, dentry->d_inode)
++             && (flags & O_TRUNC));
++
++      h_file = au_h_open(dentry, bindex, flags, file);
++      if (IS_ERR(h_file))
++              err = PTR_ERR(h_file);
++      else {
++              au_set_fbstart(file, bindex);
++              au_set_fbend(file, bindex);
++              au_set_h_fptr(file, bindex, h_file);
++              au_update_figen(file);
++              /* todo: necessary? */
++              /* file->f_ra = h_file->f_ra; */
++      }
++      return err;
++}
++
++static int aufs_open_nondir(struct inode *inode __maybe_unused,
++                          struct file *file)
++{
++      return au_do_open(file, do_open_nondir);
++}
++
++static int aufs_release_nondir(struct inode *inode __maybe_unused,
++                             struct file *file)
++{
++      struct super_block *sb = file->f_dentry->d_sb;
++
++      si_noflush_read_lock(sb);
++      kfree(au_fi(file)->fi_vm_ops);
++      au_finfo_fin(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 *h_file;
++      struct super_block *sb;
++
++      dentry = file->f_dentry;
++      sb = dentry->d_sb;
++      si_read_lock(sb, AuLock_FLUSH);
++      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
++      if (unlikely(err))
++              goto out;
++
++      h_file = au_h_fptr(file, au_fbstart(file));
++      err = vfsub_read_u(h_file, buf, count, ppos);
++      /* todo: necessary? */
++      /* file->f_ra = h_file->f_ra; */
++      fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
++
++      di_read_unlock(dentry, AuLock_IR);
++      fi_read_unlock(file);
++ out:
++      si_read_unlock(sb);
++      return err;
++}
++
++static ssize_t aufs_write(struct file *file, const char __user *ubuf,
++                        size_t count, loff_t *ppos)
++{
++      ssize_t err;
++      aufs_bindex_t bstart;
++      struct au_pin pin;
++      struct dentry *dentry;
++      struct inode *inode;
++      struct super_block *sb;
++      struct file *h_file;
++      char __user *buf = (char __user *)ubuf;
++
++      dentry = file->f_dentry;
++      sb = dentry->d_sb;
++      inode = dentry->d_inode;
++      mutex_lock(&inode->i_mutex);
++      si_read_lock(sb, AuLock_FLUSH);
++
++      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
++      if (unlikely(err))
++              goto out;
++
++      err = au_ready_to_write(file, -1, &pin);
++      di_downgrade_lock(dentry, AuLock_IR);
++      if (unlikely(err))
++              goto out_unlock;
++
++      bstart = au_fbstart(file);
++      h_file = au_h_fptr(file, bstart);
++      au_unpin(&pin);
++      err = vfsub_write_u(h_file, buf, count, ppos);
++      au_cpup_attr_timesizes(inode);
++      inode->i_mode = h_file->f_dentry->d_inode->i_mode;
++
++ out_unlock:
++      di_read_unlock(dentry, AuLock_IR);
++      fi_write_unlock(file);
++ out:
++      si_read_unlock(sb);
++      mutex_unlock(&inode->i_mutex);
++      return err;
++}
++
++static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
++                              struct pipe_inode_info *pipe, size_t len,
++                              unsigned int flags)
++{
++      ssize_t err;
++      struct file *h_file;
++      struct dentry *dentry;
++      struct super_block *sb;
++
++      dentry = file->f_dentry;
++      sb = dentry->d_sb;
++      si_read_lock(sb, AuLock_FLUSH);
++      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
++      if (unlikely(err))
++              goto out;
++
++      err = -EINVAL;
++      h_file = au_h_fptr(file, au_fbstart(file));
++      if (au_test_loopback_kthread()) {
++              file->f_mapping = h_file->f_mapping;
++              smp_mb(); /* unnecessary? */
++      }
++      err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
++      /* todo: necessasry? */
++      /* file->f_ra = h_file->f_ra; */
++      fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
++
++      di_read_unlock(dentry, AuLock_IR);
++      fi_read_unlock(file);
++
++ out:
++      si_read_unlock(sb);
++      return err;
++}
++
++static ssize_t
++aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
++                size_t len, unsigned int flags)
++{
++      ssize_t err;
++      struct au_pin pin;
++      struct dentry *dentry;
++      struct inode *inode;
++      struct super_block *sb;
++      struct file *h_file;
++
++      dentry = file->f_dentry;
++      inode = dentry->d_inode;
++      mutex_lock(&inode->i_mutex);
++      sb = dentry->d_sb;
++      si_read_lock(sb, AuLock_FLUSH);
++
++      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
++      if (unlikely(err))
++              goto out;
++
++      err = au_ready_to_write(file, -1, &pin);
++      di_downgrade_lock(dentry, AuLock_IR);
++      if (unlikely(err))
++              goto out_unlock;
++
++      h_file = au_h_fptr(file, au_fbstart(file));
++      au_unpin(&pin);
++      err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
++      au_cpup_attr_timesizes(inode);
++      inode->i_mode = h_file->f_dentry->d_inode->i_mode;
++
++ out_unlock:
++      di_read_unlock(dentry, AuLock_IR);
++      fi_write_unlock(file);
++ out:
++      si_read_unlock(sb);
++      mutex_unlock(&inode->i_mutex);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct file *au_safe_file(struct vm_area_struct *vma)
++{
++      struct file *file;
++
++      file = vma->vm_file;
++      if (file->private_data && au_test_aufs(file->f_dentry->d_sb))
++              return file;
++      return NULL;
++}
++
++static void au_reset_file(struct vm_area_struct *vma, struct file *file)
++{
++      vma->vm_file = file;
++      /* smp_mb(); */ /* flush vm_file */
++}
++
++static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
++{
++      int err;
++      static DECLARE_WAIT_QUEUE_HEAD(wq);
++      struct file *file, *h_file;
++      struct au_finfo *finfo;
++
++      /* todo: non-robr mode, user vm_file as it is? */
++      wait_event(wq, (file = au_safe_file(vma)));
++
++      /* do not revalidate, no si lock */
++      finfo = au_fi(file);
++      h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
++      AuDebugOn(!h_file || !au_test_mmapped(file));
++
++      fi_write_lock(file);
++      vma->vm_file = h_file;
++      err = finfo->fi_h_vm_ops->fault(vma, vmf);
++      /* todo: necessary? */
++      /* file->f_ra = h_file->f_ra; */
++      au_reset_file(vma, file);
++      fi_write_unlock(file);
++#if 0 /* def CONFIG_SMP */
++      /* wake_up_nr(&wq, online_cpu - 1); */
++      wake_up_all(&wq);
++#else
++      wake_up(&wq);
++#endif
++
++      return err;
++}
++
++static int aufs_page_mkwrite(struct vm_area_struct *vma, struct page *page)
++{
++      int err;
++      static DECLARE_WAIT_QUEUE_HEAD(wq);
++      struct file *file, *h_file;
++      struct au_finfo *finfo;
++
++      wait_event(wq, (file = au_safe_file(vma)));
++
++      finfo = au_fi(file);
++      h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
++      AuDebugOn(!h_file || !au_test_mmapped(file));
++
++      fi_write_lock(file);
++      vma->vm_file = h_file;
++      err = finfo->fi_h_vm_ops->page_mkwrite(vma, page);
++      au_reset_file(vma, file);
++      fi_write_unlock(file);
++      wake_up(&wq);
++
++      return err;
++}
++
++static void aufs_vm_close(struct vm_area_struct *vma)
++{
++      static DECLARE_WAIT_QUEUE_HEAD(wq);
++      struct file *file, *h_file;
++      struct au_finfo *finfo;
++
++      wait_event(wq, (file = au_safe_file(vma)));
++
++      finfo = au_fi(file);
++      h_file = finfo->fi_hfile[0 + finfo->fi_bstart].hf_file;
++      AuDebugOn(!h_file || !au_test_mmapped(file));
++
++      fi_write_lock(file);
++      vma->vm_file = h_file;
++      finfo->fi_h_vm_ops->close(vma);
++      au_reset_file(vma, file);
++      fi_write_unlock(file);
++      wake_up(&wq);
++}
++
++static struct vm_operations_struct aufs_vm_ops = {
++      /* .close and .page_mkwrite are not set by default */
++      .fault          = aufs_fault,
++};
++
++/* ---------------------------------------------------------------------- */
++
++static struct vm_operations_struct *au_vm_ops(struct file *h_file,
++                                            struct vm_area_struct *vma)
++{
++      struct vm_operations_struct *vm_ops;
++      int err;
++
++      vm_ops = ERR_PTR(-ENODEV);
++      if (!h_file->f_op || !h_file->f_op->mmap)
++              goto out;
++
++      err = h_file->f_op->mmap(h_file, vma);
++      vm_ops = ERR_PTR(err);
++      if (unlikely(err))
++              goto out;
++
++      vm_ops = vma->vm_ops;
++      err = do_munmap(current->mm, vma->vm_start,
++                      vma->vm_end - vma->vm_start);
++      if (unlikely(err)) {
++              AuIOErr("failed internal unmapping %.*s, %d\n",
++                      AuDLNPair(h_file->f_dentry), err);
++              vm_ops = ERR_PTR(-EIO);
++      }
++
++ out:
++      return vm_ops;
++}
++
++static int au_custom_vm_ops(struct au_finfo *finfo, struct vm_area_struct *vma)
++{
++      int err;
++      struct vm_operations_struct *h_ops;
++
++      err = 0;
++      h_ops = finfo->fi_h_vm_ops;
++      AuDebugOn(!h_ops);
++      if ((!h_ops->page_mkwrite && !h_ops->close)
++          || finfo->fi_vm_ops)
++              goto out;
++
++      err = -ENOMEM;
++      finfo->fi_vm_ops = kmemdup(&aufs_vm_ops, sizeof(aufs_vm_ops), GFP_NOFS);
++      if (unlikely(!finfo->fi_vm_ops))
++              goto out;
++
++      err = 0;
++      if (h_ops->page_mkwrite)
++              finfo->fi_vm_ops->page_mkwrite = aufs_page_mkwrite;
++      if (h_ops->close)
++              finfo->fi_vm_ops->close = aufs_vm_close;
++
++      vma->vm_ops = finfo->fi_vm_ops;
++
++ out:
++      return err;
++}
++
++static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
++{
++      int err;
++      unsigned char wlock, mmapped;
++      struct dentry *dentry;
++      struct super_block *sb;
++      struct file *h_file;
++      struct vm_operations_struct *vm_ops;
++
++      dentry = file->f_dentry;
++      mmapped = !!au_test_mmapped(file); /* can be harmless race condition */
++      wlock = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
++      sb = dentry->d_sb;
++      si_read_lock(sb, AuLock_FLUSH);
++      err = au_reval_and_lock_fdi(file, au_reopen_nondir, wlock | !mmapped);
++      if (unlikely(err))
++              goto out;
++
++      if (wlock) {
++              struct au_pin pin;
++
++              err = au_ready_to_write(file, -1, &pin);
++              di_downgrade_lock(dentry, AuLock_IR);
++              if (unlikely(err))
++                      goto out_unlock;
++              au_unpin(&pin);
++      } else if (!mmapped)
++              di_downgrade_lock(dentry, AuLock_IR);
++
++      h_file = au_h_fptr(file, au_fbstart(file));
++      if (au_test_fs_bad_mapping(h_file->f_dentry->d_sb)) {
++              /*
++               * by this assignment, f_mapping will differs from aufs inode
++               * i_mapping.
++               * if someone else mixes the use of f_dentry->d_inode and
++               * f_mapping->host, then a problem may arise.
++               */
++              file->f_mapping = h_file->f_mapping;
++      }
++
++      vm_ops = NULL;
++      if (!mmapped) {
++              vm_ops = au_vm_ops(h_file, vma);
++              err = PTR_ERR(vm_ops);
++              if (IS_ERR(vm_ops))
++                      goto out_unlock;
++      }
++
++      /*
++       * unnecessary to handle MAP_DENYWRITE and deny_write_access()?
++       * currently MAP_DENYWRITE from userspace is ignored, but elf loader
++       * sets it. when FMODE_EXEC is set (by open_exec() or sys_uselib()),
++       * both of the aufs file and the lower file is deny_write_access()-ed.
++       * finally I hope we can skip handlling MAP_DENYWRITE here.
++       */
++      err = generic_file_mmap(file, vma);
++      if (unlikely(err))
++              goto out_unlock;
++
++      vma->vm_ops = &aufs_vm_ops;
++      /* test again */
++      if (!au_test_mmapped(file))
++              au_fi(file)->fi_h_vm_ops = vm_ops;
++
++      err = au_custom_vm_ops(au_fi(file), vma);
++      if (unlikely(err))
++              goto out_unlock;
++
++      vfsub_file_accessed(h_file);
++      fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
++
++ out_unlock:
++      di_read_unlock(dentry, AuLock_IR);
++      if (!wlock && mmapped)
++              fi_read_unlock(file);
++      else
++              fi_write_unlock(file);
++ out:
++      si_read_unlock(sb);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static unsigned int aufs_poll(struct file *file, poll_table *wait)
++{
++      unsigned int mask;
++      int err;
++      struct file *h_file;
++      struct dentry *dentry;
++      struct super_block *sb;
++
++      /* We should pretend an error happened. */
++      mask = POLLERR /* | POLLIN | POLLOUT */;
++      dentry = file->f_dentry;
++      sb = dentry->d_sb;
++      si_read_lock(sb, AuLock_FLUSH);
++      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
++      if (unlikely(err))
++              goto out;
++
++      /* it is not an error if h_file has no operation */
++      mask = DEFAULT_POLLMASK;
++      h_file = au_h_fptr(file, au_fbstart(file));
++      if (h_file->f_op && h_file->f_op->poll)
++              mask = h_file->f_op->poll(h_file, wait);
++
++      di_read_unlock(dentry, AuLock_IR);
++      fi_read_unlock(file);
++
++ out:
++      si_read_unlock(sb);
++      AuTraceErr((int)mask);
++      return mask;
++}
++
++static int aufs_fsync_nondir(struct file *file, struct dentry *dentry,
++                           int datasync)
++{
++      int err;
++      struct au_pin pin;
++      struct inode *inode;
++      struct file *h_file;
++      struct super_block *sb;
++
++      inode = dentry->d_inode;
++      IMustLock(file->f_mapping->host);
++      if (inode != file->f_mapping->host) {
++              mutex_unlock(&file->f_mapping->host->i_mutex);
++              mutex_lock(&inode->i_mutex);
++      }
++      IMustLock(inode);
++
++      sb = dentry->d_sb;
++      si_read_lock(sb, AuLock_FLUSH);
++
++      err = 0; /* -EBADF; */ /* posix? */
++      if (unlikely(!(file->f_mode & FMODE_WRITE)))
++              goto out;
++      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
++      if (unlikely(err))
++              goto out;
++
++      err = au_ready_to_write(file, -1, &pin);
++      di_downgrade_lock(dentry, AuLock_IR);
++      if (unlikely(err))
++              goto out_unlock;
++      au_unpin(&pin);
++
++      err = -EINVAL;
++      h_file = au_h_fptr(file, au_fbstart(file));
++      if (h_file->f_op && h_file->f_op->fsync) {
++              struct dentry *h_d;
++              struct mutex *h_mtx;
++
++              /*
++               * no filemap_fdatawrite() since aufs file has no its own
++               * mapping, but dir.
++               */
++              h_d = h_file->f_dentry;
++              h_mtx = &h_d->d_inode->i_mutex;
++              mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++              err = h_file->f_op->fsync(h_file, h_d, datasync);
++              if (!err)
++                      vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
++              /*ignore*/
++              au_cpup_attr_timesizes(inode);
++              mutex_unlock(h_mtx);
++      }
++
++ out_unlock:
++      di_read_unlock(dentry, AuLock_IR);
++      fi_write_unlock(file);
++ out:
++      si_read_unlock(sb);
++      if (inode != file->f_mapping->host) {
++              mutex_unlock(&inode->i_mutex);
++              mutex_lock(&file->f_mapping->host->i_mutex);
++      }
++      return err;
++}
++
++static int aufs_fasync(int fd, struct file *file, int flag)
++{
++      int err;
++      struct file *h_file;
++      struct dentry *dentry;
++      struct super_block *sb;
++
++      dentry = file->f_dentry;
++      sb = dentry->d_sb;
++      si_read_lock(sb, AuLock_FLUSH);
++      err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
++      if (unlikely(err))
++              goto out;
++
++      h_file = au_h_fptr(file, au_fbstart(file));
++      if (h_file->f_op && h_file->f_op->fasync)
++              err = h_file->f_op->fasync(fd, h_file, flag);
++
++      di_read_unlock(dentry, AuLock_IR);
++      fi_read_unlock(file);
++
++ out:
++      si_read_unlock(sb);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++const struct file_operations aufs_file_fop = {
++      /*
++       * while generic_file_llseek/_unlocked() don't use BKL,
++       * don't use it since it operates file->f_mapping->host.
++       * in aufs, it may be a real file and may confuse users by UDBA.
++       */
++      /* .llseek              = generic_file_llseek, */
++
++      .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,
++      .splice_write   = aufs_splice_write,
++      .splice_read    = aufs_splice_read
++};
+diff -Naur a/fs/aufs/fstype.h b/fs/aufs/fstype.h
+--- a/fs/aufs/fstype.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/fstype.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,474 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * judging filesystem type
++ */
++
++#ifndef __AUFS_FSTYPE_H__
++#define __AUFS_FSTYPE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/cramfs_fs.h>
++#include <linux/fs.h>
++#include <linux/magic.h>
++#include <linux/romfs_fs.h>
++#include <linux/aufs_type.h>
++
++static inline int au_test_aufs(struct super_block *sb)
++{
++      return sb->s_magic == AUFS_SUPER_MAGIC;
++}
++
++static inline const char *au_sbtype(struct super_block *sb)
++{
++      return sb->s_type->name;
++}
++
++static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
++      return sb->s_magic == ROMFS_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_romfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
++      return sb->s_magic == ISOFS_SUPER_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
++      return sb->s_magic == CRAMFS_MAGIC;
++#endif
++      return 0;
++}
++
++static inline int au_test_nfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
++      return sb->s_magic == NFS_SUPER_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_fuse(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
++      return sb->s_magic == FUSE_SUPER_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_xfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
++      return sb->s_magic == XFS_SB_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
++{
++#ifdef CONFIG_TMPFS
++      return sb->s_magic == TMPFS_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
++      return !strcmp(au_sbtype(sb), "ecryptfs");
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
++      return sb->s_magic == SMB_SUPER_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
++      return sb->s_magic == OCFS2_SUPER_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
++      return sb->s_magic == DLMFS_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_coda(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
++      return sb->s_magic == CODA_SUPER_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
++      return sb->s_magic == V9FS_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_ext4(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
++      return sb->s_magic == EXT4_SUPER_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_sysv(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
++      return !strcmp(au_sbtype(sb), "sysv");
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_ramfs(struct super_block *sb)
++{
++      return sb->s_magic == RAMFS_MAGIC;
++}
++
++static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
++      return sb->s_magic == UBIFS_SUPER_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_procfs(struct super_block *sb __maybe_unused)
++{
++#ifdef CONFIG_PROC_FS
++      return sb->s_magic == PROC_SUPER_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
++{
++#ifdef CONFIG_SYSFS
++      return sb->s_magic == SYSFS_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_configfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
++      return sb->s_magic == CONFIGFS_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_minix(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
++      return sb->s_magic == MINIX3_SUPER_MAGIC
++              || sb->s_magic == MINIX2_SUPER_MAGIC
++              || sb->s_magic == MINIX2_SUPER_MAGIC2
++              || sb->s_magic == MINIX_SUPER_MAGIC
++              || sb->s_magic == MINIX_SUPER_MAGIC2;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_cifs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
++      return sb->s_magic == CIFS_MAGIC_NUMBER;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_fat(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
++      return sb->s_magic == MSDOS_SUPER_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_msdos(struct super_block *sb)
++{
++      return au_test_fat(sb);
++}
++
++static inline int au_test_vfat(struct super_block *sb)
++{
++      return au_test_fat(sb);
++}
++
++static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
++{
++#ifdef CONFIG_SECURITYFS
++      return sb->s_magic == SECURITYFS_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
++      return sb->s_magic == SQUASHFS_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
++      return sb->s_magic == BTRFS_SUPER_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
++{
++#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
++      return sb->s_magic == XENFS_SUPER_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
++{
++#ifdef CONFIG_DEBUG_FS
++      return sb->s_magic == DEBUGFS_MAGIC;
++#else
++      return 0;
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++/*
++ * they can't be an aufs branch.
++ */
++static inline int au_test_fs_unsuppoted(struct super_block *sb)
++{
++      return
++#ifndef CONFIG_AUFS_BR_RAMFS
++              au_test_ramfs(sb) ||
++#endif
++              au_test_procfs(sb)
++              || au_test_sysfs(sb)
++              || au_test_configfs(sb)
++              || au_test_debugfs(sb)
++              || au_test_securityfs(sb)
++              || au_test_xenfs(sb)
++              /* || !strcmp(au_sbtype(sb), "unionfs") */
++              || au_test_aufs(sb); /* will be supported in next version */
++}
++
++/*
++ * If the filesystem supports NFS-export, then it has to support NULL as
++ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
++ * We can apply this principle when we handle a lower filesystem.
++ */
++static inline int au_test_fs_null_nd(struct super_block *sb)
++{
++      return !!sb->s_export_op;
++}
++
++static inline int au_test_fs_remote(struct super_block *sb)
++{
++      return !au_test_tmpfs(sb)
++#ifdef CONFIG_AUFS_BR_RAMFS
++              && !au_test_ramfs(sb)
++#endif
++              && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * Note: these functions (below) are created after reading ->getattr() in all
++ * filesystems under linux/fs. it means we have to do so in every update...
++ */
++
++/*
++ * some filesystems require getattr to refresh the inode attributes before
++ * referencing.
++ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
++ * and leave the work for d_revalidate()
++ */
++static inline int au_test_fs_refresh_iattr(struct super_block *sb)
++{
++      return au_test_nfs(sb)
++              || au_test_fuse(sb)
++              /* || au_test_smbfs(sb) */      /* untested */
++              /* || au_test_ocfs2(sb) */      /* untested */
++              /* || au_test_btrfs(sb) */      /* untested */
++              /* || au_test_coda(sb) */       /* untested */
++              /* || au_test_v9fs(sb) */       /* untested */
++              ;
++}
++
++/*
++ * filesystems which don't maintain i_size or i_blocks.
++ */
++static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
++{
++      return au_test_xfs(sb)
++              /* || au_test_ext4(sb) */       /* untested */
++              /* || au_test_ocfs2(sb) */      /* untested */
++              /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
++              /* || au_test_sysv(sb) */       /* untested */
++              /* || au_test_ubifs(sb) */      /* untested */
++              /* || au_test_minix(sb) */      /* untested */
++              ;
++}
++
++/*
++ * filesystems which don't store the correct value in some of their inode
++ * attributes.
++ */
++static inline int au_test_fs_bad_iattr(struct super_block *sb)
++{
++      return au_test_fs_bad_iattr_size(sb)
++              /* || au_test_cifs(sb) */       /* untested */
++              || au_test_fat(sb)
++              || au_test_msdos(sb)
++              || au_test_vfat(sb);
++}
++
++/* they don't check i_nlink in link(2) */
++static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
++{
++      return au_test_tmpfs(sb)
++#ifdef CONFIG_AUFS_BR_RAMFS
++              || au_test_ramfs(sb)
++#endif
++              || au_test_ubifs(sb);
++}
++
++/*
++ * filesystems which sets S_NOATIME and S_NOCMTIME.
++ */
++static inline int au_test_fs_notime(struct super_block *sb)
++{
++      return au_test_nfs(sb)
++              || au_test_fuse(sb)
++              || au_test_ubifs(sb)
++              /* || au_test_cifs(sb) */       /* untested */
++              ;
++}
++
++/*
++ * filesystems which requires replacing i_mapping.
++ */
++static inline int au_test_fs_bad_mapping(struct super_block *sb)
++{
++      return au_test_fuse(sb)
++              || au_test_ubifs(sb);
++}
++
++/* temporary support for i#1 in cramfs */
++static inline int au_test_fs_unique_ino(struct inode *inode)
++{
++      if (au_test_cramfs(inode->i_sb))
++              return inode->i_ino != 1;
++      return 1;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * the filesystem where the xino files placed must support i/o after unlink and
++ * maintain i_size and i_blocks.
++ */
++static inline int au_test_fs_bad_xino(struct super_block *sb)
++{
++      return au_test_fs_remote(sb)
++              || au_test_fs_bad_iattr_size(sb)
++#ifdef CONFIG_AUFS_BR_RAMFS
++              || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
++#else
++              || !au_test_fs_null_nd(sb) /* to keep xino code simple */
++#endif
++              /* don't want unnecessary work for xino */
++              || au_test_aufs(sb)
++              || au_test_ecryptfs(sb);
++}
++
++static inline int au_test_fs_trunc_xino(struct super_block *sb)
++{
++      return au_test_tmpfs(sb)
++              || au_test_ramfs(sb);
++}
++
++/*
++ * test if the @sb is real-readonly.
++ */
++static inline int au_test_fs_rr(struct super_block *sb)
++{
++      return au_test_squashfs(sb)
++              || au_test_iso9660(sb)
++              || au_test_cramfs(sb)
++              || au_test_romfs(sb);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_FSTYPE_H__ */
+diff -Naur a/fs/aufs/hinotify.c b/fs/aufs/hinotify.c
+--- a/fs/aufs/hinotify.c       1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/hinotify.c       2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,755 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * inotify for the lower directories
++ */
++
++#include "aufs.h"
++
++static const __u32 AuHinMask = (IN_MOVE | IN_DELETE | IN_CREATE);
++static struct inotify_handle *au_hin_handle;
++
++AuCacheFuncs(hinotify, HINOTIFY);
++
++int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
++               struct inode *h_inode)
++{
++      int err;
++      struct au_hinotify *hin;
++      s32 wd;
++
++      err = -ENOMEM;
++      hin = au_cache_alloc_hinotify();
++      if (hin) {
++              AuDebugOn(hinode->hi_notify);
++              hinode->hi_notify = hin;
++              hin->hin_aufs_inode = inode;
++
++              inotify_init_watch(&hin->hin_watch);
++              wd = inotify_add_watch(au_hin_handle, &hin->hin_watch, h_inode,
++                                     AuHinMask);
++              if (wd >= 0)
++                      return 0; /* success */
++
++              err = wd;
++              put_inotify_watch(&hin->hin_watch);
++              au_cache_free_hinotify(hin);
++              hinode->hi_notify = NULL;
++      }
++
++      return err;
++}
++
++void au_hin_free(struct au_hinode *hinode)
++{
++      int err;
++      struct au_hinotify *hin;
++
++      hin = hinode->hi_notify;
++      if (hin) {
++              err = 0;
++              if (atomic_read(&hin->hin_watch.count))
++                      err = inotify_rm_watch(au_hin_handle, &hin->hin_watch);
++              if (unlikely(err))
++                      /* it means the watch is already removed */
++                      AuWarn("failed inotify_rm_watch() %d\n", err);
++              au_cache_free_hinotify(hin);
++              hinode->hi_notify = NULL;
++      }
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_hin_ctl(struct au_hinode *hinode, int do_set)
++{
++      struct inode *h_inode;
++      struct inotify_watch *watch;
++
++      if (!hinode->hi_notify)
++              return;
++
++      h_inode = hinode->hi_inode;
++      IMustLock(h_inode);
++
++      /* todo: try inotify_find_update_watch()? */
++      watch = &hinode->hi_notify->hin_watch;
++      mutex_lock(&h_inode->inotify_mutex);
++      /* mutex_lock(&watch->ih->mutex); */
++      if (do_set) {
++              AuDebugOn(watch->mask & AuHinMask);
++              watch->mask |= AuHinMask;
++      } else {
++              AuDebugOn(!(watch->mask & AuHinMask));
++              watch->mask &= ~AuHinMask;
++      }
++      /* mutex_unlock(&watch->ih->mutex); */
++      mutex_unlock(&h_inode->inotify_mutex);
++}
++
++void au_reset_hinotify(struct inode *inode, unsigned int flags)
++{
++      aufs_bindex_t bindex, bend;
++      struct inode *hi;
++      struct dentry *iwhdentry;
++
++      bend = au_ibend(inode);
++      for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
++              hi = au_h_iptr(inode, bindex);
++              if (!hi)
++                      continue;
++
++              /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
++              iwhdentry = au_hi_wh(inode, bindex);
++              if (iwhdentry)
++                      dget(iwhdentry);
++              au_igrab(hi);
++              au_set_h_iptr(inode, bindex, NULL, 0);
++              au_set_h_iptr(inode, bindex, au_igrab(hi),
++                            flags & ~AuHi_XINO);
++              iput(hi);
++              dput(iwhdentry);
++              /* mutex_unlock(&hi->i_mutex); */
++      }
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int hin_xino(struct inode *inode, struct inode *h_inode)
++{
++      int err;
++      aufs_bindex_t bindex, bend, bfound, bstart;
++      struct inode *h_i;
++
++      err = 0;
++      if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
++              AuWarn("branch root dir was changed\n");
++              goto out;
++      }
++
++      bfound = -1;
++      bend = au_ibend(inode);
++      bstart = au_ibstart(inode);
++#if 0 /* reserved for future use */
++      if (bindex == bend) {
++              /* keep this ino in rename case */
++              goto out;
++      }
++#endif
++      for (bindex = bstart; bindex <= bend; bindex++) {
++              if (au_h_iptr(inode, bindex) == h_inode) {
++                      bfound = bindex;
++                      break;
++              }
++      }
++      if (bfound < 0)
++              goto out;
++
++      for (bindex = bstart; bindex <= bend; bindex++) {
++              h_i = au_h_iptr(inode, bindex);
++              if (!h_i)
++                      continue;
++
++              err = au_xino_write0(inode->i_sb, bindex, h_i->i_ino, 0);
++              /* ignore this error */
++              /* bad action? */
++      }
++
++      /* children inode number will be broken */
++
++ out:
++      AuTraceErr(err);
++      return err;
++}
++
++static int hin_gen_tree(struct dentry *dentry)
++{
++      int err, i, j, ndentry;
++      struct au_dcsub_pages dpages;
++      struct au_dpage *dpage;
++      struct dentry **dentries;
++
++      err = au_dpages_init(&dpages, GFP_NOFS);
++      if (unlikely(err))
++              goto out;
++      err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
++      if (unlikely(err))
++              goto out_dpages;
++
++      for (i = 0; i < dpages.ndpage; i++) {
++              dpage = dpages.dpages + i;
++              dentries = dpage->dentries;
++              ndentry = dpage->ndentry;
++              for (j = 0; j < ndentry; j++) {
++                      struct dentry *d;
++
++                      d = dentries[j];
++                      if (IS_ROOT(d))
++                              continue;
++
++                      d_drop(d);
++                      au_digen_dec(d);
++                      if (d->d_inode)
++                              /* todo: reset children xino?
++                                 cached children only? */
++                              au_iigen_dec(d->d_inode);
++              }
++      }
++
++ out_dpages:
++      au_dpages_free(&dpages);
++
++      /* discard children */
++      dentry_unhash(dentry);
++      dput(dentry);
++ out:
++      return err;
++}
++
++/*
++ * return 0 if processed.
++ */
++static int hin_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
++                          const unsigned int isdir)
++{
++      int err;
++      struct dentry *d;
++      struct qstr *dname;
++
++      err = 1;
++      if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
++              AuWarn("branch root dir was changed\n");
++              err = 0;
++              goto out;
++      }
++
++      if (!isdir) {
++              AuDebugOn(!name);
++              au_iigen_dec(inode);
++              spin_lock(&dcache_lock);
++              list_for_each_entry(d, &inode->i_dentry, d_alias) {
++                      dname = &d->d_name;
++                      if (dname->len != nlen
++                          && memcmp(dname->name, name, nlen))
++                              continue;
++                      err = 0;
++                      spin_lock(&d->d_lock);
++                      __d_drop(d);
++                      au_digen_dec(d);
++                      spin_unlock(&d->d_lock);
++                      break;
++              }
++              spin_unlock(&dcache_lock);
++      } else {
++              au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS);
++              d = d_find_alias(inode);
++              if (!d) {
++                      au_iigen_dec(inode);
++                      goto out;
++              }
++
++              dname = &d->d_name;
++              if (dname->len == nlen && !memcmp(dname->name, name, nlen))
++                      err = hin_gen_tree(d);
++              dput(d);
++      }
++
++ out:
++      AuTraceErr(err);
++      return err;
++}
++
++static int hin_gen_by_name(struct dentry *dentry, const unsigned int isdir)
++{
++      int err;
++      struct inode *inode;
++
++      inode = dentry->d_inode;
++      if (IS_ROOT(dentry)
++          /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
++              ) {
++              AuWarn("branch root dir was changed\n");
++              return 0;
++      }
++
++      err = 0;
++      if (!isdir) {
++              d_drop(dentry);
++              au_digen_dec(dentry);
++              if (inode)
++                      au_iigen_dec(inode);
++      } else {
++              au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS);
++              if (inode)
++                      err = hin_gen_tree(dentry);
++      }
++
++      AuTraceErr(err);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* hinotify job flags */
++#define AuHinJob_XINO0                1
++#define AuHinJob_GEN          (1 << 1)
++#define AuHinJob_DIRENT               (1 << 2)
++#define AuHinJob_ISDIR                (1 << 3)
++#define AuHinJob_TRYXINO0     (1 << 4)
++#define AuHinJob_MNTPNT               (1 << 5)
++#define au_ftest_hinjob(flags, name)  ((flags) & AuHinJob_##name)
++#define au_fset_hinjob(flags, name)   { (flags) |= AuHinJob_##name; }
++#define au_fclr_hinjob(flags, name)   { (flags) &= ~AuHinJob_##name; }
++
++struct hin_job_args {
++      unsigned int flags;
++      struct inode *inode, *h_inode, *dir, *h_dir;
++      struct dentry *dentry;
++      char *h_name;
++      int h_nlen;
++};
++
++static int hin_job(struct hin_job_args *a)
++{
++      const unsigned int isdir = au_ftest_hinjob(a->flags, ISDIR);
++
++      /* reset xino */
++      if (au_ftest_hinjob(a->flags, XINO0) && a->inode)
++              hin_xino(a->inode, a->h_inode); /* ignore this error */
++
++      if (au_ftest_hinjob(a->flags, TRYXINO0)
++          && a->inode
++          && a->h_inode) {
++              mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
++              if (!a->h_inode->i_nlink)
++                      hin_xino(a->inode, a->h_inode); /* ignore this error */
++              mutex_unlock(&a->h_inode->i_mutex);
++      }
++
++      /* make the generation obsolete */
++      if (au_ftest_hinjob(a->flags, GEN)) {
++              int err = -1;
++              if (a->inode)
++                      err = hin_gen_by_inode(a->h_name, a->h_nlen, a->inode,
++                                             isdir);
++              if (err && a->dentry)
++                      hin_gen_by_name(a->dentry, isdir);
++              /* ignore this error */
++      }
++
++      /* make dir entries obsolete */
++      if (au_ftest_hinjob(a->flags, DIRENT) && a->inode) {
++              struct au_vdir *vdir;
++
++              vdir = au_ivdir(a->inode);
++              if (vdir)
++                      vdir->vd_jiffy = 0;
++              /* IMustLock(a->inode); */
++              /* a->inode->i_version++; */
++      }
++
++      /* can do nothing but warn */
++      if (au_ftest_hinjob(a->flags, MNTPNT)
++          && a->dentry
++          && d_mountpoint(a->dentry))
++              AuWarn("mount-point %.*s is removed or renamed\n",
++                     AuDLNPair(a->dentry));
++
++      return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static char *in_name(u32 mask)
++{
++#ifdef CONFIG_AUFS_DEBUG
++#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
++      return "??";
++#endif
++}
++
++static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
++                                         struct inode *dir)
++{
++      struct dentry *dentry, *d, *parent;
++      struct qstr *dname;
++
++      parent = d_find_alias(dir);
++      if (!parent)
++              return NULL;
++
++      dentry = NULL;
++      spin_lock(&dcache_lock);
++      list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
++              /* AuDbg("%.*s\n", AuDLNPair(d)); */
++              dname = &d->d_name;
++              if (dname->len != nlen || memcmp(dname->name, name, nlen))
++                      continue;
++              if (!atomic_read(&d->d_count) || !d->d_fsdata) {
++                      spin_lock(&d->d_lock);
++                      __d_drop(d);
++                      spin_unlock(&d->d_lock);
++                      continue;
++              }
++
++              dentry = dget(d);
++              break;
++      }
++      spin_unlock(&dcache_lock);
++      dput(parent);
++
++      if (dentry)
++              di_write_lock_child(dentry);
++
++      return dentry;
++}
++
++static struct inode *lookup_wlock_by_ino(struct super_block *sb,
++                                       aufs_bindex_t bindex, ino_t h_ino)
++{
++      struct inode *inode;
++      ino_t ino;
++      int err;
++
++      inode = NULL;
++      err = au_xino_read(sb, bindex, h_ino, &ino);
++      if (!err && ino)
++              inode = ilookup(sb, ino);
++      if (!inode)
++              goto out;
++
++      if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
++              AuWarn("wrong root branch\n");
++              iput(inode);
++              inode = NULL;
++              goto out;
++      }
++
++      ii_write_lock_child(inode);
++
++ out:
++      return inode;
++}
++
++enum { CHILD, PARENT };
++struct postproc_args {
++      struct inode *h_dir, *dir, *h_child_inode;
++      u32 mask;
++      unsigned int flags[2];
++      unsigned int h_child_nlen;
++      char h_child_name[];
++};
++
++static void postproc(void *_args)
++{
++      struct postproc_args *a = _args;
++      struct super_block *sb;
++      aufs_bindex_t bindex, bend, bfound;
++      unsigned char xino, try_iput;
++      int err;
++      struct inode *inode;
++      ino_t h_ino;
++      struct hin_job_args args;
++      struct dentry *dentry;
++      struct au_sbinfo *sbinfo;
++
++      AuDebugOn(!_args);
++      AuDebugOn(!a->h_dir);
++      AuDebugOn(!a->dir);
++      AuDebugOn(!a->mask);
++      AuDbg("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);
++
++      inode = NULL;
++      dentry = NULL;
++      /*
++       * do not lock a->dir->i_mutex here
++       * because of d_revalidate() may cause a deadlock.
++       */
++      sb = a->dir->i_sb;
++      AuDebugOn(!sb);
++      sbinfo = au_sbi(sb);
++      AuDebugOn(!sbinfo);
++      /* big aufs lock */
++      si_noflush_write_lock(sb);
++
++      ii_read_lock_parent(a->dir);
++      bfound = -1;
++      bend = au_ibend(a->dir);
++      for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
++              if (au_h_iptr(a->dir, bindex) == a->h_dir) {
++                      bfound = bindex;
++                      break;
++              }
++      ii_read_unlock(a->dir);
++      if (unlikely(bfound < 0))
++              goto out;
++
++      xino = !!au_opt_test(au_mntflags(sb), XINO);
++      h_ino = 0;
++      if (a->h_child_inode)
++              h_ino = a->h_child_inode->i_ino;
++
++      if (a->h_child_nlen
++          && (au_ftest_hinjob(a->flags[CHILD], GEN)
++              || au_ftest_hinjob(a->flags[CHILD], MNTPNT)))
++              dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
++                                            a->dir);
++      try_iput = 0;
++      if (dentry)
++              inode = dentry->d_inode;
++      if (xino && !inode && h_ino
++          && (au_ftest_hinjob(a->flags[CHILD], XINO0)
++              || au_ftest_hinjob(a->flags[CHILD], TRYXINO0)
++              || au_ftest_hinjob(a->flags[CHILD], GEN))) {
++              inode = lookup_wlock_by_ino(sb, bfound, h_ino);
++              try_iput = 1;
++          }
++
++      args.flags = a->flags[CHILD];
++      args.dentry = dentry;
++      args.inode = inode;
++      args.h_inode = a->h_child_inode;
++      args.dir = a->dir;
++      args.h_dir = a->h_dir;
++      args.h_name = a->h_child_name;
++      args.h_nlen = a->h_child_nlen;
++      err = hin_job(&args);
++      if (dentry) {
++              if (dentry->d_fsdata)
++                      di_write_unlock(dentry);
++              dput(dentry);
++      }
++      if (inode && try_iput) {
++              ii_write_unlock(inode);
++              iput(inode);
++      }
++
++      ii_write_lock_parent(a->dir);
++      args.flags = a->flags[PARENT];
++      args.dentry = NULL;
++      args.inode = a->dir;
++      args.h_inode = a->h_dir;
++      args.dir = NULL;
++      args.h_dir = NULL;
++      args.h_name = NULL;
++      args.h_nlen = 0;
++      err = hin_job(&args);
++      ii_write_unlock(a->dir);
++
++ out:
++      au_nwt_done(&sbinfo->si_nowait);
++      si_write_unlock(sb);
++
++      iput(a->h_child_inode);
++      iput(a->h_dir);
++      iput(a->dir);
++      kfree(a);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void aufs_inotify(struct inotify_watch *watch, u32 wd __maybe_unused,
++                       u32 mask, u32 cookie __maybe_unused,
++                       const char *h_child_name, struct inode *h_child_inode)
++{
++      struct au_hinotify *hinotify;
++      struct postproc_args *args;
++      int len, wkq_err;
++      unsigned char isdir, isroot, wh;
++      char *p;
++      struct inode *dir;
++      unsigned int flags[2];
++
++      /* if IN_UNMOUNT happens, there must be another bug */
++      AuDebugOn(mask & IN_UNMOUNT);
++      if (mask & (IN_IGNORED | IN_UNMOUNT)) {
++              put_inotify_watch(watch);
++              return;
++      }
++#ifdef AuDbgHinotify
++      au_debug(1);
++      if (1 || !h_child_name || strcmp(h_child_name, AUFS_XINO_FNAME)) {
++              AuDbg("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);
++              WARN_ON(1);
++      }
++      au_debug(0);
++#endif
++
++      hinotify = container_of(watch, struct au_hinotify, hin_watch);
++      AuDebugOn(!hinotify || !hinotify->hin_aufs_inode);
++      dir = igrab(hinotify->hin_aufs_inode);
++      if (!dir)
++              return;
++
++      isroot = (dir->i_ino == AUFS_ROOT_INO);
++      len = 0;
++      wh = 0;
++      if (h_child_name) {
++              len = strlen(h_child_name);
++              if (!memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
++                      h_child_name += AUFS_WH_PFX_LEN;
++                      len -= AUFS_WH_PFX_LEN;
++                      wh = 1;
++              }
++      }
++
++      isdir = 0;
++      if (h_child_inode)
++              isdir = !!S_ISDIR(h_child_inode->i_mode);
++      flags[PARENT] = AuHinJob_ISDIR;
++      flags[CHILD] = 0;
++      if (isdir)
++              flags[CHILD] = AuHinJob_ISDIR;
++      switch (mask & IN_ALL_EVENTS) {
++      case IN_MOVED_FROM:
++      case IN_MOVED_TO:
++              AuDebugOn(!h_child_name || !h_child_inode);
++              au_fset_hinjob(flags[CHILD], GEN);
++              au_fset_hinjob(flags[CHILD], XINO0);
++              au_fset_hinjob(flags[CHILD], MNTPNT);
++              au_fset_hinjob(flags[PARENT], DIRENT);
++              break;
++
++      case IN_CREATE:
++              AuDebugOn(!h_child_name || !h_child_inode);
++              au_fset_hinjob(flags[PARENT], DIRENT);
++              au_fset_hinjob(flags[CHILD], GEN);
++              break;
++
++      case IN_DELETE:
++              /*
++               * aufs never be able to get this child inode.
++               * revalidation should be in d_revalidate()
++               * by checking i_nlink, i_generation or d_unhashed().
++               */
++              AuDebugOn(!h_child_name);
++              au_fset_hinjob(flags[PARENT], DIRENT);
++              au_fset_hinjob(flags[CHILD], GEN);
++              au_fset_hinjob(flags[CHILD], TRYXINO0);
++              au_fset_hinjob(flags[CHILD], MNTPNT);
++              break;
++
++      default:
++              AuDebugOn(1);
++      }
++
++      if (wh)
++              h_child_inode = NULL;
++
++      /* iput() and kfree() will be called in postproc() */
++      /*
++       * inotify_mutex is already acquired and kmalloc/prune_icache may lock
++       * iprune_mutex. strange.
++       */
++      lockdep_off();
++      args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
++      lockdep_on();
++      if (unlikely(!args)) {
++              AuErr1("no memory\n");
++              iput(dir);
++              return;
++      }
++      args->flags[PARENT] = flags[PARENT];
++      args->flags[CHILD] = flags[CHILD];
++      args->mask = mask;
++      args->dir = dir;
++      args->h_dir = igrab(watch->inode);
++      if (h_child_inode)
++              h_child_inode = igrab(h_child_inode); /* can be NULL */
++      args->h_child_inode = h_child_inode;
++      args->h_child_nlen = len;
++      if (len) {
++              p = (void *)args;
++              p += sizeof(*args);
++              memcpy(p, h_child_name, len + 1);
++      }
++
++      lockdep_off();
++      wkq_err = au_wkq_nowait(postproc, args, dir->i_sb);
++      lockdep_on();
++      if (unlikely(wkq_err))
++              AuErr("wkq %d\n", wkq_err);
++}
++
++static void aufs_inotify_destroy(struct inotify_watch *watch __maybe_unused)
++{
++      return;
++}
++
++static struct inotify_operations aufs_inotify_ops = {
++      .handle_event   = aufs_inotify,
++      .destroy_watch  = aufs_inotify_destroy
++};
++
++/* ---------------------------------------------------------------------- */
++
++static void au_hin_destroy_cache(void)
++{
++      kmem_cache_destroy(au_cachep[AuCache_HINOTIFY]);
++      au_cachep[AuCache_HINOTIFY] = NULL;
++}
++
++int __init au_hinotify_init(void)
++{
++      int err;
++
++      err = -ENOMEM;
++      au_cachep[AuCache_HINOTIFY] = AuCache(au_hinotify);
++      if (au_cachep[AuCache_HINOTIFY]) {
++              err = 0;
++              au_hin_handle = inotify_init(&aufs_inotify_ops);
++              if (IS_ERR(au_hin_handle)) {
++                      err = PTR_ERR(au_hin_handle);
++                      au_hin_destroy_cache();
++              }
++      }
++      AuTraceErr(err);
++      return err;
++}
++
++void au_hinotify_fin(void)
++{
++      inotify_destroy(au_hin_handle);
++      if (au_cachep[AuCache_HINOTIFY])
++              au_hin_destroy_cache();
++}
+diff -Naur a/fs/aufs/iinfo.c b/fs/aufs/iinfo.c
+--- a/fs/aufs/iinfo.c  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/iinfo.c  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,271 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * inode private data
++ */
++
++#include "aufs.h"
++
++struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
++{
++      struct inode *h_inode;
++
++      h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
++      AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
++      return h_inode;
++}
++
++/* todo: hard/soft set? */
++void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
++{
++      struct au_iinfo *iinfo = au_ii(inode);
++      struct inode *h_inode;
++
++      iinfo->ii_bstart = bindex;
++      h_inode = iinfo->ii_hinode[bindex + 0].hi_inode;
++      if (h_inode)
++              au_cpup_igen(inode, h_inode);
++}
++
++void au_hiput(struct au_hinode *hinode)
++{
++      au_hin_free(hinode);
++      dput(hinode->hi_whdentry);
++      iput(hinode->hi_inode);
++}
++
++unsigned int au_hi_flags(struct inode *inode, int isdir)
++{
++      unsigned int flags;
++      const unsigned int mnt_flags = au_mntflags(inode->i_sb);
++
++      flags = 0;
++      if (au_opt_test(mnt_flags, XINO))
++              au_fset_hi(flags, XINO);
++      if (isdir && au_opt_test(mnt_flags, UDBA_HINOTIFY))
++              au_fset_hi(flags, HINOTIFY);
++      return flags;
++}
++
++void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
++                 struct inode *h_inode, unsigned int flags)
++{
++      struct au_hinode *hinode;
++      struct inode *hi;
++      struct au_iinfo *iinfo = au_ii(inode);
++
++      hinode = iinfo->ii_hinode + bindex;
++      hi = hinode->hi_inode;
++      AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
++      AuDebugOn(h_inode && hi);
++
++      if (hi)
++              au_hiput(hinode);
++      hinode->hi_inode = h_inode;
++      if (h_inode) {
++              int err;
++              struct super_block *sb = inode->i_sb;
++              struct au_branch *br;
++
++              if (bindex == iinfo->ii_bstart)
++                      au_cpup_igen(inode, h_inode);
++              br = au_sbr(sb, bindex);
++              hinode->hi_id = br->br_id;
++              if (au_ftest_hi(flags, XINO)) {
++                      err = au_xino_write(sb, bindex, h_inode->i_ino,
++                                          inode->i_ino);
++                      if (unlikely(err))
++                              AuIOErr1("failed au_xino_write() %d\n", err);
++              }
++
++              if (au_ftest_hi(flags, HINOTIFY)
++                  && au_br_hinotifyable(br->br_perm)) {
++                      err = au_hin_alloc(hinode, inode, h_inode);
++                      if (unlikely(err))
++                              AuIOErr1("au_hin_alloc() %d\n", err);
++              }
++      }
++}
++
++void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
++                struct dentry *h_wh)
++{
++      struct au_hinode *hinode;
++
++      hinode = au_ii(inode)->ii_hinode + bindex;
++      AuDebugOn(hinode->hi_whdentry);
++      hinode->hi_whdentry = h_wh;
++}
++
++void au_update_iigen(struct inode *inode)
++{
++      atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
++      /* smp_mb(); */ /* atomic_set */
++}
++
++/* it may be called at remount time, too */
++void au_update_brange(struct inode *inode, int do_put_zero)
++{
++      struct au_iinfo *iinfo;
++
++      iinfo = au_ii(inode);
++      if (!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)
++                              au_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_bstart = -1;
++              iinfo->ii_bend = -1;
++              return;
++      }
++
++      iinfo->ii_bend++;
++      while (0 <= --iinfo->ii_bend)
++              if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode)
++                      break;
++      AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0);
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_iinfo_init(struct inode *inode)
++{
++      struct au_iinfo *iinfo;
++      struct super_block *sb;
++      int nbr, i;
++
++      sb = inode->i_sb;
++      iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
++      nbr = au_sbend(sb) + 1;
++      if (unlikely(nbr <= 0))
++              nbr = 1;
++      iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
++      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));
++              /* smp_mb(); */ /* atomic_set */
++              init_rwsem(&iinfo->ii_rwsem);
++              iinfo->ii_bstart = -1;
++              iinfo->ii_bend = -1;
++              iinfo->ii_vdir = NULL;
++              return 0;
++      }
++      return -ENOMEM;
++}
++
++int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
++{
++      int err, sz;
++      struct au_hinode *hip;
++
++      err = -ENOMEM;
++      sz = sizeof(*hip) * (iinfo->ii_bend + 1);
++      if (!sz)
++              sz = sizeof(*hip);
++      hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
++      if (hip) {
++              iinfo->ii_hinode = hip;
++              err = 0;
++      }
++
++      return err;
++}
++
++static int au_iinfo_write0(struct super_block *sb, struct au_hinode *hinode,
++                         ino_t ino)
++{
++      int err;
++      aufs_bindex_t bindex;
++      unsigned char locked;
++
++      err = 0;
++      locked = !!si_noflush_read_trylock(sb);
++      bindex = au_br_index(sb, hinode->hi_id);
++      if (bindex >= 0)
++              err = au_xino_write0(sb, bindex, hinode->hi_inode->i_ino, ino);
++      /* error action? */
++      if (locked)
++              si_read_unlock(sb);
++      return err;
++}
++
++void au_iinfo_fin(struct inode *inode)
++{
++      ino_t ino;
++      aufs_bindex_t bend;
++      unsigned char unlinked = !inode->i_nlink;
++      struct au_iinfo *iinfo;
++      struct au_hinode *hi;
++      struct super_block *sb;
++
++      if (unlinked) {
++              int err = au_xigen_inc(inode);
++              if (unlikely(err))
++                      AuWarn1("failed resetting i_generation, %d\n", err);
++      }
++
++      iinfo = au_ii(inode);
++      /* bad_inode case */
++      if (!iinfo)
++              return;
++
++      if (iinfo->ii_vdir)
++              au_vdir_free(iinfo->ii_vdir);
++
++      if (iinfo->ii_bstart >= 0) {
++              sb = inode->i_sb;
++              ino = 0;
++              if (unlinked)
++                      ino = inode->i_ino;
++              hi = iinfo->ii_hinode + iinfo->ii_bstart;
++              bend = iinfo->ii_bend;
++              while (iinfo->ii_bstart++ <= bend) {
++                      if (hi->hi_inode) {
++                              if (unlinked || !hi->hi_inode->i_nlink) {
++                                      au_iinfo_write0(sb, hi, ino);
++                                      /* ignore this error */
++                                      ino = 0;
++                              }
++                              au_hiput(hi);
++                      }
++                      hi++;
++              }
++      }
++
++      kfree(iinfo->ii_hinode);
++      au_rwsem_destroy(&iinfo->ii_rwsem);
++}
+diff -Naur a/fs/aufs/inode.c b/fs/aufs/inode.c
+--- a/fs/aufs/inode.c  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/inode.c  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,376 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * inode functions
++ */
++
++#include "aufs.h"
++
++struct inode *au_igrab(struct inode *inode)
++{
++      if (inode) {
++              AuDebugOn(!atomic_read(&inode->i_count));
++              atomic_inc(&inode->i_count);
++      }
++      return inode;
++}
++
++static void au_refresh_hinode_attr(struct inode *inode, int do_version)
++{
++      au_cpup_attr_all(inode, /*force*/0);
++      au_update_iigen(inode);
++      if (do_version)
++              inode->i_version++;
++}
++
++int au_refresh_hinode_self(struct inode *inode, int do_attr)
++{
++      int err;
++      aufs_bindex_t bindex, new_bindex;
++      unsigned char update;
++      struct inode *first;
++      struct au_hinode *p, *q, tmp;
++      struct super_block *sb;
++      struct au_iinfo *iinfo;
++
++      update = 0;
++      sb = inode->i_sb;
++      iinfo = au_ii(inode);
++      err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
++      if (unlikely(err))
++              goto out;
++
++      p = iinfo->ii_hinode + iinfo->ii_bstart;
++      first = p->hi_inode;
++      err = 0;
++      for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
++           bindex++, p++) {
++              if (!p->hi_inode)
++                      continue;
++
++              new_bindex = au_br_index(sb, p->hi_id);
++              if (new_bindex == bindex)
++                      continue;
++
++              if (new_bindex < 0) {
++                      update++;
++                      au_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 lower inode, and loop again */
++              q = iinfo->ii_hinode + new_bindex;
++              tmp = *q;
++              *q = *p;
++              *p = tmp;
++              if (tmp.hi_inode) {
++                      bindex--;
++                      p--;
++              }
++      }
++      au_update_brange(inode, /*do_put_zero*/0);
++      if (do_attr)
++              au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
++
++ out:
++      return err;
++}
++
++int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
++{
++      int err, update;
++      unsigned int flags;
++      aufs_bindex_t bindex, bend;
++      unsigned char isdir;
++      struct inode *first;
++      struct au_hinode *p;
++      struct au_iinfo *iinfo;
++
++      err = au_refresh_hinode_self(inode, /*do_attr*/0);
++      if (unlikely(err))
++              goto out;
++
++      update = 0;
++      iinfo = au_ii(inode);
++      p = iinfo->ii_hinode + iinfo->ii_bstart;
++      first = p->hi_inode;
++      isdir = S_ISDIR(inode->i_mode);
++      flags = au_hi_flags(inode, isdir);
++      bend = au_dbend(dentry);
++      for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
++              struct inode *h_i;
++              struct dentry *h_d;
++
++              h_d = au_h_dptr(dentry, bindex);
++              if (!h_d || !h_d->d_inode)
++                      continue;
++
++              if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
++                      h_i = au_h_iptr(inode, bindex);
++                      if (h_i) {
++                              if (h_i == h_d->d_inode)
++                                      continue;
++                              err = -EIO;
++                              break;
++                      }
++              }
++              if (bindex < iinfo->ii_bstart)
++                      iinfo->ii_bstart = bindex;
++              if (iinfo->ii_bend < bindex)
++                      iinfo->ii_bend = bindex;
++              au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
++              update = 1;
++      }
++      au_update_brange(inode, /*do_put_zero*/0);
++
++      if (unlikely(err))
++              goto out;
++
++      au_refresh_hinode_attr(inode, update && isdir);
++
++ out:
++      return err;
++}
++
++static int set_inode(struct inode *inode, struct dentry *dentry)
++{
++      int err;
++      unsigned int flags;
++      umode_t mode;
++      aufs_bindex_t bindex, bstart, btail;
++      unsigned char isdir;
++      struct dentry *h_dentry;
++      struct inode *h_inode;
++      struct au_iinfo *iinfo;
++
++      err = 0;
++      isdir = 0;
++      bstart = au_dbstart(dentry);
++      h_inode = au_h_dptr(dentry, bstart)->d_inode;
++      mode = h_inode->i_mode;
++      switch (mode & S_IFMT) {
++      case S_IFREG:
++              btail = au_dbtail(dentry);
++              inode->i_op = &aufs_iop;
++              inode->i_fop = &aufs_file_fop;
++              inode->i_mapping->a_ops = &aufs_aop;
++              break;
++      case S_IFDIR:
++              isdir = 1;
++              btail = au_dbtaildir(dentry);
++              inode->i_op = &aufs_dir_iop;
++              inode->i_fop = &aufs_dir_fop;
++              break;
++      case S_IFLNK:
++              btail = au_dbtail(dentry);
++              inode->i_op = &aufs_symlink_iop;
++              break;
++      case S_IFBLK:
++      case S_IFCHR:
++      case S_IFIFO:
++      case S_IFSOCK:
++              btail = au_dbtail(dentry);
++              inode->i_op = &aufs_iop;
++              init_special_inode(inode, mode, h_inode->i_rdev);
++              break;
++      default:
++              AuIOErr("Unknown file type 0%o\n", mode);
++              err = -EIO;
++              goto out;
++      }
++
++      /* do not set inotify for whiteouted dirs (SHWH mode) */
++      flags = au_hi_flags(inode, isdir);
++      if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
++          && au_ftest_hi(flags, HINOTIFY)
++          && dentry->d_name.len > AUFS_WH_PFX_LEN
++          && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
++              au_fclr_hi(flags, HINOTIFY);
++      iinfo = au_ii(inode);
++      iinfo->ii_bstart = bstart;
++      iinfo->ii_bend = btail;
++      for (bindex = bstart; bindex <= btail; bindex++) {
++              h_dentry = au_h_dptr(dentry, bindex);
++              if (h_dentry)
++                      au_set_h_iptr(inode, bindex,
++                                    au_igrab(h_dentry->d_inode), flags);
++      }
++      au_cpup_attr_all(inode, /*force*/1);
++
++ out:
++      return err;
++}
++
++/* successful returns with iinfo write_locked */
++static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched)
++{
++      int err;
++      aufs_bindex_t bindex, bend;
++      struct inode *h_inode, *h_dinode;
++
++      *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;
++
++      err = 0;
++      ii_write_lock_new_child(inode);
++      h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
++      bend = au_ibend(inode);
++      for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
++              h_inode = au_h_iptr(inode, bindex);
++              if (h_inode && h_inode == h_dinode) {
++                      *matched = 1;
++                      err = 0;
++                      if (au_iigen(inode) != au_digen(dentry))
++                              err = au_refresh_hinode(inode, dentry);
++                      break;
++              }
++      }
++
++      if (unlikely(err))
++              ii_write_unlock(inode);
++ out:
++      return err;
++}
++
++/* successful returns with iinfo write_locked */
++/* todo: return with unlocked? */
++struct inode *au_new_inode(struct dentry *dentry, int must_new)
++{
++      struct inode *inode;
++      struct dentry *h_dentry;
++      struct super_block *sb;
++      ino_t h_ino, ino;
++      int err, match;
++      aufs_bindex_t bstart;
++
++      sb = dentry->d_sb;
++      bstart = au_dbstart(dentry);
++      h_dentry = au_h_dptr(dentry, bstart);
++      h_ino = h_dentry->d_inode->i_ino;
++      err = au_xino_read(sb, bstart, h_ino, &ino);
++      inode = ERR_PTR(err);
++      if (unlikely(err))
++              goto out;
++ new_ino:
++      if (!ino) {
++              ino = au_xino_new_ino(sb);
++              if (unlikely(!ino)) {
++                      inode = ERR_PTR(-EIO);
++                      goto out;
++              }
++      }
++
++      AuDbg("i%lu\n", (unsigned long)ino);
++      inode = au_iget_locked(sb, ino);
++      err = PTR_ERR(inode);
++      if (IS_ERR(inode))
++              goto out;
++
++      AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
++      if (inode->i_state & I_NEW) {
++              ii_write_lock_new_child(inode);
++              err = set_inode(inode, dentry);
++              unlock_new_inode(inode);
++              if (!err)
++                      goto out; /* success */
++
++              iget_failed(inode);
++              ii_write_unlock(inode);
++              goto out_iput;
++      } else if (!must_new) {
++              err = reval_inode(inode, dentry, &match);
++              if (!err)
++                      goto out; /* success */
++              else if (match)
++                      goto out_iput;
++      }
++
++      if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
++              AuWarn1("Un-notified UDBA or repeatedly renamed dir,"
++                      " b%d, %s, %.*s, hi%lu, i%lu.\n",
++                      bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
++                      (unsigned long)h_ino, (unsigned long)ino);
++      ino = 0;
++      err = au_xino_write0(sb, bstart, h_ino, 0);
++      if (!err) {
++              iput(inode);
++              goto new_ino;
++      }
++
++ out_iput:
++      iput(inode);
++      inode = ERR_PTR(err);
++ out:
++      return inode;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
++             struct inode *inode)
++{
++      int err;
++
++      err = au_br_rdonly(au_sbr(sb, bindex));
++
++      /* pseudo-link after flushed may happen out of bounds */
++      if (!err
++          && inode
++          && au_ibstart(inode) <= bindex
++          && bindex <= au_ibend(inode)) {
++              /*
++               * permission check is unnecessary since vfsub routine
++               * will be called later
++               */
++              struct inode *hi = au_h_iptr(inode, bindex);
++              if (hi)
++                      err = IS_IMMUTABLE(hi) ? -EROFS : 0;
++      }
++
++      return err;
++}
++
++int au_test_h_perm(struct inode *h_inode, int mask)
++{
++      if (!current_fsuid())
++              return 0;
++      return inode_permission(h_inode, mask);
++}
++
++int au_test_h_perm_sio(struct inode *h_inode, int mask)
++{
++      if (au_test_nfs(h_inode->i_sb)
++          && (mask & MAY_WRITE)
++          && S_ISDIR(h_inode->i_mode))
++              mask |= MAY_READ; /* force permission check */
++      return au_test_h_perm(h_inode, mask);
++}
+diff -Naur a/fs/aufs/inode.h b/fs/aufs/inode.h
+--- a/fs/aufs/inode.h  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/inode.h  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,473 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * inode operations
++ */
++
++#ifndef __AUFS_INODE_H__
++#define __AUFS_INODE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/inotify.h>
++#include <linux/aufs_type.h>
++#include "rwsem.h"
++
++struct vfsmount;
++
++struct au_hinotify {
++#ifdef CONFIG_AUFS_HINOTIFY
++      struct inotify_watch    hin_watch;
++      struct inode            *hin_aufs_inode;        /* no get/put */
++#endif
++};
++
++struct au_hinode {
++      struct inode            *hi_inode;
++      aufs_bindex_t           hi_id;
++#ifdef CONFIG_AUFS_HINOTIFY
++      struct au_hinotify      *hi_notify;
++#endif
++
++      /* reference to the copied-up whiteout with get/put */
++      struct dentry           *hi_whdentry;
++};
++
++struct au_vdir;
++struct au_iinfo {
++      atomic_t                ii_generation;
++      struct super_block      *ii_hsb1;       /* no get/put */
++
++      struct rw_semaphore     ii_rwsem;
++      aufs_bindex_t           ii_bstart, ii_bend;
++      __u32                   ii_higen;
++      struct au_hinode        *ii_hinode;
++      struct au_vdir          *ii_vdir;
++};
++
++struct au_icntnr {
++      struct au_iinfo iinfo;
++      struct inode vfs_inode;
++};
++
++/* au_pin flags */
++#define AuPin_DI_LOCKED               1
++#define AuPin_MNT_WRITE               (1 << 1)
++#define au_ftest_pin(flags, name)     ((flags) & AuPin_##name)
++#define au_fset_pin(flags, name)      { (flags) |= AuPin_##name; }
++#define au_fclr_pin(flags, name)      { (flags) &= ~AuPin_##name; }
++
++struct au_pin {
++      /* input */
++      struct dentry *dentry;
++      unsigned int udba;
++      unsigned char lsc_di, lsc_hi, flags;
++      aufs_bindex_t bindex;
++
++      /* output */
++      struct dentry *parent;
++      struct au_hinode *hdir;
++      struct vfsmount *h_mnt;
++};
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct au_iinfo *au_ii(struct inode *inode)
++{
++      struct au_iinfo *iinfo;
++
++      iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
++      if (iinfo->ii_hinode)
++              return iinfo;
++      return NULL; /* debugging bad_inode case */
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* inode.c */
++struct inode *au_igrab(struct inode *inode);
++int au_refresh_hinode_self(struct inode *inode, int do_attr);
++int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
++struct inode *au_new_inode(struct dentry *dentry, int must_new);
++int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
++             struct inode *inode);
++int au_test_h_perm(struct inode *h_inode, int mask);
++int au_test_h_perm_sio(struct inode *h_inode, int mask);
++
++/* i_op.c */
++extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
++
++/* au_wr_dir flags */
++#define AuWrDir_ADD_ENTRY     1
++#define AuWrDir_ISDIR         (1 << 1)
++#define au_ftest_wrdir(flags, name)   ((flags) & AuWrDir_##name)
++#define au_fset_wrdir(flags, name)    { (flags) |= AuWrDir_##name; }
++#define au_fclr_wrdir(flags, name)    { (flags) &= ~AuWrDir_##name; }
++
++struct au_wr_dir_args {
++      aufs_bindex_t force_btgt;
++      unsigned char flags;
++};
++int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
++            struct au_wr_dir_args *args);
++
++struct dentry *au_pinned_h_parent(struct au_pin *pin);
++void au_pin_init(struct au_pin *pin, struct dentry *dentry,
++               aufs_bindex_t bindex, int lsc_di, int lsc_hi,
++               unsigned int udba, unsigned char flags);
++int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
++         unsigned int udba, unsigned char flags) __must_check;
++int au_do_pin(struct au_pin *pin) __must_check;
++void au_unpin(struct au_pin *pin);
++
++/* i_op_add.c */
++int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
++             struct dentry *h_parent, int isdir);
++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 au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
++int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
++             struct dentry *h_parent, int isdir);
++int aufs_unlink(struct inode *dir, struct dentry *dentry);
++int aufs_rmdir(struct inode *dir, struct dentry *dentry);
++
++/* i_op_ren.c */
++int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
++int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
++              struct inode *dir, struct dentry *dentry);
++
++/* iinfo.c */
++struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
++void au_hiput(struct au_hinode *hinode);
++void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex);
++void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
++                struct dentry *h_wh);
++unsigned int au_hi_flags(struct inode *inode, int isdir);
++
++/* hinode flags */
++#define AuHi_XINO     1
++#define AuHi_HINOTIFY (1 << 1)
++#define au_ftest_hi(flags, name)      ((flags) & AuHi_##name)
++#define au_fset_hi(flags, name)               { (flags) |= AuHi_##name; }
++#define au_fclr_hi(flags, name)               { (flags) &= ~AuHi_##name; }
++
++#ifndef CONFIG_AUFS_HINOTIFY
++#undef AuHi_HINOTIFY
++#define AuHi_HINOTIFY 0
++#endif
++
++void au_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);
++int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
++
++/* plink.c */
++void au_plink_block_maintain(struct super_block *sb);
++#ifdef CONFIG_AUFS_DEBUG
++void au_plink_list(struct super_block *sb);
++#else
++static inline void au_plink_list(struct super_block *sb)
++{
++      /* nothing */
++}
++#endif
++int au_plink_test(struct inode *inode);
++struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
++void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
++                   struct dentry *h_dentry);
++void au_plink_put(struct super_block *sb);
++void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
++
++/* ---------------------------------------------------------------------- */
++
++/* 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,        /* see AuLsc_I_PARENT in vfsub.h */
++      AuLsc_II_PARENT2,
++      AuLsc_II_PARENT3,       /* copyup dirs */
++      AuLsc_II_NEW_CHILD
++};
++
++/*
++ * 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_child, ii_write_lock_new_child,
++ */
++#define AuReadLockFunc(name, lsc) \
++static inline void ii_read_lock_##name(struct inode *i) \
++{ \
++      down_read_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
++}
++
++#define AuWriteLockFunc(name, lsc) \
++static inline void ii_write_lock_##name(struct inode *i) \
++{ \
++      down_write_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
++}
++
++#define AuRWLockFuncs(name, lsc) \
++      AuReadLockFunc(name, lsc) \
++      AuWriteLockFunc(name, lsc)
++
++AuRWLockFuncs(child, CHILD);
++AuRWLockFuncs(child2, CHILD2);
++AuRWLockFuncs(child3, CHILD3);
++AuRWLockFuncs(parent, PARENT);
++AuRWLockFuncs(parent2, PARENT2);
++AuRWLockFuncs(parent3, PARENT3);
++AuRWLockFuncs(new_child, NEW_CHILD);
++
++#undef AuReadLockFunc
++#undef AuWriteLockFunc
++#undef AuRWLockFuncs
++
++/*
++ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
++ */
++AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
++
++#define IiMustNoWaiters(i)    AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
++
++/* ---------------------------------------------------------------------- */
++
++static inline unsigned int au_iigen(struct inode *inode)
++{
++      return atomic_read(&au_ii(inode)->ii_generation);
++}
++
++/* tiny test for inode number */
++/* tmpfs generation is too rough */
++static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
++{
++      struct au_iinfo *iinfo;
++
++      iinfo = au_ii(inode);
++      return !(iinfo->ii_hsb1 == h_inode->i_sb
++               && iinfo->ii_higen == h_inode->i_generation);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
++                                      aufs_bindex_t bindex)
++{
++      return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
++}
++
++static inline aufs_bindex_t au_ibstart(struct inode *inode)
++{
++      return au_ii(inode)->ii_bstart;
++}
++
++static inline aufs_bindex_t au_ibend(struct inode *inode)
++{
++      return au_ii(inode)->ii_bend;
++}
++
++static inline struct au_vdir *au_ivdir(struct inode *inode)
++{
++      return au_ii(inode)->ii_vdir;
++}
++
++static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
++{
++      return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
++}
++
++static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
++{
++      au_ii(inode)->ii_bend = bindex;
++}
++
++static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
++{
++      au_ii(inode)->ii_vdir = vdir;
++}
++
++static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
++{
++      return au_ii(inode)->ii_hinode + bindex;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct dentry *au_pinned_parent(struct au_pin *pin)
++{
++      if (pin)
++              return pin->parent;
++      return NULL;
++}
++
++static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
++{
++      if (pin && pin->hdir)
++              return pin->hdir->hi_inode;
++      return NULL;
++}
++
++static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
++{
++      if (pin)
++              return pin->hdir;
++      return NULL;
++}
++
++static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
++{
++      if (pin)
++              pin->dentry = dentry;
++}
++
++static inline void au_pin_set_parent_lflag(struct au_pin *pin,
++                                         unsigned char lflag)
++{
++      if (pin) {
++              /* dirty macros require brackets */
++              if (lflag) {
++                      au_fset_pin(pin->flags, DI_LOCKED);
++              } else {
++                      au_fclr_pin(pin->flags, DI_LOCKED);
++              }
++      }
++}
++
++static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
++{
++      if (pin) {
++              dput(pin->parent);
++              pin->parent = dget(parent);
++      }
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_HINOTIFY
++/* hinotify.c */
++int au_hin_alloc(struct au_hinode *hinode, struct inode *inode,
++               struct inode *h_inode);
++void au_hin_free(struct au_hinode *hinode);
++void au_hin_ctl(struct au_hinode *hinode, int do_set);
++void au_reset_hinotify(struct inode *inode, unsigned int flags);
++
++int __init au_hinotify_init(void);
++void au_hinotify_fin(void);
++
++static inline
++void au_hin_init(struct au_hinode *hinode, struct au_hinotify *val)
++{
++      hinode->hi_notify = val;
++}
++
++static inline void au_iigen_dec(struct inode *inode)
++{
++      atomic_dec(&au_ii(inode)->ii_generation);
++}
++
++#else
++static inline
++int au_hin_alloc(struct au_hinode *hinode __maybe_unused,
++               struct inode *inode __maybe_unused,
++               struct inode *h_inode __maybe_unused)
++{
++      return -EOPNOTSUPP;
++}
++
++static inline void au_hin_free(struct au_hinode *hinode __maybe_unused)
++{
++      /* nothing */
++}
++
++static inline void au_hin_ctl(struct au_hinode *hinode __maybe_unused,
++                            int do_set __maybe_unused)
++{
++      /* nothing */
++}
++
++static inline void au_reset_hinotify(struct inode *inode __maybe_unused,
++                                   unsigned int flags __maybe_unused)
++{
++      /* nothing */
++}
++
++static inline int au_hinotify_init(void)
++{
++      return 0;
++}
++
++#define au_hinotify_fin()     do {} while (0)
++
++static inline
++void au_hin_init(struct au_hinode *hinode __maybe_unused,
++               struct au_hinotify *val __maybe_unused)
++{
++      /* empty */
++}
++#endif /* CONFIG_AUFS_HINOTIFY */
++
++static inline void au_hin_suspend(struct au_hinode *hdir)
++{
++      au_hin_ctl(hdir, /*do_set*/0);
++}
++
++static inline void au_hin_resume(struct au_hinode *hdir)
++{
++      au_hin_ctl(hdir, /*do_set*/1);
++}
++
++static inline void au_hin_imtx_lock(struct au_hinode *hdir)
++{
++      mutex_lock(&hdir->hi_inode->i_mutex);
++      au_hin_suspend(hdir);
++}
++
++static inline void au_hin_imtx_lock_nested(struct au_hinode *hdir,
++                                         unsigned int sc __maybe_unused)
++{
++      mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
++      au_hin_suspend(hdir);
++}
++
++static inline void au_hin_imtx_unlock(struct au_hinode *hdir)
++{
++      au_hin_resume(hdir);
++      mutex_unlock(&hdir->hi_inode->i_mutex);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_INODE_H__ */
+diff -Naur a/fs/aufs/ioctl.c b/fs/aufs/ioctl.c
+--- a/fs/aufs/ioctl.c  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/ioctl.c  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,68 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * ioctl
++ * currently plink-management only.
++ */
++
++#include <linux/uaccess.h>
++#include "aufs.h"
++
++long aufs_ioctl_dir(struct file *file, unsigned int cmd,
++                  unsigned long arg __maybe_unused)
++{
++      long err;
++      struct super_block *sb;
++      struct au_sbinfo *sbinfo;
++
++      err = -EACCES;
++      if (!capable(CAP_SYS_ADMIN))
++              goto out;
++
++      err = 0;
++      sb = file->f_dentry->d_sb;
++      sbinfo = au_sbi(sb);
++      switch (cmd) {
++      case AUFS_CTL_PLINK_MAINT:
++              /*
++               * pseudo-link maintenance mode,
++               * cleared by aufs_release_dir()
++               */
++              si_write_lock(sb);
++              if (!au_ftest_si(sbinfo, MAINTAIN_PLINK)) {
++                      au_fset_si(sbinfo, MAINTAIN_PLINK);
++                      au_fi(file)->fi_maintain_plink = 1;
++              } else
++                      err = -EBUSY;
++              si_write_unlock(sb);
++              break;
++      case AUFS_CTL_PLINK_CLEAN:
++              if (au_opt_test(sbinfo->si_mntflags, PLINK)) {
++                      aufs_write_lock(sb->s_root);
++                      au_plink_put(sb);
++                      aufs_write_unlock(sb->s_root);
++              }
++              break;
++      default:
++              err = -EINVAL;
++      }
++
++ out:
++      return err;
++}
+diff -Naur a/fs/aufs/i_op_add.c b/fs/aufs/i_op_add.c
+--- a/fs/aufs/i_op_add.c       1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/i_op_add.c       2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,638 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * inode operations (add entry)
++ */
++
++#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 inode *dir, aufs_bindex_t bindex,
++                struct dentry *wh_dentry, struct dentry *dentry)
++{
++      int err, rerr;
++      aufs_bindex_t bwh;
++      struct path h_path;
++      struct inode *inode, *h_dir;
++      struct dentry *wh;
++
++      bwh = -1;
++      if (wh_dentry) {
++              h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
++              IMustLock(h_dir);
++              AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
++              bwh = au_dbwh(dentry);
++              h_path.dentry = wh_dentry;
++              h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
++              err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
++                                        dentry);
++              if (unlikely(err))
++                      goto out;
++      }
++
++      inode = au_new_inode(dentry, /*must_new*/1);
++      if (!IS_ERR(inode)) {
++              d_instantiate(dentry, inode);
++              dir = dentry->d_parent->d_inode; /* dir inode is locked */
++              IMustLock(dir);
++              if (au_ibstart(dir) == au_dbstart(dentry))
++                      au_cpup_attr_timesizes(dir);
++              dir->i_version++;
++              return 0; /* success */
++      }
++
++      err = PTR_ERR(inode);
++      if (!wh_dentry)
++              goto out;
++
++      /* revert */
++      /* dir inode is locked */
++      wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
++      rerr = PTR_ERR(wh);
++      if (IS_ERR(wh)) {
++              AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
++                      AuDLNPair(dentry), err, rerr);
++              err = -EIO;
++      } else
++              dput(wh);
++
++ out:
++      return err;
++}
++
++/*
++ * simple tests for the adding inode operations.
++ * following the checks in vfs, plus the parent-child relationship.
++ */
++int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
++             struct dentry *h_parent, int isdir)
++{
++      int err;
++      umode_t h_mode;
++      struct dentry *h_dentry;
++      struct inode *h_inode;
++
++      h_dentry = au_h_dptr(dentry, bindex);
++      h_inode = h_dentry->d_inode;
++      if (!dentry->d_inode) {
++              err = -EEXIST;
++              if (unlikely(h_inode))
++                      goto out;
++      } else {
++              /* rename(2) case */
++              err = -EIO;
++              if (unlikely(!h_inode || !h_inode->i_nlink))
++                      goto out;
++
++              h_mode = h_inode->i_mode;
++              if (!isdir) {
++                      err = -EISDIR;
++                      if (unlikely(S_ISDIR(h_mode)))
++                              goto out;
++              } else if (unlikely(!S_ISDIR(h_mode))) {
++                      err = -ENOTDIR;
++                      goto out;
++              }
++      }
++
++      err = -EIO;
++      /* expected parent dir is locked */
++      if (unlikely(h_parent != h_dentry->d_parent))
++              goto out;
++      err = 0;
++
++ out:
++      return err;
++}
++
++/*
++ * initial procedure of adding a new entry.
++ * prepare writable branch and the parent dir, lock it,
++ * and lookup whiteout for the new entry.
++ */
++static struct dentry*
++lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
++                struct dentry *src_dentry, struct au_pin *pin,
++                struct au_wr_dir_args *wr_dir_args)
++{
++      struct dentry *wh_dentry, *h_parent;
++      struct super_block *sb;
++      struct au_branch *br;
++      int err;
++      unsigned int udba;
++      aufs_bindex_t bcpup;
++
++      err = au_wr_dir(dentry, src_dentry, wr_dir_args);
++      bcpup = err;
++      wh_dentry = ERR_PTR(err);
++      if (unlikely(err < 0))
++              goto out;
++
++      sb = dentry->d_sb;
++      udba = au_opt_udba(sb);
++      err = au_pin(pin, dentry, bcpup, udba,
++                   AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++      wh_dentry = ERR_PTR(err);
++      if (unlikely(err))
++              goto out;
++
++      h_parent = au_pinned_h_parent(pin);
++      if (udba != AuOpt_UDBA_NONE
++          && au_dbstart(dentry) == bcpup) {
++              err = au_may_add(dentry, bcpup, h_parent,
++                               au_ftest_wrdir(wr_dir_args->flags, ISDIR));
++              wh_dentry = ERR_PTR(err);
++              if (unlikely(err))
++                      goto out_unpin;
++      }
++
++      br = au_sbr(sb, bcpup);
++      if (dt) {
++              struct path tmp = {
++                      .dentry = h_parent,
++                      .mnt    = br->br_mnt
++              };
++              au_dtime_store(dt, au_pinned_parent(pin), &tmp);
++      }
++
++      wh_dentry = NULL;
++      if (bcpup != au_dbwh(dentry))
++              goto out; /* success */
++
++      wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
++
++ out_unpin:
++      if (IS_ERR(wh_dentry))
++              au_unpin(pin);
++ out:
++      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;
++      aufs_bindex_t bstart;
++      unsigned char created;
++      struct au_dtime dt;
++      struct au_pin pin;
++      struct path h_path;
++      struct dentry *wh_dentry, *parent;
++      struct inode *h_dir;
++      struct au_wr_dir_args wr_dir_args = {
++              .force_btgt     = -1,
++              .flags          = AuWrDir_ADD_ENTRY
++      };
++
++      IMustLock(dir);
++
++      parent = dentry->d_parent; /* dir inode is locked */
++      aufs_read_lock(dentry, AuLock_DW);
++      di_write_lock_parent(parent);
++      wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
++                                    &wr_dir_args);
++      err = PTR_ERR(wh_dentry);
++      if (IS_ERR(wh_dentry))
++              goto out;
++
++      bstart = au_dbstart(dentry);
++      h_path.dentry = au_h_dptr(dentry, bstart);
++      h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
++      h_dir = au_pinned_h_dir(&pin);
++      switch (arg->type) {
++      case Creat:
++              err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
++              break;
++      case Symlink:
++              err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
++              break;
++      case Mknod:
++              err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
++              break;
++      default:
++              BUG();
++      }
++      created = !err;
++      if (!err)
++              err = epilog(dir, bstart, wh_dentry, dentry);
++
++      /* revert */
++      if (unlikely(created && err && h_path.dentry->d_inode)) {
++              int rerr;
++              rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
++              if (rerr) {
++                      AuIOErr("%.*s revert failure(%d, %d)\n",
++                              AuDLNPair(dentry), err, rerr);
++                      err = -EIO;
++              }
++              au_dtime_revert(&dt);
++              d_drop(dentry);
++      }
++
++      au_unpin(&pin);
++      dput(wh_dentry);
++
++ out:
++      if (unlikely(err)) {
++              au_update_dbstart(dentry);
++              d_drop(dentry);
++      }
++      di_write_unlock(parent);
++      aufs_read_unlock(dentry, AuLock_DW);
++      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 au_link_args {
++      aufs_bindex_t bdst, bsrc;
++      struct au_pin pin;
++      struct path h_path;
++      struct dentry *src_parent, *parent;
++};
++
++static int au_cpup_before_link(struct dentry *src_dentry,
++                             struct au_link_args *a)
++{
++      int err;
++      struct dentry *h_src_dentry;
++      struct mutex *h_mtx;
++
++      di_read_lock_parent(a->src_parent, AuLock_IR);
++      err = au_test_and_cpup_dirs(src_dentry, a->bdst);
++      if (unlikely(err))
++              goto out;
++
++      h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
++      h_mtx = &h_src_dentry->d_inode->i_mutex;
++      err = au_pin(&a->pin, src_dentry, a->bdst,
++                   au_opt_udba(src_dentry->d_sb),
++                   AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++      if (unlikely(err))
++              goto out;
++      mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++      err = au_sio_cpup_simple(src_dentry, a->bdst, -1,
++                               AuCpup_DTIME /* | AuCpup_KEEPLINO */);
++      mutex_unlock(h_mtx);
++      au_unpin(&a->pin);
++
++ out:
++      di_read_unlock(a->src_parent, AuLock_IR);
++      return err;
++}
++
++static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
++{
++      int err;
++      unsigned char plink;
++      struct inode *h_inode, *inode;
++      struct dentry *h_src_dentry;
++      struct super_block *sb;
++
++      plink = 0;
++      h_inode = NULL;
++      sb = src_dentry->d_sb;
++      inode = src_dentry->d_inode;
++      if (au_ibstart(inode) <= a->bdst)
++              h_inode = au_h_iptr(inode, a->bdst);
++      if (!h_inode || !h_inode->i_nlink) {
++              /* copyup src_dentry as the name of dentry. */
++              au_set_dbstart(src_dentry, a->bdst);
++              au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
++              h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
++              mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++              err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc, -1,
++                                       AuCpup_KEEPLINO, a->parent);
++              mutex_unlock(&h_inode->i_mutex);
++              au_set_h_dptr(src_dentry, a->bdst, NULL);
++              au_set_dbstart(src_dentry, a->bsrc);
++      } else {
++              /* the inode of src_dentry already exists on a.bdst branch */
++              h_src_dentry = d_find_alias(h_inode);
++              if (!h_src_dentry && au_plink_test(inode)) {
++                      plink = 1;
++                      h_src_dentry = au_plink_lkup(inode, a->bdst);
++                      err = PTR_ERR(h_src_dentry);
++                      if (IS_ERR(h_src_dentry))
++                              goto out;
++
++                      if (unlikely(!h_src_dentry->d_inode)) {
++                              dput(h_src_dentry);
++                              h_src_dentry = NULL;
++                      }
++
++              }
++              if (h_src_dentry) {
++                      err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
++                                       &a->h_path);
++                      dput(h_src_dentry);
++              } else {
++                      AuIOErr("no dentry found for hi%lu on b%d\n",
++                              h_inode->i_ino, a->bdst);
++                      err = -EIO;
++              }
++      }
++
++      if (!err && !plink)
++              au_plink_append(inode, a->bdst, a->h_path.dentry);
++
++out:
++      return err;
++}
++
++int aufs_link(struct dentry *src_dentry, struct inode *dir,
++            struct dentry *dentry)
++{
++      int err, rerr;
++      struct au_dtime dt;
++      struct au_link_args *a;
++      struct dentry *wh_dentry, *h_src_dentry;
++      struct inode *inode;
++      struct super_block *sb;
++      struct au_wr_dir_args wr_dir_args = {
++              /* .force_btgt  = -1, */
++              .flags          = AuWrDir_ADD_ENTRY
++      };
++
++      IMustLock(dir);
++      inode = src_dentry->d_inode;
++      IMustLock(inode);
++
++      err = -ENOENT;
++      if (unlikely(!inode->i_nlink))
++              goto out;
++
++      err = -ENOMEM;
++      a = kzalloc(sizeof(*a), GFP_NOFS);
++      if (unlikely(!a))
++              goto out;
++
++      a->parent = dentry->d_parent; /* dir inode is locked */
++      aufs_read_and_write_lock2(dentry, src_dentry, /*AuLock_FLUSH*/0);
++      a->src_parent = dget_parent(src_dentry);
++      wr_dir_args.force_btgt = au_dbstart(src_dentry);
++
++      di_write_lock_parent(a->parent);
++      wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
++      wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
++                                    &wr_dir_args);
++      err = PTR_ERR(wh_dentry);
++      if (IS_ERR(wh_dentry))
++              goto out_unlock;
++
++      err = 0;
++      sb = dentry->d_sb;
++      a->bdst = au_dbstart(dentry);
++      a->h_path.dentry = au_h_dptr(dentry, a->bdst);
++      a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
++      a->bsrc = au_dbstart(src_dentry);
++      if (au_opt_test(au_mntflags(sb), PLINK)) {
++              if (a->bdst < a->bsrc
++                  /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
++                      err = au_cpup_or_link(src_dentry, a);
++              else {
++                      h_src_dentry = au_h_dptr(src_dentry, a->bdst);
++                      err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
++                                       &a->h_path);
++              }
++      } else {
++              /*
++               * copyup src_dentry to the branch we process,
++               * and then link(2) to it.
++               */
++              if (a->bdst < a->bsrc
++                  /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
++                      au_unpin(&a->pin);
++                      di_write_unlock(a->parent);
++                      err = au_cpup_before_link(src_dentry, a);
++                      if (!err) {
++                              di_write_lock_parent(a->parent);
++                              err = au_pin(&a->pin, dentry, a->bdst,
++                                           au_opt_udba(sb),
++                                           AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++                              if (unlikely(err))
++                                      goto out_wh;
++                      }
++              }
++              if (!err) {
++                      h_src_dentry = au_h_dptr(src_dentry, a->bdst);
++                      err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
++                                       &a->h_path);
++              }
++      }
++      if (unlikely(err))
++              goto out_unpin;
++
++      if (wh_dentry) {
++              a->h_path.dentry = wh_dentry;
++              err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
++                                        dentry);
++              if (unlikely(err))
++                      goto out_revert;
++      }
++
++      dir->i_version++;
++      if (au_ibstart(dir) == au_dbstart(dentry))
++              au_cpup_attr_timesizes(dir);
++      inc_nlink(inode);
++      inode->i_ctime = dir->i_ctime;
++      if (!d_unhashed(a->h_path.dentry))
++              d_instantiate(dentry, au_igrab(inode));
++      else
++              /* some filesystem calls d_drop() */
++              d_drop(dentry);
++      goto out_unpin; /* success */
++
++ out_revert:
++      rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
++      if (!rerr)
++              goto out_dt;
++      AuIOErr("%.*s reverting failed(%d, %d)\n",
++              AuDLNPair(dentry), err, rerr);
++      err = -EIO;
++ out_dt:
++      d_drop(dentry);
++      au_dtime_revert(&dt);
++ out_unpin:
++      au_unpin(&a->pin);
++ out_wh:
++      dput(wh_dentry);
++ out_unlock:
++      if (unlikely(err)) {
++              au_update_dbstart(dentry);
++              d_drop(dentry);
++      }
++      di_write_unlock(a->parent);
++      dput(a->src_parent);
++      aufs_read_and_write_unlock2(dentry, src_dentry);
++      kfree(a);
++ out:
++      return err;
++}
++
++int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
++{
++      int err, rerr;
++      aufs_bindex_t bindex;
++      unsigned char diropq;
++      struct au_pin pin;
++      struct path h_path;
++      struct dentry *wh_dentry, *parent, *opq_dentry;
++      struct mutex *h_mtx;
++      struct super_block *sb;
++      struct au_dtime dt;
++      struct au_wr_dir_args wr_dir_args = {
++              .force_btgt     = -1,
++              .flags          = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
++      };
++
++      IMustLock(dir);
++
++      aufs_read_lock(dentry, AuLock_DW);
++      parent = dentry->d_parent; /* dir inode is locked */
++      di_write_lock_parent(parent);
++      wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
++                                    &wr_dir_args);
++      err = PTR_ERR(wh_dentry);
++      if (IS_ERR(wh_dentry))
++              goto out;
++
++      sb = dentry->d_sb;
++      bindex = au_dbstart(dentry);
++      h_path.dentry = au_h_dptr(dentry, bindex);
++      h_path.mnt = au_sbr_mnt(sb, bindex);
++      err = vfsub_mkdir(au_pinned_h_dir(&pin), &h_path, mode);
++      if (unlikely(err))
++              goto out_unlock;
++
++      /* make the dir opaque */
++      diropq = 0;
++      h_mtx = &h_path.dentry->d_inode->i_mutex;
++      if (wh_dentry
++          || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
++              mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++              opq_dentry = au_diropq_create(dentry, bindex);
++              mutex_unlock(h_mtx);
++              err = PTR_ERR(opq_dentry);
++              if (IS_ERR(opq_dentry))
++                      goto out_dir;
++              dput(opq_dentry);
++              diropq = 1;
++      }
++
++      err = epilog(dir, bindex, wh_dentry, dentry);
++      if (!err) {
++              inc_nlink(dir);
++              goto out_unlock; /* success */
++      }
++
++      /* revert */
++      if (diropq) {
++              AuLabel(revert opq);
++              mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++              rerr = au_diropq_remove(dentry, bindex);
++              mutex_unlock(h_mtx);
++              if (rerr) {
++                      AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
++                              AuDLNPair(dentry), err, rerr);
++                      err = -EIO;
++              }
++      }
++
++ out_dir:
++      AuLabel(revert dir);
++      rerr = vfsub_rmdir(au_pinned_h_dir(&pin), &h_path);
++      if (rerr) {
++              AuIOErr("%.*s reverting dir failed(%d, %d)\n",
++                      AuDLNPair(dentry), err, rerr);
++              err = -EIO;
++      }
++      d_drop(dentry);
++      au_dtime_revert(&dt);
++ out_unlock:
++      au_unpin(&pin);
++      dput(wh_dentry);
++ out:
++      if (unlikely(err)) {
++              au_update_dbstart(dentry);
++              d_drop(dentry);
++      }
++      di_write_unlock(parent);
++      aufs_read_unlock(dentry, AuLock_DW);
++      return err;
++}
+diff -Naur a/fs/aufs/i_op.c b/fs/aufs/i_op.c
+--- a/fs/aufs/i_op.c   1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/i_op.c   2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,874 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * inode operations (except add/del/rename)
++ */
++
++#include <linux/device_cgroup.h>
++#include <linux/fs_stack.h>
++#include <linux/mm.h>
++#include <linux/namei.h>
++#include <linux/security.h>
++#include <linux/uaccess.h>
++#include "aufs.h"
++
++static int h_permission(struct inode *h_inode, int mask,
++                      struct vfsmount *h_mnt, int brperm)
++{
++      int err;
++      const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
++
++      err = -EACCES;
++      if ((write_mask && IS_IMMUTABLE(h_inode))
++          || ((mask & MAY_EXEC)
++              && S_ISREG(h_inode->i_mode)
++              && ((h_mnt->mnt_flags & MNT_NOEXEC)
++                  || !(h_inode->i_mode & S_IXUGO))))
++              goto out;
++
++      /*
++       * - skip the lower fs test in the case of write to ro branch.
++       * - nfs dir permission write check is optimized, but a policy for
++       *   link/rename requires a real check.
++       */
++      if ((write_mask && !au_br_writable(brperm))
++          || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
++              && write_mask && !(mask & MAY_READ))
++          || !h_inode->i_op->permission) {
++              /* AuLabel(generic_permission); */
++              err = generic_permission(h_inode, mask, NULL);
++      } else {
++              /* AuLabel(h_inode->permission); */
++              err = h_inode->i_op->permission(h_inode, mask);
++              AuTraceErr(err);
++      }
++
++      if (!err)
++              err = devcgroup_inode_permission(h_inode, mask);
++      if (!err)
++              err = security_inode_permission
++                      (h_inode, mask & (MAY_READ | MAY_WRITE | MAY_EXEC
++                                        | MAY_APPEND));
++
++ out:
++      return err;
++}
++
++static int aufs_permission(struct inode *inode, int mask)
++{
++      int err;
++      aufs_bindex_t bindex, bend;
++      const unsigned char isdir = !!S_ISDIR(inode->i_mode);
++      const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
++      struct inode *h_inode;
++      struct super_block *sb;
++      struct au_branch *br;
++
++      sb = inode->i_sb;
++      si_read_lock(sb, AuLock_FLUSH);
++      ii_read_lock_child(inode);
++
++      if (!isdir || write_mask) {
++              h_inode = au_h_iptr(inode, au_ibstart(inode));
++              AuDebugOn(!h_inode
++                        || ((h_inode->i_mode & S_IFMT)
++                            != (inode->i_mode & S_IFMT)));
++              err = 0;
++              bindex = au_ibstart(inode);
++              br = au_sbr(sb, bindex);
++              err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
++
++              if (write_mask && !err) {
++                      /* test whether the upper writable branch exists */
++                      err = -EROFS;
++                      for (; bindex >= 0; bindex--)
++                              if (!au_br_rdonly(au_sbr(sb, bindex))) {
++                                      err = 0;
++                                      break;
++                              }
++              }
++              goto out;
++      }
++
++      /* non-write to dir */
++      err = 0;
++      bend = au_ibend(inode);
++      for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
++              h_inode = au_h_iptr(inode, bindex);
++              if (h_inode) {
++                      AuDebugOn(!S_ISDIR(h_inode->i_mode));
++                      br = au_sbr(sb, bindex);
++                      err = h_permission(h_inode, mask, br->br_mnt,
++                                         br->br_perm);
++              }
++      }
++
++ out:
++      ii_read_unlock(inode);
++      si_read_unlock(sb);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
++                                struct nameidata *nd)
++{
++      struct dentry *ret, *parent;
++      struct inode *inode, *h_inode;
++      struct mutex *mtx;
++      struct super_block *sb;
++      int err, npositive;
++      aufs_bindex_t bstart;
++
++      /* temporary workaround for a bug in NFSD readdir */
++      if (!au_test_nfsd(current))
++              IMustLock(dir);
++      else
++              WARN_ONCE(!mutex_is_locked(&dir->i_mutex),
++                        "a known problem of NFSD readdir since 2.6.28\n");
++
++      sb = dir->i_sb;
++      si_read_lock(sb, AuLock_FLUSH);
++      err = au_alloc_dinfo(dentry);
++      ret = ERR_PTR(err);
++      if (unlikely(err))
++              goto out;
++
++      parent = dentry->d_parent; /* dir inode is locked */
++      di_read_lock_parent(parent, AuLock_IR);
++      npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd);
++      di_read_unlock(parent, AuLock_IR);
++      err = npositive;
++      ret = ERR_PTR(err);
++      if (unlikely(err < 0))
++              goto out_unlock;
++
++      inode = NULL;
++      if (npositive) {
++              bstart = au_dbstart(dentry);
++              h_inode = au_h_dptr(dentry, bstart)->d_inode;
++              if (!S_ISDIR(h_inode->i_mode)) {
++                      /*
++                       * stop 'race'-ing between hardlinks under different
++                       * parents.
++                       */
++                      mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
++                      mutex_lock(mtx);
++                      inode = au_new_inode(dentry, /*must_new*/0);
++                      mutex_unlock(mtx);
++              } else
++                      inode = au_new_inode(dentry, /*must_new*/0);
++              ret = (void *)inode;
++      }
++      if (IS_ERR(inode))
++              goto out_unlock;
++
++      ret = d_splice_alias(inode, dentry);
++      if (unlikely(IS_ERR(ret) && inode))
++              ii_write_unlock(inode);
++      au_store_oflag(nd, inode);
++
++ out_unlock:
++      di_write_unlock(dentry);
++ out:
++      si_read_unlock(sb);
++      return ret;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
++                        const unsigned char add_entry, aufs_bindex_t bcpup,
++                        aufs_bindex_t bstart)
++{
++      int err;
++      struct dentry *h_parent;
++      struct inode *h_dir;
++
++      if (add_entry) {
++              au_update_dbstart(dentry);
++              IMustLock(parent->d_inode);
++      } else
++              di_write_lock_parent(parent);
++
++      err = 0;
++      if (!au_h_dptr(parent, bcpup)) {
++              if (bstart < bcpup)
++                      err = au_cpdown_dirs(dentry, bcpup);
++              else
++                      err = au_cpup_dirs(dentry, bcpup);
++      }
++      if (!err && add_entry) {
++              h_parent = au_h_dptr(parent, bcpup);
++              h_dir = h_parent->d_inode;
++              mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
++              err = au_lkup_neg(dentry, bcpup);
++              /* todo: no unlock here */
++              mutex_unlock(&h_dir->i_mutex);
++              if (bstart < bcpup && au_dbstart(dentry) < 0) {
++                      au_set_dbstart(dentry, 0);
++                      au_update_dbrange(dentry, /*do_put_zero*/0);
++              }
++      }
++
++      if (!add_entry)
++              di_write_unlock(parent);
++      if (!err)
++              err = bcpup; /* success */
++
++      return err;
++}
++
++/*
++ * 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 au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
++            struct au_wr_dir_args *args)
++{
++      int err;
++      aufs_bindex_t bcpup, bstart, src_bstart;
++      const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
++                                                       ADD_ENTRY);
++      struct super_block *sb;
++      struct dentry *parent;
++      struct au_sbinfo *sbinfo;
++
++      sb = dentry->d_sb;
++      sbinfo = au_sbi(sb);
++      parent = dget_parent(dentry);
++      bstart = au_dbstart(dentry);
++      bcpup = bstart;
++      if (args->force_btgt < 0) {
++              if (src_dentry) {
++                      src_bstart = au_dbstart(src_dentry);
++                      if (src_bstart < bstart)
++                              bcpup = src_bstart;
++              } else if (add_entry) {
++                      err = AuWbrCreate(sbinfo, dentry,
++                                        au_ftest_wrdir(args->flags, ISDIR));
++                      bcpup = err;
++              }
++
++              if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
++                      if (add_entry)
++                              err = AuWbrCopyup(sbinfo, dentry);
++                      else {
++                              if (!IS_ROOT(dentry)) {
++                                      di_read_lock_parent(parent, !AuLock_IR);
++                                      err = AuWbrCopyup(sbinfo, dentry);
++                                      di_read_unlock(parent, !AuLock_IR);
++                              } else
++                                      err = AuWbrCopyup(sbinfo, dentry);
++                      }
++                      bcpup = err;
++                      if (unlikely(err < 0))
++                              goto out;
++              }
++      } else {
++              bcpup = args->force_btgt;
++              AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
++      }
++      AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
++      if (bstart < bcpup)
++              au_update_dbrange(dentry, /*do_put_zero*/1);
++
++      err = bcpup;
++      if (bcpup == bstart)
++              goto out; /* success */
++
++      /* copyup the new parent into the branch we process */
++      err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
++
++ out:
++      dput(parent);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct dentry *au_pinned_h_parent(struct au_pin *pin)
++{
++      if (pin && pin->parent)
++              return au_h_dptr(pin->parent, pin->bindex);
++      return NULL;
++}
++
++void au_unpin(struct au_pin *p)
++{
++      if (au_ftest_pin(p->flags, MNT_WRITE))
++              mnt_drop_write(p->h_mnt);
++      if (!p->hdir)
++              return;
++
++      au_hin_imtx_unlock(p->hdir);
++      if (!au_ftest_pin(p->flags, DI_LOCKED))
++              di_read_unlock(p->parent, AuLock_IR);
++      iput(p->hdir->hi_inode);
++      dput(p->parent);
++      p->parent = NULL;
++      p->hdir = NULL;
++      p->h_mnt = NULL;
++}
++
++int au_do_pin(struct au_pin *p)
++{
++      int err;
++      struct super_block *sb;
++      struct dentry *h_dentry, *h_parent;
++      struct au_branch *br;
++      struct inode *h_dir;
++
++      err = 0;
++      sb = p->dentry->d_sb;
++      br = au_sbr(sb, p->bindex);
++      if (IS_ROOT(p->dentry)) {
++              if (au_ftest_pin(p->flags, MNT_WRITE)) {
++                      p->h_mnt = br->br_mnt;
++                      err = mnt_want_write(p->h_mnt);
++                      if (unlikely(err)) {
++                              au_fclr_pin(p->flags, MNT_WRITE);
++                              goto out_err;
++                      }
++              }
++              goto out;
++      }
++
++      h_dentry = NULL;
++      if (p->bindex <= au_dbend(p->dentry))
++              h_dentry = au_h_dptr(p->dentry, p->bindex);
++
++      p->parent = dget_parent(p->dentry);
++      if (!au_ftest_pin(p->flags, DI_LOCKED))
++              di_read_lock(p->parent, AuLock_IR, p->lsc_di);
++
++      h_dir = NULL;
++      h_parent = au_h_dptr(p->parent, p->bindex);
++      p->hdir = au_hi(p->parent->d_inode, p->bindex);
++      if (p->hdir)
++              h_dir = p->hdir->hi_inode;
++
++      /* udba case */
++      if (unlikely(!p->hdir || !h_dir)) {
++              err = au_busy_or_stale();
++              if (!au_ftest_pin(p->flags, DI_LOCKED))
++                      di_read_unlock(p->parent, AuLock_IR);
++              dput(p->parent);
++              p->parent = NULL;
++              goto out_err;
++      }
++
++      au_igrab(h_dir);
++      au_hin_imtx_lock_nested(p->hdir, p->lsc_hi);
++
++      if (h_dentry) {
++              err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
++              if (unlikely(err)) {
++                      au_fclr_pin(p->flags, MNT_WRITE);
++                      goto out_unpin;
++              }
++      }
++
++      if (au_ftest_pin(p->flags, MNT_WRITE)) {
++              p->h_mnt = br->br_mnt;
++              err = mnt_want_write(p->h_mnt);
++              if (unlikely(err)) {
++                      au_fclr_pin(p->flags, MNT_WRITE);
++                      goto out_unpin;
++              }
++      }
++      goto out; /* success */
++
++ out_unpin:
++      au_unpin(p);
++ out_err:
++      AuErr("err %d\n", err);
++      err = au_busy_or_stale();
++ out:
++      return err;
++}
++
++void au_pin_init(struct au_pin *p, struct dentry *dentry,
++               aufs_bindex_t bindex, int lsc_di, int lsc_hi,
++               unsigned int udba, unsigned char flags)
++{
++      p->dentry = dentry;
++      p->udba = udba;
++      p->lsc_di = lsc_di;
++      p->lsc_hi = lsc_hi;
++      p->flags = flags;
++      p->bindex = bindex;
++
++      p->parent = NULL;
++      p->hdir = NULL;
++      p->h_mnt = NULL;
++}
++
++int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
++         unsigned int udba, unsigned char flags)
++{
++      au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
++                  udba, flags);
++      return au_do_pin(pin);
++}
++
++/* ---------------------------------------------------------------------- */
++
++#define AuIcpup_DID_CPUP      1
++#define au_ftest_icpup(flags, name)   ((flags) & AuIcpup_##name)
++#define au_fset_icpup(flags, name)    { (flags) |= AuIcpup_##name; }
++#define au_fclr_icpup(flags, name)    { (flags) &= ~AuIcpup_##name; }
++
++struct au_icpup_args {
++      unsigned char flags;
++      unsigned char pin_flags;
++      aufs_bindex_t btgt;
++      struct au_pin pin;
++      struct path h_path;
++      struct inode *h_inode;
++};
++
++static int au_lock_and_icpup(struct dentry *dentry, struct iattr *ia,
++                           struct au_icpup_args *a)
++{
++      int err;
++      unsigned int udba;
++      loff_t sz;
++      aufs_bindex_t bstart;
++      struct dentry *hi_wh, *parent;
++      struct inode *inode;
++      struct au_wr_dir_args wr_dir_args = {
++              .force_btgt     = -1,
++              .flags          = 0
++      };
++
++      di_write_lock_child(dentry);
++      bstart = au_dbstart(dentry);
++      inode = dentry->d_inode;
++      if (S_ISDIR(inode->i_mode))
++              au_fset_wrdir(wr_dir_args.flags, ISDIR);
++      /* plink or hi_wh() case */
++      if (bstart != au_ibstart(inode))
++              wr_dir_args.force_btgt = au_ibstart(inode);
++      err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
++      if (unlikely(err < 0))
++              goto out_dentry;
++      a->btgt = err;
++      if (err != bstart)
++              au_fset_icpup(a->flags, DID_CPUP);
++
++      err = 0;
++      a->pin_flags = AuPin_MNT_WRITE;
++      parent = NULL;
++      if (!IS_ROOT(dentry)) {
++              au_fset_pin(a->pin_flags, DI_LOCKED);
++              parent = dget_parent(dentry);
++              di_write_lock_parent(parent);
++      }
++
++      udba = au_opt_udba(dentry->d_sb);
++      if (d_unhashed(dentry) || (ia->ia_valid & ATTR_FILE))
++              udba = AuOpt_UDBA_NONE;
++      err = au_pin(&a->pin, dentry, a->btgt, udba, a->pin_flags);
++      if (unlikely(err)) {
++              if (parent) {
++                      di_write_unlock(parent);
++                      dput(parent);
++              }
++              goto out_dentry;
++      }
++      a->h_path.dentry = au_h_dptr(dentry, bstart);
++      a->h_inode = a->h_path.dentry->d_inode;
++      mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
++      sz = -1;
++      if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
++              sz = ia->ia_size;
++
++      hi_wh = NULL;
++      if (au_ftest_icpup(a->flags, DID_CPUP) && d_unhashed(dentry)) {
++              hi_wh = au_hi_wh(inode, a->btgt);
++              if (!hi_wh) {
++                      err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
++                      if (unlikely(err))
++                              goto out_unlock;
++                      hi_wh = au_hi_wh(inode, a->btgt);
++                      /* todo: revalidate hi_wh? */
++              }
++      }
++
++      if (parent) {
++              au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
++              di_downgrade_lock(parent, AuLock_IR);
++              dput(parent);
++      }
++      if (!au_ftest_icpup(a->flags, DID_CPUP))
++              goto out; /* success */
++
++      if (!d_unhashed(dentry)) {
++              err = au_sio_cpup_simple(dentry, a->btgt, sz, AuCpup_DTIME);
++              if (!err)
++                      a->h_path.dentry = au_h_dptr(dentry, a->btgt);
++      } else if (!hi_wh)
++              a->h_path.dentry = au_h_dptr(dentry, a->btgt);
++      else
++              a->h_path.dentry = hi_wh; /* do not dget here */
++
++ out_unlock:
++      mutex_unlock(&a->h_inode->i_mutex);
++      a->h_inode = a->h_path.dentry->d_inode;
++      if (!err) {
++              mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
++              goto out; /* success */
++      }
++
++      au_unpin(&a->pin);
++
++ out_dentry:
++      di_write_unlock(dentry);
++ out:
++      return err;
++}
++
++static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
++{
++      int err;
++      struct inode *inode;
++      struct super_block *sb;
++      struct file *file;
++      struct au_icpup_args *a;
++
++      err = -ENOMEM;
++      a = kzalloc(sizeof(*a), GFP_NOFS);
++      if (unlikely(!a))
++              goto out;
++
++      inode = dentry->d_inode;
++      IMustLock(inode);
++      sb = dentry->d_sb;
++      si_read_lock(sb, AuLock_FLUSH);
++
++      file = NULL;
++      if (ia->ia_valid & ATTR_FILE) {
++              /* currently ftruncate(2) only */
++              file = ia->ia_file;
++              fi_write_lock(file);
++              ia->ia_file = au_h_fptr(file, au_fbstart(file));
++      }
++
++      if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
++              ia->ia_valid &= ~ATTR_MODE;
++
++      err = au_lock_and_icpup(dentry, ia, a);
++      if (unlikely(err < 0))
++              goto out_si;
++      if (au_ftest_icpup(a->flags, DID_CPUP)) {
++              ia->ia_file = NULL;
++              ia->ia_valid &= ~ATTR_FILE;
++      }
++
++      a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
++      if (ia->ia_valid & ATTR_SIZE) {
++              struct file *f;
++
++              if (ia->ia_size < i_size_read(inode)) {
++                      /* unmap only */
++                      err = vmtruncate(inode, ia->ia_size);
++                      if (unlikely(err))
++                              goto out_unlock;
++              }
++
++              f = NULL;
++              if (ia->ia_valid & ATTR_FILE)
++                      f = ia->ia_file;
++              mutex_unlock(&a->h_inode->i_mutex);
++              err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
++              mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
++      } else
++              err = vfsub_notify_change(&a->h_path, ia);
++      if (!err)
++              au_cpup_attr_changeable(inode);
++
++ out_unlock:
++      mutex_unlock(&a->h_inode->i_mutex);
++      au_unpin(&a->pin);
++      di_write_unlock(dentry);
++ out_si:
++      if (file) {
++              fi_write_unlock(file);
++              ia->ia_file = file;
++              ia->ia_valid |= ATTR_FILE;
++      }
++      si_read_unlock(sb);
++      kfree(a);
++ out:
++      return err;
++}
++
++static int au_getattr_lock_reval(struct dentry *dentry, unsigned int sigen)
++{
++      int err;
++      struct inode *inode;
++      struct dentry *parent;
++
++      err = 0;
++      inode = dentry->d_inode;
++      di_write_lock_child(dentry);
++      if (au_digen(dentry) != sigen || au_iigen(inode) != sigen) {
++              parent = dget_parent(dentry);
++              di_read_lock_parent(parent, AuLock_IR);
++              /* returns a number of positive dentries */
++              err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT);
++              if (err > 0)
++                      err = au_refresh_hinode(inode, dentry);
++              di_read_unlock(parent, AuLock_IR);
++              dput(parent);
++              if (unlikely(!err))
++                      err = -EIO;
++      }
++      di_downgrade_lock(dentry, AuLock_IR);
++
++      return err;
++}
++
++static void au_refresh_iattr(struct inode *inode, struct kstat *st,
++                           unsigned int nlink)
++{
++      inode->i_mode = st->mode;
++      inode->i_uid = st->uid;
++      inode->i_gid = st->gid;
++      inode->i_atime = st->atime;
++      inode->i_mtime = st->mtime;
++      inode->i_ctime = st->ctime;
++
++      au_cpup_attr_nlink(inode, /*force*/0);
++      if (S_ISDIR(inode->i_mode)) {
++              inode->i_nlink -= nlink;
++              inode->i_nlink += st->nlink;
++      }
++
++      spin_lock(&inode->i_lock);
++      inode->i_blocks = st->blocks;
++      i_size_write(inode, st->size);
++      spin_unlock(&inode->i_lock);
++}
++
++static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
++                      struct dentry *dentry, struct kstat *st)
++{
++      int err;
++      unsigned int mnt_flags;
++      aufs_bindex_t bindex;
++      unsigned char udba_none, positive, did_lock;
++      struct super_block *sb, *h_sb;
++      struct inode *inode;
++      struct vfsmount *h_mnt;
++      struct dentry *h_dentry;
++
++      err = 0;
++      did_lock = 0;
++      sb = dentry->d_sb;
++      inode = dentry->d_inode;
++      si_read_lock(sb, AuLock_FLUSH);
++      if (IS_ROOT(dentry)) {
++              /* lock free root dinfo */
++              h_dentry = dget(au_di(dentry)->di_hdentry->hd_dentry);
++              h_mnt = au_sbr_mnt(sb, 0);
++              goto getattr;
++      }
++
++      did_lock = 1;
++      mnt_flags = au_mntflags(sb);
++      udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
++
++      /* support fstat(2) */
++      if (!d_unhashed(dentry) && !udba_none) {
++              unsigned int sigen = au_sigen(sb);
++              if (au_digen(dentry) == sigen && au_iigen(inode) == sigen)
++                      di_read_lock_child(dentry, AuLock_IR);
++              else {
++                      err = au_getattr_lock_reval(dentry, sigen);
++                      if (unlikely(err))
++                              goto out;
++              }
++      } else
++              di_read_lock_child(dentry, AuLock_IR);
++
++      bindex = au_ibstart(inode);
++      h_mnt = au_sbr_mnt(sb, bindex);
++      h_sb = h_mnt->mnt_sb;
++      if (!au_test_fs_bad_iattr(h_sb) && udba_none)
++              goto out_fill; /* success */
++
++      if (au_dbstart(dentry) == bindex)
++              h_dentry = dget(au_h_dptr(dentry, bindex));
++      else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
++              h_dentry = au_plink_lkup(inode, bindex);
++              if (IS_ERR(h_dentry))
++                      goto out_fill; /* pretending success */
++      } else
++              /* illegally overlapped or something */
++              goto out_fill; /* pretending success */
++
++ getattr:
++      positive = !!h_dentry->d_inode;
++      if (positive)
++              err = vfs_getattr(h_mnt, h_dentry, st);
++      dput(h_dentry);
++      if (!err) {
++              if (positive)
++                      au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
++              goto out_fill; /* success */
++      }
++      goto out;
++
++ out_fill:
++      generic_fillattr(inode, st);
++ out:
++      if (did_lock)
++              di_read_unlock(dentry, AuLock_IR);
++      si_read_unlock(sb);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
++                    int bufsiz)
++{
++      int err;
++      struct super_block *sb;
++      struct dentry *h_dentry;
++
++      err = -EINVAL;
++      h_dentry = au_h_dptr(dentry, bindex);
++      if (unlikely(/* !h_dentry
++                   || !h_dentry->d_inode
++                   || !h_dentry->d_inode->i_op
++                   || */ !h_dentry->d_inode->i_op->readlink))
++              goto out;
++
++      err = security_inode_readlink(h_dentry);
++      if (unlikely(err))
++              goto out;
++
++      sb = dentry->d_sb;
++      if (!au_test_ro(sb, bindex, dentry->d_inode)) {
++              vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
++              fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
++      }
++      err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
++
++ out:
++      return err;
++}
++
++static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
++{
++      int err;
++
++      aufs_read_lock(dentry, AuLock_IR);
++      err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
++      aufs_read_unlock(dentry, AuLock_IR);
++
++      return err;
++}
++
++static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
++{
++      int err;
++      char *buf;
++      mm_segment_t old_fs;
++
++      err = -ENOMEM;
++      buf = __getname();
++      if (unlikely(!buf))
++              goto out;
++
++      aufs_read_lock(dentry, AuLock_IR);
++      old_fs = get_fs();
++      set_fs(KERNEL_DS);
++      err = h_readlink(dentry, au_dbstart(dentry), (char __user *)buf,
++                       PATH_MAX);
++      set_fs(old_fs);
++      aufs_read_unlock(dentry, AuLock_IR);
++
++      if (err >= 0) {
++              buf[err] = 0;
++              /* will be freed by put_link */
++              nd_set_link(nd, buf);
++              return NULL; /* success */
++      }
++      __putname(buf);
++
++ out:
++      path_put(&nd->path);
++      AuTraceErr(err);
++      return ERR_PTR(err);
++}
++
++static void aufs_put_link(struct dentry *dentry __maybe_unused,
++                        struct nameidata *nd, void *cookie __maybe_unused)
++{
++      __putname(nd_get_link(nd));
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void aufs_truncate_range(struct inode *inode __maybe_unused,
++                              loff_t start __maybe_unused,
++                              loff_t end __maybe_unused)
++{
++      AuUnsupport();
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct inode_operations aufs_symlink_iop = {
++      .permission     = aufs_permission,
++      .setattr        = aufs_setattr,
++      .getattr        = aufs_getattr,
++      .readlink       = aufs_readlink,
++      .follow_link    = aufs_follow_link,
++      .put_link       = aufs_put_link
++};
++
++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,
++      .getattr        = aufs_getattr
++};
++
++struct inode_operations aufs_iop = {
++      .permission     = aufs_permission,
++      .setattr        = aufs_setattr,
++      .getattr        = aufs_getattr,
++      .truncate_range = aufs_truncate_range
++};
+diff -Naur a/fs/aufs/i_op_del.c b/fs/aufs/i_op_del.c
+--- a/fs/aufs/i_op_del.c       1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/i_op_del.c       2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,466 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * inode operations (del entry)
++ */
++
++#include "aufs.h"
++
++/*
++ * decide if a new whiteout for @dentry is necessary or not.
++ * when it is necessary, prepare the parent dir for the upper branch whose
++ * branch index is @bcpup for creation. the actual creation of the whiteout will
++ * be done by caller.
++ * return value:
++ * 0: wh is unnecessary
++ * plus: wh is necessary
++ * minus: error
++ */
++int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
++{
++      int need_wh, err;
++      aufs_bindex_t bstart;
++      struct super_block *sb;
++
++      sb = dentry->d_sb;
++      bstart = au_dbstart(dentry);
++      if (*bcpup < 0) {
++              *bcpup = bstart;
++              if (au_test_ro(sb, bstart, dentry->d_inode)) {
++                      err = AuWbrCopyup(au_sbi(sb), dentry);
++                      *bcpup = err;
++                      if (unlikely(err < 0))
++                              goto out;
++              }
++      } else
++              AuDebugOn(bstart < *bcpup
++                        || au_test_ro(sb, *bcpup, dentry->d_inode));
++      AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
++
++      if (*bcpup != bstart) {
++              err = au_cpup_dirs(dentry, *bcpup);
++              if (unlikely(err))
++                      goto out;
++              need_wh = 1;
++      } else {
++              aufs_bindex_t old_bend, new_bend, bdiropq = -1;
++
++              old_bend = au_dbend(dentry);
++              if (isdir) {
++                      bdiropq = au_dbdiropq(dentry);
++                      au_set_dbdiropq(dentry, -1);
++              }
++              need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
++                                       /*nd*/NULL);
++              err = need_wh;
++              if (isdir)
++                      au_set_dbdiropq(dentry, bdiropq);
++              if (unlikely(err < 0))
++                      goto out;
++              new_bend = au_dbend(dentry);
++              if (!need_wh && old_bend != new_bend) {
++                      au_set_h_dptr(dentry, new_bend, NULL);
++                      au_set_dbend(dentry, old_bend);
++              }
++      }
++      AuDbg("need_wh %d\n", need_wh);
++      err = need_wh;
++
++ out:
++      return err;
++}
++
++/*
++ * simple tests for the del-entry operations.
++ * following the checks in vfs, plus the parent-child relationship.
++ */
++int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
++             struct dentry *h_parent, int isdir)
++{
++      int err;
++      umode_t h_mode;
++      struct dentry *h_dentry, *h_latest;
++      struct inode *h_inode;
++
++      h_dentry = au_h_dptr(dentry, bindex);
++      h_inode = h_dentry->d_inode;
++      if (dentry->d_inode) {
++              err = -ENOENT;
++              if (unlikely(!h_inode || !h_inode->i_nlink))
++                      goto out;
++
++              h_mode = h_inode->i_mode;
++              if (!isdir) {
++                      err = -EISDIR;
++                      if (unlikely(S_ISDIR(h_mode)))
++                              goto out;
++              } else if (unlikely(!S_ISDIR(h_mode))) {
++                      err = -ENOTDIR;
++                      goto out;
++              }
++      } else {
++              /* rename(2) case */
++              err = -EIO;
++              if (unlikely(h_inode))
++                      goto out;
++      }
++
++      err = -ENOENT;
++      /* expected parent dir is locked */
++      if (unlikely(h_parent != h_dentry->d_parent))
++              goto out;
++      err = 0;
++
++      /*
++       * rmdir a dir may break the consistency on some filesystem.
++       * let's try heavy test.
++       */
++      err = -EACCES;
++      if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
++              goto out;
++
++      h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
++                                 au_sbr(dentry->d_sb, bindex));
++      err = -EIO;
++      if (IS_ERR(h_latest))
++              goto out;
++      if (h_latest == h_dentry)
++              err = 0;
++      dput(h_latest);
++
++ out:
++      return err;
++}
++
++/*
++ * decide the branch where we operate for @dentry. the branch index will be set
++ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
++ * dir for reverting.
++ * when a new whiteout is necessary, create it.
++ */
++static struct dentry*
++lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
++                  struct au_dtime *dt, struct au_pin *pin)
++{
++      struct dentry *wh_dentry;
++      struct super_block *sb;
++      struct path h_path;
++      int err, need_wh;
++      unsigned int udba;
++      aufs_bindex_t bcpup;
++
++      need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
++      wh_dentry = ERR_PTR(need_wh);
++      if (unlikely(need_wh < 0))
++              goto out;
++
++      sb = dentry->d_sb;
++      udba = au_opt_udba(sb);
++      bcpup = *rbcpup;
++      err = au_pin(pin, dentry, bcpup, udba,
++                   AuPin_DI_LOCKED | AuPin_MNT_WRITE);
++      wh_dentry = ERR_PTR(err);
++      if (unlikely(err))
++              goto out;
++
++      h_path.dentry = au_pinned_h_parent(pin);
++      if (udba != AuOpt_UDBA_NONE
++          && au_dbstart(dentry) == bcpup) {
++              err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
++              wh_dentry = ERR_PTR(err);
++              if (unlikely(err))
++                      goto out_unpin;
++      }
++
++      h_path.mnt = au_sbr_mnt(sb, bcpup);
++      au_dtime_store(dt, au_pinned_parent(pin), &h_path);
++      wh_dentry = NULL;
++      if (!need_wh)
++              goto out; /* success, no need to create whiteout */
++
++      wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
++      if (!IS_ERR(wh_dentry))
++              goto out; /* success */
++      /* returns with the parent is locked and wh_dentry is dget-ed */
++
++ out_unpin:
++      au_unpin(pin);
++ out:
++      return wh_dentry;
++}
++
++/*
++ * when removing a dir, rename it to a unique temporary whiteout-ed name first
++ * in order to be revertible and save time for removing many child whiteouts
++ * under the dir.
++ * returns 1 when there are too many child whiteout and caller should remove
++ * them asynchronously. returns 0 when the number of children is enough small to
++ * remove now or the branch fs is a remote fs.
++ * otherwise return an error.
++ */
++static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
++                         struct au_nhash *whlist, struct inode *dir)
++{
++      int rmdir_later, err, dirwh;
++      struct dentry *h_dentry;
++      struct super_block *sb;
++
++      sb = dentry->d_sb;
++      h_dentry = au_h_dptr(dentry, bindex);
++      err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
++      if (unlikely(err))
++              goto out;
++
++      /* stop monitoring */
++      au_hin_free(au_hi(dentry->d_inode, bindex));
++
++      if (!au_test_fs_remote(h_dentry->d_sb)) {
++              dirwh = au_sbi(sb)->si_dirwh;
++              rmdir_later = (dirwh <= 1);
++              if (!rmdir_later)
++                      rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
++                                                            dirwh);
++              if (rmdir_later)
++                      return rmdir_later;
++      }
++
++      err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
++      if (unlikely(err)) {
++              AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
++                      AuDLNPair(h_dentry), bindex, err);
++              err = 0;
++      }
++
++ out:
++      return err;
++}
++
++/*
++ * final procedure for deleting a entry.
++ * maintain dentry and iattr.
++ */
++static void epilog(struct inode *dir, struct dentry *dentry,
++                 aufs_bindex_t bindex)
++{
++      struct inode *inode;
++
++      inode = dentry->d_inode;
++      d_drop(dentry);
++      inode->i_ctime = dir->i_ctime;
++
++      if (atomic_read(&dentry->d_count) == 1) {
++              au_set_h_dptr(dentry, au_dbstart(dentry), NULL);
++              au_update_dbstart(dentry);
++      }
++      if (au_ibstart(dir) == bindex)
++              au_cpup_attr_timesizes(dir);
++      dir->i_version++;
++}
++
++/*
++ * when an error happened, remove the created whiteout and revert everything.
++ */
++static int do_revert(int err, struct inode *dir, aufs_bindex_t bwh,
++                   struct dentry *wh_dentry, struct dentry *dentry,
++                   struct au_dtime *dt)
++{
++      int rerr;
++      struct path h_path = {
++              .dentry = wh_dentry,
++              .mnt    = au_sbr_mnt(dir->i_sb, bwh)
++      };
++
++      rerr = au_wh_unlink_dentry(au_h_iptr(dir, bwh), &h_path, dentry);
++      if (!rerr) {
++              au_set_dbwh(dentry, bwh);
++              au_dtime_revert(dt);
++              return 0;
++      }
++
++      AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
++              AuDLNPair(dentry), err, rerr);
++      return -EIO;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int aufs_unlink(struct inode *dir, struct dentry *dentry)
++{
++      int err;
++      aufs_bindex_t bwh, bindex, bstart;
++      struct au_dtime dt;
++      struct au_pin pin;
++      struct path h_path;
++      struct inode *inode, *h_dir;
++      struct dentry *parent, *wh_dentry;
++
++      IMustLock(dir);
++      inode = dentry->d_inode;
++      if (unlikely(!inode))
++              return -ENOENT; /* possible? */
++      IMustLock(inode);
++
++      aufs_read_lock(dentry, AuLock_DW);
++      parent = dentry->d_parent; /* dir inode is locked */
++      di_write_lock_parent(parent);
++
++      bstart = au_dbstart(dentry);
++      bwh = au_dbwh(dentry);
++      bindex = -1;
++      wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
++      err = PTR_ERR(wh_dentry);
++      if (IS_ERR(wh_dentry))
++              goto out;
++
++      h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
++      h_path.dentry = au_h_dptr(dentry, bstart);
++      dget(h_path.dentry);
++      if (bindex == bstart) {
++              h_dir = au_pinned_h_dir(&pin);
++              err = vfsub_unlink(h_dir, &h_path, /*force*/0);
++      } else {
++              /* dir inode is locked */
++              h_dir = wh_dentry->d_parent->d_inode;
++              IMustLock(h_dir);
++              err = 0;
++      }
++
++      if (!err) {
++              drop_nlink(inode);
++              epilog(dir, dentry, bindex);
++
++              /* update target timestamps */
++              if (bindex == bstart) {
++                      vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
++                      inode->i_ctime = h_path.dentry->d_inode->i_ctime;
++              } else
++                      /* todo: this timestamp may be reverted later */
++                      inode->i_ctime = h_dir->i_ctime;
++              goto out_unlock; /* success */
++      }
++
++      /* revert */
++      if (wh_dentry) {
++              int rerr;
++
++              rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
++              if (rerr)
++                      err = rerr;
++      }
++
++ out_unlock:
++      au_unpin(&pin);
++      dput(wh_dentry);
++      dput(h_path.dentry);
++ out:
++      di_write_unlock(parent);
++      aufs_read_unlock(dentry, AuLock_DW);
++      return err;
++}
++
++int aufs_rmdir(struct inode *dir, struct dentry *dentry)
++{
++      int err, rmdir_later;
++      aufs_bindex_t bwh, bindex, bstart;
++      struct au_dtime dt;
++      struct au_pin pin;
++      struct inode *inode;
++      struct dentry *parent, *wh_dentry, *h_dentry;
++      struct au_whtmp_rmdir *args;
++
++      IMustLock(dir);
++      inode = dentry->d_inode;
++      err = -ENOENT; /* possible? */
++      if (unlikely(!inode))
++              goto out;
++      IMustLock(inode);
++
++      err = -ENOMEM;
++      args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
++      if (unlikely(!args))
++              goto out;
++
++      aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH);
++      parent = dentry->d_parent; /* dir inode is locked */
++      di_write_lock_parent(parent);
++      err = au_test_empty(dentry, &args->whlist);
++      if (unlikely(err))
++              goto out_args;
++
++      bstart = au_dbstart(dentry);
++      bwh = au_dbwh(dentry);
++      bindex = -1;
++      wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
++      err = PTR_ERR(wh_dentry);
++      if (IS_ERR(wh_dentry))
++              goto out_args;
++
++      h_dentry = au_h_dptr(dentry, bstart);
++      dget(h_dentry);
++      rmdir_later = 0;
++      if (bindex == bstart) {
++              err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
++              if (err > 0) {
++                      rmdir_later = err;
++                      err = 0;
++              }
++      } else {
++              /* stop monitoring */
++              au_hin_free(au_hi(inode, bstart));
++
++              /* dir inode is locked */
++              IMustLock(wh_dentry->d_parent->d_inode);
++              err = 0;
++      }
++
++      if (!err) {
++              clear_nlink(inode);
++              au_set_dbdiropq(dentry, -1);
++              epilog(dir, dentry, bindex);
++
++              if (rmdir_later) {
++                      au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
++                      args = NULL;
++              }
++
++              goto out_unlock; /* success */
++      }
++
++      /* revert */
++      AuLabel(revert);
++      if (wh_dentry) {
++              int rerr;
++
++              rerr = do_revert(err, dir, bwh, wh_dentry, dentry, &dt);
++              if (rerr)
++                      err = rerr;
++      }
++
++ out_unlock:
++      au_unpin(&pin);
++      dput(wh_dentry);
++      dput(h_dentry);
++ out_args:
++      di_write_unlock(parent);
++      aufs_read_unlock(dentry, AuLock_DW);
++      if (args)
++              au_whtmp_rmdir_free(args);
++ out:
++      return err;
++}
+diff -Naur a/fs/aufs/i_op_ren.c b/fs/aufs/i_op_ren.c
+--- a/fs/aufs/i_op_ren.c       1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/i_op_ren.c       2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,942 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * inode operation (rename entry)
++ * todo: this is crazy monster
++ */
++
++#include "aufs.h"
++
++enum { AuSRC, AuDST, AuSrcDst };
++enum { AuPARENT, AuCHILD, AuParentChild };
++
++#define AuRen_ISDIR   1
++#define AuRen_ISSAMEDIR       (1 << 1)
++#define AuRen_WHSRC   (1 << 2)
++#define AuRen_WHDST   (1 << 3)
++#define AuRen_MNT_WRITE       (1 << 4)
++#define AuRen_DT_DSTDIR       (1 << 5)
++#define AuRen_DIROPQ  (1 << 6)
++#define AuRen_CPUP    (1 << 7)
++#define au_ftest_ren(flags, name)     ((flags) & AuRen_##name)
++#define au_fset_ren(flags, name)      { (flags) |= AuRen_##name; }
++#define au_fclr_ren(flags, name)      { (flags) &= ~AuRen_##name; }
++
++struct au_ren_args {
++      struct {
++              struct dentry *dentry, *h_dentry, *parent, *h_parent,
++                      *wh_dentry;
++              struct inode *dir, *inode;
++              struct au_hinode *hdir;
++              struct au_dtime dt[AuParentChild];
++              aufs_bindex_t bstart;
++      } sd[AuSrcDst];
++
++#define src_dentry    sd[AuSRC].dentry
++#define src_dir               sd[AuSRC].dir
++#define src_inode     sd[AuSRC].inode
++#define src_h_dentry  sd[AuSRC].h_dentry
++#define src_parent    sd[AuSRC].parent
++#define src_h_parent  sd[AuSRC].h_parent
++#define src_wh_dentry sd[AuSRC].wh_dentry
++#define src_hdir      sd[AuSRC].hdir
++#define src_h_dir     sd[AuSRC].hdir->hi_inode
++#define src_dt                sd[AuSRC].dt
++#define src_bstart    sd[AuSRC].bstart
++
++#define dst_dentry    sd[AuDST].dentry
++#define dst_dir               sd[AuDST].dir
++#define dst_inode     sd[AuDST].inode
++#define dst_h_dentry  sd[AuDST].h_dentry
++#define dst_parent    sd[AuDST].parent
++#define dst_h_parent  sd[AuDST].h_parent
++#define dst_wh_dentry sd[AuDST].wh_dentry
++#define dst_hdir      sd[AuDST].hdir
++#define dst_h_dir     sd[AuDST].hdir->hi_inode
++#define dst_dt                sd[AuDST].dt
++#define dst_bstart    sd[AuDST].bstart
++
++      struct dentry *h_trap;
++      struct au_branch *br;
++      struct au_hinode *src_hinode;
++      struct path h_path;
++      struct au_nhash whlist;
++      aufs_bindex_t btgt;
++
++      unsigned int flags;
++
++      struct au_whtmp_rmdir *thargs;
++      struct dentry *h_dst;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * functions for reverting.
++ * when an error happened in a single rename systemcall, we should revert
++ * everything as if nothing happend.
++ * we don't need to revert the copied-up/down the parent dir since they are
++ * harmless.
++ */
++
++#define RevertFailure(fmt, args...) do { \
++      AuIOErr("revert failure: " fmt " (%d, %d)\n", \
++              ##args, err, rerr); \
++      err = -EIO; \
++} while (0)
++
++static void au_ren_rev_diropq(int err, struct au_ren_args *a)
++{
++      int rerr;
++
++      au_hin_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
++      rerr = au_diropq_remove(a->src_dentry, a->btgt);
++      au_hin_imtx_unlock(a->src_hinode);
++      if (rerr)
++              RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
++}
++
++
++static void au_ren_rev_rename(int err, struct au_ren_args *a)
++{
++      int rerr;
++
++      a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
++                                     a->br, /*nd*/NULL);
++      rerr = PTR_ERR(a->h_path.dentry);
++      if (IS_ERR(a->h_path.dentry)) {
++              RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
++              return;
++      }
++
++      rerr = vfsub_rename(a->dst_h_dir,
++                          au_h_dptr(a->src_dentry, a->btgt),
++                          a->src_h_dir, &a->h_path);
++      d_drop(a->h_path.dentry);
++      dput(a->h_path.dentry);
++      /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
++      if (rerr)
++              RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
++}
++
++static void au_ren_rev_cpup(int err, struct au_ren_args *a)
++{
++      int rerr;
++
++      a->h_path.dentry = a->dst_h_dentry;
++      rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
++      au_set_h_dptr(a->src_dentry, a->btgt, NULL);
++      au_set_dbstart(a->src_dentry, a->src_bstart);
++      if (rerr)
++              RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
++}
++
++
++static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
++{
++      int rerr;
++
++      a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
++                                     a->br, /*nd*/NULL);
++      rerr = PTR_ERR(a->h_path.dentry);
++      if (IS_ERR(a->h_path.dentry)) {
++              RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
++              return;
++      }
++      if (a->h_path.dentry->d_inode) {
++              d_drop(a->h_path.dentry);
++              dput(a->h_path.dentry);
++              return;
++      }
++
++      rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
++      d_drop(a->h_path.dentry);
++      dput(a->h_path.dentry);
++      if (!rerr) {
++              au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
++              au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
++      } else
++              RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
++}
++
++static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
++{
++      int rerr;
++
++      a->h_path.dentry = a->src_wh_dentry;
++      rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
++      if (rerr)
++              RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
++}
++
++static void au_ren_rev_drop(struct au_ren_args *a)
++{
++      struct dentry *d, *h_d;
++      int i;
++      aufs_bindex_t bend, bindex;
++
++      for (i = 0; i < AuSrcDst; i++) {
++              d = a->sd[i].dentry;
++              d_drop(d);
++              bend = au_dbend(d);
++              for (bindex = au_dbstart(d); bindex <= bend; bindex++) {
++                      h_d = au_h_dptr(d, bindex);
++                      if (h_d)
++                              d_drop(h_d);
++              }
++      }
++
++      au_update_dbstart(a->dst_dentry);
++      if (a->thargs)
++              d_drop(a->h_dst);
++}
++#undef RevertFailure
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * when we have to copyup the renaming entry, do it with the rename-target name
++ * in order to minimize the cost (the later actual rename is unnecessary).
++ * otherwise rename it on the target branch.
++ */
++static int au_ren_or_cpup(struct au_ren_args *a)
++{
++      int err;
++      struct dentry *d;
++
++      d = a->src_dentry;
++      if (au_dbstart(d) == a->btgt) {
++              a->h_path.dentry = a->dst_h_dentry;
++              if (au_ftest_ren(a->flags, DIROPQ)
++                  && au_dbdiropq(d) == a->btgt)
++                      au_fclr_ren(a->flags, DIROPQ);
++              AuDebugOn(au_dbstart(d) != a->btgt);
++              err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
++                                 a->dst_h_dir, &a->h_path);
++      } else {
++              struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
++
++              au_fset_ren(a->flags, CPUP);
++              mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++              au_set_dbstart(d, a->btgt);
++              au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
++              err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
++                                       !AuCpup_DTIME, a->dst_parent);
++              if (unlikely(err)) {
++                      au_set_h_dptr(d, a->btgt, NULL);
++                      au_set_dbstart(d, a->src_bstart);
++              }
++              mutex_unlock(h_mtx);
++      }
++
++      return err;
++}
++
++/* cf. aufs_rmdir() */
++static int au_ren_del_whtmp(struct au_ren_args *a)
++{
++      int err;
++      struct inode *dir;
++
++      dir = a->dst_dir;
++      if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
++                                   au_sbi(dir->i_sb)->si_dirwh)
++          || au_test_fs_remote(a->h_dst->d_sb)) {
++              err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
++              if (unlikely(err))
++                      AuWarn("failed removing whtmp dir %.*s (%d), "
++                             "ignored.\n", AuDLNPair(a->h_dst), err);
++      } else {
++              au_nhash_wh_free(&a->thargs->whlist);
++              a->thargs->whlist = a->whlist;
++              a->whlist.nh_num = 0;
++              au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
++              dput(a->h_dst);
++              a->thargs = NULL;
++      }
++
++      return 0;
++}
++
++/* make it 'opaque' dir. */
++static int au_ren_diropq(struct au_ren_args *a)
++{
++      int err;
++      struct dentry *diropq;
++
++      err = 0;
++      a->src_hinode = au_hi(a->src_inode, a->btgt);
++      au_hin_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
++      diropq = au_diropq_create(a->src_dentry, a->btgt);
++      au_hin_imtx_unlock(a->src_hinode);
++      if (IS_ERR(diropq))
++              err = PTR_ERR(diropq);
++      dput(diropq);
++
++      return err;
++}
++
++static int do_rename(struct au_ren_args *a)
++{
++      int err;
++      struct dentry *d, *h_d;
++
++      /* prepare workqueue args for asynchronous rmdir */
++      h_d = a->dst_h_dentry;
++      if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
++              err = -ENOMEM;
++              a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
++              if (unlikely(!a->thargs))
++                      goto out;
++              a->h_dst = dget(h_d);
++      }
++
++      /* create whiteout for src_dentry */
++      if (au_ftest_ren(a->flags, WHSRC)) {
++              a->src_wh_dentry
++                      = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
++              err = PTR_ERR(a->src_wh_dentry);
++              if (IS_ERR(a->src_wh_dentry))
++                      goto out_thargs;
++      }
++
++      /* lookup whiteout for dentry */
++      if (au_ftest_ren(a->flags, WHDST)) {
++              h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
++                               a->br);
++              err = PTR_ERR(h_d);
++              if (IS_ERR(h_d))
++                      goto out_whsrc;
++              if (!h_d->d_inode)
++                      dput(h_d);
++              else
++                      a->dst_wh_dentry = h_d;
++      }
++
++      /* rename dentry to tmpwh */
++      if (a->thargs) {
++              err = au_whtmp_ren(a->dst_h_dentry, a->br);
++              if (unlikely(err))
++                      goto out_whdst;
++
++              d = a->dst_dentry;
++              au_set_h_dptr(d, a->btgt, NULL);
++              err = au_lkup_neg(d, a->btgt);
++              if (unlikely(err))
++                      goto out_whtmp;
++              a->dst_h_dentry = au_h_dptr(d, a->btgt);
++      }
++
++      /* cpup src */
++      if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
++              struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
++
++              mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++              err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
++                                       !AuCpup_DTIME);
++              mutex_unlock(h_mtx);
++              if (unlikely(err))
++                      goto out_whtmp;
++      }
++
++      /* rename by vfs_rename or cpup */
++      d = a->dst_dentry;
++      if (au_ftest_ren(a->flags, ISDIR)
++          && (a->dst_wh_dentry
++              || au_dbdiropq(d) == a->btgt
++              /* hide the lower to keep xino */
++              || a->btgt < au_dbend(d)
++              || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
++              au_fset_ren(a->flags, DIROPQ);
++      err = au_ren_or_cpup(a);
++      if (unlikely(err))
++              /* leave the copied-up one */
++              goto out_whtmp;
++
++      /* make dir opaque */
++      if (au_ftest_ren(a->flags, DIROPQ)) {
++              err = au_ren_diropq(a);
++              if (unlikely(err))
++                      goto out_rename;
++      }
++
++      /* update target timestamps */
++      AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
++      a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
++      vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
++      a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
++
++      /* remove whiteout for dentry */
++      if (a->dst_wh_dentry) {
++              a->h_path.dentry = a->dst_wh_dentry;
++              err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
++                                        a->dst_dentry);
++              if (unlikely(err))
++                      goto out_diropq;
++      }
++
++      /* remove whtmp */
++      if (a->thargs)
++              au_ren_del_whtmp(a); /* ignore this error */
++
++      err = 0;
++      goto out_success;
++
++ out_diropq:
++      if (au_ftest_ren(a->flags, DIROPQ))
++              au_ren_rev_diropq(err, a);
++ out_rename:
++      if (!au_ftest_ren(a->flags, CPUP))
++              au_ren_rev_rename(err, a);
++      else
++              au_ren_rev_cpup(err, a);
++ out_whtmp:
++      if (a->thargs)
++              au_ren_rev_whtmp(err, a);
++ out_whdst:
++      dput(a->dst_wh_dentry);
++      a->dst_wh_dentry = NULL;
++ out_whsrc:
++      if (a->src_wh_dentry)
++              au_ren_rev_whsrc(err, a);
++      au_ren_rev_drop(a);
++ out_success:
++      dput(a->src_wh_dentry);
++      dput(a->dst_wh_dentry);
++ out_thargs:
++      if (a->thargs) {
++              dput(a->h_dst);
++              au_whtmp_rmdir_free(a->thargs);
++              a->thargs = NULL;
++      }
++ out:
++      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, struct au_nhash *whlist)
++{
++      return au_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,
++ * - 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;
++
++      bstart = au_dbstart(dentry);
++      if (bstart != btgt) {
++              struct au_nhash whlist;
++
++              err = au_nhash_alloc(&whlist, au_sbi(dentry->d_sb)->si_rdhash,
++                                   GFP_NOFS);
++              if (unlikely(err))
++                      goto out;
++              err = au_test_empty(dentry, &whlist);
++              au_nhash_wh_free(&whlist);
++              goto out;
++      }
++
++      if (bstart == au_dbtaildir(dentry))
++              return 0; /* success */
++
++      err = au_test_empty_lower(dentry);
++
++ out:
++      if (err == -ENOTEMPTY) {
++              AuWarn1("renaming dir who has child(ren) on multiple branches,"
++                      " is not supported\n");
++              err = -EXDEV;
++      }
++      return err;
++}
++
++/* side effect: sets whlist and h_dentry */
++static int au_ren_may_dir(struct au_ren_args *a)
++{
++      int err;
++      struct dentry *d;
++
++      d = a->dst_dentry;
++      err = au_nhash_alloc(&a->whlist, au_sbi(d->d_sb)->si_rdhash, GFP_NOFS);
++      if (unlikely(err))
++              goto out;
++
++      err = 0;
++      if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
++              au_set_dbstart(d, a->dst_bstart);
++              err = may_rename_dstdir(d, &a->whlist);
++              au_set_dbstart(d, a->btgt);
++      }
++      a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
++      if (unlikely(err))
++              goto out;
++
++      d = a->src_dentry;
++      a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
++      if (au_ftest_ren(a->flags, ISDIR)) {
++              err = may_rename_srcdir(d, a->btgt);
++              if (unlikely(err)) {
++                      au_nhash_wh_free(&a->whlist);
++                      a->whlist.nh_num = 0;
++              }
++      }
++ out:
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * simple tests for rename.
++ * following the checks in vfs, plus the parent-child relationship.
++ */
++static int au_may_ren(struct au_ren_args *a)
++{
++      int err, isdir;
++      struct inode *h_inode;
++
++      if (a->src_bstart == a->btgt) {
++              err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
++                               au_ftest_ren(a->flags, ISDIR));
++              if (unlikely(err))
++                      goto out;
++              err = -EINVAL;
++              if (unlikely(a->src_h_dentry == a->h_trap))
++                      goto out;
++      }
++
++      err = 0;
++      if (a->dst_bstart != a->btgt)
++              goto out;
++
++      err = -EIO;
++      h_inode = a->dst_h_dentry->d_inode;
++      isdir = !!au_ftest_ren(a->flags, ISDIR);
++      if (!a->dst_dentry->d_inode) {
++              if (unlikely(h_inode))
++                      goto out;
++              err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
++                               isdir);
++      } else {
++              if (unlikely(!h_inode || !h_inode->i_nlink))
++                      goto out;
++              err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
++                               isdir);
++              if (unlikely(err))
++                      goto out;
++              err = -ENOTEMPTY;
++              if (unlikely(a->dst_h_dentry == a->h_trap))
++                      goto out;
++              err = 0;
++      }
++
++ out:
++      if (unlikely(err == -ENOENT || err == -EEXIST))
++              err = -EIO;
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * locking order
++ * (VFS)
++ * - src_dir and dir by lock_rename()
++ * - inode if exitsts
++ * (aufs)
++ * - lock all
++ *   + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
++ *     + si_read_lock
++ *     + di_write_lock2_child()
++ *       + di_write_lock_child()
++ *       + ii_write_lock_child()
++ *       + di_write_lock_child2()
++ *       + ii_write_lock_child2()
++ *     + src_parent and parent
++ *       + di_write_lock_parent()
++ *       + ii_write_lock_parent()
++ *       + di_write_lock_parent2()
++ *       + ii_write_lock_parent2()
++ *   + lower src_dir and dir by vfsub_lock_rename()
++ *   + verify the every relationships between child and parent. if any
++ *     of them failed, unlock all and return -EBUSY.
++ */
++static void au_ren_unlock(struct au_ren_args *a)
++{
++      struct super_block *sb;
++
++      sb = a->dst_dentry->d_sb;
++      if (au_ftest_ren(a->flags, MNT_WRITE))
++              mnt_drop_write(a->br->br_mnt);
++      vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
++                          a->dst_h_parent, a->dst_hdir);
++}
++
++static int au_ren_lock(struct au_ren_args *a)
++{
++      int err;
++      unsigned int udba;
++
++      err = 0;
++      a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
++      a->src_hdir = au_hi(a->src_dir, a->btgt);
++      a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
++      a->dst_hdir = au_hi(a->dst_dir, a->btgt);
++      a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
++                                    a->dst_h_parent, a->dst_hdir);
++      udba = au_opt_udba(a->src_dentry->d_sb);
++      if (au_dbstart(a->src_dentry) == a->btgt)
++              err = au_h_verify(a->src_h_dentry, udba,
++                                a->src_h_parent->d_inode, a->src_h_parent,
++                                a->br);
++      if (!err && au_dbstart(a->dst_dentry) == a->btgt)
++              err = au_h_verify(a->dst_h_dentry, udba,
++                                a->dst_h_parent->d_inode, a->dst_h_parent,
++                                a->br);
++      if (!err) {
++              err = mnt_want_write(a->br->br_mnt);
++              if (unlikely(err))
++                      goto out_unlock;
++              au_fset_ren(a->flags, MNT_WRITE);
++              goto out; /* success */
++      }
++
++      err = au_busy_or_stale();
++
++ out_unlock:
++      au_ren_unlock(a);
++ out:
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void au_ren_refresh_dir(struct au_ren_args *a)
++{
++      struct inode *dir;
++
++      dir = a->dst_dir;
++      dir->i_version++;
++      if (au_ftest_ren(a->flags, ISDIR)) {
++              /* is this updating defined in POSIX? */
++              au_cpup_attr_timesizes(a->src_inode);
++              au_cpup_attr_nlink(dir, /*force*/1);
++              if (a->dst_inode) {
++                      clear_nlink(a->dst_inode);
++                      au_cpup_attr_timesizes(a->dst_inode);
++              }
++      }
++      if (au_ibstart(dir) == a->btgt)
++              au_cpup_attr_timesizes(dir);
++
++      if (au_ftest_ren(a->flags, ISSAMEDIR))
++              return;
++
++      dir = a->src_dir;
++      dir->i_version++;
++      if (au_ftest_ren(a->flags, ISDIR))
++              au_cpup_attr_nlink(dir, /*force*/1);
++      if (au_ibstart(dir) == a->btgt)
++              au_cpup_attr_timesizes(dir);
++}
++
++static void au_ren_refresh(struct au_ren_args *a)
++{
++      aufs_bindex_t bend, bindex;
++      struct dentry *d, *h_d;
++      struct inode *i, *h_i;
++      struct super_block *sb;
++
++      d = a->src_dentry;
++      au_set_dbwh(d, -1);
++      bend = au_dbend(d);
++      for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
++              h_d = au_h_dptr(d, bindex);
++              if (h_d)
++                      au_set_h_dptr(d, bindex, NULL);
++      }
++      au_set_dbend(d, a->btgt);
++
++      sb = d->d_sb;
++      i = a->src_inode;
++      if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
++              return; /* success */
++
++      bend = au_ibend(i);
++      for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
++              h_i = au_h_iptr(i, bindex);
++              if (h_i) {
++                      au_xino_write0(sb, bindex, h_i->i_ino, 0);
++                      /* ignore this error */
++                      au_set_h_iptr(i, bindex, NULL, 0);
++              }
++      }
++      au_set_ibend(i, a->btgt);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* mainly for link(2) and rename(2) */
++int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
++{
++      aufs_bindex_t bdiropq, bwh;
++      struct dentry *parent;
++      struct au_branch *br;
++
++      parent = dentry->d_parent;
++      IMustLock(parent->d_inode); /* dir is locked */
++
++      bdiropq = au_dbdiropq(parent);
++      bwh = au_dbwh(dentry);
++      br = au_sbr(dentry->d_sb, btgt);
++      if (au_br_rdonly(br)
++          || (0 <= bdiropq && bdiropq < btgt)
++          || (0 <= bwh && bwh < btgt))
++              btgt = -1;
++
++      AuDbg("btgt %d\n", btgt);
++      return btgt;
++}
++
++/* sets src_bstart, dst_bstart and btgt */
++static int au_ren_wbr(struct au_ren_args *a)
++{
++      int err;
++      struct au_wr_dir_args wr_dir_args = {
++              /* .force_btgt  = -1, */
++              .flags          = AuWrDir_ADD_ENTRY
++      };
++
++      a->src_bstart = au_dbstart(a->src_dentry);
++      a->dst_bstart = au_dbstart(a->dst_dentry);
++      if (au_ftest_ren(a->flags, ISDIR))
++              au_fset_wrdir(wr_dir_args.flags, ISDIR);
++      wr_dir_args.force_btgt = a->src_bstart;
++      if (a->dst_inode && a->dst_bstart < a->src_bstart)
++              wr_dir_args.force_btgt = a->dst_bstart;
++      wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
++      err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
++      a->btgt = err;
++
++      return err;
++}
++
++static void au_ren_dt(struct au_ren_args *a)
++{
++      a->h_path.dentry = a->src_h_parent;
++      au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
++      if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
++              a->h_path.dentry = a->dst_h_parent;
++              au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
++      }
++
++      au_fclr_ren(a->flags, DT_DSTDIR);
++      if (!au_ftest_ren(a->flags, ISDIR))
++              return;
++
++      a->h_path.dentry = a->src_h_dentry;
++      au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
++      if (a->dst_h_dentry->d_inode) {
++              au_fset_ren(a->flags, DT_DSTDIR);
++              a->h_path.dentry = a->dst_h_dentry;
++              au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
++      }
++}
++
++static void au_ren_rev_dt(int err, struct au_ren_args *a)
++{
++      struct dentry *h_d;
++      struct mutex *h_mtx;
++
++      au_dtime_revert(a->src_dt + AuPARENT);
++      if (!au_ftest_ren(a->flags, ISSAMEDIR))
++              au_dtime_revert(a->dst_dt + AuPARENT);
++
++      if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
++              h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
++              h_mtx = &h_d->d_inode->i_mutex;
++              mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++              au_dtime_revert(a->src_dt + AuCHILD);
++              mutex_unlock(h_mtx);
++
++              if (au_ftest_ren(a->flags, DT_DSTDIR)) {
++                      h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
++                      h_mtx = &h_d->d_inode->i_mutex;
++                      mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
++                      au_dtime_revert(a->dst_dt + AuCHILD);
++                      mutex_unlock(h_mtx);
++              }
++      }
++}
++
++/* ---------------------------------------------------------------------- */
++
++int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
++              struct inode *_dst_dir, struct dentry *_dst_dentry)
++{
++      int err;
++      /* reduce stack space */
++      struct au_ren_args *a;
++
++      IMustLock(_src_dir);
++      IMustLock(_dst_dir);
++
++      err = -ENOMEM;
++      BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
++      a = kzalloc(sizeof(*a), GFP_NOFS);
++      if (unlikely(!a))
++              goto out;
++
++      a->src_dir = _src_dir;
++      a->src_dentry = _src_dentry;
++      a->src_inode = a->src_dentry->d_inode;
++      a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
++      a->dst_dir = _dst_dir;
++      a->dst_dentry = _dst_dentry;
++      a->dst_inode = a->dst_dentry->d_inode;
++      a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
++      if (a->dst_inode) {
++              IMustLock(a->dst_inode);
++              au_igrab(a->dst_inode);
++      }
++
++      err = -ENOTDIR;
++      if (S_ISDIR(a->src_inode->i_mode)) {
++              au_fset_ren(a->flags, ISDIR);
++              if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
++                      goto out_free;
++              aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
++                                        AuLock_DIR | AuLock_FLUSH);
++      } else
++              aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
++                                        AuLock_FLUSH);
++
++      au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
++      di_write_lock_parent(a->dst_parent);
++
++      /* which branch we process */
++      err = au_ren_wbr(a);
++      if (unlikely(err < 0))
++              goto out_unlock;
++      a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
++      a->h_path.mnt = a->br->br_mnt;
++
++      /* are they available to be renamed */
++      err = au_ren_may_dir(a);
++      if (unlikely(err))
++              goto out_unlock;
++
++      /* prepare the writable parent dir on the same branch */
++      if (a->dst_bstart == a->btgt) {
++              au_fset_ren(a->flags, WHDST);
++      } else {
++              err = au_cpup_dirs(a->dst_dentry, a->btgt);
++              if (unlikely(err))
++                      goto out_children;
++      }
++
++      if (a->src_dir != a->dst_dir) {
++              /*
++               * this temporary unlock is safe,
++               * because both dir->i_mutex are locked.
++               */
++              di_write_unlock(a->dst_parent);
++              di_write_lock_parent(a->src_parent);
++              err = au_wr_dir_need_wh(a->src_dentry,
++                                      au_ftest_ren(a->flags, ISDIR),
++                                      &a->btgt);
++              di_write_unlock(a->src_parent);
++              di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
++              au_fclr_ren(a->flags, ISSAMEDIR);
++      } else
++              err = au_wr_dir_need_wh(a->src_dentry,
++                                      au_ftest_ren(a->flags, ISDIR),
++                                      &a->btgt);
++      if (unlikely(err < 0))
++              goto out_children;
++      if (err)
++              au_fset_ren(a->flags, WHSRC);
++
++      /* lock them all */
++      err = au_ren_lock(a);
++      if (unlikely(err))
++              goto out_children;
++
++      if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE)) {
++              err = au_may_ren(a);
++              if (unlikely(err))
++                      goto out_hdir;
++      }
++
++      /* store timestamps to be revertible */
++      au_ren_dt(a);
++
++      /* here we go */
++      err = do_rename(a);
++      if (unlikely(err))
++              goto out_dt;
++
++      /* update dir attributes */
++      au_ren_refresh_dir(a);
++
++      /* dput/iput all lower dentries */
++      au_ren_refresh(a);
++
++      goto out_hdir; /* success */
++
++ out_dt:
++      au_ren_rev_dt(err, a);
++ out_hdir:
++      au_ren_unlock(a);
++ out_children:
++      au_nhash_wh_free(&a->whlist);
++ out_unlock:
++      if (unlikely(err && au_ftest_ren(a->flags, ISDIR))) {
++              au_update_dbstart(a->dst_dentry);
++              d_drop(a->dst_dentry);
++      }
++      if (!err)
++              d_move(a->src_dentry, a->dst_dentry);
++      if (au_ftest_ren(a->flags, ISSAMEDIR))
++              di_write_unlock(a->dst_parent);
++      else
++              di_write_unlock2(a->src_parent, a->dst_parent);
++      aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
++ out_free:
++      iput(a->dst_inode);
++      if (a->thargs)
++              au_whtmp_rmdir_free(a->thargs);
++      kfree(a);
++ out:
++      return err;
++}
+diff -Naur a/fs/aufs/Kconfig b/fs/aufs/Kconfig
+--- a/fs/aufs/Kconfig  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/Kconfig  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,117 @@
++config AUFS_FS
++      tristate "Aufs (Advanced multi layered unification filesystem) support"
++      depends on EXPERIMENTAL
++      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. Introducing many
++      original ideas, approaches and improvements, it becomes totally
++      different from Unionfs while keeping the basic features.
++
++if AUFS_FS
++choice
++      prompt "Maximum number of branches"
++      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 a minor 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 a minor 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 a minor 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 a minor 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 a minor impact to performance.
++endchoice
++
++config AUFS_HINOTIFY
++      bool "Use inotify to detect actions on a branch"
++      depends on INOTIFY
++      help
++      If you want to modify files on branches directly, eg. bypassing aufs,
++      and want aufs to detect the changes of them fully, then enable this
++      option and use 'udba=inotify' mount option.
++      It will have a negative impact to the performance.
++      See detail in aufs.5.
++
++config AUFS_EXPORT
++      bool "NFS-exportable aufs"
++      depends on (AUFS_FS = y && EXPORTFS = y) || (AUFS_FS = m && EXPORTFS)
++      help
++      If you want to export your mounted aufs via NFS, then enable this
++      option. There are several requirements for this configuration.
++      See detail in aufs.5.
++
++config AUFS_SHWH
++      bool "Show whiteouts"
++      help
++      If you want to make the whiteouts in aufs visible, then enable
++      this option and specify 'shwh' mount option. Although it may
++      sounds like philosophy or something, but in technically it
++      simply shows the name of whiteout with keeping its behaviour.
++
++config AUFS_BR_RAMFS
++      bool "Ramfs (initramfs/rootfs) as an aufs branch"
++      help
++      If you want to use ramfs as an aufs branch fs, then enable this
++      option. Generally tmpfs is recommended.
++      Aufs prohibited them to be a branch fs by default, because
++      initramfs becomes unusable after switch_root or something
++      generally. If you sets initramfs as an aufs branch and boot your
++      system by switch_root, you will meet a problem easily since the
++      files in initramfs may be inaccessible.
++      Unless you are going to use ramfs as an aufs branch fs without
++      switch_root or something, leave it N.
++
++config AUFS_DEBUG
++      bool "Debug aufs"
++      help
++      Enable this to compile aufs internal debug code.
++      It will have a negative impact to the performance.
++
++config AUFS_MAGIC_SYSRQ
++      bool
++      depends on AUFS_DEBUG && MAGIC_SYSRQ
++      default y
++      help
++      Automatic configuration for internal use.
++      When aufs supports Magic SysRq, enabled automatically.
++
++config AUFS_BDEV_LOOP
++      bool
++      depends on BLK_DEV_LOOP
++      default y
++      help
++      Automatic configuration for internal use.
++      Convert =[ym] into =y.
++
++config AUFS_INO_T_64
++      bool
++      depends on AUFS_EXPORT
++      depends on 64BIT && !(ALPHA || S390)
++      default y
++      help
++      Automatic configuration for internal use.
++      /* typedef unsigned long/int __kernel_ino_t */
++      /* alpha and s390x are int */
++endif
+diff -Naur a/fs/aufs/loop.c b/fs/aufs/loop.c
+--- a/fs/aufs/loop.c   1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/loop.c   2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,55 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * support for loopback block device as a branch
++ */
++
++#include <linux/loop.h>
++#include "aufs.h"
++
++/*
++ * test if two lower dentries have overlapping branches.
++ */
++int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
++                           struct dentry *h_d2)
++{
++      struct inode *h_inode;
++      struct loop_device *l;
++
++      h_inode = h_d1->d_inode;
++      if (MAJOR(h_inode->i_sb->s_dev) != LOOP_MAJOR)
++              return 0;
++
++      l = h_inode->i_sb->s_bdev->bd_disk->private_data;
++      h_d1 = l->lo_backing_file->f_dentry;
++      /* h_d1 can be local NFS. in this case aufs cannot detect the loop */
++      if (unlikely(h_d1->d_sb == sb))
++              return 1;
++      return !!au_test_subdir(h_d1, h_d2);
++}
++
++/* true if a kernel thread named 'loop[0-9].*' accesses a file */
++int au_test_loopback_kthread(void)
++{
++      const char c = current->comm[4];
++
++      return current->mm == NULL
++             && '0' <= c && c <= '9'
++             && strncmp(current->comm, "loop", 4) == 0;
++}
+diff -Naur a/fs/aufs/loop.h b/fs/aufs/loop.h
+--- a/fs/aufs/loop.h   1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/loop.h   2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,51 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * support for loopback mount as a branch
++ */
++
++#ifndef __AUFS_LOOP_H__
++#define __AUFS_LOOP_H__
++
++#ifdef __KERNEL__
++
++struct dentry;
++struct super_block;
++
++#ifdef CONFIG_AUFS_BDEV_LOOP
++/* loop.c */
++int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
++                           struct dentry *h_d2);
++int au_test_loopback_kthread(void);
++#else
++static inline
++int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1,
++                           struct dentry *h_d2)
++{
++      return 0;
++}
++
++static inline int au_test_loopback_kthread(void)
++{
++      return 0;
++}
++#endif /* BLK_DEV_LOOP */
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_LOOP_H__ */
+diff -Naur a/fs/aufs/magic.mk b/fs/aufs/magic.mk
+--- a/fs/aufs/magic.mk 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/magic.mk 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,52 @@
++
++# defined in ${srctree}/fs/fuse/inode.c
++# tristate
++ifdef CONFIG_FUSE_FS
++ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
++endif
++
++# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
++# tristate
++ifdef CONFIG_OCFS2_FS
++ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
++endif
++
++# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
++# tristate
++ifdef CONFIG_OCFS2_FS_O2CB
++ccflags-y += -DDLMFS_MAGIC=0x76a9f425
++endif
++
++# defined in ${srctree}/fs/ramfs/inode.c
++# always true
++ccflags-y += -DRAMFS_MAGIC=0x858458f6
++
++# defined in ${srctree}/fs/cifs/cifsfs.c
++# tristate
++ifdef CONFIG_CIFS_FS
++ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
++endif
++
++# defined in ${srctree}/fs/xfs/xfs_sb.h
++# tristate
++ifdef CONFIG_XFS_FS
++ccflags-y += -DXFS_SB_MAGIC=0x58465342
++endif
++
++# defined in ${srctree}/fs/configfs/mount.c
++# tristate
++ifdef CONFIG_CONFIGFS_FS
++ccflags-y += -DCONFIGFS_MAGIC=0x62656570
++endif
++
++# defined in ${srctree}/fs/9p/v9fs.h
++# tristate
++ifdef CONFIG_9P_FS
++ccflags-y += -DV9FS_MAGIC=0x01021997
++endif
++
++# defined in ${srctree}/fs/ubifs/ubifs.h
++# tristate
++ifdef CONFIG_UBIFS_FS
++ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
++endif
+diff -Naur a/fs/aufs/Makefile b/fs/aufs/Makefile
+--- a/fs/aufs/Makefile 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/Makefile 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,22 @@
++
++include ${src}/magic.mk
++-include ${src}/priv_def.mk
++
++obj-$(CONFIG_AUFS_FS) += aufs.o
++aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
++      wkq.o vfsub.o dcsub.o \
++      cpup.o whout.o plink.o wbr_policy.o \
++      dinfo.o dentry.o \
++      finfo.o file.o f_op.o \
++      dir.o vdir.o \
++      iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
++      ioctl.o
++
++# all are boolean
++aufs-$(CONFIG_SYSFS) += sysfs.o
++aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
++aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
++aufs-$(CONFIG_AUFS_HINOTIFY) += hinotify.o
++aufs-$(CONFIG_AUFS_EXPORT) += export.o
++aufs-$(CONFIG_AUFS_DEBUG) += debug.o
++aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
+diff -Naur a/fs/aufs/module.c b/fs/aufs/module.c
+--- a/fs/aufs/module.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/module.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,173 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * module global variables and operations
++ */
++
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include "aufs.h"
++
++void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
++{
++      if (new_sz <= nused)
++              return p;
++
++      p = krealloc(p, new_sz, gfp);
++      if (p)
++              memset(p + nused, 0, new_sz - nused);
++      return p;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * aufs caches
++ */
++struct kmem_cache *au_cachep[AuCache_Last];
++static int __init au_cache_init(void)
++{
++      au_cachep[AuCache_DINFO] = AuCache(au_dinfo);
++      if (au_cachep[AuCache_DINFO])
++              au_cachep[AuCache_ICNTNR] = AuCache(au_icntnr);
++      if (au_cachep[AuCache_ICNTNR])
++              au_cachep[AuCache_FINFO] = AuCache(au_finfo);
++      if (au_cachep[AuCache_FINFO])
++              au_cachep[AuCache_VDIR] = AuCache(au_vdir);
++      if (au_cachep[AuCache_VDIR])
++              au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
++      if (au_cachep[AuCache_DEHSTR])
++              return 0;
++
++      return -ENOMEM;
++}
++
++static void au_cache_fin(void)
++{
++      int i;
++      for (i = 0; i < AuCache_Last; i++)
++              if (au_cachep[i]) {
++                      kmem_cache_destroy(au_cachep[i]);
++                      au_cachep[i] = NULL;
++              }
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_dir_roflags;
++
++/*
++ * functions for module interface.
++ */
++MODULE_LICENSE("GPL");
++/* MODULE_LICENSE("GPL v2"); */
++MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
++MODULE_DESCRIPTION(AUFS_NAME
++      " -- Advanced multi layered unification filesystem");
++MODULE_VERSION(AUFS_VERSION);
++
++/* it should be 'byte', but param_set_byte() prints it 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, S_IRUGO);
++
++/* this module parameter has no meaning when SYSFS is disabled */
++int sysaufs_brs = 1;
++MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
++module_param_named(brs, sysaufs_brs, int, S_IRUGO);
++
++/* ---------------------------------------------------------------------- */
++
++static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
++
++int au_seq_path(struct seq_file *seq, struct path *path)
++{
++      return seq_path(seq, path, au_esc_chars);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int __init aufs_init(void)
++{
++      int err, i;
++      char *p;
++
++      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);
++
++      sysaufs_brs_init();
++      au_debug_init();
++
++      err = -EINVAL;
++      if (unlikely(aufs_nwkq <= 0))
++              goto out;
++
++      err = sysaufs_init();
++      if (unlikely(err))
++              goto out;
++      err = au_wkq_init();
++      if (unlikely(err))
++              goto out_sysaufs;
++      err = au_hinotify_init();
++      if (unlikely(err))
++              goto out_wkq;
++      err = au_sysrq_init();
++      if (unlikely(err))
++              goto out_hin;
++      err = au_cache_init();
++      if (unlikely(err))
++              goto out_sysrq;
++      err = register_filesystem(&aufs_fs_type);
++      if (unlikely(err))
++              goto out_cache;
++      pr_info(AUFS_NAME " " AUFS_VERSION "\n");
++      goto out; /* success */
++
++ out_cache:
++      au_cache_fin();
++ out_sysrq:
++      au_sysrq_fin();
++ out_hin:
++      au_hinotify_fin();
++ out_wkq:
++      au_wkq_fin();
++ out_sysaufs:
++      sysaufs_fin();
++ out:
++      return err;
++}
++
++static void __exit aufs_exit(void)
++{
++      unregister_filesystem(&aufs_fs_type);
++      au_cache_fin();
++      au_sysrq_fin();
++      au_hinotify_fin();
++      au_wkq_fin();
++      sysaufs_fin();
++}
++
++module_init(aufs_init);
++module_exit(aufs_exit);
+diff -Naur a/fs/aufs/module.h b/fs/aufs/module.h
+--- a/fs/aufs/module.h 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/module.h 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,78 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * module initialization and module-global
++ */
++
++#ifndef __AUFS_MODULE_H__
++#define __AUFS_MODULE_H__
++
++#ifdef __KERNEL__
++
++#include <linux/slab.h>
++
++struct path;
++struct seq_file;
++
++/* module parameters */
++extern short aufs_nwkq;
++extern int sysaufs_brs;
++
++/* ---------------------------------------------------------------------- */
++
++extern int au_dir_roflags;
++
++void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
++int au_seq_path(struct seq_file *seq, struct path *path);
++
++/* ---------------------------------------------------------------------- */
++
++/* kmem cache */
++enum {
++      AuCache_DINFO,
++      AuCache_ICNTNR,
++      AuCache_FINFO,
++      AuCache_VDIR,
++      AuCache_DEHSTR,
++#ifdef CONFIG_AUFS_HINOTIFY
++      AuCache_HINOTIFY,
++#endif
++      AuCache_Last
++};
++
++#define AuCache(type) KMEM_CACHE(type, SLAB_RECLAIM_ACCOUNT)
++
++extern struct kmem_cache *au_cachep[];
++
++#define AuCacheFuncs(name, index) \
++static inline void *au_cache_alloc_##name(void) \
++{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
++static inline void au_cache_free_##name(void *p) \
++{ kmem_cache_free(au_cachep[AuCache_##index], p); }
++
++AuCacheFuncs(dinfo, DINFO);
++AuCacheFuncs(icntnr, ICNTNR);
++AuCacheFuncs(finfo, FINFO);
++AuCacheFuncs(vdir, VDIR);
++AuCacheFuncs(dehstr, DEHSTR);
++
++/*  ---------------------------------------------------------------------- */
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_MODULE_H__ */
+diff -Naur a/fs/aufs/opts.c b/fs/aufs/opts.c
+--- a/fs/aufs/opts.c   1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/opts.c   2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,1533 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * mount options/flags
++ */
++
++#include <linux/file.h>
++#include <linux/namei.h>
++#include <linux/types.h> /* a distribution requires */
++#include <linux/parser.h>
++#include "aufs.h"
++
++/* ---------------------------------------------------------------------- */
++
++enum {
++      Opt_br,
++      Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
++      Opt_idel, Opt_imod, Opt_ireorder,
++      Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
++      Opt_rdblk_def, Opt_rdhash_def,
++      Opt_xino, Opt_zxino, Opt_noxino,
++      Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
++      Opt_trunc_xino_path, Opt_itrunc_xino,
++      Opt_trunc_xib, Opt_notrunc_xib,
++      Opt_shwh, Opt_noshwh,
++      Opt_plink, Opt_noplink, Opt_list_plink,
++      Opt_udba,
++      /* Opt_lock, Opt_unlock, */
++      Opt_cmd, Opt_cmd_args,
++      Opt_diropq_a, Opt_diropq_w,
++      Opt_warn_perm, Opt_nowarn_perm,
++      Opt_wbr_copyup, Opt_wbr_create,
++      Opt_refrof, Opt_norefrof,
++      Opt_verbose, Opt_noverbose,
++      Opt_sum, Opt_nosum, Opt_wsum,
++      Opt_tail, Opt_ignore, Opt_ignore_silent, 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_xino, "xino=%s"},
++      {Opt_noxino, "noxino"},
++      {Opt_trunc_xino, "trunc_xino"},
++      {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
++      {Opt_notrunc_xino, "notrunc_xino"},
++      {Opt_trunc_xino_path, "trunc_xino=%s"},
++      {Opt_itrunc_xino, "itrunc_xino=%d"},
++      /* {Opt_zxino, "zxino=%s"}, */
++      {Opt_trunc_xib, "trunc_xib"},
++      {Opt_notrunc_xib, "notrunc_xib"},
++
++      {Opt_plink, "plink"},
++      {Opt_noplink, "noplink"},
++#ifdef CONFIG_AUFS_DEBUG
++      {Opt_list_plink, "list_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"},
++
++      /* keep them temporary */
++      {Opt_ignore_silent, "coo=%s"},
++      {Opt_ignore_silent, "nodlgt"},
++      {Opt_ignore_silent, "nodirperm1"},
++      {Opt_ignore_silent, "clean_plink"},
++
++#ifdef CONFIG_AUFS_SHWH
++      {Opt_shwh, "shwh"},
++#endif
++      {Opt_noshwh, "noshwh"},
++
++      {Opt_rendir, "rendir=%d"},
++
++      {Opt_refrof, "refrof"},
++      {Opt_norefrof, "norefrof"},
++
++      {Opt_verbose, "verbose"},
++      {Opt_verbose, "v"},
++      {Opt_noverbose, "noverbose"},
++      {Opt_noverbose, "quiet"},
++      {Opt_noverbose, "q"},
++      {Opt_noverbose, "silent"},
++
++      {Opt_sum, "sum"},
++      {Opt_nosum, "nosum"},
++      {Opt_wsum, "wsum"},
++
++      {Opt_rdcache, "rdcache=%d"},
++      {Opt_rdblk, "rdblk=%d"},
++      {Opt_rdblk_def, "rdblk=def"},
++      {Opt_rdhash, "rdhash=%d"},
++      {Opt_rdhash_def, "rdhash=def"},
++
++      {Opt_wbr_create, "create=%s"},
++      {Opt_wbr_create, "create_policy=%s"},
++      {Opt_wbr_copyup, "cpup=%s"},
++      {Opt_wbr_copyup, "copyup=%s"},
++      {Opt_wbr_copyup, "copyup_policy=%s"},
++
++      /* internal use for the scripts */
++      {Opt_ignore_silent, "si=%s"},
++
++      {Opt_br, "dirs=%s"},
++      {Opt_ignore, "debug=%d"},
++      {Opt_ignore, "delete=whiteout"},
++      {Opt_ignore, "delete=all"},
++      {Opt_ignore, "imap=%s"},
++
++      {Opt_err, NULL}
++};
++
++/* ---------------------------------------------------------------------- */
++
++static const char *au_parser_pattern(int val, struct match_token *token)
++{
++      while (token->pattern) {
++              if (token->token == val)
++                      return token->pattern;
++              token++;
++      }
++      BUG();
++      return "??";
++}
++
++/* ---------------------------------------------------------------------- */
++
++static match_table_t brperms = {
++      {AuBrPerm_RO, AUFS_BRPERM_RO},
++      {AuBrPerm_RR, AUFS_BRPERM_RR},
++      {AuBrPerm_RW, AUFS_BRPERM_RW},
++
++      {AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
++      {AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
++      {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
++
++      {AuBrPerm_ROWH, "nfsro"},
++      {AuBrPerm_RO, NULL}
++};
++
++static int br_perm_val(char *perm)
++{
++      int val;
++      substring_t args[MAX_OPT_ARGS];
++
++      val = match_token(perm, brperms, args);
++      return val;
++}
++
++const char *au_optstr_br_perm(int brperm)
++{
++      return au_parser_pattern(brperm, (void *)brperms);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static match_table_t udbalevel = {
++      {AuOpt_UDBA_REVAL, "reval"},
++      {AuOpt_UDBA_NONE, "none"},
++#ifdef CONFIG_AUFS_HINOTIFY
++      {AuOpt_UDBA_HINOTIFY, "inotify"},
++#endif
++      {-1, NULL}
++};
++
++static int udba_val(char *str)
++{
++      substring_t args[MAX_OPT_ARGS];
++
++      return match_token(str, udbalevel, args);
++}
++
++const char *au_optstr_udba(int udba)
++{
++      return au_parser_pattern(udba, (void *)udbalevel);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static match_table_t au_wbr_create_policy = {
++      {AuWbrCreate_TDP, "tdp"},
++      {AuWbrCreate_TDP, "top-down-parent"},
++      {AuWbrCreate_RR, "rr"},
++      {AuWbrCreate_RR, "round-robin"},
++      {AuWbrCreate_MFS, "mfs"},
++      {AuWbrCreate_MFS, "most-free-space"},
++      {AuWbrCreate_MFSV, "mfs:%d"},
++      {AuWbrCreate_MFSV, "most-free-space:%d"},
++
++      {AuWbrCreate_MFSRR, "mfsrr:%d"},
++      {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
++      {AuWbrCreate_PMFS, "pmfs"},
++      {AuWbrCreate_PMFSV, "pmfs:%d"},
++
++      {-1, NULL}
++};
++
++/*
++ * cf. linux/lib/parser.c and cmdline.c
++ * gave up calling memparse() since it uses simple_strtoull() instead of
++ * strict_...().
++ */
++static int au_match_ull(substring_t *s, unsigned long long *result)
++{
++      int err;
++      unsigned int len;
++      char a[32];
++
++      err = -ERANGE;
++      len = s->to - s->from;
++      if (len + 1 <= sizeof(a)) {
++              memcpy(a, s->from, len);
++              a[len] = '\0';
++              err = strict_strtoull(a, 0, result);
++      }
++      return err;
++}
++
++static int au_wbr_mfs_wmark(substring_t *arg, char *str,
++                          struct au_opt_wbr_create *create)
++{
++      int err;
++      unsigned long long ull;
++
++      err = 0;
++      if (!au_match_ull(arg, &ull))
++              create->mfsrr_watermark = ull;
++      else {
++              AuErr("bad integer in %s\n", str);
++              err = -EINVAL;
++      }
++
++      return err;
++}
++
++static int au_wbr_mfs_sec(substring_t *arg, char *str,
++                        struct au_opt_wbr_create *create)
++{
++      int n, err;
++
++      err = 0;
++      if (!match_int(arg, &n) && 0 <= n)
++              create->mfs_second = n;
++      else {
++              AuErr("bad integer in %s\n", str);
++              err = -EINVAL;
++      }
++
++      return err;
++}
++
++static int au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
++{
++      int err, e;
++      substring_t args[MAX_OPT_ARGS];
++
++      err = match_token(str, au_wbr_create_policy, args);
++      create->wbr_create = err;
++      switch (err) {
++      case AuWbrCreate_MFSRRV:
++              e = au_wbr_mfs_wmark(&args[0], str, create);
++              if (!e)
++                      e = au_wbr_mfs_sec(&args[1], str, create);
++              if (unlikely(e))
++                      err = e;
++              break;
++      case AuWbrCreate_MFSRR:
++              e = au_wbr_mfs_wmark(&args[0], str, create);
++              if (unlikely(e)) {
++                      err = e;
++                      break;
++              }
++              /*FALLTHROUGH*/
++      case AuWbrCreate_MFS:
++      case AuWbrCreate_PMFS:
++              create->mfs_second = AUFS_MFS_SECOND_DEF;
++              break;
++      case AuWbrCreate_MFSV:
++      case AuWbrCreate_PMFSV:
++              e = au_wbr_mfs_sec(&args[0], str, create);
++              if (unlikely(e))
++                      err = e;
++              break;
++      }
++
++      return err;
++}
++
++const char *au_optstr_wbr_create(int wbr_create)
++{
++      return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
++}
++
++static match_table_t au_wbr_copyup_policy = {
++      {AuWbrCopyup_TDP, "tdp"},
++      {AuWbrCopyup_TDP, "top-down-parent"},
++      {AuWbrCopyup_BUP, "bup"},
++      {AuWbrCopyup_BUP, "bottom-up-parent"},
++      {AuWbrCopyup_BU, "bu"},
++      {AuWbrCopyup_BU, "bottom-up"},
++      {-1, NULL}
++};
++
++static int au_wbr_copyup_val(char *str)
++{
++      substring_t args[MAX_OPT_ARGS];
++
++      return match_token(str, au_wbr_copyup_policy, args);
++}
++
++const char *au_optstr_wbr_copyup(int wbr_copyup)
++{
++      return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
++
++static void dump_opts(struct au_opts *opts)
++{
++#ifdef CONFIG_AUFS_DEBUG
++      /* reduce stack space */
++      union {
++              struct au_opt_add *add;
++              struct au_opt_del *del;
++              struct au_opt_mod *mod;
++              struct au_opt_xino *xino;
++              struct au_opt_xino_itrunc *xino_itrunc;
++              struct au_opt_wbr_create *create;
++      } u;
++      struct au_opt *opt;
++
++      opt = opts->opt;
++      while (opt->type != Opt_tail) {
++              switch (opt->type) {
++              case Opt_add:
++                      u.add = &opt->add;
++                      AuDbg("add {b%d, %s, 0x%x, %p}\n",
++                                u.add->bindex, u.add->pathname, u.add->perm,
++                                u.add->path.dentry);
++                      break;
++              case Opt_del:
++              case Opt_idel:
++                      u.del = &opt->del;
++                      AuDbg("del {%s, %p}\n",
++                            u.del->pathname, u.del->h_path.dentry);
++                      break;
++              case Opt_mod:
++              case Opt_imod:
++                      u.mod = &opt->mod;
++                      AuDbg("mod {%s, 0x%x, %p}\n",
++                                u.mod->path, u.mod->perm, u.mod->h_root);
++                      break;
++              case Opt_append:
++                      u.add = &opt->add;
++                      AuDbg("append {b%d, %s, 0x%x, %p}\n",
++                                u.add->bindex, u.add->pathname, u.add->perm,
++                                u.add->path.dentry);
++                      break;
++              case Opt_prepend:
++                      u.add = &opt->add;
++                      AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
++                                u.add->bindex, u.add->pathname, u.add->perm,
++                                u.add->path.dentry);
++                      break;
++              case Opt_dirwh:
++                      AuDbg("dirwh %d\n", opt->dirwh);
++                      break;
++              case Opt_rdcache:
++                      AuDbg("rdcache %d\n", opt->rdcache);
++                      break;
++              case Opt_rdblk:
++                      AuDbg("rdblk %u\n", opt->rdblk);
++                      break;
++              case Opt_rdblk_def:
++                      AuDbg("rdblk_def\n");
++                      break;
++              case Opt_rdhash:
++                      AuDbg("rdhash %u\n", opt->rdhash);
++                      break;
++              case Opt_rdhash_def:
++                      AuDbg("rdhash_def\n");
++                      break;
++              case Opt_xino:
++                      u.xino = &opt->xino;
++                      AuDbg("xino {%s %.*s}\n",
++                                u.xino->path,
++                                AuDLNPair(u.xino->file->f_dentry));
++                      break;
++              case Opt_trunc_xino:
++                      AuLabel(trunc_xino);
++                      break;
++              case Opt_notrunc_xino:
++                      AuLabel(notrunc_xino);
++                      break;
++              case Opt_trunc_xino_path:
++              case Opt_itrunc_xino:
++                      u.xino_itrunc = &opt->xino_itrunc;
++                      AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
++                      break;
++
++              case Opt_noxino:
++                      AuLabel(noxino);
++                      break;
++              case Opt_trunc_xib:
++                      AuLabel(trunc_xib);
++                      break;
++              case Opt_notrunc_xib:
++                      AuLabel(notrunc_xib);
++                      break;
++              case Opt_shwh:
++                      AuLabel(shwh);
++                      break;
++              case Opt_noshwh:
++                      AuLabel(noshwh);
++                      break;
++              case Opt_plink:
++                      AuLabel(plink);
++                      break;
++              case Opt_noplink:
++                      AuLabel(noplink);
++                      break;
++              case Opt_list_plink:
++                      AuLabel(list_plink);
++                      break;
++              case Opt_udba:
++                      AuDbg("udba %d, %s\n",
++                                opt->udba, au_optstr_udba(opt->udba));
++                      break;
++              case Opt_diropq_a:
++                      AuLabel(diropq_a);
++                      break;
++              case Opt_diropq_w:
++                      AuLabel(diropq_w);
++                      break;
++              case Opt_warn_perm:
++                      AuLabel(warn_perm);
++                      break;
++              case Opt_nowarn_perm:
++                      AuLabel(nowarn_perm);
++                      break;
++              case Opt_refrof:
++                      AuLabel(refrof);
++                      break;
++              case Opt_norefrof:
++                      AuLabel(norefrof);
++                      break;
++              case Opt_verbose:
++                      AuLabel(verbose);
++                      break;
++              case Opt_noverbose:
++                      AuLabel(noverbose);
++                      break;
++              case Opt_sum:
++                      AuLabel(sum);
++                      break;
++              case Opt_nosum:
++                      AuLabel(nosum);
++                      break;
++              case Opt_wsum:
++                      AuLabel(wsum);
++                      break;
++              case Opt_wbr_create:
++                      u.create = &opt->wbr_create;
++                      AuDbg("create %d, %s\n", u.create->wbr_create,
++                                au_optstr_wbr_create(u.create->wbr_create));
++                      switch (u.create->wbr_create) {
++                      case AuWbrCreate_MFSV:
++                      case AuWbrCreate_PMFSV:
++                              AuDbg("%d sec\n", u.create->mfs_second);
++                              break;
++                      case AuWbrCreate_MFSRR:
++                              AuDbg("%llu watermark\n",
++                                        u.create->mfsrr_watermark);
++                              break;
++                      case AuWbrCreate_MFSRRV:
++                              AuDbg("%llu watermark, %d sec\n",
++                                        u.create->mfsrr_watermark,
++                                        u.create->mfs_second);
++                              break;
++                      }
++                      break;
++              case Opt_wbr_copyup:
++                      AuDbg("copyup %d, %s\n", opt->wbr_copyup,
++                                au_optstr_wbr_copyup(opt->wbr_copyup));
++                      break;
++              default:
++                      BUG();
++              }
++              opt++;
++      }
++#endif
++}
++
++void au_opts_free(struct au_opts *opts)
++{
++      struct au_opt *opt;
++
++      opt = opts->opt;
++      while (opt->type != Opt_tail) {
++              switch (opt->type) {
++              case Opt_add:
++              case Opt_append:
++              case Opt_prepend:
++                      path_put(&opt->add.path);
++                      break;
++              case Opt_del:
++              case Opt_idel:
++                      path_put(&opt->del.h_path);
++                      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 au_opt *opt, char *opt_str, unsigned long sb_flags,
++                 aufs_bindex_t bindex)
++{
++      int err;
++      struct au_opt_add *add = &opt->add;
++      char *p;
++
++      add->bindex = bindex;
++      add->perm = AuBrPerm_Last;
++      add->pathname = opt_str;
++      p = strchr(opt_str, '=');
++      if (p) {
++              *p++ = 0;
++              if (*p)
++                      add->perm = br_perm_val(p);
++      }
++
++      err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
++      if (!err) {
++              if (!p) {
++                      add->perm = AuBrPerm_RO;
++                      if (au_test_fs_rr(add->path.dentry->d_sb))
++                              add->perm = AuBrPerm_RR;
++                      else if (!bindex && !(sb_flags & MS_RDONLY))
++                              add->perm = AuBrPerm_RW;
++              }
++              opt->type = Opt_add;
++              goto out;
++      }
++      AuErr("lookup failed %s (%d)\n", add->pathname, err);
++      err = -EINVAL;
++
++ out:
++      return err;
++}
++
++static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
++{
++      int err;
++
++      del->pathname = args[0].from;
++      AuDbg("del path %s\n", del->pathname);
++
++      err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
++      if (unlikely(err))
++              AuErr("lookup failed %s (%d)\n", del->pathname, err);
++
++      return err;
++}
++
++#if 0 /* reserved for future use */
++static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
++                            struct au_opt_del *del, substring_t args[])
++{
++      int err;
++      struct dentry *root;
++
++      err = -EINVAL;
++      root = sb->s_root;
++      aufs_read_lock(root, AuLock_FLUSH);
++      if (bindex < 0 || au_sbend(sb) < bindex) {
++              AuErr("out of bounds, %d\n", bindex);
++              goto out;
++      }
++
++      err = 0;
++      del->h_path.dentry = dget(au_h_dptr(root, bindex));
++      del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
++
++ out:
++      aufs_read_unlock(root, !AuLock_IR);
++      return err;
++}
++#endif
++
++static int au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
++{
++      int err;
++      struct path path;
++      char *p;
++
++      err = -EINVAL;
++      mod->path = args[0].from;
++      p = strchr(mod->path, '=');
++      if (unlikely(!p)) {
++              AuErr("no permssion %s\n", args[0].from);
++              goto out;
++      }
++
++      *p++ = 0;
++      err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
++      if (unlikely(err)) {
++              AuErr("lookup failed %s (%d)\n", mod->path, err);
++              goto out;
++      }
++
++      mod->perm = br_perm_val(p);
++      AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
++      mod->h_root = dget(path.dentry);
++      path_put(&path);
++
++ out:
++      return err;
++}
++
++#if 0 /* reserved for future use */
++static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
++                            struct au_opt_mod *mod, substring_t args[])
++{
++      int err;
++      struct dentry *root;
++
++      err = -EINVAL;
++      root = sb->s_root;
++      aufs_read_lock(root, AuLock_FLUSH);
++      if (bindex < 0 || au_sbend(sb) < bindex) {
++              AuErr("out of bounds, %d\n", bindex);
++              goto out;
++      }
++
++      err = 0;
++      mod->perm = br_perm_val(args[1].from);
++      AuDbg("mod path %s, perm 0x%x, %s\n",
++            mod->path, mod->perm, args[1].from);
++      mod->h_root = dget(au_h_dptr(root, bindex));
++
++ out:
++      aufs_read_unlock(root, !AuLock_IR);
++      return err;
++}
++#endif
++
++static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
++                            substring_t args[])
++{
++      int err;
++      struct file *file;
++
++      file = au_xino_create(sb, args[0].from, /*silent*/0);
++      err = PTR_ERR(file);
++      if (IS_ERR(file))
++              goto out;
++
++      err = -EINVAL;
++      if (unlikely(file->f_dentry->d_sb == sb)) {
++              fput(file);
++              AuErr("%s must be outside\n", args[0].from);
++              goto out;
++      }
++
++      err = 0;
++      xino->file = file;
++      xino->path = args[0].from;
++
++ out:
++      return err;
++}
++
++static
++int au_opts_parse_xino_itrunc_path(struct super_block *sb,
++                                 struct au_opt_xino_itrunc *xino_itrunc,
++                                 substring_t args[])
++{
++      int err;
++      aufs_bindex_t bend, bindex;
++      struct path path;
++      struct dentry *root;
++
++      err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
++      if (unlikely(err)) {
++              AuErr("lookup failed %s (%d)\n", args[0].from, err);
++              goto out;
++      }
++
++      xino_itrunc->bindex = -1;
++      root = sb->s_root;
++      aufs_read_lock(root, AuLock_FLUSH);
++      bend = au_sbend(sb);
++      for (bindex = 0; bindex <= bend; bindex++) {
++              if (au_h_dptr(root, bindex) == path.dentry) {
++                      xino_itrunc->bindex = bindex;
++                      break;
++              }
++      }
++      aufs_read_unlock(root, !AuLock_IR);
++      path_put(&path);
++
++      if (unlikely(xino_itrunc->bindex < 0)) {
++              AuErr("no such branch %s\n", args[0].from);
++              err = -EINVAL;
++      }
++
++ out:
++      return err;
++}
++
++/* called without aufs lock */
++int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
++{
++      int err, n, token;
++      aufs_bindex_t bindex;
++      unsigned char skipped;
++      struct dentry *root;
++      struct au_opt *opt, *opt_tail;
++      char *opt_str;
++      /* reduce the stack space */
++      union {
++              struct au_opt_xino_itrunc *xino_itrunc;
++              struct au_opt_wbr_create *create;
++      } u;
++      struct {
++              substring_t args[MAX_OPT_ARGS];
++      } *a;
++
++      err = -ENOMEM;
++      a = kmalloc(sizeof(*a), GFP_NOFS);
++      if (unlikely(!a))
++              goto out;
++
++      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) {
++              err = -EINVAL;
++              skipped = 0;
++              token = match_token(opt_str, options, a->args);
++              switch (token) {
++              case Opt_br:
++                      err = 0;
++                      while (!err && (opt_str = strsep(&a->args[0].from, ":"))
++                             && *opt_str) {
++                              err = opt_add(opt, opt_str, opts->sb_flags,
++                                            bindex++);
++                              if (unlikely(!err && ++opt > opt_tail)) {
++                                      err = -E2BIG;
++                                      break;
++                              }
++                              opt->type = Opt_tail;
++                              skipped = 1;
++                      }
++                      break;
++              case Opt_add:
++                      if (unlikely(match_int(&a->args[0], &n))) {
++                              AuErr("bad integer in %s\n", opt_str);
++                              break;
++                      }
++                      bindex = n;
++                      err = opt_add(opt, a->args[1].from, opts->sb_flags,
++                                    bindex);
++                      if (!err)
++                              opt->type = token;
++                      break;
++              case Opt_append:
++                      err = opt_add(opt, a->args[0].from, opts->sb_flags,
++                                    /*dummy bindex*/1);
++                      if (!err)
++                              opt->type = token;
++                      break;
++              case Opt_prepend:
++                      err = opt_add(opt, a->args[0].from, opts->sb_flags,
++                                    /*bindex*/0);
++                      if (!err)
++                              opt->type = token;
++                      break;
++              case Opt_del:
++                      err = au_opts_parse_del(&opt->del, a->args);
++                      if (!err)
++                              opt->type = token;
++                      break;
++#if 0 /* reserved for future use */
++              case Opt_idel:
++                      del->pathname = "(indexed)";
++                      if (unlikely(match_int(&args[0], &n))) {
++                              AuErr("bad integer in %s\n", opt_str);
++                              break;
++                      }
++                      err = au_opts_parse_idel(sb, n, &opt->del, a->args);
++                      if (!err)
++                              opt->type = token;
++                      break;
++#endif
++              case Opt_mod:
++                      err = au_opts_parse_mod(&opt->mod, a->args);
++                      if (!err)
++                              opt->type = token;
++                      break;
++#ifdef IMOD /* reserved for future use */
++              case Opt_imod:
++                      u.mod->path = "(indexed)";
++                      if (unlikely(match_int(&a->args[0], &n))) {
++                              AuErr("bad integer in %s\n", opt_str);
++                              break;
++                      }
++                      err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
++                      if (!err)
++                              opt->type = token;
++                      break;
++#endif
++              case Opt_xino:
++                      err = au_opts_parse_xino(sb, &opt->xino, a->args);
++                      if (!err)
++                              opt->type = token;
++                      break;
++
++              case Opt_trunc_xino_path:
++                      err = au_opts_parse_xino_itrunc_path
++                              (sb, &opt->xino_itrunc, a->args);
++                      if (!err)
++                              opt->type = token;
++                      break;
++
++              case Opt_itrunc_xino:
++                      u.xino_itrunc = &opt->xino_itrunc;
++                      if (unlikely(match_int(&a->args[0], &n))) {
++                              AuErr("bad integer in %s\n", opt_str);
++                              break;
++                      }
++                      u.xino_itrunc->bindex = n;
++                      aufs_read_lock(root, AuLock_FLUSH);
++                      if (n < 0 || au_sbend(sb) < n) {
++                              AuErr("out of bounds, %d\n", n);
++                              aufs_read_unlock(root, !AuLock_IR);
++                              break;
++                      }
++                      aufs_read_unlock(root, !AuLock_IR);
++                      err = 0;
++                      opt->type = token;
++                      break;
++
++              case Opt_dirwh:
++                      if (unlikely(match_int(&a->args[0], &opt->dirwh)))
++                              break;
++                      err = 0;
++                      opt->type = token;
++                      break;
++
++              case Opt_rdcache:
++                      if (unlikely(match_int(&a->args[0], &opt->rdcache)))
++                              break;
++                      err = 0;
++                      opt->type = token;
++                      break;
++              case Opt_rdblk:
++                      if (unlikely(match_int(&a->args[0], &n)
++                                   || n <= 0
++                                   || n > KMALLOC_MAX_SIZE)) {
++                              AuErr("bad integer in %s\n", opt_str);
++                              break;
++                      }
++                      if (unlikely(n < NAME_MAX)) {
++                              AuErr("rdblk must be larger than %d\n",
++                                    NAME_MAX);
++                              break;
++                      }
++                      opt->rdblk = n;
++                      err = 0;
++                      opt->type = token;
++                      break;
++              case Opt_rdhash:
++                      if (unlikely(match_int(&a->args[0], &n)
++                                   || n <= 0
++                                   || n * sizeof(struct hlist_head)
++                                   > KMALLOC_MAX_SIZE)) {
++                              AuErr("bad integer in %s\n", opt_str);
++                              break;
++                      }
++                      opt->rdhash = n;
++                      err = 0;
++                      opt->type = token;
++                      break;
++
++              case Opt_trunc_xino:
++              case Opt_notrunc_xino:
++              case Opt_noxino:
++              case Opt_trunc_xib:
++              case Opt_notrunc_xib:
++              case Opt_shwh:
++              case Opt_noshwh:
++              case Opt_plink:
++              case Opt_noplink:
++              case Opt_list_plink:
++              case Opt_diropq_a:
++              case Opt_diropq_w:
++              case Opt_warn_perm:
++              case Opt_nowarn_perm:
++              case Opt_refrof:
++              case Opt_norefrof:
++              case Opt_verbose:
++              case Opt_noverbose:
++              case Opt_sum:
++              case Opt_nosum:
++              case Opt_wsum:
++              case Opt_rdblk_def:
++              case Opt_rdhash_def:
++                      err = 0;
++                      opt->type = token;
++                      break;
++
++              case Opt_udba:
++                      opt->udba = udba_val(a->args[0].from);
++                      if (opt->udba >= 0) {
++                              err = 0;
++                              opt->type = token;
++                      } else
++                              AuErr("wrong value, %s\n", opt_str);
++                      break;
++
++              case Opt_wbr_create:
++                      u.create = &opt->wbr_create;
++                      u.create->wbr_create
++                              = au_wbr_create_val(a->args[0].from, u.create);
++                      if (u.create->wbr_create >= 0) {
++                              err = 0;
++                              opt->type = token;
++                      } else
++                              AuErr("wrong value, %s\n", opt_str);
++                      break;
++              case Opt_wbr_copyup:
++                      opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
++                      if (opt->wbr_copyup >= 0) {
++                              err = 0;
++                              opt->type = token;
++                      } else
++                              AuErr("wrong value, %s\n", opt_str);
++                      break;
++
++              case Opt_ignore:
++                      AuWarn("ignored %s\n", opt_str);
++                      /*FALLTHROUGH*/
++              case Opt_ignore_silent:
++                      skipped = 1;
++                      err = 0;
++                      break;
++              case Opt_err:
++                      AuErr("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;
++              }
++      }
++
++      kfree(a);
++      dump_opts(opts);
++      if (unlikely(err))
++              au_opts_free(opts);
++
++ out:
++      return err;
++}
++
++static int au_opt_wbr_create(struct super_block *sb,
++                           struct au_opt_wbr_create *create)
++{
++      int err;
++      struct au_sbinfo *sbinfo;
++
++      err = 1; /* handled */
++      sbinfo = au_sbi(sb);
++      if (sbinfo->si_wbr_create_ops->fin) {
++              err = sbinfo->si_wbr_create_ops->fin(sb);
++              if (!err)
++                      err = 1;
++      }
++
++      sbinfo->si_wbr_create = create->wbr_create;
++      sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
++      switch (create->wbr_create) {
++      case AuWbrCreate_MFSRRV:
++      case AuWbrCreate_MFSRR:
++              sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
++              /*FALLTHROUGH*/
++      case AuWbrCreate_MFS:
++      case AuWbrCreate_MFSV:
++      case AuWbrCreate_PMFS:
++      case AuWbrCreate_PMFSV:
++              sbinfo->si_wbr_mfs.mfs_expire = create->mfs_second * HZ;
++              break;
++      }
++
++      if (sbinfo->si_wbr_create_ops->init)
++              sbinfo->si_wbr_create_ops->init(sb); /* ignore */
++
++      return err;
++}
++
++/*
++ * returns,
++ * plus: processed without an error
++ * zero: unprocessed
++ */
++static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
++                       struct au_opts *opts)
++{
++      int err;
++      struct au_sbinfo *sbinfo;
++
++      err = 1; /* handled */
++      sbinfo = au_sbi(sb);
++      switch (opt->type) {
++      case Opt_udba:
++              sbinfo->si_mntflags &= ~AuOptMask_UDBA;
++              sbinfo->si_mntflags |= opt->udba;
++              opts->given_udba |= opt->udba;
++              break;
++
++      case Opt_plink:
++              au_opt_set(sbinfo->si_mntflags, PLINK);
++              break;
++      case Opt_noplink:
++              if (au_opt_test(sbinfo->si_mntflags, PLINK))
++                      au_plink_put(sb);
++              au_opt_clr(sbinfo->si_mntflags, PLINK);
++              break;
++      case Opt_list_plink:
++              if (au_opt_test(sbinfo->si_mntflags, PLINK))
++                      au_plink_list(sb);
++              break;
++
++      case Opt_diropq_a:
++              au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
++              break;
++      case Opt_diropq_w:
++              au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
++              break;
++
++      case Opt_warn_perm:
++              au_opt_set(sbinfo->si_mntflags, WARN_PERM);
++              break;
++      case Opt_nowarn_perm:
++              au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
++              break;
++
++      case Opt_refrof:
++              au_opt_set(sbinfo->si_mntflags, REFROF);
++              break;
++      case Opt_norefrof:
++              au_opt_clr(sbinfo->si_mntflags, REFROF);
++              break;
++
++      case Opt_verbose:
++              au_opt_set(sbinfo->si_mntflags, VERBOSE);
++              break;
++      case Opt_noverbose:
++              au_opt_clr(sbinfo->si_mntflags, VERBOSE);
++              break;
++
++      case Opt_sum:
++              au_opt_set(sbinfo->si_mntflags, SUM);
++              break;
++      case Opt_wsum:
++              au_opt_clr(sbinfo->si_mntflags, SUM);
++              au_opt_set(sbinfo->si_mntflags, SUM_W);
++      case Opt_nosum:
++              au_opt_clr(sbinfo->si_mntflags, SUM);
++              au_opt_clr(sbinfo->si_mntflags, SUM_W);
++              break;
++
++      case Opt_wbr_create:
++              err = au_opt_wbr_create(sb, &opt->wbr_create);
++              break;
++      case Opt_wbr_copyup:
++              sbinfo->si_wbr_copyup = opt->wbr_copyup;
++              sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
++              break;
++
++      case Opt_dirwh:
++              sbinfo->si_dirwh = opt->dirwh;
++              break;
++
++      case Opt_rdcache:
++              sbinfo->si_rdcache = opt->rdcache * HZ;
++              break;
++      case Opt_rdblk:
++              sbinfo->si_rdblk = opt->rdblk;
++              break;
++      case Opt_rdblk_def:
++              sbinfo->si_rdblk = AUFS_RDBLK_DEF;
++              break;
++      case Opt_rdhash:
++              sbinfo->si_rdhash = opt->rdhash;
++              break;
++      case Opt_rdhash_def:
++              sbinfo->si_rdhash = AUFS_RDHASH_DEF;
++              break;
++
++      case Opt_shwh:
++              au_opt_set(sbinfo->si_mntflags, SHWH);
++              break;
++      case Opt_noshwh:
++              au_opt_clr(sbinfo->si_mntflags, SHWH);
++              break;
++
++      case Opt_trunc_xino:
++              au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
++              break;
++      case Opt_notrunc_xino:
++              au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
++              break;
++
++      case Opt_trunc_xino_path:
++      case Opt_itrunc_xino:
++              err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
++              if (!err)
++                      err = 1;
++              break;
++
++      case Opt_trunc_xib:
++              au_fset_opts(opts->flags, TRUNC_XIB);
++              break;
++      case Opt_notrunc_xib:
++              au_fclr_opts(opts->flags, TRUNC_XIB);
++              break;
++
++      default:
++              err = 0;
++              break;
++      }
++
++      return err;
++}
++
++/*
++ * returns tri-state.
++ * plus: processed without an error
++ * zero: unprocessed
++ * minus: error
++ */
++static int au_opt_br(struct super_block *sb, struct au_opt *opt,
++                   struct au_opts *opts)
++{
++      int err, do_refresh;
++
++      err = 0;
++      switch (opt->type) {
++      case Opt_append:
++              opt->add.bindex = au_sbend(sb) + 1;
++              if (opt->add.bindex < 0)
++                      opt->add.bindex = 0;
++              goto add;
++      case Opt_prepend:
++              opt->add.bindex = 0;
++      add:
++      case Opt_add:
++              err = au_br_add(sb, &opt->add,
++                              au_ftest_opts(opts->flags, REMOUNT));
++              if (!err) {
++                      err = 1;
++                      au_fset_opts(opts->flags, REFRESH_DIR);
++                      if (au_br_whable(opt->add.perm))
++                              au_fset_opts(opts->flags, REFRESH_NONDIR);
++              }
++              break;
++
++      case Opt_del:
++      case Opt_idel:
++              err = au_br_del(sb, &opt->del,
++                              au_ftest_opts(opts->flags, REMOUNT));
++              if (!err) {
++                      err = 1;
++                      au_fset_opts(opts->flags, TRUNC_XIB);
++                      au_fset_opts(opts->flags, REFRESH_DIR);
++                      au_fset_opts(opts->flags, REFRESH_NONDIR);
++              }
++              break;
++
++      case Opt_mod:
++      case Opt_imod:
++              err = au_br_mod(sb, &opt->mod,
++                              au_ftest_opts(opts->flags, REMOUNT),
++                              &do_refresh);
++              if (!err) {
++                      err = 1;
++                      if (do_refresh) {
++                              au_fset_opts(opts->flags, REFRESH_DIR);
++                              au_fset_opts(opts->flags, REFRESH_NONDIR);
++                      }
++              }
++              break;
++      }
++
++      return err;
++}
++
++static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
++                     struct au_opt_xino **opt_xino,
++                     struct au_opts *opts)
++{
++      int err;
++      aufs_bindex_t bend, bindex;
++      struct dentry *root, *parent, *h_root;
++
++      err = 0;
++      switch (opt->type) {
++      case Opt_xino:
++              err = au_xino_set(sb, &opt->xino,
++                                !!au_ftest_opts(opts->flags, REMOUNT));
++              if (unlikely(err))
++                      break;
++
++              *opt_xino = &opt->xino;
++              au_xino_brid_set(sb, -1);
++
++              /* safe d_parent access */
++              parent = opt->xino.file->f_dentry->d_parent;
++              root = sb->s_root;
++              bend = au_sbend(sb);
++              for (bindex = 0; bindex <= bend; bindex++) {
++                      h_root = au_h_dptr(root, bindex);
++                      if (h_root == parent) {
++                              au_xino_brid_set(sb, au_sbr_id(sb, bindex));
++                              break;
++                      }
++              }
++              break;
++
++      case Opt_noxino:
++              au_xino_clr(sb);
++              au_xino_brid_set(sb, -1);
++              *opt_xino = (void *)-1;
++              break;
++      }
++
++      return err;
++}
++
++int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
++                 unsigned int pending)
++{
++      int err;
++      aufs_bindex_t bindex, bend;
++      unsigned char do_plink, skip, do_free;
++      struct au_branch *br;
++      struct au_wbr *wbr;
++      struct dentry *root;
++      struct inode *dir, *h_dir;
++      struct au_sbinfo *sbinfo;
++      struct au_hinode *hdir;
++
++      sbinfo = au_sbi(sb);
++      AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
++
++      if (!(sb_flags & MS_RDONLY)) {
++              if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
++                      AuWarn("first branch should be rw\n");
++              if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
++                      AuWarn("shwh should be used with ro\n");
++      }
++
++      if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HINOTIFY)
++          && !au_opt_test(sbinfo->si_mntflags, XINO))
++              AuWarn("udba=inotify requires xino\n");
++
++      err = 0;
++      root = sb->s_root;
++      dir = sb->s_root->d_inode;
++      do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
++      bend = au_sbend(sb);
++      for (bindex = 0; !err && bindex <= bend; bindex++) {
++              skip = 0;
++              h_dir = au_h_iptr(dir, bindex);
++              br = au_sbr(sb, bindex);
++              do_free = 0;
++
++              wbr = br->br_wbr;
++              if (wbr)
++                      wbr_wh_read_lock(wbr);
++
++              switch (br->br_perm) {
++              case AuBrPerm_RO:
++              case AuBrPerm_ROWH:
++              case AuBrPerm_RR:
++              case AuBrPerm_RRWH:
++                      do_free = !!wbr;
++                      skip = (!wbr
++                              || (!wbr->wbr_whbase
++                                  && !wbr->wbr_plink
++                                  && !wbr->wbr_orph));
++                      break;
++
++              case AuBrPerm_RWNoLinkWH:
++                      /* skip = (!br->br_whbase && !br->br_orph); */
++                      skip = (!wbr || !wbr->wbr_whbase);
++                      if (skip && wbr) {
++                              if (do_plink)
++                                      skip = !!wbr->wbr_plink;
++                              else
++                                      skip = !wbr->wbr_plink;
++                      }
++                      break;
++
++              case AuBrPerm_RW:
++                      /* skip = (br->br_whbase && br->br_ohph); */
++                      skip = (wbr && wbr->wbr_whbase);
++                      if (skip) {
++                              if (do_plink)
++                                      skip = !!wbr->wbr_plink;
++                              else
++                                      skip = !wbr->wbr_plink;
++                      }
++                      break;
++
++              default:
++                      BUG();
++              }
++              if (wbr)
++                      wbr_wh_read_unlock(wbr);
++
++              if (skip)
++                      continue;
++
++              hdir = au_hi(dir, bindex);
++              au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++              if (wbr)
++                      wbr_wh_write_lock(wbr);
++              err = au_wh_init(au_h_dptr(root, bindex), br, sb);
++              if (wbr)
++                      wbr_wh_write_unlock(wbr);
++              au_hin_imtx_unlock(hdir);
++
++              if (!err && do_free) {
++                      kfree(wbr);
++                      br->br_wbr = NULL;
++              }
++      }
++
++      return err;
++}
++
++int au_opts_mount(struct super_block *sb, struct au_opts *opts)
++{
++      int err;
++      unsigned int tmp;
++      aufs_bindex_t bend;
++      struct au_opt *opt;
++      struct au_opt_xino *opt_xino, xino;
++      struct au_sbinfo *sbinfo;
++
++      err = 0;
++      opt_xino = NULL;
++      opt = opts->opt;
++      while (err >= 0 && opt->type != Opt_tail)
++              err = au_opt_simple(sb, opt++, opts);
++      if (err > 0)
++              err = 0;
++      else if (unlikely(err < 0))
++              goto out;
++
++      /* disable xino and udba temporary */
++      sbinfo = au_sbi(sb);
++      tmp = sbinfo->si_mntflags;
++      au_opt_clr(sbinfo->si_mntflags, XINO);
++      au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
++
++      opt = opts->opt;
++      while (err >= 0 && opt->type != Opt_tail)
++              err = au_opt_br(sb, opt++, opts);
++      if (err > 0)
++              err = 0;
++      else if (unlikely(err < 0))
++              goto out;
++
++      bend = au_sbend(sb);
++      if (unlikely(bend < 0)) {
++              err = -EINVAL;
++              AuErr("no branches\n");
++              goto out;
++      }
++
++      if (au_opt_test(tmp, XINO))
++              au_opt_set(sbinfo->si_mntflags, XINO);
++      opt = opts->opt;
++      while (!err && opt->type != Opt_tail)
++              err = au_opt_xino(sb, opt++, &opt_xino, opts);
++      if (unlikely(err))
++              goto out;
++
++      err = au_opts_verify(sb, sb->s_flags, tmp);
++      if (unlikely(err))
++              goto out;
++
++      /* restore xino */
++      if (au_opt_test(tmp, XINO) && !opt_xino) {
++              xino.file = au_xino_def(sb);
++              err = PTR_ERR(xino.file);
++              if (IS_ERR(xino.file))
++                      goto out;
++
++              err = au_xino_set(sb, &xino, /*remount*/0);
++              fput(xino.file);
++              if (unlikely(err))
++                      goto out;
++      }
++
++      /* restore udba */
++      sbinfo->si_mntflags &= ~AuOptMask_UDBA;
++      sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA);
++      if (au_opt_test(tmp, UDBA_HINOTIFY)) {
++              struct inode *dir = sb->s_root->d_inode;
++              au_reset_hinotify(dir,
++                                au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
++      }
++
++ out:
++      return err;
++}
++
++int au_opts_remount(struct super_block *sb, struct au_opts *opts)
++{
++      int err, rerr;
++      struct inode *dir;
++      struct au_opt_xino *opt_xino;
++      struct au_opt *opt;
++      struct au_sbinfo *sbinfo;
++
++      dir = sb->s_root->d_inode;
++      sbinfo = au_sbi(sb);
++      err = 0;
++      opt_xino = NULL;
++      opt = opts->opt;
++      while (err >= 0 && opt->type != Opt_tail) {
++              err = au_opt_simple(sb, opt, opts);
++              if (!err)
++                      err = au_opt_br(sb, opt, opts);
++              if (!err)
++                      err = au_opt_xino(sb, opt, &opt_xino, opts);
++              opt++;
++      }
++      if (err > 0)
++              err = 0;
++      AuTraceErr(err);
++      /* go on even err */
++
++      rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
++      if (unlikely(rerr && !err))
++              err = rerr;
++
++      if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
++              rerr = au_xib_trunc(sb);
++              if (unlikely(rerr && !err))
++                      err = rerr;
++      }
++
++      /* will be handled by the caller */
++      if (!au_ftest_opts(opts->flags, REFRESH_DIR)
++          && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
++              au_fset_opts(opts->flags, REFRESH_DIR);
++
++      AuDbg("status 0x%x\n", opts->flags);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++unsigned int au_opt_udba(struct super_block *sb)
++{
++      return au_mntflags(sb) & AuOptMask_UDBA;
++}
+diff -Naur a/fs/aufs/opts.h b/fs/aufs/opts.h
+--- a/fs/aufs/opts.h   1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/opts.h   2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,196 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * mount options/flags
++ */
++
++#ifndef __AUFS_OPTS_H__
++#define __AUFS_OPTS_H__
++
++#ifdef __KERNEL__
++
++#include <linux/path.h>
++#include <linux/aufs_type.h>
++
++struct file;
++struct super_block;
++
++/* ---------------------------------------------------------------------- */
++
++/* mount flags */
++#define AuOpt_XINO            1               /* external inode number bitmap
++                                                 and translation table */
++#define AuOpt_TRUNC_XINO      (1 << 1)        /* truncate xino files */
++#define AuOpt_UDBA_NONE               (1 << 2)        /* users direct branch access */
++#define AuOpt_UDBA_REVAL      (1 << 3)
++#define AuOpt_UDBA_HINOTIFY   (1 << 4)
++#define AuOpt_SHWH            (1 << 5)        /* show whiteout */
++#define AuOpt_PLINK           (1 << 6)        /* pseudo-link */
++#define AuOpt_DIRPERM1                (1 << 7)        /* unimplemented */
++#define AuOpt_REFROF          (1 << 8)        /* unimplemented */
++#define AuOpt_ALWAYS_DIROPQ   (1 << 9)        /* policy to creating diropq */
++#define AuOpt_SUM             (1 << 10)       /* summation for statfs(2) */
++#define AuOpt_SUM_W           (1 << 11)       /* unimplemented */
++#define AuOpt_WARN_PERM               (1 << 12)       /* warn when add-branch */
++#define AuOpt_VERBOSE         (1 << 13)       /* busy inode when del-branch */
++
++#ifndef CONFIG_AUFS_HINOTIFY
++#undef AuOpt_UDBA_HINOTIFY
++#define AuOpt_UDBA_HINOTIFY   0
++#endif
++#ifndef CONFIG_AUFS_SHWH
++#undef AuOpt_SHWH
++#define AuOpt_SHWH            0
++#endif
++
++#define AuOpt_Def     (AuOpt_XINO \
++                       | AuOpt_UDBA_REVAL \
++                       | AuOpt_PLINK \
++                       /* | AuOpt_DIRPERM1 */ \
++                       | AuOpt_WARN_PERM)
++#define AuOptMask_UDBA        (AuOpt_UDBA_NONE \
++                       | AuOpt_UDBA_REVAL \
++                       | AuOpt_UDBA_HINOTIFY)
++
++#define au_opt_test(flags, name)      (flags & AuOpt_##name)
++#define au_opt_set(flags, name) do { \
++      BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
++      ((flags) |= AuOpt_##name); \
++} while (0)
++#define au_opt_set_udba(flags, name) do { \
++      (flags) &= ~AuOptMask_UDBA; \
++      ((flags) |= AuOpt_##name); \
++} while (0)
++#define au_opt_clr(flags, name)               { ((flags) &= ~AuOpt_##name); }
++
++/* ---------------------------------------------------------------------- */
++
++/* policies to select one among multiple writable branches */
++enum {
++      AuWbrCreate_TDP,        /* top down parent */
++      AuWbrCreate_RR,         /* round robin */
++      AuWbrCreate_MFS,        /* most free space */
++      AuWbrCreate_MFSV,       /* mfs with seconds */
++      AuWbrCreate_MFSRR,      /* mfs then rr */
++      AuWbrCreate_MFSRRV,     /* mfs then rr with seconds */
++      AuWbrCreate_PMFS,       /* parent and mfs */
++      AuWbrCreate_PMFSV,      /* parent and mfs with seconds */
++
++      AuWbrCreate_Def = AuWbrCreate_TDP
++};
++
++enum {
++      AuWbrCopyup_TDP,        /* top down parent */
++      AuWbrCopyup_BUP,        /* bottom up parent */
++      AuWbrCopyup_BU,         /* bottom up */
++
++      AuWbrCopyup_Def = AuWbrCopyup_TDP
++};
++
++/* ---------------------------------------------------------------------- */
++
++struct au_opt_add {
++      aufs_bindex_t   bindex;
++      char            *pathname;
++      int             perm;
++      struct path     path;
++};
++
++struct au_opt_del {
++      char            *pathname;
++      struct path     h_path;
++};
++
++struct au_opt_mod {
++      char            *path;
++      int             perm;
++      struct dentry   *h_root;
++};
++
++struct au_opt_xino {
++      char            *path;
++      struct file     *file;
++};
++
++struct au_opt_xino_itrunc {
++      aufs_bindex_t   bindex;
++};
++
++struct au_opt_wbr_create {
++      int                     wbr_create;
++      int                     mfs_second;
++      unsigned long long      mfsrr_watermark;
++};
++
++struct au_opt {
++      int type;
++      union {
++              struct au_opt_xino      xino;
++              struct au_opt_xino_itrunc xino_itrunc;
++              struct au_opt_add       add;
++              struct au_opt_del       del;
++              struct au_opt_mod       mod;
++              int                     dirwh;
++              int                     rdcache;
++              unsigned int            rdblk;
++              unsigned int            rdhash;
++              int                     udba;
++              struct au_opt_wbr_create wbr_create;
++              int                     wbr_copyup;
++      };
++};
++
++/* opts flags */
++#define AuOpts_REMOUNT                1
++#define AuOpts_REFRESH_DIR    (1 << 1)
++#define AuOpts_REFRESH_NONDIR (1 << 2)
++#define AuOpts_TRUNC_XIB      (1 << 3)
++#define au_ftest_opts(flags, name)    ((flags) & AuOpts_##name)
++#define au_fset_opts(flags, name)     { (flags) |= AuOpts_##name; }
++#define au_fclr_opts(flags, name)     { (flags) &= ~AuOpts_##name; }
++
++struct au_opts {
++      struct au_opt   *opt;
++      int             max_opt;
++
++      unsigned int    given_udba;
++      unsigned int    flags;
++      unsigned long   sb_flags;
++};
++
++/* ---------------------------------------------------------------------- */
++
++const char *au_optstr_br_perm(int brperm);
++const char *au_optstr_udba(int udba);
++const char *au_optstr_wbr_copyup(int wbr_copyup);
++const char *au_optstr_wbr_create(int wbr_create);
++
++void au_opts_free(struct au_opts *opts);
++int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
++int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
++                 unsigned int pending);
++int au_opts_mount(struct super_block *sb, struct au_opts *opts);
++int au_opts_remount(struct super_block *sb, struct au_opts *opts);
++
++unsigned int au_opt_udba(struct super_block *sb);
++
++/* ---------------------------------------------------------------------- */
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_OPTS_H__ */
+diff -Naur a/fs/aufs/plink.c b/fs/aufs/plink.c
+--- a/fs/aufs/plink.c  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/plink.c  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,344 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * pseudo-link
++ */
++
++#include "aufs.h"
++
++/*
++ * during a user process maintains the pseudo-links,
++ * prohibit adding a new plink and branch manipulation.
++ */
++void au_plink_block_maintain(struct super_block *sb)
++{
++      struct au_sbinfo *sbi = au_sbi(sb);
++      /* gave up wake_up_bit() */
++      wait_event(sbi->si_plink_wq, !au_ftest_si(sbi, MAINTAIN_PLINK));
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct pseudo_link {
++      struct list_head list;
++      struct inode *inode;
++};
++
++#ifdef CONFIG_AUFS_DEBUG
++void au_plink_list(struct super_block *sb)
++{
++      struct au_sbinfo *sbinfo;
++      struct list_head *plink_list;
++      struct pseudo_link *plink;
++
++      sbinfo = au_sbi(sb);
++      AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++
++      plink_list = &sbinfo->si_plink.head;
++      spin_lock(&sbinfo->si_plink.spin);
++      list_for_each_entry(plink, plink_list, list)
++              AuDbg("%lu\n", plink->inode->i_ino);
++      spin_unlock(&sbinfo->si_plink.spin);
++}
++#endif
++
++/* is the inode pseudo-linked? */
++int au_plink_test(struct inode *inode)
++{
++      int found;
++      struct au_sbinfo *sbinfo;
++      struct list_head *plink_list;
++      struct pseudo_link *plink;
++
++      sbinfo = au_sbi(inode->i_sb);
++      AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
++
++      found = 0;
++      plink_list = &sbinfo->si_plink.head;
++      spin_lock(&sbinfo->si_plink.spin);
++      list_for_each_entry(plink, plink_list, list)
++              if (plink->inode == inode) {
++                      found = 1;
++                      break;
++              }
++      spin_unlock(&sbinfo->si_plink.spin);
++      return found;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * generate a name for plink.
++ * the file will be stored under AUFS_WH_PLINKDIR.
++ */
++/* 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;
++
++      h_inode = au_h_iptr(inode, bindex);
++      rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
++      return rlen;
++}
++
++/* lookup the plink-ed @inode under the branch at @bindex */
++struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
++{
++      struct dentry *h_dentry, *h_parent;
++      struct au_branch *br;
++      struct inode *h_dir;
++      char a[PLINK_NAME_LEN];
++      struct qstr tgtname = {
++              .name   = a
++      };
++
++      br = au_sbr(inode->i_sb, bindex);
++      h_parent = br->br_wbr->wbr_plink;
++      h_dir = h_parent->d_inode;
++      tgtname.len = plink_name(a, sizeof(a), inode, bindex);
++
++      /* always superio. */
++      mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
++      h_dentry = au_sio_lkup_one(&tgtname, h_parent, br);
++      mutex_unlock(&h_dir->i_mutex);
++      return h_dentry;
++}
++
++/* create a pseudo-link */
++static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
++                    struct dentry *h_dentry, struct au_branch *br)
++{
++      int err;
++      struct path h_path = {
++              .mnt = br->br_mnt
++      };
++      struct inode *h_dir;
++
++      h_dir = h_parent->d_inode;
++ again:
++      h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
++      err = PTR_ERR(h_path.dentry);
++      if (IS_ERR(h_path.dentry))
++              goto out;
++
++      err = 0;
++      /* wh.plink dir is not monitored */
++      if (h_path.dentry->d_inode
++          && h_path.dentry->d_inode != h_dentry->d_inode) {
++              err = vfsub_unlink(h_dir, &h_path, /*force*/0);
++              dput(h_path.dentry);
++              h_path.dentry = NULL;
++              if (!err)
++                      goto again;
++      }
++      if (!err && !h_path.dentry->d_inode)
++              err = vfsub_link(h_dentry, h_dir, &h_path);
++      dput(h_path.dentry);
++
++ out:
++      return err;
++}
++
++struct do_whplink_args {
++      int *errp;
++      struct qstr *tgt;
++      struct dentry *h_parent;
++      struct dentry *h_dentry;
++      struct au_branch *br;
++};
++
++static void call_do_whplink(void *args)
++{
++      struct do_whplink_args *a = args;
++      *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
++}
++
++static int whplink(struct dentry *h_dentry, struct inode *inode,
++                 aufs_bindex_t bindex, struct au_branch *br)
++{
++      int err, wkq_err;
++      struct au_wbr *wbr;
++      struct dentry *h_parent;
++      struct inode *h_dir;
++      char a[PLINK_NAME_LEN];
++      struct qstr tgtname = {
++              .name = a
++      };
++
++      wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
++      h_parent = wbr->wbr_plink;
++      h_dir = h_parent->d_inode;
++      tgtname.len = plink_name(a, sizeof(a), inode, bindex);
++
++      /* always superio. */
++      mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
++      if (!au_test_wkq(current)) {
++              struct do_whplink_args args = {
++                      .errp           = &err,
++                      .tgt            = &tgtname,
++                      .h_parent       = h_parent,
++                      .h_dentry       = h_dentry,
++                      .br             = br
++              };
++              wkq_err = au_wkq_wait(call_do_whplink, &args);
++              if (unlikely(wkq_err))
++                      err = wkq_err;
++      } else
++              err = do_whplink(&tgtname, h_parent, h_dentry, br);
++      mutex_unlock(&h_dir->i_mutex);
++
++      return err;
++}
++
++/* free a single plink */
++static void do_put_plink(struct pseudo_link *plink, int do_del)
++{
++      iput(plink->inode);
++      if (do_del)
++              list_del(&plink->list);
++      kfree(plink);
++}
++
++/*
++ * create a new pseudo-link for @h_dentry on @bindex.
++ * the linked inode is held in aufs @inode.
++ */
++void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
++                   struct dentry *h_dentry)
++{
++      struct super_block *sb;
++      struct au_sbinfo *sbinfo;
++      struct list_head *plink_list;
++      struct pseudo_link *plink;
++      int found, err, cnt;
++
++      sb = inode->i_sb;
++      sbinfo = au_sbi(sb);
++      AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++
++      err = 0;
++      cnt = 0;
++      found = 0;
++      plink_list = &sbinfo->si_plink.head;
++      spin_lock(&sbinfo->si_plink.spin);
++      list_for_each_entry(plink, plink_list, list) {
++              cnt++;
++              if (plink->inode == inode) {
++                      found = 1;
++                      break;
++              }
++      }
++      if (found) {
++              spin_unlock(&sbinfo->si_plink.spin);
++              return;
++      }
++
++      plink = NULL;
++      if (!found) {
++              plink = kmalloc(sizeof(*plink), GFP_ATOMIC);
++              if (plink) {
++                      plink->inode = au_igrab(inode);
++                      list_add(&plink->list, plink_list);
++                      cnt++;
++              } else
++                      err = -ENOMEM;
++      }
++      spin_unlock(&sbinfo->si_plink.spin);
++
++      if (!err) {
++              au_plink_block_maintain(sb);
++              err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
++      }
++
++      if (unlikely(cnt > AUFS_PLINK_WARN))
++              AuWarn1("unexpectedly many pseudo links, %d\n", cnt);
++      if (unlikely(err)) {
++              AuWarn("err %d, damaged pseudo link.\n", err);
++              if (!found && plink)
++                      do_put_plink(plink, /*do_del*/1);
++      }
++}
++
++/* free all plinks */
++void au_plink_put(struct super_block *sb)
++{
++      struct au_sbinfo *sbinfo;
++      struct list_head *plink_list;
++      struct pseudo_link *plink, *tmp;
++
++      sbinfo = au_sbi(sb);
++      AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++
++      plink_list = &sbinfo->si_plink.head;
++      /* no spin_lock since sbinfo is write-locked */
++      list_for_each_entry_safe(plink, tmp, plink_list, list)
++              do_put_plink(plink, 0);
++      INIT_LIST_HEAD(plink_list);
++}
++
++/* free the plinks on a branch specified by @br_id */
++void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
++{
++      struct au_sbinfo *sbinfo;
++      struct list_head *plink_list;
++      struct pseudo_link *plink, *tmp;
++      struct inode *inode;
++      aufs_bindex_t bstart, bend, bindex;
++      unsigned char do_put;
++
++      sbinfo = au_sbi(sb);
++      AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
++
++      plink_list = &sbinfo->si_plink.head;
++      /* no spin_lock since sbinfo is write-locked */
++      list_for_each_entry_safe(plink, tmp, plink_list, list) {
++              do_put = 0;
++              inode = au_igrab(plink->inode);
++              ii_write_lock_child(inode);
++              bstart = au_ibstart(inode);
++              bend = au_ibend(inode);
++              if (bstart >= 0) {
++                      for (bindex = bstart; bindex <= bend; bindex++) {
++                              if (!au_h_iptr(inode, bindex)
++                                  || au_ii_br_id(inode, bindex) != br_id)
++                                      continue;
++                              au_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(inode, bindex)) {
++                                      do_put = 0;
++                                      break;
++                              }
++                      if (do_put)
++                              do_put_plink(plink, 1);
++              }
++              ii_write_unlock(inode);
++              iput(inode);
++      }
++}
+diff -Naur a/fs/aufs/rwsem.h b/fs/aufs/rwsem.h
+--- a/fs/aufs/rwsem.h  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/rwsem.h  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,61 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * simple read-write semaphore wrappers
++ */
++
++#ifndef __AUFS_RWSEM_H__
++#define __AUFS_RWSEM_H__
++
++#ifdef __KERNEL__
++
++#include <linux/rwsem.h>
++
++#define au_rwsem_destroy(rw)  AuDebugOn(rwsem_is_locked(rw))
++#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->wait_list))
++
++#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
++static inline void prefix##_read_lock(param) \
++{ down_read(rwsem); } \
++static inline void prefix##_write_lock(param) \
++{ down_write(rwsem); } \
++static inline int prefix##_read_trylock(param) \
++{ return down_read_trylock(rwsem); } \
++static inline int prefix##_write_trylock(param) \
++{ return down_write_trylock(rwsem); }
++/* why is not _nested version defined */
++/* static inline void prefix##_read_trylock_nested(param, lsc)
++{ down_write_trylock_nested(rwsem, lsc)); }
++static inline void prefix##_write_trylock_nestd(param, lsc)
++{ down_write_trylock_nested(rwsem, lsc); } */
++
++#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
++static inline void prefix##_read_unlock(param) \
++{ up_read(rwsem); } \
++static inline void prefix##_write_unlock(param) \
++{ up_write(rwsem); } \
++static inline void prefix##_downgrade_lock(param) \
++{ downgrade_write(rwsem); }
++
++#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
++      AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
++      AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_RWSEM_H__ */
+diff -Naur a/fs/aufs/sbinfo.c b/fs/aufs/sbinfo.c
+--- a/fs/aufs/sbinfo.c 1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/sbinfo.c 2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,203 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * superblock private data
++ */
++
++#include "aufs.h"
++
++/*
++ * they are necessary regardless sysfs is disabled.
++ */
++void au_si_free(struct kobject *kobj)
++{
++      struct au_sbinfo *sbinfo;
++      struct super_block *sb;
++
++      sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
++      AuDebugOn(!list_empty(&sbinfo->si_plink.head));
++
++      sb = sbinfo->si_sb;
++      si_write_lock(sb);
++      au_xino_clr(sb);
++      au_br_free(sbinfo);
++      kfree(sbinfo->si_branch);
++      mutex_destroy(&sbinfo->si_xib_mtx);
++      si_write_unlock(sb);
++      au_rwsem_destroy(&sbinfo->si_rwsem);
++
++      kfree(sbinfo);
++}
++
++int au_si_alloc(struct super_block *sb)
++{
++      int err;
++      struct au_sbinfo *sbinfo;
++
++      err = -ENOMEM;
++      sbinfo = kmalloc(sizeof(*sbinfo), GFP_NOFS);
++      if (unlikely(!sbinfo))
++              goto out;
++
++      /* will be reallocated separately */
++      sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
++      if (unlikely(!sbinfo->si_branch))
++              goto out_sbinfo;
++
++      memset(&sbinfo->si_kobj, 0, sizeof(sbinfo->si_kobj));
++      err = sysaufs_si_init(sbinfo);
++      if (unlikely(err))
++              goto out_br;
++
++      au_nwt_init(&sbinfo->si_nowait);
++      init_rwsem(&sbinfo->si_rwsem);
++      down_write(&sbinfo->si_rwsem);
++      sbinfo->si_generation = 0;
++      sbinfo->au_si_status = 0;
++      sbinfo->si_bend = -1;
++      sbinfo->si_last_br_id = 0;
++
++      sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
++      sbinfo->si_wbr_create = AuWbrCreate_Def;
++      sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + AuWbrCopyup_Def;
++      sbinfo->si_wbr_create_ops = au_wbr_create_ops + AuWbrCreate_Def;
++
++      sbinfo->si_mntflags = AuOpt_Def;
++
++      sbinfo->si_xread = NULL;
++      sbinfo->si_xwrite = NULL;
++      sbinfo->si_xib = NULL;
++      mutex_init(&sbinfo->si_xib_mtx);
++      sbinfo->si_xib_buf = NULL;
++      sbinfo->si_xino_brid = -1;
++      /* leave si_xib_last_pindex and si_xib_next_bit */
++
++      sbinfo->si_rdcache = AUFS_RDCACHE_DEF * HZ;
++      sbinfo->si_rdblk = AUFS_RDBLK_DEF;
++      sbinfo->si_rdhash = AUFS_RDHASH_DEF;
++      sbinfo->si_dirwh = AUFS_DIRWH_DEF;
++
++      au_spl_init(&sbinfo->si_plink);
++      init_waitqueue_head(&sbinfo->si_plink_wq);
++
++      /* leave other members for sysaufs and si_mnt. */
++      sbinfo->si_sb = sb;
++      sb->s_fs_info = sbinfo;
++      au_debug_sbinfo_init(sbinfo);
++      return 0; /* success */
++
++ out_br:
++      kfree(sbinfo->si_branch);
++ out_sbinfo:
++      kfree(sbinfo);
++ out:
++      return err;
++}
++
++int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
++{
++      int err, sz;
++      struct au_branch **brp;
++
++      err = -ENOMEM;
++      sz = sizeof(*brp) * (sbinfo->si_bend + 1);
++      if (unlikely(!sz))
++              sz = sizeof(*brp);
++      brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
++      if (brp) {
++              sbinfo->si_branch = brp;
++              err = 0;
++      }
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++unsigned int au_sigen_inc(struct super_block *sb)
++{
++      unsigned int gen;
++
++      gen = ++au_sbi(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;
++}
++
++aufs_bindex_t au_new_br_id(struct super_block *sb)
++{
++      aufs_bindex_t br_id;
++      int i;
++      struct au_sbinfo *sbinfo;
++
++      sbinfo = au_sbi(sb);
++      for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
++              br_id = ++sbinfo->si_last_br_id;
++              if (br_id && au_br_index(sb, br_id) < 0)
++                      return br_id;
++      }
++
++      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, flags);
++      if (au_ftest_lock(flags, DW))
++              di_write_lock_child(dentry);
++      else
++              di_read_lock_child(dentry, flags);
++}
++
++void aufs_read_unlock(struct dentry *dentry, int flags)
++{
++      if (au_ftest_lock(flags, DW))
++              di_write_unlock(dentry);
++      else
++              di_read_unlock(dentry, flags);
++      si_read_unlock(dentry->d_sb);
++}
++
++void aufs_write_lock(struct dentry *dentry)
++{
++      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);
++}
++
++void aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
++{
++      si_read_lock(d1->d_sb, flags);
++      di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
++}
++
++void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
++{
++      di_write_unlock2(d1, d2);
++      si_read_unlock(d1->d_sb);
++}
+diff -Naur a/fs/aufs/spl.h b/fs/aufs/spl.h
+--- a/fs/aufs/spl.h    1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/spl.h    2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,57 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * simple list protected by a spinlock
++ */
++
++#ifndef __AUFS_SPL_H__
++#define __AUFS_SPL_H__
++
++#ifdef __KERNEL__
++
++#include <linux/spinlock.h>
++#include <linux/list.h>
++
++struct au_splhead {
++      spinlock_t              spin;
++      struct list_head        head;
++};
++
++static inline void au_spl_init(struct au_splhead *spl)
++{
++      spin_lock_init(&spl->spin);
++      INIT_LIST_HEAD(&spl->head);
++}
++
++static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
++{
++      spin_lock(&spl->spin);
++      list_add(list, &spl->head);
++      spin_unlock(&spl->spin);
++}
++
++static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
++{
++      spin_lock(&spl->spin);
++      list_del(list);
++      spin_unlock(&spl->spin);
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_SPL_H__ */
+diff -Naur a/fs/aufs/super.c b/fs/aufs/super.c
+--- a/fs/aufs/super.c  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/super.c  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,870 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * mount and super_block operations
++ */
++
++#include <linux/buffer_head.h>
++#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 __maybe_unused)
++{
++      struct au_icntnr *c;
++
++      c = au_cache_alloc_icntnr();
++      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)
++{
++      au_iinfo_fin(inode);
++      au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
++}
++
++struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
++{
++      struct inode *inode;
++      int err;
++
++      inode = iget_locked(sb, ino);
++      if (unlikely(!inode)) {
++              inode = ERR_PTR(-ENOMEM);
++              goto out;
++      }
++      if (!(inode->i_state & I_NEW))
++              goto out;
++
++      err = au_xigen_new(inode);
++      if (!err)
++              err = au_iinfo_init(inode);
++      if (!err)
++              inode->i_version++;
++      else {
++              iget_failed(inode);
++              inode = ERR_PTR(err);
++      }
++
++ out:
++      /* never return NULL */
++      AuDebugOn(!inode);
++      AuTraceErrPtr(inode);
++      return inode;
++}
++
++/* lock free root dinfo */
++static int au_show_brs(struct seq_file *seq, struct super_block *sb)
++{
++      int err;
++      aufs_bindex_t bindex, bend;
++      struct path path;
++      struct au_hdentry *hd;
++      struct au_branch *br;
++
++      err = 0;
++      bend = au_sbend(sb);
++      hd = au_di(sb->s_root)->di_hdentry;
++      for (bindex = 0; !err && bindex <= bend; bindex++) {
++              br = au_sbr(sb, bindex);
++              path.mnt = br->br_mnt;
++              path.dentry = hd[bindex].hd_dentry;
++              err = au_seq_path(seq, &path);
++              if (err > 0)
++                      err = seq_printf(seq, "=%s",
++                                       au_optstr_br_perm(br->br_perm));
++              if (!err && bindex != bend)
++                      err = seq_putc(seq, ':');
++      }
++
++      return err;
++}
++
++static void au_show_wbr_create(struct seq_file *m, int v,
++                             struct au_sbinfo *sbinfo)
++{
++      const char *pat;
++
++      seq_printf(m, ",create=");
++      pat = au_optstr_wbr_create(v);
++      switch (v) {
++      case AuWbrCreate_TDP:
++      case AuWbrCreate_RR:
++      case AuWbrCreate_MFS:
++      case AuWbrCreate_PMFS:
++              seq_printf(m, pat);
++              break;
++      case AuWbrCreate_MFSV:
++              seq_printf(m, /*pat*/"mfs:%lu",
++                         sbinfo->si_wbr_mfs.mfs_expire / HZ);
++              break;
++      case AuWbrCreate_PMFSV:
++              seq_printf(m, /*pat*/"pmfs:%lu",
++                         sbinfo->si_wbr_mfs.mfs_expire / HZ);
++              break;
++      case AuWbrCreate_MFSRR:
++              seq_printf(m, /*pat*/"mfsrr:%llu",
++                         sbinfo->si_wbr_mfs.mfsrr_watermark);
++              break;
++      case AuWbrCreate_MFSRRV:
++              seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
++                         sbinfo->si_wbr_mfs.mfsrr_watermark,
++                         sbinfo->si_wbr_mfs.mfs_expire / HZ);
++              break;
++      }
++}
++
++static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
++{
++#ifdef CONFIG_SYSFS
++      return 0;
++#else
++      int err;
++      const int len = sizeof(AUFS_XINO_FNAME) - 1;
++      aufs_bindex_t bindex, brid;
++      struct super_block *sb;
++      struct qstr *name;
++      struct file *f;
++      struct dentry *d, *h_root;
++
++      err = 0;
++      sb = mnt->mnt_sb;
++      f = au_sbi(sb)->si_xib;
++      if (!f)
++              goto out;
++
++      /* stop printing the default xino path on the first writable branch */
++      h_root = NULL;
++      brid = au_xino_brid(sb);
++      if (brid >= 0) {
++              bindex = au_br_index(sb, brid);
++              h_root = au_di(sb->s_root)->di_hdentry[0 + bindex].hd_dentry;
++      }
++      d = f->f_dentry;
++      name = &d->d_name;
++      /* safe ->d_parent because the file is unlinked */
++      if (d->d_parent == h_root
++          && name->len == len
++          && !memcmp(name->name, AUFS_XINO_FNAME, len))
++              goto out;
++
++      seq_puts(seq, ",xino=");
++      err = au_xino_path(seq, f);
++
++ out:
++      return err;
++#endif
++}
++
++/* seq_file will re-call me in case of too long string */
++static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
++{
++      int err, n;
++      unsigned int mnt_flags, v;
++      struct super_block *sb;
++      struct au_sbinfo *sbinfo;
++
++#define AuBool(name, str) do { \
++      v = au_opt_test(mnt_flags, name); \
++      if (v != au_opt_test(AuOpt_Def, name)) \
++              seq_printf(m, ",%s" #str, v ? "" : "no"); \
++} while (0)
++
++#define AuStr(name, str) do { \
++      v = mnt_flags & AuOptMask_##name; \
++      if (v != (AuOpt_Def & AuOptMask_##name)) \
++              seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
++} while (0)
++
++#define AuUInt(name, str, val) do { \
++      if (val != AUFS_##name##_DEF) \
++              seq_printf(m, "," #str "=%u", val); \
++} while (0)
++
++      /* lock free root dinfo */
++      sb = mnt->mnt_sb;
++      si_noflush_read_lock(sb);
++      sbinfo = au_sbi(sb);
++      seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
++
++      mnt_flags = au_mntflags(sb);
++      if (au_opt_test(mnt_flags, XINO)) {
++              err = au_show_xino(m, mnt);
++              if (unlikely(err))
++                      goto out;
++      } else
++              seq_puts(m, ",noxino");
++
++      AuBool(TRUNC_XINO, trunc_xino);
++      AuStr(UDBA, udba);
++      AuBool(SHWH, shwh);
++      AuBool(PLINK, plink);
++      /* AuBool(DIRPERM1, dirperm1); */
++      /* AuBool(REFROF, refrof); */
++
++      v = sbinfo->si_wbr_create;
++      if (v != AuWbrCreate_Def)
++              au_show_wbr_create(m, v, sbinfo);
++
++      v = sbinfo->si_wbr_copyup;
++      if (v != AuWbrCopyup_Def)
++              seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
++
++      v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
++      if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
++              seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
++
++      AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
++
++      n = sbinfo->si_rdcache / HZ;
++      AuUInt(RDCACHE, rdcache, n);
++
++      AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
++      AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
++
++      AuBool(SUM, sum);
++      /* AuBool(SUM_W, wsum); */
++      AuBool(WARN_PERM, warn_perm);
++      AuBool(VERBOSE, verbose);
++
++ out:
++      /* be sure to print "br:" last */
++      if (!sysaufs_brs) {
++              seq_puts(m, ",br:");
++              au_show_brs(m, sb);
++      }
++      si_read_unlock(sb);
++      return 0;
++
++#undef Deleted
++#undef AuBool
++#undef AuStr
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* sum mode which returns the summation for statfs(2) */
++
++static u64 au_add_till_max(u64 a, u64 b)
++{
++      u64 old;
++
++      old = a;
++      a += b;
++      if (old < a)
++              return a;
++      return ULLONG_MAX;
++}
++
++static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
++{
++      int err;
++      u64 blocks, bfree, bavail, files, ffree;
++      aufs_bindex_t bend, bindex, i;
++      unsigned char shared;
++      struct vfsmount *h_mnt;
++      struct super_block *h_sb;
++
++      blocks = 0;
++      bfree = 0;
++      bavail = 0;
++      files = 0;
++      ffree = 0;
++
++      err = 0;
++      bend = au_sbend(sb);
++      for (bindex = bend; bindex >= 0; bindex--) {
++              h_mnt = au_sbr_mnt(sb, bindex);
++              h_sb = h_mnt->mnt_sb;
++              shared = 0;
++              for (i = bindex + 1; !shared && i <= bend; i++)
++                      shared = (au_sbr_sb(sb, i) == h_sb);
++              if (shared)
++                      continue;
++
++              /* sb->s_root for NFS is unreliable */
++              err = vfs_statfs(h_mnt->mnt_root, buf);
++              if (unlikely(err))
++                      goto out;
++
++              blocks = au_add_till_max(blocks, buf->f_blocks);
++              bfree = au_add_till_max(bfree, buf->f_bfree);
++              bavail = au_add_till_max(bavail, buf->f_bavail);
++              files = au_add_till_max(files, buf->f_files);
++              ffree = au_add_till_max(ffree, buf->f_ffree);
++      }
++
++      buf->f_blocks = blocks;
++      buf->f_bfree = bfree;
++      buf->f_bavail = bavail;
++      buf->f_files = files;
++      buf->f_ffree = ffree;
++
++ out:
++      return err;
++}
++
++static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
++{
++      int err;
++      struct super_block *sb;
++
++      /* lock free root dinfo */
++      sb = dentry->d_sb;
++      si_noflush_read_lock(sb);
++      if (!au_opt_test(au_mntflags(sb), SUM))
++              /* sb->s_root for NFS is unreliable */
++              err = vfs_statfs(au_sbr_mnt(sb, 0)->mnt_root, buf);
++      else
++              err = au_statfs_sum(sb, buf);
++      si_read_unlock(sb);
++
++      if (!err) {
++              buf->f_type = AUFS_SUPER_MAGIC;
++              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; */
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* try flushing the lower fs at aufs remount/unmount time */
++
++static void au_fsync_br(struct super_block *sb)
++{
++      aufs_bindex_t bend, bindex;
++      int brperm;
++      struct au_branch *br;
++      struct super_block *h_sb;
++
++      bend = au_sbend(sb);
++      for (bindex = 0; bindex < bend; bindex++) {
++              br = au_sbr(sb, bindex);
++              brperm = br->br_perm;
++              if (brperm == AuBrPerm_RR || brperm == AuBrPerm_RRWH)
++                      continue;
++              h_sb = br->br_mnt->mnt_sb;
++              if (bdev_read_only(h_sb->s_bdev))
++                      continue;
++
++              lockdep_off();
++              down_write(&h_sb->s_umount);
++              shrink_dcache_sb(h_sb);
++              fsync_super(h_sb);
++              up_write(&h_sb->s_umount);
++              lockdep_on();
++      }
++}
++
++/*
++ * this IS NOT for super_operations.
++ * I guess it will be reverted someday.
++ */
++static void aufs_umount_begin(struct super_block *sb)
++{
++      struct au_sbinfo *sbinfo;
++
++      sbinfo = au_sbi(sb);
++      if (!sbinfo)
++              return;
++
++      si_write_lock(sb);
++      au_fsync_br(sb);
++      if (au_opt_test(au_mntflags(sb), PLINK))
++              au_plink_put(sb);
++      if (sbinfo->si_wbr_create_ops->fin)
++              sbinfo->si_wbr_create_ops->fin(sb);
++      si_write_unlock(sb);
++}
++
++/* final actions when unmounting a file system */
++static void aufs_put_super(struct super_block *sb)
++{
++      struct au_sbinfo *sbinfo;
++
++      sbinfo = au_sbi(sb);
++      if (!sbinfo)
++              return;
++
++      aufs_umount_begin(sb);
++      dbgaufs_si_fin(sbinfo);
++      kobject_put(&sbinfo->si_kobj);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * refresh dentry and inode at remount time.
++ */
++static int do_refresh(struct dentry *dentry, mode_t type,
++                    unsigned int dir_flags)
++{
++      int err;
++      struct dentry *parent;
++
++      di_write_lock_child(dentry);
++      parent = dget_parent(dentry);
++      di_read_lock_parent(parent, AuLock_IR);
++
++      /* returns the number of positive dentries */
++      err = au_refresh_hdentry(dentry, type);
++      if (err >= 0) {
++              struct inode *inode = dentry->d_inode;
++              err = au_refresh_hinode(inode, dentry);
++              if (!err && type == S_IFDIR)
++                      au_reset_hinotify(inode, dir_flags);
++      }
++      if (unlikely(err))
++              AuErr("unrecoverable error %d, %.*s\n", err, AuDLNPair(dentry));
++
++      di_read_unlock(parent, AuLock_IR);
++      dput(parent);
++      di_write_unlock(dentry);
++
++      return err;
++}
++
++static int test_dir(struct dentry *dentry, void *arg __maybe_unused)
++{
++      return S_ISDIR(dentry->d_inode->i_mode);
++}
++
++/* gave up consolidating with refresh_nondir() */
++static int refresh_dir(struct dentry *root, unsigned int sigen)
++{
++      int err, i, j, ndentry, e;
++      struct au_dcsub_pages dpages;
++      struct au_dpage *dpage;
++      struct dentry **dentries;
++      struct inode *inode;
++      const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1);
++
++      err = 0;
++      list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
++              if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
++                      ii_write_lock_child(inode);
++                      e = au_refresh_hinode_self(inode, /*do_attr*/1);
++                      ii_write_unlock(inode);
++                      if (unlikely(e)) {
++                              AuDbg("e %d, i%lu\n", e, inode->i_ino);
++                              if (!err)
++                                      err = e;
++                              /* go on even if err */
++                      }
++              }
++
++      e = au_dpages_init(&dpages, GFP_NOFS);
++      if (unlikely(e)) {
++              if (!err)
++                      err = e;
++              goto out;
++      }
++      e = au_dcsub_pages(&dpages, root, test_dir, NULL);
++      if (unlikely(e)) {
++              if (!err)
++                      err = e;
++              goto out_dpages;
++      }
++
++      for (i = 0; !e && i < dpages.ndpage; i++) {
++              dpage = dpages.dpages + i;
++              dentries = dpage->dentries;
++              ndentry = dpage->ndentry;
++              for (j = 0; !e && j < ndentry; j++) {
++                      struct dentry *d;
++
++                      d = dentries[j];
++                      au_dbg_verify_dir_parent(d, sigen);
++                      if (au_digen(d) != sigen) {
++                              e = do_refresh(d, S_IFDIR, flags);
++                              if (unlikely(e && !err))
++                                      err = e;
++                              /* break on err */
++                      }
++              }
++      }
++
++ out_dpages:
++      au_dpages_free(&dpages);
++ out:
++      return err;
++}
++
++static int test_nondir(struct dentry *dentry, void *arg __maybe_unused)
++{
++      return !S_ISDIR(dentry->d_inode->i_mode);
++}
++
++static int refresh_nondir(struct dentry *root, unsigned int sigen,
++                        int do_dentry)
++{
++      int err, i, j, ndentry, e;
++      struct au_dcsub_pages dpages;
++      struct au_dpage *dpage;
++      struct dentry **dentries;
++      struct inode *inode;
++
++      err = 0;
++      list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list)
++              if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) {
++                      ii_write_lock_child(inode);
++                      e = au_refresh_hinode_self(inode, /*do_attr*/1);
++                      ii_write_unlock(inode);
++                      if (unlikely(e)) {
++                              AuDbg("e %d, i%lu\n", e, inode->i_ino);
++                              if (!err)
++                                      err = e;
++                              /* go on even if err */
++                      }
++              }
++
++      if (!do_dentry)
++              goto out;
++
++      e = au_dpages_init(&dpages, GFP_NOFS);
++      if (unlikely(e)) {
++              if (!err)
++                      err = e;
++              goto out;
++      }
++      e = au_dcsub_pages(&dpages, root, test_nondir, NULL);
++      if (unlikely(e)) {
++              if (!err)
++                      err = e;
++              goto out_dpages;
++      }
++
++      for (i = 0; i < dpages.ndpage; i++) {
++              dpage = dpages.dpages + i;
++              dentries = dpage->dentries;
++              ndentry = dpage->ndentry;
++              for (j = 0; j < ndentry; j++) {
++                      struct dentry *d;
++
++                      d = dentries[j];
++                      au_dbg_verify_nondir_parent(d, sigen);
++                      inode = d->d_inode;
++                      if (inode && au_digen(d) != sigen) {
++                              e = do_refresh(d, inode->i_mode & S_IFMT,
++                                             /*dir_flags*/0);
++                              if (unlikely(e && !err))
++                                      err = e;
++                              /* go on even err */
++                      }
++              }
++      }
++
++ out_dpages:
++      au_dpages_free(&dpages);
++ out:
++      return err;
++}
++
++static void au_remount_refresh(struct super_block *sb, unsigned int flags)
++{
++      int err;
++      unsigned int sigen;
++      struct au_sbinfo *sbinfo;
++      struct dentry *root;
++      struct inode *inode;
++
++      au_sigen_inc(sb);
++      sigen = au_sigen(sb);
++      sbinfo = au_sbi(sb);
++      au_fclr_si(sbinfo, FAILED_REFRESH_DIRS);
++
++      root = sb->s_root;
++      DiMustNoWaiters(root);
++      inode = root->d_inode;
++      IiMustNoWaiters(inode);
++      au_reset_hinotify(inode, au_hi_flags(inode, /*isdir*/1));
++      di_write_unlock(root);
++
++      err = refresh_dir(root, sigen);
++      if (unlikely(err)) {
++              au_fset_si(sbinfo, FAILED_REFRESH_DIRS);
++              AuWarn("Refreshing directories failed, ignored (%d)\n", err);
++      }
++
++      if (au_ftest_opts(flags, REFRESH_NONDIR)) {
++              err = refresh_nondir(root, sigen, !err);
++              if (unlikely(err))
++                      AuWarn("Refreshing non-directories failed, ignored"
++                             "(%d)\n", err);
++      }
++
++      /* aufs_write_lock() calls ..._child() */
++      di_write_lock_child(root);
++      au_cpup_attr_all(root->d_inode, /*force*/1);
++}
++
++/* stop extra interpretation of errno in mount(8), and strange error messages */
++static int cvt_err(int err)
++{
++      AuTraceErr(err);
++
++      switch (err) {
++      case -ENOENT:
++      case -ENOTDIR:
++      case -EEXIST:
++      case -EIO:
++              err = -EINVAL;
++      }
++      return err;
++}
++
++static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
++{
++      int err;
++      struct au_opts opts;
++      struct dentry *root;
++      struct inode *inode;
++      struct au_sbinfo *sbinfo;
++
++      err = 0;
++      root = sb->s_root;
++      if (!data || !*data) {
++              aufs_write_lock(root);
++              err = au_opts_verify(sb, *flags, /*pending*/0);
++              if (!err)
++                      au_fsync_br(sb);
++              aufs_write_unlock(root);
++              goto out;
++      }
++
++      err = -ENOMEM;
++      memset(&opts, 0, sizeof(opts));
++      opts.opt = (void *)__get_free_page(GFP_NOFS);
++      if (unlikely(!opts.opt))
++              goto out;
++      opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
++      opts.flags = AuOpts_REMOUNT;
++      opts.sb_flags = *flags;
++
++      /* parse it before aufs lock */
++      err = au_opts_parse(sb, data, &opts);
++      if (unlikely(err))
++              goto out_opts;
++
++      sbinfo = au_sbi(sb);
++      inode = root->d_inode;
++      mutex_lock(&inode->i_mutex);
++      aufs_write_lock(root);
++      au_fsync_br(sb);
++
++      /* au_opts_remount() may return an error */
++      err = au_opts_remount(sb, &opts);
++      au_opts_free(&opts);
++
++      if (au_ftest_opts(opts.flags, REFRESH_DIR)
++          || au_ftest_opts(opts.flags, REFRESH_NONDIR))
++              au_remount_refresh(sb, opts.flags);
++
++      aufs_write_unlock(root);
++      mutex_unlock(&inode->i_mutex);
++
++ out_opts:
++      free_page((unsigned long)opts.opt);
++ out:
++      err = cvt_err(err);
++      AuTraceErr(err);
++      return err;
++}
++
++static struct super_operations aufs_sop = {
++      .alloc_inode    = aufs_alloc_inode,
++      .destroy_inode  = aufs_destroy_inode,
++      .drop_inode     = generic_delete_inode,
++      .show_options   = aufs_show_options,
++      .statfs         = aufs_statfs,
++      .put_super      = aufs_put_super,
++      .remount_fs     = aufs_remount_fs
++};
++
++/* ---------------------------------------------------------------------- */
++
++static int alloc_root(struct super_block *sb)
++{
++      int err;
++      struct inode *inode;
++      struct dentry *root;
++
++      err = -ENOMEM;
++      inode = au_iget_locked(sb, AUFS_ROOT_INO);
++      err = PTR_ERR(inode);
++      if (IS_ERR(inode))
++              goto out;
++
++      inode->i_op = &aufs_dir_iop;
++      inode->i_fop = &aufs_dir_fop;
++      inode->i_mode = S_IFDIR;
++      inode->i_nlink = 2;
++      unlock_new_inode(inode);
++
++      root = d_alloc_root(inode);
++      if (unlikely(!root))
++              goto out_iput;
++      err = PTR_ERR(root);
++      if (IS_ERR(root))
++              goto out_iput;
++
++      err = au_alloc_dinfo(root);
++      if (!err) {
++              sb->s_root = root;
++              return 0; /* success */
++      }
++      dput(root);
++      goto out; /* do not iput */
++
++ out_iput:
++      iget_failed(inode);
++      iput(inode);
++ out:
++      return err;
++
++}
++
++static int aufs_fill_super(struct super_block *sb, void *raw_data,
++                         int silent __maybe_unused)
++{
++      int err;
++      struct au_opts opts;
++      struct dentry *root;
++      struct inode *inode;
++      char *arg = raw_data;
++
++      if (unlikely(!arg || !*arg)) {
++              err = -EINVAL;
++              AuErr("no arg\n");
++              goto out;
++      }
++
++      err = -ENOMEM;
++      memset(&opts, 0, sizeof(opts));
++      opts.opt = (void *)__get_free_page(GFP_NOFS);
++      if (unlikely(!opts.opt))
++              goto out;
++      opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
++      opts.sb_flags = sb->s_flags;
++
++      err = au_si_alloc(sb);
++      if (unlikely(err))
++              goto out_opts;
++
++      /* all timestamps always follow the ones on the branch */
++      sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
++      sb->s_op = &aufs_sop;
++      sb->s_magic = AUFS_SUPER_MAGIC;
++      sb->s_maxbytes = 0;
++      au_export_init(sb);
++
++      err = alloc_root(sb);
++      if (unlikely(err)) {
++              si_write_unlock(sb);
++              goto out_info;
++      }
++      root = sb->s_root;
++      inode = root->d_inode;
++
++      /*
++       * 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_opts_parse(sb, arg, &opts);
++      if (unlikely(err))
++              goto out_root;
++
++      /* lock vfs_inode first, then aufs. */
++      mutex_lock(&inode->i_mutex);
++      inode->i_op = &aufs_dir_iop;
++      inode->i_fop = &aufs_dir_fop;
++      aufs_write_lock(root);
++      err = au_opts_mount(sb, &opts);
++      au_opts_free(&opts);
++      if (unlikely(err))
++              goto out_unlock;
++      aufs_write_unlock(root);
++      mutex_unlock(&inode->i_mutex);
++      goto out_opts; /* success */
++
++ out_unlock:
++      aufs_write_unlock(root);
++      mutex_unlock(&inode->i_mutex);
++ out_root:
++      dput(root);
++      sb->s_root = NULL;
++ out_info:
++      kobject_put(&au_sbi(sb)->si_kobj);
++      sb->s_fs_info = NULL;
++ out_opts:
++      free_page((unsigned long)opts.opt);
++ out:
++      AuTraceErr(err);
++      err = cvt_err(err);
++      AuTraceErr(err);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int aufs_get_sb(struct file_system_type *fs_type, int flags,
++                     const char *dev_name __maybe_unused, void *raw_data,
++                     struct vfsmount *mnt)
++{
++      int err;
++      struct super_block *sb;
++
++      /* 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) {
++              sb = mnt->mnt_sb;
++              si_write_lock(sb);
++              sysaufs_brs_add(sb, 0);
++              si_write_unlock(sb);
++      }
++      return err;
++}
++
++struct file_system_type aufs_fs_type = {
++      .name           = AUFS_FSTYPE,
++      .fs_flags       =
++              FS_RENAME_DOES_D_MOVE   /* a race between rename and others */
++              | FS_REVAL_DOT,         /* for NFS branch and udba */
++      .get_sb         = aufs_get_sb,
++      .kill_sb        = generic_shutdown_super,
++      /* no need to __module_get() and module_put(). */
++      .owner          = THIS_MODULE,
++};
+diff -Naur a/fs/aufs/super.h b/fs/aufs/super.h
+--- a/fs/aufs/super.h  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/super.h  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,359 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * super_block operations
++ */
++
++#ifndef __AUFS_SUPER_H__
++#define __AUFS_SUPER_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/aufs_type.h>
++#include "rwsem.h"
++#include "spl.h"
++#include "wkq.h"
++
++typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
++typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
++                             loff_t *);
++
++/* policies to select one among multiple writable branches */
++struct au_wbr_copyup_operations {
++      int (*copyup)(struct dentry *dentry);
++};
++
++struct au_wbr_create_operations {
++      int (*create)(struct dentry *dentry, int isdir);
++      int (*init)(struct super_block *sb);
++      int (*fin)(struct super_block *sb);
++};
++
++struct au_wbr_mfs {
++      struct mutex    mfs_lock; /* protect this structure */
++      unsigned long   mfs_jiffy;
++      unsigned long   mfs_expire;
++      aufs_bindex_t   mfs_bindex;
++
++      unsigned long long      mfsrr_bytes;
++      unsigned long long      mfsrr_watermark;
++};
++
++/* sbinfo status flags */
++/*
++ * set true when refresh_dirs() failed at remount time.
++ * then try refreshing dirs at access time again.
++ * if it is false, refreshing dirs at access time is unnecesary
++ */
++#define AuSi_FAILED_REFRESH_DIRS      1
++#define AuSi_MAINTAIN_PLINK           (1 << 1)        /* ioctl */
++#define au_ftest_si(sbinfo, name)     ((sbinfo)->au_si_status & AuSi_##name)
++#define au_fset_si(sbinfo, name) \
++      { (sbinfo)->au_si_status |= AuSi_##name; }
++#define au_fclr_si(sbinfo, name) \
++      { (sbinfo)->au_si_status &= ~AuSi_##name; }
++
++struct au_branch;
++struct au_sbinfo {
++      /* nowait tasks in the system-wide workqueue */
++      struct au_nowait_tasks  si_nowait;
++
++      struct rw_semaphore     si_rwsem;
++
++      /* branch management */
++      unsigned int            si_generation;
++
++      /* see above flags */
++      unsigned char           au_si_status;
++
++      aufs_bindex_t           si_bend;
++      aufs_bindex_t           si_last_br_id;
++      struct au_branch        **si_branch;
++
++      /* policy to select a writable branch */
++      unsigned char           si_wbr_copyup;
++      unsigned char           si_wbr_create;
++      struct au_wbr_copyup_operations *si_wbr_copyup_ops;
++      struct au_wbr_create_operations *si_wbr_create_ops;
++
++      /* round robin */
++      atomic_t                si_wbr_rr_next;
++
++      /* most free space */
++      struct au_wbr_mfs       si_wbr_mfs;
++
++      /* mount flags */
++      /* include/asm-ia64/siginfo.h defines a macro named si_flags */
++      unsigned int            si_mntflags;
++
++      /* external inode number (bitmap and translation table) */
++      au_readf_t              si_xread;
++      au_writef_t             si_xwrite;
++      struct file             *si_xib;
++      struct mutex            si_xib_mtx; /* protect xib members */
++      unsigned long           *si_xib_buf;
++      unsigned long           si_xib_last_pindex;
++      int                     si_xib_next_bit;
++      aufs_bindex_t           si_xino_brid;
++      /* reserved for future use */
++      /* unsigned long long   si_xib_limit; */        /* Max xib file size */
++
++#ifdef CONFIG_AUFS_EXPORT
++      /* i_generation */
++      struct file             *si_xigen;
++      atomic_t                si_xigen_next;
++#endif
++
++      /* vdir parameters */
++      unsigned long           si_rdcache;     /* max cache time in HZ */
++      unsigned int            si_rdblk;       /* deblk size */
++      unsigned int            si_rdhash;      /* hash size */
++
++      /*
++       * If the number of whiteouts are larger than si_dirwh, leave all of
++       * them after au_whtmp_ren 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;
++
++      /*
++       * rename(2) a directory with all children.
++       */
++      /* reserved for future use */
++      /* int                  si_rendir; */
++
++      /* pseudo_link list */
++      struct au_splhead       si_plink;
++      wait_queue_head_t       si_plink_wq;
++
++      /*
++       * sysfs and lifetime management.
++       * this is not a small structure and it may be a waste of memory in case
++       * of sysfs is disabled, particulary when many aufs-es are mounted.
++       * but using sysfs is majority.
++       */
++      struct kobject          si_kobj;
++#ifdef CONFIG_DEBUG_FS
++      struct dentry            *si_dbgaufs, *si_dbgaufs_xib;
++#ifdef CONFIG_AUFS_EXPORT
++      struct dentry            *si_dbgaufs_xigen;
++#endif
++#endif
++
++      /* dirty, necessary for unmounting, sysfs and sysrq */
++      struct super_block      *si_sb;
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* policy to select one among writable branches */
++#define AuWbrCopyup(sbinfo, args...) \
++      ((sbinfo)->si_wbr_copyup_ops->copyup(args))
++#define AuWbrCreate(sbinfo, args...) \
++      ((sbinfo)->si_wbr_create_ops->create(args))
++
++/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
++#define AuLock_DW             1               /* write-lock dentry */
++#define AuLock_IR             (1 << 1)        /* read-lock inode */
++#define AuLock_IW             (1 << 2)        /* write-lock inode */
++#define AuLock_FLUSH          (1 << 3)        /* wait for 'nowait' tasks */
++#define AuLock_DIR            (1 << 4)        /* target is a dir */
++#define au_ftest_lock(flags, name)    ((flags) & AuLock_##name)
++#define au_fset_lock(flags, name)     { (flags) |= AuLock_##name; }
++#define au_fclr_lock(flags, name)     { (flags) &= ~AuLock_##name; }
++
++/* ---------------------------------------------------------------------- */
++
++/* super.c */
++extern struct file_system_type aufs_fs_type;
++struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
++
++/* sbinfo.c */
++void au_si_free(struct kobject *kobj);
++int au_si_alloc(struct super_block *sb);
++int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
++
++unsigned int au_sigen_inc(struct super_block *sb);
++aufs_bindex_t au_new_br_id(struct super_block *sb);
++
++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);
++
++/* wbr_policy.c */
++extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
++extern struct au_wbr_create_operations au_wbr_create_ops[];
++int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct au_sbinfo *au_sbi(struct super_block *sb)
++{
++      return sb->s_fs_info;
++}
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_EXPORT
++void au_export_init(struct super_block *sb);
++
++static inline int au_test_nfsd(struct task_struct *tsk)
++{
++      return !tsk->mm && !strcmp(tsk->comm, "nfsd");
++}
++
++int au_xigen_inc(struct inode *inode);
++int au_xigen_new(struct inode *inode);
++int au_xigen_set(struct super_block *sb, struct file *base);
++void au_xigen_clr(struct super_block *sb);
++
++static inline int au_busy_or_stale(void)
++{
++      if (!au_test_nfsd(current))
++              return -EBUSY;
++      return -ESTALE;
++}
++#else
++static inline void au_export_init(struct super_block *sb)
++{
++      /* nothing */
++}
++
++static inline int au_test_nfsd(struct task_struct *tsk)
++{
++      return 0;
++}
++
++static inline int au_xigen_inc(struct inode *inode)
++{
++      return 0;
++}
++
++static inline int au_xigen_new(struct inode *inode)
++{
++      return 0;
++}
++
++static inline int au_xigen_set(struct super_block *sb, struct file *base)
++{
++      return 0;
++}
++
++static inline void au_xigen_clr(struct super_block *sb)
++{
++      /* empty */
++}
++
++static inline int au_busy_or_stale(void)
++{
++      return -EBUSY;
++}
++#endif /* CONFIG_AUFS_EXPORT */
++
++/* ---------------------------------------------------------------------- */
++
++static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
++{
++#ifdef CONFIG_DEBUG_FS
++      sbinfo->si_dbgaufs = NULL;
++      sbinfo->si_dbgaufs_xib = NULL;
++#ifdef CONFIG_AUFS_EXPORT
++      sbinfo->si_dbgaufs_xigen = NULL;
++#endif
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* lock superblock. mainly for entry point functions */
++/*
++ * si_noflush_read_lock, si_noflush_write_lock,
++ * si_read_unlock, si_write_unlock, si_downgrade_lock
++ */
++AuSimpleLockRwsemFuncs(si_noflush, struct super_block *sb,
++                     &au_sbi(sb)->si_rwsem);
++AuSimpleUnlockRwsemFuncs(si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
++
++static inline void si_read_lock(struct super_block *sb, int flags)
++{
++      if (au_ftest_lock(flags, FLUSH))
++              au_nwt_flush(&au_sbi(sb)->si_nowait);
++      si_noflush_read_lock(sb);
++}
++
++static inline void si_write_lock(struct super_block *sb)
++{
++      au_nwt_flush(&au_sbi(sb)->si_nowait);
++      si_noflush_write_lock(sb);
++}
++
++static inline int si_read_trylock(struct super_block *sb, int flags)
++{
++      if (au_ftest_lock(flags, FLUSH))
++              au_nwt_flush(&au_sbi(sb)->si_nowait);
++      return si_noflush_read_trylock(sb);
++}
++
++static inline int si_write_trylock(struct super_block *sb, int flags)
++{
++      if (au_ftest_lock(flags, FLUSH))
++              au_nwt_flush(&au_sbi(sb)->si_nowait);
++      return si_noflush_write_trylock(sb);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static inline aufs_bindex_t au_sbend(struct super_block *sb)
++{
++      return au_sbi(sb)->si_bend;
++}
++
++static inline unsigned int au_mntflags(struct super_block *sb)
++{
++      return au_sbi(sb)->si_mntflags;
++}
++
++static inline unsigned int au_sigen(struct super_block *sb)
++{
++      return au_sbi(sb)->si_generation;
++}
++
++static inline struct au_branch *au_sbr(struct super_block *sb,
++                                     aufs_bindex_t bindex)
++{
++      return au_sbi(sb)->si_branch[0 + bindex];
++}
++
++static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
++{
++      au_sbi(sb)->si_xino_brid = brid;
++}
++
++static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
++{
++      return au_sbi(sb)->si_xino_brid;
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_SUPER_H__ */
+diff -Naur a/fs/aufs/sysaufs.c b/fs/aufs/sysaufs.c
+--- a/fs/aufs/sysaufs.c        1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/sysaufs.c        2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,104 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * sysfs interface and lifetime management
++ * they are necessary regardless sysfs is disabled.
++ */
++
++#include <linux/fs.h>
++#include <linux/random.h>
++#include <linux/sysfs.h>
++#include "aufs.h"
++
++unsigned long sysaufs_si_mask;
++struct kset *sysaufs_ket;
++
++#define AuSiAttr(_name) { \
++      .attr   = { .name = __stringify(_name), .mode = 0444 }, \
++      .show   = sysaufs_si_##_name,                           \
++}
++
++static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
++struct attribute *sysaufs_si_attrs[] = {
++      &sysaufs_si_attr_xi_path.attr,
++      NULL,
++};
++
++static struct sysfs_ops au_sbi_ops = {
++      .show   = sysaufs_si_show
++};
++
++static struct kobj_type au_sbi_ktype = {
++      .release        = au_si_free,
++      .sysfs_ops      = &au_sbi_ops,
++      .default_attrs  = sysaufs_si_attrs
++};
++
++/* ---------------------------------------------------------------------- */
++
++int sysaufs_si_init(struct au_sbinfo *sbinfo)
++{
++      int err;
++
++      sbinfo->si_kobj.kset = sysaufs_ket;
++      /* cf. sysaufs_name() */
++      err = kobject_init_and_add
++              (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_ket->kobj*/NULL,
++               SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
++
++      dbgaufs_si_null(sbinfo);
++      if (!err) {
++              err = dbgaufs_si_init(sbinfo);
++              if (unlikely(err))
++                      kobject_put(&sbinfo->si_kobj);
++      }
++      return err;
++}
++
++void sysaufs_fin(void)
++{
++      dbgaufs_fin();
++      sysfs_remove_group(&sysaufs_ket->kobj, sysaufs_attr_group);
++      kset_unregister(sysaufs_ket);
++}
++
++int __init sysaufs_init(void)
++{
++      int err;
++
++      do {
++              get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
++      } while (!sysaufs_si_mask);
++
++      sysaufs_ket = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
++      err = PTR_ERR(sysaufs_ket);
++      if (IS_ERR(sysaufs_ket))
++              goto out;
++      err = sysfs_create_group(&sysaufs_ket->kobj, sysaufs_attr_group);
++      if (unlikely(err)) {
++              kset_unregister(sysaufs_ket);
++              goto out;
++      }
++
++      err = dbgaufs_init();
++      if (unlikely(err))
++              sysaufs_fin();
++ out:
++      return err;
++}
+diff -Naur a/fs/aufs/sysaufs.h b/fs/aufs/sysaufs.h
+--- a/fs/aufs/sysaufs.h        1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/sysaufs.h        2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,120 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * sysfs interface and mount lifetime management
++ */
++
++#ifndef __SYSAUFS_H__
++#define __SYSAUFS_H__
++
++#ifdef __KERNEL__
++
++#include <linux/sysfs.h>
++#include <linux/aufs_type.h>
++#include "module.h"
++
++struct super_block;
++struct au_sbinfo;
++
++struct sysaufs_si_attr {
++      struct attribute attr;
++      int (*show)(struct seq_file *seq, struct super_block *sb);
++};
++
++/* ---------------------------------------------------------------------- */
++
++/* sysaufs.c */
++extern unsigned long sysaufs_si_mask;
++extern struct kset *sysaufs_ket;
++extern struct attribute *sysaufs_si_attrs[];
++int sysaufs_si_init(struct au_sbinfo *sbinfo);
++int __init sysaufs_init(void);
++void sysaufs_fin(void);
++
++/* ---------------------------------------------------------------------- */
++
++/* some people doesn't like to show a pointer in kernel */
++static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
++{
++      return sysaufs_si_mask ^ (unsigned long)sbinfo;
++}
++
++#define SysaufsSiNamePrefix   "si_"
++#define SysaufsSiNameLen      (sizeof(SysaufsSiNamePrefix) + 16)
++static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
++{
++      snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
++               sysaufs_si_id(sbinfo));
++}
++
++struct au_branch;
++#ifdef CONFIG_SYSFS
++/* sysfs.c */
++extern struct attribute_group *sysaufs_attr_group;
++
++int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
++ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
++                       char *buf);
++
++void sysaufs_br_init(struct au_branch *br);
++void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
++void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
++
++#define sysaufs_brs_init()    do {} while (0)
++
++#else
++#define sysaufs_attr_group    NULL
++
++static inline
++int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
++{
++      return 0;
++}
++
++static inline
++ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
++                       char *buf)
++{
++      return 0;
++}
++
++static inline void sysaufs_br_init(struct au_branch *br)
++{
++      /* empty */
++}
++
++static inline void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
++{
++      /* nothing */
++}
++
++static inline void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
++{
++      /* nothing */
++}
++
++static inline void sysaufs_brs_init(void)
++{
++      sysaufs_brs = 0;
++}
++
++#endif /* CONFIG_SYSFS */
++
++#endif /* __KERNEL__ */
++#endif /* __SYSAUFS_H__ */
+diff -Naur a/fs/aufs/sysfs.c b/fs/aufs/sysfs.c
+--- a/fs/aufs/sysfs.c  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/sysfs.c  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,208 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * sysfs interface
++ */
++
++#include <linux/fs.h>
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include <linux/sysfs.h>
++#include "aufs.h"
++
++static struct attribute *au_attr[] = {
++      NULL,   /* need to NULL terminate the list of attributes */
++};
++
++static struct attribute_group sysaufs_attr_group_body = {
++      .attrs = au_attr
++};
++
++struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
++
++/* ---------------------------------------------------------------------- */
++
++int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
++{
++      int err;
++
++      err = 0;
++      if (au_opt_test(au_mntflags(sb), XINO)) {
++              err = au_xino_path(seq, au_sbi(sb)->si_xib);
++              seq_putc(seq, '\n');
++      }
++      return err;
++}
++
++/*
++ * the lifetime of branch is independent from the entry under sysfs.
++ * sysfs handles the lifetime of the entry, and never call ->show() after it is
++ * unlinked.
++ */
++static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
++                       aufs_bindex_t bindex)
++{
++      struct path path;
++      struct dentry *root;
++      struct au_branch *br;
++
++      AuDbg("b%d\n", bindex);
++
++      root = sb->s_root;
++      di_read_lock_parent(root, !AuLock_IR);
++      br = au_sbr(sb, bindex);
++      path.mnt = br->br_mnt;
++      path.dentry = au_h_dptr(root, bindex);
++      au_seq_path(seq, &path);
++      di_read_unlock(root, !AuLock_IR);
++      seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
++      return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static struct seq_file *au_seq(char *p, ssize_t len)
++{
++      struct seq_file *seq;
++
++      seq = kzalloc(sizeof(*seq), GFP_NOFS);
++      if (seq) {
++              /* mutex_init(&seq.lock); */
++              seq->buf = p;
++              seq->size = len;
++              return seq; /* success */
++      }
++
++      seq = ERR_PTR(-ENOMEM);
++      return seq;
++}
++
++#define SysaufsBr_PREFIX "br"
++
++/* todo: file size may exceed PAGE_SIZE */
++ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
++                       char *buf)
++{
++      ssize_t err;
++      long l;
++      aufs_bindex_t bend;
++      struct au_sbinfo *sbinfo;
++      struct super_block *sb;
++      struct seq_file *seq;
++      char *name;
++      struct attribute **cattr;
++
++      sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
++      sb = sbinfo->si_sb;
++      si_noflush_read_lock(sb);
++
++      seq = au_seq(buf, PAGE_SIZE);
++      err = PTR_ERR(seq);
++      if (IS_ERR(seq))
++              goto out;
++
++      name = (void *)attr->name;
++      cattr = sysaufs_si_attrs;
++      while (*cattr) {
++              if (!strcmp(name, (*cattr)->name)) {
++                      err = container_of(*cattr, struct sysaufs_si_attr, attr)
++                              ->show(seq, sb);
++                      goto out_seq;
++              }
++              cattr++;
++      }
++
++      bend = au_sbend(sb);
++      if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
++              name += sizeof(SysaufsBr_PREFIX) - 1;
++              err = strict_strtol(name, 10, &l);
++              if (!err) {
++                      if (l <= bend)
++                              err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
++                      else
++                              err = -ENOENT;
++              }
++              goto out_seq;
++      }
++      BUG();
++
++ out_seq:
++      if (!err) {
++              err = seq->count;
++              /* sysfs limit */
++              if (unlikely(err == PAGE_SIZE))
++                      err = -EFBIG;
++      }
++      kfree(seq);
++ out:
++      si_read_unlock(sb);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void sysaufs_br_init(struct au_branch *br)
++{
++      br->br_attr.name = br->br_name;
++      br->br_attr.mode = S_IRUGO;
++      br->br_attr.owner = THIS_MODULE;
++}
++
++void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
++{
++      struct au_branch *br;
++      struct kobject *kobj;
++      aufs_bindex_t bend;
++
++      dbgaufs_brs_del(sb, bindex);
++
++      if (!sysaufs_brs)
++              return;
++
++      kobj = &au_sbi(sb)->si_kobj;
++      bend = au_sbend(sb);
++      for (; bindex <= bend; bindex++) {
++              br = au_sbr(sb, bindex);
++              sysfs_remove_file(kobj, &br->br_attr);
++      }
++}
++
++void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
++{
++      int err;
++      aufs_bindex_t bend;
++      struct kobject *kobj;
++      struct au_branch *br;
++
++      dbgaufs_brs_add(sb, bindex);
++
++      if (!sysaufs_brs)
++              return;
++
++      kobj = &au_sbi(sb)->si_kobj;
++      bend = au_sbend(sb);
++      for (; bindex <= bend; bindex++) {
++              br = au_sbr(sb, bindex);
++              snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
++                       "%d", bindex);
++              err = sysfs_create_file(kobj, &br->br_attr);
++              if (unlikely(err))
++                      AuWarn("failed %s under sysfs(%d)\n", br->br_name, err);
++      }
++}
+diff -Naur a/fs/aufs/sysrq.c b/fs/aufs/sysrq.c
+--- a/fs/aufs/sysrq.c  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/sysrq.c  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,115 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * magic sysrq hanlder
++ */
++
++#include <linux/fs.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++/* #include <linux/sysrq.h> */
++#include "aufs.h"
++
++/* ---------------------------------------------------------------------- */
++
++static void sysrq_sb(struct super_block *sb)
++{
++      char *plevel;
++      struct au_sbinfo *sbinfo;
++      struct file *file;
++
++      plevel = au_plevel;
++      au_plevel = KERN_WARNING;
++      au_debug(1);
++
++      sbinfo = au_sbi(sb);
++      pr_warning("si=%lx\n", sysaufs_si_id(sbinfo));
++      pr_warning(AUFS_NAME ": superblock\n");
++      au_dpri_sb(sb);
++      pr_warning(AUFS_NAME ": root dentry\n");
++      au_dpri_dentry(sb->s_root);
++      pr_warning(AUFS_NAME ": root inode\n");
++      au_dpri_inode(sb->s_root->d_inode);
++#if 0
++      struct inode *i;
++      pr_warning(AUFS_NAME ": isolated inode\n");
++      list_for_each_entry(i, &sb->s_inodes, i_sb_list)
++              if (list_empty(&i->i_dentry))
++                      au_dpri_inode(i);
++#endif
++      pr_warning(AUFS_NAME ": files\n");
++      list_for_each_entry(file, &sb->s_files, f_u.fu_list)
++              if (!special_file(file->f_dentry->d_inode->i_mode))
++                      au_dpri_file(file);
++
++      au_plevel = plevel;
++      au_debug(0);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* module parameter */
++static char *aufs_sysrq_key = "a";
++module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
++MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
++
++static void au_sysrq(int key __maybe_unused,
++                   struct tty_struct *tty __maybe_unused)
++{
++      struct kobject *kobj;
++      struct au_sbinfo *sbinfo;
++
++      /* spin_lock(&sysaufs_ket->list_lock); */
++      list_for_each_entry(kobj, &sysaufs_ket->list, entry) {
++              sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
++              sysrq_sb(sbinfo->si_sb);
++      }
++      /* spin_unlock(&sysaufs_ket->list_lock); */
++}
++
++static struct sysrq_key_op au_sysrq_op = {
++      .handler        = au_sysrq,
++      .help_msg       = "Aufs",
++      .action_msg     = "Aufs",
++      .enable_mask    = SYSRQ_ENABLE_DUMP
++};
++
++/* ---------------------------------------------------------------------- */
++
++int __init au_sysrq_init(void)
++{
++      int err;
++      char key;
++
++      err = -1;
++      key = *aufs_sysrq_key;
++      if ('a' <= key && key <= 'z')
++              err = register_sysrq_key(key, &au_sysrq_op);
++      if (unlikely(err))
++              AuErr("err %d, sysrq=%c\n", err, key);
++      return err;
++}
++
++void au_sysrq_fin(void)
++{
++      int err;
++      err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
++      if (unlikely(err))
++              AuErr("err %d (ignored)\n", err);
++}
+diff -Naur a/fs/aufs/vdir.c b/fs/aufs/vdir.c
+--- a/fs/aufs/vdir.c   1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/vdir.c   2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,876 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * virtual or vertical directory
++ */
++
++#include <linux/hash.h>
++#include "aufs.h"
++
++static unsigned int calc_size(int nlen)
++{
++      BUILD_BUG_ON(sizeof(ino_t) != sizeof(long));
++      return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
++}
++
++static int set_deblk_end(union au_vdir_deblk_p *p,
++                       union au_vdir_deblk_p *deblk_end)
++{
++      if (calc_size(0) <= deblk_end->deblk - p->deblk) {
++              p->de->de_str.len = 0;
++              /* smp_mb(); */
++              return 0;
++      }
++      return -1; /* error */
++}
++
++/* returns true or false */
++static int is_deblk_end(union au_vdir_deblk_p *p,
++                      union au_vdir_deblk_p *deblk_end)
++{
++      if (calc_size(0) <= deblk_end->deblk - p->deblk)
++              return !p->de->de_str.len;
++      return 1;
++}
++
++static unsigned char *last_deblk(struct au_vdir *vdir)
++{
++      return vdir->vd_deblk[vdir->vd_nblk - 1];
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * the allocated memory has to be freed by
++ * au_nhash_wh_free() or au_nhash_de_free().
++ */
++int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
++{
++      struct hlist_head *head;
++      unsigned int u;
++
++      head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
++      if (head) {
++              nhash->nh_num = num_hash;
++              nhash->nh_head = head;
++              for (u = 0; u < num_hash; u++)
++                      INIT_HLIST_HEAD(head++);
++              return 0; /* success */
++      }
++
++      return -ENOMEM;
++}
++
++static void nhash_count(struct hlist_head *head)
++{
++#if 0
++      unsigned long n;
++      struct hlist_node *pos;
++
++      n = 0;
++      hlist_for_each(pos, head)
++              n++;
++      AuInfo("%lu\n", n);
++#endif
++}
++
++static void au_nhash_wh_do_free(struct hlist_head *head)
++{
++      struct au_vdir_wh *tpos;
++      struct hlist_node *pos, *node;
++
++      hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
++              /* hlist_del(pos); */
++              kfree(tpos);
++      }
++}
++
++static void au_nhash_de_do_free(struct hlist_head *head)
++{
++      struct au_vdir_dehstr *tpos;
++      struct hlist_node *pos, *node;
++
++      hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
++              /* hlist_del(pos); */
++              au_cache_free_dehstr(tpos);
++      }
++}
++
++static void au_nhash_do_free(struct au_nhash *nhash,
++                           void (*free)(struct hlist_head *head))
++{
++      unsigned int u, n;
++      struct hlist_head *head;
++
++      n = nhash->nh_num;
++      head = nhash->nh_head;
++      for (u = 0; u < n; u++) {
++              nhash_count(head);
++              free(head++);
++      }
++      kfree(nhash->nh_head);
++}
++
++void au_nhash_wh_free(struct au_nhash *whlist)
++{
++      au_nhash_do_free(whlist, au_nhash_wh_do_free);
++}
++
++static void au_nhash_de_free(struct au_nhash *delist)
++{
++      au_nhash_do_free(delist, au_nhash_de_do_free);
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
++                          int limit)
++{
++      int num;
++      unsigned int u, n;
++      struct hlist_head *head;
++      struct au_vdir_wh *tpos;
++      struct hlist_node *pos;
++
++      num = 0;
++      n = whlist->nh_num;
++      head = whlist->nh_head;
++      for (u = 0; u < n; u++) {
++              hlist_for_each_entry(tpos, pos, head, wh_hash)
++                      if (tpos->wh_bindex == btgt && ++num > limit)
++                              return 1;
++              head++;
++      }
++      return 0;
++}
++
++static struct hlist_head *au_name_hash(struct au_nhash *nhash,
++                                     unsigned char *name,
++                                     unsigned int len)
++{
++      unsigned int v;
++      /* const unsigned int magic_bit = 12; */
++
++      v = 0;
++      while (len--)
++              v += *name++;
++      /* v = hash_long(v, magic_bit); */
++      v %= nhash->nh_num;
++      return nhash->nh_head + v;
++}
++
++static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
++                            int nlen)
++{
++      return str->len == nlen && !memcmp(str->name, name, nlen);
++}
++
++/* returns found or not */
++int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
++{
++      struct hlist_head *head;
++      struct au_vdir_wh *tpos;
++      struct hlist_node *pos;
++      struct au_vdir_destr *str;
++
++      head = au_name_hash(whlist, name, nlen);
++      hlist_for_each_entry(tpos, pos, head, wh_hash) {
++              str = &tpos->wh_str;
++              AuDbg("%.*s\n", str->len, str->name);
++              if (au_nhash_test_name(str, name, nlen))
++                      return 1;
++      }
++      return 0;
++}
++
++/* returns found(true) or not */
++static int test_known(struct au_nhash *delist, char *name, int nlen)
++{
++      struct hlist_head *head;
++      struct au_vdir_dehstr *tpos;
++      struct hlist_node *pos;
++      struct au_vdir_destr *str;
++
++      head = au_name_hash(delist, name, nlen);
++      hlist_for_each_entry(tpos, pos, head, hash) {
++              str = tpos->str;
++              AuDbg("%.*s\n", str->len, str->name);
++              if (au_nhash_test_name(str, name, nlen))
++                      return 1;
++      }
++      return 0;
++}
++
++static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
++                          unsigned char d_type)
++{
++#ifdef CONFIG_AUFS_SHWH
++      wh->wh_ino = ino;
++      wh->wh_type = d_type;
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
++                     unsigned int d_type, aufs_bindex_t bindex,
++                     unsigned char shwh)
++{
++      int err;
++      struct au_vdir_destr *str;
++      struct au_vdir_wh *wh;
++
++      AuDbg("%.*s\n", nlen, name);
++      err = -ENOMEM;
++      wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
++      if (unlikely(!wh))
++              goto out;
++
++      err = 0;
++      wh->wh_bindex = bindex;
++      if (shwh)
++              au_shwh_init_wh(wh, ino, d_type);
++      str = &wh->wh_str;
++      str->len = nlen;
++      memcpy(str->name, name, nlen);
++      hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
++      /* smp_mb(); */
++
++ out:
++      return err;
++}
++
++static int append_deblk(struct au_vdir *vdir)
++{
++      int err;
++      unsigned long ul;
++      const unsigned int deblk_sz = vdir->vd_deblk_sz;
++      union au_vdir_deblk_p p, deblk_end;
++      unsigned char **o;
++
++      err = -ENOMEM;
++      o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
++                   GFP_NOFS);
++      if (unlikely(!o))
++              goto out;
++
++      vdir->vd_deblk = o;
++      p.deblk = kmalloc(deblk_sz, GFP_NOFS);
++      if (p.deblk) {
++              ul = vdir->vd_nblk++;
++              vdir->vd_deblk[ul] = p.deblk;
++              vdir->vd_last.ul = ul;
++              vdir->vd_last.p.deblk = p.deblk;
++              deblk_end.deblk = p.deblk + deblk_sz;
++              err = set_deblk_end(&p, &deblk_end);
++      }
++
++ out:
++      return err;
++}
++
++static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
++                   unsigned int d_type, struct au_nhash *delist)
++{
++      int err;
++      unsigned int sz;
++      const unsigned int deblk_sz = vdir->vd_deblk_sz;
++      union au_vdir_deblk_p p, *room, deblk_end;
++      struct au_vdir_dehstr *dehstr;
++
++      p.deblk = last_deblk(vdir);
++      deblk_end.deblk = p.deblk + deblk_sz;
++      room = &vdir->vd_last.p;
++      AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
++                || !is_deblk_end(room, &deblk_end));
++
++      sz = calc_size(nlen);
++      if (unlikely(sz > deblk_end.deblk - room->deblk)) {
++              err = append_deblk(vdir);
++              if (unlikely(err))
++                      goto out;
++
++              p.deblk = last_deblk(vdir);
++              deblk_end.deblk = p.deblk + deblk_sz;
++              /* smp_mb(); */
++              AuDebugOn(room->deblk != p.deblk);
++      }
++
++      err = -ENOMEM;
++      dehstr = au_cache_alloc_dehstr();
++      if (unlikely(!dehstr))
++              goto out;
++
++      dehstr->str = &room->de->de_str;
++      hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
++      room->de->de_ino = ino;
++      room->de->de_type = d_type;
++      room->de->de_str.len = nlen;
++      memcpy(room->de->de_str.name, name, nlen);
++
++      err = 0;
++      room->deblk += sz;
++      if (unlikely(set_deblk_end(room, &deblk_end)))
++              err = append_deblk(vdir);
++      /* smp_mb(); */
++
++ out:
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_vdir_free(struct au_vdir *vdir)
++{
++      unsigned char **deblk;
++
++      deblk = vdir->vd_deblk;
++      while (vdir->vd_nblk--)
++              kfree(*deblk++);
++      kfree(vdir->vd_deblk);
++      au_cache_free_vdir(vdir);
++}
++
++static struct au_vdir *alloc_vdir(struct super_block *sb)
++{
++      struct au_vdir *vdir;
++      int err;
++
++      err = -ENOMEM;
++      vdir = au_cache_alloc_vdir();
++      if (unlikely(!vdir))
++              goto out;
++
++      vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
++      if (unlikely(!vdir->vd_deblk))
++              goto out_free;
++
++      vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
++      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:
++      au_cache_free_vdir(vdir);
++ out:
++      vdir = ERR_PTR(err);
++      return vdir;
++}
++
++static int reinit_vdir(struct au_vdir *vdir)
++{
++      int err;
++      union au_vdir_deblk_p p, deblk_end;
++
++      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 + vdir->vd_deblk_sz;
++      err = set_deblk_end(&p, &deblk_end);
++      /* keep vd_dblk_sz */
++      vdir->vd_last.ul = 0;
++      vdir->vd_last.p.deblk = vdir->vd_deblk[0];
++      vdir->vd_version = 0;
++      vdir->vd_jiffy = 0;
++      /* smp_mb(); */
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++                unsigned int d_type, ino_t *ino)
++{
++      int err;
++      struct mutex *mtx;
++      const int isdir = (d_type == DT_DIR);
++
++      /* prevent hardlinks from race condition */
++      mtx = NULL;
++      if (!isdir) {
++              mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
++              mutex_lock(mtx);
++      }
++      err = au_xino_read(sb, bindex, h_ino, ino);
++      if (unlikely(err))
++              goto out;
++
++      if (!*ino) {
++              err = -EIO;
++              *ino = au_xino_new_ino(sb);
++              if (unlikely(!*ino))
++                      goto out;
++              err = au_xino_write(sb, bindex, h_ino, *ino);
++              if (unlikely(err))
++                      goto out;
++      }
++
++ out:
++      if (!isdir)
++              mutex_unlock(mtx);
++      return err;
++}
++
++static int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++                   unsigned int d_type, ino_t *ino)
++{
++#ifdef CONFIG_AUFS_SHWH
++      return au_ino(sb, bindex, h_ino, d_type, ino);
++#else
++      return 0;
++#endif
++}
++
++#define AuFillVdir_CALLED     1
++#define AuFillVdir_WHABLE     (1 << 1)
++#define AuFillVdir_SHWH               (1 << 2)
++#define au_ftest_fillvdir(flags, name)        ((flags) & AuFillVdir_##name)
++#define au_fset_fillvdir(flags, name) { (flags) |= AuFillVdir_##name; }
++#define au_fclr_fillvdir(flags, name) { (flags) &= ~AuFillVdir_##name; }
++
++#ifndef CONFIG_AUFS_SHWH
++#undef AuFillVdir_SHWH
++#define AuFillVdir_SHWH               0
++#endif
++
++struct fillvdir_arg {
++      struct file             *file;
++      struct au_vdir          *vdir;
++      struct au_nhash         delist;
++      struct au_nhash         whlist;
++      aufs_bindex_t           bindex;
++      unsigned int            flags;
++      int                     err;
++};
++
++static int fillvdir(void *__arg, const char *__name, int nlen,
++                  loff_t offset __maybe_unused, u64 h_ino,
++                  unsigned int d_type)
++{
++      struct fillvdir_arg *arg = __arg;
++      char *name = (void *)__name;
++      struct super_block *sb;
++      ino_t ino;
++      const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
++
++      arg->err = 0;
++      sb = arg->file->f_dentry->d_sb;
++      au_fset_fillvdir(arg->flags, CALLED);
++      /* smp_mb(); */
++      if (nlen <= AUFS_WH_PFX_LEN
++          || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
++              if (test_known(&arg->delist, name, nlen)
++                  || au_nhash_test_known_wh(&arg->whlist, name, nlen))
++                      goto out; /* already exists or whiteouted */
++
++              sb = arg->file->f_dentry->d_sb;
++              arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
++              if (!arg->err)
++                      arg->err = append_de(arg->vdir, name, nlen, ino,
++                                           d_type, &arg->delist);
++      } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
++              name += AUFS_WH_PFX_LEN;
++              nlen -= AUFS_WH_PFX_LEN;
++              if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
++                      goto out; /* already whiteouted */
++
++              if (shwh)
++                      arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
++                                           &ino);
++              if (!arg->err)
++                      arg->err = au_nhash_append_wh
++                              (&arg->whlist, name, nlen, ino, d_type,
++                               arg->bindex, shwh);
++      }
++
++ out:
++      if (!arg->err)
++              arg->vdir->vd_jiffy = jiffies;
++      /* smp_mb(); */
++      AuTraceErr(arg->err);
++      return arg->err;
++}
++
++static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
++                        struct au_nhash *whlist, struct au_nhash *delist)
++{
++#ifdef CONFIG_AUFS_SHWH
++      int err;
++      unsigned int nh, u;
++      struct hlist_head *head;
++      struct au_vdir_wh *tpos;
++      struct hlist_node *pos, *n;
++      char *p, *o;
++      struct au_vdir_destr *destr;
++
++      AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
++
++      err = -ENOMEM;
++      o = p = __getname();
++      if (unlikely(!p))
++              goto out;
++
++      err = 0;
++      nh = whlist->nh_num;
++      memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
++      p += AUFS_WH_PFX_LEN;
++      for (u = 0; u < nh; u++) {
++              head = whlist->nh_head + u;
++              hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
++                      destr = &tpos->wh_str;
++                      memcpy(p, destr->name, destr->len);
++                      err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
++                                      tpos->wh_ino, tpos->wh_type, delist);
++                      if (unlikely(err))
++                              break;
++              }
++      }
++
++      __putname(o);
++
++ out:
++      AuTraceErr(err);
++      return err;
++#else
++      return 0;
++#endif
++}
++
++static int au_do_read_vdir(struct fillvdir_arg *arg)
++{
++      int err;
++      unsigned int rdhash;
++      loff_t offset;
++      aufs_bindex_t bend, bindex, bstart;
++      unsigned char shwh;
++      struct file *hf, *file;
++      struct super_block *sb;
++
++      file = arg->file;
++      sb = file->f_dentry->d_sb;
++      rdhash = au_sbi(sb)->si_rdhash;
++      err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
++      if (unlikely(err))
++              goto out;
++      err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
++      if (unlikely(err))
++              goto out_delist;
++
++      err = 0;
++      arg->flags = 0;
++      shwh = 0;
++      if (au_opt_test(au_mntflags(sb), SHWH)) {
++              shwh = 1;
++              au_fset_fillvdir(arg->flags, SHWH);
++      }
++      bstart = au_fbstart(file);
++      bend = au_fbend(file);
++      for (bindex = bstart; !err && bindex <= bend; bindex++) {
++              hf = au_h_fptr(file, bindex);
++              if (!hf)
++                      continue;
++
++              offset = vfsub_llseek(hf, 0, SEEK_SET);
++              err = offset;
++              if (unlikely(offset))
++                      break;
++
++              arg->bindex = bindex;
++              au_fclr_fillvdir(arg->flags, WHABLE);
++              if (shwh
++                  || (bindex != bend
++                      && au_br_whable(au_sbr_perm(sb, bindex))))
++                      au_fset_fillvdir(arg->flags, WHABLE);
++              do {
++                      arg->err = 0;
++                      au_fclr_fillvdir(arg->flags, CALLED);
++                      /* smp_mb(); */
++                      err = vfsub_readdir(hf, fillvdir, arg);
++                      if (err >= 0)
++                              err = arg->err;
++              } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
++      }
++
++      if (!err && shwh)
++              err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
++
++      au_nhash_wh_free(&arg->whlist);
++
++ out_delist:
++      au_nhash_de_free(&arg->delist);
++ out:
++      return err;
++}
++
++static int read_vdir(struct file *file, int may_read)
++{
++      int err;
++      unsigned long expire;
++      unsigned char do_read;
++      struct fillvdir_arg arg;
++      struct inode *inode;
++      struct au_vdir *vdir, *allocated;
++
++      err = 0;
++      inode = file->f_dentry->d_inode;
++      IMustLock(inode);
++      allocated = NULL;
++      do_read = 0;
++      expire = au_sbi(inode->i_sb)->si_rdcache;
++      vdir = au_ivdir(inode);
++      if (!vdir) {
++              do_read = 1;
++              vdir = alloc_vdir(inode->i_sb);
++              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))) {
++              do_read = 1;
++              err = reinit_vdir(vdir);
++              if (unlikely(err))
++                      goto out;
++      }
++
++      if (!do_read)
++              return 0; /* success */
++
++      arg.file = file;
++      arg.vdir = vdir;
++      err = au_do_read_vdir(&arg);
++      if (!err) {
++              /* file->f_pos = 0; */
++              vdir->vd_version = inode->i_version;
++              vdir->vd_last.ul = 0;
++              vdir->vd_last.p.deblk = vdir->vd_deblk[0];
++              if (allocated)
++                      au_set_ivdir(inode, allocated);
++      } else if (allocated)
++              au_vdir_free(allocated);
++
++ out:
++      return err;
++}
++
++static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
++{
++      int err, rerr;
++      unsigned long ul, n;
++      const unsigned int deblk_sz = src->vd_deblk_sz;
++
++      AuDebugOn(tgt->vd_nblk != 1);
++
++      err = -ENOMEM;
++      if (tgt->vd_nblk < src->vd_nblk) {
++              unsigned char **p;
++
++              p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
++                           GFP_NOFS);
++              if (unlikely(!p))
++                      goto out;
++              tgt->vd_deblk = p;
++      }
++
++      tgt->vd_nblk = src->vd_nblk;
++      tgt->vd_deblk_sz = deblk_sz;
++      memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
++      /* 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;
++
++      n = src->vd_nblk;
++      for (ul = 1; ul < n; ul++) {
++              tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
++                                          GFP_NOFS);
++              if (unlikely(!tgt->vd_deblk[ul]))
++                      goto out;
++      }
++      /* smp_mb(); */
++      return 0; /* success */
++
++ out:
++      rerr = reinit_vdir(tgt);
++      BUG_ON(rerr);
++      return err;
++}
++
++int au_vdir_init(struct file *file)
++{
++      int err;
++      struct inode *inode;
++      struct au_vdir *vdir_cache, *allocated;
++
++      err = read_vdir(file, !file->f_pos);
++      if (unlikely(err))
++              goto out;
++
++      allocated = NULL;
++      vdir_cache = au_fvdir_cache(file);
++      if (!vdir_cache) {
++              vdir_cache = alloc_vdir(file->f_dentry->d_sb);
++              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 */
++
++      inode = file->f_dentry->d_inode;
++      err = copy_vdir(vdir_cache, au_ivdir(inode));
++      if (!err) {
++              file->f_version = inode->i_version;
++              if (allocated)
++                      au_set_fvdir_cache(file, allocated);
++      } else if (allocated)
++              au_vdir_free(allocated);
++
++ out:
++      return err;
++}
++
++static loff_t calc_offset(struct au_vdir *vdir)
++{
++      loff_t offset;
++      union au_vdir_deblk_p p;
++
++      p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
++      offset = vdir->vd_last.p.deblk - p.deblk;
++      offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
++      return offset;
++}
++
++/* returns true or false */
++static int seek_vdir(struct file *file)
++{
++      int valid;
++      unsigned int deblk_sz;
++      unsigned long ul, n;
++      loff_t offset;
++      union au_vdir_deblk_p p, deblk_end;
++      struct au_vdir *vdir_cache;
++
++      valid = 1;
++      vdir_cache = au_fvdir_cache(file);
++      offset = calc_offset(vdir_cache);
++      AuDbg("offset %lld\n", offset);
++      if (file->f_pos == offset)
++              goto out;
++
++      vdir_cache->vd_last.ul = 0;
++      vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
++      if (!file->f_pos)
++              goto out;
++
++      valid = 0;
++      deblk_sz = vdir_cache->vd_deblk_sz;
++      ul = div64_u64(file->f_pos, deblk_sz);
++      AuDbg("ul %lu\n", ul);
++      if (ul >= vdir_cache->vd_nblk)
++              goto out;
++
++      n = vdir_cache->vd_nblk;
++      for (; ul < n; ul++) {
++              p.deblk = vdir_cache->vd_deblk[ul];
++              deblk_end.deblk = p.deblk + deblk_sz;
++              offset = ul;
++              offset *= deblk_sz;
++              while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
++                      unsigned int l;
++
++                      l = calc_size(p.de->de_str.len);
++                      offset += l;
++                      p.deblk += l;
++              }
++              if (!is_deblk_end(&p, &deblk_end)) {
++                      valid = 1;
++                      vdir_cache->vd_last.ul = ul;
++                      vdir_cache->vd_last.p = p;
++                      break;
++              }
++      }
++
++ out:
++      /* smp_mb(); */
++      AuTraceErr(!valid);
++      return valid;
++}
++
++int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
++{
++      int err;
++      unsigned int l, deblk_sz;
++      union au_vdir_deblk_p deblk_end;
++      struct au_vdir *vdir_cache;
++      struct au_vdir_de *de;
++
++      vdir_cache = au_fvdir_cache(file);
++      if (!seek_vdir(file))
++              return 0;
++
++      deblk_sz = vdir_cache->vd_deblk_sz;
++      while (1) {
++              deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
++              deblk_end.deblk += deblk_sz;
++              while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
++                      de = vdir_cache->vd_last.p.de;
++                      AuDbg("%.*s, off%lld, i%lu, dt%d\n",
++                            de->de_str.len, de->de_str.name, file->f_pos,
++                            (unsigned long)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)) {
++                              AuTraceErr(err);
++                              /* todo: ignore the error caused by udba? */
++                              /* return err; */
++                              return 0;
++                      }
++
++                      l = calc_size(de->de_str.len);
++                      vdir_cache->vd_last.p.deblk += l;
++                      file->f_pos += l;
++              }
++              if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
++                      vdir_cache->vd_last.ul++;
++                      vdir_cache->vd_last.p.deblk
++                              = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
++                      file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
++                      continue;
++              }
++              break;
++      }
++
++      /* smp_mb(); */
++      return 0;
++}
+diff -Naur a/fs/aufs/vfsub.c b/fs/aufs/vfsub.c
+--- a/fs/aufs/vfsub.c  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/vfsub.c  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,736 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * sub-routines for VFS
++ */
++
++#include <linux/namei.h>
++#include <linux/security.h>
++#include <linux/splice.h>
++#include <linux/uaccess.h>
++#include "aufs.h"
++
++int vfsub_update_h_iattr(struct path *h_path, int *did)
++{
++      int err;
++      struct kstat st;
++      struct super_block *h_sb;
++
++      /* for remote fs, leave work for its getattr or d_revalidate */
++      /* for bad i_attr fs, handle them in aufs_getattr() */
++      /* still some fs may acquire i_mutex. we need to skip them */
++      err = 0;
++      if (!did)
++              did = &err;
++      h_sb = h_path->dentry->d_sb;
++      *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
++      if (*did)
++              err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct file *vfsub_filp_open(const char *path, int oflags, int mode)
++{
++      struct file *file;
++
++      lockdep_off();
++      file = filp_open(path, oflags, mode);
++      lockdep_on();
++      if (IS_ERR(file))
++              goto out;
++      vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
++
++ out:
++      return file;
++}
++
++int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
++{
++      int err;
++
++      /* lockdep_off(); */
++      err = kern_path(name, flags, path);
++      /* lockdep_on(); */
++      if (!err && path->dentry->d_inode)
++              vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
++      return err;
++}
++
++struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
++                                  int len)
++{
++      struct path path = {
++              .mnt = NULL
++      };
++
++      IMustLock(parent->d_inode);
++
++      path.dentry = lookup_one_len(name, parent, len);
++      if (IS_ERR(path.dentry))
++              goto out;
++      if (path.dentry->d_inode)
++              vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
++
++ out:
++      return path.dentry;
++}
++
++struct dentry *vfsub_lookup_hash(struct nameidata *nd)
++{
++      struct path path = {
++              .mnt = nd->path.mnt
++      };
++
++      IMustLock(nd->path.dentry->d_inode);
++
++      path.dentry = lookup_hash(nd);
++      if (!IS_ERR(path.dentry) && path.dentry->d_inode)
++              vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
++
++      return path.dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
++                               struct dentry *d2, struct au_hinode *hdir2)
++{
++      struct dentry *d;
++
++      lockdep_off();
++      d = lock_rename(d1, d2);
++      lockdep_on();
++      au_hin_suspend(hdir1);
++      if (hdir1 != hdir2)
++              au_hin_suspend(hdir2);
++
++      return d;
++}
++
++void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
++                       struct dentry *d2, struct au_hinode *hdir2)
++{
++      au_hin_resume(hdir1);
++      if (hdir1 != hdir2)
++              au_hin_resume(hdir2);
++      lockdep_off();
++      unlock_rename(d1, d2);
++      lockdep_on();
++}
++
++/* ---------------------------------------------------------------------- */
++
++int vfsub_create(struct inode *dir, struct path *path, int mode)
++{
++      int err;
++      struct dentry *d;
++
++      IMustLock(dir);
++
++      d = path->dentry;
++      path->dentry = d->d_parent;
++      err = security_path_mknod(path, path->dentry, mode, 0);
++      path->dentry = d;
++      if (unlikely(err))
++              goto out;
++
++      if (au_test_fs_null_nd(dir->i_sb))
++              err = vfs_create(dir, path->dentry, mode, NULL);
++      else {
++              struct nameidata h_nd;
++
++              memset(&h_nd, 0, sizeof(h_nd));
++              h_nd.flags = LOOKUP_CREATE;
++              h_nd.intent.open.flags = O_CREAT
++                      | vfsub_fmode_to_uint(FMODE_READ);
++              h_nd.intent.open.create_mode = mode;
++              h_nd.path.dentry = path->dentry->d_parent;
++              h_nd.path.mnt = path->mnt;
++              path_get(&h_nd.path);
++              err = vfs_create(dir, path->dentry, mode, &h_nd);
++              path_put(&h_nd.path);
++      }
++
++      if (!err) {
++              struct path tmp = *path;
++              int did;
++
++              vfsub_update_h_iattr(&tmp, &did);
++              if (did) {
++                      tmp.dentry = path->dentry->d_parent;
++                      vfsub_update_h_iattr(&tmp, /*did*/NULL);
++              }
++              /*ignore*/
++      }
++
++ out:
++      return err;
++}
++
++int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
++{
++      int err;
++      struct dentry *d;
++
++      IMustLock(dir);
++
++      d = path->dentry;
++      path->dentry = d->d_parent;
++      err = security_path_symlink(path, path->dentry, symname);
++      path->dentry = d;
++      if (unlikely(err))
++              goto out;
++
++      err = vfs_symlink(dir, path->dentry, symname);
++      if (!err) {
++              struct path tmp = *path;
++              int did;
++
++              vfsub_update_h_iattr(&tmp, &did);
++              if (did) {
++                      tmp.dentry = path->dentry->d_parent;
++                      vfsub_update_h_iattr(&tmp, /*did*/NULL);
++              }
++              /*ignore*/
++      }
++
++ out:
++      return err;
++}
++
++int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
++{
++      int err;
++      struct dentry *d;
++
++      IMustLock(dir);
++
++      d = path->dentry;
++      path->dentry = d->d_parent;
++      err = security_path_mknod(path, path->dentry, mode, dev);
++      path->dentry = d;
++      if (unlikely(err))
++              goto out;
++
++      err = vfs_mknod(dir, path->dentry, mode, dev);
++      if (!err) {
++              struct path tmp = *path;
++              int did;
++
++              vfsub_update_h_iattr(&tmp, &did);
++              if (did) {
++                      tmp.dentry = path->dentry->d_parent;
++                      vfsub_update_h_iattr(&tmp, /*did*/NULL);
++              }
++              /*ignore*/
++      }
++
++ out:
++      return err;
++}
++
++static int au_test_nlink(struct inode *inode)
++{
++      const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
++
++      if (!au_test_fs_no_limit_nlink(inode->i_sb)
++          || inode->i_nlink < link_max)
++              return 0;
++      return -EMLINK;
++}
++
++int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
++{
++      int err;
++      struct dentry *d;
++
++      IMustLock(dir);
++
++      err = au_test_nlink(src_dentry->d_inode);
++      if (unlikely(err))
++              return err;
++
++      d = path->dentry;
++      path->dentry = d->d_parent;
++      err = security_path_link(src_dentry, path, path->dentry);
++      path->dentry = d;
++      if (unlikely(err))
++              goto out;
++
++      lockdep_off();
++      err = vfs_link(src_dentry, dir, path->dentry);
++      lockdep_on();
++      if (!err) {
++              struct path tmp = *path;
++              int did;
++
++              /* fuse has different memory inode for the same inumber */
++              vfsub_update_h_iattr(&tmp, &did);
++              if (did) {
++                      tmp.dentry = path->dentry->d_parent;
++                      vfsub_update_h_iattr(&tmp, /*did*/NULL);
++                      tmp.dentry = src_dentry;
++                      vfsub_update_h_iattr(&tmp, /*did*/NULL);
++              }
++              /*ignore*/
++      }
++
++ out:
++      return err;
++}
++
++int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
++               struct inode *dir, struct path *path)
++{
++      int err;
++      struct path tmp = {
++              .mnt    = path->mnt
++      };
++      struct dentry *d;
++
++      IMustLock(dir);
++      IMustLock(src_dir);
++
++      d = path->dentry;
++      path->dentry = d->d_parent;
++      tmp.dentry = src_dentry->d_parent;
++      err = security_path_rename(&tmp, src_dentry, path, path->dentry);
++      path->dentry = d;
++      if (unlikely(err))
++              goto out;
++
++      lockdep_off();
++      err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
++      lockdep_on();
++      if (!err) {
++              int did;
++
++              tmp.dentry = d->d_parent;
++              vfsub_update_h_iattr(&tmp, &did);
++              if (did) {
++                      tmp.dentry = src_dentry;
++                      vfsub_update_h_iattr(&tmp, /*did*/NULL);
++                      tmp.dentry = src_dentry->d_parent;
++                      vfsub_update_h_iattr(&tmp, /*did*/NULL);
++              }
++              /*ignore*/
++      }
++
++ out:
++      return err;
++}
++
++int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
++{
++      int err;
++      struct dentry *d;
++
++      IMustLock(dir);
++
++      d = path->dentry;
++      path->dentry = d->d_parent;
++      err = security_path_mkdir(path, path->dentry, mode);
++      path->dentry = d;
++      if (unlikely(err))
++              goto out;
++
++      err = vfs_mkdir(dir, path->dentry, mode);
++      if (!err) {
++              struct path tmp = *path;
++              int did;
++
++              vfsub_update_h_iattr(&tmp, &did);
++              if (did) {
++                      tmp.dentry = path->dentry->d_parent;
++                      vfsub_update_h_iattr(&tmp, /*did*/NULL);
++              }
++              /*ignore*/
++      }
++
++ out:
++      return err;
++}
++
++int vfsub_rmdir(struct inode *dir, struct path *path)
++{
++      int err;
++      struct dentry *d;
++
++      IMustLock(dir);
++
++      d = path->dentry;
++      path->dentry = d->d_parent;
++      err = security_path_rmdir(path, path->dentry);
++      path->dentry = d;
++      if (unlikely(err))
++              goto out;
++
++      lockdep_off();
++      err = vfs_rmdir(dir, path->dentry);
++      lockdep_on();
++      if (!err) {
++              struct path tmp = {
++                      .dentry = path->dentry->d_parent,
++                      .mnt    = path->mnt
++              };
++
++              vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
++      }
++
++ out:
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
++                   loff_t *ppos)
++{
++      ssize_t err;
++
++      err = vfs_read(file, ubuf, count, ppos);
++      if (err >= 0)
++              vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
++      return err;
++}
++
++/* todo: kernel_read()? */
++ssize_t 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 = vfsub_read_u(file, (char __user *)kbuf, count, ppos);
++      set_fs(oldfs);
++      return err;
++}
++
++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
++                    loff_t *ppos)
++{
++      ssize_t err;
++
++      lockdep_off();
++      err = vfs_write(file, ubuf, count, ppos);
++      lockdep_on();
++      if (err >= 0)
++              vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
++      return err;
++}
++
++ssize_t 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 = vfsub_write_u(file, (const char __user *)kbuf, count, ppos);
++      set_fs(oldfs);
++      return err;
++}
++
++int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
++{
++      int err;
++
++      lockdep_off();
++      err = vfs_readdir(file, filldir, arg);
++      lockdep_on();
++      if (err >= 0)
++              vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
++      return err;
++}
++
++long vfsub_splice_to(struct file *in, loff_t *ppos,
++                   struct pipe_inode_info *pipe, size_t len,
++                   unsigned int flags)
++{
++      long err;
++
++      lockdep_off();
++      err = do_splice_to(in, ppos, pipe, len, flags);
++      lockdep_on();
++      if (err >= 0)
++              vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
++      return err;
++}
++
++long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
++                     loff_t *ppos, size_t len, unsigned int flags)
++{
++      long err;
++
++      lockdep_off();
++      err = do_splice_from(pipe, out, ppos, len, flags);
++      lockdep_on();
++      if (err >= 0)
++              vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
++      return err;
++}
++
++/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
++int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
++              struct file *h_file)
++{
++      int err;
++      struct inode *h_inode;
++
++      h_inode = h_path->dentry->d_inode;
++      if (!h_file) {
++              err = mnt_want_write(h_path->mnt);
++              if (err)
++                      goto out;
++              err = inode_permission(h_inode, MAY_WRITE);
++              if (err)
++                      goto out_mnt;
++              err = get_write_access(h_inode);
++              if (err)
++                      goto out_mnt;
++              err = break_lease(h_inode, vfsub_fmode_to_uint(FMODE_WRITE));
++              if (err)
++                      goto out_inode;
++      }
++
++      err = locks_verify_truncate(h_inode, h_file, length);
++      if (!err)
++              err = security_path_truncate(h_path, length, attr);
++      if (!err) {
++              lockdep_off();
++              err = do_truncate(h_path->dentry, length, attr, h_file);
++              lockdep_on();
++      }
++
++ out_inode:
++      if (!h_file)
++              put_write_access(h_inode);
++ out_mnt:
++      if (!h_file)
++              mnt_drop_write(h_path->mnt);
++ out:
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct au_vfsub_mkdir_args {
++      int *errp;
++      struct inode *dir;
++      struct path *path;
++      int mode;
++};
++
++static void au_call_vfsub_mkdir(void *args)
++{
++      struct au_vfsub_mkdir_args *a = args;
++      *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
++}
++
++int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
++{
++      int err, do_sio, wkq_err;
++
++      do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
++      if (!do_sio)
++              err = vfsub_mkdir(dir, path, mode);
++      else {
++              struct au_vfsub_mkdir_args args = {
++                      .errp   = &err,
++                      .dir    = dir,
++                      .path   = path,
++                      .mode   = mode
++              };
++              wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
++              if (unlikely(wkq_err))
++                      err = wkq_err;
++      }
++
++      return err;
++}
++
++struct au_vfsub_rmdir_args {
++      int *errp;
++      struct inode *dir;
++      struct path *path;
++};
++
++static void au_call_vfsub_rmdir(void *args)
++{
++      struct au_vfsub_rmdir_args *a = args;
++      *a->errp = vfsub_rmdir(a->dir, a->path);
++}
++
++int vfsub_sio_rmdir(struct inode *dir, struct path *path)
++{
++      int err, do_sio, wkq_err;
++
++      do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
++      if (!do_sio)
++              err = vfsub_rmdir(dir, path);
++      else {
++              struct au_vfsub_rmdir_args args = {
++                      .errp   = &err,
++                      .dir    = dir,
++                      .path   = path
++              };
++              wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
++              if (unlikely(wkq_err))
++                      err = wkq_err;
++      }
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct notify_change_args {
++      int *errp;
++      struct path *path;
++      struct iattr *ia;
++};
++
++static void call_notify_change(void *args)
++{
++      struct notify_change_args *a = args;
++      struct inode *h_inode;
++
++      h_inode = a->path->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->path->dentry, a->ia);
++              lockdep_on();
++              if (!*a->errp)
++                      vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
++      }
++      AuTraceErr(*a->errp);
++}
++
++int vfsub_notify_change(struct path *path, struct iattr *ia)
++{
++      int err;
++      struct notify_change_args args = {
++              .errp   = &err,
++              .path   = path,
++              .ia     = ia
++      };
++
++      call_notify_change(&args);
++
++      return err;
++}
++
++int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
++{
++      int err, wkq_err;
++      struct notify_change_args args = {
++              .errp   = &err,
++              .path   = path,
++              .ia     = ia
++      };
++
++      wkq_err = au_wkq_wait(call_notify_change, &args);
++      if (unlikely(wkq_err))
++              err = wkq_err;
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct unlink_args {
++      int *errp;
++      struct inode *dir;
++      struct path *path;
++};
++
++static void call_unlink(void *args)
++{
++      struct unlink_args *a = args;
++      struct dentry *d = a->path->dentry;
++      struct inode *h_inode;
++      const int stop_sillyrename = (au_test_nfs(d->d_sb)
++                                    && atomic_read(&d->d_count) == 1);
++
++      IMustLock(a->dir);
++
++      a->path->dentry = d->d_parent;
++      *a->errp = security_path_unlink(a->path, d);
++      a->path->dentry = d;
++      if (unlikely(*a->errp))
++              return;
++
++      if (!stop_sillyrename)
++              dget(d);
++      h_inode = d->d_inode;
++      if (h_inode)
++              atomic_inc(&h_inode->i_count);
++
++      lockdep_off();
++      *a->errp = vfs_unlink(a->dir, d);
++      lockdep_on();
++      if (!*a->errp) {
++              struct path tmp = {
++                      .dentry = d->d_parent,
++                      .mnt    = a->path->mnt
++              };
++              vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
++      }
++
++      if (!stop_sillyrename)
++              dput(d);
++      if (h_inode)
++              iput(h_inode);
++
++      AuTraceErr(*a->errp);
++}
++
++/*
++ * @dir: must be locked.
++ * @dentry: target dentry.
++ */
++int vfsub_unlink(struct inode *dir, struct path *path, int force)
++{
++      int err;
++      struct unlink_args args = {
++              .errp   = &err,
++              .dir    = dir,
++              .path   = path
++      };
++
++      if (!force)
++              call_unlink(&args);
++      else {
++              int wkq_err;
++
++              wkq_err = au_wkq_wait(call_unlink, &args);
++              if (unlikely(wkq_err))
++                      err = wkq_err;
++      }
++
++      return err;
++}
+diff -Naur a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h
+--- a/fs/aufs/vfsub.h  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/vfsub.h  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,171 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * sub-routines for VFS
++ */
++
++#ifndef __AUFS_VFSUB_H__
++#define __AUFS_VFSUB_H__
++
++#ifdef __KERNEL__
++
++#include <linux/fs.h>
++#include <linux/fs_stack.h>
++
++/* ---------------------------------------------------------------------- */
++
++/* lock subclass for lower inode */
++/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
++/* reduce? gave up. */
++enum {
++      AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
++      AuLsc_I_PARENT,         /* lower inode, parent first */
++      AuLsc_I_PARENT2,        /* copyup dirs */
++      AuLsc_I_CHILD,
++      AuLsc_I_CHILD2,
++      AuLsc_I_End
++};
++
++/* to debug easier, do not make them inlined functions */
++#define MtxMustLock(mtx)      AuDebugOn(!mutex_is_locked(mtx))
++#define IMustLock(i)          MtxMustLock(&(i)->i_mutex)
++
++/* ---------------------------------------------------------------------- */
++
++static inline void vfsub_copy_inode_size(struct inode *inode,
++                                       struct inode *h_inode)
++{
++      spin_lock(&inode->i_lock);
++      fsstack_copy_inode_size(inode, h_inode);
++      spin_unlock(&inode->i_lock);
++}
++
++int vfsub_update_h_iattr(struct path *h_path, int *did);
++struct file *vfsub_filp_open(const char *path, int oflags, int mode);
++int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
++struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
++                                  int len);
++struct dentry *vfsub_lookup_hash(struct nameidata *nd);
++
++/* ---------------------------------------------------------------------- */
++
++struct au_hinode;
++struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
++                               struct dentry *d2, struct au_hinode *hdir2);
++void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
++                       struct dentry *d2, struct au_hinode *hdir2);
++
++int vfsub_create(struct inode *dir, struct path *path, int mode);
++int vfsub_symlink(struct inode *dir, struct path *path,
++                const char *symname);
++int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
++int vfsub_link(struct dentry *src_dentry, struct inode *dir,
++             struct path *path);
++int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
++               struct inode *hdir, struct path *path);
++int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
++int vfsub_rmdir(struct inode *dir, struct path *path);
++
++/* ---------------------------------------------------------------------- */
++
++ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
++                   loff_t *ppos);
++ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
++                      loff_t *ppos);
++ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
++                    loff_t *ppos);
++ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
++                    loff_t *ppos);
++int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
++
++static inline void vfsub_file_accessed(struct file *h_file)
++{
++      file_accessed(h_file);
++      vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
++}
++
++static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
++                                   struct dentry *h_dentry)
++{
++      struct path h_path = {
++              .dentry = h_dentry,
++              .mnt    = h_mnt
++      };
++      touch_atime(h_mnt, h_dentry);
++      vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
++}
++
++long vfsub_splice_to(struct file *in, loff_t *ppos,
++                   struct pipe_inode_info *pipe, size_t len,
++                   unsigned int flags);
++long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
++                     loff_t *ppos, size_t len, unsigned int flags);
++int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
++              struct file *h_file);
++
++/* ---------------------------------------------------------------------- */
++
++static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
++{
++      loff_t err;
++
++      lockdep_off();
++      err = vfs_llseek(file, offset, origin);
++      lockdep_on();
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* dirty workaround for strict type of fmode_t */
++union vfsub_fmu {
++      fmode_t fm;
++      unsigned int ui;
++};
++
++static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
++{
++      union vfsub_fmu u = {
++              .fm = fm
++      };
++
++      BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
++
++      return u.ui;
++}
++
++static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
++{
++      union vfsub_fmu u = {
++              .ui = ui
++      };
++
++      return u.fm;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
++int vfsub_sio_rmdir(struct inode *dir, struct path *path);
++int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
++int vfsub_notify_change(struct path *path, struct iattr *ia);
++int vfsub_unlink(struct inode *dir, struct path *path, int force);
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_VFSUB_H__ */
+diff -Naur a/fs/aufs/wbr_policy.c b/fs/aufs/wbr_policy.c
+--- a/fs/aufs/wbr_policy.c     1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/wbr_policy.c     2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,637 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * policies for selecting one among multiple writable branches
++ */
++
++#include <linux/statfs.h>
++#include "aufs.h"
++
++/* subset of cpup_attr() */
++static noinline_for_stack
++int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
++{
++      int err, sbits;
++      struct iattr ia;
++      struct inode *h_isrc;
++
++      h_isrc = h_src->d_inode;
++      ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
++      ia.ia_mode = h_isrc->i_mode;
++      ia.ia_uid = h_isrc->i_uid;
++      ia.ia_gid = h_isrc->i_gid;
++      sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
++      au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
++      err = vfsub_sio_notify_change(h_path, &ia);
++
++      /* is this nfs only? */
++      if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
++              ia.ia_valid = ATTR_FORCE | ATTR_MODE;
++              ia.ia_mode = h_isrc->i_mode;
++              err = vfsub_sio_notify_change(h_path, &ia);
++      }
++
++      return err;
++}
++
++#define AuCpdown_PARENT_OPQ   1
++#define AuCpdown_WHED         (1 << 1)
++#define AuCpdown_MADE_DIR     (1 << 2)
++#define AuCpdown_DIROPQ               (1 << 3)
++#define au_ftest_cpdown(flags, name)  ((flags) & AuCpdown_##name)
++#define au_fset_cpdown(flags, name)   { (flags) |= AuCpdown_##name; }
++#define au_fclr_cpdown(flags, name)   { (flags) &= ~AuCpdown_##name; }
++
++struct au_cpdown_dir_args {
++      struct dentry *parent;
++      unsigned int flags;
++};
++
++static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
++                           struct au_cpdown_dir_args *a)
++{
++      int err;
++      struct dentry *opq_dentry;
++
++      opq_dentry = au_diropq_create(dentry, bdst);
++      err = PTR_ERR(opq_dentry);
++      if (IS_ERR(opq_dentry))
++              goto out;
++      dput(opq_dentry);
++      au_fset_cpdown(a->flags, DIROPQ);
++
++ out:
++      return err;
++}
++
++static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
++                          struct inode *dir, aufs_bindex_t bdst)
++{
++      int err;
++      struct path h_path;
++      struct au_branch *br;
++
++      br = au_sbr(dentry->d_sb, bdst);
++      h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
++      err = PTR_ERR(h_path.dentry);
++      if (IS_ERR(h_path.dentry))
++              goto out;
++
++      err = 0;
++      if (h_path.dentry->d_inode) {
++              h_path.mnt = br->br_mnt;
++              err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
++                                        dentry);
++      }
++      dput(h_path.dentry);
++
++ out:
++      return err;
++}
++
++static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
++                       struct dentry *h_parent, void *arg)
++{
++      int err, rerr;
++      aufs_bindex_t bend, bopq, bstart;
++      unsigned char parent_opq;
++      struct path h_path;
++      struct dentry *parent;
++      struct inode *h_dir, *h_inode, *inode, *dir;
++      struct au_cpdown_dir_args *args = arg;
++
++      bstart = au_dbstart(dentry);
++      /* dentry is di-locked */
++      parent = dget_parent(dentry);
++      dir = parent->d_inode;
++      h_dir = h_parent->d_inode;
++      AuDebugOn(h_dir != au_h_iptr(dir, bdst));
++      IMustLock(h_dir);
++
++      err = au_lkup_neg(dentry, bdst);
++      if (unlikely(err < 0))
++              goto out;
++      h_path.dentry = au_h_dptr(dentry, bdst);
++      h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
++      err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
++                            S_IRWXU | S_IRUGO | S_IXUGO);
++      if (unlikely(err))
++              goto out_put;
++      au_fset_cpdown(args->flags, MADE_DIR);
++
++      bend = au_dbend(dentry);
++      bopq = au_dbdiropq(dentry);
++      au_fclr_cpdown(args->flags, WHED);
++      au_fclr_cpdown(args->flags, DIROPQ);
++      if (au_dbwh(dentry) == bdst)
++              au_fset_cpdown(args->flags, WHED);
++      if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
++              au_fset_cpdown(args->flags, PARENT_OPQ);
++      parent_opq = (au_ftest_cpdown(args->flags, PARENT_OPQ)
++                    && args->parent == dentry);
++      h_inode = h_path.dentry->d_inode;
++      mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++      if (au_ftest_cpdown(args->flags, WHED)) {
++              err = au_cpdown_dir_opq(dentry, bdst, args);
++              if (unlikely(err)) {
++                      mutex_unlock(&h_inode->i_mutex);
++                      goto out_dir;
++              }
++      }
++
++      err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
++      mutex_unlock(&h_inode->i_mutex);
++      if (unlikely(err))
++              goto out_opq;
++
++      if (au_ftest_cpdown(args->flags, WHED)) {
++              err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
++              if (unlikely(err))
++                      goto out_opq;
++      }
++
++      inode = dentry->d_inode;
++      if (au_ibend(inode) < bdst)
++              au_set_ibend(inode, bdst);
++      au_set_h_iptr(inode, bdst, au_igrab(h_inode),
++                    au_hi_flags(inode, /*isdir*/1));
++      goto out; /* success */
++
++      /* revert */
++ out_opq:
++      if (au_ftest_cpdown(args->flags, DIROPQ)) {
++              mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
++              rerr = au_diropq_remove(dentry, bdst);
++              mutex_unlock(&h_inode->i_mutex);
++              if (unlikely(rerr)) {
++                      AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
++                              AuDLNPair(dentry), bdst, rerr);
++                      err = -EIO;
++                      goto out;
++              }
++      }
++ out_dir:
++      if (au_ftest_cpdown(args->flags, MADE_DIR)) {
++              rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
++              if (unlikely(rerr)) {
++                      AuIOErr("failed removing %.*s b%d (%d)\n",
++                              AuDLNPair(dentry), bdst, rerr);
++                      err = -EIO;
++              }
++      }
++ out_put:
++      au_set_h_dptr(dentry, bdst, NULL);
++      if (au_dbend(dentry) == bdst)
++              au_update_dbend(dentry);
++ out:
++      dput(parent);
++      return err;
++}
++
++int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
++{
++      int err;
++      struct au_cpdown_dir_args args = {
++              .parent = dget_parent(dentry),
++              .flags  = 0
++      };
++
++      err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
++      dput(args.parent);
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* policies for create */
++
++static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
++{
++      for (; bindex >= 0; bindex--)
++              if (!au_br_rdonly(au_sbr(sb, bindex)))
++                      return bindex;
++      return -EROFS;
++}
++
++/* top down parent */
++static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
++{
++      int err;
++      aufs_bindex_t bstart, bindex;
++      struct super_block *sb;
++      struct dentry *parent, *h_parent;
++
++      sb = dentry->d_sb;
++      bstart = au_dbstart(dentry);
++      err = bstart;
++      if (!au_br_rdonly(au_sbr(sb, bstart)))
++              goto out;
++
++      err = -EROFS;
++      parent = dget_parent(dentry);
++      for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
++              h_parent = au_h_dptr(parent, bindex);
++              if (!h_parent || !h_parent->d_inode)
++                      continue;
++
++              if (!au_br_rdonly(au_sbr(sb, bindex))) {
++                      err = bindex;
++                      break;
++              }
++      }
++      dput(parent);
++
++      /* bottom up here */
++      if (unlikely(err < 0))
++              err = au_wbr_bu(sb, bstart - 1);
++
++ out:
++      AuDbg("b%d\n", err);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* an exception for the policy other than tdp */
++static int au_wbr_create_exp(struct dentry *dentry)
++{
++      int err;
++      aufs_bindex_t bwh, bdiropq;
++      struct dentry *parent;
++
++      err = -1;
++      bwh = au_dbwh(dentry);
++      parent = dget_parent(dentry);
++      bdiropq = au_dbdiropq(parent);
++      if (bwh >= 0) {
++              if (bdiropq >= 0)
++                      err = min(bdiropq, bwh);
++              else
++                      err = bwh;
++              AuDbg("%d\n", err);
++      } else if (bdiropq >= 0) {
++              err = bdiropq;
++              AuDbg("%d\n", err);
++      }
++      dput(parent);
++
++      if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
++              err = -1;
++
++      AuDbg("%d\n", err);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* round robin */
++static int au_wbr_create_init_rr(struct super_block *sb)
++{
++      int err;
++
++      err = au_wbr_bu(sb, au_sbend(sb));
++      atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
++
++      AuDbg("b%d\n", err);
++      return err;
++}
++
++static int au_wbr_create_rr(struct dentry *dentry, int isdir)
++{
++      int err, nbr;
++      unsigned int u;
++      aufs_bindex_t bindex, bend;
++      struct super_block *sb;
++      atomic_t *next;
++
++      err = au_wbr_create_exp(dentry);
++      if (err >= 0)
++              goto out;
++
++      sb = dentry->d_sb;
++      next = &au_sbi(sb)->si_wbr_rr_next;
++      bend = au_sbend(sb);
++      nbr = bend + 1;
++      for (bindex = 0; bindex <= bend; bindex++) {
++              if (!isdir) {
++                      err = atomic_dec_return(next) + 1;
++                      /* modulo for 0 is meaningless */
++                      if (unlikely(!err))
++                              err = atomic_dec_return(next) + 1;
++              } else
++                      err = atomic_read(next);
++              AuDbg("%d\n", err);
++              u = err;
++              err = u % nbr;
++              AuDbg("%d\n", err);
++              if (!au_br_rdonly(au_sbr(sb, err)))
++                      break;
++              err = -EROFS;
++      }
++
++ out:
++      AuDbg("%d\n", err);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* most free space */
++static void au_mfs(struct dentry *dentry)
++{
++      struct super_block *sb;
++      struct au_branch *br;
++      struct au_wbr_mfs *mfs;
++      aufs_bindex_t bindex, bend;
++      int err;
++      unsigned long long b, bavail;
++      /* reduce the stack usage */
++      struct kstatfs *st;
++
++      st = kmalloc(sizeof(*st), GFP_NOFS);
++      if (unlikely(!st)) {
++              AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
++              return;
++      }
++
++      bavail = 0;
++      sb = dentry->d_sb;
++      mfs = &au_sbi(sb)->si_wbr_mfs;
++      mfs->mfs_bindex = -EROFS;
++      mfs->mfsrr_bytes = 0;
++      bend = au_sbend(sb);
++      for (bindex = 0; bindex <= bend; bindex++) {
++              br = au_sbr(sb, bindex);
++              if (au_br_rdonly(br))
++                      continue;
++
++              /* sb->s_root for NFS is unreliable */
++              err = vfs_statfs(br->br_mnt->mnt_root, st);
++              if (unlikely(err)) {
++                      AuWarn1("failed statfs, b%d, %d\n", bindex, err);
++                      continue;
++              }
++
++              /* when the available size is equal, select the lower one */
++              BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
++                           || sizeof(b) < sizeof(st->f_bsize));
++              b = st->f_bavail * st->f_bsize;
++              br->br_wbr->wbr_bytes = b;
++              if (b >= bavail) {
++                      bavail = b;
++                      mfs->mfs_bindex = bindex;
++                      mfs->mfs_jiffy = jiffies;
++              }
++      }
++
++      mfs->mfsrr_bytes = bavail;
++      AuDbg("b%d\n", mfs->mfs_bindex);
++      kfree(st);
++}
++
++static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
++{
++      int err;
++      struct super_block *sb;
++      struct au_wbr_mfs *mfs;
++
++      err = au_wbr_create_exp(dentry);
++      if (err >= 0)
++              goto out;
++
++      sb = dentry->d_sb;
++      mfs = &au_sbi(sb)->si_wbr_mfs;
++      mutex_lock(&mfs->mfs_lock);
++      if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
++          || mfs->mfs_bindex < 0
++          || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
++              au_mfs(dentry);
++      mutex_unlock(&mfs->mfs_lock);
++      err = mfs->mfs_bindex;
++
++ out:
++      AuDbg("b%d\n", err);
++      return err;
++}
++
++static int au_wbr_create_init_mfs(struct super_block *sb)
++{
++      struct au_wbr_mfs *mfs;
++
++      mfs = &au_sbi(sb)->si_wbr_mfs;
++      mutex_init(&mfs->mfs_lock);
++      mfs->mfs_jiffy = 0;
++      mfs->mfs_bindex = -EROFS;
++
++      return 0;
++}
++
++static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
++{
++      mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
++      return 0;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* most free space and then round robin */
++static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
++{
++      int err;
++      struct au_wbr_mfs *mfs;
++
++      err = au_wbr_create_mfs(dentry, isdir);
++      if (err >= 0) {
++              mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
++              if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
++                      err = au_wbr_create_rr(dentry, isdir);
++      }
++
++      AuDbg("b%d\n", err);
++      return err;
++}
++
++static int au_wbr_create_init_mfsrr(struct super_block *sb)
++{
++      int err;
++
++      au_wbr_create_init_mfs(sb); /* ignore */
++      err = au_wbr_create_init_rr(sb);
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* top down parent and most free space */
++static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
++{
++      int err, e2;
++      unsigned long long b;
++      aufs_bindex_t bindex, bstart, bend;
++      struct super_block *sb;
++      struct dentry *parent, *h_parent;
++      struct au_branch *br;
++
++      err = au_wbr_create_tdp(dentry, isdir);
++      if (unlikely(err < 0))
++              goto out;
++      parent = dget_parent(dentry);
++      bstart = au_dbstart(parent);
++      bend = au_dbtaildir(parent);
++      if (bstart == bend)
++              goto out_parent; /* success */
++
++      e2 = au_wbr_create_mfs(dentry, isdir);
++      if (e2 < 0)
++              goto out_parent; /* success */
++
++      /* when the available size is equal, select upper one */
++      sb = dentry->d_sb;
++      br = au_sbr(sb, err);
++      b = br->br_wbr->wbr_bytes;
++      AuDbg("b%d, %llu\n", err, b);
++
++      for (bindex = bstart; bindex <= bend; bindex++) {
++              h_parent = au_h_dptr(parent, bindex);
++              if (!h_parent || !h_parent->d_inode)
++                      continue;
++
++              br = au_sbr(sb, bindex);
++              if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
++                      b = br->br_wbr->wbr_bytes;
++                      err = bindex;
++                      AuDbg("b%d, %llu\n", err, b);
++              }
++      }
++
++ out_parent:
++      dput(parent);
++ out:
++      AuDbg("b%d\n", err);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* policies for copyup */
++
++/* top down parent */
++static int au_wbr_copyup_tdp(struct dentry *dentry)
++{
++      return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
++}
++
++/* bottom up parent */
++static int au_wbr_copyup_bup(struct dentry *dentry)
++{
++      int err;
++      aufs_bindex_t bindex, bstart;
++      struct dentry *parent, *h_parent;
++      struct super_block *sb;
++
++      err = -EROFS;
++      sb = dentry->d_sb;
++      parent = dget_parent(dentry);
++      bstart = au_dbstart(parent);
++      for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
++              h_parent = au_h_dptr(parent, bindex);
++              if (!h_parent || !h_parent->d_inode)
++                      continue;
++
++              if (!au_br_rdonly(au_sbr(sb, bindex))) {
++                      err = bindex;
++                      break;
++              }
++      }
++      dput(parent);
++
++      /* bottom up here */
++      if (unlikely(err < 0))
++              err = au_wbr_bu(sb, bstart - 1);
++
++      AuDbg("b%d\n", err);
++      return err;
++}
++
++/* bottom up */
++static int au_wbr_copyup_bu(struct dentry *dentry)
++{
++      int err;
++
++      err = au_wbr_bu(dentry->d_sb, au_dbstart(dentry));
++
++      AuDbg("b%d\n", err);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
++      [AuWbrCopyup_TDP] = {
++              .copyup = au_wbr_copyup_tdp
++      },
++      [AuWbrCopyup_BUP] = {
++              .copyup = au_wbr_copyup_bup
++      },
++      [AuWbrCopyup_BU] = {
++              .copyup = au_wbr_copyup_bu
++      }
++};
++
++struct au_wbr_create_operations au_wbr_create_ops[] = {
++      [AuWbrCreate_TDP] = {
++              .create = au_wbr_create_tdp
++      },
++      [AuWbrCreate_RR] = {
++              .create = au_wbr_create_rr,
++              .init   = au_wbr_create_init_rr
++      },
++      [AuWbrCreate_MFS] = {
++              .create = au_wbr_create_mfs,
++              .init   = au_wbr_create_init_mfs,
++              .fin    = au_wbr_create_fin_mfs
++      },
++      [AuWbrCreate_MFSV] = {
++              .create = au_wbr_create_mfs,
++              .init   = au_wbr_create_init_mfs,
++              .fin    = au_wbr_create_fin_mfs
++      },
++      [AuWbrCreate_MFSRR] = {
++              .create = au_wbr_create_mfsrr,
++              .init   = au_wbr_create_init_mfsrr,
++              .fin    = au_wbr_create_fin_mfs
++      },
++      [AuWbrCreate_MFSRRV] = {
++              .create = au_wbr_create_mfsrr,
++              .init   = au_wbr_create_init_mfsrr,
++              .fin    = au_wbr_create_fin_mfs
++      },
++      [AuWbrCreate_PMFS] = {
++              .create = au_wbr_create_pmfs,
++              .init   = au_wbr_create_init_mfs,
++              .fin    = au_wbr_create_fin_mfs
++      },
++      [AuWbrCreate_PMFSV] = {
++              .create = au_wbr_create_pmfs,
++              .init   = au_wbr_create_init_mfs,
++              .fin    = au_wbr_create_fin_mfs
++      }
++};
+diff -Naur a/fs/aufs/whout.c b/fs/aufs/whout.c
+--- a/fs/aufs/whout.c  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/whout.c  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,1042 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * whiteout for logical deletion and opaque directory
++ */
++
++#include <linux/fs.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 kfree().
++ */
++int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
++{
++      char *p;
++
++      if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
++              return -ENAMETOOLONG;
++
++      wh->len = name->len + AUFS_WH_PFX_LEN;
++      p = kmalloc(wh->len, GFP_NOFS);
++      wh->name = p;
++      if (p) {
++              memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
++              memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
++              /* smp_mb(); */
++              return 0;
++      }
++      return -ENOMEM;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * test if the @wh_name exists under @h_parent.
++ * @try_sio specifies the necessary of super-io.
++ */
++int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
++             struct au_branch *br, int try_sio)
++{
++      int err;
++      struct dentry *wh_dentry;
++      struct inode *h_dir;
++
++      h_dir = h_parent->d_inode;
++      if (!try_sio)
++              wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
++      else
++              wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
++      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;
++      AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
++              AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
++
++ out_wh:
++      dput(wh_dentry);
++ out:
++      return err;
++}
++
++/*
++ * test if the @h_dentry sets opaque or not.
++ */
++int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
++{
++      int err;
++      struct inode *h_dir;
++
++      h_dir = h_dentry->d_inode;
++      err = au_wh_test(h_dentry, &diropq_name, br,
++                       au_test_h_perm_sio(h_dir, MAY_EXEC));
++      return err;
++}
++
++/*
++ * returns a negative dentry whose name is unique and temporary.
++ */
++struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
++                           struct qstr *prefix)
++{
++#define HEX_LEN       4
++      struct dentry *dentry;
++      int i;
++      char defname[AUFS_WH_PFX_LEN * 2 + DNAME_INLINE_LEN_MIN + 1
++                   + HEX_LEN + 1], *name, *p;
++      static unsigned short cnt;
++      struct qstr qs;
++
++      name = defname;
++      qs.len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1;
++      if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) {
++              dentry = ERR_PTR(-ENAMETOOLONG);
++              if (unlikely(qs.len >= PATH_MAX))
++                      goto out;
++              dentry = ERR_PTR(-ENOMEM);
++              name = kmalloc(qs.len + 1, GFP_NOFS);
++              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++ = '.';
++      AuDebugOn(name + qs.len + 1 - p <= HEX_LEN);
++
++      qs.name = name;
++      for (i = 0; i < 3; i++) {
++              sprintf(p, "%.*d", HEX_LEN, cnt++);
++              dentry = au_sio_lkup_one(&qs, h_parent, br);
++              if (IS_ERR(dentry) || !dentry->d_inode)
++                      goto out_name;
++              dput(dentry);
++      }
++      /* AuWarn("could not get random name\n"); */
++      dentry = ERR_PTR(-EEXIST);
++      AuDbg("%.*s\n", AuLNPair(&qs));
++      BUG();
++
++ out_name:
++      if (name != defname)
++              kfree(name);
++ out:
++      return dentry;
++#undef HEX_LEN
++}
++
++/*
++ * rename the @h_dentry on @br to the whiteouted temporary name.
++ */
++int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
++{
++      int err;
++      struct path h_path = {
++              .mnt = br->br_mnt
++      };
++      struct inode *h_dir;
++      struct dentry *h_parent;
++
++      h_parent = h_dentry->d_parent; /* dir inode is locked */
++      h_dir = h_parent->d_inode;
++      IMustLock(h_dir);
++
++      h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
++      err = PTR_ERR(h_path.dentry);
++      if (IS_ERR(h_path.dentry))
++              goto out;
++
++      /* under the same dir, no need to lock_rename() */
++      err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
++      AuTraceErr(err);
++      dput(h_path.dentry);
++
++ out:
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++/*
++ * functions for removing a whiteout
++ */
++
++static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
++{
++      int force;
++
++      /*
++       * forces superio when the dir has a sticky bit.
++       * this may be a violation of unix fs semantics.
++       */
++      force = (h_dir->i_mode & S_ISVTX)
++              && h_path->dentry->d_inode->i_uid != current_fsuid();
++      return vfsub_unlink(h_dir, h_path, force);
++}
++
++int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
++                      struct dentry *dentry)
++{
++      int err;
++
++      err = do_unlink_wh(h_dir, h_path);
++      if (!err && dentry)
++              au_set_dbwh(dentry, -1);
++
++      return err;
++}
++
++static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
++                        struct au_branch *br)
++{
++      int err;
++      struct path h_path = {
++              .mnt = br->br_mnt
++      };
++
++      err = 0;
++      h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
++      if (IS_ERR(h_path.dentry))
++              err = PTR_ERR(h_path.dentry);
++      else {
++              if (h_path.dentry->d_inode
++                  && S_ISREG(h_path.dentry->d_inode->i_mode))
++                      err = do_unlink_wh(h_parent->d_inode, &h_path);
++              dput(h_path.dentry);
++      }
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++/*
++ * initialize/clean whiteout for a branch
++ */
++
++static void au_wh_clean(struct inode *h_dir, struct path *whpath,
++                      const int isdir)
++{
++      int err;
++
++      if (!whpath->dentry->d_inode)
++              return;
++
++      err = mnt_want_write(whpath->mnt);
++      if (!err) {
++              if (isdir)
++                      err = vfsub_rmdir(h_dir, whpath);
++              else
++                      err = vfsub_unlink(h_dir, whpath, /*force*/0);
++              mnt_drop_write(whpath->mnt);
++      }
++      if (unlikely(err))
++              AuWarn("failed removing %.*s (%d), ignored.\n",
++                     AuDLNPair(whpath->dentry), err);
++}
++
++static int test_linkable(struct dentry *h_root)
++{
++      struct inode *h_dir = h_root->d_inode;
++
++      if (h_dir->i_op->link)
++              return 0;
++
++      AuErr("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
++            AuDLNPair(h_root), au_sbtype(h_root->d_sb));
++      return -ENOSYS;
++}
++
++/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
++static int au_whdir(struct inode *h_dir, struct path *path)
++{
++      int err;
++
++      err = -EEXIST;
++      if (!path->dentry->d_inode) {
++              int mode = S_IRWXU;
++
++              if (au_test_nfs(path->dentry->d_sb))
++                      mode |= S_IXUGO;
++              err = mnt_want_write(path->mnt);
++              if (!err) {
++                      err = vfsub_mkdir(h_dir, path, mode);
++                      mnt_drop_write(path->mnt);
++              }
++      } else if (S_ISDIR(path->dentry->d_inode->i_mode))
++              err = 0;
++      else
++              AuErr("unknown %.*s exists\n", AuDLNPair(path->dentry));
++
++      return err;
++}
++
++struct au_wh_base {
++      const struct qstr *name;
++      struct dentry *dentry;
++};
++
++static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
++                        struct path *h_path)
++{
++      h_path->dentry = base[AuBrWh_BASE].dentry;
++      au_wh_clean(h_dir, h_path, /*isdir*/0);
++      h_path->dentry = base[AuBrWh_PLINK].dentry;
++      au_wh_clean(h_dir, h_path, /*isdir*/1);
++      h_path->dentry = base[AuBrWh_ORPH].dentry;
++      au_wh_clean(h_dir, h_path, /*isdir*/1);
++}
++
++/*
++ * returns tri-state,
++ * minus: error, caller should print the mesage
++ * zero: succuess
++ * plus: error, caller should NOT print the mesage
++ */
++static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
++                              int do_plink, struct au_wh_base base[],
++                              struct path *h_path)
++{
++      int err;
++      struct inode *h_dir;
++
++      h_dir = h_root->d_inode;
++      h_path->dentry = base[AuBrWh_BASE].dentry;
++      au_wh_clean(h_dir, h_path, /*isdir*/0);
++      h_path->dentry = base[AuBrWh_PLINK].dentry;
++      if (do_plink) {
++              err = test_linkable(h_root);
++              if (unlikely(err)) {
++                      err = 1;
++                      goto out;
++              }
++
++              err = au_whdir(h_dir, h_path);
++              if (unlikely(err))
++                      goto out;
++              wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
++      } else
++              au_wh_clean(h_dir, h_path, /*isdir*/1);
++      h_path->dentry = base[AuBrWh_ORPH].dentry;
++      err = au_whdir(h_dir, h_path);
++      if (unlikely(err))
++              goto out;
++      wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
++
++ out:
++      return err;
++}
++
++/*
++ * 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.
++ *
++ * returns tri-state, see above.
++ */
++static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
++                       int do_plink, struct au_wh_base base[],
++                       struct path *h_path)
++{
++      int err;
++      struct inode *h_dir;
++
++      err = test_linkable(h_root);
++      if (unlikely(err)) {
++              err = 1;
++              goto out;
++      }
++
++      /*
++       * todo: should this create be done in /sbin/mount.aufs helper?
++       */
++      err = -EEXIST;
++      h_dir = h_root->d_inode;
++      if (!base[AuBrWh_BASE].dentry->d_inode) {
++              err = mnt_want_write(h_path->mnt);
++              if (!err) {
++                      h_path->dentry = base[AuBrWh_BASE].dentry;
++                      err = vfsub_create(h_dir, h_path, WH_MASK);
++                      mnt_drop_write(h_path->mnt);
++              }
++      } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
++              err = 0;
++      else
++              AuErr("unknown %.*s/%.*s exists\n",
++                    AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
++      if (unlikely(err))
++              goto out;
++
++      h_path->dentry = base[AuBrWh_PLINK].dentry;
++      if (do_plink) {
++              err = au_whdir(h_dir, h_path);
++              if (unlikely(err))
++                      goto out;
++              wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
++      } else
++              au_wh_clean(h_dir, h_path, /*isdir*/1);
++      wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
++
++      h_path->dentry = base[AuBrWh_ORPH].dentry;
++      err = au_whdir(h_dir, h_path);
++      if (unlikely(err))
++              goto out;
++      wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
++
++ out:
++      return err;
++}
++
++/*
++ * initialize the whiteout base file/dir for @br.
++ */
++int au_wh_init(struct dentry *h_root, struct au_branch *br,
++             struct super_block *sb)
++{
++      int err, i;
++      const unsigned char do_plink
++              = !!au_opt_test(au_mntflags(sb), PLINK);
++      struct path path = {
++              .mnt = br->br_mnt
++      };
++      struct inode *h_dir;
++      struct au_wbr *wbr = br->br_wbr;
++      static const struct qstr base_name[] = {
++              [AuBrWh_BASE] = {
++                      .name   = AUFS_BASE_NAME,
++                      .len    = sizeof(AUFS_BASE_NAME) - 1
++              },
++              [AuBrWh_PLINK] = {
++                      .name   = AUFS_PLINKDIR_NAME,
++                      .len    = sizeof(AUFS_PLINKDIR_NAME) - 1
++              },
++              [AuBrWh_ORPH] = {
++                      .name   = AUFS_ORPHDIR_NAME,
++                      .len    = sizeof(AUFS_ORPHDIR_NAME) - 1
++              }
++      };
++      struct au_wh_base base[] = {
++              [AuBrWh_BASE] = {
++                      .name   = base_name + AuBrWh_BASE,
++                      .dentry = NULL
++              },
++              [AuBrWh_PLINK] = {
++                      .name   = base_name + AuBrWh_PLINK,
++                      .dentry = NULL
++              },
++              [AuBrWh_ORPH] = {
++                      .name   = base_name + AuBrWh_ORPH,
++                      .dentry = NULL
++              }
++      };
++
++
++      h_dir = h_root->d_inode;
++      for (i = 0; i < AuBrWh_Last; i++) {
++              /* doubly whiteouted */
++              struct dentry *d;
++
++              d = au_wh_lkup(h_root, (void *)base[i].name, br);
++              err = PTR_ERR(d);
++              if (IS_ERR(d))
++                      goto out;
++
++              base[i].dentry = d;
++              AuDebugOn(wbr
++                        && wbr->wbr_wh[i]
++                        && wbr->wbr_wh[i] != base[i].dentry);
++      }
++
++      if (wbr)
++              for (i = 0; i < AuBrWh_Last; i++) {
++                      dput(wbr->wbr_wh[i]);
++                      wbr->wbr_wh[i] = NULL;
++              }
++
++      err = 0;
++
++      switch (br->br_perm) {
++      case AuBrPerm_RO:
++      case AuBrPerm_ROWH:
++      case AuBrPerm_RR:
++      case AuBrPerm_RRWH:
++              au_wh_init_ro(h_dir, base, &path);
++              break;
++
++      case AuBrPerm_RWNoLinkWH:
++              err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
++              if (err > 0)
++                      goto out;
++              else if (err)
++                      goto out_err;
++              break;
++
++      case AuBrPerm_RW:
++              err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
++              if (err > 0)
++                      goto out;
++              else if (err)
++                      goto out_err;
++              break;
++
++      default:
++              BUG();
++      }
++      goto out; /* success */
++
++ out_err:
++      AuErr("an error(%d) on the writable branch %.*s(%s)\n",
++            err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
++ out:
++      for (i = 0; i < AuBrWh_Last; i++)
++              dput(base[i].dentry);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++/*
++ * whiteouts are all hard-linked usually.
++ * when its link count reaches a ceiling, we create a new whiteout base
++ * asynchronously.
++ */
++
++struct reinit_br_wh {
++      struct super_block *sb;
++      struct au_branch *br;
++};
++
++static void reinit_br_wh(void *arg)
++{
++      int err;
++      aufs_bindex_t bindex;
++      struct path h_path;
++      struct reinit_br_wh *a = arg;
++      struct au_wbr *wbr;
++      struct inode *dir;
++      struct dentry *h_root;
++      struct au_hinode *hdir;
++
++      err = 0;
++      wbr = a->br->br_wbr;
++      /* big aufs lock */
++      si_noflush_write_lock(a->sb);
++      if (!au_br_writable(a->br->br_perm))
++              goto out;
++      bindex = au_br_index(a->sb, a->br->br_id);
++      if (unlikely(bindex < 0))
++              goto out;
++
++      dir = a->sb->s_root->d_inode;
++      /* ii_read_lock_parent(dir); */
++      hdir = au_hi(dir, bindex);
++      h_root = au_h_dptr(a->sb->s_root, bindex);
++
++      au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++      wbr_wh_write_lock(wbr);
++      err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
++                        h_root, a->br);
++      if (!err) {
++              err = mnt_want_write(a->br->br_mnt);
++              if (!err) {
++                      h_path.dentry = wbr->wbr_whbase;
++                      h_path.mnt = a->br->br_mnt;
++                      err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
++                      mnt_drop_write(a->br->br_mnt);
++              }
++      } else {
++              AuWarn("%.*s is moved, ignored\n", AuDLNPair(wbr->wbr_whbase));
++              err = 0;
++      }
++      dput(wbr->wbr_whbase);
++      wbr->wbr_whbase = NULL;
++      if (!err)
++              err = au_wh_init(h_root, a->br, a->sb);
++      wbr_wh_write_unlock(wbr);
++      au_hin_imtx_unlock(hdir);
++      /* ii_read_unlock(dir); */
++
++ out:
++      if (wbr)
++              atomic_dec(&wbr->wbr_wh_running);
++      atomic_dec(&a->br->br_count);
++      au_nwt_done(&au_sbi(a->sb)->si_nowait);
++      si_write_unlock(a->sb);
++      kfree(arg);
++      if (unlikely(err))
++              AuIOErr("err %d\n", err);
++}
++
++static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
++{
++      int do_dec, wkq_err;
++      struct reinit_br_wh *arg;
++
++      do_dec = 1;
++      if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
++              goto out;
++
++      /* ignore ENOMEM */
++      arg = kmalloc(sizeof(*arg), GFP_NOFS);
++      if (arg) {
++              /*
++               * dec(wh_running), kfree(arg) and dec(br_count)
++               * in reinit function
++               */
++              arg->sb = sb;
++              arg->br = br;
++              atomic_inc(&br->br_count);
++              wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
++              if (unlikely(wkq_err)) {
++                      atomic_dec(&br->br_wbr->wbr_wh_running);
++                      atomic_dec(&br->br_count);
++                      kfree(arg);
++              }
++              do_dec = 0;
++      }
++
++ out:
++      if (do_dec)
++              atomic_dec(&br->br_wbr->wbr_wh_running);
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * create the whiteout @wh.
++ */
++static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
++                           struct dentry *wh)
++{
++      int err;
++      struct path h_path = {
++              .dentry = wh
++      };
++      struct au_branch *br;
++      struct au_wbr *wbr;
++      struct dentry *h_parent;
++      struct inode *h_dir;
++
++      h_parent = wh->d_parent; /* dir inode is locked */
++      h_dir = h_parent->d_inode;
++      IMustLock(h_dir);
++
++      br = au_sbr(sb, bindex);
++      h_path.mnt = br->br_mnt;
++      wbr = br->br_wbr;
++      wbr_wh_read_lock(wbr);
++      if (wbr->wbr_whbase) {
++              err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
++              if (!err || err != -EMLINK)
++                      goto out;
++
++              /* link count full. re-initialize br_whbase. */
++              kick_reinit_br_wh(sb, br);
++      }
++
++      /* return this error in this context */
++      err = vfsub_create(h_dir, &h_path, WH_MASK);
++
++ out:
++      wbr_wh_read_unlock(wbr);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * create or remove the diropq.
++ */
++static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
++                              unsigned int flags)
++{
++      struct dentry *opq_dentry, *h_dentry;
++      struct super_block *sb;
++      struct au_branch *br;
++      int err;
++
++      sb = dentry->d_sb;
++      br = au_sbr(sb, bindex);
++      h_dentry = au_h_dptr(dentry, bindex);
++      opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
++      if (IS_ERR(opq_dentry))
++              goto out;
++
++      if (au_ftest_diropq(flags, CREATE)) {
++              err = link_or_create_wh(sb, bindex, opq_dentry);
++              if (!err) {
++                      au_set_dbdiropq(dentry, bindex);
++                      goto out; /* success */
++              }
++      } else {
++              struct path tmp = {
++                      .dentry = opq_dentry,
++                      .mnt    = br->br_mnt
++              };
++              err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
++              if (!err)
++                      au_set_dbdiropq(dentry, -1);
++      }
++      dput(opq_dentry);
++      opq_dentry = ERR_PTR(err);
++
++ out:
++      return opq_dentry;
++}
++
++struct do_diropq_args {
++      struct dentry **errp;
++      struct dentry *dentry;
++      aufs_bindex_t bindex;
++      unsigned int flags;
++};
++
++static void call_do_diropq(void *args)
++{
++      struct do_diropq_args *a = args;
++      *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
++}
++
++struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
++                           unsigned int flags)
++{
++      struct dentry *diropq, *h_dentry;
++
++      h_dentry = au_h_dptr(dentry, bindex);
++      if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
++              diropq = do_diropq(dentry, bindex, flags);
++      else {
++              int wkq_err;
++              struct do_diropq_args args = {
++                      .errp           = &diropq,
++                      .dentry         = dentry,
++                      .bindex         = bindex,
++                      .flags          = flags
++              };
++
++              wkq_err = au_wkq_wait(call_do_diropq, &args);
++              if (unlikely(wkq_err))
++                      diropq = ERR_PTR(wkq_err);
++      }
++
++      return diropq;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * lookup whiteout dentry.
++ * @h_parent: lower parent dentry which must exist and be locked
++ * @base_name: name of dentry which will be whiteouted
++ * returns dentry for whiteout.
++ */
++struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
++                        struct au_branch *br)
++{
++      int err;
++      struct qstr wh_name;
++      struct dentry *wh_dentry;
++
++      err = au_wh_name_alloc(&wh_name, base_name);
++      wh_dentry = ERR_PTR(err);
++      if (!err) {
++              wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
++              kfree(wh_name.name);
++      }
++      return wh_dentry;
++}
++
++/*
++ * link/create a whiteout for @dentry on @bindex.
++ */
++struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
++                          struct dentry *h_parent)
++{
++      struct dentry *wh_dentry;
++      struct super_block *sb;
++      int err;
++
++      sb = dentry->d_sb;
++      wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
++      if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
++              err = link_or_create_wh(sb, bindex, wh_dentry);
++              if (!err)
++                      au_set_dbwh(dentry, bindex);
++              else {
++                      dput(wh_dentry);
++                      wh_dentry = ERR_PTR(err);
++              }
++      }
++
++      return wh_dentry;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* Delete all whiteouts in this directory on branch bindex. */
++static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
++                         aufs_bindex_t bindex, struct au_branch *br)
++{
++      int err;
++      unsigned long ul, n;
++      struct qstr wh_name;
++      char *p;
++      struct hlist_head *head;
++      struct au_vdir_wh *tpos;
++      struct hlist_node *pos;
++      struct au_vdir_destr *str;
++
++      err = -ENOMEM;
++      p = __getname();
++      wh_name.name = p;
++      if (unlikely(!wh_name.name))
++              goto out;
++
++      err = 0;
++      memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
++      p += AUFS_WH_PFX_LEN;
++      n = whlist->nh_num;
++      head = whlist->nh_head;
++      for (ul = 0; !err && ul < n; ul++, head++) {
++              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(h_dentry, &wh_name, br);
++                              if (!err)
++                                      continue;
++                              break;
++                      }
++                      AuIOErr("whiteout name too long %.*s\n",
++                              str->len, str->name);
++                      err = -EIO;
++                      break;
++              }
++      }
++      __putname(wh_name.name);
++
++ out:
++      return err;
++}
++
++struct del_wh_children_args {
++      int *errp;
++      struct dentry *h_dentry;
++      struct au_nhash whlist;
++      aufs_bindex_t bindex;
++      struct au_branch *br;
++};
++
++static void call_del_wh_children(void *args)
++{
++      struct del_wh_children_args *a = args;
++      *a->errp = del_wh_children(a->h_dentry, &a->whlist, a->bindex, a->br);
++}
++
++/* ---------------------------------------------------------------------- */
++
++struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
++{
++      struct au_whtmp_rmdir *whtmp;
++      int err;
++
++      whtmp = kmalloc(sizeof(*whtmp), gfp);
++      if (unlikely(!whtmp)) {
++              whtmp = ERR_PTR(-ENOMEM);
++              goto out;
++      }
++
++      whtmp->dir = NULL;
++      whtmp->wh_dentry = NULL;
++      err = au_nhash_alloc(&whtmp->whlist, au_sbi(sb)->si_rdhash, gfp);
++      if (!err)
++              return whtmp; /* success */
++
++      kfree(whtmp);
++      whtmp = ERR_PTR(err);
++
++ out:
++      return whtmp;
++}
++
++void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
++{
++      dput(whtmp->wh_dentry);
++      iput(whtmp->dir);
++      au_nhash_wh_free(&whtmp->whlist);
++      kfree(whtmp);
++}
++
++/*
++ * rmdir the whiteouted temporary named dir @h_dentry.
++ * @whlist: whiteouted children.
++ */
++int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
++                 struct dentry *wh_dentry, struct au_nhash *whlist)
++{
++      int err;
++      struct path h_tmp;
++      struct inode *wh_inode, *h_dir;
++      struct au_branch *br;
++
++      h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
++      IMustLock(h_dir);
++
++      br = au_sbr(dir->i_sb, bindex);
++      wh_inode = wh_dentry->d_inode;
++      mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
++
++      /*
++       * someone else might change some whiteouts while we were sleeping.
++       * it means this whlist may have an obsoleted entry.
++       */
++      if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
++              err = del_wh_children(wh_dentry, whlist, bindex, br);
++      else {
++              int wkq_err;
++              struct del_wh_children_args args = {
++                      .errp           = &err,
++                      .h_dentry       = wh_dentry,
++                      .whlist         = *whlist,
++                      .bindex         = bindex,
++                      .br             = br
++              };
++
++              wkq_err = au_wkq_wait(call_del_wh_children, &args);
++              if (unlikely(wkq_err))
++                      err = wkq_err;
++      }
++      mutex_unlock(&wh_inode->i_mutex);
++
++      if (!err) {
++              h_tmp.dentry = wh_dentry;
++              h_tmp.mnt = br->br_mnt;
++              err = vfsub_rmdir(h_dir, &h_tmp);
++              /* d_drop(h_dentry); */
++      }
++
++      if (!err) {
++              if (au_ibstart(dir) == bindex) {
++                      au_cpup_attr_timesizes(dir);
++                      drop_nlink(dir);
++              }
++              return 0; /* success */
++      }
++
++      AuWarn("failed removing %.*s(%d), ignored\n",
++             AuDLNPair(wh_dentry), err);
++      return err;
++}
++
++static void call_rmdir_whtmp(void *args)
++{
++      int err;
++      struct au_whtmp_rmdir *a = args;
++      struct super_block *sb;
++      struct dentry *h_parent;
++      struct inode *h_dir;
++      struct au_branch *br;
++      struct au_hinode *hdir;
++
++      /* rmdir by nfsd may cause deadlock with this i_mutex */
++      /* mutex_lock(&a->dir->i_mutex); */
++      sb = a->dir->i_sb;
++      si_noflush_read_lock(sb);
++      err = au_test_ro(sb, a->bindex, NULL);
++      if (unlikely(err))
++              goto out;
++
++      err = -EIO;
++      br = au_sbr(sb, a->bindex);
++      ii_write_lock_parent(a->dir);
++      h_parent = dget_parent(a->wh_dentry);
++      h_dir = h_parent->d_inode;
++      hdir = au_hi(a->dir, a->bindex);
++      au_hin_imtx_lock_nested(hdir, AuLsc_I_PARENT);
++      err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, br);
++      if (!err) {
++              err = mnt_want_write(br->br_mnt);
++              if (!err) {
++                      err = au_whtmp_rmdir(a->dir, a->bindex, a->wh_dentry,
++                                           &a->whlist);
++                      mnt_drop_write(br->br_mnt);
++              }
++      }
++      au_hin_imtx_unlock(hdir);
++      dput(h_parent);
++      ii_write_unlock(a->dir);
++
++ out:
++      /* mutex_unlock(&a->dir->i_mutex); */
++      au_nwt_done(&au_sbi(sb)->si_nowait);
++      si_read_unlock(sb);
++      au_whtmp_rmdir_free(a);
++      if (unlikely(err))
++              AuIOErr("err %d\n", err);
++}
++
++void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
++                       struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
++{
++      int wkq_err;
++
++      IMustLock(dir);
++
++      /* all post-process will be done in do_rmdir_whtmp(). */
++      args->dir = au_igrab(dir);
++      args->bindex = bindex;
++      args->wh_dentry = dget(wh_dentry);
++      wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, dir->i_sb);
++      if (unlikely(wkq_err)) {
++              AuWarn("rmdir error %.*s (%d), ignored\n",
++                     AuDLNPair(wh_dentry), wkq_err);
++              au_whtmp_rmdir_free(args);
++      }
++}
+diff -Naur a/fs/aufs/whout.h b/fs/aufs/whout.h
+--- a/fs/aufs/whout.h  1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/whout.h  2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,87 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * whiteout for logical deletion and opaque directory
++ */
++
++#ifndef __AUFS_WHOUT_H__
++#define __AUFS_WHOUT_H__
++
++#ifdef __KERNEL__
++
++#include <linux/aufs_type.h>
++#include "dir.h"
++
++/* whout.c */
++int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
++struct au_branch;
++int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
++             struct au_branch *br, int try_sio);
++int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
++struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
++                           struct qstr *prefix);
++int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
++int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
++                      struct dentry *dentry);
++int au_wh_init(struct dentry *h_parent, struct au_branch *br,
++             struct super_block *sb);
++
++/* diropq flags */
++#define AuDiropq_CREATE       1
++#define au_ftest_diropq(flags, name)  ((flags) & AuDiropq_##name)
++#define au_fset_diropq(flags, name)   { (flags) |= AuDiropq_##name; }
++#define au_fclr_diropq(flags, name)   { (flags) &= ~AuDiropq_##name; }
++
++struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
++                           unsigned int flags);
++struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
++                        struct au_branch *br);
++struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
++                          struct dentry *h_parent);
++
++/* real rmdir for the whiteout-ed dir */
++struct au_whtmp_rmdir {
++      struct inode *dir;
++      aufs_bindex_t bindex;
++      struct dentry *wh_dentry;
++      struct au_nhash whlist;
++};
++
++struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
++void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
++int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
++                 struct dentry *wh_dentry, struct au_nhash *whlist);
++void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
++                       struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
++
++/* ---------------------------------------------------------------------- */
++
++static inline struct dentry *au_diropq_create(struct dentry *dentry,
++                                            aufs_bindex_t bindex)
++{
++      return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
++}
++
++static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
++{
++      return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_WHOUT_H__ */
+diff -Naur a/fs/aufs/wkq.c b/fs/aufs/wkq.c
+--- a/fs/aufs/wkq.c    1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/wkq.c    2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,259 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * workqueue for asynchronous/super-io operations
++ * todo: try new dredential scheme
++ */
++
++#include <linux/module.h>
++#include "aufs.h"
++
++/* internal workqueue named AUFS_WKQ_NAME */
++static struct au_wkq {
++      struct workqueue_struct *q;
++
++      /* balancing */
++      atomic_t                busy;
++} *au_wkq;
++
++struct au_wkinfo {
++      struct work_struct wk;
++      struct super_block *sb;
++
++      unsigned int flags; /* see wkq.h */
++
++      au_wkq_func_t func;
++      void *args;
++
++      atomic_t *busyp;
++      struct completion *comp;
++};
++
++/* ---------------------------------------------------------------------- */
++
++static int enqueue(struct au_wkq *wkq, struct au_wkinfo *wkinfo)
++{
++      wkinfo->busyp = &wkq->busy;
++      if (au_ftest_wkq(wkinfo->flags, 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;
++
++      while (1) {
++              if (au_ftest_wkq(wkinfo->flags, 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? */
++              AuWarn1("failed to queue_work()\n");
++              yield();
++      }
++}
++
++static void wkq_func(struct work_struct *wk)
++{
++      struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
++
++      wkinfo->func(wkinfo->args);
++      atomic_dec(wkinfo->busyp);
++      if (au_ftest_wkq(wkinfo->flags, WAIT))
++              complete(wkinfo->comp);
++      else {
++              kobject_put(&au_sbi(wkinfo->sb)->si_kobj);
++              module_put(THIS_MODULE);
++              kfree(wkinfo);
++      }
++}
++
++/*
++ * Since struct completion is large, try allocating it dynamically.
++ */
++#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
++#define AuWkqCompDeclare(name)        struct completion *comp = NULL
++
++static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
++{
++      *comp = kmalloc(sizeof(**comp), GFP_NOFS);
++      if (*comp) {
++              init_completion(*comp);
++              wkinfo->comp = *comp;
++              return 0;
++      }
++      return -ENOMEM;
++}
++
++static void au_wkq_comp_free(struct completion *comp)
++{
++      kfree(comp);
++}
++
++#else
++
++/* no braces */
++#define AuWkqCompDeclare(name) \
++      DECLARE_COMPLETION_ONSTACK(_ ## name); \
++      struct completion *comp = &_ ## name
++
++static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
++{
++      wkinfo->comp = *comp;
++      return 0;
++}
++
++static void au_wkq_comp_free(struct completion *comp __maybe_unused)
++{
++      /* empty */
++}
++#endif /* 4KSTACKS */
++
++static void au_wkq_run(struct au_wkinfo *wkinfo)
++{
++      au_dbg_verify_kthread();
++      INIT_WORK(&wkinfo->wk, wkq_func);
++      do_wkq(wkinfo);
++}
++
++int au_wkq_wait(au_wkq_func_t func, void *args)
++{
++      int err;
++      AuWkqCompDeclare(comp);
++      struct au_wkinfo wkinfo = {
++              .flags  = AuWkq_WAIT,
++              .func   = func,
++              .args   = args
++      };
++
++      err = au_wkq_comp_alloc(&wkinfo, &comp);
++      if (!err) {
++              au_wkq_run(&wkinfo);
++              /* no timeout, no interrupt */
++              wait_for_completion(wkinfo.comp);
++              au_wkq_comp_free(comp);
++      }
++
++      return err;
++
++}
++
++int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
++{
++      int err;
++      struct au_wkinfo *wkinfo;
++
++      atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
++
++      /*
++       * wkq_func() must free this wkinfo.
++       * it highly depends upon the implementation of workqueue.
++       */
++      err = 0;
++      wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
++      if (wkinfo) {
++              wkinfo->sb = sb;
++              wkinfo->flags = !AuWkq_WAIT;
++              wkinfo->func = func;
++              wkinfo->args = args;
++              wkinfo->comp = NULL;
++              kobject_get(&au_sbi(sb)->si_kobj);
++              __module_get(THIS_MODULE);
++
++              au_wkq_run(wkinfo);
++      } else {
++              err = -ENOMEM;
++              atomic_dec(&au_sbi(sb)->si_nowait.nw_len);
++      }
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++void au_nwt_init(struct au_nowait_tasks *nwt)
++{
++      atomic_set(&nwt->nw_len, 0);
++      /* smp_mb();*/ /* atomic_set */
++      init_waitqueue_head(&nwt->nw_wq);
++}
++
++void au_wkq_fin(void)
++{
++      int i;
++
++      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;
++
++      /* '+1' is for accounting of nowait queue */
++      err = -ENOMEM;
++      au_wkq = kcalloc(aufs_nwkq + 1, sizeof(*au_wkq), GFP_NOFS);
++      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);
++                      continue;
++              }
++
++              err = PTR_ERR(au_wkq[i].q);
++              au_wkq_fin();
++              goto out;
++      }
++
++      /* nowait accounting */
++      nowaitq = au_wkq + aufs_nwkq;
++      atomic_set(&nowaitq->busy, 0);
++      nowaitq->q = NULL;
++      /* smp_mb(); */ /* atomic_set */
++
++ out:
++      return err;
++}
+diff -Naur a/fs/aufs/wkq.h b/fs/aufs/wkq.h
+--- a/fs/aufs/wkq.h    1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/wkq.h    2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,82 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * workqueue for asynchronous/super-io operations
++ * todo: try new credentials management scheme
++ */
++
++#ifndef __AUFS_WKQ_H__
++#define __AUFS_WKQ_H__
++
++#ifdef __KERNEL__
++
++#include <linux/sched.h>
++#include <linux/wait.h>
++#include <linux/aufs_type.h>
++
++struct super_block;
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
++ */
++struct au_nowait_tasks {
++      atomic_t                nw_len;
++      wait_queue_head_t       nw_wq;
++};
++
++/* ---------------------------------------------------------------------- */
++
++typedef void (*au_wkq_func_t)(void *args);
++
++/* wkq flags */
++#define AuWkq_WAIT    1
++#define au_ftest_wkq(flags, name)     ((flags) & AuWkq_##name)
++#define au_fset_wkq(flags, name)      { (flags) |= AuWkq_##name; }
++#define au_fclr_wkq(flags, name)      { (flags) &= ~AuWkq_##name; }
++
++/* wkq.c */
++int au_wkq_wait(au_wkq_func_t func, void *args);
++int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
++void au_nwt_init(struct au_nowait_tasks *nwt);
++int __init au_wkq_init(void);
++void au_wkq_fin(void);
++
++/* ---------------------------------------------------------------------- */
++
++static inline int au_test_wkq(struct task_struct *tsk)
++{
++      return !tsk->mm && !strcmp(tsk->comm, AUFS_WKQ_NAME);
++}
++
++static inline void au_nwt_done(struct au_nowait_tasks *nwt)
++{
++      if (!atomic_dec_return(&nwt->nw_len))
++              wake_up_all(&nwt->nw_wq);
++}
++
++static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
++{
++      wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
++      return 0;
++}
++
++#endif /* __KERNEL__ */
++#endif /* __AUFS_WKQ_H__ */
+diff -Naur a/fs/aufs/xino.c b/fs/aufs/xino.c
+--- a/fs/aufs/xino.c   1969-12-31 16:00:00.000000000 -0800
++++ b/fs/aufs/xino.c   2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,1191 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++/*
++ * external inode number translation table and bitmap
++ */
++
++#include <linux/file.h>
++#include <linux/seq_file.h>
++#include <linux/uaccess.h>
++#include "aufs.h"
++
++ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
++                 loff_t *pos)
++{
++      ssize_t err;
++      mm_segment_t oldfs;
++
++      oldfs = get_fs();
++      set_fs(KERNEL_DS);
++      do {
++              /* todo: signal_pending? */
++              err = func(file, (char __user *)buf, size, pos);
++      } while (err == -EAGAIN || err == -EINTR);
++      set_fs(oldfs);
++
++#if 0 /* reserved for future use */
++      if (err > 0)
++              fsnotify_access(file->f_dentry);
++#endif
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *buf,
++                            size_t size, loff_t *pos)
++{
++      ssize_t err;
++      mm_segment_t oldfs;
++
++      oldfs = get_fs();
++      set_fs(KERNEL_DS);
++      lockdep_off();
++      do {
++              /* todo: signal_pending? */
++              err = func(file, (const char __user *)buf, size, pos);
++      } while (err == -EAGAIN || err == -EINTR);
++      lockdep_on();
++      set_fs(oldfs);
++
++#if 0 /* reserved for future use */
++      if (err > 0)
++              fsnotify_modify(file->f_dentry);
++#endif
++
++      return err;
++}
++
++struct do_xino_fwrite_args {
++      ssize_t *errp;
++      au_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);
++}
++
++ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
++                  loff_t *pos)
++{
++      ssize_t err;
++
++      /* todo: signal block and no wkq? */
++      /* todo: new credential scheme */
++      /*
++       * it breaks RLIMIT_FSIZE and normal user's limit,
++       * users should care about quota and real 'filesystem full.'
++       */
++      if (!au_test_wkq(current)) {
++              int wkq_err;
++              struct do_xino_fwrite_args args = {
++                      .errp   = &err,
++                      .func   = func,
++                      .file   = file,
++                      .buf    = buf,
++                      .size   = size,
++                      .pos    = pos
++              };
++
++              wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
++              if (unlikely(wkq_err))
++                      err = wkq_err;
++      } else
++              err = do_xino_fwrite(func, file, buf, size, pos);
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * create a new xinofile at the same place/path as @base_file.
++ */
++struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
++{
++      struct file *file;
++      struct dentry *base, *dentry, *parent;
++      struct inode *dir;
++      struct qstr *name;
++      int err;
++
++      base = base_file->f_dentry;
++      parent = base->d_parent; /* dir inode is locked */
++      dir = parent->d_inode;
++      IMustLock(dir);
++
++      file = ERR_PTR(-EINVAL);
++      name = &base->d_name;
++      dentry = vfsub_lookup_one_len(name->name, parent, name->len);
++      if (IS_ERR(dentry)) {
++              file = (void *)dentry;
++              AuErr("%.*s lookup err %ld\n", AuLNPair(name), PTR_ERR(dentry));
++              goto out;
++      }
++
++      /* no need to mnt_want_write() since we call dentry_open() later */
++      err = vfs_create(dir, dentry, S_IRUGO | S_IWUGO, NULL);
++      if (unlikely(err)) {
++              file = ERR_PTR(err);
++              AuErr("%.*s create err %d\n", AuLNPair(name), err);
++              goto out_dput;
++      }
++
++      file = dentry_open(dget(dentry), mntget(base_file->f_vfsmnt),
++                         O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
++                         current_cred());
++      if (IS_ERR(file)) {
++              AuErr("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
++              goto out_dput;
++      }
++
++      err = vfsub_unlink(dir, &file->f_path, /*force*/0);
++      if (unlikely(err)) {
++              AuErr("%.*s unlink err %d\n", AuLNPair(name), err);
++              goto out_fput;
++      }
++
++      if (copy_src) {
++              /* no one can touch copy_src xino */
++              err = au_copy_file(file, copy_src,
++                                 i_size_read(copy_src->f_dentry->d_inode));
++              if (unlikely(err)) {
++                      AuErr("%.*s copy err %d\n", AuLNPair(name), err);
++                      goto out_fput;
++              }
++      }
++      goto out_dput; /* success */
++
++ out_fput:
++      fput(file);
++      file = ERR_PTR(err);
++ out_dput:
++      dput(dentry);
++ out:
++      return file;
++}
++
++struct au_xino_lock_dir {
++      struct au_hinode *hdir;
++      struct dentry *parent;
++      struct mutex *mtx;
++};
++
++static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
++                           struct au_xino_lock_dir *ldir)
++{
++      aufs_bindex_t brid, bindex;
++
++      ldir->hdir = NULL;
++      bindex = -1;
++      brid = au_xino_brid(sb);
++      if (brid >= 0)
++              bindex = au_br_index(sb, brid);
++      if (bindex >= 0) {
++              ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
++              au_hin_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
++      } else {
++              ldir->parent = dget_parent(xino->f_dentry);
++              ldir->mtx = &ldir->parent->d_inode->i_mutex;
++              mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
++      }
++}
++
++static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
++{
++      if (ldir->hdir)
++              au_hin_imtx_unlock(ldir->hdir);
++      else {
++              mutex_unlock(ldir->mtx);
++              dput(ldir->parent);
++      }
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* trucate xino files asynchronously */
++
++int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
++{
++      int err;
++      aufs_bindex_t bi, bend;
++      struct au_branch *br;
++      struct file *new_xino, *file;
++      struct super_block *h_sb;
++      struct au_xino_lock_dir ldir;
++
++      err = -EINVAL;
++      bend = au_sbend(sb);
++      if (unlikely(bindex < 0 || bend < bindex))
++              goto out;
++      br = au_sbr(sb, bindex);
++      file = br->br_xino.xi_file;
++      if (!file)
++              goto out;
++
++      au_xino_lock_dir(sb, file, &ldir);
++      /* mnt_want_write() is unnecessary here */
++      new_xino = au_xino_create2(file, file);
++      au_xino_unlock_dir(&ldir);
++      err = PTR_ERR(new_xino);
++      if (IS_ERR(new_xino))
++              goto out;
++      err = 0;
++      fput(file);
++      br->br_xino.xi_file = new_xino;
++
++      h_sb = br->br_mnt->mnt_sb;
++      for (bi = 0; bi <= bend; bi++) {
++              if (unlikely(bi == bindex))
++                      continue;
++              br = au_sbr(sb, bi);
++              if (br->br_mnt->mnt_sb != h_sb)
++                      continue;
++
++              fput(br->br_xino.xi_file);
++              br->br_xino.xi_file = new_xino;
++              get_file(new_xino);
++      }
++
++ out:
++      return err;
++}
++
++struct xino_do_trunc_args {
++      struct super_block *sb;
++      struct au_branch *br;
++};
++
++static void xino_do_trunc(void *_args)
++{
++      struct xino_do_trunc_args *args = _args;
++      struct super_block *sb;
++      struct au_branch *br;
++      struct inode *dir;
++      int err;
++      aufs_bindex_t bindex;
++
++      err = 0;
++      sb = args->sb;
++      dir = sb->s_root->d_inode;
++      br = args->br;
++
++      si_noflush_write_lock(sb);
++      ii_read_lock_parent(dir);
++      bindex = au_br_index(sb, br->br_id);
++      err = au_xino_trunc(sb, bindex);
++      if (unlikely(err))
++              goto out;
++
++      if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
++          >= br->br_xino_upper)
++              br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
++
++ out:
++      ii_read_unlock(dir);
++      if (unlikely(err))
++              AuWarn("err b%d, (%d)\n", bindex, err);
++      atomic_dec(&br->br_xino_running);
++      atomic_dec(&br->br_count);
++      au_nwt_done(&au_sbi(sb)->si_nowait);
++      si_write_unlock(sb);
++      kfree(args);
++}
++
++static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
++{
++      struct xino_do_trunc_args *args;
++      int wkq_err;
++
++      if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
++          < br->br_xino_upper)
++              return;
++
++      if (atomic_inc_return(&br->br_xino_running) > 1)
++              goto out;
++
++      /* lock and kfree() will be called in trunc_xino() */
++      args = kmalloc(sizeof(*args), GFP_NOFS);
++      if (unlikely(!args)) {
++              AuErr1("no memory\n");
++              goto out_args;
++      }
++
++      atomic_inc(&br->br_count);
++      args->sb = sb;
++      args->br = br;
++      wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
++      if (!wkq_err)
++              return; /* success */
++
++      AuErr("wkq %d\n", wkq_err);
++      atomic_dec(&br->br_count);
++
++ out_args:
++      kfree(args);
++ out:
++      atomic_dec(&br->br_xino_running);
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_xino_do_write(au_writef_t write, struct file *file,
++                          ino_t h_ino, ino_t ino)
++{
++      loff_t pos;
++      ssize_t sz;
++
++      pos = h_ino;
++      if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
++              AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
++              return -EFBIG;
++      }
++      pos *= sizeof(ino);
++      sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
++      if (sz == sizeof(ino))
++              return 0; /* success */
++
++      AuIOErr("write failed (%zd)\n", sz);
++      return -EIO;
++}
++
++/*
++ * write @ino to the xinofile for the specified branch{@sb, @bindex}
++ * at the position of @h_ino.
++ * even if @ino is zero, it is written to the xinofile and means no entry.
++ * if the size of the xino file on a specific filesystem exceeds the watermark,
++ * try truncating it.
++ */
++int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++                ino_t ino)
++{
++      int err;
++      unsigned int mnt_flags;
++      struct au_branch *br;
++
++      BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
++                   || ((loff_t)-1) > 0);
++
++      mnt_flags = au_mntflags(sb);
++      if (!au_opt_test(mnt_flags, XINO))
++              return 0;
++
++      br = au_sbr(sb, bindex);
++      err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
++                             h_ino, ino);
++      if (!err) {
++              if (au_opt_test(mnt_flags, TRUNC_XINO)
++                  && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
++                      xino_try_trunc(sb, br);
++              return 0; /* success */
++      }
++
++      AuIOErr("write failed (%d)\n", err);
++      return -EIO;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* aufs inode number bitmap */
++
++static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
++static ino_t xib_calc_ino(unsigned long pindex, int bit)
++{
++      ino_t ino;
++
++      AuDebugOn(bit < 0 || page_bits <= bit);
++      ino = AUFS_FIRST_INO + pindex * page_bits + bit;
++      return ino;
++}
++
++static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
++{
++      AuDebugOn(ino < AUFS_FIRST_INO);
++      ino -= AUFS_FIRST_INO;
++      *pindex = ino / page_bits;
++      *bit = ino % page_bits;
++}
++
++static int xib_pindex(struct super_block *sb, unsigned long pindex)
++{
++      int err;
++      loff_t pos;
++      ssize_t sz;
++      struct au_sbinfo *sbinfo;
++      struct file *xib;
++      unsigned long *p;
++
++      sbinfo = au_sbi(sb);
++      MtxMustLock(&sbinfo->si_xib_mtx);
++      AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
++                || !au_opt_test(sbinfo->si_mntflags, XINO));
++
++      if (pindex == sbinfo->si_xib_last_pindex)
++              return 0;
++
++      xib = sbinfo->si_xib;
++      p = sbinfo->si_xib_buf;
++      pos = sbinfo->si_xib_last_pindex;
++      pos *= PAGE_SIZE;
++      sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
++      if (unlikely(sz != PAGE_SIZE))
++              goto out;
++
++      pos = pindex;
++      pos *= PAGE_SIZE;
++      if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
++              sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
++      else {
++              memset(p, 0, PAGE_SIZE);
++              sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
++      }
++      if (sz == PAGE_SIZE) {
++              sbinfo->si_xib_last_pindex = pindex;
++              return 0; /* success */
++      }
++
++ out:
++      AuIOErr1("write failed (%zd)\n", sz);
++      err = sz;
++      if (sz >= 0)
++              err = -EIO;
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_xino_write0(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++                 ino_t ino)
++{
++      int err, bit;
++      unsigned long pindex;
++      struct au_sbinfo *sbinfo;
++
++      if (!au_opt_test(au_mntflags(sb), XINO))
++              return 0;
++
++      err = 0;
++      if (ino) {
++              sbinfo = au_sbi(sb);
++              xib_calc_bit(ino, &pindex, &bit);
++              AuDebugOn(page_bits <= bit);
++              mutex_lock(&sbinfo->si_xib_mtx);
++              err = xib_pindex(sb, pindex);
++              if (!err) {
++                      clear_bit(bit, sbinfo->si_xib_buf);
++                      sbinfo->si_xib_next_bit = bit;
++              }
++              mutex_unlock(&sbinfo->si_xib_mtx);
++      }
++
++      if (!err)
++              err = au_xino_write(sb, bindex, h_ino, 0);
++      return err;
++}
++
++/* get an unused inode number from bitmap */
++ino_t au_xino_new_ino(struct super_block *sb)
++{
++      ino_t ino;
++      unsigned long *p, pindex, ul, pend;
++      struct au_sbinfo *sbinfo;
++      struct file *file;
++      int free_bit, err;
++
++      if (!au_opt_test(au_mntflags(sb), XINO))
++              return iunique(sb, AUFS_FIRST_INO);
++
++      sbinfo = au_sbi(sb);
++      mutex_lock(&sbinfo->si_xib_mtx);
++      p = sbinfo->si_xib_buf;
++      free_bit = sbinfo->si_xib_next_bit;
++      if (free_bit < page_bits && !test_bit(free_bit, p))
++              goto out; /* success */
++      free_bit = find_first_zero_bit(p, page_bits);
++      if (free_bit < page_bits)
++              goto out; /* success */
++
++      pindex = sbinfo->si_xib_last_pindex;
++      for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
++              err = xib_pindex(sb, ul);
++              if (unlikely(err))
++                      goto out_err;
++              free_bit = find_first_zero_bit(p, page_bits);
++              if (free_bit < page_bits)
++                      goto out; /* success */
++      }
++
++      file = sbinfo->si_xib;
++      pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
++      for (ul = pindex + 1; ul <= pend; ul++) {
++              err = xib_pindex(sb, ul);
++              if (unlikely(err))
++                      goto out_err;
++              free_bit = find_first_zero_bit(p, page_bits);
++              if (free_bit < page_bits)
++                      goto out; /* success */
++      }
++      BUG();
++
++ out:
++      set_bit(free_bit, p);
++      sbinfo->si_xib_next_bit++;
++      pindex = sbinfo->si_xib_last_pindex;
++      mutex_unlock(&sbinfo->si_xib_mtx);
++      ino = xib_calc_ino(pindex, free_bit);
++      AuDbg("i%lu\n", (unsigned long)ino);
++      return ino;
++ out_err:
++      mutex_unlock(&sbinfo->si_xib_mtx);
++      AuDbg("i0\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 au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
++               ino_t *ino)
++{
++      int err;
++      ssize_t sz;
++      loff_t pos;
++      struct file *file;
++      struct au_sbinfo *sbinfo;
++
++      *ino = 0;
++      if (!au_opt_test(au_mntflags(sb), XINO))
++              return 0; /* no xino */
++
++      err = 0;
++      sbinfo = au_sbi(sb);
++      pos = h_ino;
++      if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
++              AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
++              return -EFBIG;
++      }
++      pos *= sizeof(*ino);
++
++      file = au_sbr(sb, bindex)->br_xino.xi_file;
++      if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
++              return 0; /* no ino */
++
++      sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
++      if (sz == sizeof(*ino))
++              return 0; /* success */
++
++      err = sz;
++      if (unlikely(sz >= 0)) {
++              err = -EIO;
++              AuIOErr("xino read error (%zd)\n", sz);
++      }
++
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* create and set a new xino file */
++
++struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
++{
++      struct file *file;
++      struct dentry *h_parent, *d;
++      struct inode *h_dir;
++      int err;
++
++      /*
++       * at mount-time, and the xino file is the default path,
++       * hinotify is disabled so we have no inotify events to ignore.
++       * when a user specified the xino, we cannot get au_hdir to be ignored.
++       */
++      file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE,
++                             S_IRUGO | S_IWUGO);
++      if (IS_ERR(file)) {
++              if (!silent)
++                      AuErr("open %s(%ld)\n", fname, PTR_ERR(file));
++              return file;
++      }
++
++      /* keep file count */
++      h_parent = dget_parent(file->f_dentry);
++      h_dir = h_parent->d_inode;
++      mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
++      /* mnt_want_write() is unnecessary here */
++      err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
++      mutex_unlock(&h_dir->i_mutex);
++      dput(h_parent);
++      if (unlikely(err)) {
++              if (!silent)
++                      AuErr("unlink %s(%d)\n", fname, err);
++              goto out;
++      }
++
++      err = -EINVAL;
++      d = file->f_dentry;
++      if (unlikely(sb == d->d_sb)) {
++              if (!silent)
++                      AuErr("%s must be outside\n", fname);
++              goto out;
++      }
++      if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
++              if (!silent)
++                      AuErr("xino doesn't support %s(%s)\n",
++                            fname, au_sbtype(d->d_sb));
++              goto out;
++      }
++      return file; /* success */
++
++ 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 = au_sbr_sb(sb, btgt);
++
++      for (bindex = 0; bindex < btgt; bindex++)
++              if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
++                      return bindex;
++      for (bindex++; bindex <= bend; bindex++)
++              if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
++                      return bindex;
++      return -1;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * initialize the xinofile for the specified branch @br
++ * 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 au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
++             struct file *base_file, int do_test)
++{
++      int err;
++      ino_t ino;
++      aufs_bindex_t bend, bindex;
++      struct au_branch *shared_br, *b;
++      struct file *file;
++      struct super_block *tgt_sb;
++
++      shared_br = NULL;
++      bend = au_sbend(sb);
++      if (do_test) {
++              tgt_sb = br->br_mnt->mnt_sb;
++              for (bindex = 0; bindex <= bend; bindex++) {
++                      b = au_sbr(sb, bindex);
++                      if (tgt_sb == b->br_mnt->mnt_sb) {
++                              shared_br = b;
++                              break;
++                      }
++              }
++      }
++
++      if (!shared_br || !shared_br->br_xino.xi_file) {
++              struct au_xino_lock_dir ldir;
++
++              au_xino_lock_dir(sb, base_file, &ldir);
++              /* mnt_want_write() is unnecessary here */
++              file = au_xino_create2(base_file, NULL);
++              au_xino_unlock_dir(&ldir);
++              err = PTR_ERR(file);
++              if (IS_ERR(file))
++                      goto out;
++              br->br_xino.xi_file = file;
++      } else {
++              br->br_xino.xi_file = shared_br->br_xino.xi_file;
++              get_file(br->br_xino.xi_file);
++      }
++
++      ino = AUFS_ROOT_INO;
++      err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
++                             h_ino, ino);
++      if (!err)
++              return 0; /* success */
++
++
++ out:
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/* trucate a xino bitmap file */
++
++/* todo: slow */
++static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
++{
++      int err, bit;
++      ssize_t sz;
++      unsigned long pindex;
++      loff_t pos, pend;
++      struct au_sbinfo *sbinfo;
++      au_readf_t func;
++      ino_t *ino;
++      unsigned long *p;
++
++      err = 0;
++      sbinfo = au_sbi(sb);
++      p = sbinfo->si_xib_buf;
++      func = sbinfo->si_xread;
++      pend = i_size_read(file->f_dentry->d_inode);
++      pos = 0;
++      while (pos < pend) {
++              sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
++              err = sz;
++              if (unlikely(sz <= 0))
++                      goto out;
++
++              err = 0;
++              for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
++                      if (unlikely(*ino < AUFS_FIRST_INO))
++                              continue;
++
++                      xib_calc_bit(*ino, &pindex, &bit);
++                      AuDebugOn(page_bits <= bit);
++                      err = xib_pindex(sb, pindex);
++                      if (!err)
++                              set_bit(bit, p);
++                      else
++                              goto out;
++              }
++      }
++
++ out:
++      return err;
++}
++
++static int xib_restore(struct super_block *sb)
++{
++      int err;
++      aufs_bindex_t bindex, bend;
++      void *page;
++
++      err = -ENOMEM;
++      page = (void *)__get_free_page(GFP_NOFS);
++      if (unlikely(!page))
++              goto out;
++
++      err = 0;
++      bend = au_sbend(sb);
++      for (bindex = 0; !err && bindex <= bend; bindex++)
++              if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
++                      err = do_xib_restore
++                              (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
++              else
++                      AuDbg("b%d\n", bindex);
++      free_page((unsigned long)page);
++
++ out:
++      return err;
++}
++
++int au_xib_trunc(struct super_block *sb)
++{
++      int err;
++      ssize_t sz;
++      loff_t pos;
++      struct au_xino_lock_dir ldir;
++      struct au_sbinfo *sbinfo;
++      unsigned long *p;
++      struct file *file;
++
++      err = 0;
++      sbinfo = au_sbi(sb);
++      if (!au_opt_test(sbinfo->si_mntflags, XINO))
++              goto out;
++
++      file = sbinfo->si_xib;
++      if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
++              goto out;
++
++      au_xino_lock_dir(sb, file, &ldir);
++      /* mnt_want_write() is unnecessary here */
++      file = au_xino_create2(sbinfo->si_xib, NULL);
++      au_xino_unlock_dir(&ldir);
++      err = PTR_ERR(file);
++      if (IS_ERR(file))
++              goto out;
++      fput(sbinfo->si_xib);
++      sbinfo->si_xib = file;
++
++      p = sbinfo->si_xib_buf;
++      memset(p, 0, PAGE_SIZE);
++      pos = 0;
++      sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
++      if (unlikely(sz != PAGE_SIZE)) {
++              err = sz;
++              AuIOErr("err %d\n", err);
++              if (sz >= 0)
++                      err = -EIO;
++              goto out;
++      }
++
++      mutex_lock(&sbinfo->si_xib_mtx);
++      /* mnt_want_write() is unnecessary here */
++      err = xib_restore(sb);
++      mutex_unlock(&sbinfo->si_xib_mtx);
++
++out:
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * xino mount option handlers
++ */
++static au_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 au_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);
++}
++
++/* xino bitmap */
++static void xino_clear_xib(struct super_block *sb)
++{
++      struct au_sbinfo *sbinfo;
++
++      sbinfo = au_sbi(sb);
++      sbinfo->si_xread = NULL;
++      sbinfo->si_xwrite = NULL;
++      if (sbinfo->si_xib)
++              fput(sbinfo->si_xib);
++      sbinfo->si_xib = NULL;
++      free_page((unsigned long)sbinfo->si_xib_buf);
++      sbinfo->si_xib_buf = NULL;
++}
++
++static int au_xino_set_xib(struct super_block *sb, struct file *base)
++{
++      int err;
++      loff_t pos;
++      struct au_sbinfo *sbinfo;
++      struct file *file;
++
++      sbinfo = au_sbi(sb);
++      file = au_xino_create2(base, sbinfo->si_xib);
++      err = PTR_ERR(file);
++      if (IS_ERR(file))
++              goto out;
++      if (sbinfo->si_xib)
++              fput(sbinfo->si_xib);
++      sbinfo->si_xib = file;
++      sbinfo->si_xread = find_readf(file);
++      sbinfo->si_xwrite = find_writef(file);
++
++      err = -ENOMEM;
++      if (!sbinfo->si_xib_buf)
++              sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
++      if (unlikely(!sbinfo->si_xib_buf))
++              goto out_unset;
++
++      sbinfo->si_xib_last_pindex = 0;
++      sbinfo->si_xib_next_bit = 0;
++      if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
++              pos = 0;
++              err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
++                                PAGE_SIZE, &pos);
++              if (unlikely(err != PAGE_SIZE))
++                      goto out_free;
++      }
++      err = 0;
++      goto out; /* success */
++
++ out_free:
++      free_page((unsigned long)sbinfo->si_xib_buf);
++      sbinfo->si_xib_buf = NULL;
++      if (err >= 0)
++              err = -EIO;
++ out_unset:
++      fput(sbinfo->si_xib);
++      sbinfo->si_xib = NULL;
++      sbinfo->si_xread = NULL;
++      sbinfo->si_xwrite = NULL;
++ out:
++      return err;
++}
++
++/* xino for each branch */
++static void xino_clear_br(struct super_block *sb)
++{
++      aufs_bindex_t bindex, bend;
++      struct au_branch *br;
++
++      bend = au_sbend(sb);
++      for (bindex = 0; bindex <= bend; bindex++) {
++              br = au_sbr(sb, bindex);
++              if (!br || !br->br_xino.xi_file)
++                      continue;
++
++              fput(br->br_xino.xi_file);
++              br->br_xino.xi_file = NULL;
++      }
++}
++
++static int au_xino_set_br(struct super_block *sb, struct file *base)
++{
++      int err;
++      ino_t ino;
++      aufs_bindex_t bindex, bend, bshared;
++      struct {
++              struct file *old, *new;
++      } *fpair, *p;
++      struct au_branch *br;
++      struct inode *inode;
++      au_writef_t writef;
++
++      err = -ENOMEM;
++      bend = au_sbend(sb);
++      fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
++      if (unlikely(!fpair))
++              goto out;
++
++      inode = sb->s_root->d_inode;
++      ino = AUFS_ROOT_INO;
++      writef = au_sbi(sb)->si_xwrite;
++      for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
++              br = au_sbr(sb, bindex);
++              bshared = is_sb_shared(sb, bindex, bindex - 1);
++              if (bshared >= 0) {
++                      /* shared xino */
++                      *p = fpair[bshared];
++                      get_file(p->new);
++              }
++
++              if (!p->new) {
++                      /* new xino */
++                      p->old = br->br_xino.xi_file;
++                      p->new = au_xino_create2(base, br->br_xino.xi_file);
++                      err = PTR_ERR(p->new);
++                      if (IS_ERR(p->new)) {
++                              p->new = NULL;
++                              goto out_pair;
++                      }
++              }
++
++              err = au_xino_do_write(writef, p->new,
++                                     au_h_iptr(inode, bindex)->i_ino, ino);
++              if (unlikely(err))
++                      goto out_pair;
++      }
++
++      for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
++              br = au_sbr(sb, bindex);
++              if (br->br_xino.xi_file)
++                      fput(br->br_xino.xi_file);
++              get_file(p->new);
++              br->br_xino.xi_file = p->new;
++      }
++
++ out_pair:
++      for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
++              if (p->new)
++                      fput(p->new);
++              else
++                      break;
++      kfree(fpair);
++ out:
++      return err;
++}
++
++void au_xino_clr(struct super_block *sb)
++{
++      struct au_sbinfo *sbinfo;
++
++      au_xigen_clr(sb);
++      xino_clear_xib(sb);
++      xino_clear_br(sb);
++      sbinfo = au_sbi(sb);
++      /* lvalue, do not call au_mntflags() */
++      au_opt_clr(sbinfo->si_mntflags, XINO);
++}
++
++int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
++{
++      int err, skip;
++      struct dentry *parent, *cur_parent;
++      struct qstr *dname, *cur_name;
++      struct file *cur_xino;
++      struct inode *dir;
++      struct au_sbinfo *sbinfo;
++
++      err = 0;
++      sbinfo = au_sbi(sb);
++      parent = dget_parent(xino->file->f_dentry);
++      if (remount) {
++              skip = 0;
++              dname = &xino->file->f_dentry->d_name;
++              cur_xino = sbinfo->si_xib;
++              if (cur_xino) {
++                      cur_parent = dget_parent(cur_xino->f_dentry);
++                      cur_name = &cur_xino->f_dentry->d_name;
++                      skip = (cur_parent == parent
++                              && dname->len == cur_name->len
++                              && !memcmp(dname->name, cur_name->name,
++                                         dname->len));
++                      dput(cur_parent);
++              }
++              if (skip)
++                      goto out;
++      }
++
++      au_opt_set(sbinfo->si_mntflags, XINO);
++      dir = parent->d_inode;
++      mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
++      /* mnt_want_write() is unnecessary here */
++      err = au_xino_set_xib(sb, xino->file);
++      if (!err)
++              err = au_xigen_set(sb, xino->file);
++      if (!err)
++              err = au_xino_set_br(sb, xino->file);
++      mutex_unlock(&dir->i_mutex);
++      if (!err)
++              goto out; /* success */
++
++      /* reset all */
++      AuIOErr("failed creating xino(%d).\n", err);
++
++ out:
++      dput(parent);
++      return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * create a xinofile at the default place/path.
++ */
++struct file *au_xino_def(struct super_block *sb)
++{
++      struct file *file;
++      char *page, *p;
++      struct au_branch *br;
++      struct super_block *h_sb;
++      struct path path;
++      aufs_bindex_t bend, bindex, bwr;
++
++      br = NULL;
++      bend = au_sbend(sb);
++      bwr = -1;
++      for (bindex = 0; bindex <= bend; bindex++) {
++              br = au_sbr(sb, bindex);
++              if (au_br_writable(br->br_perm)
++                  && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
++                      bwr = bindex;
++                      break;
++              }
++      }
++
++      if (bwr >= 0) {
++              file = ERR_PTR(-ENOMEM);
++              page = __getname();
++              if (unlikely(!page))
++                      goto out;
++              path.mnt = br->br_mnt;
++              path.dentry = au_h_dptr(sb->s_root, bwr);
++              p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
++              file = (void *)p;
++              if (!IS_ERR(p)) {
++                      strcat(p, "/" AUFS_XINO_FNAME);
++                      AuDbg("%s\n", p);
++                      file = au_xino_create(sb, p, /*silent*/0);
++                      if (!IS_ERR(file))
++                              au_xino_brid_set(sb, br->br_id);
++              }
++              __putname(page);
++      } else {
++              file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
++              if (IS_ERR(file))
++                      goto out;
++              h_sb = file->f_dentry->d_sb;
++              if (unlikely(au_test_fs_bad_xino(h_sb))) {
++                      AuErr("xino doesn't support %s(%s)\n",
++                            AUFS_XINO_DEFPATH, au_sbtype(h_sb));
++                      fput(file);
++                      file = ERR_PTR(-EINVAL);
++              }
++              if (!IS_ERR(file))
++                      au_xino_brid_set(sb, -1);
++      }
++
++ out:
++      return file;
++}
++
++/* ---------------------------------------------------------------------- */
++
++int au_xino_path(struct seq_file *seq, struct file *file)
++{
++      int err;
++
++      err = au_seq_path(seq, &file->f_path);
++      if (unlikely(err < 0))
++              goto out;
++
++      err = 0;
++#define Deleted "\\040(deleted)"
++      seq->count -= sizeof(Deleted) - 1;
++      AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
++                       sizeof(Deleted) - 1));
++#undef Deleted
++
++ out:
++      return err;
++}
+diff -Naur a/include/linux/aufs_type.h b/include/linux/aufs_type.h
+--- a/include/linux/aufs_type.h        1969-12-31 16:00:00.000000000 -0800
++++ b/include/linux/aufs_type.h        2009-06-22 23:36:25.000000000 -0700
+@@ -0,0 +1,109 @@
++/*
++ * Copyright (C) 2005-2009 Junjiro R. 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
++ */
++
++#ifndef __AUFS_TYPE_H__
++#define __AUFS_TYPE_H__
++
++#include <linux/ioctl.h>
++
++#define AUFS_VERSION  "2-standalone.tree-29-20090622"
++
++/* todo? move this to linux-2.6.19/include/magic.h */
++#define AUFS_SUPER_MAGIC      ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
++
++/* ---------------------------------------------------------------------- */
++
++#ifdef CONFIG_AUFS_BRANCH_MAX_127
++/* some environments treat 'char' as 'unsigned char' by default */
++typedef signed 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
++#endif
++#endif
++
++#ifdef __KERNEL__
++#ifndef AUFS_BRANCH_MAX
++#error unknown CONFIG_AUFS_BRANCH_MAX value
++#endif
++#endif /* __KERNEL__ */
++
++/* ---------------------------------------------------------------------- */
++
++#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_XINO_TRUNC_INIT  64 /* blocks */
++#define AUFS_XINO_TRUNC_STEP  4  /* blocks */
++#define AUFS_DIRWH_DEF                3
++#define AUFS_RDCACHE_DEF      10 /* seconds */
++#define AUFS_RDBLK_DEF                512 /* bytes */
++#define AUFS_RDHASH_DEF               32
++#define AUFS_WKQ_NAME         AUFS_NAME "d"
++#define AUFS_NWKQ_DEF         4
++#define AUFS_MFS_SECOND_DEF   30 /* seconds */
++#define AUFS_PLINK_WARN               100 /* number of plinks */
++
++#define AUFS_DIROPQ_NAME      AUFS_WH_PFX ".opq" /* whiteouted doubly */
++#define AUFS_WH_DIROPQ                AUFS_WH_PFX AUFS_DIROPQ_NAME
++
++#define AUFS_BASE_NAME                AUFS_WH_PFX AUFS_NAME
++#define AUFS_PLINKDIR_NAME    AUFS_WH_PFX "plnk"
++#define AUFS_ORPHDIR_NAME     AUFS_WH_PFX "orph"
++
++/* doubly whiteouted */
++#define AUFS_WH_BASE          AUFS_WH_PFX AUFS_BASE_NAME
++#define AUFS_WH_PLINKDIR      AUFS_WH_PFX AUFS_PLINKDIR_NAME
++#define AUFS_WH_ORPHDIR               AUFS_WH_PFX AUFS_ORPHDIR_NAME
++
++/* branch permission */
++#define AUFS_BRPERM_RW                "rw"
++#define AUFS_BRPERM_RO                "ro"
++#define AUFS_BRPERM_RR                "rr"
++#define AUFS_BRPERM_WH                "wh"
++#define AUFS_BRPERM_NLWH      "nolwh"
++#define AUFS_BRPERM_ROWH      AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
++#define AUFS_BRPERM_RRWH      AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
++#define AUFS_BRPERM_RWNLWH    AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
++
++/* ---------------------------------------------------------------------- */
++
++/* ioctl */
++enum {
++      AuCtl_PLINK_MAINT,
++      AuCtl_PLINK_CLEAN
++};
++
++#define AuCtlType             'A'
++#define AUFS_CTL_PLINK_MAINT  _IO(AuCtlType, AuCtl_PLINK_MAINT)
++#define AUFS_CTL_PLINK_CLEAN  _IO(AuCtlType, AuCtl_PLINK_CLEAN)
++
++#endif /* __AUFS_TYPE_H__ */
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-squashfs-mount-to-avoid-initramfs.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/aufs-squashfs-mount-to-avoid-initramfs.patch
new file mode 100644 (file)
index 0000000..9a9b982
--- /dev/null
@@ -0,0 +1,40 @@
+--- linux-omap-2.6/init/do_mounts.c    2008-11-23 01:22:52.000000000 -0800
++++ linux-omap-2.6/init/do_mounts.c    2008-11-23 02:17:58.000000000 -0800
+@@ -325,6 +325,37 @@
+ void __init mount_root(void)
+ {
++      int do_special = 0;
++      if (strcmp(root_device_name, "special") == 0)
++              do_special = 1;
++      //do_special = 1;
++
++      if (do_special) {
++              dev_t ROOT_DEV_RO;
++              dev_t ROOT_DEV_RW;
++
++              sys_mkdir("/root-ro", 0700);
++              ROOT_DEV_RO = name_to_dev_t("/dev/mtd4");
++              create_dev("/dev/root-ro", ROOT_DEV_RO);
++              if (sys_mount("/dev/root-ro", "/root-ro", "squashfs", MS_RDONLY | MS_SILENT, NULL) != 0) {
++                      ROOT_DEV_RO = name_to_dev_t("/dev/mmcblk0p2");
++                      create_dev("/dev/root-ro2", ROOT_DEV_RO);
++                      if (sys_mount("/dev/root-ro2", "/root-ro", "squashfs", MS_RDONLY | MS_SILENT, NULL) != 0)
++                              goto no_special;
++              }
++              
++              sys_mkdir("/root-rw", 0700);
++              ROOT_DEV_RW = name_to_dev_t("/dev/mmcblk0p3");
++              create_dev("/dev/root-rw", ROOT_DEV_RW);
++              if (sys_mount("/dev/root-rw", "/root-rw", "ext3", MS_SILENT, NULL) != 0)
++                      goto no_special;
++              sys_mount("none", "/root", "aufs", 0, "br:/root-rw:/root-ro=ro");
++              sys_chdir("/root");
++              return;
++      }
++
++no_special:
++
+ #ifdef CONFIG_ROOT_NFS
+       if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
+               if (mount_nfs_root())
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-1.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-1.patch
new file mode 100644 (file)
index 0000000..035627a
--- /dev/null
@@ -0,0 +1,221 @@
+From 1b3e7e2e095648f244a08b1459ff035bbdc99942 Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Tue, 5 May 2009 23:33:00 -0700
+Subject: [PATCH] TWL BCI: Make charge current controllable and backup battery optional.
+
+This patch makes the charging current controllable via sysfs and also
+makes the backup battery optional. Also, if you don't care about the
+temperature readings, you can opt-out from having to supply a
+temperature lookup table.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ drivers/power/twl4030_bci_battery.c |   91 +++++++++++++++++++++++++++++------
+ include/linux/i2c/twl4030.h         |    2 +
+ 2 files changed, 78 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/power/twl4030_bci_battery.c b/drivers/power/twl4030_bci_battery.c
+index ddba62b..eab0933 100644
+--- a/drivers/power/twl4030_bci_battery.c
++++ b/drivers/power/twl4030_bci_battery.c
+@@ -125,6 +125,14 @@
+ /* BCIEDR3 */
+ #define       VBATLVL_EDRRISIN        0x02
++/* BCIIREF1 */
++#define REG_BCIIREF1          0x027
++#define REG_BCIIREF2          0x028
++
++/* Key */
++#define KEY_IIREF             0xE7
++#define REG_BCIMFKEY          0x011
++
+ /* Step size and prescaler ratio */
+ #define TEMP_STEP_SIZE                147
+ #define TEMP_PSR_R            100
+@@ -142,9 +150,6 @@
+ #define ENABLE                1
+ #define DISABLE               1
+-/* Ptr to thermistor table */
+-int *therm_tbl;
+-
+ struct twl4030_bci_device_info {
+       struct device           *dev;
+@@ -160,6 +165,8 @@ struct twl4030_bci_device_info {
+       struct power_supply     bk_bat;
+       struct delayed_work     twl4030_bci_monitor_work;
+       struct delayed_work     twl4030_bk_bci_monitor_work;
++
++      struct twl4030_bci_platform_data *pdata;
+ };
+ static int usb_charger_flag;
+@@ -518,11 +525,15 @@ int twl4030charger_usb_en(int enable)
+  * Return battery temperature
+  * Or < 0 on failure.
+  */
+-static int twl4030battery_temperature(void)
++static int twl4030battery_temperature(struct twl4030_bci_device_info *di)
+ {
+       u8 val;
+       int temp, curr, volt, res, ret;
++      /* Is a temperature table specified? */
++      if (!di->pdata->tblsize)
++              return 0;
++
+       /* Getting and calculating the thermistor voltage */
+       ret = read_bci_val(T2_BATTERY_TEMP);
+       if (ret < 0)
+@@ -543,7 +554,7 @@ static int twl4030battery_temperature(void)
+       /*calculating temperature*/
+       for (temp = 58; temp >= 0; temp--) {
+-              int actual = therm_tbl[temp];
++              int actual = di->pdata->battery_tmp_tbl[temp];
+               if ((actual - res) >= 0)
+                       break;
+       }
+@@ -772,13 +783,14 @@ static void twl4030_bk_bci_battery_work(struct work_struct *work)
+               struct twl4030_bci_device_info,
+               twl4030_bk_bci_monitor_work.work);
+-      twl4030_bk_bci_battery_read_status(di);
++      if(!di->pdata->no_backup_battery)
++              twl4030_bk_bci_battery_read_status(di);
+       schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
+ }
+ static void twl4030_bci_battery_read_status(struct twl4030_bci_device_info *di)
+ {
+-      di->temp_C = twl4030battery_temperature();
++      di->temp_C = twl4030battery_temperature(di);
+       di->voltage_uV = twl4030battery_voltage();
+       di->current_uA = twl4030battery_current();
+ }
+@@ -819,6 +831,43 @@ static void twl4030_bci_battery_external_power_changed(struct power_supply *psy)
+ #define to_twl4030_bk_bci_device_info(x) container_of((x), \
+               struct twl4030_bci_device_info, bk_bat);
++static ssize_t
++show_charge_current(struct device *dev, struct device_attribute *attr, char *buf)
++{
++      return sprintf(buf, "%d\n", read_bci_val(REG_BCIIREF1));
++}
++
++static ssize_t
++set_charge_current(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
++{
++      unsigned long newCurrent;
++      int ret;
++
++      ret = strict_strtoul(buf, 10, &newCurrent);
++      if (ret)
++              return -EINVAL;
++
++      ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF, REG_BCIMFKEY);
++      if (ret)
++              return ret;
++
++      ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, newCurrent & 0xff, REG_BCIIREF1);
++      if (ret)
++              return ret;
++
++      ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF, REG_BCIMFKEY);
++      if (ret)
++              return ret;
++
++      ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >> 8) & 0x03, REG_BCIIREF2);
++      if (ret)
++              return ret;
++
++      return count;
++}
++
++static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUGO, show_charge_current, set_charge_current);
++
+ static int twl4030_bk_bci_battery_get_property(struct power_supply *psy,
+                                       enum power_supply_property psp,
+                                       union power_supply_propval *val)
+@@ -912,8 +961,6 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+       int irq;
+       int ret;
+-      therm_tbl = pdata->battery_tmp_tbl;
+-
+       di = kzalloc(sizeof(*di), GFP_KERNEL);
+       if (!di)
+               return -ENOMEM;
+@@ -937,6 +984,7 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+       di->bk_bat.num_properties = ARRAY_SIZE(twl4030_bk_bci_battery_props);
+       di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
+       di->bk_bat.external_power_changed = NULL;
++      di->pdata = pdata;
+       twl4030charger_ac_en(ENABLE);
+       twl4030charger_usb_en(ENABLE);
+@@ -951,9 +999,12 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+               goto temp_setup_fail;
+       /* enabling GPCH09 for read back battery voltage */
+-      ret = twl4030backupbatt_voltage_setup();
+-      if (ret)
+-              goto voltage_setup_fail;
++      if(!di->pdata->no_backup_battery)
++      {
++              ret = twl4030backupbatt_voltage_setup();
++              if (ret)
++                      goto voltage_setup_fail;
++      }
+       /* REVISIT do we need to request both IRQs ?? */
+@@ -988,9 +1039,18 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+                               twl4030_bci_battery_work);
+       schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
+-      ret = power_supply_register(&pdev->dev, &di->bk_bat);
++      if(!pdata->no_backup_battery)
++      {
++              ret = power_supply_register(&pdev->dev, &di->bk_bat);
++              if (ret) {
++                      dev_dbg(&pdev->dev, "failed to register backup battery\n");
++                      goto bk_batt_failed;
++              }
++      }
++
++      ret = device_create_file(di->bat.dev, &dev_attr_charge_current);
+       if (ret) {
+-              dev_dbg(&pdev->dev, "failed to register backup battery\n");
++              dev_err(&pdev->dev, "failed to create sysfs entries\n");
+               goto bk_batt_failed;
+       }
+@@ -1001,7 +1061,8 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+       return 0;
+ bk_batt_failed:
+-      power_supply_unregister(&di->bat);
++      if(!pdata->no_backup_battery)
++              power_supply_unregister(&di->bat);
+ batt_failed:
+       free_irq(irq, di);
+ chg_irq_fail:
+diff --git a/include/linux/i2c/twl4030.h b/include/linux/i2c/twl4030.h
+index 87accda..a188b6c 100644
+--- a/include/linux/i2c/twl4030.h
++++ b/include/linux/i2c/twl4030.h
+@@ -299,6 +299,8 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
+ struct twl4030_bci_platform_data {
+       int *battery_tmp_tbl;
+       unsigned int tblsize;
++
++      bool no_backup_battery;
+ };
+ /* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */
+-- 
+1.5.6.3
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-2.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery1-tps65950-charging-management-2.patch
new file mode 100644 (file)
index 0000000..ce5a98f
--- /dev/null
@@ -0,0 +1,246 @@
+diff --git a/drivers/power/twl4030_bci_battery.c b/drivers/power/twl4030_bci_battery.c
+index eab0933..d1220d7 100644
+--- a/drivers/power/twl4030_bci_battery.c
++++ b/drivers/power/twl4030_bci_battery.c
+@@ -15,6 +15,9 @@
+  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+  */
++/* Boot with automatic charge */
++#define CHARGE_MODE 1
++
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/device.h>
+@@ -50,6 +53,7 @@
+ /* Boot BCI flag bits */
+ #define BCIAUTOWEN            0x020
+ #define CONFIG_DONE           0x010
++#define CVENAC                        0x004
+ #define BCIAUTOUSB            0x002
+ #define BCIAUTOAC             0x001
+ #define BCIMSTAT_MASK         0x03F
+@@ -81,6 +85,11 @@
+ #define REG_BB_CFG            0x012
+ #define BBCHEN                        0x010
++/* GPBR */
++#define REG_GPBR1             0x0c
++#define MADC_HFCLK_EN         0x80
++#define DEFAULT_MADC_CLK_EN   0x10
++
+ /* Power supply charge interrupt */
+ #define REG_PWR_ISR1          0x00
+ #define REG_PWR_IMR1          0x01
+@@ -129,8 +138,12 @@
+ #define REG_BCIIREF1          0x027
+ #define REG_BCIIREF2          0x028
++/* BCIMFTH1 */
++#define REG_BCIMFTH1          0x016
++
+ /* Key */
+ #define KEY_IIREF             0xE7
++#define KEY_FTH1              0xD2
+ #define REG_BCIMFKEY          0x011
+ /* Step size and prescaler ratio */
+@@ -432,15 +445,21 @@ static int twl4030battery_hw_presence_en(int enable)
+ /*
+  * Enable/Disable AC Charge funtionality.
+  */
+-static int twl4030charger_ac_en(int enable)
++static int twl4030charger_ac_en(int enable, int automatic)
+ {
+       int ret;
+       if (enable) {
+               /* forcing the field BCIAUTOAC (BOOT_BCI[0) to 1 */
+-              ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
+-                      (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC),
+-                      REG_BOOT_BCI);
++              if(!automatic) {
++                      ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC | CVENAC,
++                              (CONFIG_DONE | BCIAUTOWEN),
++                              REG_BOOT_BCI);
++              } else {
++                      ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
++                              (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC | CVENAC),
++                              REG_BOOT_BCI);
++              }
+               if (ret)
+                       return ret;
+       } else {
+@@ -672,6 +691,9 @@ static int twl4030bci_status(void)
+               return ret;
+       }
++#ifdef DEBUG
++      printk("BCI DEBUG: BCIMSTATEC Charge state is 0x%x\n", status);
++#endif
+       return (int) (status & BCIMSTAT_MASK);
+ }
+@@ -720,14 +742,43 @@ static int twl4030backupbatt_voltage_setup(void)
+  */
+ static int twl4030battery_temp_setup(void)
+ {
+-      int ret;
++#ifdef DEBUG
++      u8 i;
++#endif
++      u8 ret;
+       /* Enabling thermistor current */
+-      ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, ITHEN,
++      ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, 0x1B,
+               REG_BCICTL1);
+       if (ret)
+               return ret;
++#ifdef DEBUG
++      twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_BOOT_BCI);
++      printk("BCI DEBUG: BOOT_BCI Value is 0x%x\n", ret);
++
++      twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_STS_HW_CONDITIONS);
++      printk("BCI DEBUG: STS_HW_CONDITIONS Value is 0x%x\n", ret);
++
++      twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL1);
++      printk("BCI DEBUG: BCICTL1 Value is 0x%x\n", ret);
++
++      twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL2);
++      printk("BCI DEBUG: BCICTL2 Value is 0x%x\n", ret);
++
++      twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, 0x0);
++      printk("BCI DEBUG: BCIMDEN Value is 0x%x\n", ret);
++
++      twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &ret, REG_GPBR1);
++      printk("BCI DEBUG: GPBR1 Value is 0x%x\n", ret);
++
++      for(i = 0x0; i <= 0x32; i++)
++      {
++              twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, i);
++              printk("BCI DEBUG: BCI 0x%x Value is 0x%x\n", i, ret);
++      }
++#endif
++
+       return 0;
+ }
+@@ -743,7 +794,6 @@ static inline int clear_n_set(u8 mod_no, u8 clear, u8 set, u8 reg)
+       ret = twl4030_i2c_read_u8(mod_no, &val, reg);
+       if (ret)
+               return ret;
+-
+       /* Clearing all those bits to clear */
+       val &= ~(clear);
+@@ -834,7 +884,19 @@ static void twl4030_bci_battery_external_power_changed(struct power_supply *psy)
+ static ssize_t
+ show_charge_current(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+-      return sprintf(buf, "%d\n", read_bci_val(REG_BCIIREF1));
++      u8  ctl;
++      int ret = read_bci_val(REG_BCIIREF1) & 0x1FF;
++      twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ctl, REG_BCICTL1);
++
++      if (ctl & CGAIN)
++              ret |= 0x200;
++
++#ifdef DEBUG
++      /* Dump debug */
++      twl4030battery_temp_setup();
++#endif
++
++      return sprintf(buf, "%d\n", ret);
+ }
+ static ssize_t
+@@ -859,13 +921,45 @@ set_charge_current(struct device *dev, struct device_attribute *attr, const char
+       if (ret)
+               return ret;
+-      ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >> 8) & 0x03, REG_BCIIREF2);
++      ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >> 8) & 0x1, REG_BCIIREF2);
+       if (ret)
+               return ret;
++      /* Set software-controlled charge */
++      twl4030charger_ac_en(ENABLE, 0);
++
++      /* Set CGAIN = 0 or 1 */
++      if(newCurrent > 511) {
++              u8 tmp;
++
++              /* Set CGAIN = 1 -- need to wait until automatic charge turns off */
++              while(!ret) {
++                      clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, CGAIN | 0x1B, REG_BCICTL1);
++                      twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
++
++                      ret = tmp & CGAIN;
++                      if(!ret)
++                              mdelay(50);
++              }
++      } else {
++              u8 tmp;
++
++              /* Set CGAIN = 0 -- need to wait until automatic charge turns off */
++              while(!ret) {
++                      clear_n_set(TWL4030_MODULE_MAIN_CHARGE, CGAIN, 0x1B, REG_BCICTL1);
++                      twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
++
++                      ret = !(tmp & CGAIN);
++                      if(!ret)
++                              mdelay(50);
++              }
++      }
++
++      /* Set automatic charge (CGAIN = 0/1 persists) */
++      twl4030charger_ac_en(ENABLE, 1);
++
+       return count;
+ }
+-
+ static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUGO, show_charge_current, set_charge_current);
+ static int twl4030_bk_bci_battery_get_property(struct power_supply *psy,
+@@ -986,7 +1080,10 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+       di->bk_bat.external_power_changed = NULL;
+       di->pdata = pdata;
+-      twl4030charger_ac_en(ENABLE);
++      /* Set up clocks */
++      twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, MADC_HFCLK_EN | DEFAULT_MADC_CLK_EN, REG_GPBR1);
++
++      twl4030charger_ac_en(ENABLE, CHARGE_MODE);
+       twl4030charger_usb_en(ENABLE);
+       twl4030battery_hw_level_en(ENABLE);
+       twl4030battery_hw_presence_en(ENABLE);
+@@ -1058,6 +1155,7 @@ static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
+                               twl4030_bk_bci_battery_work);
+       schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
++      set_charge_current (NULL, NULL, "1023", 4);
+       return 0;
+ bk_batt_failed:
+@@ -1071,7 +1169,7 @@ chg_irq_fail:
+ batt_irq_fail:
+ voltage_setup_fail:
+ temp_setup_fail:
+-      twl4030charger_ac_en(DISABLE);
++      twl4030charger_ac_en(DISABLE, CHARGE_MODE);
+       twl4030charger_usb_en(DISABLE);
+       twl4030battery_hw_level_en(DISABLE);
+       twl4030battery_hw_presence_en(DISABLE);
+@@ -1085,7 +1183,7 @@ static int __exit twl4030_bci_battery_remove(struct platform_device *pdev)
+       struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
+       int irq;
+-      twl4030charger_ac_en(DISABLE);
++      twl4030charger_ac_en(DISABLE, CHARGE_MODE);
+       twl4030charger_usb_en(DISABLE);
+       twl4030battery_hw_level_en(DISABLE);
+       twl4030battery_hw_presence_en(DISABLE);
+
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery2-bq27200-gpio-charged.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery2-bq27200-gpio-charged.patch
new file mode 100644 (file)
index 0000000..fd62907
--- /dev/null
@@ -0,0 +1,53 @@
+diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
+index bc6ef06..df7aa70 100644
+--- a/drivers/power/bq27x00_battery.c
++++ b/drivers/power/bq27x00_battery.c
+@@ -28,6 +28,7 @@
+ #define DRIVER_VERSION                        "1.0.0"
++#define BQ27x00_REG_MODE              0x00
+ #define BQ27x00_REG_TEMP              0x06
+ #define BQ27x00_REG_VOLT              0x08
+ #define BQ27x00_REG_RSOC              0x0B /* Relative State-of-Charge */
+@@ -65,6 +66,7 @@ static enum power_supply_property bq27x00_battery_props[] = {
+       POWER_SUPPLY_PROP_CURRENT_NOW,
+       POWER_SUPPLY_PROP_CAPACITY,
+       POWER_SUPPLY_PROP_TEMP,
++      POWER_SUPPLY_PROP_ONLINE,
+ };
+ /*
+@@ -83,6 +85,22 @@ static int bq27x00_read(u8 reg, int *rt_value, int b_single,
+ }
+ /*
++ * Return the GPIO status (0 or 1)
++ * Or < 0 if something fails.
++ */
++static int bq27x00_gpio(struct bq27x00_device_info *di)
++{
++      int ret;
++      int gpio = 0;
++
++      ret = bq27x00_read(BQ27x00_REG_MODE, &gpio, 0, di);
++      if (ret)
++              return ret;
++
++      return (gpio & 0x40) >> 6;
++}
++
++/*
+  * Return the battery temperature in Celcius degrees
+  * Or < 0 if something fails.
+  */
+@@ -184,6 +202,9 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
+       case POWER_SUPPLY_PROP_TEMP:
+               val->intval = bq27x00_battery_temperature(di);
+               break;
++      case POWER_SUPPLY_PROP_ONLINE:
++              val->intval = bq27x00_gpio(di);
++              break;
+       default:
+               return -EINVAL;
+       }
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery2-bq27200-no-error-message.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/battery2-bq27200-no-error-message.patch
new file mode 100644 (file)
index 0000000..eb7c8c9
--- /dev/null
@@ -0,0 +1,39 @@
+--- a/drivers/power/bq27x00_battery.c
++++ b/drivers/power/bq27x00_battery.c
+@@ -93,7 +93,6 @@ static int bq27x00_battery_temperature(struct bq27x00_device_info *di)
+       ret = bq27x00_read(BQ27x00_REG_TEMP, &temp, 0, di);
+       if (ret) {
+-              dev_err(di->dev, "error reading temperature\n");
+               return ret;
+       }
+@@ -111,7 +110,6 @@ static int bq27x00_battery_voltage(struct bq27x00_device_info *di)
+       ret = bq27x00_read(BQ27x00_REG_VOLT, &volt, 0, di);
+       if (ret) {
+-              dev_err(di->dev, "error reading voltage\n");
+               return ret;
+       }
+@@ -131,12 +129,10 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di)
+       ret = bq27x00_read(BQ27x00_REG_AI, &curr, 0, di);
+       if (ret) {
+-              dev_err(di->dev, "error reading current\n");
+               return 0;
+       }
+       ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);
+       if (ret < 0) {
+-              dev_err(di->dev, "error reading flags\n");
+               return 0;
+       }
+       if ((flags & (1 << 7)) != 0) {
+@@ -157,7 +153,6 @@ static int bq27x00_battery_rsoc(struct bq27x00_device_info *di)
+       ret = bq27x00_read(BQ27x00_REG_RSOC, &rsoc, 1, di);
+       if (ret) {
+-              dev_err(di->dev, "error reading relative State-of-Charge\n");
+               return ret;
+       }
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/beagle-asoc.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/beagle-asoc.patch
new file mode 100644 (file)
index 0000000..b2b9200
--- /dev/null
@@ -0,0 +1,35 @@
+diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
+index 4f7f040..ccd8973 100644
+--- a/sound/soc/omap/Kconfig
++++ b/sound/soc/omap/Kconfig
+@@ -55,3 +55,13 @@ config SND_OMAP_SOC_OMAP3_PANDORA
+       select SND_SOC_TWL4030
+       help
+         Say Y if you want to add support for SoC audio on the OMAP3 Pandora.
++
++config SND_OMAP_SOC_OMAP3_BEAGLE
++      tristate "SoC Audio support for OMAP3 Beagle"
++      depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_BEAGLE
++      select SND_OMAP_SOC_MCBSP
++      select SND_SOC_TWL4030
++      help
++        Say Y if you want to add support for SoC audio on the Beagleboard.
++
++
+diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
+index 76fedd9..0c9e4ac 100644
+--- a/sound/soc/omap/Makefile
++++ b/sound/soc/omap/Makefile
+@@ -12,6 +12,7 @@ snd-soc-overo-objs := overo.o
+ snd-soc-omap2evm-objs := omap2evm.o
+ snd-soc-sdp3430-objs := sdp3430.o
+ snd-soc-omap3pandora-objs := omap3pandora.o
++snd-soc-omap3beagle-objs := omap3beagle.o
+ obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
+ obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
+@@ -19,3 +20,4 @@ obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
+ obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o
+ obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
+ obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
++obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/board-omap3beagle.c b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/board-omap3beagle.c
new file mode 100644 (file)
index 0000000..c7867be
--- /dev/null
@@ -0,0 +1,744 @@
+/*
+ * linux/arch/arm/mach-omap2/board-omap3beagle.c
+ *
+ * Copyright (C) 2008 Texas Instruments
+ *
+ * Modified from mach-omap2/board-3430sdp.c
+ *
+ * Initial code: Syed Mohammed Khasim
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+
+#include <mach/mcspi.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+#include <linux/mma7455l.h>
+
+#include <mach/dmtimer.h>
+#include <linux/backlight.h>
+
+#include <linux/regulator/machine.h>
+#include <linux/i2c/twl4030.h>
+#include <linux/omapfb.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <mach/board.h>
+#include <mach/usb.h>
+#include <mach/common.h>
+#include <mach/gpmc.h>
+#include <mach/nand.h>
+#include <mach/mux.h>
+#include <mach/omap-pm.h>
+#include <mach/clock.h>
+#include <mach/display.h>
+
+#include "twl4030-generic-scripts.h"
+#include "mmc-twl4030.h"
+#include "pm.h"
+#include "omap3-opp.h"
+
+
+#define GPMC_CS0_BASE  0x60
+#define GPMC_CS_SIZE   0x30
+
+#define NAND_BLOCK_SIZE                SZ_128K
+
+#define OMAP3_AC_GPIO          136 //Int1 DRDY
+#define OMAP3_TS_GPIO          162
+#define TB_BL_PWM_TIMER                9
+#define TB_KILL_POWER_GPIO     168
+
+static struct mtd_partition omap3beagle_nand_partitions[] = {
+       /* All the partition sizes are listed in terms of NAND block size */
+       {
+               .name           = "X-Loader",
+               .offset         = 0,
+               .size           = 4 * NAND_BLOCK_SIZE,
+               .mask_flags     = MTD_WRITEABLE,        /* force read-only */
+       },
+       {
+               .name           = "U-Boot",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x80000 */
+               .size           = 15 * NAND_BLOCK_SIZE,
+               .mask_flags     = MTD_WRITEABLE,        /* force read-only */
+       },
+       {
+               .name           = "U-Boot Env",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x260000 */
+               .size           = 1 * NAND_BLOCK_SIZE,
+       },
+       {
+               .name           = "Kernel",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x280000 */
+               .size           = 32 * NAND_BLOCK_SIZE,
+       },
+       {
+               .name           = "File System",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x680000 */
+               .size           = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct omap_nand_platform_data omap3beagle_nand_data = {
+       .options        = NAND_BUSWIDTH_16,
+       .parts          = omap3beagle_nand_partitions,
+       .nr_parts       = ARRAY_SIZE(omap3beagle_nand_partitions),
+       .dma_channel    = -1,           /* disable DMA in OMAP NAND driver */
+       .nand_setup     = NULL,
+       .dev_ready      = NULL,
+};
+
+static struct resource omap3beagle_nand_resource = {
+       .flags          = IORESOURCE_MEM,
+};
+
+static struct platform_device omap3beagle_nand_device = {
+       .name           = "omap2-nand",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &omap3beagle_nand_data,
+       },
+       .num_resources  = 1,
+       .resource       = &omap3beagle_nand_resource,
+};
+
+#include "sdram-micron-mt46h32m32lf-6.h"
+
+static struct omap_uart_config omap3_beagle_uart_config __initdata = {
+       .enabled_uarts  = ((1 << 0) | (1 << 1) | (1 << 2)),
+};
+
+static struct twl4030_usb_data beagle_usb_data = {
+       .usb_mode       = T2_USB_MODE_ULPI,
+};
+
+static struct twl4030_hsmmc_info mmc[] = {
+       {
+               .mmc            = 1,
+               .wires          = 8,
+               .gpio_wp        = 29,
+       },
+       {}      /* Terminator */
+};
+
+static struct regulator_consumer_supply beagle_vmmc1_supply = {
+       .supply                 = "vmmc",
+};
+
+static struct regulator_consumer_supply beagle_vsim_supply = {
+       .supply                 = "vmmc_aux",
+};
+
+static struct gpio_led gpio_leds[];
+
+static int beagle_twl_gpio_setup(struct device *dev,
+               unsigned gpio, unsigned ngpio)
+{
+       /* gpio + 0 is "mmc0_cd" (input/IRQ) */
+       omap_cfg_reg(AH8_34XX_GPIO29);
+       mmc[0].gpio_cd = gpio + 0;
+       twl4030_mmc_init(mmc);
+
+       /* link regulators to MMC adapters */
+       beagle_vmmc1_supply.dev = mmc[0].dev;
+       beagle_vsim_supply.dev = mmc[0].dev;
+
+       /* REVISIT: need ehci-omap hooks for external VBUS
+        * power switch and overcurrent detect
+        */
+
+#if 0 /* TODO: This needs to be modified to not rely on u-boot */
+       gpio_request(gpio + 1, "EHCI_nOC");
+       gpio_direction_input(gpio + 1);
+
+       /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
+       gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
+       gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
+
+       /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
+       gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
+#endif
+       return 0;
+}
+
+static struct twl4030_gpio_platform_data beagle_gpio_data = {
+       .gpio_base      = OMAP_MAX_GPIO_LINES,
+       .irq_base       = TWL4030_GPIO_IRQ_BASE,
+       .irq_end        = TWL4030_GPIO_IRQ_END,
+       .use_leds       = true,
+       .pullups        = BIT(1),
+       .pulldowns      = BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13)
+                               | BIT(15) | BIT(16) | BIT(17),
+       .setup          = beagle_twl_gpio_setup,
+};
+
+static struct platform_device omap3_beagle_lcd_device = {
+       .name           = "omap3beagle_lcd",
+       .id             = -1,
+};
+
+static struct regulator_consumer_supply beagle_vdac_supply = {
+       .supply         = "vdac",
+       .dev            = &omap3_beagle_lcd_device.dev,
+};
+
+static struct regulator_consumer_supply beagle_vdvi_supply = {
+       .supply         = "vdvi",
+       .dev            = &omap3_beagle_lcd_device.dev,
+};
+
+/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
+static struct regulator_init_data beagle_vmmc1 = {
+       .constraints = {
+               .min_uV                 = 1850000,
+               .max_uV                 = 3150000,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE
+                                       | REGULATOR_CHANGE_MODE
+                                       | REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &beagle_vmmc1_supply,
+};
+
+/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
+static struct regulator_init_data beagle_vsim = {
+       .constraints = {
+               .min_uV                 = 1800000,
+               .max_uV                 = 3000000,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE
+                                       | REGULATOR_CHANGE_MODE
+                                       | REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &beagle_vsim_supply,
+};
+
+/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
+static struct regulator_init_data beagle_vdac = {
+       .constraints = {
+               .min_uV                 = 1800000,
+               .max_uV                 = 1800000,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_MODE
+                                       | REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &beagle_vdac_supply,
+};
+
+/* VPLL2 for digital video outputs */
+static struct regulator_init_data beagle_vpll2 = {
+       .constraints = {
+               .name                   = "VDVI",
+               .min_uV                 = 1800000,
+               .max_uV                 = 1800000,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_MODE
+                                       | REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &beagle_vdvi_supply,
+};
+
+static const struct twl4030_resconfig beagle_resconfig[] = {
+       /* disable regulators that u-boot left enabled; the
+        * devices' drivers should be managing these.
+        */
+       { .resource = RES_VAUX3, },     /* not even connected! */
+       { .resource = RES_VMMC1, },
+       { .resource = RES_VSIM, },
+       { .resource = RES_VPLL2, },
+       { .resource = RES_VDAC, },
+       { .resource = RES_VUSB_1V5, },
+       { .resource = RES_VUSB_1V8, },
+       { .resource = RES_VUSB_3V1, },
+       { 0, },
+};
+
+static struct twl4030_power_data beagle_power_data = {
+       .resource_config        = beagle_resconfig,
+       /* REVISIT can't use GENERIC3430_T2SCRIPTS_DATA;
+        * among other things, it makes reboot fail.
+        */
+};
+
+static struct twl4030_bci_platform_data touchbook_bci_data = {
+       .tblsize                = 0,
+       .no_backup_battery      = 1,
+};
+
+static struct twl4030_platform_data beagle_twldata = {
+       .irq_base       = TWL4030_IRQ_BASE,
+       .irq_end        = TWL4030_IRQ_END,
+
+       /* platform_data for children goes here */
+       .usb            = &beagle_usb_data,
+       .gpio           = &beagle_gpio_data,
+       .power          = &beagle_power_data,
+       .vmmc1          = &beagle_vmmc1,
+       .vsim           = &beagle_vsim,
+       .vdac           = &beagle_vdac,
+       .vpll2          = &beagle_vpll2,
+
+       /* TouchBook BCI */
+       .bci            = &touchbook_bci_data,
+};
+
+static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("twl4030", 0x48),
+               .flags = I2C_CLIENT_WAKE,
+               .irq = INT_34XX_SYS_NIRQ,
+               .platform_data = &beagle_twldata,
+       },
+};
+
+static struct i2c_board_info __initdata touchBook_i2c_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("bq27200", 0x55),
+       },
+};
+
+static int __init omap3_beagle_i2c_init(void)
+{
+       /* Standard BeagleBoard bus */
+       omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
+                       ARRAY_SIZE(beagle_i2c_boardinfo));
+
+       /* TouchBook keyboard bus */
+       omap_register_i2c_bus(3, 100, touchBook_i2c_boardinfo,
+                       ARRAY_SIZE(touchBook_i2c_boardinfo));
+
+       return 0;
+}
+
+static void __init omap3_ads7846_init(void)
+{
+       if (gpio_request(OMAP3_TS_GPIO, "ads7846_pen_down")) {
+               printk(KERN_ERR "Failed to request GPIO %d for "
+                               "ads7846 pen down IRQ\n", OMAP3_TS_GPIO);
+               return;
+       }
+
+       gpio_direction_input(OMAP3_TS_GPIO);
+       omap_set_gpio_debounce(OMAP3_TS_GPIO, 1);
+       omap_set_gpio_debounce_time(OMAP3_TS_GPIO, 0xa);
+}
+
+static struct ads7846_platform_data ads7846_config = {
+       .x_min                  = 100,
+       .y_min                  = 265,
+       .x_max                  = 3950,
+       .y_max                  = 3750,
+       .x_plate_ohms           = 40,
+       .pressure_max           = 255,
+       .debounce_max           = 10,
+       .debounce_tol           = 5,
+       .debounce_rep           = 1,
+       .gpio_pendown           = OMAP3_TS_GPIO,
+       .keep_vref_on           = 1,
+};
+
+static struct omap2_mcspi_device_config ads7846_mcspi_config = {
+       .turbo_mode     = 0,
+       .single_channel = 1,    /* 0: slave, 1: master */
+};
+
+static struct spi_board_info omap3_ads7846_spi_board_info[] __initdata = {
+       {
+               .modalias               = "ads7846",
+               .bus_num                = 4,
+               .chip_select            = 0,
+               .max_speed_hz           = 1500000,
+               .controller_data        = &ads7846_mcspi_config, //(void *) 161,
+               .irq                    = OMAP_GPIO_IRQ(OMAP3_TS_GPIO),
+               .platform_data          = &ads7846_config,
+       }
+};
+
+static void __init omap3_beagle_init_irq(void)
+{
+       omap2_init_common_hw(mt46h32m32lf6_sdrc_params, omap3_mpu_rate_table,
+                   omap3_dsp_rate_table, omap3_l3_rate_table);
+       omap_init_irq();
+       omap_gpio_init();
+}
+
+static struct gpio_led gpio_leds[] = {
+       {
+               .name                   = "beagleboard::usr0",
+               .default_trigger        = "heartbeat",
+               .gpio                   = 150,
+       },
+       {
+               .name                   = "beagleboard::usr1",
+               .default_trigger        = "mmc0",
+               .gpio                   = 149,
+       },
+       {
+               .name                   = "beagleboard::pmu_stat",
+               .gpio                   = -EINVAL,      /* gets replaced */
+               .active_low             = true,
+       },
+};
+
+static struct gpio_led_platform_data gpio_led_info = {
+       .leds           = gpio_leds,
+       .num_leds       = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio = {
+       .name   = "leds-gpio",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &gpio_led_info,
+       },
+};
+
+static struct gpio_keys_button gpio_buttons[] = {
+       {
+               .code                   = BTN_EXTRA,
+               .gpio                   = 7,
+               .desc                   = "user",
+               .wakeup                 = 1,
+       },
+       {
+               .code                   = KEY_POWER,
+               .gpio                   = 183,
+               .desc                   = "power",
+               .wakeup                 = 1,
+       },
+};
+
+static struct gpio_keys_platform_data gpio_key_info = {
+       .buttons        = gpio_buttons,
+       .nbuttons       = ARRAY_SIZE(gpio_buttons),
+};
+
+static struct platform_device keys_gpio = {
+       .name   = "gpio-keys",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &gpio_key_info,
+       },
+};
+
+/* DSS */
+
+static int beagle_enable_dvi(struct omap_display *display)
+{
+       if (display->hw_config.panel_reset_gpio != -1)
+               gpio_set_value(display->hw_config.panel_reset_gpio, 1);
+
+       return 0;
+}
+
+static void beagle_disable_dvi(struct omap_display *display)
+{
+       if (display->hw_config.panel_reset_gpio != -1)
+               gpio_set_value(display->hw_config.panel_reset_gpio, 0);
+}
+
+static struct omap_dss_display_config beagle_display_data_dvi = {
+       .type = OMAP_DISPLAY_TYPE_DPI,
+       .name = "dvi",
+       .panel_name = "panel-generic",
+       .u.dpi.data_lines = 24,
+       .panel_reset_gpio = 176,
+       .panel_enable = beagle_enable_dvi,
+       .panel_disable = beagle_disable_dvi,
+};
+
+
+static int beagle_panel_enable_tv(struct omap_display *display)
+{
+#define ENABLE_VDAC_DEDICATED           0x03
+#define ENABLE_VDAC_DEV_GRP             0x20
+
+       twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+                       ENABLE_VDAC_DEDICATED,
+                       TWL4030_VDAC_DEDICATED);
+       twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+                       ENABLE_VDAC_DEV_GRP, TWL4030_VDAC_DEV_GRP);
+
+       return 0;
+}
+
+static void beagle_panel_disable_tv(struct omap_display *display)
+{
+       twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+                       TWL4030_VDAC_DEDICATED);
+       twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x00,
+                       TWL4030_VDAC_DEV_GRP);
+}
+
+static struct omap_dss_display_config beagle_display_data_tv = {
+       .type = OMAP_DISPLAY_TYPE_VENC,
+       .name = "tv",
+       .u.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
+       .panel_enable = beagle_panel_enable_tv,
+       .panel_disable = beagle_panel_disable_tv,
+};
+
+static struct omap_dss_board_info beagle_dss_data = {
+       .num_displays = 2,
+       .displays = {
+               &beagle_display_data_dvi,
+               &beagle_display_data_tv,
+       }
+};
+
+static struct platform_device beagle_dss_device = {
+       .name          = "omapdss",
+       .id            = -1,
+       .dev            = {
+               .platform_data = &beagle_dss_data,
+       },
+};
+
+static void __init beagle_display_init(void)
+{
+       int r;
+
+       r = gpio_request(beagle_display_data_dvi.panel_reset_gpio, "DVI reset");
+       if (r < 0) {
+               printk(KERN_ERR "Unable to get DVI reset GPIO\n");
+               return;
+       }
+
+       gpio_direction_output(beagle_display_data_dvi.panel_reset_gpio, 0);
+}
+
+static struct omap_board_config_kernel omap3_beagle_config[] __initdata = {
+       { OMAP_TAG_UART,        &omap3_beagle_uart_config },
+};
+
+static struct platform_device *omap3_beagle_devices[] __initdata = {
+       &beagle_dss_device,
+       &leds_gpio,
+       &keys_gpio,
+};
+
+static void __init omap3beagle_flash_init(void)
+{
+       u8 cs = 0;
+       u8 nandcs = GPMC_CS_NUM + 1;
+
+       u32 gpmc_base_add = OMAP34XX_GPMC_VIRT;
+
+       /* find out the chip-select on which NAND exists */
+       while (cs < GPMC_CS_NUM) {
+               u32 ret = 0;
+               ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+               if ((ret & 0xC00) == 0x800) {
+                       printk(KERN_INFO "Found NAND on CS%d\n", cs);
+                       if (nandcs > GPMC_CS_NUM)
+                               nandcs = cs;
+               }
+               cs++;
+       }
+
+       if (nandcs > GPMC_CS_NUM) {
+               printk(KERN_INFO "NAND: Unable to find configuration "
+                                "in GPMC\n ");
+               return;
+       }
+
+       if (nandcs < GPMC_CS_NUM) {
+               omap3beagle_nand_data.cs = nandcs;
+               omap3beagle_nand_data.gpmc_cs_baseaddr = (void *)
+                       (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE);
+               omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add);
+
+               printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
+               if (platform_device_register(&omap3beagle_nand_device) < 0)
+                       printk(KERN_ERR "Unable to register NAND device\n");
+       }
+}
+
+static void __init omap3_mma7455l_init(void)
+{
+       int ret;
+
+       ret = gpio_request(OMAP3_AC_GPIO, "mma7455l");
+       if (ret < 0) {
+               printk(KERN_ERR "Failed to request GPIO %d for mma7455l IRQ\n", OMAP3_AC_GPIO);
+               return;
+       }
+
+       gpio_direction_input(OMAP3_AC_GPIO);
+}
+
+static struct mma7455l_platform_data mma7455l_config = {
+       .calibration_x = -4, //26 for Beagleboard
+       .calibration_y = 28, //44 for Beagleboard
+       .calibration_z = -28, //26 for Beagleboard
+};
+
+static struct omap2_mcspi_device_config mma7455l_mcspi_config = {
+       .turbo_mode     = 0,
+       .single_channel = 1,    /* 0: slave, 1: master */
+};
+
+static struct spi_board_info omap3_mma7455l_spi_board_info[] __initdata = {
+       {
+               .modalias               = "mma7455l",
+               .bus_num                = 3,
+               .chip_select            = 0,
+               .max_speed_hz           = 200000,
+               .irq                    = OMAP_GPIO_IRQ(OMAP3_AC_GPIO),
+               .controller_data        = &mma7455l_mcspi_config, //(void *) 135,
+               .platform_data          = &mma7455l_config,
+       }
+};
+
+static int touchbook_backlight_brightness = 50;
+static struct omap_dm_timer *touchbook_backlight_pwm;
+
+static int touchbook_backlight_read(struct backlight_device *bd)
+{
+       return touchbook_backlight_brightness;
+}
+
+static int touchbook_backlight_update(struct backlight_device *bd)
+{
+       int value = bd->props.brightness;
+       touchbook_backlight_brightness = value;
+
+       /* Frequency calculation:
+          - For 200Hz PWM, you want to load -164 (=> -32768Hz / 200Hz).
+          - Minimum duty cycle for the backlight is 15%.
+          - You have (164*0.85) => ~140 levels of brightness.
+       */
+
+       /* Convert from 0-100 range to 0-140 range */
+       value = (value * 14) / 10 / 2;
+
+       /* For maximum brightness, just stop the timer... */
+       if(value != bd->props.max_brightness)
+       {
+               omap_dm_timer_set_load(touchbook_backlight_pwm, 1, -164);
+               omap_dm_timer_set_match(touchbook_backlight_pwm, 1, -24 - value);
+               omap_dm_timer_write_counter(touchbook_backlight_pwm, -1);
+               //omap_dm_timer_stop(touchbook_backlight_pwm);
+               omap_dm_timer_start(touchbook_backlight_pwm);
+       }
+       else
+               omap_dm_timer_stop(touchbook_backlight_pwm);
+
+
+       return 0;
+}
+
+static struct backlight_ops touchbook_backlight_properties = {
+       .get_brightness = touchbook_backlight_read,
+       .update_status = touchbook_backlight_update,
+};
+
+static void __init omap3_touchbook_backlight_init(void)
+{
+       static struct backlight_device *bd;
+       bd = backlight_device_register("touchbook", NULL, NULL, &touchbook_backlight_properties);
+
+       if(bd)
+       {
+               touchbook_backlight_pwm = omap_dm_timer_request_specific(TB_BL_PWM_TIMER);
+               omap_dm_timer_enable(touchbook_backlight_pwm);
+               omap_dm_timer_set_source(touchbook_backlight_pwm, OMAP_TIMER_SRC_32_KHZ);
+               omap_dm_timer_set_pwm(touchbook_backlight_pwm, 1, 1, OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
+
+               bd->props.max_brightness = 100;
+               bd->props.brightness = touchbook_backlight_brightness;
+       }
+
+       touchbook_backlight_update(bd);
+}
+
+static void omap3_touchbook_poweroff(void)
+{
+       int r;
+
+       r = gpio_request(TB_KILL_POWER_GPIO, "DVI reset");
+       if (r < 0) {
+               printk(KERN_ERR "Unable to get kill power GPIO\n");
+               return;
+       }
+
+       gpio_direction_output(TB_KILL_POWER_GPIO, 0);
+}
+
+static void __init omap3_beagle_init(void)
+{
+       pm_power_off = omap3_touchbook_poweroff;
+
+       omap3_beagle_i2c_init();
+       platform_add_devices(omap3_beagle_devices,
+                       ARRAY_SIZE(omap3_beagle_devices));
+       omap_board_config = omap3_beagle_config;
+       omap_board_config_size = ARRAY_SIZE(omap3_beagle_config);
+       omap_serial_init();
+
+       omap_cfg_reg(J25_34XX_GPIO170);
+
+       omap3beagle_flash_init();
+       beagle_display_init();
+       omap3_touchbook_backlight_init();
+
+       /* Touch Book */
+       spi_register_board_info(omap3_ads7846_spi_board_info, ARRAY_SIZE(omap3_ads7846_spi_board_info));
+       spi_register_board_info(omap3_mma7455l_spi_board_info, ARRAY_SIZE(omap3_mma7455l_spi_board_info));
+
+       omap3_ads7846_init();
+       omap3_mma7455l_init();
+
+       usb_musb_init();
+       usb_ehci_init();
+}
+
+static void __init omap3_beagle_map_io(void)
+{
+       omap2_set_globals_343x();
+       omap2_map_common_io();
+}
+
+MACHINE_START(OMAP3_BEAGLE, "OMAP3 Touch Book")
+       /* Maintainer: Gregoire Gentil - http://www.alwaysinnovating.com */
+       .phys_io        = 0x48000000,
+       .io_pg_offst    = ((0xd8000000) >> 18) & 0xfffc,
+       .boot_params    = 0x80000100,
+       .map_io         = omap3_beagle_map_io,
+       .init_irq       = omap3_beagle_init_irq,
+       .init_machine   = omap3_beagle_init,
+       .timer          = &omap_timer,
+MACHINE_END
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/boot-no-power-message.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/boot-no-power-message.patch
new file mode 100644 (file)
index 0000000..4be59a4
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/arch/arm/mach-omap2/pm34xx.c     2009-07-18 10:13:43.000000000 -0700
++++ b/arch/arm/mach-omap2/pm34xx.c     2009-07-18 10:13:54.000000000 -0700
+@@ -625,7 +625,7 @@
+       struct power_state *pwrst, *tmp;
+       int ret;
+-      printk(KERN_ERR "Power Management for TI OMAP3.\n");
++//    printk(KERN_ERR "Power Management for TI OMAP3.\n");
+       /* XXX prcm_setup_regs needs to be before enabling hw
+        * supervised mode for powerdomains */
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/defconfig b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/defconfig
new file mode 100644 (file)
index 0000000..2ff46a4
--- /dev/null
@@ -0,0 +1,2720 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-omap1
+# Fri May 29 14:47:52 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_OPROFILE_ARMV7=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+CONFIG_OMAP_SMARTREFLEX=y
+# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_BOOT_TAG=y
+CONFIG_OMAP_BOOT_REASON=y
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_IOMMU is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_TICK_GPTIMER=12
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_OMAP3EVM is not set
+CONFIG_MACH_OMAP3_BEAGLE=y
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+# CONFIG_VMSPLIT_3G is not set
+CONFIG_VMSPLIT_2G=y
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0x80000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_LEDS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_FREQ is not set
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_ARM_ERRATUM_451034 is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE 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=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+# CONFIG_IPV6_PIMSM_V2 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+CONFIG_IP_VS_DEBUG=y
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_IDLETIMER=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
+CONFIG_IP_DCCP_TFRC_LIB=y
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# 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=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+# CONFIG_ACT200L_DONGLE is not set
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_MCS_FIR=m
+# CONFIG_OMAP_IR is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=y
+CONFIG_BT_HCIBTSDIO=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+CONFIG_BT_HCIBFUSB=y
+# CONFIG_BT_HCIBRF6150 is not set
+# CONFIG_BT_HCIH4P is not set
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+# CONFIG_RXKAD is not set
+# CONFIG_PHONET is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+# CONFIG_RFKILL is not set
+CONFIG_NET_9P=m
+# CONFIG_NET_9P_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+CONFIG_MTD_NAND_PLATFORM=y
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+CONFIG_EEPROM_93CX6=y
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+# CONFIG_NET_ETHERNET is not set
+CONFIG_MII=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=y
+CONFIG_LIBERTAS_USB=y
+# CONFIG_LIBERTAS_SDIO is not set
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+CONFIG_USB_ZD1201=y
+CONFIG_USB_NET_RNDIS_WLAN=y
+CONFIG_RTL8187=y
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_P54_COMMON=y
+CONFIG_P54_USB=y
+# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_B43=y
+CONFIG_B43_LEDS=y
+# CONFIG_B43_DEBUG is not set
+# CONFIG_B43LEGACY is not set
+CONFIG_ZD1211RW=y
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_RT2X00=y
+CONFIG_RT2500USB=y
+CONFIG_RT73USB=y
+CONFIG_RT2X00_LIB_USB=y
+CONFIG_RT2X00_LIB=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+# CONFIG_WIMAX_I2400M_USB is not set
+# CONFIG_WIMAX_I2400M_SDIO is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=y
+CONFIG_USB_KAWETH=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=y
+CONFIG_USB_NET_NET1080=y
+CONFIG_USB_NET_PLUSB=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_NET_RNDIS_HOST=y
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOATM is not set
+CONFIG_PPPOL2TP=m
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_TWL4030 is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
+# CONFIG_TOUCHSCREEN_TSC210X is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_MMA7455L=y
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+CONFIG_TWL4030_MADC=y
+CONFIG_TWL4030_POWEROFF=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_TSL2563 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_OMAP24XX=y
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_TSC210X is not set
+# CONFIG_SPI_TSC2301 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+CONFIG_TWL4030_BCI_BATTERY=y
+CONFIG_BATTERY_BQ27x00=y
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_TSC210X is not set
+CONFIG_SENSORS_OMAP34XX=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_POWER is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_IR_I2C=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_VIVI=m
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+# CONFIG_VIDEO_OMAP3 is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+CONFIG_DVB_DYNAMIC_MINORS=y
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_SIANO_SMS1XXX=m
+CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_DRX397XD=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3304=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+# CONFIG_DVB_ISL6405 is not set
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_LGS8GL5=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+CONFIG_DVB_AF9013=m
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_VRAM_SIZE=14
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C=m
+# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
+# CONFIG_PANEL_N800 is not set
+# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_GENERIC=y
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_TOPSEED=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_OMAP_EHCI_PHY_MODE=y
+# CONFIG_OMAP_EHCI_TLL_MODE is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_OXU210HP_HCD=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_U132_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_BERRY_CHARGE=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGET=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETMOTORCONTROL=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+CONFIG_USB_VST=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ZERO_HNPTEST=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=y
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SPI=m
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_OMAP_DEBUG is not set
+CONFIG_LEDS_OMAP=y
+# CONFIG_LEDS_OMAP_PWM is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_MEILHAUS is not set
+# CONFIG_USB_IP_COMMON is not set
+CONFIG_W35UND=m
+CONFIG_PRISM2_USB=m
+# CONFIG_ECHO is not set
+CONFIG_USB_ATMEL=m
+# CONFIG_AGNX is not set
+CONFIG_OTUS=m
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_INPUT_MIMIO is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=m
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
+# CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION is not set
+# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set
+CONFIG_ANDROID_TIMED_GPIO=m
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+CONFIG_MPU_BRIDGE=m
+CONFIG_BRIDGE_MEMPOOL_SIZE=0x600000
+# CONFIG_BRIDGE_DEBUG is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+# CONFIG_REISERFS_FS_POSIX_ACL is not set
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=m
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+CONFIG_BTRFS_FS=m
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+# CONFIG_ECRYPT_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_JFFS2_CMODE_FAVOURLZO=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_AUFS_FS=y
+CONFIG_AUFS_BRANCH_MAX_127=y
+# CONFIG_AUFS_BRANCH_MAX_511 is not set
+# CONFIG_AUFS_BRANCH_MAX_1023 is not set
+# CONFIG_AUFS_BRANCH_MAX_32767 is not set
+# CONFIG_AUFS_HINOTIFY is not set
+# CONFIG_AUFS_SHWH is not set
+# CONFIG_AUFS_BR_RAMFS is not set
+CONFIG_AUFS_DEBUG=y
+CONFIG_AUFS_MAGIC_SYSRQ=y
+CONFIG_AUFS_BDEV_LOOP=y
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_CIFS_DFS_UPCALL is not set
+CONFIG_NCP_FS=m
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+# CONFIG_AFS_DEBUG is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_LDM_DEBUG=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/defconfig.orig b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/defconfig.orig
new file mode 100644 (file)
index 0000000..1aa7cf5
--- /dev/null
@@ -0,0 +1,2701 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-omap1
+# Fri May 29 14:47:52 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_OPROFILE_ARMV7=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+CONFIG_ARCH_OMAP=y
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI OMAP Implementations
+#
+CONFIG_ARCH_OMAP_OTG=y
+# CONFIG_ARCH_OMAP1 is not set
+# CONFIG_ARCH_OMAP2 is not set
+CONFIG_ARCH_OMAP3=y
+
+#
+# OMAP Feature Selections
+#
+# CONFIG_OMAP_DEBUG_POWERDOMAIN is not set
+# CONFIG_OMAP_DEBUG_CLOCKDOMAIN is not set
+CONFIG_OMAP_SMARTREFLEX=y
+# CONFIG_OMAP_SMARTREFLEX_TESTING is not set
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_BOOT_TAG=y
+CONFIG_OMAP_BOOT_REASON=y
+# CONFIG_OMAP_COMPONENT_VERSION is not set
+# CONFIG_OMAP_GPIO_SWITCH is not set
+# CONFIG_OMAP_MUX is not set
+CONFIG_OMAP_MCBSP=y
+# CONFIG_OMAP_MBOX_FWK is not set
+# CONFIG_OMAP_IOMMU is not set
+# CONFIG_OMAP_MPU_TIMER is not set
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
+CONFIG_OMAP_TICK_GPTIMER=12
+CONFIG_OMAP_DM_TIMER=y
+# CONFIG_OMAP_LL_DEBUG_UART1 is not set
+# CONFIG_OMAP_LL_DEBUG_UART2 is not set
+CONFIG_OMAP_LL_DEBUG_UART3=y
+CONFIG_ARCH_OMAP34XX=y
+CONFIG_ARCH_OMAP3430=y
+
+#
+# OMAP Board Type
+#
+# CONFIG_MACH_NOKIA_RX51 is not set
+# CONFIG_MACH_OMAP_LDP is not set
+# CONFIG_MACH_OMAP_3430SDP is not set
+# CONFIG_MACH_OMAP3EVM is not set
+CONFIG_MACH_OMAP3_BEAGLE=y
+# CONFIG_MACH_OVERO is not set
+# CONFIG_MACH_OMAP3_PANDORA is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_32v6K=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_CPU_ABRT_EV7=y
+CONFIG_CPU_PABRT_IFAR=y
+CONFIG_CPU_CACHE_V7=y
+CONFIG_CPU_CACHE_VIPT=y
+CONFIG_CPU_COPY_V6=y
+CONFIG_CPU_TLB_V7=y
+CONFIG_CPU_HAS_ASID=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_BPREDICT_DISABLE is not set
+CONFIG_HAS_TLS_REG=y
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=128
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_LEDS=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" debug "
+# CONFIG_XIP_KERNEL is not set
+CONFIG_KEXEC=y
+CONFIG_ATAGS_PROC=y
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_VFP=y
+CONFIG_VFPv3=y
+CONFIG_NEON=y
+# CONFIG_ARM_ERRATUM_451034 is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=y
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+# CONFIG_PM_TEST_SUSPEND is not set
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=m
+CONFIG_NET_KEY=y
+# CONFIG_NET_KEY_MIGRATE 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=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_LRO=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=m
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_VEGAS=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+# CONFIG_DEFAULT_BIC is not set
+CONFIG_DEFAULT_CUBIC=y
+# CONFIG_DEFAULT_HTCP is not set
+# CONFIG_DEFAULT_VEGAS is not set
+# CONFIG_DEFAULT_WESTWOOD is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+# CONFIG_IPV6_PIMSM_V2 is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_ACCT=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_GRE=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+# CONFIG_NETFILTER_XT_TARGET_TRACE is not set
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+CONFIG_IP_VS_DEBUG=y
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_AH_ESP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_NF_NAT=m
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_IDLETIMER=m
+CONFIG_NF_NAT_SNMP_BASIC=m
+CONFIG_NF_NAT_PROTO_DCCP=m
+CONFIG_NF_NAT_PROTO_GRE=m
+CONFIG_NF_NAT_PROTO_UDPLITE=m
+CONFIG_NF_NAT_PROTO_SCTP=m
+CONFIG_NF_NAT_FTP=m
+CONFIG_NF_NAT_IRC=m
+CONFIG_NF_NAT_TFTP=m
+CONFIG_NF_NAT_AMANDA=m
+CONFIG_NF_NAT_PPTP=m
+CONFIG_NF_NAT_H323=m
+CONFIG_NF_NAT_SIP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+CONFIG_IP_DCCP=m
+CONFIG_INET_DCCP_DIAG=m
+
+#
+# DCCP CCIDs Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP_CCID2_DEBUG is not set
+CONFIG_IP_DCCP_CCID3=y
+# CONFIG_IP_DCCP_CCID3_DEBUG is not set
+CONFIG_IP_DCCP_CCID3_RTO=100
+CONFIG_IP_DCCP_TFRC_LIB=y
+
+#
+# DCCP Kernel Hacking
+#
+# CONFIG_IP_DCCP_DEBUG is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+CONFIG_TIPC=m
+# CONFIG_TIPC_ADVANCED is not set
+# CONFIG_TIPC_DEBUG is not set
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_STP=m
+CONFIG_GARP=m
+CONFIG_BRIDGE=m
+# CONFIG_NET_DSA is not set
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# 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=m
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_IND=y
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+# CONFIG_CAN_DEBUG_DEVICES is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+CONFIG_IRDA_ULTRA=y
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+CONFIG_TOIM3232_DONGLE=m
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+# CONFIG_ACT200L_DONGLE is not set
+CONFIG_KINGSUN_DONGLE=m
+CONFIG_KSDAZZLE_DONGLE=m
+CONFIG_KS959_DONGLE=m
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_MCS_FIR=m
+# CONFIG_OMAP_IR is not set
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=y
+CONFIG_BT_HCIBTSDIO=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+CONFIG_BT_HCIBFUSB=y
+# CONFIG_BT_HCIBRF6150 is not set
+# CONFIG_BT_HCIH4P is not set
+# CONFIG_BT_HCIVHCI is not set
+CONFIG_AF_RXRPC=m
+# CONFIG_AF_RXRPC_DEBUG is not set
+# CONFIG_RXKAD is not set
+# CONFIG_PHONET is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_NL80211=y
+CONFIG_WIRELESS_OLD_REGULATORY=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=y
+CONFIG_LIB80211_CRYPT_WEP=y
+CONFIG_LIB80211_CRYPT_CCMP=y
+CONFIG_LIB80211_CRYPT_TKIP=y
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=y
+
+#
+# Rate control algorithm selection
+#
+CONFIG_MAC80211_RC_PID=y
+# CONFIG_MAC80211_RC_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+# CONFIG_MAC80211_RC_DEFAULT_MINSTREL is not set
+CONFIG_MAC80211_RC_DEFAULT="pid"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+CONFIG_WIMAX=m
+CONFIG_WIMAX_DEBUG_LEVEL=8
+# CONFIG_RFKILL is not set
+CONFIG_NET_9P=m
+# CONFIG_NET_9P_DEBUG is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+CONFIG_MTD_NAND_PLATFORM=y
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_OMAP_STI is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+CONFIG_EEPROM_93CX6=y
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_RAID_ATTRS=m
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_ISCSI_ATTRS=m
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+CONFIG_ISCSI_TCP=m
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+CONFIG_MD_RAID5_RESHAPE=y
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_DELAY=m
+# CONFIG_DM_UEVENT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_MACVLAN=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+CONFIG_VETH=m
+# CONFIG_NET_ETHERNET is not set
+CONFIG_MII=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+CONFIG_WLAN_80211=y
+CONFIG_LIBERTAS=y
+CONFIG_LIBERTAS_USB=y
+# CONFIG_LIBERTAS_SDIO is not set
+# CONFIG_LIBERTAS_DEBUG is not set
+# CONFIG_LIBERTAS_THINFIRM is not set
+CONFIG_USB_ZD1201=y
+CONFIG_USB_NET_RNDIS_WLAN=y
+CONFIG_RTL8187=y
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_P54_COMMON=y
+CONFIG_P54_USB=y
+# CONFIG_IWLWIFI_LEDS is not set
+CONFIG_HOSTAP=y
+CONFIG_HOSTAP_FIRMWARE=y
+CONFIG_HOSTAP_FIRMWARE_NVRAM=y
+CONFIG_B43=y
+CONFIG_B43_LEDS=y
+# CONFIG_B43_DEBUG is not set
+# CONFIG_B43LEGACY is not set
+CONFIG_ZD1211RW=y
+# CONFIG_ZD1211RW_DEBUG is not set
+CONFIG_RT2X00=y
+CONFIG_RT2500USB=y
+CONFIG_RT73USB=y
+CONFIG_RT2X00_LIB_USB=y
+CONFIG_RT2X00_LIB=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+
+#
+# WiMAX Wireless Broadband devices
+#
+# CONFIG_WIMAX_I2400M_USB is not set
+# CONFIG_WIMAX_I2400M_SDIO is not set
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=y
+CONFIG_USB_KAWETH=y
+CONFIG_USB_PEGASUS=y
+CONFIG_USB_RTL8150=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_DM9601=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=y
+CONFIG_USB_NET_NET1080=y
+CONFIG_USB_NET_PLUSB=y
+CONFIG_USB_NET_MCS7830=y
+CONFIG_USB_NET_RNDIS_HOST=y
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_WAN is not set
+CONFIG_ATM_DRIVERS=y
+# CONFIG_ATM_DUMMY is not set
+# CONFIG_ATM_TCP is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+# CONFIG_PPPOATM is not set
+CONFIG_PPPOL2TP=m
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_TWL4030 is not set
+# CONFIG_KEYBOARD_LM8323 is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_ATI_REMOTE is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+CONFIG_INPUT_UINPUT=y
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_OMAP=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+CONFIG_TWL4030_MADC=m
+CONFIG_TWL4030_POWEROFF=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_TSL2563 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OMAP24XX is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_TSC210X is not set
+# CONFIG_SPI_TSC2301 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+CONFIG_GPIO_TWL4030=y
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=m
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_TWL4030_BCI_BATTERY is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_TSC210X is not set
+CONFIG_SENSORS_OMAP34XX=y
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_OMAP_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB=y
+# CONFIG_SSB_SILENT is not set
+# CONFIG_SSB_DEBUG is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+CONFIG_TWL4030_CORE=y
+# CONFIG_TWL4030_POWER is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_DVB_CORE=m
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+CONFIG_MEDIA_ATTACH=y
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMIZE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_MT2060=m
+CONFIG_MEDIA_TUNER_MT2266=m
+CONFIG_MEDIA_TUNER_QT1010=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MXL5005S=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_V4L1=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEOBUF_DVB=m
+CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_VIDEO_IR_I2C=m
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+CONFIG_VIDEO_SAA711X=m
+CONFIG_VIDEO_TVP5150=m
+CONFIG_VIDEO_CX25840=m
+CONFIG_VIDEO_CX2341X=m
+CONFIG_VIDEO_VIVI=m
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_AU0828 is not set
+# CONFIG_VIDEO_OMAP3 is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+CONFIG_VIDEO_PVRUSB2_DVB=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_VIDEO_USBVISION=m
+CONFIG_VIDEO_USBVIDEO=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_QUICKCAM_MESSENGER=m
+CONFIG_USB_ET61X251=m
+CONFIG_VIDEO_OVCAMCHIP=m
+CONFIG_USB_W9968CF=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_ZC0301=m
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_SI470X is not set
+# CONFIG_USB_MR800 is not set
+# CONFIG_RADIO_TEA5764 is not set
+CONFIG_DVB_DYNAMIC_MINORS=y
+CONFIG_DVB_CAPTURE_DRIVERS=y
+# CONFIG_TTPCI_EEPROM is not set
+
+#
+# Supported USB Adapters
+#
+CONFIG_DVB_USB=m
+# CONFIG_DVB_USB_DEBUG is not set
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_SIANO_SMS1XXX=m
+CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS=y
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+CONFIG_DVB_B2C2_FLEXCOP=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+# CONFIG_DVB_FE_CUSTOMISE is not set
+
+#
+# Multistandard (satellite) frontends
+#
+CONFIG_DVB_STB0899=m
+CONFIG_DVB_STB6100=m
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24123=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_S5H1420=m
+CONFIG_DVB_STV0288=m
+CONFIG_DVB_STB6000=m
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA10086=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_TUNER_ITD1000=m
+CONFIG_DVB_TUNER_CX24113=m
+CONFIG_DVB_TDA826X=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_CX24116=m
+CONFIG_DVB_SI21XX=m
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_DRX397XD=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+CONFIG_DVB_ZL10353=m
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+CONFIG_DVB_DIB7000M=m
+CONFIG_DVB_DIB7000P=m
+CONFIG_DVB_TDA10048=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_TDA10023=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terrestrial/Cable DTV) frontends
+#
+CONFIG_DVB_NXT200X=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_BCM3510=m
+CONFIG_DVB_LGDT330X=m
+CONFIG_DVB_LGDT3304=m
+CONFIG_DVB_S5H1409=m
+CONFIG_DVB_AU8522=m
+CONFIG_DVB_S5H1411=m
+
+#
+# ISDB-T (terrestrial) frontends
+#
+CONFIG_DVB_S921=m
+
+#
+# Digital terrestrial only tuners/PLL
+#
+CONFIG_DVB_PLL=m
+CONFIG_DVB_TUNER_DIB0070=m
+
+#
+# SEC control devices for DVB-S
+#
+CONFIG_DVB_LNBP21=m
+# CONFIG_DVB_ISL6405 is not set
+CONFIG_DVB_ISL6421=m
+CONFIG_DVB_LGS8GL5=m
+
+#
+# Tools to develop new frontends
+#
+# CONFIG_DVB_DUMMY_FE is not set
+CONFIG_DVB_AF9013=m
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
+CONFIG_OMAP2_DSS=y
+CONFIG_OMAP2_DSS_VRAM_SIZE=14
+CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
+# CONFIG_OMAP2_DSS_RFBI is not set
+CONFIG_OMAP2_DSS_VENC=y
+# CONFIG_OMAP2_DSS_SDI is not set
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_OMAP2_DSS_USE_DSI_PLL=y
+# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
+CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
+
+#
+# OMAP2/3 Display Device Drivers
+#
+CONFIG_PANEL_GENERIC=y
+CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C=m
+# CONFIG_PANEL_SHARP_LS037V7DW01 is not set
+# CONFIG_PANEL_N800 is not set
+# CONFIG_CTRL_BLIZZARD is not set
+CONFIG_FB_OMAP2=y
+CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
+# CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE is not set
+CONFIG_FB_OMAP2_NUM_FBS=3
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+CONFIG_DISPLAY_SUPPORT=y
+
+#
+# Display hardware drivers
+#
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_HWDEP=y
+CONFIG_SND_RAWMIDI=y
+CONFIG_SND_SEQUENCER=m
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_MCBSP=y
+CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_TWL4030=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+CONFIG_HID_DEBUG=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_TOPSEED=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_OTG=y
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_OMAP_EHCI_PHY_MODE=y
+# CONFIG_OMAP_EHCI_TLL_MODE is not set
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_OXU210HP_HCD=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_OHCI_HCD is not set
+# CONFIG_USB_U132_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_SOC=y
+
+#
+# OMAP 343x high speed USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+# CONFIG_USB_MUSB_PERIPHERAL is not set
+CONFIG_USB_MUSB_OTG=y
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_MUSB_HDRC_HCD=y
+# CONFIG_MUSB_PIO_ONLY is not set
+CONFIG_USB_INVENTRA_DMA=y
+# CONFIG_USB_TI_CPPI_DMA is not set
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+CONFIG_USB_TMC=m
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP2101=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_DEBUG=m
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_BERRY_CHARGE=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGET=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETMOTORCONTROL=m
+CONFIG_USB_PHIDGETSERVO=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+# CONFIG_USB_APPLEDISPLAY is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+CONFIG_USB_VST=m
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+CONFIG_USB_CXACRU=m
+CONFIG_USB_UEAGLEATM=m
+CONFIG_USB_XUSBATM=m
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ZERO_HNPTEST=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+CONFIG_USB_GPIO_VBUS=y
+# CONFIG_ISP1301_OMAP is not set
+CONFIG_TWL4030_USB=y
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_UNSAFE_RESUME=y
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+CONFIG_SDIO_UART=y
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+CONFIG_MMC_OMAP_HS=y
+CONFIG_MMC_SPI=m
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_OMAP_DEBUG is not set
+CONFIG_LEDS_OMAP=y
+# CONFIG_LEDS_OMAP_PWM is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+CONFIG_RTC_DRV_TWL4030=y
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+CONFIG_REGULATOR=y
+# CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
+# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
+# CONFIG_REGULATOR_BQ24022 is not set
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_UIO_SMX is not set
+# CONFIG_UIO_SERCOS3 is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+# CONFIG_MEILHAUS is not set
+# CONFIG_USB_IP_COMMON is not set
+CONFIG_W35UND=m
+CONFIG_PRISM2_USB=m
+# CONFIG_ECHO is not set
+CONFIG_USB_ATMEL=m
+# CONFIG_AGNX is not set
+CONFIG_OTUS=m
+# CONFIG_COMEDI is not set
+# CONFIG_ASUS_OLED is not set
+# CONFIG_INPUT_MIMIO is not set
+# CONFIG_TRANZPORT is not set
+
+#
+# Android
+#
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=m
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
+# CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION is not set
+# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set
+CONFIG_ANDROID_TIMED_GPIO=m
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+
+#
+# CBUS support
+#
+# CONFIG_CBUS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+CONFIG_REISERFS_PROC_INFO=y
+CONFIG_REISERFS_FS_XATTR=y
+# CONFIG_REISERFS_FS_POSIX_ACL is not set
+# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_JFS_FS=m
+# CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=m
+CONFIG_OCFS2_FS=m
+CONFIG_OCFS2_FS_O2CB=m
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m
+CONFIG_OCFS2_FS_STATS=y
+CONFIG_OCFS2_DEBUG_MASKLOG=y
+# CONFIG_OCFS2_DEBUG_FS is not set
+# CONFIG_OCFS2_FS_POSIX_ACL is not set
+CONFIG_BTRFS_FS=m
+# CONFIG_BTRFS_FS_POSIX_ACL is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+CONFIG_QUOTA_TREE=y
+# CONFIG_QFMT_V1 is not set
+CONFIG_QFMT_V2=y
+CONFIG_QUOTACTL=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=m
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+# CONFIG_ECRYPT_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+# CONFIG_JFFS2_CMODE_PRIORITY is not set
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_JFFS2_CMODE_FAVOURLZO=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+CONFIG_CRAMFS=m
+CONFIG_SQUASHFS=y
+# CONFIG_SQUASHFS_EMBEDDED is not set
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
+CONFIG_VXFS_FS=m
+CONFIG_MINIX_FS=m
+CONFIG_OMFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+# CONFIG_UFS_FS_WRITE is not set
+# CONFIG_UFS_DEBUG is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS=y
+CONFIG_CIFS_STATS2=y
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+CONFIG_CIFS_EXPERIMENTAL=y
+# CONFIG_CIFS_DFS_UPCALL is not set
+CONFIG_NCP_FS=m
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+# CONFIG_AFS_DEBUG is not set
+CONFIG_9P_FS=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+CONFIG_LDM_DEBUG=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=y
+CONFIG_DLM=m
+# CONFIG_DLM_DEBUG is not set
+
+#
+# Kernel hacking
+#
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_ERRORS is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=m
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_GF128MUL=m
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=m
+CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_SEQIV=m
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dspbridge.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dspbridge.patch
new file mode 100644 (file)
index 0000000..621ae93
--- /dev/null
@@ -0,0 +1,66715 @@
+From ea83ad971e877ef8e9b1304f2678469c2fc74c67 Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Sun, 26 Apr 2009 18:58:30 -0700
+Subject: [PATCH] Merge in tidspbridge from git://gitorious.org/tidspbridge/mainline.git
+ revisions fe30e75..20f5ca.
+
+Made a few changes so this compiles clean against a 2.6.29 non-PM
+tree.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ Documentation/tidspbridge/README                   |   70 +
+ arch/arm/Kconfig                                   |    2 +
+ arch/arm/mach-omap2/Makefile                       |    2 +
+ arch/arm/mach-omap2/dspbridge.c                    |   74 +
+ arch/arm/mach-omap2/io.c                           |    3 +
+ arch/arm/plat-omap/devices.c                       |   28 +
+ arch/arm/plat-omap/include/dspbridge/_chnl_sm.h    |  212 ++
+ arch/arm/plat-omap/include/dspbridge/_dcd.h        |  187 +
+ arch/arm/plat-omap/include/dspbridge/brddefs.h     |   54 +
+ arch/arm/plat-omap/include/dspbridge/cfg.h         |  339 ++
+ arch/arm/plat-omap/include/dspbridge/cfgdefs.h     |  126 +
+ arch/arm/plat-omap/include/dspbridge/chnl.h        |  170 +
+ arch/arm/plat-omap/include/dspbridge/chnl_sm.h     |  168 +
+ arch/arm/plat-omap/include/dspbridge/chnldefs.h    |   92 +
+ arch/arm/plat-omap/include/dspbridge/chnlpriv.h    |  136 +
+ arch/arm/plat-omap/include/dspbridge/clk.h         |  155 +
+ arch/arm/plat-omap/include/dspbridge/cmm.h         |  420 +++
+ arch/arm/plat-omap/include/dspbridge/cmmdefs.h     |  135 +
+ arch/arm/plat-omap/include/dspbridge/cod.h         |  433 +++
+ arch/arm/plat-omap/include/dspbridge/csl.h         |  135 +
+ arch/arm/plat-omap/include/dspbridge/dbc.h         |   66 +
+ arch/arm/plat-omap/include/dspbridge/dbdcd.h       |  388 +++
+ arch/arm/plat-omap/include/dspbridge/dbdcddef.h    |   94 +
+ arch/arm/plat-omap/include/dspbridge/dbdefs.h      |  580 ++++
+ arch/arm/plat-omap/include/dspbridge/dbg.h         |  110 +
+ arch/arm/plat-omap/include/dspbridge/dbl.h         |  354 ++
+ arch/arm/plat-omap/include/dspbridge/dbldefs.h     |  155 +
+ arch/arm/plat-omap/include/dspbridge/dbll.h        |   70 +
+ arch/arm/plat-omap/include/dspbridge/dblldefs.h    |  509 +++
+ arch/arm/plat-omap/include/dspbridge/dbof.h        |  117 +
+ arch/arm/plat-omap/include/dspbridge/dbreg.h       |  113 +
+ arch/arm/plat-omap/include/dspbridge/dbtype.h      |  103 +
+ arch/arm/plat-omap/include/dspbridge/dehdefs.h     |   42 +
+ arch/arm/plat-omap/include/dspbridge/dev.h         |  785 +++++
+ arch/arm/plat-omap/include/dspbridge/devdefs.h     |   35 +
+ arch/arm/plat-omap/include/dspbridge/disp.h        |  236 ++
+ arch/arm/plat-omap/include/dspbridge/dispdefs.h    |   45 +
+ arch/arm/plat-omap/include/dspbridge/dmm.h         |   85 +
+ arch/arm/plat-omap/include/dspbridge/dpc.h         |  167 +
+ arch/arm/plat-omap/include/dspbridge/drv.h         |  449 +++
+ arch/arm/plat-omap/include/dspbridge/drvdefs.h     |   34 +
+ arch/arm/plat-omap/include/dspbridge/dspdrv.h      |  106 +
+ .../plat-omap/include/dspbridge/dynamic_loader.h   |  505 +++
+ arch/arm/plat-omap/include/dspbridge/errbase.h     |  509 +++
+ arch/arm/plat-omap/include/dspbridge/gb.h          |   85 +
+ arch/arm/plat-omap/include/dspbridge/getsection.h  |  118 +
+ arch/arm/plat-omap/include/dspbridge/gh.h          |   37 +
+ arch/arm/plat-omap/include/dspbridge/gs.h          |   64 +
+ arch/arm/plat-omap/include/dspbridge/gt.h          |  315 ++
+ arch/arm/plat-omap/include/dspbridge/host_os.h     |   96 +
+ arch/arm/plat-omap/include/dspbridge/io.h          |  132 +
+ arch/arm/plat-omap/include/dspbridge/io_sm.h       |  335 ++
+ arch/arm/plat-omap/include/dspbridge/iodefs.h      |   45 +
+ arch/arm/plat-omap/include/dspbridge/kfile.h       |  216 ++
+ arch/arm/plat-omap/include/dspbridge/ldr.h         |   51 +
+ arch/arm/plat-omap/include/dspbridge/list.h        |  296 ++
+ arch/arm/plat-omap/include/dspbridge/mbx_sh.h      |  213 ++
+ arch/arm/plat-omap/include/dspbridge/mem.h         |  340 ++
+ arch/arm/plat-omap/include/dspbridge/memdefs.h     |   52 +
+ arch/arm/plat-omap/include/dspbridge/mgr.h         |  234 ++
+ arch/arm/plat-omap/include/dspbridge/mgrpriv.h     |   55 +
+ arch/arm/plat-omap/include/dspbridge/msg.h         |  106 +
+ arch/arm/plat-omap/include/dspbridge/msgdefs.h     |   43 +
+ arch/arm/plat-omap/include/dspbridge/nldr.h        |   81 +
+ arch/arm/plat-omap/include/dspbridge/nldrdefs.h    |  307 ++
+ arch/arm/plat-omap/include/dspbridge/node.h        |  619 ++++
+ arch/arm/plat-omap/include/dspbridge/nodedefs.h    |   40 +
+ arch/arm/plat-omap/include/dspbridge/nodepriv.h    |  202 ++
+ arch/arm/plat-omap/include/dspbridge/ntfy.h        |  146 +
+ arch/arm/plat-omap/include/dspbridge/proc.h        |  648 ++++
+ arch/arm/plat-omap/include/dspbridge/procpriv.h    |   35 +
+ arch/arm/plat-omap/include/dspbridge/pwr.h         |  129 +
+ arch/arm/plat-omap/include/dspbridge/pwr_sh.h      |   41 +
+ arch/arm/plat-omap/include/dspbridge/reg.h         |  257 ++
+ .../plat-omap/include/dspbridge/resourcecleanup.h  |   88 +
+ arch/arm/plat-omap/include/dspbridge/rmm.h         |  199 ++
+ arch/arm/plat-omap/include/dspbridge/rms_sh.h      |  125 +
+ arch/arm/plat-omap/include/dspbridge/rmstypes.h    |   40 +
+ arch/arm/plat-omap/include/dspbridge/services.h    |   63 +
+ arch/arm/plat-omap/include/dspbridge/std.h         |  143 +
+ arch/arm/plat-omap/include/dspbridge/strm.h        |  441 +++
+ arch/arm/plat-omap/include/dspbridge/strmdefs.h    |   57 +
+ arch/arm/plat-omap/include/dspbridge/sync.h        |  340 ++
+ arch/arm/plat-omap/include/dspbridge/util.h        |  122 +
+ arch/arm/plat-omap/include/dspbridge/utildefs.h    |   51 +
+ arch/arm/plat-omap/include/dspbridge/uuidutil.h    |   74 +
+ arch/arm/plat-omap/include/dspbridge/wcd.h         |   61 +
+ arch/arm/plat-omap/include/dspbridge/wcdioctl.h    |  519 +++
+ arch/arm/plat-omap/include/dspbridge/wmd.h         | 1193 +++++++
+ arch/arm/plat-omap/include/dspbridge/wmdchnl.h     |   90 +
+ arch/arm/plat-omap/include/dspbridge/wmddeh.h      |   64 +
+ arch/arm/plat-omap/include/dspbridge/wmdio.h       |   53 +
+ arch/arm/plat-omap/include/dspbridge/wmdioctl.h    |   91 +
+ arch/arm/plat-omap/include/dspbridge/wmdmsg.h      |   70 +
+ drivers/Makefile                                   |    1 +
+ drivers/dsp/bridge/Kbuild                          |   39 +
+ drivers/dsp/bridge/Kconfig                         |   36 +
+ drivers/dsp/bridge/dynload/cload.c                 | 1854 ++++++++++
+ drivers/dsp/bridge/dynload/dlclasses_hdr.h         |   41 +
+ drivers/dsp/bridge/dynload/dload_internal.h        |  237 ++
+ drivers/dsp/bridge/dynload/doff.h                  |  347 ++
+ drivers/dsp/bridge/dynload/getsection.c            |  412 +++
+ drivers/dsp/bridge/dynload/header.h                |   59 +
+ drivers/dsp/bridge/dynload/module_list.h           |  161 +
+ drivers/dsp/bridge/dynload/params.h                |  231 ++
+ drivers/dsp/bridge/dynload/reloc.c                 |  425 +++
+ drivers/dsp/bridge/dynload/reloc_table.h           |  102 +
+ drivers/dsp/bridge/dynload/reloc_table_c6000.c     |  258 ++
+ drivers/dsp/bridge/gen/_gt_para.c                  |  107 +
+ drivers/dsp/bridge/gen/gb.c                        |  182 +
+ drivers/dsp/bridge/gen/gh.c                        |  191 ++
+ drivers/dsp/bridge/gen/gs.c                        |  108 +
+ drivers/dsp/bridge/gen/gt.c                        |  348 ++
+ drivers/dsp/bridge/gen/uuidutil.c                  |  238 ++
+ drivers/dsp/bridge/hw/EasiGlobal.h                 |   42 +
+ drivers/dsp/bridge/hw/GlobalTypes.h                |  325 ++
+ drivers/dsp/bridge/hw/IPIAccInt.h                  |   41 +
+ drivers/dsp/bridge/hw/IVA2RegAcM.h                 |   28 +
+ drivers/dsp/bridge/hw/MLBAccInt.h                  |  132 +
+ drivers/dsp/bridge/hw/MLBRegAcM.h                  |  200 ++
+ drivers/dsp/bridge/hw/MMUAccInt.h                  |   76 +
+ drivers/dsp/bridge/hw/MMURegAcM.h                  |  253 ++
+ drivers/dsp/bridge/hw/PRCMAccInt.h                 |  300 ++
+ drivers/dsp/bridge/hw/PRCMRegAcM.h                 |  669 ++++
+ drivers/dsp/bridge/hw/hw_defs.h                    |   73 +
+ drivers/dsp/bridge/hw/hw_dspssC64P.c               |   55 +
+ drivers/dsp/bridge/hw/hw_dspssC64P.h               |   48 +
+ drivers/dsp/bridge/hw/hw_mbox.c                    |  244 ++
+ drivers/dsp/bridge/hw/hw_mbox.h                    |  323 ++
+ drivers/dsp/bridge/hw/hw_mmu.c                     |  598 ++++
+ drivers/dsp/bridge/hw/hw_mmu.h                     |  177 +
+ drivers/dsp/bridge/hw/hw_prcm.c                    |  167 +
+ drivers/dsp/bridge/hw/hw_prcm.h                    |  168 +
+ drivers/dsp/bridge/pmgr/chnl.c                     |  260 ++
+ drivers/dsp/bridge/pmgr/chnlobj.h                  |   71 +
+ drivers/dsp/bridge/pmgr/cmm.c                      | 1291 +++++++
+ drivers/dsp/bridge/pmgr/cod.c                      |  683 ++++
+ drivers/dsp/bridge/pmgr/dbl.c                      | 1385 ++++++++
+ drivers/dsp/bridge/pmgr/dbll.c                     | 1564 +++++++++
+ drivers/dsp/bridge/pmgr/dev.c                      | 1476 ++++++++
+ drivers/dsp/bridge/pmgr/dmm.c                      |  692 ++++
+ drivers/dsp/bridge/pmgr/io.c                       |  205 ++
+ drivers/dsp/bridge/pmgr/ioobj.h                    |   52 +
+ drivers/dsp/bridge/pmgr/msg.c                      |  173 +
+ drivers/dsp/bridge/pmgr/msgobj.h                   |   52 +
+ drivers/dsp/bridge/pmgr/wcd.c                      | 1647 +++++++++
+ drivers/dsp/bridge/rmgr/dbdcd.c                    | 1573 +++++++++
+ drivers/dsp/bridge/rmgr/disp.c                     |  916 +++++
+ drivers/dsp/bridge/rmgr/drv.c                      | 1893 +++++++++++
+ drivers/dsp/bridge/rmgr/drv_interface.c            |  777 +++++
+ drivers/dsp/bridge/rmgr/drv_interface.h            |   40 +
+ drivers/dsp/bridge/rmgr/dspdrv.c                   |  276 ++
+ drivers/dsp/bridge/rmgr/mgr.c                      |  491 +++
+ drivers/dsp/bridge/rmgr/nldr.c                     | 1967 +++++++++++
+ drivers/dsp/bridge/rmgr/node.c                     | 3544 ++++++++++++++++++++
+ drivers/dsp/bridge/rmgr/proc.c                     | 1985 +++++++++++
+ drivers/dsp/bridge/rmgr/pwr.c                      |  184 +
+ drivers/dsp/bridge/rmgr/rmm.c                      |  604 ++++
+ drivers/dsp/bridge/rmgr/strm.c                     | 1066 ++++++
+ drivers/dsp/bridge/services/cfg.c                  |  483 +++
+ drivers/dsp/bridge/services/clk.c                  |  375 +++
+ drivers/dsp/bridge/services/csl.c                  |  173 +
+ drivers/dsp/bridge/services/dbg.c                  |  119 +
+ drivers/dsp/bridge/services/dpc.c                  |  274 ++
+ drivers/dsp/bridge/services/kfile.c                |  338 ++
+ drivers/dsp/bridge/services/list.c                 |  285 ++
+ drivers/dsp/bridge/services/mem.c                  |  599 ++++
+ drivers/dsp/bridge/services/ntfy.c                 |  329 ++
+ drivers/dsp/bridge/services/reg.c                  |  196 ++
+ drivers/dsp/bridge/services/regsup.c               |  368 ++
+ drivers/dsp/bridge/services/regsup.h               |   58 +
+ drivers/dsp/bridge/services/services.c             |  193 ++
+ drivers/dsp/bridge/services/sync.c                 |  602 ++++
+ drivers/dsp/bridge/wmd/_cmm.h                      |   59 +
+ drivers/dsp/bridge/wmd/_deh.h                      |   46 +
+ drivers/dsp/bridge/wmd/_msg_sm.h                   |  158 +
+ drivers/dsp/bridge/wmd/_tiomap.h                   |  384 +++
+ drivers/dsp/bridge/wmd/_tiomap_mmu.h               |   53 +
+ drivers/dsp/bridge/wmd/_tiomap_pwr.h               |  102 +
+ drivers/dsp/bridge/wmd/_tiomap_util.h              |   46 +
+ drivers/dsp/bridge/wmd/chnl_sm.c                   | 1100 ++++++
+ drivers/dsp/bridge/wmd/io_sm.c                     | 2011 +++++++++++
+ drivers/dsp/bridge/wmd/mmu_fault.c                 |  172 +
+ drivers/dsp/bridge/wmd/mmu_fault.h                 |   45 +
+ drivers/dsp/bridge/wmd/msg_sm.c                    |  643 ++++
+ drivers/dsp/bridge/wmd/tiomap3430.c                | 2149 ++++++++++++
+ drivers/dsp/bridge/wmd/tiomap3430_pwr.c            |  731 ++++
+ drivers/dsp/bridge/wmd/tiomap_io.c                 |  427 +++
+ drivers/dsp/bridge/wmd/tiomap_io.h                 |  112 +
+ drivers/dsp/bridge/wmd/tiomap_sm.c                 |  195 ++
+ drivers/dsp/bridge/wmd/ue_deh.c                    |  329 ++
+ 191 files changed, 65137 insertions(+), 0 deletions(-)
+ create mode 100644 Documentation/tidspbridge/README
+ create mode 100644 arch/arm/mach-omap2/dspbridge.c
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/_chnl_sm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/_dcd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/brddefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cfg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cfgdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnl_sm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnldefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnlpriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/clk.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cmm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cmmdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cod.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/csl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbc.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbdcd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbdcddef.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbldefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbll.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dblldefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbof.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbreg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbtype.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dehdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dev.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/devdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/disp.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dispdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dmm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dpc.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/drv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/drvdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dspdrv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dynamic_loader.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/errbase.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gb.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/getsection.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gt.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/host_os.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/io.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/io_sm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/iodefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/kfile.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/ldr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/list.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mbx_sh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mem.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/memdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mgr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mgrpriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/msg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/msgdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nldr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nldrdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/node.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nodedefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nodepriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/ntfy.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/proc.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/procpriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/pwr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/pwr_sh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/reg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/rmm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/rms_sh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/rmstypes.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/services.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/std.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/strm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/strmdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/sync.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/util.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/utildefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/uuidutil.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wcd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wcdioctl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdchnl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmddeh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdio.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdioctl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdmsg.h
+ create mode 100644 drivers/dsp/bridge/Kbuild
+ create mode 100644 drivers/dsp/bridge/Kconfig
+ create mode 100644 drivers/dsp/bridge/dynload/cload.c
+ create mode 100644 drivers/dsp/bridge/dynload/dlclasses_hdr.h
+ create mode 100644 drivers/dsp/bridge/dynload/dload_internal.h
+ create mode 100644 drivers/dsp/bridge/dynload/doff.h
+ create mode 100644 drivers/dsp/bridge/dynload/getsection.c
+ create mode 100644 drivers/dsp/bridge/dynload/header.h
+ create mode 100644 drivers/dsp/bridge/dynload/module_list.h
+ create mode 100644 drivers/dsp/bridge/dynload/params.h
+ create mode 100644 drivers/dsp/bridge/dynload/reloc.c
+ create mode 100644 drivers/dsp/bridge/dynload/reloc_table.h
+ create mode 100644 drivers/dsp/bridge/dynload/reloc_table_c6000.c
+ create mode 100644 drivers/dsp/bridge/gen/_gt_para.c
+ create mode 100644 drivers/dsp/bridge/gen/gb.c
+ create mode 100644 drivers/dsp/bridge/gen/gh.c
+ create mode 100644 drivers/dsp/bridge/gen/gs.c
+ create mode 100644 drivers/dsp/bridge/gen/gt.c
+ create mode 100644 drivers/dsp/bridge/gen/uuidutil.c
+ create mode 100644 drivers/dsp/bridge/hw/EasiGlobal.h
+ create mode 100644 drivers/dsp/bridge/hw/GlobalTypes.h
+ create mode 100644 drivers/dsp/bridge/hw/IPIAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/IVA2RegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/MLBAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/MLBRegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/MMUAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/MMURegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/PRCMAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/PRCMRegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_defs.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_dspssC64P.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_dspssC64P.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_mbox.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_mbox.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_mmu.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_mmu.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_prcm.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_prcm.h
+ create mode 100644 drivers/dsp/bridge/pmgr/chnl.c
+ create mode 100644 drivers/dsp/bridge/pmgr/chnlobj.h
+ create mode 100644 drivers/dsp/bridge/pmgr/cmm.c
+ create mode 100644 drivers/dsp/bridge/pmgr/cod.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dbl.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dbll.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dev.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dmm.c
+ create mode 100644 drivers/dsp/bridge/pmgr/io.c
+ create mode 100644 drivers/dsp/bridge/pmgr/ioobj.h
+ create mode 100644 drivers/dsp/bridge/pmgr/msg.c
+ create mode 100644 drivers/dsp/bridge/pmgr/msgobj.h
+ create mode 100644 drivers/dsp/bridge/pmgr/wcd.c
+ create mode 100644 drivers/dsp/bridge/rmgr/dbdcd.c
+ create mode 100644 drivers/dsp/bridge/rmgr/disp.c
+ create mode 100644 drivers/dsp/bridge/rmgr/drv.c
+ create mode 100644 drivers/dsp/bridge/rmgr/drv_interface.c
+ create mode 100644 drivers/dsp/bridge/rmgr/drv_interface.h
+ create mode 100644 drivers/dsp/bridge/rmgr/dspdrv.c
+ create mode 100644 drivers/dsp/bridge/rmgr/mgr.c
+ create mode 100644 drivers/dsp/bridge/rmgr/nldr.c
+ create mode 100644 drivers/dsp/bridge/rmgr/node.c
+ create mode 100644 drivers/dsp/bridge/rmgr/proc.c
+ create mode 100644 drivers/dsp/bridge/rmgr/pwr.c
+ create mode 100644 drivers/dsp/bridge/rmgr/rmm.c
+ create mode 100644 drivers/dsp/bridge/rmgr/strm.c
+ create mode 100644 drivers/dsp/bridge/services/cfg.c
+ create mode 100644 drivers/dsp/bridge/services/clk.c
+ create mode 100644 drivers/dsp/bridge/services/csl.c
+ create mode 100644 drivers/dsp/bridge/services/dbg.c
+ create mode 100644 drivers/dsp/bridge/services/dpc.c
+ create mode 100644 drivers/dsp/bridge/services/kfile.c
+ create mode 100644 drivers/dsp/bridge/services/list.c
+ create mode 100644 drivers/dsp/bridge/services/mem.c
+ create mode 100644 drivers/dsp/bridge/services/ntfy.c
+ create mode 100644 drivers/dsp/bridge/services/reg.c
+ create mode 100644 drivers/dsp/bridge/services/regsup.c
+ create mode 100644 drivers/dsp/bridge/services/regsup.h
+ create mode 100644 drivers/dsp/bridge/services/services.c
+ create mode 100644 drivers/dsp/bridge/services/sync.c
+ create mode 100644 drivers/dsp/bridge/wmd/_cmm.h
+ create mode 100644 drivers/dsp/bridge/wmd/_deh.h
+ create mode 100644 drivers/dsp/bridge/wmd/_msg_sm.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap_mmu.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap_pwr.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap_util.h
+ create mode 100644 drivers/dsp/bridge/wmd/chnl_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/io_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/mmu_fault.c
+ create mode 100644 drivers/dsp/bridge/wmd/mmu_fault.h
+ create mode 100644 drivers/dsp/bridge/wmd/msg_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap3430.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap3430_pwr.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap_io.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap_io.h
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/ue_deh.c
+
+diff --git a/Documentation/tidspbridge/README b/Documentation/tidspbridge/README
+new file mode 100644
+index 0000000..df6d371
+--- /dev/null
++++ b/Documentation/tidspbridge/README
+@@ -0,0 +1,70 @@
++                        Linux DSP/BIOS Bridge release
++
++DSP/BIOS Bridge overview
++========================
++
++DSP/BIOS Bridge is designed for platforms that contain a GPP and one or more
++attached DSPs.  The GPP is considered the master or "host" processor, and the
++attached DSPs are processing resources that can be utilized by applications
++and drivers running on the GPP.
++
++The abstraction that DSP/BIOS Bridge supplies, is a direct link between a GPP
++program and a DSP task.  This communication link is partitioned into two
++types of sub-links:  messaging (short, fixed-length packets) and data
++streaming (multiple, large buffers).  Each sub-link operates independently,
++and features in-order delivery of data, meaning that messages are delivered
++in the order they were submitted to the message link, and stream buffers are
++delivered in the order they were submitted to the stream link.
++
++In addition, a GPP client can specify what inputs and outputs a DSP task
++uses. DSP tasks typically use message objects for passing control and status
++information and stream objects for efficient streaming of real-time data.
++
++GPP Software Architecture
++=========================
++
++A GPP application communicates with its associated DSP task running on the
++DSP subsystem using the DSP/BIOS Bridge API. For example, a GPP audio
++application can use the API to pass messages to a DSP task that is managing
++data flowing from analog-to-digital converters (ADCs) to digital-to-analog
++converters (DACs).
++
++From the perspective of the GPP OS, the DSP is treated as just another
++peripheral device.   Most high level GPP OS typically support a device driver
++model, whereby applications can safely access and share a hardware peripheral
++through standard driver interfaces.  Therefore, to allow multiple GPP
++applications to share access to the DSP, the GPP side of DSP/BIOS Bridge
++implements a device driver for the DSP.
++
++Since driver interfaces are not always standard across GPP OS, and to provide
++some level of interoperability of application code using DSP/BIOS Bridge
++between GPP OS, DSP/BIOS Bridge provides a standard library of APIs which
++wrap calls into the device driver.   So, rather than calling GPP OS specific
++driver interfaces, applications (and even other device drivers) can use the
++standard API library directly.
++
++DSP Software Architecture
++=========================
++
++For DSP/BIOS, DSP/BIOS Bridge adds a device-independent streaming I/O (STRM)
++interface, a messaging interface (NODE), and a Resource Manager (RM) Server.
++The RM Server runs as a task of DSP/BIOS and is subservient to commands
++and queries from the GPP.  It executes commands to start and stop DSP signal
++processing nodes in response to GPP programs making requests through the
++(GPP-side) API.
++
++DSP tasks started by the RM Server are similar to any other DSP task with two
++important differences:  they must follow a specific task model consisting of
++three C-callable functions (node create, execute, and delete), with specific
++sets of arguments, and they have a pre-defined task environment established
++by the RM Server.
++
++Tasks started by the RM Server communicate using the STRM and NODE interfaces
++and act as servers for their corresponding GPP clients, performing signal
++processing functions as requested by messages sent by their GPP client.
++Typically, a DSP task moves data from source devices to sink devices using
++device independent I/O streams, performing application-specific processing
++and transformations on the data while it is moved.  For example, an audio
++task might perform audio decompression (ADPCM, MPEG, CELP) on data received
++from a GPP audio driver and then send the decompressed linear samples to a
++digital-to-analog converter.
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index e7fb201..2060772 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -1331,6 +1331,8 @@ if ARCH_OMAP
+ source "drivers/cbus/Kconfig"
+ endif
++source "drivers/dsp/bridge/Kconfig"
++
+ endmenu
+ source "fs/Kconfig"
+diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
+index 9b270d8..e52e01e 100644
+--- a/arch/arm/mach-omap2/Makefile
++++ b/arch/arm/mach-omap2/Makefile
+@@ -34,6 +34,8 @@ obj-$(CONFIG_OMAP_SMARTREFLEX)               += smartreflex.o
+ obj-$(CONFIG_ARCH_OMAP2)              += clock24xx.o
+ obj-$(CONFIG_ARCH_OMAP3)              += clock34xx.o
++obj-$(CONFIG_MPU_BRIDGE)              += dspbridge.o
++
+ # DSP
+ obj-$(CONFIG_OMAP_MBOX_FWK)   += mailbox_mach.o
+ mailbox_mach-objs             := mailbox.o
+diff --git a/arch/arm/mach-omap2/dspbridge.c b/arch/arm/mach-omap2/dspbridge.c
+new file mode 100644
+index 0000000..221e8ff
+--- /dev/null
++++ b/arch/arm/mach-omap2/dspbridge.c
+@@ -0,0 +1,74 @@
++/*
++ * TI's dspbridge platform device registration
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ * Copyright (C) 2009 Nokia Corporation
++ *
++ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/platform_device.h>
++#include <dspbridge/host_os.h>
++
++static struct platform_device *dspbridge_pdev;
++
++#ifdef CONFIG_BRIDGE_DVFS
++#include <mach/omap-pm.h>
++static struct dspbridge_platform_data dspbridge_pdata __initdata = {
++      .dsp_set_min_opp = omap_pm_dsp_set_min_opp,
++      .dsp_get_opp     = omap_pm_dsp_get_opp,
++      .cpu_set_freq    = omap_pm_cpu_set_freq,
++      .cpu_get_freq    = omap_pm_cpu_get_freq,
++};
++#else
++static struct dspbridge_platform_data dspbridge_pdata;
++#endif
++
++static int __init dspbridge_init(void)
++{
++      struct platform_device *pdev;
++      int err = -ENOMEM;
++      struct dspbridge_platform_data *pdata = &dspbridge_pdata;
++
++      pdata->phys_mempool_base = dspbridge_get_mempool_base();
++
++      if (pdata->phys_mempool_base) {
++              pdata->phys_mempool_size = CONFIG_BRIDGE_MEMPOOL_SIZE;
++              pr_info("%s: %x bytes @ %x\n", __func__,
++                      pdata->phys_mempool_size, pdata->phys_mempool_base);
++      }
++
++      pdev = platform_device_alloc("C6410", -1);
++      if (!pdev)
++              goto err_out;
++
++      err = platform_device_add_data(pdev, pdata, sizeof(*pdata));
++      if (err)
++              goto err_out;
++
++      err = platform_device_add(pdev);
++      if (err)
++              goto err_out;
++
++      dspbridge_pdev = pdev;
++      return 0;
++
++err_out:
++      platform_device_put(pdev);
++      return err;
++}
++module_init(dspbridge_init);
++
++static void __exit dspbridge_exit(void)
++{
++      platform_device_unregister(dspbridge_pdev);
++}
++module_exit(dspbridge_exit);
++
++MODULE_AUTHOR("Hiroshi DOYU");
++MODULE_DESCRIPTION("TI's dspbridge platform device registration");
++MODULE_LICENSE("GPL v2");
+diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
+index a04e3ee..40488ae 100644
+--- a/arch/arm/mach-omap2/io.c
++++ b/arch/arm/mach-omap2/io.c
+@@ -38,6 +38,8 @@
+ #include <mach/clockdomain.h>
+ #include "clockdomains.h"
++#include <dspbridge/host_os.h>
++
+ /*
+  * The machine specific code may provide the extra mapping besides the
+  * default mapping provided here.
+@@ -192,6 +194,7 @@ void __init omap2_map_common_io(void)
+       omap2_check_revision();
+       omap_sram_init();
+       omapfb_reserve_sdram();
++      dspbridge_reserve_sdram();
+ }
+ void __init omap2_init_common_hw(struct omap_sdrc_params *sp)
+diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
+index 6b742a8..e66dd8a 100644
+--- a/arch/arm/plat-omap/devices.c
++++ b/arch/arm/plat-omap/devices.c
+@@ -15,6 +15,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+ #include <linux/i2c/menelaus.h>
++#include <linux/bootmem.h>
+ #include <mach/hardware.h>
+ #include <asm/mach-types.h>
+@@ -89,6 +90,33 @@ EXPORT_SYMBOL(dsp_kfunc_device_register);
+ static inline void omap_init_dsp(void) { }
+ #endif        /* CONFIG_OMAP_DSP */
++#if defined(CONFIG_MPU_BRIDGE) ||  defined(CONFIG_MPU_BRIDGE_MODULE)
++
++static unsigned long dspbridge_phys_mempool_base;
++
++void dspbridge_reserve_sdram(void)
++{
++      void *va;
++      unsigned long size = CONFIG_BRIDGE_MEMPOOL_SIZE;
++
++      if (!size)
++              return;
++
++      va = __alloc_bootmem_nopanic(size, SZ_1M, 0);
++      if (!va) {
++              pr_err("%s: Failed to bootmem allocation(%lu bytes)\n",
++                     __func__, size);
++              return;
++      }
++      dspbridge_phys_mempool_base = virt_to_phys(va);
++}
++
++unsigned long dspbridge_get_mempool_base(void)
++{
++      return dspbridge_phys_mempool_base;
++}
++EXPORT_SYMBOL(dspbridge_get_mempool_base);
++#endif
+ /*-------------------------------------------------------------------------*/
+ #if   defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
+diff --git a/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h b/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h
+new file mode 100644
+index 0000000..28af799
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h
+@@ -0,0 +1,212 @@
++/*
++ * _chnl_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== _chnl_sm.h ========
++ *  Description:
++ *      Private header file defining channel manager and channel objects for
++ *      a shared memory channel driver.
++ *
++ *  Public Functions:
++ *      None.
++ *
++ *  Notes:
++ *      Shared between the modules implementing the shared memory channel class
++ *      library.
++ *
++ *! Revision History:
++ *! ================
++ *! 15-Oct-2002 kc  Removed legacy PERF code.
++ *! 12-Jan-2002 ag  Removed unused gppReqIO & ddmaChnlId DDMA fields.
++ *!                 Added zero-copy chnl descriptor array: zchnldesc.
++ *! 21-Dec-2001 ag  Moved descPaGpp to private chnl obj from chnl descriptor.
++ *! 20-May-2001 ag/jeh Removed fShmSyms field from CHNL_MGR.
++ *! 04-Feb-2001 ag  DSP-DMA support added.
++ *! 26-Oct-2000 jeh Added arg and resvd to SHM control structure. Added dwArg
++ *!                 to CHNL_IRP.
++ *! 16-Oct-2000 jeh Removed #ifdef DEBUG from around channel object's cIOCs
++ *!                 field, added cIOReqs.
++ *! 20-Jan-2000 ag: Incorporated code review comments.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 03-Nov-1999 ag: Added szEventName[] to CHNL object for name event support.
++ *! 02-Nov-1999 ag: _SHM_BEG & _END Syms from COFF now used for IO and SM CLASS.
++ *! 27-Oct-1999 jeh Define SHM structure to work for 16-bit targets.
++ *! 25-May-1999 jg: Added target side symbol names for share memory buffer
++ *! 03-Jan-1997 gp: Added fSharedIRQ field.
++ *! 22-Oct-1996 gp: Made dwProcessID a handle.
++ *! 09-Sep-1996 gp: Added dwProcessID field to CHNL_OBJECT.
++ *! 13-Aug-1996 gp: Created.
++ */
++
++#ifndef _CHNL_SM_
++#define _CHNL_SM_
++
++#include <dspbridge/wcd.h>
++#include <dspbridge/wmd.h>
++#include <dspbridge/dpc.h>
++
++#include <dspbridge/list.h>
++#include <dspbridge/ntfy.h>
++
++/*
++ *  These target side symbols define the beginning and ending addresses
++ *  of shared memory buffer. They are defined in the *cfg.cmd file by
++ *  cdb code.
++ */
++#define CHNL_SHARED_BUFFER_BASE_SYM "_SHM_BEG"
++#define CHNL_SHARED_BUFFER_LIMIT_SYM "_SHM_END"
++#define BRIDGEINIT_BIOSGPTIMER "_BRIDGEINIT_BIOSGPTIMER"
++#define BRIDGEINIT_LOADMON_GPTIMER "_BRIDGEINIT_LOADMON_GPTIMER"
++
++#ifndef _CHNL_WORDSIZE
++#define _CHNL_WORDSIZE 4      /* default _CHNL_WORDSIZE is 2 bytes/word */
++#endif
++
++#define MAXOPPS 16
++
++struct oppTableEntry {
++    u32 voltage;
++    u32 frequency;
++    u32 minFreq;
++    u32 maxFreq;
++} ;
++
++struct oppStruct {
++    u32 currOppPt;
++    u32 numOppPts;
++    struct oppTableEntry oppPoint[MAXOPPS];
++} ;
++
++/* Request to MPU */
++struct oppRqstStruct {
++    u32 rqstDspFreq;
++    u32 rqstOppPt;
++};
++
++/* Info to MPU */
++struct loadMonStruct {
++    u32 currDspLoad;
++    u32 currDspFreq;
++    u32 predDspLoad;
++    u32 predDspFreq;
++};
++
++      enum SHM_DESCTYPE {
++              SHM_CURROPP = 0,
++              SHM_OPPINFO = 1,
++              SHM_GETOPP = 2,         /* Get DSP requested OPP info */
++      } ;
++
++/* Structure in shared between DSP and PC for communication.*/
++      struct SHM {
++              u32 dspFreeMask;        /* Written by DSP, read by PC. */
++              u32 hostFreeMask;       /* Written by PC, read by DSP */
++
++              u32 inputFull;  /* Input channel has unread data. */
++              u32 inputId;    /* Channel for which input is available. */
++              u32 inputSize;  /* Size of data block (in DSP words). */
++
++              u32 outputFull; /* Output channel has unread data. */
++              u32 outputId;   /* Channel for which output is available. */
++              u32 outputSize; /* Size of data block (in DSP words). */
++
++              u32 arg;        /* Arg for Issue/Reclaim (23 bits for 55x). */
++              u32 resvd;      /* Keep structure size even for 32-bit DSPs */
++
++              /* Operating Point structure */
++              struct oppStruct  oppTableStruct;
++              /* Operating Point Request structure */
++              struct oppRqstStruct oppRequest;
++              /* load monitor information structure*/
++              struct loadMonStruct loadMonInfo;
++              char dummy[184];             /* padding to 256 byte boundary */
++              u32 shm_dbg_var[64];         /* shared memory debug variables */
++      } ;
++
++      /* Channel Manager: only one created per board: */
++      struct CHNL_MGR {
++              u32 dwSignature;        /* Used for object validation */
++              /* Function interface to WMD */
++              struct WMD_DRV_INTERFACE *pIntfFxns;
++              struct IO_MGR *hIOMgr;  /* IO manager */
++              /* Device this board represents */
++              struct DEV_OBJECT *hDevObject;
++
++              /* These fields initialized in WMD_CHNL_Create():    */
++              u32 dwOutputMask; /* Host output channels w/ full buffers */
++              u32 dwLastOutput;       /* Last output channel fired from DPC */
++              /* Critical section object handle */
++              struct SYNC_CSOBJECT *hCSObj;
++              u32 uWordSize;  /* Size in bytes of DSP word */
++              u32 cChannels;  /* Total number of channels */
++              u32 cOpenChannels;      /* Total number of open channels */
++              struct CHNL_OBJECT **apChannel; /* Array of channels */
++              u32 dwType;     /* Type of channel class library */
++              /* If no SHM syms, return for CHNL_Open */
++              DSP_STATUS chnlOpenStatus;
++      } ;
++
++/*
++ *  Channel: up to CHNL_MAXCHANNELS per board or if DSP-DMA supported then
++ *     up to CHNL_MAXCHANNELS + CHNL_MAXDDMACHNLS per board.
++ */
++      struct CHNL_OBJECT {
++              u32 dwSignature;        /* Used for object validation */
++              /* Pointer back to channel manager */
++              struct CHNL_MGR *pChnlMgr;
++              u32 uId;        /* Channel id */
++              u32 dwState;    /* Current channel state */
++              u32 uMode;      /* Chnl mode and attributes */
++              /* Chnl I/O completion event (user mode) */
++              HANDLE hUserEvent;
++              /* Abstract syncronization object */
++              struct SYNC_OBJECT *hSyncEvent;
++              /* Name of Sync event */
++              char szEventName[SYNC_MAXNAMELENGTH + 1];
++               u32 hProcess;   /* Process which created this channel */
++              u32 pCBArg;     /* Argument to use with callback */
++              struct LST_LIST *pIORequests;   /* List of IOR's to driver */
++              s32 cIOCs;      /* Number of IOC's in queue */
++              s32 cIOReqs;    /* Number of IORequests in queue */
++              s32 cChirps;    /* Initial number of free Irps */
++              /* List of IOC's from driver */
++              struct LST_LIST *pIOCompletions;
++              struct LST_LIST *pFreeList;     /* List of free Irps */
++              struct NTFY_OBJECT *hNtfy;
++              u32 cBytesMoved;        /* Total number of bytes transfered */
++
++              /* For DSP-DMA */
++
++              /* Type of chnl transport:CHNL_[PCPY][DDMA] */
++              u32 uChnlType;
++      } ;
++
++/* I/O Request/completion packet: */
++      struct CHNL_IRP {
++              struct LST_ELEM link;   /* Link to next CHIRP in queue. */
++              /* Buffer to be filled/emptied. (User)   */
++              u8 *pHostUserBuf;
++              /* Buffer to be filled/emptied. (System) */
++              u8 *pHostSysBuf;
++              u32 dwArg;      /* Issue/Reclaim argument.               */
++              u32 uDspAddr;   /* Transfer address on DSP side.         */
++              u32 cBytes;     /* Bytes transferred.                    */
++              u32 cBufSize;   /* Actual buffer size when allocated.    */
++              u32 status;     /* Status of IO completion.              */
++      } ;
++
++#endif                                /* _CHNL_SM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/_dcd.h b/arch/arm/plat-omap/include/dspbridge/_dcd.h
+new file mode 100644
+index 0000000..b6a8d9e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/_dcd.h
+@@ -0,0 +1,187 @@
++/*
++ * _dcd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== _dcd.h ========
++ *  Description:
++ *      Includes the wrapper functions called directly by the
++ *      DeviceIOControl interface.
++ *
++ *  Public Functions:
++ *      WCD_CallDevIOCtl
++ *      WCD_Init
++ *      WCD_InitComplete2
++ *      WCD_Exit
++ *      <MOD>WRAP_*
++ *
++ *  Notes:
++ *      Compiled with CDECL calling convention.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb  Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb  Added the Dynamic Memory Mapping feature
++ *! 30-Jan-2002 ag  Renamed CMMWRAP_AllocBuf to CMMWRAP_CallocBuf.
++ *! 22-Nov-2000 kc: Added MGRWRAP_GetPerf_Data to acquire PERF stats.
++ *! 27-Oct-2000 jeh Added NODEWRAP_AllocMsgBuf, NODEWRAP_FreeMsgBuf. Removed
++ *!                 NODEWRAP_GetMessageStream.
++ *! 10-Oct-2000 ag: Added user CMM wrappers.
++ *! 04-Aug-2000 rr: MEMWRAP and UTIL_Wrap added.
++ *! 27-Jul-2000 rr: NODEWRAP, STRMWRAP added.
++ *! 27-Jun-2000 rr: MGRWRAP fxns added.IFDEF to build for PM or DSP/BIOS Bridge
++ *! 03-Dec-1999 rr: WCD_InitComplete2 enabled for BRD_AutoStart.
++ *! 09-Nov-1999 kc: Added MEMRY.
++ *! 02-Nov-1999 ag: Added CHNL.
++ *! 08-Oct-1999 rr: Utilwrap_Testdll fxn added
++ *! 24-Sep-1999 rr: header changed from _wcd.h to _dcd.h
++ *! 09-Sep-1997 gp: Created.
++ */
++
++#ifndef _WCD_
++#define _WCD_
++
++#include <dspbridge/wcdioctl.h>
++
++/*
++ *  ======== WCD_CallDevIOCtl ========
++ *  Purpose:
++ *      Call the (wrapper) function for the corresponding WCD IOCTL.
++ *  Parameters:
++ *      cmd:        IOCTL id, base 0.
++ *      args:       Argument structure.
++ *      pResult:
++ *  Returns:
++ *      DSP_SOK if command called; DSP_EINVALIDARG if command not in IOCTL
++ *      table.
++ *  Requires:
++ *  Ensures:
++ */
++      extern DSP_STATUS WCD_CallDevIOCtl(unsigned int cmd,
++                                         union Trapped_Args *args,
++                                         u32 *pResult);
++
++/*
++ *  ======== WCD_Init ========
++ *  Purpose:
++ *      Initialize WCD modules, and export WCD services to WMD's.
++ *      This procedure is called when the class driver is loaded.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if success; FALSE otherwise.
++ *  Requires:
++ *  Ensures:
++ */
++      extern bool WCD_Init(void);
++
++/*
++ *  ======== WCD_InitComplete2 ========
++ *  Purpose:
++ *      Perform any required WCD, and WMD initialization which
++ *      cannot not be performed in WCD_Init(void) or DEV_StartDevice() due
++ *      to the fact that some services are not yet
++ *      completely initialized.
++ *  Parameters:
++ *  Returns:
++ *      DSP_SOK:        Allow this device to load
++ *      DSP_EFAIL:      Failure.
++ *  Requires:
++ *      WCD initialized.
++ *  Ensures:
++ */
++      extern DSP_STATUS WCD_InitComplete2(void);
++
++/*
++ *  ======== WCD_Exit ========
++ *  Purpose:
++ *      Exit all modules initialized in WCD_Init(void).
++ *      This procedure is called when the class driver is unloaded.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      WCD_Init(void) was previously called.
++ *  Ensures:
++ *      Resources acquired in WCD_Init(void) are freed.
++ */
++      extern void WCD_Exit(void);
++
++/* MGR wrapper functions */
++      extern u32 MGRWRAP_EnumNode_Info(union Trapped_Args *args);
++      extern u32 MGRWRAP_EnumProc_Info(union Trapped_Args *args);
++      extern u32 MGRWRAP_RegisterObject(union Trapped_Args *args);
++      extern u32 MGRWRAP_UnregisterObject(union Trapped_Args *args);
++      extern u32 MGRWRAP_WaitForBridgeEvents(union Trapped_Args *args);
++
++#ifndef RES_CLEANUP_DISABLE
++      extern u32 MGRWRAP_GetProcessResourcesInfo(union Trapped_Args *args);
++#endif
++
++
++/* CPRC (Processor) wrapper Functions */
++      extern u32 PROCWRAP_Attach(union Trapped_Args *args);
++      extern u32 PROCWRAP_Ctrl(union Trapped_Args *args);
++      extern u32 PROCWRAP_Detach(union Trapped_Args *args);
++      extern u32 PROCWRAP_EnumNode_Info(union Trapped_Args *args);
++      extern u32 PROCWRAP_EnumResources(union Trapped_Args *args);
++      extern u32 PROCWRAP_GetState(union Trapped_Args *args);
++      extern u32 PROCWRAP_GetTrace(union Trapped_Args *args);
++      extern u32 PROCWRAP_Load(union Trapped_Args *args);
++      extern u32 PROCWRAP_RegisterNotify(union Trapped_Args *args);
++      extern u32 PROCWRAP_Start(union Trapped_Args *args);
++      extern u32 PROCWRAP_ReserveMemory(union Trapped_Args *args);
++      extern u32 PROCWRAP_UnReserveMemory(union Trapped_Args *args);
++      extern u32 PROCWRAP_Map(union Trapped_Args *args);
++      extern u32 PROCWRAP_UnMap(union Trapped_Args *args);
++      extern u32 PROCWRAP_FlushMemory(union Trapped_Args *args);
++      extern u32 PROCWRAP_Stop(union Trapped_Args *args);
++      extern u32 PROCWRAP_InvalidateMemory(union Trapped_Args *args);
++
++/* NODE wrapper functions */
++      extern u32 NODEWRAP_Allocate(union Trapped_Args *args);
++      extern u32 NODEWRAP_AllocMsgBuf(union Trapped_Args *args);
++      extern u32 NODEWRAP_ChangePriority(union Trapped_Args *args);
++      extern u32 NODEWRAP_Connect(union Trapped_Args *args);
++      extern u32 NODEWRAP_Create(union Trapped_Args *args);
++      extern u32 NODEWRAP_Delete(union Trapped_Args *args);
++      extern u32 NODEWRAP_FreeMsgBuf(union Trapped_Args *args);
++      extern u32 NODEWRAP_GetAttr(union Trapped_Args *args);
++      extern u32 NODEWRAP_GetMessage(union Trapped_Args *args);
++      extern u32 NODEWRAP_Pause(union Trapped_Args *args);
++      extern u32 NODEWRAP_PutMessage(union Trapped_Args *args);
++      extern u32 NODEWRAP_RegisterNotify(union Trapped_Args *args);
++      extern u32 NODEWRAP_Run(union Trapped_Args *args);
++      extern u32 NODEWRAP_Terminate(union Trapped_Args *args);
++      extern u32 NODEWRAP_GetUUIDProps(union Trapped_Args *args);
++
++/* STRM wrapper functions */
++      extern u32 STRMWRAP_AllocateBuffer(union Trapped_Args *args);
++      extern u32 STRMWRAP_Close(union Trapped_Args *args);
++      extern u32 STRMWRAP_FreeBuffer(union Trapped_Args *args);
++      extern u32 STRMWRAP_GetEventHandle(union Trapped_Args *args);
++      extern u32 STRMWRAP_GetInfo(union Trapped_Args *args);
++      extern u32 STRMWRAP_Idle(union Trapped_Args *args);
++      extern u32 STRMWRAP_Issue(union Trapped_Args *args);
++      extern u32 STRMWRAP_Open(union Trapped_Args *args);
++      extern u32 STRMWRAP_Reclaim(union Trapped_Args *args);
++      extern u32 STRMWRAP_RegisterNotify(union Trapped_Args *args);
++      extern u32 STRMWRAP_Select(union Trapped_Args *args);
++
++      extern u32 CMMWRAP_CallocBuf(union Trapped_Args *args);
++      extern u32 CMMWRAP_FreeBuf(union Trapped_Args *args);
++      extern u32 CMMWRAP_GetHandle(union Trapped_Args *args);
++      extern u32 CMMWRAP_GetInfo(union Trapped_Args *args);
++
++#endif                                /* _WCD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/brddefs.h b/arch/arm/plat-omap/include/dspbridge/brddefs.h
+new file mode 100644
+index 0000000..c62388c
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/brddefs.h
+@@ -0,0 +1,54 @@
++/*
++ * brddefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== brddefs.h ========
++ *  Description:
++ *      Global BRD constants and types, shared between WSX, WCD, and WMD.
++ *
++ *! Revision History:
++ *! ================
++ *! 31-Jan-2000 rr: Comment Exec changed to Monitor
++ *! 22-Jul-1999 jeh Added BRD_LOADED state.
++ *! 26-Mar-1997 gp: Added BRD_SYNCINIT state.
++ *! 11-Dec-1996 cr: Added BRD_LASTSTATE definition.
++ *! 11-Jul-1996 gp: Added missing u32 callback argument to BRD_CALLBACK.
++ *! 10-Jun-1996 gp: Created from board.h and brd.h.
++ */
++
++#ifndef BRDDEFS_
++#define BRDDEFS_
++
++/* platform status values */
++#define BRD_STOPPED     0x0   /* No Monitor Loaded, Not running. */
++#define BRD_IDLE        0x1   /* Monitor Loaded, but suspended.  */
++#define BRD_RUNNING     0x2   /* Monitor loaded, and executing.  */
++#define BRD_UNKNOWN     0x3   /* Board state is indeterminate. */
++#define BRD_SYNCINIT    0x4
++#define BRD_LOADED      0x5
++#define BRD_LASTSTATE   BRD_LOADED    /* Set to highest legal board state. */
++#define BRD_SLEEP_TRANSITION 0x6      /* Sleep transition in progress  */
++#define BRD_HIBERNATION 0x7           /* MPU initiated hibernation */
++#define BRD_RETENTION     0x8       /* Retention mode */
++#define BRD_DSP_HIBERNATION     0x9       /* DSP initiated hibernation */
++#define BRD_ERROR             0xA       /* Board state is Error */
++      typedef u32 BRD_STATUS;
++
++/* BRD Object */
++      struct BRD_OBJECT;
++
++#endif                                /* BRDDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cfg.h b/arch/arm/plat-omap/include/dspbridge/cfg.h
+new file mode 100644
+index 0000000..68db842
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cfg.h
+@@ -0,0 +1,339 @@
++/*
++ * cfg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== cfg.h ========
++ *  Purpose:
++ *      PM Configuration module.
++ *
++ *  Private Functions:
++ *      CFG_Exit
++ *      CFG_GetAutoStart
++ *      CFG_GetCDVersion
++ *      CFG_GetDevObject
++ *      CFG_GetDSPResources
++ *      CFG_GetExecFile
++ *      CFG_GetHostResources
++ *      CFG_GetObject
++ *      CFG_GetPerfValue
++ *      CFG_GetWMDFileName
++ *      CFG_GetZLFile
++ *      CFG_Init
++ *      CFG_SetDevObject
++ *      CFG_SetObject
++ *
++ *! Revision History:
++ *! =================
++ *! 26-Feb-2003 kc  Removed unused CFG fxns.
++ *! 28-Aug-2001 jeh  Added CFG_GetLoaderName.
++ *! 26-Jul-2000 rr:  Added CFG_GetDCDName to retrieve the DCD Dll name.
++ *! 13-Jul-2000 rr:  Added CFG_GetObject & CFG_SetObject.
++ *! 13-Jan-2000 rr:  CFG_Get/SetPrivateDword renamed to CFG_Get/SetDevObject.
++ *!                  CFG_GetWinBRIDGEDir/Directory,CFG_GetSearchPath removed.
++ *! 15-Jan-1998 cr:  Code review cleanup.
++ *! 16-Aug-1997 cr:  Added explicit cdecl identifiers.
++ *! 12-Dec-1996 gp:  Moved CFG_FindInSearchPath to CSP module.
++ *! 13-Sep-1996 gp:  Added CFG_GetBoardName().
++ *! 22-Jul-1996 gp:  Added CFG_GetTraceStr, to retrieve an initial GT trace.
++ *! 26-Jun-1996 cr:  Added CFG_FindInSearchPath.
++ *! 25-Jun-1996 cr:  Added CFG_GetWinSPOXDir.
++ *! 17-Jun-1996 cr:  Added CFG_GetDevNode.
++ *! 11-Jun-1996 cr:  Cleaned up for code review.
++ *! 07-Jun-1996 cr:  Added CFG_GetExecFile and CFG_GetZLFileName functions.
++ *! 04-Jun-1996 gp:  Added AutoStart regkey and accessor function.  Placed
++ *!                  OUT parameters in accessor function param. lists at end.
++ *! 29-May-1996 gp:  Moved DEV_HDEVNODE to here and renamed CFG_HDEVNODE.
++ *! 22-May-1996 cr:  Added GetHostResources, GetDSPResources, and
++ *!                  GetWMDFileName services.
++ *! 18-May-1996 gp:  Created.
++ */
++
++#ifndef CFG_
++#define CFG_
++#include <dspbridge/host_os.h>
++#include <dspbridge/cfgdefs.h>
++
++/*
++ *  ======== CFG_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the CFG module.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      CFG_Init(void) was previously called.
++ *  Ensures:
++ *      Resources acquired in CFG_Init(void) are freed.
++ */
++      extern void CFG_Exit(void);
++
++/*
++ *  ======== CFG_GetAutoStart ========
++ *  Purpose:
++ *      Retreive the autostart mask, if any, for this board.
++ *  Parameters:
++ *      hDevNode:       Handle to the DevNode who's WMD we are querying.
++ *      pdwAutoStart:   Ptr to location for 32 bit autostart mask.
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      CFG_E_INVALIDHDEVNODE:  hDevNode is invalid.
++ *      CFG_E_RESOURCENOTAVAIL: Unable to retreive resource.
++ *  Requires:
++ *      CFG initialized.
++ *  Ensures:
++ *      DSP_SOK:        *pdwAutoStart contains autostart mask for this devnode.
++ */
++      extern DSP_STATUS CFG_GetAutoStart(IN struct CFG_DEVNODE *hDevNode,
++                                         OUT u32 *pdwAutoStart);
++
++/*
++ *  ======== CFG_GetCDVersion ========
++ *  Purpose:
++ *      Retrieves the version of the PM Class Driver.
++ *  Parameters:
++ *      pdwVersion: Ptr to u32 to contain version number upon return.
++ *  Returns:
++ *      DSP_SOK:    Success.  pdwVersion contains Class Driver version in
++ *                  the form: 0xAABBCCDD where AABB is Major version and
++ *                  CCDD is Minor.
++ *      DSP_EFAIL:  Failure.
++ *  Requires:
++ *      CFG initialized.
++ *  Ensures:
++ *      DSP_SOK:    Success.
++ *      else:       *pdwVersion is NULL.
++ */
++      extern DSP_STATUS CFG_GetCDVersion(OUT u32 *pdwVersion);
++
++/*
++ *  ======== CFG_GetDevObject ========
++ *  Purpose:
++ *      Retrieve the Device Object handle for a given devnode.
++ *  Parameters:
++ *      hDevNode:       Platform's DevNode handle from which to retrieve value.
++ *      pdwValue:       Ptr to location to store the value.
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      CFG_E_INVALIDHDEVNODE:  hDevNode is invalid.
++ *      CFG_E_INVALIDPOINTER:   phDevObject is invalid.
++ *      CFG_E_RESOURCENOTAVAIL: The resource is not available.
++ *  Requires:
++ *      CFG initialized.
++ *  Ensures:
++ *      DSP_SOK:    *pdwValue is set to the retrieved u32.
++ *      else:       *pdwValue is set to 0L.
++ */
++      extern DSP_STATUS CFG_GetDevObject(IN struct CFG_DEVNODE *hDevNode,
++                                         OUT u32 *pdwValue);
++
++/*
++ *  ======== CFG_GetDSPResources ========
++ *  Purpose:
++ *      Get the DSP resources available to a given device.
++ *  Parameters:
++ *      hDevNode:       Handle to the DEVNODE who's resources we are querying.
++ *      pDSPResTable:   Ptr to a location to store the DSP resource table.
++ *  Returns:
++ *      DSP_SOK:                On success.
++ *      CFG_E_INVALIDHDEVNODE:  hDevNode is invalid.
++ *      CFG_E_RESOURCENOTAVAIL: The DSP Resource information is not
++ *                              available
++ *  Requires:
++ *      CFG initialized.
++ *  Ensures:
++ *      DSP_SOK:    pDSPResTable points to a filled table of resources allocated
++ *                  for the specified WMD.
++ */
++      extern DSP_STATUS CFG_GetDSPResources(IN struct CFG_DEVNODE *hDevNode,
++                                    OUT struct CFG_DSPRES *pDSPResTable);
++
++
++/*
++ *  ======== CFG_GetExecFile ========
++ *  Purpose:
++ *      Retreive the default executable, if any, for this board.
++ *  Parameters:
++ *      hDevNode:       Handle to the DevNode who's WMD we are querying.
++ *      cBufSize:       Size of buffer.
++ *      pstrExecFile:   Ptr to character buf to hold ExecFile.
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      CFG_E_INVALIDHDEVNODE:  hDevNode is invalid.
++ *      CFG_E_INVALIDPOINTER:   pstrExecFile is invalid.
++ *      CFG_E_RESOURCENOTAVAIL: The resource is not available.
++ *  Requires:
++ *      CFG initialized.
++ *  Ensures:
++ *      DSP_SOK:    Not more than cBufSize bytes were copied into pstrExecFile,
++ *                  and *pstrExecFile contains default executable for this
++ *                  devnode.
++ */
++      extern DSP_STATUS CFG_GetExecFile(IN struct CFG_DEVNODE *hDevNode,
++                                        IN u32 cBufSize,
++                                        OUT char *pstrExecFile);
++
++/*
++ *  ======== CFG_GetHostResources ========
++ *  Purpose:
++ *      Get the Host PC allocated resources assigned to a given device.
++ *  Parameters:
++ *      hDevNode:       Handle to the DEVNODE who's resources we are querying.
++ *      pHostResTable:  Ptr to a location to store the host resource table.
++ *  Returns:
++ *      DSP_SOK:                On success.
++ *      CFG_E_INVALIDPOINTER:   pHostResTable is invalid.
++ *      CFG_E_INVALIDHDEVNODE:  hDevNode is invalid.
++ *      CFG_E_RESOURCENOTAVAIL: The resource is not available.
++ *  Requires:
++ *      CFG initialized.
++ *  Ensures:
++ *      DSP_SOK:    pHostResTable points to a filled table of resources
++ *                  allocated for the specified WMD.
++ *
++ */
++      extern DSP_STATUS CFG_GetHostResources(IN struct CFG_DEVNODE *hDevNode,
++                                     OUT struct CFG_HOSTRES *pHostResTable);
++
++/*
++ *  ======== CFG_GetObject ========
++ *  Purpose:
++ *      Retrieve the Driver Object handle From the Registry
++ *  Parameters:
++ *      pdwValue:   Ptr to location to store the value.
++ *      dwType      Type of Object to Get
++ *  Returns:
++ *      DSP_SOK:    Success.
++ *  Requires:
++ *      CFG initialized.
++ *  Ensures:
++ *      DSP_SOK:    *pdwValue is set to the retrieved u32(non-Zero).
++ *      else:       *pdwValue is set to 0L.
++ */
++      extern DSP_STATUS CFG_GetObject(OUT u32 *pdwValue, u32 dwType);
++
++/*
++ *  ======== CFG_GetPerfValue ========
++ *  Purpose:
++ *      Retrieve a flag indicating whether PERF should log statistics for the
++ *      PM class driver.
++ *  Parameters:
++ *      pfEnablePerf:   Location to store flag.  0 indicates the key was
++ *                      not found, or had a zero value.  A nonzero value
++ *                      means the key was found and had a nonzero value.
++ *  Returns:
++ *  Requires:
++ *      pfEnablePerf != NULL;
++ *  Ensures:
++ */
++      extern void CFG_GetPerfValue(OUT bool *pfEnablePerf);
++
++/*
++ *  ======== CFG_GetWMDFileName ========
++ *  Purpose:
++ *    Get the mini-driver file name for a given device.
++ *  Parameters:
++ *      hDevNode:       Handle to the DevNode who's WMD we are querying.
++ *      cBufSize:       Size of buffer.
++ *      pWMDFileName:   Ptr to a character buffer to hold the WMD filename.
++ *  Returns:
++ *      DSP_SOK:                On success.
++ *      CFG_E_INVALIDHDEVNODE:  hDevNode is invalid.
++ *      CFG_E_RESOURCENOTAVAIL: The filename is not available.
++ *  Requires:
++ *      CFG initialized.
++ *  Ensures:
++ *      DSP_SOK:        Not more than cBufSize bytes were copied
++ *                      into pWMDFileName.
++ *
++ */
++      extern DSP_STATUS CFG_GetWMDFileName(IN struct CFG_DEVNODE *hDevNode,
++                                           IN u32 cBufSize,
++                                           OUT char *pWMDFileName);
++
++/*
++ *  ======== CFG_GetZLFile ========
++ *  Purpose:
++ *      Retreive the ZLFile, if any, for this board.
++ *  Parameters:
++ *      hDevNode:       Handle to the DevNode who's WMD we are querying.
++ *      cBufSize:       Size of buffer.
++ *      pstrZLFileName: Ptr to character buf to hold ZLFileName.
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      CFG_E_INVALIDPOINTER:   pstrZLFileName is invalid.
++ *      CFG_E_INVALIDHDEVNODE:  hDevNode is invalid.
++ *      CFG_E_RESOURCENOTAVAIL: couldn't find the ZLFileName.
++ *  Requires:
++ *      CFG initialized.
++ *  Ensures:
++ *      DSP_SOK:    Not more than cBufSize bytes were copied into
++ *                  pstrZLFileName, and *pstrZLFileName contains ZLFileName
++ *                  for this devnode.
++ */
++      extern DSP_STATUS CFG_GetZLFile(IN struct CFG_DEVNODE *hDevNode,
++                                      IN u32 cBufSize,
++                                      OUT char *pstrZLFileName);
++
++/*
++ *  ======== CFG_Init ========
++ *  Purpose:
++ *      Initialize the CFG module's private state.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialized; FALSE if error occured.
++ *  Requires:
++ *  Ensures:
++ *      A requirement for each of the other public CFG functions.
++ */
++      extern bool CFG_Init(void);
++
++/*
++ *  ======== CFG_SetDevObject ========
++ *  Purpose:
++ *      Store the Device Object handle for a given devnode.
++ *  Parameters:
++ *      hDevNode:   Platform's DevNode handle we are storing value with.
++ *      dwValue:    Arbitrary value to store.
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      CFG_E_INVALIDHDEVNODE:  hDevNode is invalid.
++ *      DSP_EFAIL:              Internal Error.
++ *  Requires:
++ *      CFG initialized.
++ *  Ensures:
++ *      DSP_SOK:    The Private u32 was successfully set.
++ */
++      extern DSP_STATUS CFG_SetDevObject(IN struct CFG_DEVNODE *hDevNode,
++                                         IN u32 dwValue);
++
++/*
++ *  ======== CFG_SetDrvObject ========
++ *  Purpose:
++ *      Store the Driver Object handle.
++ *  Parameters:
++ *      dwValue:        Arbitrary value to store.
++ *      dwType          Type of Object to Store
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Internal Error.
++ *  Requires:
++ *      CFG initialized.
++ *  Ensures:
++ *      DSP_SOK:        The Private u32 was successfully set.
++ */
++      extern DSP_STATUS CFG_SetObject(IN u32 dwValue, IN u32 dwType);
++
++#endif                                /* CFG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cfgdefs.h b/arch/arm/plat-omap/include/dspbridge/cfgdefs.h
+new file mode 100644
+index 0000000..4f78d82
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cfgdefs.h
+@@ -0,0 +1,126 @@
++/*
++ * cfgdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== cfgdefs.h ========
++ *  Purpose:
++ *      Global CFG constants and types, shared between class and mini driver.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 kc  Removed wIOPort* in CFG_HOSTRES.
++ *! 06-Sep-2000 jeh Added channel info to CFG_HOSTRES.
++ *! 09-May-2000 rr: CFG_HOSTRES now support multiple windows for PCI support.
++ *! 31-Jan-2000 rr: Comments changed after code review.
++ *! 06-Jan-2000 rr: Bus Type included in CFG_HOSTRES.
++ *! 12-Nov-1999 rr: CFG_HOSTRES member names changed.
++ *! 25-Oct-1999 rr: Modified the CFG_HOSTRES Structure
++ *!                 PCMCIA ISR Register/Unregister fxn removed..
++ *!                 New flag PCCARD introduced during compile time.
++ *! 10-Sep-1999 ww: Added PCMCIA ISR Register/Unregister fxn.
++ *! 01-Sep-1999 ag: Removed NT/95 specific fields in CFG_HOSTRES
++ *! 27-Oct-1997 cr: Updated CFG_HOSTRES struct to support 1+ IRQs per board.
++ *! 17-Sep-1997 gp: Tacked some NT config info to end of CFG_HOSTRES structure.
++ *! 12-Dec-1996 cr: Cleaned up after code review.
++ *! 14-Nov-1996 gp: Renamed from wsxcfg.h
++ *! 19-Jun-1996 cr: Created.
++ */
++
++#ifndef CFGDEFS_
++#define CFGDEFS_
++
++/* Maximum length of module search path. */
++#define CFG_MAXSEARCHPATHLEN    255
++
++/* Maximum length of general paths. */
++#define CFG_MAXPATH             255
++
++/* Host Resources:  */
++#define CFG_MAXMEMREGISTERS     9
++#define CFG_MAXIOPORTS          20
++#define CFG_MAXIRQS             7
++#define CFG_MAXDMACHANNELS      7
++
++/* IRQ flag */
++#define CFG_IRQSHARED           0x01  /* IRQ can be shared */
++
++/* DSP Resources: */
++#define CFG_DSPMAXMEMTYPES      10
++#define CFG_DEFAULT_NUM_WINDOWS 1     /* We support only one window. */
++
++/* A platform-related device handle: */
++      struct CFG_DEVNODE;
++
++/*
++ *  Host resource structure.
++ */
++      struct CFG_HOSTRES {
++              u32 wNumMemWindows;     /* Set to default */
++              /* This is the base.memory */
++              u32 dwMemBase[CFG_MAXMEMREGISTERS];  /* SHM virtual address */
++              u32 dwMemLength[CFG_MAXMEMREGISTERS]; /* Length of the Base */
++              u32 dwMemPhys[CFG_MAXMEMREGISTERS]; /* SHM Physical address */
++              u8 bIRQRegisters;       /* IRQ Number */
++              u8 bIRQAttrib;  /* IRQ Attribute */
++              u32 dwOffsetForMonitor; /* The Shared memory starts from
++                                       * dwMemBase + this offset */
++              u32 dwBusType;  /* Bus type for this device */
++              u32 dwProgBase; /* DSP ProgBase */
++              u32 dwProgLength;       /* DSP ProgBase Length */
++              u32 dwRegBase;  /* DSP memory mapped register base */
++              u32 dwRegLength;        /* DSP Register Base Length */
++              u32 ClientHandle;       /* Client Handle */
++              u32 SocketHandle;       /* Socket and Function Pair */
++              u32 CardInfo;   /* This will be used as a context data in
++                               * in the CardRequestIRQ */
++      /*
++       *  Info needed by NODE for allocating channels to communicate with RMS:
++       *      dwChnlOffset:       Offset of RMS channels. Lower channels are
++       *                          reserved.
++       *      dwChnlBufSize:      Size of channel buffer to send to RMS
++       *      dwNumChnls:       Total number of channels (including reserved).
++       */
++              u32 dwChnlOffset;
++              u32 dwChnlBufSize;
++              u32 dwNumChnls;
++              u32 dwPrmBase;
++              u32 dwCmBase;
++              u32 dwPerBase;
++               u32 dwPerPmBase;
++               u32 dwCorePmBase;
++              u32 dwWdTimerDspBase;
++              u32 dwMboxBase;
++              u32 dwDmmuBase;
++              u32 dwDipiBase;
++              u32 dwSysCtrlBase;
++      } ;
++
++      struct CFG_DSPMEMDESC {
++              u32 uMemType;   /* Type of memory.                        */
++              u32 ulMin;      /* Minimum amount of memory of this type. */
++              u32 ulMax;      /* Maximum amount of memory of this type. */
++      } ;
++
++      struct CFG_DSPRES {
++              u32 uChipType;  /* DSP chip type.               */
++              u32 uWordSize;  /* Number of bytes in a word    */
++              u32 cChips;     /* Number of chips.             */
++              u32 cMemTypes;  /* Types of memory.             */
++              struct CFG_DSPMEMDESC aMemDesc[CFG_DSPMAXMEMTYPES];
++              /* DSP Memory types */
++      } ;
++
++#endif                                /* CFGDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnl.h b/arch/arm/plat-omap/include/dspbridge/chnl.h
+new file mode 100644
+index 0000000..f39e3f4
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnl.h
+@@ -0,0 +1,170 @@
++/*
++ * chnl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== chnl.h ========
++ *  Description:
++ *      WCD channel interface: multiplexes data streams through the single
++ *      physical link managed by a mini-driver.
++ *
++ *  Public Functions:
++ *      CHNL_AddIOReq
++ *      CHNL_AllocBuffer
++ *      CHNL_CancelIO
++ *      CHNL_Close
++ *      CHNL_CloseOrphans
++ *      CHNL_Create
++ *      CHNL_Destroy
++ *      CHNL_Exit
++ *      CHNL_FlushIO
++ *      CHNL_FreeBuffer
++ *      CHNL_GetEventHandle
++ *      CHNL_GetHandle
++ *      CHNL_GetIOCompletion
++ *      CHNL_GetId
++ *      CHNL_GetMgr
++ *      CHNL_GetMode
++ *      CHNL_GetPosition
++ *      CHNL_GetProcessHandle
++ *      CHNL_Init
++ *      CHNL_Open
++ *
++ *  Notes:
++ *      See DSP API chnl.h for more details.
++ *
++ *! Revision History:
++ *! ================
++ *! 14-Jan-1997 gp: Updated based on code review feedback.
++ *! 24-Oct-1996 gp: Move CloseOrphans into here from dspsys.
++ *! 09-Sep-1996 gp: Added CHNL_GetProcessID() and CHNL_GetHandle().
++ *! 10-Jul-1996 gp: Created.
++ */
++
++#ifndef CHNL_
++#define CHNL_
++
++#include <dspbridge/chnlpriv.h>
++
++/*
++ *  ======== CHNL_Close ========
++ *  Purpose:
++ *      Ensures all pending I/O on this channel is cancelled, discards all
++ *      queued I/O completion notifications, then frees the resources allocated
++ *      for this channel, and makes the corresponding logical channel id
++ *      available for subsequent use.
++ *  Parameters:
++ *      hChnl:          Channel object handle.
++ *  Returns:
++ *      DSP_SOK:        Success;
++ *      DSP_EHANDLE:    Invalid hChnl.
++ *  Requires:
++ *      CHNL_Init(void) called.
++ *      No thread must be blocked on this channel's I/O completion event.
++ *  Ensures:
++ *      DSP_SOK:        The I/O completion event for this channel is freed.
++ *                      hChnl is no longer valid.
++ */
++      extern DSP_STATUS CHNL_Close(struct CHNL_OBJECT *hChnl);
++
++
++/*
++ *  ======== CHNL_Create ========
++ *  Purpose:
++ *      Create a channel manager object, responsible for opening new channels
++ *      and closing old ones for a given board.
++ *  Parameters:
++ *      phChnlMgr:      Location to store a channel manager object on output.
++ *      hDevObject:     Handle to a device object.
++ *      pMgrAttrs:      Channel manager attributes.
++ *      pMgrAttrs->cChannels:   Max channels
++ *      pMgrAttrs->bIRQ:        Channel's I/O IRQ number.
++ *      pMgrAttrs->fShared:     TRUE if the IRQ is shareable.
++ *      pMgrAttrs->uWordSize:   DSP Word size in equivalent PC bytes..
++ *  Returns:
++ *      DSP_SOK:                Success;
++ *      DSP_EHANDLE:            hDevObject is invalid.
++ *      DSP_EINVALIDARG:        cChannels is 0.
++ *      DSP_EMEMORY:            Insufficient memory for requested resources.
++ *      CHNL_E_ISR:             Unable to plug channel ISR for configured IRQ.
++ *      CHNL_E_MAXCHANNELS:     This manager cannot handle this many channels.
++ *      CHNL_E_INVALIDIRQ:      Invalid IRQ number. Must be 0 <= bIRQ <= 15.
++ *      CHNL_E_INVALIDWORDSIZE: Invalid DSP word size.  Must be > 0.
++ *      CHNL_E_INVALIDMEMBASE:  Invalid base address for DSP communications.
++ *      CHNL_E_MGREXISTS:       Channel manager already exists for this device.
++ *  Requires:
++ *      CHNL_Init(void) called.
++ *      phChnlMgr != NULL.
++ *      pMgrAttrs != NULL.
++ *  Ensures:
++ *      DSP_SOK:                Subsequent calls to CHNL_Create() for the same
++ *                              board without an intervening call to
++ *                              CHNL_Destroy() will fail.
++ */
++      extern DSP_STATUS CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++                                    struct DEV_OBJECT *hDevObject,
++                                    IN CONST struct CHNL_MGRATTRS *pMgrAttrs);
++
++/*
++ *  ======== CHNL_Destroy ========
++ *  Purpose:
++ *      Close all open channels, and destroy the channel manager.
++ *  Parameters:
++ *      hChnlMgr:           Channel manager object.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EHANDLE:        hChnlMgr was invalid.
++ *  Requires:
++ *      CHNL_Init(void) called.
++ *  Ensures:
++ *      DSP_SOK:            Cancels I/O on each open channel.
++ *                          Closes each open channel.
++ *                          CHNL_Create may subsequently be called for the
++ *                          same board.
++ */
++      extern DSP_STATUS CHNL_Destroy(struct CHNL_MGR *hChnlMgr);
++
++/*
++ *  ======== CHNL_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the CHNL module.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      CHNL_Init(void) previously called.
++ *  Ensures:
++ *      Resources, if any acquired in CHNL_Init(void), are freed when the last
++ *      client of CHNL calls CHNL_Exit(void).
++ */
++      extern void CHNL_Exit(void);
++
++
++/*
++ *  ======== CHNL_Init ========
++ *  Purpose:
++ *      Initialize the CHNL module's private state.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialized; FALSE if error occurred.
++ *  Requires:
++ *  Ensures:
++ *      A requirement for each of the other public CHNL functions.
++ */
++      extern bool CHNL_Init(void);
++
++
++
++#endif                                /* CHNL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnl_sm.h b/arch/arm/plat-omap/include/dspbridge/chnl_sm.h
+new file mode 100644
+index 0000000..789b9bd
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnl_sm.h
+@@ -0,0 +1,168 @@
++/*
++ * chnl_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== chnl_sm.h ========
++ *  Description:
++ *      Prototypes for channel lower edge functions for a WinBRIDGE mini driver
++ *      implementing data transfer via shared memory.
++ *
++ *  Public Functions:
++ *      CHNLSM_DisableInterrupt;
++ *      CHNLSM_EnableInterrupt;
++ *      CHNLSM_ISR;
++ *      CHNLSM_Read;
++ *      CHNLSM_UpdateSHMLength;
++ *      CHNLSM_Write;
++ *
++ *  Notes:
++ *      These lower edge functions must be implemented by the WMD writer.
++ *      Currently, CHNLSM_Read() and CHNLSM_Write() are not called, but must
++ *      be defined to link.
++ *
++ */
++
++#ifndef CHNLSM_
++#define CHNLSM_
++
++#include <dspbridge/wmd.h>
++
++/*
++ *  ======== CHNLSM_DisableInterrupt ========
++ *  Purpose:
++ *      Disable interrupts from the DSP board to the PC.
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device info.
++ *  Returns:
++ *  Requires:
++ *  Ensures:
++ */
++       extern DSP_STATUS CHNLSM_DisableInterrupt(struct WMD_DEV_CONTEXT*
++                                                      hDevContext);
++
++/*
++ *  ======== CHNLSM_EnableInterrupt ========
++ *  Purpose:
++ *      Enable interrupts from the DSP board to the PC.
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device info.
++ *  Returns:
++ *  Requires:
++ *  Ensures:
++ */
++       extern DSP_STATUS CHNLSM_EnableInterrupt(struct WMD_DEV_CONTEXT*
++                                                     hDevContext);
++
++/*
++ *  ======== CHNLSM_InterruptDSP2 ========
++ *  Purpose:
++ *      Set interrupt value & send an interrupt to the DSP processor(s).
++ *      This is typicaly used when mailbox interrupt mechanisms allow data
++ *      to be associated with interrupt such as for OMAP's CMD/DATA regs.
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device info.
++ *      wMbVal:         Value associated with interrupt(e.g. mailbox value).
++ *  Returns:
++ *      DSP_SOK:        Interrupt sent;
++ *      else:           Unable to send interrupt.
++ *  Requires:
++ *  Ensures:
++ */
++       extern DSP_STATUS CHNLSM_InterruptDSP2(struct WMD_DEV_CONTEXT*
++                                                   hDevContext, u16 wMbVal);
++
++/*
++ *  ======== CHNLSM_ISR ========
++ *  Purpose:
++ *      Mini-driver's ISR, called by WCD when the board interrupts the host.
++ *  Parameters:
++ *      hDevContext:    Handle to the mini-driver defined device info.
++ *      pfSchedDPC:     Set to TRUE to schedule a deferred procedure call
++ *                      to advance the channel protocol.  The channel class
++ *                      library will call the WMD's CHNLSM_DPC routine during
++ *                      its own DPC, before dispatching I/O.
++ *                      The channel class library should ignore *pfSchedDPC when
++ *                      CHNLSM_ISR returns FALSE.
++ *      pwMBRegVal:     Value of mailbox register.
++ *  Returns:
++ *      TRUE if this interrupt is was generated by the DSP board.
++ *      FALSE otherwise.
++ *  Requires:
++ *      Interrupts to the host processor are disabled on entry.
++ *      Must only call functions which are in page locked memory.
++ *      Must only call asynchronous OS services.
++ *      The EOI for this interrupt has already been sent to the PIC.
++ *  Ensures:
++ *      If the interrupt is *not* shared, this routine must return TRUE.
++ */
++       extern bool CHNLSM_ISR(struct WMD_DEV_CONTEXT *hDevContext,
++                                   OUT bool *pfSchedDPC,
++                                   OUT u16 *pwIntrVal);
++
++/*
++ *  ======== CHNLSM_Read ========
++ *  Purpose:
++ *      Read data from DSP board memory into a Host buffer.
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device info.
++ *      pHostBuf:       Pointer to host buffer (Destination).
++ *      dwDSPAddr:      Address on DSP board (Source).
++ *      ulNumBytes:     Number of bytes to transfer.
++ *  Returns:
++ *  Requires:
++ *  Ensures:
++ */
++       extern DSP_STATUS CHNLSM_Read(struct WMD_DEV_CONTEXT *hDevContext,
++                                          OUT u8 *pHostBuf,
++                                          u32 dwDSPAddr, u32 ulNumBytes);
++
++/*
++ *  ======== CHNLSM_UpdateSHMLength ========
++ *  Purpose:
++ *      Allow the minidriver a chance to override the SHM length as reported
++ *      to the mini driver (chnl_sm.lib) by Windows Plug and Play.
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device info.
++ *      pSHMLength:     Pointer to size of SHM window (in DSP words).
++ *  Returns:
++ *      TRUE if pSHMLength updated; FALSE otherwise.
++ *  Requires:
++ *      pSHMLength != NULL.
++ *  Ensures:
++ *      No more than sizeof(u32) bytes written to *pSHMLength
++ */
++      extern bool CHNLSM_UpdateSHMLength(struct WMD_DEV_CONTEXT *hDevContext,
++                                         IN OUT u32 *pSHMLength);
++
++/*
++ *  ======== CHNLSM_Write ========
++ *  Purpose:
++ *      Write data from a Host buffer to DSP board memory.
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device info.
++ *      pHostBuf:       Pointer to host buffer (Source).
++ *      dwDSPAddr:      Address on DSP board (Destination).
++ *      ulNumBytes:     Number of bytes to transfer.
++ *  Returns:
++ *  Requires:
++ *  Ensures:
++ */
++       extern DSP_STATUS CHNLSM_Write(struct WMD_DEV_CONTEXT *hDevContext,
++                                          IN u8 *pHostBuf,
++                                          u32 dwDSPAddr, u32 ulNumBytes);
++
++#endif                                /* CHNLSM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnldefs.h b/arch/arm/plat-omap/include/dspbridge/chnldefs.h
+new file mode 100644
+index 0000000..9f59229
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnldefs.h
+@@ -0,0 +1,92 @@
++/*
++ * chnldefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== chnldefs.h ========
++ *  Purpose:
++ *      System-wide channel objects and constants.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Jan-2002 ag  Added cBufSize to IOC.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 02-Dec-1999 ag: Added new chnl attribute pstrEventName.
++ *! 12-Nov-1999 kc: Enabled hEvent attribute for tests.
++ *! 01-Nov-1999 ag: hEvent attribute not supported(yet).
++ *! 16-Jan-1997 gp: Moved private stuff into chnlpriv.h
++ *! 14-Jan-1997 gp: Updated based on code review feedback:
++ *!                 Removed CHNL_MODENOWAIT, CHNL_MODEDIRECT,
++ *! 03-Jan-1997 gp: Added channel class library types.
++ *! 14-Dec-1996 gp: Moved uChnlId field from CHNL_ATTRS to CHNL_Open().
++ *! 10-Dec-1996 gp: Added CHNL_IsTimedOut() macro.
++ *! 14-Nov-1996 gp: Renamed from wsxchnl.h.
++ *! 09-Sep-1996 gp: Added hReserved2 field to CHNL_ATTRS. Updated CHNL_INFO.
++ *! 10-Jul-1996 gp: Created from channel.h.
++ */
++
++#ifndef CHNLDEFS_
++#define CHNLDEFS_
++
++/* Channel id option. */
++#define CHNL_PICKFREE       (~0UL)    /* Let manager pick a free channel. */
++
++/* Channel manager limits: */
++#define CHNL_INITIOREQS      4        /* Default # of I/O requests.       */
++
++/* Channel modes */
++#define CHNL_MODETODSP       0x0000   /* Data streaming to the DSP.      */
++#define CHNL_MODEFROMDSP     0x0001   /* Data streaming from the DSP.    */
++
++/* GetIOCompletion flags */
++#define CHNL_IOCINFINITE     0xffffffff       /* Wait forever for IO completion. */
++#define CHNL_IOCNOWAIT       0x0      /* Dequeue an IOC, if available.   */
++
++/* IO Completion Record status: */
++#define CHNL_IOCSTATCOMPLETE 0x0000   /* IO Completed.             */
++#define CHNL_IOCSTATCANCEL   0x0002   /* IO was cancelled          */
++#define CHNL_IOCSTATTIMEOUT  0x0008   /* Wait for IOC timed out.   */
++#define CHNL_IOCSTATEOS      0x8000   /* End Of Stream reached.    */
++
++/* Macros for checking I/O Completion status: */
++#define CHNL_IsEOS(ioc)         (ioc.status & CHNL_IOCSTATEOS)
++#define CHNL_IsIOComplete(ioc)  (!(ioc.status & ~CHNL_IOCSTATEOS))
++#define CHNL_IsIOCancelled(ioc) (ioc.status & CHNL_IOCSTATCANCEL)
++#define CHNL_IsTimedOut(ioc)    (ioc.status & CHNL_IOCSTATTIMEOUT)
++
++/* CHNL types: */
++      typedef u32 CHNL_MODE;  /* Channel transfer mode.         */
++
++/* Channel attributes: */
++      struct CHNL_ATTRS {
++              u32 uIOReqs;    /* Max # of preallocated I/O requests.    */
++              HANDLE hEvent;  /* User supplied auto-reset event object. */
++              char *pstrEventName;    /* Ptr to name of user event object.  */
++              HANDLE hReserved1;      /* Reserved for future use.         */
++              u32 hReserved2; /* Reserved for future use.        */
++
++      };
++
++/* I/O completion record: */
++      struct CHNL_IOC {
++              void *pBuf;     /* Buffer to be filled/emptied.           */
++              u32 cBytes;     /* Bytes transferred.                     */
++              u32 cBufSize;   /* Actual buffer size in bytes            */
++              u32 status;     /* Status of IO completion.               */
++              u32 dwArg;      /* User argument associated with pBuf.    */
++      } ;
++
++#endif                                /* CHNLDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnlpriv.h b/arch/arm/plat-omap/include/dspbridge/chnlpriv.h
+new file mode 100644
+index 0000000..fdcda24
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnlpriv.h
+@@ -0,0 +1,136 @@
++/*
++ * chnlpriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== chnlpriv.h ========
++ *  Description:
++ *      Private channel header shared between DSPSYS, WCD and WMD modules.
++ *
++ *  Public Functions:
++ *      None.
++ *
++ *  Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 05-Jan-2002 ag  Added cChannels(total # of chnls) to CHNL_MGRINFO struct.
++ *!                 Added private CHNL_[PCPY][ZCPY][DDMA].
++ *! 17-Nov-2000 jeh Removed IRQ, shared memory from CHNL_MGRATTRS, since these
++ *!                 now belong to IO_ATTRS.
++ *! 21-Jan-2000 ag: Code review comments added.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 11-Dec-1999 ag: Added CHNL_MAXLOCKPAGES for CHNL_PrepareBuffer().
++ *! 04-Dec-1999 ag: Added CHNL_MAXEVTNAMELEN for i/o compl named event support.
++ *! 01-Nov-1999 ag: CHNL_MAXCHANNELS set to 16 for 16-bit DSPs.
++ *! 27-Oct-1997 cr: Expanded CHNL_MAXIRQ from 0x0f to 0xff.
++ *! 16-Jan-1997 gp: Moved symbols into here from chnldefs.h.
++ *! 03-Jan-1997 gp: Added CHNL_MAXIRQ define.
++ *! 09-Dec-1996 gp: Removed CHNL_STATEIDLE.
++ *! 15-Jul-1996 gp: Created.
++ */
++
++#ifndef CHNLPRIV_
++#define CHNLPRIV_
++
++#include <dspbridge/chnldefs.h>
++#include <dspbridge/devdefs.h>
++#include <dspbridge/sync.h>
++
++/* CHNL Object validation signatures: */
++#define CHNL_MGRSIGNATURE   0x52474D43        /* "CMGR" (in reverse). */
++#define CHNL_SIGNATURE      0x4C4E4843        /* "CHNL" (in reverse). */
++
++/* Channel manager limits: */
++#define CHNL_MAXCHANNELS    32        /* Max channels available per transport */
++
++
++/*
++ *  Trans port channel Id definitions:(must match dsp-side).
++ *
++ *  For CHNL_MAXCHANNELS = 16:
++ *
++ *  ChnlIds:
++ *      0-15  (PCPY) - transport 0)
++ *      16-31 (DDMA) - transport 1)
++ *      32-47 (ZCPY) - transport 2)
++ */
++#define CHNL_PCPY       0     /* Proc-copy transport 0 */
++
++#define CHNL_MAXIRQ     0xff  /* Arbitrarily large number. */
++
++/* The following modes are private: */
++#define CHNL_MODEUSEREVENT  0x1000    /* User provided the channel event. */
++#define CHNL_MODEMASK       0x1001
++
++/* Higher level channel states: */
++#define CHNL_STATEREADY     0x0000    /* Channel ready for I/O.    */
++#define CHNL_STATECANCEL    0x0001    /* I/O was cancelled.        */
++#define CHNL_STATEEOS       0x0002    /* End Of Stream reached.    */
++
++/* Determine if user supplied an event for this channel:  */
++#define CHNL_IsUserEvent(mode)  (mode & CHNL_MODEUSEREVENT)
++
++/* Macros for checking mode: */
++#define CHNL_IsInput(mode)      (mode & CHNL_MODEFROMDSP)
++#define CHNL_IsOutput(mode)     (!CHNL_IsInput(mode))
++
++/* Types of channel class libraries: */
++#define CHNL_TYPESM         1 /* Shared memory driver. */
++#define CHNL_TYPEBM         2 /* Bus Mastering driver. */
++
++/* Max string length of channel I/O completion event name - change if needed */
++#define CHNL_MAXEVTNAMELEN  32
++
++/* Max memory pages lockable in CHNL_PrepareBuffer() - change if needed */
++#define CHNL_MAXLOCKPAGES   64
++
++/* Channel info.  */
++       struct CHNL_INFO {
++              struct CHNL_MGR *hChnlMgr;      /* Owning channel manager.   */
++              u32 dwID;       /* Channel ID.                            */
++              HANDLE hEvent;  /* Channel I/O completion event.          */
++              /*Abstraction of I/O completion event.*/
++              struct SYNC_OBJECT *hSyncEvent;
++              u32 dwMode;     /* Channel mode.                          */
++              u32 dwState;    /* Current channel state.                 */
++              u32 cPosition;  /* Total bytes transferred.        */
++              u32 cIOCs;      /* Number of IOCs in queue.               */
++              u32 cIOReqs;    /* Number of IO Requests in queue.        */
++               u32 hProcess;   /* Process owning this channel.     */
++              /*
++               * Name of channel I/O completion event. Not required in Linux
++               */
++              char szEventName[CHNL_MAXEVTNAMELEN + 1];
++      } ;
++
++/* Channel manager info: */
++      struct CHNL_MGRINFO {
++              u32 dwType;     /* Type of channel class library.         */
++              /* Channel handle, given the channel id. */
++              struct CHNL_OBJECT *hChnl;
++              u32 cOpenChannels;      /* Number of open channels.     */
++              u32 cChannels;  /* total # of chnls supported */
++      } ;
++
++/* Channel Manager Attrs: */
++      struct CHNL_MGRATTRS {
++              /* Max number of channels this manager can use. */
++              u32 cChannels;
++              u32 uWordSize;  /* DSP Word size.                       */
++      } ;
++
++#endif                                /* CHNLPRIV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/clk.h b/arch/arm/plat-omap/include/dspbridge/clk.h
+new file mode 100644
+index 0000000..4a23dab
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/clk.h
+@@ -0,0 +1,155 @@
++/*
++ * clk.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== clk.h ========
++ *  Purpose: Provides Clock functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 08-May-2007 rg: Moved all clock functions from sync module.
++ */
++
++#ifndef _CLK_H
++#define _CLK_H
++
++      /* Generic TIMER object: */
++      struct TIMER_OBJECT;
++      enum SERVICES_ClkId {
++              SERVICESCLK_iva2_ck = 0,
++              SERVICESCLK_mailbox_ick,
++              SERVICESCLK_gpt5_fck,
++              SERVICESCLK_gpt5_ick,
++              SERVICESCLK_gpt6_fck,
++              SERVICESCLK_gpt6_ick,
++              SERVICESCLK_gpt7_fck,
++              SERVICESCLK_gpt7_ick,
++              SERVICESCLK_gpt8_fck,
++              SERVICESCLK_gpt8_ick,
++              SERVICESCLK_wdt3_fck,
++              SERVICESCLK_wdt3_ick,
++              SERVICESCLK_mcbsp1_fck,
++              SERVICESCLK_mcbsp1_ick,
++              SERVICESCLK_mcbsp2_fck,
++              SERVICESCLK_mcbsp2_ick,
++              SERVICESCLK_mcbsp3_fck,
++              SERVICESCLK_mcbsp3_ick,
++              SERVICESCLK_mcbsp4_fck,
++              SERVICESCLK_mcbsp4_ick,
++              SERVICESCLK_mcbsp5_fck,
++              SERVICESCLK_mcbsp5_ick,
++              SERVICESCLK_ssi_fck,
++              SERVICESCLK_ssi_ick,
++              SERVICESCLK_sys_32k_ck,
++              SERVICESCLK_sys_ck,
++              SERVICESCLK_NOT_DEFINED
++      } ;
++
++/*
++ *  ======== CLK_Exit ========
++ *  Purpose:
++ *      Discontinue usage of module; free resources when reference count
++ *      reaches 0.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      CLK initialized.
++ *  Ensures:
++ *      Resources used by module are freed when cRef reaches zero.
++ */
++      extern void CLK_Exit(void);
++
++/*
++ *  ======== CLK_Init ========
++ *  Purpose:
++ *      Initializes private state of CLK module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialized; FALSE if error occured.
++ *  Requires:
++ *  Ensures:
++ *      CLK initialized.
++ */
++      extern bool CLK_Init(void);
++
++
++/*
++ *  ======== CLK_Enable ========
++ *  Purpose:
++ *      Enables the clock requested.
++ *  Parameters:
++ *  Returns:
++ *      DSP_SOK:      Success.
++ *    DSP_EFAIL:      Error occured while enabling the clock.
++ *  Requires:
++ *  Ensures:
++ */
++      extern DSP_STATUS CLK_Enable(IN enum SERVICES_ClkId clk_id);
++
++/*
++ *  ======== CLK_Disable ========
++ *  Purpose:
++ *      Disables the clock requested.
++ *  Parameters:
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Error occured while disabling the clock.
++ *  Requires:
++ *  Ensures:
++ */
++      extern DSP_STATUS CLK_Disable(IN enum SERVICES_ClkId clk_id);
++
++/*
++ *  ======== CLK_GetRate ========
++ *  Purpose:
++ *      Get the clock rate of requested clock.
++ *  Parameters:
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Error occured while Getting the clock rate.
++ *  Requires:
++ *  Ensures:
++ */
++      extern DSP_STATUS CLK_GetRate(IN enum SERVICES_ClkId clk_id,
++                                   u32 *speedMhz);
++/*
++ *  ======== CLK_Set_32KHz ========
++ *  Purpose:
++ *      Set the requested clock to 32KHz.
++ *  Parameters:
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Error occured while setting the clock parent to 32KHz.
++ *  Requires:
++ *  Ensures:
++ */
++      extern DSP_STATUS CLK_Set_32KHz(IN enum SERVICES_ClkId clk_id);
++      extern void SSI_Clk_Prepare(bool FLAG);
++
++/*
++ *  ======== CLK_Get_RefCnt ========
++ *  Purpose:
++ *      get the reference count for the clock.
++ *  Parameters:
++ *  Returns:
++ *      s32:        Reference Count for the clock.
++ *      DSP_EFAIL:  Error occured while getting the reference count of a clock.
++ *  Requires:
++ *  Ensures:
++ */
++      extern s32 CLK_Get_UseCnt(IN enum SERVICES_ClkId clk_id);
++
++#endif                                /* _SYNC_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cmm.h b/arch/arm/plat-omap/include/dspbridge/cmm.h
+new file mode 100644
+index 0000000..0df8b83
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cmm.h
+@@ -0,0 +1,420 @@
++/*
++ * cmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== cmm.h ========
++ *  Purpose:
++ *      The Communication Memory Management(CMM) module provides shared memory
++ *      management services for DSP/BIOS Bridge data streaming and messaging.
++ *      Multiple shared memory segments can be registered with CMM. Memory is
++ *      coelesced back to the appropriate pool when a buffer is freed.
++ *
++ *      The CMM_Xlator[xxx] functions are used for node messaging and data
++ *      streaming address translation to perform zero-copy inter-processor
++ *      data transfer(GPP<->DSP). A "translator" object is created for a node or
++ *      stream object that contains per thread virtual address information. This
++ *      translator info is used at runtime to perform SM address translation
++ *      to/from the DSP address space.
++ *
++ *
++ *  Public Functions:
++ *      CMM_CallocBuf
++ *      CMM_Create
++ *      CMM_Destroy
++ *      CMM_Exit
++ *      CMM_FreeBuf
++ *      CMM_GetHandle
++ *      CMM_GetInfo
++ *      CMM_Init
++ *      CMM_RegisterGPPSMSeg
++ *      CMM_UnRegisterGPPSMSeg
++ *      CMM_XlatorAllocBuf       (Note #1 below)
++ *      CMM_XlatorCreate           "
++ *      CMM_XlatorDelete           "
++ *      CMM_XlatorFreeBuf          "
++ *      CMM_XlatorTranslate        "
++ *
++ *
++ *  Notes:
++ *      #1: Used by Node and Stream modules for SM address translation.
++ *
++ *! Revision History:
++ *! ================
++ *! 30-Jan-2002 ag  Removed unused CMM_Alloc[Free]Desc & CMM_XlatorRegisterPa.
++ *!                 Renamed CMM_AllocBuf() to CMM_CallocBuf().
++ *! 29-Aug-2001 ag: Added dsp virt base and size to CMM_RegisterGPPSMSeg().
++ *! 12-Aug-2001 ag: Added CMM_UnRegisterGPP[DSP}SMSeg[s]().
++ *! 05-Dec-2000 ag: Added param to CMM_XlatorDelete() to force buf cleanup.
++ *! 30-Oct-2000 ag: Added conversion factor to CMM_RegisterDSP[GPP]SMSeg().
++ *! 12-Oct-2000 ag: Added CMM_Xlator[xxx] functions.
++ *! 10-Aug-2000 ag: Created.
++ *!
++ */
++
++#ifndef CMM_
++#define CMM_
++
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/cmmdefs.h>
++#include <dspbridge/host_os.h>
++
++/*
++ *  ======== CMM_CallocBuf ========
++ *  Purpose:
++ *      Allocate memory buffers that can be used for data streaming or
++ *      messaging.
++ *  Parameters:
++ *      hCmmMgr:   Cmm Mgr handle.
++ *      uSize:     Number of bytes to allocate.
++ *      pAttr:     Attributes of memory to allocate.
++ *      ppBufVA:   Address of where to place VA.
++ *  Returns:
++ *      Pointer to a zero'd block of SM memory;
++ *      NULL if memory couldn't be allocated,
++ *      or if cBytes == 0,
++ *  Requires:
++ *      Valid hCmmMgr.
++ *      CMM initialized.
++ *  Ensures:
++ *      The returned pointer, if not NULL, points to a valid memory block of
++ *      the size requested.
++ *
++ */
++      extern void *CMM_CallocBuf(struct CMM_OBJECT *hCmmMgr,
++                                 u32 uSize, struct CMM_ATTRS *pAttrs,
++                                 OUT void **ppBufVA);
++
++/*
++ *  ======== CMM_Create ========
++ *  Purpose:
++ *      Create a communication memory manager object.
++ *  Parameters:
++ *      phCmmMgr:   Location to store a communication manager handle on output.
++ *      hDevObject: Handle to a device object.
++ *      pMgrAttrs:  Comm mem manager attributes.
++ *  Returns:
++ *      DSP_SOK:        Success;
++ *      DSP_EMEMORY:    Insufficient memory for requested resources.
++ *      DSP_EFAIL:      Failed to initialize critical sect sync object.
++ *
++ *  Requires:
++ *      CMM_Init(void) called.
++ *      phCmmMgr != NULL.
++ *      pMgrAttrs->ulMinBlockSize >= 4 bytes.
++ *  Ensures:
++ *
++ */
++      extern DSP_STATUS CMM_Create(OUT struct CMM_OBJECT **phCmmMgr,
++                                   struct DEV_OBJECT *hDevObject,
++                                   IN CONST struct CMM_MGRATTRS *pMgrAttrs);
++
++/*
++ *  ======== CMM_Destroy ========
++ *  Purpose:
++ *      Destroy the communication memory manager object.
++ *  Parameters:
++ *      hCmmMgr:   Cmm Mgr handle.
++ *      bForce:    Force deallocation of all cmm memory immediately if set TRUE.
++ *                 If FALSE, and outstanding allocations will return DSP_EFAIL
++ *                 status.
++ *  Returns:
++ *      DSP_SOK:        CMM object & resources deleted.
++ *      DSP_EFAIL:      Unable to free CMM object due to outstanding allocation.
++ *      DSP_EHANDLE:    Unable to free CMM due to bad handle.
++ *  Requires:
++ *      CMM is initialized.
++ *      hCmmMgr != NULL.
++ *  Ensures:
++ *      Memory resources used by Cmm Mgr are freed.
++ */
++      extern DSP_STATUS CMM_Destroy(struct CMM_OBJECT *hCmmMgr, bool bForce);
++
++/*
++ *  ======== CMM_Exit ========
++ *  Purpose:
++ *     Discontinue usage of module. Cleanup CMM module if CMM cRef reaches zero.
++ *  Parameters:
++ *     n/a
++ *  Returns:
++ *     n/a
++ *  Requires:
++ *     CMM is initialized.
++ *  Ensures:
++ */
++      extern void CMM_Exit(void);
++
++/*
++ *  ======== CMM_FreeBuf ========
++ *  Purpose:
++ *      Free the given buffer.
++ *  Parameters:
++ *      hCmmMgr:    Cmm Mgr handle.
++ *      pBuf:       Pointer to memory allocated by CMM_CallocBuf().
++ *      ulSegId:    SM segment Id used in CMM_Calloc() attrs.
++ *                  Set to 0 to use default segment.
++ *  Returns:
++ *      DSP_SOK
++ *      DSP_EFAIL
++ *  Requires:
++ *      CMM initialized.
++ *      pBufPA != NULL
++ *  Ensures:
++ *
++ */
++      extern DSP_STATUS CMM_FreeBuf(struct CMM_OBJECT *hCmmMgr,
++                                    void *pBufPA, u32 ulSegId);
++
++/*
++ *  ======== CMM_GetHandle ========
++ *  Purpose:
++ *      Return the handle to the cmm mgr for the given device obj.
++ *  Parameters:
++ *      hProcessor:   Handle to a Processor.
++ *      phCmmMgr:     Location to store the shared memory mgr handle on output.
++ *
++ *  Returns:
++ *      DSP_SOK:        Cmm Mgr opaque handle returned.
++ *      DSP_EHANDLE:    Invalid handle.
++ *  Requires:
++ *      phCmmMgr != NULL
++ *      hDevObject != NULL
++ *  Ensures:
++ */
++      extern DSP_STATUS CMM_GetHandle(DSP_HPROCESSOR hProcessor,
++                                      OUT struct CMM_OBJECT **phCmmMgr);
++
++/*
++ *  ======== CMM_GetInfo ========
++ *  Purpose:
++ *      Return the current SM and VM utilization information.
++ *  Parameters:
++ *      hCmmMgr:     Handle to a Cmm Mgr.
++ *      pCmmInfo:    Location to store the Cmm information on output.
++ *
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid handle.
++ *      DSP_EINVALIDARG Invalid input argument.
++ *  Requires:
++ *  Ensures:
++ *
++ */
++      extern DSP_STATUS CMM_GetInfo(struct CMM_OBJECT *hCmmMgr,
++                                    OUT struct CMM_INFO *pCmmInfo);
++
++/*
++ *  ======== CMM_Init ========
++ *  Purpose:
++ *      Initializes private state of CMM module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialized; FALSE if error occured.
++ *  Requires:
++ *  Ensures:
++ *      CMM initialized.
++ */
++      extern bool CMM_Init(void);
++
++/*
++ *  ======== CMM_RegisterGPPSMSeg ========
++ *  Purpose:
++ *      Register a block of SM with the CMM.
++ *  Parameters:
++ *      hCmmMgr:         Handle to a Cmm Mgr.
++ *      lpGPPBasePA:     GPP Base Physical address.
++ *      ulSize:          Size in GPP bytes.
++ *      dwDSPAddrOffset  GPP PA to DSP PA Offset.
++ *      cFactor:         Add offset if CMM_ADDTODSPPA, sub if CMM_SUBFROMDSPPA.
++ *      dwDSPBase:       DSP virtual base byte address.
++ *      ulDSPSize:       Size of DSP segment in bytes.
++ *      pulSegId:        Address to store segment Id.
++ *
++ *  Returns:
++ *      DSP_SOK:         Success.
++ *      DSP_EHANDLE:     Invalid hCmmMgr handle.
++ *      DSP_EINVALIDARG: Invalid input argument.
++ *      DSP_EFAIL:       Unable to register.
++ *      - On success *pulSegId is a valid SM segment ID.
++ *  Requires:
++ *      ulSize > 0
++ *      pulSegId != NULL
++ *      dwGPPBasePA != 0
++ *      cFactor = CMM_ADDTODSPPA || cFactor = CMM_SUBFROMDSPPA
++ *  Ensures:
++ *
++ */
++      extern DSP_STATUS CMM_RegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr,
++                                             unsigned int dwGPPBasePA,
++                                             u32 ulSize,
++                                             u32 dwDSPAddrOffset,
++                                             enum CMM_CNVTTYPE cFactor,
++                                             unsigned int dwDSPBase,
++                                             u32 ulDSPSize,
++                                             u32 *pulSegId,
++                                             u32 dwGPPBaseBA);
++
++/*
++ *  ======== CMM_UnRegisterGPPSMSeg ========
++ *  Purpose:
++ *      Unregister the given memory segment that was previously registered
++ *      by CMM_RegisterGPPSMSeg.
++ *  Parameters:
++ *      hCmmMgr:    Handle to a Cmm Mgr.
++ *      ulSegId     Segment identifier returned by CMM_RegisterGPPSMSeg.
++ *  Returns:
++ *       DSP_SOK:         Success.
++ *       DSP_EHANDLE:     Invalid handle.
++ *       DSP_EINVALIDARG: Invalid ulSegId.
++ *       DSP_EFAIL:       Unable to unregister for unknown reason.
++ *  Requires:
++ *  Ensures:
++ *
++ */
++      extern DSP_STATUS CMM_UnRegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr,
++                                               u32 ulSegId);
++
++/*
++ *  ======== CMM_XlatorAllocBuf ========
++ *  Purpose:
++ *      Allocate the specified SM buffer and create a local memory descriptor.
++ *      Place on the descriptor on the translator's HaQ (Host Alloc'd Queue).
++ *  Parameters:
++ *      hXlator:    Handle to a Xlator object.
++ *      pVaBuf:     Virtual address ptr(client context)
++ *      uPaSize:    Size of SM memory to allocate.
++ *  Returns:
++ *      Ptr to valid physical address(Pa) of uPaSize bytes, NULL if failed.
++ *  Requires:
++ *      pVaBuf != 0.
++ *      uPaSize != 0.
++ *  Ensures:
++ *
++ */
++      extern void *CMM_XlatorAllocBuf(struct CMM_XLATOROBJECT *hXlator,
++                                      void *pVaBuf, u32 uPaSize);
++
++/*
++ *  ======== CMM_XlatorCreate ========
++ *  Purpose:
++ *     Create a translator(xlator) object used for process specific Va<->Pa
++ *     address translation. Node messaging and streams use this to perform
++ *     inter-processor(GPP<->DSP) zero-copy data transfer.
++ *  Parameters:
++ *     phXlator:       Address to place handle to a new Xlator handle.
++ *     hCmmMgr:        Handle to Cmm Mgr associated with this translator.
++ *     pXlatorAttrs:   Translator attributes used for the client NODE or STREAM.
++ *  Returns:
++ *     DSP_SOK:            Success.
++ *     DSP_EINVALIDARG:    Bad input Attrs.
++ *     DSP_EMEMORY:   Insufficient memory(local) for requested resources.
++ *  Requires:
++ *     phXlator != NULL
++ *     hCmmMgr != NULL
++ *     pXlatorAttrs != NULL
++ *  Ensures:
++ *
++ */
++      extern DSP_STATUS CMM_XlatorCreate(OUT struct CMM_XLATOROBJECT **phXlator,
++                                       struct CMM_OBJECT *hCmmMgr,
++                                       struct CMM_XLATORATTRS *pXlatorAttrs);
++
++/*
++ *  ======== CMM_XlatorDelete ========
++ *  Purpose:
++ *      Delete translator resources
++ *  Parameters:
++ *      hXlator:    handle to translator.
++ *      bForce:     bForce = TRUE will free XLators SM buffers/dscriptrs.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Bad translator handle.
++ *      DSP_EFAIL:      Unable to free translator resources.
++ *  Requires:
++ *      cRefs > 0
++ *  Ensures:
++ *
++ */
++      extern DSP_STATUS CMM_XlatorDelete(struct CMM_XLATOROBJECT *hXlator,
++                                         bool bForce);
++
++/*
++ *  ======== CMM_XlatorFreeBuf ========
++ *  Purpose:
++ *      Free SM buffer and descriptor.
++ *      Does not free client process VM.
++ *  Parameters:
++ *      hXlator:    handle to translator.
++ *      pBufVa      Virtual address of PA to free.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Bad translator handle.
++ *  Requires:
++ *  Ensures:
++ *
++ */
++      extern DSP_STATUS CMM_XlatorFreeBuf(struct CMM_XLATOROBJECT *hXlator,
++                                          void *pBufVa);
++
++/*
++ *  ======== CMM_XlatorInfo ========
++ *  Purpose:
++ *      Set/Get process specific "translator" address info.
++ *      This is used to perform fast virtaul address translation
++ *      for shared memory buffers between the GPP and DSP.
++ *  Parameters:
++ *     hXlator:     handle to translator.
++ *     pAddr:       Virtual base address of segment.
++ *     ulSize:      Size in bytes.
++ *     uSegId:      Segment identifier of SM segment(s)
++ *     bSetInfo     Set xlator fields if TRUE, else return base addr
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Bad translator handle.
++ *  Requires:
++ *      (cRefs > 0)
++ *      (pAddr != NULL)
++ *      (ulSize > 0)
++ *  Ensures:
++ *
++ */
++      extern DSP_STATUS CMM_XlatorInfo(struct CMM_XLATOROBJECT *hXlator,
++                                       IN OUT u8 **pAddr,
++                                       u32 ulSize, u32 uSegId,
++                                       bool bSetInfo);
++
++/*
++ *  ======== CMM_XlatorTranslate ========
++ *  Purpose:
++ *      Perform address translation VA<->PA for the specified stream or
++ *      message shared memory buffer.
++ *  Parameters:
++ *     hXlator: handle to translator.
++ *     pAddr    address of buffer to translate.
++ *     xType    Type of address xlation. CMM_PA2VA or CMM_VA2PA.
++ *  Returns:
++ *     Valid address on success, else NULL.
++ *  Requires:
++ *      cRefs > 0
++ *      pAddr != NULL
++ *      xType >= CMM_VA2PA) && (xType <= CMM_DSPPA2PA)
++ *  Ensures:
++ *
++ */
++      extern void *CMM_XlatorTranslate(struct CMM_XLATOROBJECT *hXlator,
++                                       void *pAddr, enum CMM_XLATETYPE xType);
++
++#endif                                /* CMM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cmmdefs.h b/arch/arm/plat-omap/include/dspbridge/cmmdefs.h
+new file mode 100644
+index 0000000..a779377
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cmmdefs.h
+@@ -0,0 +1,135 @@
++/*
++ * cmmdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== cmmdefs.h ========
++ *  Purpose:
++ *      Global MEM constants and types.
++ *
++ *! Revision History:
++ *! ================
++ *! 12-Nov-2001 ag  CMM_KERNMAPTYPE added for dsp<->device process addr map'n.
++ *!                 This allows addr conversion from drvr process <-> DSP addr.
++ *! 29-Aug-2001 ag  Added CMM_ALLSEGMENTS.
++ *! 08-Dec-2000 ag  Added bus address conversion type CMM_POMAPEMIF2DSPBUS.
++ *! 05-Dec-2000 ag  Added default CMM_DEFLTCONVFACTOR & CMM_DEFLTDSPADDROFFSET.
++ *! 29-Oct-2000 ag  Added converstion factor for GPP DSP Pa translation.
++ *! 15-Oct-2000 ag  Added address translator attributes and defaults.
++ *! 12-Jul-2000 ag  Created.
++ */
++
++#ifndef CMMDEFS_
++#define CMMDEFS_
++
++#include <dspbridge/list.h>
++
++/* Cmm attributes used in CMM_Create() */
++      struct CMM_MGRATTRS {
++              /* Minimum SM allocation; default 32 bytes.  */
++              u32 ulMinBlockSize;
++      } ;
++
++/* Attributes for CMM_AllocBuf() & CMM_AllocDesc() */
++      struct CMM_ATTRS {
++              u32 ulSegId;    /*  1,2... are SM segments. 0 is not. */
++              u32 ulAlignment;        /*  0,1,2,4....ulMinBlockSize */
++      } ;
++
++/*
++ *  DSPPa to GPPPa Conversion Factor.
++ *
++ *  For typical platforms:
++ *      converted Address = PaDSP + ( cFactor * addressToConvert).
++ */
++      enum CMM_CNVTTYPE {
++              CMM_SUBFROMDSPPA = -1,
++              /* PreOMAP is special case: not simple offset */
++              CMM_POMAPEMIF2DSPBUS = 0,
++              CMM_ADDTODSPPA = 1
++      } ;
++
++#define CMM_DEFLTDSPADDROFFSET  0
++#define CMM_DEFLTCONVFACTOR     CMM_POMAPEMIF2DSPBUS /* PreOMAP DSPBUS<->EMIF */
++#define CMM_ALLSEGMENTS         0xFFFFFF      /* All SegIds */
++#define CMM_MAXGPPSEGS          1     /* Maximum # of SM segs */
++
++/*
++ *  SMSEGs are SM segments the DSP allocates from.
++ *
++ *  This info is used by the GPP to xlate DSP allocated PAs.
++ */
++
++      struct CMM_SEGINFO {
++              u32 dwSegBasePa;        /* Start Phys address of SM segment */
++              /* Total size in bytes of segment: DSP+GPP */
++              u32 ulTotalSegSize;
++              u32 dwGPPBasePA;        /* Start Phys addr of Gpp SM seg */
++              u32 ulGPPSize;  /* Size of Gpp SM seg in bytes */
++              u32 dwDSPBaseVA;        /* DSP virt base byte address */
++              u32 ulDSPSize;  /* DSP seg size in bytes */
++              /* # of current GPP allocations from this segment */
++              u32 ulInUseCnt;
++              u32 dwSegBaseVa;        /* Start Virt address of SM seg */
++
++      } ;
++
++/* CMM useful information */
++      struct CMM_INFO {
++              /* # of SM segments registered with this Cmm. */
++              u32 ulNumGPPSMSegs;
++              /* Total # of allocations outstanding for CMM */
++              u32 ulTotalInUseCnt;
++              /* Min SM block size allocation from CMM_Create() */
++              u32 ulMinBlockSize;
++              /* Info per registered SM segment. */
++              struct CMM_SEGINFO segInfo[CMM_MAXGPPSEGS];
++      } ;
++
++/* XlatorCreate attributes */
++      struct CMM_XLATORATTRS {
++              u32 ulSegId;    /* segment Id used for SM allocations */
++              u32 dwDSPBufs;  /* # of DSP-side bufs */
++              u32 dwDSPBufSize;       /* size of DSP-side bufs in GPP bytes */
++              /* Vm base address alloc'd in client process context */
++              void *pVmBase;
++              /* dwVmSize must be >= (dwMaxNumBufs * dwMaxSize) */
++              u32 dwVmSize;
++      } ;
++
++/*
++ * Cmm translation types. Use to map SM addresses to process context.
++ */
++      enum CMM_XLATETYPE {
++              CMM_VA2PA = 0,  /* Virtual to GPP physical address xlation */
++              CMM_PA2VA = 1,  /* GPP Physical to virtual  */
++              CMM_VA2DSPPA = 2,       /* Va to DSP Pa  */
++              CMM_PA2DSPPA = 3,       /* GPP Pa to DSP Pa */
++              CMM_DSPPA2PA = 4,       /* DSP Pa to GPP Pa */
++      } ;
++
++/*
++ *  Used to "map" between device process virt addr and dsp addr.
++ */
++      enum CMM_KERNMAPTYPE {
++              CMM_KERNVA2DSP = 0, /* Device process context to dsp address. */
++              CMM_DSP2KERNVA = 1, /* Dsp address to device process context. */
++      } ;
++
++      struct CMM_OBJECT;
++      struct CMM_XLATOROBJECT;
++
++#endif                                /* CMMDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cod.h b/arch/arm/plat-omap/include/dspbridge/cod.h
+new file mode 100644
+index 0000000..a8a12c6
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cod.h
+@@ -0,0 +1,433 @@
++/*
++ * cod.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== cod.h ========
++ *  Description:
++ *      Code management module for DSPs. This module provides an interface
++ *      interface for loading both static and dynamic code objects onto DSP
++ *      systems.
++ *
++ *  Public Functions:
++ *      COD_Close
++ *      COD_Create
++ *      COD_Delete
++ *      COD_Exit
++ *      COD_GetBaseLib
++ *      COD_GetBaseName
++ *      COD_GetLoader
++ *      COD_GetSection
++ *      COD_GetSymValue
++ *      COD_Init
++ *      COD_LoadBase
++ *      COD_Open
++ *      COD_OpenBase
++ *      COD_ReadSection
++ *      COD_UnloadSection
++ *
++ *  Note:
++ *      Currently, only static loading is supported.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Apr-2003 map: Changed DBL to DBLL
++ *! 07-Aug-2002 jeh: Added COD_GetBaseName().
++ *! 17-Jul-2002 jeh: Added COD_Open(), COD_Close().
++ *! 15-Mar-2002 jeh: Added DBL_Flags param to COD_OpenBase().
++ *! 19-Oct-2001 jeh: Added COD_GetBaseLib, COD_GetLoader, (left in
++ *!                  COD_LoadSection(), COD_UnloadSection(), since they
++ *!                  may be needed for BridgeLite).
++ *! 07-Sep-2001 jeh: Added COD_LoadSection(), COD_UnloadSection().
++ *! 11-Jan-2001 jeh: Added COD_OpenBase.
++ *! 29-Sep-2000 kc:  Added size param to COD_ReadSection for input buffer
++ *!                  validation.
++ *! 02-Aug-2000 kc:  Added COD_ReadSection.
++ *! 04-Sep-1997 gp:  Added CDECL identifier to COD_WRITEFXN (for NT)..
++ *! 18-Aug-1997 cr:  Added explicit CDECL identifier.
++ *! 28-Oct-1996 gp:  Added COD_GetSection.
++ *! 30-Jul-1996 gp:  Added envp[] argument to COD_LoadBase().
++ *! 12-Jun-1996 gp:  Moved OUT param first in _Create().  Updated _Create()
++ *!                  call to take a ZLFileName.  Moved COD_ processor types
++ *!                  to CFG.
++ *! 29-May-1996 gp:  Changed WCD_STATUS to DSP_STATUS.  Removed include's.
++ *! 07-May-1996 mg:  Created.
++ *
++ */
++
++#ifndef COD_
++#define COD_
++
++#include <dspbridge/dblldefs.h>
++
++#define COD_MAXPATHLENGTH       255
++#define COD_TRACEBEG            "SYS_PUTCBEG"
++#define COD_TRACEEND            "SYS_PUTCEND"
++#define COD_TRACESECT           "trace"
++#define COD_TRACEBEGOLD         "PUTCBEG"
++#define COD_TRACEENDOLD         "PUTCEND"
++
++#define COD_NOLOAD              DBLL_NOLOAD
++#define COD_SYMB                DBLL_SYMB
++
++/* Flags passed to COD_Open */
++      typedef DBLL_Flags COD_FLAGS;
++
++/* COD code manager handle */
++      struct COD_MANAGER;
++
++/* COD library handle */
++      struct COD_LIBRARYOBJ;
++
++/* COD attributes */
++       struct COD_ATTRS {
++              u32 ulReserved;
++      } ;
++
++/*
++ *  Function prototypes for writing memory to a DSP system, allocating
++ *  and freeing DSP memory.
++ */
++       typedef u32(*COD_WRITEFXN) (void *pPrivRef, u32 ulDspAddr,
++                                           void *pBuf, u32 ulNumBytes,
++                                           u32 nMemSpace);
++
++
++/*
++ *  ======== COD_Close ========
++ *  Purpose:
++ *      Close a library opened with COD_Open().
++ *  Parameters:
++ *      lib             - Library handle returned by COD_Open().
++ *  Returns:
++ *      None.
++ *  Requires:
++ *      COD module initialized.
++ *      valid lib.
++ *  Ensures:
++ *
++ */
++       extern void COD_Close(struct COD_LIBRARYOBJ *lib);
++
++/*
++ *  ======== COD_Create ========
++ *  Purpose:
++ *      Create an object to manage code on a DSP system. This object can be
++ *      used to load an initial program image with arguments that can later
++ *      be expanded with dynamically loaded object files.
++ *      Symbol table information is managed by this object and can be retrieved
++ *      using the COD_GetSymValue() function.
++ *  Parameters:
++ *      phManager:      created manager object
++ *      pstrZLFile:     ZL DLL filename, of length < COD_MAXPATHLENGTH.
++ *      attrs:          attributes to be used by this object. A NULL value
++ *                      will cause default attrs to be used.
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      COD_E_NOZLFUNCTIONS:    Could not initialize ZL functions.
++ *      COD_E_ZLCREATEFAILED:   ZL_Create failed.
++ *      DSP_ENOTIMPL:           attrs was not NULL.  We don't yet support
++ *                              non default values of attrs.
++ *  Requires:
++ *      COD module initialized.
++ *      pstrZLFile != NULL
++ *  Ensures:
++ */
++       extern DSP_STATUS COD_Create(OUT struct COD_MANAGER **phManager,
++                                  char *pstrZLFile,
++                                  IN OPTIONAL CONST struct COD_ATTRS *attrs);
++
++/*
++ *  ======== COD_Delete ========
++ *  Purpose:
++ *      Delete a code manager object.
++ *  Parameters:
++ *      hManager:   handle of manager to be deleted
++ *  Returns:
++ *      None.
++ *  Requires:
++ *      COD module initialized.
++ *      valid hManager.
++ *  Ensures:
++ */
++       extern void COD_Delete(struct COD_MANAGER *hManager);
++
++/*
++ *  ======== COD_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the COD module.
++ *  Parameters:
++ *      None.
++ *  Returns:
++ *      None.
++ *  Requires:
++ *      COD initialized.
++ *  Ensures:
++ *      Resources acquired in COD_Init(void) are freed.
++ */
++       extern void COD_Exit(void);
++
++/*
++ *  ======== COD_GetBaseLib ========
++ *  Purpose:
++ *      Get handle to the base image DBL library.
++ *  Parameters:
++ *      hManager:   handle of manager to be deleted
++ *      plib:       location to store library handle on output.
++ *  Returns:
++ *      DSP_SOK:    Success.
++ *  Requires:
++ *      COD module initialized.
++ *      valid hManager.
++ *      plib != NULL.
++ *  Ensures:
++ */
++       extern DSP_STATUS COD_GetBaseLib(struct COD_MANAGER *hManager,
++                                             struct DBLL_LibraryObj **plib);
++
++/*
++ *  ======== COD_GetBaseName ========
++ *  Purpose:
++ *      Get the name of the base image DBL library.
++ *  Parameters:
++ *      hManager:   handle of manager to be deleted
++ *      pszName:    location to store library name on output.
++ *      uSize:       size of name buffer.
++ *  Returns:
++ *      DSP_SOK:    Success.
++ *      DSP_EFAIL:  Buffer too small.
++ *  Requires:
++ *      COD module initialized.
++ *      valid hManager.
++ *      pszName != NULL.
++ *  Ensures:
++ */
++       extern DSP_STATUS COD_GetBaseName(struct COD_MANAGER *hManager,
++                                              char *pszName, u32 uSize);
++
++/*
++ *  ======== COD_GetEntry ========
++ *  Purpose:
++ *      Retrieve the entry point of a loaded DSP program image
++ *  Parameters:
++ *      hManager:   handle of manager to be deleted
++ *      pulEntry:   pointer to location for entry point
++ *  Returns:
++ *      DSP_SOK:       Success.
++ *  Requires:
++ *      COD module initialized.
++ *      valid hManager.
++ *      pulEntry != NULL.
++ *  Ensures:
++ */
++       extern DSP_STATUS COD_GetEntry(struct COD_MANAGER *hManager,
++                                           u32 *pulEntry);
++
++/*
++ *  ======== COD_GetLoader ========
++ *  Purpose:
++ *      Get handle to the DBL loader.
++ *  Parameters:
++ *      hManager:   handle of manager to be deleted
++ *      phLoader:   location to store loader handle on output.
++ *  Returns:
++ *      DSP_SOK:    Success.
++ *  Requires:
++ *      COD module initialized.
++ *      valid hManager.
++ *      phLoader != NULL.
++ *  Ensures:
++ */
++       extern DSP_STATUS COD_GetLoader(struct COD_MANAGER *hManager,
++                                            struct DBLL_TarObj **phLoader);
++
++/*
++ *  ======== COD_GetSection ========
++ *  Purpose:
++ *      Retrieve the starting address and length of a section in the COFF file
++ *      given the section name.
++ *  Parameters:
++ *      lib         Library handle returned from COD_Open().
++ *      pstrSect:   name of the section, with or without leading "."
++ *      puAddr:     Location to store address.
++ *      puLen:      Location to store length.
++ *  Returns:
++ *      DSP_SOK:                Success
++ *      COD_E_NOSYMBOLSLOADED:  Symbols have not been loaded onto the board.
++ *      COD_E_SYMBOLNOTFOUND:   The symbol could not be found.
++ *  Requires:
++ *      COD module initialized.
++ *      valid hManager.
++ *      pstrSect != NULL;
++ *      puAddr != NULL;
++ *      puLen != NULL;
++ *  Ensures:
++ *      DSP_SOK:  *puAddr and *puLen contain the address and length of the
++ *                 section.
++ *      else:  *puAddr == 0 and *puLen == 0;
++ *
++ */
++       extern DSP_STATUS COD_GetSection(struct COD_LIBRARYOBJ *lib,
++                                             IN char *pstrSect,
++                                             OUT u32 *puAddr,
++                                             OUT u32 *puLen);
++
++/*
++ *  ======== COD_GetSymValue ========
++ *  Purpose:
++ *      Retrieve the value for the specified symbol. The symbol is first
++ *      searched for literally and then, if not found, searched for as a
++ *      C symbol.
++ *  Parameters:
++ *      lib:        library handle returned from COD_Open().
++ *      pstrSymbol: name of the symbol
++ *      value:      value of the symbol
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      COD_E_NOSYMBOLSLOADED:  Symbols have not been loaded onto the board.
++ *      COD_E_SYMBOLNOTFOUND:   The symbol could not be found.
++ *  Requires:
++ *      COD module initialized.
++ *      Valid hManager.
++ *      pstrSym != NULL.
++ *      pulValue != NULL.
++ *  Ensures:
++ */
++       extern DSP_STATUS COD_GetSymValue(struct COD_MANAGER *hManager,
++                                              IN char *pstrSym,
++                                              OUT u32 *pulValue);
++
++/*
++ *  ======== COD_Init ========
++ *  Purpose:
++ *      Initialize the COD module's private state.
++ *  Parameters:
++ *      None.
++ *  Returns:
++ *      TRUE if initialized; FALSE if error occured.
++ *  Requires:
++ *  Ensures:
++ *      A requirement for each of the other public COD functions.
++ */
++       extern bool COD_Init(void);
++
++/*
++ *  ======== COD_LoadBase ========
++ *  Purpose:
++ *      Load the initial program image, optionally with command-line arguments,
++ *      on the DSP system managed by the supplied handle. The program to be
++ *      loaded must be the first element of the args array and must be a fully
++ *      qualified pathname.
++ *  Parameters:
++ *      hMgr:       manager to load the code with
++ *      nArgc:      number of arguments in the args array
++ *      args:       array of strings for arguments to DSP program
++ *      writeFxn:   board-specific function to write data to DSP system
++ *      pArb:       arbitrary pointer to be passed as first arg to writeFxn
++ *      envp:       array of environment strings for DSP exec.
++ *  Returns:
++ *      DSP_SOK:                   Success.
++ *      COD_E_OPENFAILED:       Failed to open target code.
++ *      COD_E_LOADFAILED:       Failed to load code onto target.
++ *  Requires:
++ *      COD module initialized.
++ *      hMgr is valid.
++ *      nArgc > 0.
++ *      aArgs != NULL.
++ *      aArgs[0] != NULL.
++ *      pfnWrite != NULL.
++ *  Ensures:
++ */
++       extern DSP_STATUS COD_LoadBase(struct COD_MANAGER *hManager,
++                                           u32 nArgc, char *aArgs[],
++                                           COD_WRITEFXN pfnWrite, void *pArb,
++                                           char *envp[]);
++
++
++/*
++ *  ======== COD_Open ========
++ *  Purpose:
++ *      Open a library for reading sections. Does not load or set the base.
++ *  Parameters:
++ *      hMgr:           manager to load the code with
++ *      pszCoffPath:    Coff file to open.
++ *      flags:          COD_NOLOAD (don't load symbols) or COD_SYMB (load
++ *                      symbols).
++ *      pLib:           Handle returned that can be used in calls to COD_Close
++ *                      and COD_GetSection.
++ *  Returns:
++ *      S_OK:                   Success.
++ *      COD_E_OPENFAILED:       Failed to open target code.
++ *  Requires:
++ *      COD module initialized.
++ *      hMgr is valid.
++ *      flags == COD_NOLOAD || flags == COD_SYMB.
++ *      pszCoffPath != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS COD_Open(struct COD_MANAGER *hMgr,
++                                 IN char *pszCoffPath,
++                                 COD_FLAGS flags,
++                                 OUT struct COD_LIBRARYOBJ **pLib);
++
++/*
++ *  ======== COD_OpenBase ========
++ *  Purpose:
++ *      Open base image for reading sections. Does not load the base.
++ *  Parameters:
++ *      hMgr:           manager to load the code with
++ *      pszCoffPath:    Coff file to open.
++ *      flags:          Specifies whether to load symbols.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      COD_E_OPENFAILED:   Failed to open target code.
++ *  Requires:
++ *      COD module initialized.
++ *      hMgr is valid.
++ *      pszCoffPath != NULL.
++ *  Ensures:
++ */
++extern DSP_STATUS COD_OpenBase(struct COD_MANAGER *hMgr, IN char *pszCoffPath,
++                                     DBLL_Flags flags);
++
++/*
++ *  ======== COD_ReadSection ========
++ *  Purpose:
++ *      Retrieve the content of a code section given the section name.
++ *  Parameters:
++ *      hManager    - manager in which to search for the symbol
++ *      pstrSect    - name of the section, with or without leading "."
++ *      pstrContent - buffer to store content of the section.
++ *  Returns:
++ *      DSP_SOK: on success, error code on failure
++ *      COD_E_NOSYMBOLSLOADED:  Symbols have not been loaded onto the board.
++ *      COD_E_READFAILED: Failed to read content of code section.
++ *  Requires:
++ *      COD module initialized.
++ *      valid hManager.
++ *      pstrSect != NULL;
++ *      pstrContent != NULL;
++ *  Ensures:
++ *      DSP_SOK:  *pstrContent stores the content of the named section.
++ */
++       extern DSP_STATUS COD_ReadSection(struct COD_LIBRARYOBJ *lib,
++                                              IN char *pstrSect,
++                                              OUT char *pstrContent,
++                                              IN u32 cContentSize);
++
++
++
++#endif                                /* COD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/csl.h b/arch/arm/plat-omap/include/dspbridge/csl.h
+new file mode 100644
+index 0000000..b90d6ff
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/csl.h
+@@ -0,0 +1,135 @@
++/*
++ * csl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== csl.h ========
++ *  Purpose:
++ *      Platform independent C Standard library functions.
++ *
++ *  Public Functions:
++ *      CSL_AnsiToWchar
++ *      CSL_ByteSwap
++ *      CSL_Exit
++ *      CSL_Init
++ *      CSL_NumToAscii
++ *      CSL_Strtok
++ *      CSL_Strtokr
++ *      CSL_WcharToAnsi
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Aug-2002 jeh: Added CSL_Strtokr().
++ *! 21-Sep-2001 jeh: Added CSL_Strncmp.
++ *! 22-Nov-2000 map: Added CSL_Atoi and CSL_Strtok
++ *! 19-Nov-2000 kc:  Added CSL_ByteSwap().
++ *! 09-Nov-2000 kc:  Added CSL_Strncat.
++ *! 29-Oct-1999 kc:  Added CSL_Wstrlen().
++ *! 20-Sep-1999 ag:  Added CSL_Wchar2Ansi().
++ *! 19-Jan-1998 cr:  Code review cleanup (mostly documentation fixes).
++ *! 29-Dec-1997 cr:  Changed CSL_lowercase to CSL_Uppercase, added
++ *!                  CSL_AnsiToWchar.
++ *! 30-Sep-1997 cr:  Added explicit cdecl descriptors to fxn definitions.
++ *! 25-Jun-1997 cr:  Added CSL_strcmp.
++ *! 12-Jun-1996 gp:  Created.
++ */
++
++#ifndef CSL_
++#define CSL_
++
++#include <dspbridge/host_os.h>
++
++/*
++ *  ======== CSL_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the CSL module.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      CSL initialized.
++ *  Ensures:
++ *      Resources acquired in CSL_Init(void) are freed.
++ */
++      extern void CSL_Exit(void);
++
++/*
++ *  ======== CSL_Init ========
++ *  Purpose:
++ *      Initialize the CSL module's private state.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialized; FALSE if error occured.
++ *  Requires:
++ *  Ensures:
++ *      A requirement for each of the other public CSL functions.
++ */
++      extern bool CSL_Init(void);
++
++/*
++ *  ======== CSL_NumToAscii ========
++ *  Purpose:
++ *      Convert a 1 or 2 digit number to a 2 digit string.
++ *  Parameters:
++ *      pstrNumber: Buffer to store converted string.
++ *      dwNum:      Number to convert.
++ *  Returns:
++ *  Requires:
++ *      pstrNumber must be able to hold at least three characters.
++ *  Ensures:
++ *      pstrNumber will be null terminated.
++ */
++      extern void CSL_NumToAscii(OUT char *pstrNumber, IN u32 dwNum);
++
++
++/*
++ *  ======== CSL_Strtok ========
++ *  Purpose:
++ *      Tokenize a NULL terminated string
++ *  Parameters:
++ *      ptstrSrc:       pointer to string.
++ *      szSeparators:   pointer to a string of seperators
++ *  Returns:
++ *      char *
++ *  Requires:
++ *      CSL initialized.
++ *      ptstrSrc is a valid string pointer.
++ *      szSeparators is a valid string pointer.
++ *  Ensures:
++ */
++      extern char *CSL_Strtok(IN char *ptstrSrc,
++                              IN CONST char *szSeparators);
++
++/*
++ *  ======== CSL_Strtokr ========
++ *  Purpose:
++ *      Re-entrant version of strtok.
++ *  Parameters:
++ *      pstrSrc:        Pointer to string. May be NULL on subsequent calls.
++ *      szSeparators:   Pointer to a string of seperators
++ *      ppstrCur:       Location to store start of string for next call to
++ *                      to CSL_Strtokr.
++ *  Returns:
++ *      char * (the token)
++ *  Requires:
++ *      CSL initialized.
++ *      szSeparators != NULL
++ *      ppstrCur != NULL
++ *  Ensures:
++ */
++      extern char *CSL_Strtokr(IN char *pstrSrc,
++                               IN CONST char *szSeparators,
++                               OUT char **ppstrCur);
++
++#endif                                /* CSL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbc.h b/arch/arm/plat-omap/include/dspbridge/dbc.h
+new file mode 100644
+index 0000000..0e6a67d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbc.h
+@@ -0,0 +1,66 @@
++/*
++ * dbc.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== dbc.h ========
++ *  Purpose:
++ *      "Design by Contract" programming macros.
++ *
++ *  Public Functions:
++ *      DBC_Assert
++ *      DBC_Require
++ *      DBC_Ensure
++ *
++ *  Notes:
++ *      Requires that the GT->ERROR function has been defaulted to a valid
++ *      error handler for the given execution environment.
++ *
++ *      Does not require that GT_init() be called.
++ *
++ *! Revision History:
++ *! ================
++ *! 11-Aug-2000 ag: Removed include <dspbridge/std.h>
++ *! 22-Apr-1996 gp: Created.
++ */
++
++#ifndef DBC_
++#define DBC_
++
++#ifndef GT_TRACE
++#define GT_TRACE 0        /* 0 = "trace compiled out"; 1 = "trace active" */
++#endif
++
++/* Assertion Macros: */
++#if GT_TRACE
++
++#include <dspbridge/gt.h>
++
++#define DBC_Assert(exp) \
++    if (!(exp)) \
++      printk("%s, line %d: Assertion (" #exp ") failed.\n", \
++      __FILE__, __LINE__)
++#define DBC_Require DBC_Assert        /* Function Precondition.  */
++#define DBC_Ensure  DBC_Assert        /* Function Postcondition. */
++
++#else
++
++#define DBC_Assert(exp)
++#define DBC_Require(exp)
++#define DBC_Ensure(exp)
++
++#endif                                /* DEBUG */
++
++#endif                                /* DBC_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbdcd.h b/arch/arm/plat-omap/include/dspbridge/dbdcd.h
+new file mode 100644
+index 0000000..fbc3870
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbdcd.h
+@@ -0,0 +1,388 @@
++/*
++ * dbdcd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== dbdcd.h ========
++ *  Description:
++ *      Defines the DSP/BIOS Bridge Configuration Database (DCD) API.
++ *
++ *! Revision History
++ *! ================
++ *! 03-Dec-2003 map Changed DCD_OBJTYPE to DSP_DCDOBJTYPE
++ *! 24-Feb-2003 kc  Updated DCD_AutoUnregister and DCD_GetObjects to simplify
++ *!                 DCD implementation.
++ *! 05-Aug-2002 jeh Added DCD_GetObjects().
++ *! 11-Jul-2002 jeh Added DCD_GetDepLibs(), DCD_GetNumDepLibs().
++ *! 22-Apr-2002 jeh Added DCD_GetLibraryName().
++ *! 03-Apr-2001 sg  Changed error names to have DCD_E* format.
++ *! 13-Feb-2001 kc  Name changed from dcdbs.h to dbdcd.h.
++ *! 12-Dec-2000 kc  Added DCD_AutoUnregister.
++ *! 09-Nov-2000 kc  Updated usage of DCD_EnumerateObject.
++ *! 30-Oct-2000 kc  Added DCD_AutoRegister. Updated error DCD error codes.
++ *! 29-Sep-2000 kc  Incorporated code review comments. See
++ *!                 /src/reviews/dcd_review.txt.
++ *! 26-Jul-2000 kc  Created.
++ *!
++ */
++
++#ifndef DBDCD_
++#define DBDCD_
++
++#include <dspbridge/dbdcddef.h>
++#include <dspbridge/host_os.h>
++#include <dspbridge/nldrdefs.h>
++
++/*
++ *  ======== DCD_AutoRegister ========
++ *  Purpose:
++ *      This function automatically registers DCD objects specified in a
++ *      special COFF section called ".dcd_register"
++ *  Parameters:
++ *      hDcdMgr:                A DCD manager handle.
++ *      pszCoffPath:            Pointer to name of COFF file containing DCD
++ *                              objects to be registered.
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      DSP_EDCDNOAUTOREGISTER: Unable to find auto-registration section.
++ *      DSP_EDCDREADSECT:       Unable to read object code section.
++ *      DSP_EDCDLOADBASE:       Unable to load code base.
++ *      DSP_EHANDLE:            Invalid DCD_HMANAGER handle..
++ *  Requires:
++ *      DCD initialized.
++ *  Ensures:
++ *  Note:
++ *      Due to the DCD database construction, it is essential for a DCD-enabled
++ *      COFF file to contain the right COFF sections, especially
++ *      ".dcd_register", which is used for auto registration.
++ */
++      extern DSP_STATUS DCD_AutoRegister(IN struct DCD_MANAGER *hDcdMgr,
++                                         IN char *pszCoffPath);
++
++/*
++ *  ======== DCD_AutoUnregister ========
++ *  Purpose:
++ *      This function automatically unregisters DCD objects specified in a
++ *      special COFF section called ".dcd_register"
++ *  Parameters:
++ *      hDcdMgr:                A DCD manager handle.
++ *      pszCoffPath:            Pointer to name of COFF file containing
++ *                              DCD objects to be unregistered.
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      DSP_EDCDNOAUTOREGISTER: Unable to find auto-registration section.
++ *      DSP_EDCDREADSECT:       Unable to read object code section.
++ *      DSP_EDCDLOADBASE:       Unable to load code base.
++ *      DSP_EHANDLE:            Invalid DCD_HMANAGER handle..
++ *  Requires:
++ *      DCD initialized.
++ *  Ensures:
++ *  Note:
++ *      Due to the DCD database construction, it is essential for a DCD-enabled
++ *      COFF file to contain the right COFF sections, especially
++ *      ".dcd_register", which is used for auto unregistration.
++ */
++      extern DSP_STATUS DCD_AutoUnregister(IN struct DCD_MANAGER *hDcdMgr,
++                                           IN char *pszCoffPath);
++
++/*
++ *  ======== DCD_CreateManager ========
++ *  Purpose:
++ *      This function creates a DCD module manager.
++ *  Parameters:
++ *      pszZlDllName:   Pointer to a DLL name string.
++ *      phDcdMgr:       A pointer to a DCD manager handle.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Unable to allocate memory for DCD manager handle.
++ *      DSP_EFAIL:      General failure.
++ *  Requires:
++ *      DCD initialized.
++ *      pszZlDllName is non-NULL.
++ *      phDcdMgr is non-NULL.
++ *  Ensures:
++ *      A DCD manager handle is created.
++ */
++      extern DSP_STATUS DCD_CreateManager(IN char *pszZlDllName,
++                                          OUT struct DCD_MANAGER **phDcdMgr);
++
++/*
++ *  ======== DCD_DestroyManager ========
++ *  Purpose:
++ *      This function destroys a DCD module manager.
++ *  Parameters:
++ *      hDcdMgr:        A DCD manager handle.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid DCD manager handle.
++ *  Requires:
++ *      DCD initialized.
++ *  Ensures:
++ */
++      extern DSP_STATUS DCD_DestroyManager(IN struct DCD_MANAGER *hDcdMgr);
++
++/*
++ *  ======== DCD_EnumerateObject ========
++ *  Purpose:
++ *      This function enumerates currently visible DSP/BIOS Bridge objects
++ *      and returns the UUID and type of each enumerated object.
++ *  Parameters:
++ *      cIndex:             The object enumeration index.
++ *      objType:            Type of object to enumerate.
++ *      pUuid:              Pointer to a DSP_UUID object.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EFAIL:          Unable to enumerate through the DCD database.
++ *      DSP_SENUMCOMPLETE:  Enumeration completed. This is not an error code.
++ *  Requires:
++ *      DCD initialized.
++ *      pUuid is a valid pointer.
++ *  Ensures:
++ *  Details:
++ *      This function can be used in conjunction with DCD_GetObjectDef to
++ *      retrieve object properties.
++ */
++      extern DSP_STATUS DCD_EnumerateObject(IN s32 cIndex,
++                                            IN enum DSP_DCDOBJTYPE objType,
++                                            OUT struct DSP_UUID *pUuid);
++
++/*
++ *  ======== DCD_Exit ========
++ *  Purpose:
++ *      This function cleans up the DCD module.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      DCD initialized.
++ *  Ensures:
++ */
++      extern void DCD_Exit(void);
++
++/*
++ *  ======== DCD_GetDepLibs ========
++ *  Purpose:
++ *      Given the uuid of a library and size of array of uuids, this function
++ *      fills the array with the uuids of all dependent libraries of the input
++ *      library.
++ *  Parameters:
++ *      hDcdMgr: A DCD manager handle.
++ *      pUuid: Pointer to a DSP_UUID for a library.
++ *      numLibs: Size of uuid array (number of library uuids).
++ *      pDepLibUuids: Array of dependent library uuids to be filled in.
++ *      pPersistentDepLibs: Array indicating if corresponding lib is persistent.
++ *      phase: phase to obtain correct input library
++ *  Returns:
++ *      DSP_SOK: Success.
++ *      DSP_EMEMORY: Memory allocation failure.
++ *      DSP_EDCDREADSECT: Failure to read section containing library info.
++ *      DSP_EFAIL: General failure.
++ *  Requires:
++ *      DCD initialized.
++ *      Valid hDcdMgr.
++ *      pUuid != NULL
++ *      pDepLibUuids != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS DCD_GetDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++                                       IN struct DSP_UUID *pUuid,
++                                       u16 numLibs,
++                                       OUT struct DSP_UUID *pDepLibUuids,
++                                       OUT bool *pPersistentDepLibs,
++                                       IN enum NLDR_PHASE phase);
++
++/*
++ *  ======== DCD_GetNumDepLibs ========
++ *  Purpose:
++ *      Given the uuid of a library, determine its number of dependent
++ *      libraries.
++ *  Parameters:
++ *      hDcdMgr:        A DCD manager handle.
++ *      pUuid:          Pointer to a DSP_UUID for a library.
++ *      pNumLibs:       Size of uuid array (number of library uuids).
++ *      pNumPersLibs:   number of persistent dependent library.
++ *      phase:          Phase to obtain correct input library
++ *  Returns:
++ *      DSP_SOK: Success.
++ *      DSP_EMEMORY: Memory allocation failure.
++ *      DSP_EDCDREADSECT: Failure to read section containing library info.
++ *      DSP_EFAIL: General failure.
++ *  Requires:
++ *      DCD initialized.
++ *      Valid hDcdMgr.
++ *      pUuid != NULL
++ *      pNumLibs != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS DCD_GetNumDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++                                          IN struct DSP_UUID *pUuid,
++                                          OUT u16 *pNumLibs,
++                                          OUT u16 *pNumPersLibs,
++                                          IN enum NLDR_PHASE phase);
++
++/*
++ *  ======== DCD_GetLibraryName ========
++ *  Purpose:
++ *      This function returns the name of a (dynamic) library for a given
++ *      UUID.
++ *  Parameters:
++ *      hDcdMgr: A DCD manager handle.
++ *      pUuid:          Pointer to a DSP_UUID that represents a unique DSP/BIOS
++ *                      Bridge object.
++ *      pstrLibName: Buffer to hold library name.
++ *      pdwSize: Contains buffer size. Set to string size on output.
++ *      phase:          Which phase to load
++ *      fPhaseSplit:    Are phases in multiple libraries
++ *  Returns:
++ *      DSP_SOK: Success.
++ *      DSP_EFAIL: General failure.
++ *  Requires:
++ *      DCD initialized.
++ *      Valid hDcdMgr.
++ *      pstrLibName != NULL.
++ *      pUuid != NULL
++ *      pdwSize != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS DCD_GetLibraryName(IN struct DCD_MANAGER *hDcdMgr,
++                                           IN struct DSP_UUID *pUuid,
++                                           IN OUT char *pstrLibName,
++                                           IN OUT u32 *pdwSize,
++                                           IN enum NLDR_PHASE phase,
++                                           OUT bool *fPhaseSplit);
++
++/*
++ *  ======== DCD_GetObjectDef ========
++ *  Purpose:
++ *      This function returns the properties/attributes of a DSP/BIOS Bridge
++ *      object.
++ *  Parameters:
++ *      hDcdMgr:            A DCD manager handle.
++ *      pUuid:              Pointer to a DSP_UUID that represents a unique
++ *                          DSP/BIOS Bridge object.
++ *      objType:            The type of DSP/BIOS Bridge object to be
++ *                          referenced (node, processor, etc).
++ *      pObjDef:            Pointer to an object definition structure. A
++ *                          union of various possible DCD object types.
++ *  Returns:
++ *      DSP_SOK: Success.
++ *      DSP_EDCDPARSESECT:  Unable to parse content of object code section.
++ *      DSP_EDCDREADSECT:   Unable to read object code section.
++ *      DSP_EDCDGETSECT:    Unable to access object code section.
++ *      DSP_EDCDLOADBASE:   Unable to load code base.
++ *      DSP_EFAIL:          General failure.
++ *      DSP_EHANDLE:        Invalid DCD_HMANAGER handle.
++ *  Requires:
++ *      DCD initialized.
++ *      pObjUuid is non-NULL.
++ *      pObjDef is non-NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS DCD_GetObjectDef(IN struct DCD_MANAGER *hDcdMgr,
++                                         IN struct DSP_UUID *pObjUuid,
++                                         IN enum DSP_DCDOBJTYPE objType,
++                                         OUT struct DCD_GENERICOBJ *pObjDef);
++
++/*
++ *  ======== DCD_GetObjects ========
++ *  Purpose:
++ *      This function finds all DCD objects specified in a special
++ *      COFF section called ".dcd_register", and for each object,
++ *      call a "register" function.  The "register" function may perform
++ *      various actions, such as 1) register nodes in the node database, 2)
++ *      unregister nodes from the node database, and 3) add overlay nodes.
++ *  Parameters:
++ *      hDcdMgr:                A DCD manager handle.
++ *      pszCoffPath:            Pointer to name of COFF file containing DCD
++ *                              objects.
++ *      registerFxn:            Callback fxn to be applied on each located
++ *                              DCD object.
++ *      handle:                 Handle to pass to callback.
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      DSP_EDCDNOAUTOREGISTER: Unable to find .dcd_register section.
++ *      DSP_EDCDREADSECT:       Unable to read object code section.
++ *      DSP_EDCDLOADBASE:       Unable to load code base.
++ *      DSP_EHANDLE:            Invalid DCD_HMANAGER handle..
++ *  Requires:
++ *      DCD initialized.
++ *  Ensures:
++ *  Note:
++ *      Due to the DCD database construction, it is essential for a DCD-enabled
++ *      COFF file to contain the right COFF sections, especially
++ *      ".dcd_register", which is used for auto registration.
++ */
++      extern DSP_STATUS DCD_GetObjects(IN struct DCD_MANAGER *hDcdMgr,
++                                       IN char *pszCoffPath,
++                                       DCD_REGISTERFXN registerFxn,
++                                       void *handle);
++
++/*
++ *  ======== DCD_Init ========
++ *  Purpose:
++ *      This function initializes DCD.
++ *  Parameters:
++ *  Returns:
++ *      FALSE:  Initialization failed.
++ *      TRUE:   Initialization succeeded.
++ *  Requires:
++ *  Ensures:
++ *      DCD initialized.
++ */
++      extern bool DCD_Init(void);
++
++/*
++ *  ======== DCD_RegisterObject ========
++ *  Purpose:
++ *      This function registers a DSP/BIOS Bridge object in the DCD database.
++ *  Parameters:
++ *      pUuid:          Pointer to a DSP_UUID that identifies a DSP/BIOS
++ *                      Bridge object.
++ *      objType:        Type of object.
++ *      pszPathName:    Path to the object's COFF file.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Failed to register object.
++ *  Requires:
++ *      DCD initialized.
++ *      pUuid and szPathName are non-NULL values.
++ *      objType is a valid type value.
++ *  Ensures:
++ */
++      extern DSP_STATUS DCD_RegisterObject(IN struct DSP_UUID *pUuid,
++                                           IN enum DSP_DCDOBJTYPE objType,
++                                           IN char *pszPathName);
++
++/*
++ *  ======== DCD_UnregisterObject ========
++ *  Purpose:
++ *      This function de-registers a valid DSP/BIOS Bridge object from the DCD
++ *      database.
++ *  Parameters:
++ *      pUuid:      Pointer to a DSP_UUID that identifies a DSP/BIOS Bridge
++ *                  object.
++ *      objType:    Type of object.
++ *  Returns:
++ *      DSP_SOK:    Success.
++ *      DSP_EFAIL:  Unable to de-register the specified object.
++ *  Requires:
++ *      DCD initialized.
++ *      pUuid is a non-NULL value.
++ *      objType is a valid type value.
++ *  Ensures:
++ */
++      extern DSP_STATUS DCD_UnregisterObject(IN struct DSP_UUID *pUuid,
++                                             IN enum DSP_DCDOBJTYPE objType);
++
++#endif                                /* _DBDCD_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbdcddef.h b/arch/arm/plat-omap/include/dspbridge/dbdcddef.h
+new file mode 100644
+index 0000000..91b1c45
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbdcddef.h
+@@ -0,0 +1,94 @@
++/*
++ * dbdcddef.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dbdcddef.h ========
++ *  Description:
++ *      DCD (DSP/BIOS Bridge Configuration Database) constants and types.
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Dec-2003 map Moved and renamed DCD_OBJTYPE to DSP_DCDOBJTYPE in dbdefs.h
++ *! 05-Dec-2002 map Added DCD_CREATELIBTYPE, DCD_EXECUTELIBTYPE,
++ *                        DCD_DELETELIBTYPE
++ *! 24-Feb-2003 kc  Updated REG entry names to DspBridge.
++ *! 22-Nov-2002 gp  Cleaned up comments, formatting.
++ *! 05-Aug-2002 jeh Added DCD_REGISTERFXN.
++ *! 19-Apr-2002 jeh Added DCD_LIBRARYTYPE to DCD_OBJTYPE, dynamic load
++ *!                 properties to DCD_NODEPROPS.
++ *! 29-Jul-2001 ag  Added extended procObj.
++ *! 13-Feb-2001 kc: Named changed from dcdbsdef.h dbdcddef.h.
++ *! 12-Dec-2000 jeh Added DAIS iAlg name to DCD_NODEPROPS.
++ *! 30-Oct-2000 kc: Added #defines for DCD_AutoRegister function.
++ *! 05-Sep-2000 jeh Added DCD_NODEPROPS.
++ *! 12-Aug-2000 kc: Incoroporated the use of types defined in <dspdefs.h>.
++ *! 29-Jul-2000 kc: Created.
++ */
++
++#ifndef DBDCDDEF_
++#define DBDCDDEF_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/mgrpriv.h>                /* for MGR_PROCESSOREXTINFO */
++
++/*
++ *  The following defines are critical elements for the DCD module:
++ *
++ * - DCD_REGKEY enables DCD functions to locate registered DCD objects.
++ * - DCD_REGISTER_SECTION identifies the COFF section where the UUID of
++ *   registered DCD objects are stored.
++ */
++#define DCD_REGKEY              "Software\\TexasInstruments\\DspBridge\\DCD"
++#define DCD_REGISTER_SECTION    ".dcd_register"
++
++/* DCD Manager Object */
++      struct DCD_MANAGER;
++
++/* DCD Node Properties */
++      struct DCD_NODEPROPS {
++              struct DSP_NDBPROPS ndbProps;
++              u32 uMsgSegid;
++              u32 uMsgNotifyType;
++              char *pstrCreatePhaseFxn;
++              char *pstrDeletePhaseFxn;
++              char *pstrExecutePhaseFxn;
++              char *pstrIAlgName;
++
++              /* Dynamic load properties */
++              u16 usLoadType; /* Static, dynamic, overlay */
++              u32 ulDataMemSegMask;   /* Data memory requirements */
++              u32 ulCodeMemSegMask;   /* Code memory requirements */
++      } ;
++
++/* DCD Generic Object Type */
++      struct DCD_GENERICOBJ {
++              union dcdObjUnion {
++                      struct DCD_NODEPROPS nodeObj;   /* node object. */
++                      /* processor object. */
++                      struct DSP_PROCESSORINFO procObj;
++                      /* extended proc object (private) */
++                      struct MGR_PROCESSOREXTINFO extProcObj;
++              } objData;
++      } ;
++
++/* DCD Internal Callback Type */
++       typedef DSP_STATUS(*DCD_REGISTERFXN) (IN struct DSP_UUID *pUuid,
++                                              IN enum DSP_DCDOBJTYPE objType,
++                                              IN void *handle);
++
++#endif                                /* DBDCDDEF_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbdefs.h b/arch/arm/plat-omap/include/dspbridge/dbdefs.h
+new file mode 100644
+index 0000000..9782693
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbdefs.h
+@@ -0,0 +1,580 @@
++/*
++ * dbdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== dbdefs.h ========
++ *  Description:
++ *      Global definitions and constants for DSP/BIOS Bridge.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb  Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb  Added MAPATTR & ELEM_SIZE for Dynamic Memory Mapping feature
++ *! 09-Feb-2004 vp  Added processor ID numbers for DSP and IVA
++ *! 06-Feb-2003 kc  Removed DSP_POSTMESSAGE. Updated IsValid*Event macros.
++ *! 22-Nov-2002 gp  Cleaned up comments, formatting.
++ *!                 Removed unused DSP_ENUMLASTNODE define.
++ *! 13-Feb-2002 jeh Added uSysStackSize to DSP_NDBPROPS.
++ *! 23-Jan-2002 ag  Added #define DSP_SHMSEG0.
++ *! 12-Dec-2001 ag  Added DSP_ESTRMMODE error code.
++ *! 04-Dec-2001 jeh Added DSP_ENOTCONNECTED error code.
++ *! 10-Dec-2001 kc: Modified macros and definitions to disable DSP_POSTMESSAGE.
++ *! 01-Nov-2001 jeh Added DSP_EOVERLAYMEMORY.
++ *! 18-Oct-2001 ag  Added DSP_STRMMODE type.
++ *!                 Added DSP_ENOTSHAREDMEM.
++ *! 21-Sep-2001 ag  Added additional error codes.
++ *! 07-Jun-2001 sg  Made DSPStream_AllocateBuffer fxn name plural.
++ *! 11-May-2001 jeh Changed DSP_NODE_MIN_PRIORITY from 0 to 1. Removed hNode
++ *!                 from DSP_NODEINFO.
++ *! 02-Apr-2001 sg  Added missing error codes, rearranged codes, switched to
++ *!             hex offsets, renamed some codes to match API spec.
++ *! 16-Jan-2001 jeh Added DSP_ESYMBOL, DSP_EUUID.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 05-Dec-2000 ag: Added DSP_RMSxxx user available message command codes.
++ *! 09-Nov-2000 rr: Added DSP_PROCEESORRESTART define; Removed DSP_PBUFFER.
++ *!                 Added DSP_DCD_ENOAUTOREGISTER, DSP_EUSER1-16, DSP_ESTRMFUL
++ *!                 Removed DSP_EDONE. Macros's modified.
++ *! 23-Oct-2000 jeh Replaced DSP_STREAMSTATECHANGE with DSP_STREAMDONE.
++ *! 09-Oct-2000 jeh Updated to version 0.9 DSP Bridge API spec.
++ *! 29-Sep-2000 kc  Added error codes for DCD and REG to simplify use of
++ *!                 these codes within the RM module.
++ *! 27-Sep-2000 jeh Added segid, alignment, uNumBufs to DSP_STREAMATTRIN.
++ *! 29-Aug-2000 jeh Added DSP_NODETYPE enum, changed DSP_EALREADYATTACHED to
++ *!                 DSP_EALREADYCONNECTED. Changed scStreamConnection[1]
++ *!                 to scStreamConnection[16] in DSP_NODEINFO structure.
++ *!                 Added DSP_NOTIFICATION, DSP_STRMATTR. PSTRING changed
++ *!                 back to TCHAR * and moved to dbtype.h.
++ *! 11-Aug-2000 rr: Macros to check valid events and notify masks added.
++ *! 09-Aug-2000 rr: Changed PSTRING to *s8
++ *! 07-Aug-2000 rr: PROC_IDLE/SYNCINIT/UNKNOWN state removed.
++ *! 20-Jul-2000 rr: Updated to version 0.8
++ *! 17-Jul-2000 rr: New PROC states added to the DSP_PROCSTATE.
++ *! 27-Jun-2000 rr: Created from dspapi.h
++ */
++
++#ifndef DBDEFS_
++#define DBDEFS_
++
++#include <linux/types.h>
++
++#include <dspbridge/dbtype.h>         /* GPP side type definitions           */
++#include <dspbridge/std.h>            /* DSP/BIOS type definitions           */
++#include <dspbridge/rms_sh.h>         /* Types shared between GPP and DSP    */
++
++#define PG_SIZE_4K 4096
++#define PG_MASK(pg_size) (~((pg_size)-1))
++#define PG_ALIGN_LOW(addr, pg_size) ((addr) & PG_MASK(pg_size))
++#define PG_ALIGN_HIGH(addr, pg_size) (((addr)+(pg_size)-1) & PG_MASK(pg_size))
++
++/* API return value and calling convention */
++#define DBAPI                       DSP_STATUS
++
++/* Infinite time value for the uTimeout parameter to DSPStream_Select() */
++#define DSP_FOREVER                 (-1)
++
++/* Maximum length of node name, used in DSP_NDBPROPS */
++#define DSP_MAXNAMELEN              32
++
++/* uNotifyType values for the RegisterNotify() functions. */
++#define DSP_SIGNALEVENT             0x00000001
++
++/* Types of events for processors */
++#define DSP_PROCESSORSTATECHANGE    0x00000001
++#define DSP_PROCESSORATTACH         0x00000002
++#define DSP_PROCESSORDETACH         0x00000004
++#define DSP_PROCESSORRESTART        0x00000008
++
++/* DSP exception events (DSP/BIOS and DSP MMU fault) */
++#define DSP_MMUFAULT                0x00000010
++#define DSP_SYSERROR                0x00000020
++#define DSP_EXCEPTIONABORT          0x00000300
++
++/* IVA exception events (IVA MMU fault) */
++#define IVA_MMUFAULT                0x00000040
++/* Types of events for nodes */
++#define DSP_NODESTATECHANGE         0x00000100
++#define DSP_NODEMESSAGEREADY        0x00000200
++
++/* Types of events for streams */
++#define DSP_STREAMDONE              0x00001000
++#define DSP_STREAMIOCOMPLETION      0x00002000
++
++/* Handle definition representing the GPP node in DSPNode_Connect() calls */
++#define DSP_HGPPNODE                0xFFFFFFFF
++
++/* Node directions used in DSPNode_Connect() */
++#define DSP_TONODE                  1
++#define DSP_FROMNODE                2
++
++/* Define Node Minimum and Maximum Priorities */
++#define DSP_NODE_MIN_PRIORITY       1
++#define DSP_NODE_MAX_PRIORITY       15
++
++/* Pre-Defined Message Command Codes available to user: */
++#define DSP_RMSUSERCODESTART RMS_USER /* Start of RMS user cmd codes */
++/* end of user codes */
++#define DSP_RMSUSERCODEEND (RMS_USER + RMS_MAXUSERCODES);
++#define DSP_RMSBUFDESC RMS_BUFDESC    /* MSG contains SM buffer description */
++
++/* Shared memory identifier for MEM segment named "SHMSEG0" */
++#define DSP_SHMSEG0     (u32)(-1)
++
++/* Processor ID numbers */
++#define DSP_UNIT    0
++#define IVA_UNIT    1
++
++#define DSPWORD       unsigned char
++#define DSPWORDSIZE     sizeof(DSPWORD)
++
++/* Success & Failure macros  */
++#define DSP_SUCCEEDED(Status)      likely((s32)(Status) >= 0)
++#define DSP_FAILED(Status)         unlikely((s32)(Status) < 0)
++
++/* Power control enumerations */
++#define PROC_PWRCONTROL             0x8070
++
++#define PROC_PWRMGT_ENABLE          (PROC_PWRCONTROL + 0x3)
++#define PROC_PWRMGT_DISABLE         (PROC_PWRCONTROL + 0x4)
++
++/* Bridge Code Version */
++#define BRIDGE_VERSION_CODE         333
++
++#define    MAX_PROFILES     16
++
++/* Types defined for 'Bridge API */
++      typedef u32 DSP_STATUS; /* API return code type         */
++
++      typedef HANDLE DSP_HNODE;       /* Handle to a DSP Node object  */
++      typedef HANDLE DSP_HPROCESSOR;  /* Handle to a Processor object */
++      typedef HANDLE DSP_HSTREAM;     /* Handle to a Stream object    */
++
++      typedef u32 DSP_PROCFAMILY;     /* Processor family             */
++      typedef u32 DSP_PROCTYPE;       /* Processor type (w/in family) */
++      typedef u32 DSP_RTOSTYPE;       /* Type of DSP RTOS             */
++
++/* Handy Macros */
++#define IsValidProcEvent(x) (((x) == 0) || (((x) & (DSP_PROCESSORSTATECHANGE | \
++                                  DSP_PROCESSORATTACH | \
++                                  DSP_PROCESSORDETACH | \
++                                  DSP_PROCESSORRESTART | \
++                                  DSP_NODESTATECHANGE | \
++                                  DSP_STREAMDONE | \
++                                  DSP_STREAMIOCOMPLETION | \
++                                  DSP_MMUFAULT | \
++                                  DSP_SYSERROR)) && \
++                              !((x) & ~(DSP_PROCESSORSTATECHANGE | \
++                                  DSP_PROCESSORATTACH | \
++                                  DSP_PROCESSORDETACH | \
++                                  DSP_PROCESSORRESTART | \
++                                  DSP_NODESTATECHANGE | \
++                                  DSP_STREAMDONE | \
++                                  DSP_STREAMIOCOMPLETION | \
++                                  DSP_MMUFAULT | \
++                                  DSP_SYSERROR))))
++
++#define IsValidNodeEvent(x)    (((x) == 0) || (((x) & (DSP_NODESTATECHANGE | \
++                              DSP_NODEMESSAGEREADY)) && \
++                              !((x) & ~(DSP_NODESTATECHANGE | \
++                              DSP_NODEMESSAGEREADY))))
++
++#define IsValidStrmEvent(x)     (((x) == 0) || (((x) & (DSP_STREAMDONE | \
++                              DSP_STREAMIOCOMPLETION)) && \
++                              !((x) & ~(DSP_STREAMDONE | \
++                              DSP_STREAMIOCOMPLETION))))
++
++#define IsValidNotifyMask(x)   ((x) & DSP_SIGNALEVENT)
++
++/* The Node UUID structure */
++      struct DSP_UUID {
++              u32 ulData1;
++              u16 usData2;
++              u16 usData3;
++              u8 ucData4;
++              u8 ucData5;
++              u8 ucData6[6];
++      };
++
++/* DCD types */
++      enum DSP_DCDOBJTYPE {
++              DSP_DCDNODETYPE,
++              DSP_DCDPROCESSORTYPE,
++              DSP_DCDLIBRARYTYPE,
++              DSP_DCDCREATELIBTYPE,
++              DSP_DCDEXECUTELIBTYPE,
++              DSP_DCDDELETELIBTYPE
++      } ;
++
++/* Processor states */
++      enum DSP_PROCSTATE {
++              PROC_STOPPED,
++              PROC_LOADED,
++              PROC_RUNNING,
++              PROC_ERROR
++      } ;
++
++/*
++ *  Node types: Message node, task node, xDAIS socket node, and
++ *  device node. _NODE_GPP is used when defining a stream connection
++ *  between a task or socket node and the GPP.
++ *
++ */
++      enum NODE_TYPE {
++              NODE_DEVICE,
++              NODE_TASK,
++              NODE_DAISSOCKET,
++              NODE_MESSAGE,
++              NODE_GPP
++      } ;
++
++/*
++ *  ======== NODE_STATE ========
++ *  Internal node states.
++ */
++      enum NODE_STATE {
++              NODE_ALLOCATED,
++              NODE_CREATED,
++              NODE_RUNNING,
++              NODE_PAUSED,
++              NODE_DONE,
++              NODE_CREATING,
++              NODE_STARTING,
++              NODE_PAUSING,
++              NODE_TERMINATING,
++              NODE_DELETING,
++      } ;
++
++/* Stream states */
++      enum DSP_STREAMSTATE {
++              STREAM_IDLE,
++              STREAM_READY,
++              STREAM_PENDING,
++              STREAM_DONE
++      } ;
++
++/* Stream connect types */
++      enum DSP_CONNECTTYPE {
++              CONNECTTYPE_NODEOUTPUT,
++              CONNECTTYPE_GPPOUTPUT,
++              CONNECTTYPE_NODEINPUT,
++              CONNECTTYPE_GPPINPUT
++      } ;
++
++/* Stream mode types */
++      enum DSP_STRMMODE {
++              STRMMODE_PROCCOPY, /* Processor(s) copy stream data payloads */
++              STRMMODE_ZEROCOPY, /* Strm buffer ptrs swapped no data copied */
++              STRMMODE_LDMA,  /* Local DMA : OMAP's System-DMA device */
++              STRMMODE_RDMA   /* Remote DMA: OMAP's DSP-DMA device */
++      } ;
++
++/* Resource Types */
++      enum DSP_RESOURCEINFOTYPE {
++              DSP_RESOURCE_DYNDARAM = 0,
++              DSP_RESOURCE_DYNSARAM,
++              DSP_RESOURCE_DYNEXTERNAL,
++              DSP_RESOURCE_DYNSRAM,
++              DSP_RESOURCE_PROCLOAD
++      } ;
++
++/* Memory Segment Types */
++      enum DSP_MEMTYPE {
++              DSP_DYNDARAM = 0,
++              DSP_DYNSARAM,
++              DSP_DYNEXTERNAL,
++              DSP_DYNSRAM
++      } ;
++
++/* Memory Flush Types */
++       enum DSP_FLUSHTYPE {
++              PROC_INVALIDATE_MEM = 0,
++              PROC_WRITEBACK_MEM,
++              PROC_WRITEBACK_INVALIDATE_MEM,
++      } ;
++
++/* Memory Segment Status Values */
++      struct DSP_MEMSTAT {
++              u32 ulSize;
++              u32 ulTotalFreeSize;
++              u32 ulLenMaxFreeBlock;
++              u32 ulNumFreeBlocks;
++              u32 ulNumAllocBlocks;
++      } ;
++
++/* Processor Load information Values */
++       struct DSP_PROCLOADSTAT {
++              u32 uCurrLoad;
++              u32 uPredictedLoad;
++              u32 uCurrDspFreq;
++              u32 uPredictedFreq;
++      } ;
++
++/* Attributes for STRM connections between nodes */
++      struct DSP_STRMATTR {
++              u32 uSegid;     /* Memory segment on DSP to allocate buffers */
++              u32 uBufsize;   /* Buffer size (DSP words) */
++              u32 uNumBufs;   /* Number of buffers */
++              u32 uAlignment; /* Buffer alignment */
++              u32 uTimeout;   /* Timeout for blocking STRM calls */
++              enum DSP_STRMMODE lMode;        /* mode of stream when opened */
++              /* DMA chnl id if DSP_STRMMODE is LDMA or RDMA */
++              u32 uDMAChnlId;
++              u32 uDMAPriority;  /* DMA channel priority 0=lowest, >0=high */
++      } ;
++
++/* The DSP_CBDATA structure */
++      struct DSP_CBDATA {
++              u32 cbData;
++              u8 cData[1];
++      } ;
++
++/* The DSP_MSG structure */
++      struct DSP_MSG {
++              u32 dwCmd;
++              u32 dwArg1;
++              u32 dwArg2;
++      } ;
++
++/* The DSP_RESOURCEREQMTS structure for node's resource requirements  */
++      struct DSP_RESOURCEREQMTS {
++              u32 cbStruct;
++              u32 uStaticDataSize;
++              u32 uGlobalDataSize;
++              u32 uProgramMemSize;
++              u32 uWCExecutionTime;
++              u32 uWCPeriod;
++              u32 uWCDeadline;
++              u32 uAvgExectionTime;
++              u32 uMinimumPeriod;
++      } ;
++
++/*
++ * The DSP_STREAMCONNECT structure describes a stream connection
++ * between two nodes, or between a node and the GPP
++ */
++      struct DSP_STREAMCONNECT {
++              u32 cbStruct;
++              enum DSP_CONNECTTYPE lType;
++              u32 uThisNodeStreamIndex;
++              DSP_HNODE hConnectedNode;
++              struct DSP_UUID uiConnectedNodeID;
++              u32 uConnectedNodeStreamIndex;
++      } ;
++
++      struct DSP_NODEPROFS {
++              u32 ulHeapSize;
++      } ;
++
++/* The DSP_NDBPROPS structure reports the attributes of a node */
++      struct DSP_NDBPROPS {
++              u32 cbStruct;
++              struct DSP_UUID uiNodeID;
++              char acName[DSP_MAXNAMELEN];
++              enum NODE_TYPE uNodeType;
++              u32 bCacheOnGPP;
++              struct DSP_RESOURCEREQMTS dspResourceReqmts;
++              s32 iPriority;
++              u32 uStackSize;
++              u32 uSysStackSize;
++              u32 uStackSeg;
++              u32 uMessageDepth;
++              u32 uNumInputStreams;
++              u32 uNumOutputStreams;
++              u32 uTimeout;
++              u32 uCountProfiles;     /* Number of supported profiles */
++              /* Array of profiles */
++              struct DSP_NODEPROFS aProfiles[MAX_PROFILES];
++              u32 uStackSegName; /* Stack Segment Name */
++      } ;
++
++      /* The DSP_NODEATTRIN structure describes the attributes of a
++       * node client */
++      struct DSP_NODEATTRIN {
++              u32 cbStruct;
++              s32 iPriority;
++              u32 uTimeout;
++              u32    uProfileID;
++              /* Reserved, for Bridge Internal use only */
++              u32    uHeapSize;
++              void *pGPPVirtAddr; /* Reserved, for Bridge Internal use only */
++      } ;
++
++      /* The DSP_NODEINFO structure is used to retrieve information
++       * about a node */
++      struct DSP_NODEINFO {
++              u32 cbStruct;
++              struct DSP_NDBPROPS nbNodeDatabaseProps;
++              u32 uExecutionPriority;
++              enum NODE_STATE nsExecutionState;
++              DSP_HNODE hDeviceOwner;
++              u32 uNumberStreams;
++              struct DSP_STREAMCONNECT scStreamConnection[16];
++              u32 uNodeEnv;
++      } ;
++
++      /* The DSP_NODEATTR structure describes the attributes of a node */
++      struct DSP_NODEATTR {
++              u32 cbStruct;
++              struct DSP_NODEATTRIN inNodeAttrIn;
++              u32 uInputs;
++              u32 uOutputs;
++              struct DSP_NODEINFO iNodeInfo;
++      } ;
++
++/*
++ *  Notification type: either the name of an opened event, or an event or
++ *  window handle.
++ */
++      struct DSP_NOTIFICATION {
++              char *psName;
++              HANDLE handle;
++      } ;
++
++/* The DSP_PROCESSORATTRIN structure describes the attributes of a processor */
++      struct DSP_PROCESSORATTRIN{
++              u32 cbStruct;
++              u32 uTimeout;
++      } ;
++
++      enum chipTypes {
++              DSPTYPE_55 = 6,
++              IVA_ARM7 = 0x97,
++              DSPTYPE_64 = 0x99
++      };
++
++/*
++ * The DSP_PROCESSORINFO structure describes basic capabilities of a
++ * DSP processor
++ */
++      struct DSP_PROCESSORINFO {
++              u32 cbStruct;
++              DSP_PROCFAMILY uProcessorFamily;
++              DSP_PROCTYPE uProcessorType;
++              u32 uClockRate;
++              u32 ulInternalMemSize;
++              u32 ulExternalMemSize;
++              u32 uProcessorID;
++              DSP_RTOSTYPE tyRunningRTOS;
++              s32 nNodeMinPriority;
++              s32 nNodeMaxPriority;
++      } ;
++
++/* Error information of last DSP exception signalled to the GPP */
++      struct DSP_ERRORINFO {
++              u32 dwErrMask;
++              u32 dwVal1;
++              u32 dwVal2;
++              u32 dwVal3;
++      } ;
++
++/* The DSP_PROCESSORSTATE structure describes the state of a DSP processor */
++      struct DSP_PROCESSORSTATE {
++              u32 cbStruct;
++              enum DSP_PROCSTATE iState;
++              struct DSP_ERRORINFO errInfo;
++      } ;
++
++/*
++ * The DSP_RESOURCEINFO structure is used to retrieve information about a
++ * processor's resources
++ */
++      struct DSP_RESOURCEINFO {
++              u32 cbStruct;
++              enum DSP_RESOURCEINFOTYPE uResourceType;
++              union {
++                      u32 ulResource;
++                      struct DSP_MEMSTAT memStat;
++                      struct DSP_PROCLOADSTAT procLoadStat;
++              } result;
++      } ;
++
++/*
++ * The DSP_STREAMATTRIN structure describes the attributes of a stream,
++ * including segment and alignment of data buffers allocated with
++ * DSPStream_AllocateBuffers(), if applicable
++ */
++      struct DSP_STREAMATTRIN {
++              u32 cbStruct;
++              u32 uTimeout;
++              u32 uSegment;
++              u32 uAlignment;
++              u32 uNumBufs;
++              enum DSP_STRMMODE lMode;
++              u32 uDMAChnlId;
++              u32 uDMAPriority;
++      } ;
++
++/* The DSP_BUFFERATTR structure describes the attributes of a data buffer */
++      struct DSP_BUFFERATTR {
++              u32 cbStruct;
++              u32 uSegment;
++              u32 uAlignment;
++      } ;
++
++/*
++ *  The DSP_STREAMINFO structure is used to retrieve information
++ *  about a stream.
++ */
++      struct DSP_STREAMINFO {
++              u32 cbStruct;
++              u32 uNumberBufsAllowed;
++              u32 uNumberBufsInStream;
++              u32 ulNumberBytes;
++              HANDLE hSyncObjectHandle;
++              enum DSP_STREAMSTATE ssStreamState;
++      } ;
++
++/* DMM MAP attributes
++It is a bit mask with each bit value indicating a specific attribute
++bit 0 - GPP address type (user virtual=0, physical=1)
++bit 1 - MMU Endianism (Big Endian=1, Little Endian=0)
++bit 2 - MMU mixed page attribute (Mixed/ CPUES=1, TLBES =0)
++bit 3 - MMU element size = 8bit (valid only for non mixed page entries)
++bit 4 - MMU element size = 16bit (valid only for non mixed page entries)
++bit 5 - MMU element size = 32bit (valid only for non mixed page entries)
++bit 6 - MMU element size = 64bit (valid only for non mixed page entries)
++*/
++
++/* Types of mapping attributes */
++
++/* MPU address is virtual and needs to be translated to physical addr */
++#define DSP_MAPVIRTUALADDR          0x00000000
++#define DSP_MAPPHYSICALADDR         0x00000001
++
++/* Mapped data is big endian */
++#define DSP_MAPBIGENDIAN            0x00000002
++#define DSP_MAPLITTLEENDIAN         0x00000000
++
++/* Element size is based on DSP r/w access size */
++#define DSP_MAPMIXEDELEMSIZE        0x00000004
++
++/*
++ * Element size for MMU mapping (8, 16, 32, or 64 bit)
++ * Ignored if DSP_MAPMIXEDELEMSIZE enabled
++ */
++#define DSP_MAPELEMSIZE8            0x00000008
++#define DSP_MAPELEMSIZE16           0x00000010
++#define DSP_MAPELEMSIZE32           0x00000020
++#define DSP_MAPELEMSIZE64           0x00000040
++
++#define DSP_MAPVMALLOCADDR         0x00000080
++
++#define DSP_MAPDONOTLOCK         0x00000100
++
++
++#define GEM_CACHE_LINE_SIZE     128
++#define GEM_L1P_PREFETCH_SIZE   128
++
++#endif                                /* DBDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbg.h b/arch/arm/plat-omap/include/dspbridge/dbg.h
+new file mode 100644
+index 0000000..7f44ff9
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbg.h
+@@ -0,0 +1,110 @@
++/*
++ * dbg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== dbg.h ========
++ *  Purpose:
++ *      Provide debugging services for 'Bridge Mini Drivers.
++ *
++ *  Public Functions:
++ *      DBG_Exit
++ *      DBG_Init
++ *      DBG_Printf
++ *      DBG_Trace
++ *
++ *  Notes:
++ *      WMD's must not call DBG_Init or DBG_Exit.
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Feb-2000 rr: DBG Levels redefined.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 10-Oct-1997 cr: Added DBG_Printf service.
++ *! 29-May-1996 gp: Removed WCD_ prefix.
++ *! 15-May-1996 gp: Created.
++ */
++
++#ifndef DBG_
++#define DBG_
++#include <dspbridge/host_os.h>
++#include <linux/types.h>
++
++/* Levels of trace debug messages: */
++#define DBG_ENTER   (u8)(0x01)        /* Function entry point. */
++#define DBG_LEVEL1  (u8)(0x02)        /* Display debugging state/varibles */
++#define DBG_LEVEL2  (u8)(0x04)        /* Display debugging state/varibles */
++#define DBG_LEVEL3  (u8)(0x08)        /* Display debugging state/varibles */
++#define DBG_LEVEL4  (u8)(0x10)        /* Display debugging state/varibles */
++#define DBG_LEVEL5  (u8)(0x20)        /* Module Init, Exit */
++#define DBG_LEVEL6  (u8)(0x40)        /* Warn SERVICES Failures */
++#define DBG_LEVEL7  (u8)(0x80)        /* Warn Critical Errors */
++
++#if (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE
++
++/*
++ *  ======== DBG_Exit ========
++ *  Purpose:
++ *      Discontinue usage of module; free resources when reference count
++ *      reaches 0.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      DBG initialized.
++ *  Ensures:
++ *      Resources used by module are freed when cRef reaches zero.
++ */
++      extern void DBG_Exit(void);
++
++/*
++ *  ======== DBG_Init ========
++ *  Purpose:
++ *      Initializes private state of DBG module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialized; FALSE if error occured.
++ *  Requires:
++ *  Ensures:
++ */
++      extern bool DBG_Init(void);
++
++/*
++ *  ======== DBG_Trace ========
++ *  Purpose:
++ *      Output a trace message to the debugger, if the given trace level
++ *      is unmasked.
++ *  Parameters:
++ *      bLevel:         Trace level.
++ *      pstrFormat:     sprintf-style format string.
++ *      ...:            Arguments for format string.
++ *  Returns:
++ *      DSP_SOK:        Success, or trace level masked.
++ *      DSP_EFAIL:      On Error.
++ *  Requires:
++ *      DBG initialized.
++ *  Ensures:
++ *      Debug message is printed to debugger output window, if trace level
++ *      is unmasked.
++ */
++      extern DSP_STATUS DBG_Trace(IN u8 bLevel, IN char *pstrFormat, ...);
++#else
++
++#define DBG_Exit(void)
++#define DBG_Init(void) true
++#define DBG_Trace(bLevel, pstrFormat, args...)
++
++#endif             /* (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE */
++
++#endif                                /* DBG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbl.h b/arch/arm/plat-omap/include/dspbridge/dbl.h
+new file mode 100644
+index 0000000..19847f9
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbl.h
+@@ -0,0 +1,354 @@
++/*
++ * dbl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dbl.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 19-Mar-2002 jeh     Pass DBL_Symbol pointer to DBL_getAddr, DBL_getCAddr
++ *!                     to accomodate dynamic loader library.
++ *! 20-Nov-2001 jeh     Removed DBL_loadArgs().
++ *! 24-Sep-2001 jeh     Code review changes.
++ *! 07-Sep-2001 jeh     Added DBL_LoadSect(), DBL_UnloadSect().
++ *! 05-Jun-2001 jeh     Created based on zl.h.
++ */
++
++#ifndef DBL_
++#define DBL_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/dbldefs.h>
++
++/*
++ *  ======== DBL_close ========
++ *  Close library opened with DBL_open.
++ *  Parameters:
++ *      lib             - Handle returned from DBL_open().
++ *  Returns:
++ *  Requires:
++ *      DBL initialized.
++ *      Valid lib.
++ *  Ensures:
++ */
++      extern void DBL_close(struct DBL_LibraryObj *lib);
++
++/*
++ *  ======== DBL_create ========
++ *  Create a target object by specifying the alloc, free, and write
++ *  functions for the target.
++ *  Parameters:
++ *      pTarget         - Location to store target handle on output.
++ *      pAttrs          - Attributes.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Memory allocation failed.
++ *  Requires:
++ *      DBL initialized.
++ *      pAttrs != NULL.
++ *      pTarget != NULL;
++ *  Ensures:
++ *      Success:        *pTarget != NULL.
++ *      Failure:        *pTarget == NULL.
++ */
++      extern DSP_STATUS DBL_create(struct DBL_TargetObj **pTarget,
++                                   struct DBL_Attrs *pAttrs);
++
++/*
++ *  ======== DBL_delete ========
++ *  Delete target object and free resources for any loaded libraries.
++ *  Parameters:
++ *      target          - Handle returned from DBL_Create().
++ *  Returns:
++ *  Requires:
++ *      DBL initialized.
++ *      Valid target.
++ *  Ensures:
++ */
++      extern void DBL_delete(struct DBL_TargetObj *target);
++
++/*
++ *  ======== DBL_exit ========
++ *  Discontinue use of DBL module.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      cRefs > 0.
++ *  Ensures:
++ *      cRefs >= 0.
++ */
++      extern void DBL_exit(void);
++
++/*
++ *  ======== DBL_getAddr ========
++ *  Get address of name in the specified library.
++ *  Parameters:
++ *      lib             - Handle returned from DBL_open().
++ *      name            - Name of symbol
++ *      ppSym           - Location to store symbol address on output.
++ *  Returns:
++ *      TRUE:           Success.
++ *      FALSE:          Symbol not found.
++ *  Requires:
++ *      DBL initialized.
++ *      Valid lib.
++ *      name != NULL.
++ *      pAddr != NULL.
++ *  Ensures:
++ */
++      extern bool DBL_getAddr(struct DBL_LibraryObj *lib, char *name,
++                              struct DBL_Symbol **ppSym);
++
++/*
++ *  ======== DBL_getAttrs ========
++ *  Retrieve the attributes of the target.
++ *  Parameters:
++ *      target          - Handle returned from DBL_Create().
++ *      pAttrs          - Location to store attributes on output.
++ *  Returns:
++ *  Requires:
++ *      DBL initialized.
++ *      Valid target.
++ *      pAttrs != NULL.
++ *  Ensures:
++ */
++      extern void DBL_getAttrs(struct DBL_TargetObj *target,
++                               struct DBL_Attrs *pAttrs);
++
++/*
++ *  ======== DBL_getCAddr ========
++ *  Get address of "C" name in the specified library.
++ *  Parameters:
++ *      lib             - Handle returned from DBL_open().
++ *      name            - Name of symbol
++ *      ppSym           - Location to store symbol address on output.
++ *  Returns:
++ *      TRUE:           Success.
++ *      FALSE:          Symbol not found.
++ *  Requires:
++ *      DBL initialized.
++ *      Valid lib.
++ *      name != NULL.
++ *      pAddr != NULL.
++ *  Ensures:
++ */
++      extern bool DBL_getCAddr(struct DBL_LibraryObj *lib, char *name,
++                               struct DBL_Symbol **ppSym);
++
++/*
++ *  ======== DBL_getEntry ========
++ *  Get program entry point.
++ *
++ *  Parameters:
++ *      lib             - Handle returned from DBL_open().
++ *      pEntry          - Location to store entry address on output.
++ *  Returns:
++ *      TRUE:           Success.
++ *      FALSE:          Failure.
++ *  Requires:
++ *      DBL initialized.
++ *      Valid lib.
++ *      pEntry != NULL.
++ *  Ensures:
++ */
++      extern bool DBL_getEntry(struct DBL_LibraryObj *lib, u32 *pEntry);
++
++/*
++ *  ======== DBL_getSect ========
++ *  Get address and size of a named section.
++ *  Parameters:
++ *      lib             - Library handle returned from DBL_open().
++ *      name            - Name of section.
++ *      pAddr           - Location to store section address on output.
++ *      pSize           - Location to store section size on output.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_ENOSECT:    Section not found.
++ *  Requires:
++ *      DBL initialized.
++ *      Valid lib.
++ *      name != NULL.
++ *      pAddr != NULL;
++ *      pSize != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS DBL_getSect(struct DBL_LibraryObj *lib, char *name,
++                                    u32 *pAddr, u32 *pSize);
++
++/*
++ *  ======== DBL_init ========
++ *  Initialize DBL module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE:           Success.
++ *      FALSE:          Failure.
++ *  Requires:
++ *      cRefs >= 0.
++ *  Ensures:
++ *      Success:        cRefs > 0.
++ *      Failure:        cRefs >= 0.
++ */
++      extern bool DBL_init(void);
++
++/*
++ *  ======== DBL_load ========
++ *  Add symbols/code/data defined in file to that already present on
++ *  the target.
++ *
++ *  Parameters:
++ *      lib             - Library handle returned from DBL_open().
++ *      flags           - Specifies whether loading code, data, and/or symbols.
++ *      attrs           - May contain write, alloc, and free functions.
++ *      pulEntry        - Location to store program entry on output.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFREAD:     File read failed.
++ *      DSP_EFWRITE:    Write to target failed.
++ *  Requires:
++ *      DBL initialized.
++ *      Valid lib.
++ *      pEntry != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS DBL_load(struct DBL_LibraryObj *lib, DBL_Flags flags,
++                                 struct DBL_Attrs *attrs, u32 *pEntry);
++
++/*
++ *  ======== DBL_loadSect ========
++ *  Load a named section from an library (for overlay support).
++ *  Parameters:
++ *      lib             - Handle returned from DBL_open().
++ *      sectName        - Name of section to load.
++ *      attrs           - Contains write function and handle to pass to it.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_ENOSECT:    Section not found.
++ *      DSP_EFWRITE:    Write function failed.
++ *  Requires:
++ *      Valid lib.
++ *      sectName != NULL.
++ *      attrs != NULL.
++ *      attrs->write != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS DBL_loadSect(struct DBL_LibraryObj *lib,
++                                     char *sectName,
++                                     struct DBL_Attrs *attrs);
++
++/*
++ *  ======== DBL_open ========
++ *  DBL_open() returns a library handle that can be used to load/unload
++ *  the symbols/code/data via DBL_load()/DBL_unload().
++ *  Parameters:
++ *      target          - Handle returned from DBL_create().
++ *      file            - Name of file to open.
++ *      flags           - Specifies whether to load symbols now.
++ *      pLib            - Location to store library handle on output.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EMEMORY:        Memory allocation failure.
++ *      DSP_EFOPEN:         File open failure.
++ *      DSP_EFREAD:         File read failure.
++ *      DSP_ECORRUPTFILE:   Unable to determine target type.
++ *  Requires:
++ *      DBL initialized.
++ *      Valid target.
++ *      file != NULL.
++ *      pLib != NULL.
++ *      struct DBL_Attrs fopen function non-NULL.
++ *  Ensures:
++ *      Success:        Valid *pLib.
++ *      Failure:        *pLib == NULL.
++ */
++      extern DSP_STATUS DBL_open(struct DBL_TargetObj *target, char *file,
++                                 DBL_Flags flags,
++                                 struct DBL_LibraryObj **pLib);
++
++/*
++ *  ======== DBL_readSect ========
++ *  Read COFF section into a character buffer.
++ *  Parameters:
++ *      lib             - Library handle returned from DBL_open().
++ *      name            - Name of section.
++ *      pBuf            - Buffer to write section contents into.
++ *      size            - Buffer size
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_ENOSECT:    Named section does not exists.
++ *  Requires:
++ *      DBL initialized.
++ *      Valid lib.
++ *      name != NULL.
++ *      pBuf != NULL.
++ *      size != 0.
++ *  Ensures:
++ */
++      extern DSP_STATUS DBL_readSect(struct DBL_LibraryObj *lib, char *name,
++                                     char *pBuf, u32 size);
++
++/*
++ *  ======== DBL_setAttrs ========
++ *  Set the attributes of the target.
++ *  Parameters:
++ *      target          - Handle returned from DBL_create().
++ *      pAttrs          - New attributes.
++ *  Returns:
++ *  Requires:
++ *      DBL initialized.
++ *      Valid target.
++ *      pAttrs != NULL.
++ *  Ensures:
++ */
++      extern void DBL_setAttrs(struct DBL_TargetObj *target,
++                               struct DBL_Attrs *pAttrs);
++
++/*
++ *  ======== DBL_unload ========
++ *  Remove the symbols/code/data corresponding to the library lib.
++ *  Parameters:
++ *      lib             - Handle returned from DBL_open().
++ *      attrs           - Contains free() function and handle to pass to it.
++ *  Returns:
++ *  Requires:
++ *      DBL initialized.
++ *      Valid lib.
++ *  Ensures:
++ */
++      extern void DBL_unload(struct DBL_LibraryObj *lib,
++                             struct DBL_Attrs *attrs);
++
++/*
++ *  ======== DBL_unloadSect ========
++ *  Unload a named section from an library (for overlay support).
++ *  Parameters:
++ *      lib             - Handle returned from DBL_open().
++ *      sectName        - Name of section to load.
++ *      attrs           - Contains free() function and handle to pass to it.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_ENOSECT:    Named section not found.
++ *  Requires:
++ *      DBL initialized.
++ *      Valid lib.
++ *      sectName != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS DBL_unloadSect(struct DBL_LibraryObj *lib,
++                                       char *sectName,
++                                       struct DBL_Attrs *attrs);
++
++#endif                                /* DBL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbldefs.h b/arch/arm/plat-omap/include/dspbridge/dbldefs.h
+new file mode 100644
+index 0000000..79b9e54
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbldefs.h
+@@ -0,0 +1,155 @@
++/*
++ * dbldefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dbldefs.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 19-Mar-2002 jeh     Added DBL_Fxns type (to make it easier to switch
++ *!                     between different loaders).
++ *! 28-Sep-2001 jeh     Created from zl.h.
++ */
++#ifndef DBLDEFS_
++#define DBLDEFS_
++
++/*
++ *  Bit masks for DBL_Flags.
++ */
++#define DBL_NOLOAD   0x0      /* Don't load symbols, code, or data */
++#define DBL_SYMB     0x1      /* load symbols */
++#define DBL_CODE     0x2      /* load code */
++#define DBL_DATA     0x4      /* load data */
++#define DBL_DYNAMIC  0x8      /* dynamic load */
++#define DBL_BSS      0x20     /* Unitialized section */
++
++#define DBL_MAXPATHLENGTH       255
++
++
++
++/*
++ *  ======== DBL_Flags ========
++ *  Specifies whether to load code, data, or symbols
++ */
++typedef s32 DBL_Flags;
++
++/*
++ *  ======== DBL_SectInfo ========
++ *  For collecting info on overlay sections
++ */
++struct DBL_SectInfo {
++      const char *name;       /* name of section */
++      u32 runAddr;            /* run address of section */
++      u32 loadAddr;           /* load address of section */
++      u32 size;               /* size of section (target MAUs) */
++      DBL_Flags type;         /* Code, data, or BSS */
++} ;
++
++/*
++ *  ======== DBL_Symbol ========
++ *  (Needed for dynamic load library)
++ */
++struct DBL_Symbol {
++      u32 value;
++};
++
++/*
++ *  ======== DBL_AllocFxn ========
++ *  Allocate memory function.  Allocate or reserve (if reserved == TRUE)
++ *  "size" bytes of memory from segment "space" and return the address in
++ *  *dspAddr (or starting at *dspAddr if reserve == TRUE). Returns 0 on
++ *  success, or an error code on failure.
++ */
++typedef s32(*DBL_AllocFxn) (void *hdl, s32 space, u32 size, u32 align,
++                      u32 *dspAddr, s32 segId, s32 req, bool reserved);
++
++
++
++/*
++ *  ======== DBL_FreeFxn ========
++ *  Free memory function.  Free, or unreserve (if reserved == TRUE) "size"
++ *  bytes of memory from segment "space"
++ */
++typedef bool(*DBL_FreeFxn) (void *hdl, u32 addr, s32 space, u32 size,
++                          bool reserved);
++
++/*
++ *  ======== DBL_LogWriteFxn ========
++ *  Function to call when writing data from a section, to log the info.
++ *  Can be NULL if no logging is required.
++ */
++typedef DSP_STATUS(*DBL_LogWriteFxn) (void *handle, struct DBL_SectInfo *sect,
++                                    u32 addr, u32 nBytes);
++
++
++/*
++ *  ======== DBL_SymLookup ========
++ *  Symbol lookup function - Find the symbol name and return its value.
++ *
++ *  Parameters:
++ *      handle          - Opaque handle
++ *      pArg            - Opaque argument.
++ *      name            - Name of symbol to lookup.
++ *      sym             - Location to store address of symbol structure.
++ *
++ *  Returns:
++ *      TRUE:           Success (symbol was found).
++ *      FALSE:          Failed to find symbol.
++ */
++typedef bool(*DBL_SymLookup) (void *handle, void *pArg, void *rmmHandle,
++                            const char *name, struct DBL_Symbol **sym);
++
++
++/*
++ *  ======== DBL_WriteFxn ========
++ *  Write memory function.  Write "n" HOST bytes of memory to segment "mtype"
++ *  starting at address "dspAddr" from the buffer "buf".  The buffer is
++ *  formatted as an array of words appropriate for the DSP.
++ */
++typedef s32(*DBL_WriteFxn) (void *hdl, u32 dspAddr, void *buf,
++                          u32 n, s32 mtype);
++
++/*
++ *  ======== DBL_Attrs ========
++ */
++struct DBL_Attrs {
++      DBL_AllocFxn alloc;
++      DBL_FreeFxn free;
++      void *rmmHandle;        /* Handle to pass to alloc, free functions */
++      DBL_WriteFxn write;
++      void *wHandle;          /* Handle to pass to write, cinit function */
++
++      DBL_LogWriteFxn logWrite;
++      void *logWriteHandle;
++
++      /* Symbol matching function and handle to pass to it */
++      DBL_SymLookup symLookup;
++      void *symHandle;
++      void *symArg;
++
++      /*
++       *  These file manipulation functions should be compatible with the
++       *  "C" run time library functions of the same name.
++       */
++      s32(*fread) (void *, size_t, size_t, void *);
++      s32(*fseek) (void *, long, int);
++      s32(*ftell) (void *);
++      s32(*fclose) (void *);
++      void *(*fopen) (const char *, const char *);
++} ;
++
++#endif                                /* DBLDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbll.h b/arch/arm/plat-omap/include/dspbridge/dbll.h
+new file mode 100644
+index 0000000..c3aa212
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbll.h
+@@ -0,0 +1,70 @@
++/*
++ * dbll.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dbll.h ========
++ *  DSP/BIOS Bridge Dynamic load library module interface. Function header
++ *  comments are in the file dblldefs.h.
++ *
++ *! Revision History
++ *! ================
++ *! 31-Jul-2002 jeh     Removed function comments (now in dblldefs.h).
++ *! 17-Apr-2002 jeh     Created based on zl.h.
++ */
++
++#ifndef DBLL_
++#define DBLL_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/dblldefs.h>
++
++      extern void DBLL_close(struct DBLL_LibraryObj *lib);
++      extern DSP_STATUS DBLL_create(struct DBLL_TarObj **pTarget,
++                                    struct DBLL_Attrs *pAttrs);
++      extern void DBLL_delete(struct DBLL_TarObj *target);
++      extern void DBLL_exit(void);
++      extern bool DBLL_getAddr(struct DBLL_LibraryObj *lib, char *name,
++                               struct DBLL_Symbol **ppSym);
++      extern void DBLL_getAttrs(struct DBLL_TarObj *target,
++                                struct DBLL_Attrs *pAttrs);
++      extern bool DBLL_getCAddr(struct DBLL_LibraryObj *lib, char *name,
++                                struct DBLL_Symbol **ppSym);
++      extern DSP_STATUS DBLL_getSect(struct DBLL_LibraryObj *lib, char *name,
++                                     u32 *pAddr, u32 *pSize);
++      extern bool DBLL_init(void);
++      extern DSP_STATUS DBLL_load(struct DBLL_LibraryObj *lib,
++                                  DBLL_Flags flags,
++                                  struct DBLL_Attrs *attrs, u32 *pEntry);
++      extern DSP_STATUS DBLL_loadSect(struct DBLL_LibraryObj *lib,
++                                      char *sectName,
++                                      struct DBLL_Attrs *attrs);
++      extern DSP_STATUS DBLL_open(struct DBLL_TarObj *target, char *file,
++                                  DBLL_Flags flags,
++                                  struct DBLL_LibraryObj **pLib);
++      extern DSP_STATUS DBLL_readSect(struct DBLL_LibraryObj *lib,
++                                      char *name,
++                                      char *pBuf, u32 size);
++      extern void DBLL_setAttrs(struct DBLL_TarObj *target,
++                                struct DBLL_Attrs *pAttrs);
++      extern void DBLL_unload(struct DBLL_LibraryObj *lib,
++                              struct DBLL_Attrs *attrs);
++      extern DSP_STATUS DBLL_unloadSect(struct DBLL_LibraryObj *lib,
++                                        char *sectName,
++                                        struct DBLL_Attrs *attrs);
++
++#endif                                /* DBLL_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/dblldefs.h b/arch/arm/plat-omap/include/dspbridge/dblldefs.h
+new file mode 100644
+index 0000000..2361ce8
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dblldefs.h
+@@ -0,0 +1,509 @@
++/*
++ * dblldefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dblldefs.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 08-Apr-2003 map       Consolidated DBL into DBLL name
++ *! 19-Mar-2002 jeh     Added DBL_Fxns type (to make it easier to switch
++ *!                     between different loaders).
++ *! 28-Sep-2001 jeh     Created from zl.h.
++ */
++#ifndef DBLLDEFS_
++#define DBLLDEFS_
++
++/*
++ *  Bit masks for DBL_Flags.
++ */
++#define DBLL_NOLOAD   0x0     /* Don't load symbols, code, or data */
++#define DBLL_SYMB     0x1     /* load symbols */
++#define DBLL_CODE     0x2     /* load code */
++#define DBLL_DATA     0x4     /* load data */
++#define DBLL_DYNAMIC  0x8     /* dynamic load */
++#define DBLL_BSS      0x20    /* Unitialized section */
++
++#define DBLL_MAXPATHLENGTH       255
++
++
++/*
++ *  ======== DBLL_Target ========
++ *
++ */
++struct DBLL_TarObj;
++
++/*
++ *  ======== DBLL_Flags ========
++ *  Specifies whether to load code, data, or symbols
++ */
++typedef s32 DBLL_Flags;
++
++/*
++ *  ======== DBLL_Library ========
++ *
++ */
++struct DBLL_LibraryObj;
++
++/*
++ *  ======== DBLL_SectInfo ========
++ *  For collecting info on overlay sections
++ */
++struct DBLL_SectInfo {
++      const char *name;       /* name of section */
++      u32 runAddr;            /* run address of section */
++      u32 loadAddr;           /* load address of section */
++      u32 size;               /* size of section (target MAUs) */
++      DBLL_Flags type;        /* Code, data, or BSS */
++} ;
++
++/*
++ *  ======== DBLL_Symbol ========
++ *  (Needed for dynamic load library)
++ */
++struct DBLL_Symbol {
++      u32 value;
++};
++
++/*
++ *  ======== DBLL_AllocFxn ========
++ *  Allocate memory function.  Allocate or reserve (if reserved == TRUE)
++ *  "size" bytes of memory from segment "space" and return the address in
++ *  *dspAddr (or starting at *dspAddr if reserve == TRUE). Returns 0 on
++ *  success, or an error code on failure.
++ */
++typedef s32(*DBLL_AllocFxn) (void *hdl, s32 space, u32 size, u32 align,
++                           u32 *dspAddr, s32 segId, s32 req,
++                           bool reserved);
++
++/*
++ *  ======== DBLL_CloseFxn ========
++ */
++typedef s32(*DBLL_FCloseFxn) (void *);
++
++/*
++ *  ======== DBLL_FreeFxn ========
++ *  Free memory function.  Free, or unreserve (if reserved == TRUE) "size"
++ *  bytes of memory from segment "space"
++ */
++typedef bool(*DBLL_FreeFxn) (void *hdl, u32 addr, s32 space, u32 size,
++                           bool reserved);
++
++/*
++ *  ======== DBLL_FOpenFxn ========
++ */
++typedef void *(*DBLL_FOpenFxn) (const char *, const char *);
++
++/*
++ *  ======== DBLL_LogWriteFxn ========
++ *  Function to call when writing data from a section, to log the info.
++ *  Can be NULL if no logging is required.
++ */
++typedef DSP_STATUS(*DBLL_LogWriteFxn)(void *handle, struct DBLL_SectInfo *sect,
++                                     u32 addr, u32 nBytes);
++
++/*
++ *  ======== DBLL_ReadFxn ========
++ */
++typedef s32(*DBLL_ReadFxn) (void *, size_t, size_t, void *);
++
++/*
++ *  ======== DBLL_SeekFxn ========
++ */
++typedef s32(*DBLL_SeekFxn) (void *, long, int);
++
++/*
++ *  ======== DBLL_SymLookup ========
++ *  Symbol lookup function - Find the symbol name and return its value.
++ *
++ *  Parameters:
++ *      handle          - Opaque handle
++ *      pArg            - Opaque argument.
++ *      name            - Name of symbol to lookup.
++ *      sym             - Location to store address of symbol structure.
++ *
++ *  Returns:
++ *      TRUE:           Success (symbol was found).
++ *      FALSE:          Failed to find symbol.
++ */
++typedef bool(*DBLL_SymLookup) (void *handle, void *pArg, void *rmmHandle,
++                             const char *name, struct DBLL_Symbol **sym);
++
++/*
++ *  ======== DBLL_TellFxn ========
++ */
++typedef s32(*DBLL_TellFxn) (void *);
++
++/*
++ *  ======== DBLL_WriteFxn ========
++ *  Write memory function.  Write "n" HOST bytes of memory to segment "mtype"
++ *  starting at address "dspAddr" from the buffer "buf".  The buffer is
++ *  formatted as an array of words appropriate for the DSP.
++ */
++typedef s32(*DBLL_WriteFxn) (void *hdl, u32 dspAddr, void *buf,
++                           u32 n, s32 mtype);
++
++/*
++ *  ======== DBLL_Attrs ========
++ */
++struct DBLL_Attrs {
++      DBLL_AllocFxn alloc;
++      DBLL_FreeFxn free;
++      void *rmmHandle;        /* Handle to pass to alloc, free functions */
++      DBLL_WriteFxn write;
++      void *wHandle;          /* Handle to pass to write, cinit function */
++      bool baseImage;
++      DBLL_LogWriteFxn logWrite;
++      void *logWriteHandle;
++
++      /* Symbol matching function and handle to pass to it */
++      DBLL_SymLookup symLookup;
++      void *symHandle;
++      void *symArg;
++
++      /*
++       *  These file manipulation functions should be compatible with the
++       *  "C" run time library functions of the same name.
++       */
++       s32(*fread) (void *, size_t, size_t, void *);
++       s32(*fseek) (void *, long, int);
++       s32(*ftell) (void *);
++       s32(*fclose) (void *);
++      void *(*fopen) (const char *, const char *);
++} ;
++
++/*
++ *  ======== DBLL_close ========
++ *  Close library opened with DBLL_open.
++ *  Parameters:
++ *      lib             - Handle returned from DBLL_open().
++ *  Returns:
++ *  Requires:
++ *      DBL initialized.
++ *      Valid lib.
++ *  Ensures:
++ */
++typedef void(*DBLL_CloseFxn) (struct DBLL_LibraryObj *library);
++
++/*
++ *  ======== DBLL_create ========
++ *  Create a target object, specifying the alloc, free, and write functions.
++ *  Parameters:
++ *      pTarget         - Location to store target handle on output.
++ *      pAttrs          - Attributes.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Memory allocation failed.
++ *  Requires:
++ *      DBL initialized.
++ *      pAttrs != NULL.
++ *      pTarget != NULL;
++ *  Ensures:
++ *      Success:        *pTarget != NULL.
++ *      Failure:        *pTarget == NULL.
++ */
++typedef DSP_STATUS(*DBLL_CreateFxn)(struct DBLL_TarObj **pTarget,
++                                  struct DBLL_Attrs *attrs);
++
++/*
++ *  ======== DBLL_delete ========
++ *  Delete target object and free resources for any loaded libraries.
++ *  Parameters:
++ *      target          - Handle returned from DBLL_Create().
++ *  Returns:
++ *  Requires:
++ *      DBL initialized.
++ *      Valid target.
++ *  Ensures:
++ */
++typedef void(*DBLL_DeleteFxn) (struct DBLL_TarObj *target);
++
++/*
++ *  ======== DBLL_exit ========
++ *  Discontinue use of DBL module.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      cRefs > 0.
++ *  Ensures:
++ *      cRefs >= 0.
++ */
++typedef void(*DBLL_ExitFxn) (void);
++
++/*
++ *  ======== DBLL_getAddr ========
++ *  Get address of name in the specified library.
++ *  Parameters:
++ *      lib             - Handle returned from DBLL_open().
++ *      name            - Name of symbol
++ *      ppSym           - Location to store symbol address on output.
++ *  Returns:
++ *      TRUE:           Success.
++ *      FALSE:          Symbol not found.
++ *  Requires:
++ *      DBL initialized.
++ *      Valid library.
++ *      name != NULL.
++ *      ppSym != NULL.
++ *  Ensures:
++ */
++typedef bool(*DBLL_GetAddrFxn) (struct DBLL_LibraryObj *lib, char *name,
++                              struct DBLL_Symbol **ppSym);
++
++/*
++ *  ======== DBLL_getAttrs ========
++ *  Retrieve the attributes of the target.
++ *  Parameters:
++ *      target          - Handle returned from DBLL_Create().
++ *      pAttrs          - Location to store attributes on output.
++ *  Returns:
++ *  Requires:
++ *      DBL initialized.
++ *      Valid target.
++ *      pAttrs != NULL.
++ *  Ensures:
++ */
++typedef void(*DBLL_GetAttrsFxn) (struct DBLL_TarObj *target,
++                               struct DBLL_Attrs *attrs);
++
++/*
++ *  ======== DBLL_getCAddr ========
++ *  Get address of "C" name on the specified library.
++ *  Parameters:
++ *      lib             - Handle returned from DBLL_open().
++ *      name            - Name of symbol
++ *      ppSym           - Location to store symbol address on output.
++ *  Returns:
++ *      TRUE:           Success.
++ *      FALSE:          Symbol not found.
++ *  Requires:
++ *      DBL initialized.
++ *      Valid target.
++ *      name != NULL.
++ *      ppSym != NULL.
++ *  Ensures:
++ */
++typedef bool(*DBLL_GetCAddrFxn) (struct DBLL_LibraryObj *lib, char *name,
++                               struct DBLL_Symbol **ppSym);
++
++/*
++ *  ======== DBLL_getSect ========
++ *  Get address and size of a named section.
++ *  Parameters:
++ *      lib             - Library handle returned from DBLL_open().
++ *      name            - Name of section.
++ *      pAddr           - Location to store section address on output.
++ *      pSize           - Location to store section size on output.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_ENOSECT:    Section not found.
++ *  Requires:
++ *      DBL initialized.
++ *      Valid lib.
++ *      name != NULL.
++ *      pAddr != NULL;
++ *      pSize != NULL.
++ *  Ensures:
++ */
++typedef DSP_STATUS(*DBLL_GetSectFxn) (struct DBLL_LibraryObj *lib, char *name,
++                                    u32 *addr, u32 *size);
++
++/*
++ *  ======== DBLL_init ========
++ *  Initialize DBL module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE:           Success.
++ *      FALSE:          Failure.
++ *  Requires:
++ *      cRefs >= 0.
++ *  Ensures:
++ *      Success:        cRefs > 0.
++ *      Failure:        cRefs >= 0.
++ */
++typedef bool(*DBLL_InitFxn) (void);
++
++/*
++ *  ======== DBLL_load ========
++ *  Load library onto the target.
++ *
++ *  Parameters:
++ *      lib             - Library handle returned from DBLL_open().
++ *      flags           - Load code, data and/or symbols.
++ *      attrs           - May contain alloc, free, and write function.
++ *      pulEntry        - Location to store program entry on output.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFREAD:     File read failed.
++ *      DSP_EFWRITE:    Write to target failed.
++ *      DSP_EDYNLOAD:   Failure in dynamic loader library.
++ *  Requires:
++ *      DBL initialized.
++ *      Valid lib.
++ *      pEntry != NULL.
++ *  Ensures:
++ */
++typedef DSP_STATUS(*DBLL_LoadFxn) (struct DBLL_LibraryObj *lib,
++                                 DBLL_Flags flags,
++                                 struct DBLL_Attrs *attrs, u32 *entry);
++
++/*
++ *  ======== DBLL_loadSect ========
++ *  Load a named section from an library (for overlay support).
++ *  Parameters:
++ *      lib             - Handle returned from DBLL_open().
++ *      sectName        - Name of section to load.
++ *      attrs           - Contains write function and handle to pass to it.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_ENOSECT:    Section not found.
++ *      DSP_EFWRITE:    Write function failed.
++ *      DSP_ENOTIMPL:   Function not implemented.
++ *  Requires:
++ *      Valid lib.
++ *      sectName != NULL.
++ *      attrs != NULL.
++ *      attrs->write != NULL.
++ *  Ensures:
++ */
++typedef DSP_STATUS(*DBLL_LoadSectFxn) (struct DBLL_LibraryObj *lib,
++                                     char *pszSectName,
++                                     struct DBLL_Attrs *attrs);
++
++/*
++ *  ======== DBLL_open ========
++ *  DBLL_open() returns a library handle that can be used to load/unload
++ *  the symbols/code/data via DBLL_load()/DBLL_unload().
++ *  Parameters:
++ *      target          - Handle returned from DBLL_create().
++ *      file            - Name of file to open.
++ *      flags           - If flags & DBLL_SYMB, load symbols.
++ *      pLib            - Location to store library handle on output.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EMEMORY:        Memory allocation failure.
++ *      DSP_EFOPEN:         File open failure.
++ *      DSP_EFREAD:         File read failure.
++ *      DSP_ECORRUPTFILE:   Unable to determine target type.
++ *  Requires:
++ *      DBL initialized.
++ *      Valid target.
++ *      file != NULL.
++ *      pLib != NULL.
++ *      DBLL_Attrs fopen function non-NULL.
++ *  Ensures:
++ *      Success:        Valid *pLib.
++ *      Failure:        *pLib == NULL.
++ */
++typedef DSP_STATUS(*DBLL_OpenFxn) (struct DBLL_TarObj *target, char *file,
++                                 DBLL_Flags flags,
++                                 struct DBLL_LibraryObj **pLib);
++
++/*
++ *  ======== DBLL_readSect ========
++ *  Read COFF section into a character buffer.
++ *  Parameters:
++ *      lib             - Library handle returned from DBLL_open().
++ *      name            - Name of section.
++ *      pBuf            - Buffer to write section contents into.
++ *      size            - Buffer size
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_ENOSECT:    Named section does not exists.
++ *  Requires:
++ *      DBL initialized.
++ *      Valid lib.
++ *      name != NULL.
++ *      pBuf != NULL.
++ *      size != 0.
++ *  Ensures:
++ */
++typedef DSP_STATUS(*DBLL_ReadSectFxn) (struct DBLL_LibraryObj *lib, char *name,
++                                     char *content, u32 uContentSize);
++
++/*
++ *  ======== DBLL_setAttrs ========
++ *  Set the attributes of the target.
++ *  Parameters:
++ *      target          - Handle returned from DBLL_create().
++ *      pAttrs          - New attributes.
++ *  Returns:
++ *  Requires:
++ *      DBL initialized.
++ *      Valid target.
++ *      pAttrs != NULL.
++ *  Ensures:
++ */
++typedef void(*DBLL_SetAttrsFxn)(struct DBLL_TarObj *target,
++                              struct DBLL_Attrs *attrs);
++
++/*
++ *  ======== DBLL_unload ========
++ *  Unload library loaded with DBLL_load().
++ *  Parameters:
++ *      lib             - Handle returned from DBLL_open().
++ *      attrs           - Contains free() function and handle to pass to it.
++ *  Returns:
++ *  Requires:
++ *      DBL initialized.
++ *      Valid lib.
++ *  Ensures:
++ */
++typedef void(*DBLL_UnloadFxn) (struct DBLL_LibraryObj *library,
++                             struct DBLL_Attrs *attrs);
++
++/*
++ *  ======== DBLL_unloadSect ========
++ *  Unload a named section from an library (for overlay support).
++ *  Parameters:
++ *      lib             - Handle returned from DBLL_open().
++ *      sectName        - Name of section to load.
++ *      attrs           - Contains free() function and handle to pass to it.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_ENOSECT:    Named section not found.
++ *      DSP_ENOTIMPL
++ *  Requires:
++ *      DBL initialized.
++ *      Valid lib.
++ *      sectName != NULL.
++ *  Ensures:
++ */
++typedef DSP_STATUS(*DBLL_UnloadSectFxn) (struct DBLL_LibraryObj *lib,
++                                       char *pszSectName,
++                                       struct DBLL_Attrs *attrs);
++
++struct DBLL_Fxns {
++      DBLL_CloseFxn closeFxn;
++      DBLL_CreateFxn createFxn;
++      DBLL_DeleteFxn deleteFxn;
++      DBLL_ExitFxn exitFxn;
++      DBLL_GetAttrsFxn getAttrsFxn;
++      DBLL_GetAddrFxn getAddrFxn;
++      DBLL_GetCAddrFxn getCAddrFxn;
++      DBLL_GetSectFxn getSectFxn;
++      DBLL_InitFxn initFxn;
++      DBLL_LoadFxn loadFxn;
++      DBLL_LoadSectFxn loadSectFxn;
++      DBLL_OpenFxn openFxn;
++      DBLL_ReadSectFxn readSectFxn;
++      DBLL_SetAttrsFxn setAttrsFxn;
++      DBLL_UnloadFxn unloadFxn;
++      DBLL_UnloadSectFxn unloadSectFxn;
++} ;
++
++#endif                                /* DBLDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbof.h b/arch/arm/plat-omap/include/dspbridge/dbof.h
+new file mode 100644
+index 0000000..54f4250
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbof.h
+@@ -0,0 +1,117 @@
++/*
++ * dbof.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dbof.h ========
++ *  Description:
++ *      Defines and typedefs for DSP/BIOS Bridge Object File Format (DBOF).
++ *
++ *! Revision History
++ *! ================
++ *! 12-Jul-2002 jeh     Added defines for DBOF_SectHdr page.
++ *! 12-Oct-2001 jeh     Converted to std.h format.
++ *! 07-Sep-2001 jeh     Added overlay support.
++ *! 06-Jul-2001 jeh     Created.
++ */
++
++#ifndef DBOF_
++#define DBOF_
++
++/* Enough to hold DCD section names: 32 digit ID + underscores */
++#define DBOF_DCDSECTNAMELEN     40
++
++/* Values for DBOF_SectHdr page field. */
++#define         DBOF_PROGRAM    0
++#define         DBOF_DATA       1
++#define         DBOF_CINIT      2
++
++/*
++ *  ======== DBOF_FileHdr ========
++ */
++      struct DBOF_FileHdr {
++              u32 magic;      /* COFF magic number */
++              u32 entry;      /* Program entry point */
++              u16 numSymbols; /* Number of bridge symbols */
++              u16 numDCDSects;        /* Number of DCD sections */
++              u16 numSects;   /* Number of sections to load */
++              u16 numOvlySects;       /* Number of overlay sections */
++              u32 symOffset;  /* Offset in file to symbols */
++              u32 dcdSectOffset;      /* Offset to DCD sections */
++              u32 loadSectOffset;     /* Offset to loadable sections */
++              u32 ovlySectOffset;     /* Offset to overlay data */
++              u16 version;    /* DBOF version number */
++              u16 resvd;      /* Reserved for future use */
++      } ;
++
++/*
++ *  ======== DBOF_DCDSectHdr ========
++ */
++      struct DBOF_DCDSectHdr {
++              u32 size;       /* Sect size (target MAUs) */
++              char name[DBOF_DCDSECTNAMELEN]; /* DCD section name */
++      } ;
++
++/*
++ *  ======== DBOF_OvlySectHdr ========
++ */
++      struct DBOF_OvlySectHdr {
++              u16 nameLen;    /* Length of section name */
++              u16 numCreateSects;     /* # of sects loaded for create phase */
++              u16 numDeleteSects;     /* # of sects loaded for delete phase */
++              u16 numExecuteSects; /* # of sects loaded for execute phase */
++
++              /*
++               *  Number of sections where load/unload phase is not specified.
++               *  These sections will be loaded when create phase sects are
++               *  loaded, and unloaded when the delete phase is unloaded.
++               */
++              u16 numOtherSects;
++              u16 resvd;      /* Reserved for future use */
++      };
++
++/*
++ *  ======== DBOF_OvlySectData ========
++ */
++      struct DBOF_OvlySectData {
++              u32 loadAddr;   /* Section load address */
++              u32 runAddr;    /* Section run address */
++              u32 size;       /* Section size (target MAUs) */
++              u16 page;       /* Memory page number */
++              u16 resvd;      /* Reserved */
++      } ;
++
++/*
++ *  ======== DBOF_SectHdr ========
++ */
++      struct DBOF_SectHdr {
++              u32 addr;       /* Section address */
++              u32 size;       /* Section size (target MAUs) */
++              u16 page;       /* Page number */
++              u16 resvd;      /* Reserved for future use */
++      } ;
++
++/*
++ *  ======== DBOF_SymbolHdr ========
++ */
++      struct DBOF_SymbolHdr {
++              u32 value;      /* Symbol value */
++              u16 nameLen;    /* Length of symbol name */
++              u16 resvd;      /* Reserved for future use */
++      } ;
++
++#endif                                /* DBOF_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbreg.h b/arch/arm/plat-omap/include/dspbridge/dbreg.h
+new file mode 100644
+index 0000000..d311b88
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbreg.h
+@@ -0,0 +1,113 @@
++/*
++ * dbreg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dbreg.h ========
++ *  Purpose:
++ *      Registry keys for use in Linux.  This is the clearinghouse for
++ *      registry definitions, hopefully eliminating overlapping between
++ *      modules.
++ *
++ *! Revision History:
++ *! ================
++ *! 10-Apr-2003 vp:  Added macro for subkey TCWORDSWAP.
++ *! 21-Mar-2003 sb:  Added macro for subkey SHMSize
++ *! 27-Aug-2001 jeh  Added WSXREG_LOADERFILENAME.
++ *! 13-Feb-2001 kc:  DSP/BIOS Bridge name updates.
++ *! 29-Nov-2000 rr:  Added WSXREG_DSPTYPE_55 as 6.
++ *! 06-Sep-2000 jeh: Added WSXREG_CHNLOFFSET, WSXREG_NUMCHNLS,
++ *!                  WSXREG_CHNLBUFSIZE.
++ *! 26-Aug-2000 rr:  MEMBASE expanded to 9 entries.
++ *! 26-Jul-2000 rr:  Added WSXREG_DCDNAME for the DCD Dll name. It will
++ *!                  live under WSXREG_WINSPOXCONFIG.
++ *! 17-Jul-2000 rr:  REG_MGR_OBJECT and REG_DRV_OBJECT defined. They
++ *!                  are stored in the Registrty under WSXREG_WINSPOXCONFIG
++ *!                  when they are created in DSP_Init. WSXREG_DEVOBJECT
++ *!                  and WSXREG_MGROBJECT defined.
++ *! 11-Dec-1999 ag:  Renamed Isa to IsaBus due to conflict with ceddk.h.
++ *! 12-Nov-1999 rr:  New Registry Defnitions.
++ *! 15-Oct-1999 rr:  New entry for DevObject created. WSXREG_DEVOBJECT
++ *!                  under WSXREG_DDSPDRIVERPATH
++ *! 10-Nov-1997 cr:  Added WSXREG_INFPATH, WSXREG_WINDEVICEPATH,
++ *!                  WSXREG_WINCURVERSION
++ *! 21-Oct-1997 cr:  Added WSXREG_BUSTYPE.
++ *! 08-Sep-1997 cr:  Added WSXREG_SERVICES, WSXREG_SERVICENAME and
++ *!                  WSXREG_CLASSINDEX.
++ *! 30-Aug-1997 cr:  Added WSXREG_SOFTWAREPATHNT & WSXREG_WBCLASSGUID.
++ *! 24-Mar-1997 gp:  Added MAXCHIPINFOSUBKEY def.
++ *! 18-Feb-1997 cr:  Changed Version1.1 -> Version1.0
++ *! 12-Feb-1997 cr:  Changed WinSPOX -> WinBRIDGE.
++ *! 11-Dec-1996 gp:  Added Perf key name in WinSPOX Config.
++ *! 22-Jul-1996 gp:  Added Trace key name.
++ *! 30-May-1996 cr:  Created.
++ */
++
++#ifndef DBREG_
++#define DBREG_ 1      /* Defined as "1" so InstallShield programs compile. */
++
++#define REG_MGR_OBJECT      1
++#define REG_DRV_OBJECT      2
++/* general registry definitions */
++#define MAXREGPATHLENGTH    255       /* Max registry path length. Also the
++                                 max registry value length. */
++#define DSPTYPE_55          6 /* This is the DSP Chip type for 55 */
++#define DSPTYPE_64          0x99
++#define IVA_ARM7            0x97    /* This is the DSP Chip type for IVA/ARM7 */
++
++#define DSPPROCTYPE_C55               5510
++#define DSPPROCTYPE_C64               6410
++#define IVAPROCTYPE_ARM7      470
++/* registry */
++#define DEVNODESTRING    "DevNode"    /* u32 devnode */
++#define CONFIG           "Software\\TexasInstruments\\DirectDSP\\Config"
++#define DRVOBJECT        "DrvObject"
++#define MGROBJECT        "MgrObject"
++#define CLASS            "Device"     /*  device class */
++#define TRACE            "Trace"      /* GT Trace settings.  */
++#define PERFR            "Perf"       /* Enable perf bool.  */
++#define ROOT             "Root"       /*  root dir */
++
++/* MiniDriver related definitions */
++/* The following definitions are under "Drivers\\DirectDSP\\Device\\XXX "
++ * Where XXX is the device or board name */
++
++#define WMDFILENAME      "MiniDriver" /* WMD entry name */
++#define CHIPTYPE         "ChipType"   /* Chip type */
++#define CHIPNUM          "NumChips"   /* Number of chips */
++#define NUMPROCS         "NumOfProcessors"    /* Number of processors */
++#define DEFEXEC          "DefaultExecutable"  /* Default executable */
++#define AUTOSTART        "AutoStart"  /* Statically load flag */
++#define IVAAUTOSTART     "IvaAutoStart"       /* Statically load flag */
++#define BOARDNAME        "BoardName"  /* Name of the Board */
++#define UNITNUMBER       "UnitNumber" /* Unit # of the Board */
++#define BUSTYPE          "BusType"    /* Bus type board is on */
++#define BUSNUMBER        "BusNumber"  /* Bus number board is on */
++#define CURRENTCONFIG    "CurrentConfig"      /* Current resources */
++#define PCIVENDEVID      "VendorDeviceId"     /* The board's id */
++#define INFPATH          "InfPath"    /* wmd's inf filename */
++#define DEVOBJECT        "DevObject"
++#define ZLFILENAME       "ZLFileName" /* Name of ZL file */
++#define WORDSIZE         "WordSize"   /* NumBytes in DSP Word */
++#define SHMSIZE          "SHMSize"    /* Size of SHM reservd on MPU */
++#define IVAEXTMEMSIZE    "IVAEXTMEMSize"      /* IVA External Memeory size  */
++#define TCWORDSWAP       "TCWordSwap" /* Traffic Contoller Word Swap */
++#define DSPRESOURCES     "DspTMSResources"    /* C55 DSP resurces on OMAP */
++#define IVA1RESOURCES    "ARM7IvaResources"   /* ARM7 IVA resurces on OMAP */
++#define PHYSMEMPOOLBASE  "PhysicalMemBase"   /* Physical mem passed to driver */
++#define PHYSMEMPOOLSIZE  "PhysicalMemSize"   /* Physical mem passed to driver */
++
++#endif                                /* DBREG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbtype.h b/arch/arm/plat-omap/include/dspbridge/dbtype.h
+new file mode 100644
+index 0000000..b4953a0
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbtype.h
+@@ -0,0 +1,103 @@
++/*
++ * dbtype.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== dbtype.h ========
++ *  Description:
++ *      This header defines data types for DSP/BIOS Bridge APIs and device
++ *      driver modules. It also defines the Hungarian
++ *      prefix to use for each base type.
++ *
++ *
++ *! Revision History:
++ *! =================
++ *! 23-Nov-2002 gp: Purpose -> Description in file header.
++ *! 13-Feb-2001 kc: Name changed from ddsptype.h dbtype.h.
++ *! 09-Oct-2000 jeh Added CHARACTER.
++ *! 11-Aug-2000 ag: Added 'typedef void void'.
++ *! 08-Apr-2000 ww: Cloned.
++ */
++
++#ifndef DBTYPE_
++#define DBTYPE_
++
++/*============================================================================*/
++/*  Argument specification syntax                                             */
++/*============================================================================*/
++
++#ifndef IN
++#define IN                    /* Following parameter is for input. */
++#endif
++
++#ifndef OUT
++#define OUT                   /* Following parameter is for output. */
++#endif
++
++#ifndef OPTIONAL
++#define OPTIONAL        /* Function may optionally use previous parameter. */
++#endif
++
++#ifndef CONST
++#define CONST   const
++#endif
++
++/*============================================================================*/
++/*  Boolean constants                                                         */
++/*============================================================================*/
++
++#ifndef FALSE
++#define FALSE   0
++#endif
++#ifndef TRUE
++#define TRUE    1
++#endif
++
++/*============================================================================*/
++/*  NULL    (Definition is language specific)                                 */
++/*============================================================================*/
++
++#ifndef NULL
++#define NULL    ((void *)0)   /* Null pointer. */
++#endif
++
++/*============================================================================*/
++/*  NULL character   (normally used for string termination)                   */
++/*============================================================================*/
++
++#ifndef NULL_CHAR
++#define NULL_CHAR    '\0'     /* Null character. */
++#endif
++
++/*============================================================================*/
++/*  Basic Type definitions (with Prefixes for Hungarian notation)             */
++/*============================================================================*/
++
++#ifndef OMAPBRIDGE_TYPES
++#define OMAPBRIDGE_TYPES
++typedef volatile unsigned short REG_UWORD16;
++#endif
++
++typedef void *HANDLE;         /* h    */
++
++#define TEXT(x) x
++
++#define DLLIMPORT
++#define DLLEXPORT
++
++/* Define DSPAPIDLL correctly in dspapi.h */
++#define _DSPSYSDLL32_
++
++#endif                                /* DBTYPE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dehdefs.h b/arch/arm/plat-omap/include/dspbridge/dehdefs.h
+new file mode 100644
+index 0000000..06e5582
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dehdefs.h
+@@ -0,0 +1,42 @@
++/*
++ * dehdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== dehdefs.h ========
++ *  Purpose:
++ *      Definition for mini-driver module DEH.
++ *
++ *! Revision History:
++ *! ================
++ *! 17-Dec-2001 ag: added #include <dspbridge/mbx_sh.h> for shared mailbox codes.
++ *! 10-Dec-2001 kc: added DEH error base value and error max value.
++ *! 11-Sep-2001 kc: created.
++ */
++
++#ifndef DEHDEFS_
++#define DEHDEFS_
++
++#include <dspbridge/mbx_sh.h>         /* shared mailbox codes */
++
++/* DEH object manager */
++      struct DEH_MGR;
++
++/* Magic code used to determine if DSP signaled exception. */
++#define DEH_BASE        MBX_DEH_BASE
++#define DEH_USERS_BASE  MBX_DEH_USERS_BASE
++#define DEH_LIMIT       MBX_DEH_LIMIT
++
++#endif                                /* _DEHDEFS_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dev.h b/arch/arm/plat-omap/include/dspbridge/dev.h
+new file mode 100644
+index 0000000..5f468c9
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dev.h
+@@ -0,0 +1,785 @@
++/*
++ * dev.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dev.h ========
++ *  Description:
++ *      'Bridge Mini-driver device operations.
++ *
++ *  Public Functions:
++ *      DEV_BrdWriteFxn
++ *      DEV_CreateDevice
++ *      DEV_Create2
++ *      DEV_Destroy2
++ *      DEV_DestroyDevice
++ *      DEV_GetChnlMgr
++ *      DEV_GetCmmMgr
++ *      DEV_GetCodMgr
++ *      DEV_GetDehMgr
++ *      DEV_GetDevNode
++ *      DEV_GetDSPWordSize
++ *      DEV_GetFirst
++ *      DEV_GetIntfFxns
++ *      DEV_GetIOMgr
++ *      DEV_GetMsgMgr
++ *      DEV_GetNext
++ *      DEV_GetNodeManager
++ *      DEV_GetSymbol
++ *      DEV_GetWMDContext
++ *      DEV_Exit
++ *      DEV_Init
++ *      DEV_InsertProcObject
++ *      DEV_IsLocked
++ *      DEV_NotifyClient
++ *      DEV_RegisterNotify
++ *      DEV_ReleaseCodMgr
++ *      DEV_RemoveDevice
++ *      DEV_RemoveProcObject
++ *      DEV_SetChnlMgr
++ *      DEV_SetMsgMgr
++ *      DEV_SetLockOwner
++ *      DEV_StartDevice
++ *
++ *! Revision History:
++ *! ================
++ *! 08-Mar-2004 sb  Added the Dynamic Memory Mapping feature - Dev_GetDmmMgr
++ *! 09-Feb-2004 vp  Added functions required for IVA
++ *! 25-Feb-2003 swa PMGR Code Review changes incorporated
++ *! 05-Nov-2001 kc: Added DEV_GetDehMgr.
++ *! 05-Dec-2000 jeh Added DEV_SetMsgMgr.
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 17-Nov-2000 jeh Added DEV_GetMsgMgr.
++ *! 05-Oct-2000 rr: DEV_Create2 & DEV_Destroy2 Added.
++ *! 02-Oct-2000 rr: Added DEV_GetNodeManager.
++ *! 11-Aug-2000 ag: Added DEV_GetCmmMgr() for shared memory management.
++ *! 10-Aug-2000 rr: DEV_InsertProcObject/RemoveProcObject added.
++ *! 06-Jun-2000 jeh Added DEV_GetSymbol().
++ *! 05-Nov-1999 kc: Updated function prototypes.
++ *! 08-Oct-1997 cr: Added explicit CDECL function identifiers.
++ *! 07-Nov-1996 gp: Updated for code review.
++ *! 22-Oct-1996 gp: Added DEV_CleanupProcessState().
++ *! 29-May-1996 gp: Changed DEV_HDEVNODE --> CFG_HDEVNODE.
++ *! 18-May-1996 gp: Created.
++ */
++
++#ifndef DEV_
++#define DEV_
++
++/*  ----------------------------------- Module Dependent Headers */
++#include <dspbridge/chnldefs.h>
++#include <dspbridge/cmm.h>
++#include <dspbridge/cod.h>
++#include <dspbridge/dehdefs.h>
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/dispdefs.h>
++#include <dspbridge/wmd.h>
++#include <dspbridge/dmm.h>
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/devdefs.h>
++
++
++/*
++ *  ======== DEV_BrdWriteFxn ========
++ *  Purpose:
++ *      Exported function to be used as the COD write function.  This function
++ *      is passed a handle to a DEV_hObject by ZL in pArb, then calls the
++ *      device's WMD_BRD_Write() function.
++ *  Parameters:
++ *      pArb:           Handle to a Device Object.
++ *      hDevContext:    Handle to mini-driver defined device info.
++ *      dwDSPAddr:      Address on DSP board (Destination).
++ *      pHostBuf:       Pointer to host buffer (Source).
++ *      ulNumBytes:     Number of bytes to transfer.
++ *      ulMemType:      Memory space on DSP to which to transfer.
++ *  Returns:
++ *      Number of bytes written.  Returns 0 if the DEV_hObject passed in via
++ *      pArb is invalid.
++ *  Requires:
++ *      DEV Initialized.
++ *      pHostBuf != NULL
++ *  Ensures:
++ */
++       extern u32 DEV_BrdWriteFxn(void *pArb,
++                                         u32 ulDspAddr,
++                                         void *pHostBuf,
++                                         u32 ulNumBytes, u32 nMemSpace);
++
++/*
++ *  ======== DEV_CreateDevice ========
++ *  Purpose:
++ *      Called by the operating system to load the 'Bridge Mini Driver for a
++ *      'Bridge device.
++ *  Parameters:
++ *      phDevObject:    Ptr to location to receive the device object handle.
++ *      pstrWMDFileName: Name of WMD PE DLL file to load.  If the absolute
++ *                      path is not provided, the file is loaded through
++ *                      'Bridge's module search path.
++ *      pHostConfig:    Host configuration information, to be passed down
++ *                      to the WMD when WMD_DEV_Create() is called.
++ *      pDspConfig:     DSP resources, to be passed down to the WMD when
++ *                      WMD_DEV_Create() is called.
++ *      hDevNode:       Platform (Windows) specific device node.
++ *  Returns:
++ *      DSP_SOK:            Module is loaded, device object has been created
++ *      DSP_EMEMORY:        Insufficient memory to create needed resources.
++ *      DEV_E_NEWWMD:       The WMD was compiled for a newer version of WCD.
++ *      DEV_E_NULLWMDINTF:  WMD passed back a NULL Fxn Interface Struct Ptr
++ *      DEV_E_NOCODMODULE:  No ZL file name was specified in the registry
++ *                          for this hDevNode.
++ *      LDR_E_FILEUNABLETOOPEN: Unable to open the specified WMD.
++ *      LDR_E_NOMEMORY:         PELDR is out of resources.
++ *      DSP_EFAIL:              Unable to find WMD entry point function.
++ *      COD_E_NOZLFUNCTIONS:    One or more ZL functions exports not found.
++ *      COD_E_ZLCREATEFAILED:   Unable to load ZL DLL.
++ *  Requires:
++ *      DEV Initialized.
++ *      phDevObject != NULL.
++ *      pstrWMDFileName != NULL.
++ *      pHostConfig != NULL.
++ *      pDspConfig != NULL.
++ *  Ensures:
++ *      DSP_SOK:  *phDevObject will contain handle to the new device object.
++ *      Otherwise, does not create the device object, ensures the WMD module is
++ *      unloaded, and sets *phDevObject to NULL.
++ */
++       extern DSP_STATUS DEV_CreateDevice(OUT struct DEV_OBJECT
++                                               **phDevObject,
++                                               IN CONST char *pstrWMDFileName,
++                                               IN CONST struct CFG_HOSTRES
++                                               *pHostConfig,
++                                               IN CONST struct CFG_DSPRES
++                                               *pDspConfig,
++                                               struct CFG_DEVNODE *hDevNode);
++
++/*
++ *  ======== DEV_CreateIVADevice ========
++ *  Purpose:
++ *      Called by the operating system to load the 'Bridge Mini Driver for IVA.
++ *  Parameters:
++ *      phDevObject:    Ptr to location to receive the device object handle.
++ *      pstrWMDFileName: Name of WMD PE DLL file to load.  If the absolute
++ *                      path is not provided, the file is loaded through
++ *                      'Bridge's module search path.
++ *      pHostConfig:    Host configuration information, to be passed down
++ *                      to the WMD when WMD_DEV_Create() is called.
++ *      pDspConfig:     DSP resources, to be passed down to the WMD when
++ *                      WMD_DEV_Create() is called.
++ *      hDevNode:       Platform (Windows) specific device node.
++ *  Returns:
++ *      DSP_SOK:            Module is loaded, device object has been created
++ *      DSP_EMEMORY:        Insufficient memory to create needed resources.
++ *      DEV_E_NEWWMD:       The WMD was compiled for a newer version of WCD.
++ *      DEV_E_NULLWMDINTF:  WMD passed back a NULL Fxn Interface Struct Ptr
++ *      DEV_E_NOCODMODULE:  No ZL file name was specified in the registry
++ *                          for this hDevNode.
++ *      LDR_E_FILEUNABLETOOPEN: Unable to open the specified WMD.
++ *      LDR_E_NOMEMORY:         PELDR is out of resources.
++ *      DSP_EFAIL:              Unable to find WMD entry point function.
++ *      COD_E_NOZLFUNCTIONS:    One or more ZL functions exports not found.
++ *      COD_E_ZLCREATEFAILED:   Unable to load ZL DLL.
++ *  Requires:
++ *      DEV Initialized.
++ *      phDevObject != NULL.
++ *      pstrWMDFileName != NULL.
++ *      pHostConfig != NULL.
++ *      pDspConfig != NULL.
++ *  Ensures:
++ *      DSP_SOK:  *phDevObject will contain handle to the new device object.
++ *      Otherwise, does not create the device object, ensures the WMD module is
++ *      unloaded, and sets *phDevObject to NULL.
++ */
++       extern DSP_STATUS DEV_CreateIVADevice(OUT struct DEV_OBJECT
++                              **phDevObject,
++                              IN CONST char *pstrWMDFileName,
++                              IN CONST struct CFG_HOSTRES *pHostConfig,
++                              IN CONST struct CFG_DSPRES *pDspConfig,
++                              struct CFG_DEVNODE *hDevNode);
++
++/*
++ *  ======== DEV_Create2 ========
++ *  Purpose:
++ *      After successful loading of the image from WCD_InitComplete2
++ *      (PROC Auto_Start) or PROC_Load this fxn is called. This creates
++ *      the Node Manager and updates the DEV Object.
++ *  Parameters:
++ *      hDevObject: Handle to device object created with DEV_CreateDevice().
++ *  Returns:
++ *      DSP_SOK:    Successful Creation of Node Manager
++ *      DSP_EFAIL:  Some Error Occurred.
++ *  Requires:
++ *      DEV Initialized
++ *      Valid hDevObject
++ *  Ensures:
++ *      DSP_SOK and hDevObject->hNodeMgr != NULL
++ *      else    hDevObject->hNodeMgr == NULL
++ */
++       extern DSP_STATUS DEV_Create2(IN struct DEV_OBJECT *hDevObject);
++
++/*
++ *  ======== DEV_Destroy2 ========
++ *  Purpose:
++ *      Destroys the Node manager for this device.
++ *  Parameters:
++ *      hDevObject: Handle to device object created with DEV_CreateDevice().
++ *  Returns:
++ *      DSP_SOK:    Successful Creation of Node Manager
++ *      DSP_EFAIL:  Some Error Occurred.
++ *  Requires:
++ *      DEV Initialized
++ *      Valid hDevObject
++ *  Ensures:
++ *      DSP_SOK and hDevObject->hNodeMgr == NULL
++ *      else    DSP_EFAIL.
++ */
++       extern DSP_STATUS DEV_Destroy2(IN struct DEV_OBJECT *hDevObject);
++
++/*
++ *  ======== DEV_DestroyDevice ========
++ *  Purpose:
++ *      Destroys the channel manager for this device, if any, calls
++ *      WMD_DEV_Destroy(), and then attempts to unload the WMD module.
++ *  Parameters:
++ *      hDevObject:     Handle to device object created with
++ *                      DEV_CreateDevice().
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hDevObject.
++ *      DSP_EFAIL:      The WMD failed it's WMD_DEV_Destroy() function.
++ *  Requires:
++ *      DEV Initialized.
++ *  Ensures:
++ */
++       extern DSP_STATUS DEV_DestroyDevice(struct DEV_OBJECT
++                                                *hDevObject);
++
++/*
++ *  ======== DEV_GetChnlMgr ========
++ *  Purpose:
++ *      Retrieve the handle to the channel manager created for this device.
++ *  Parameters:
++ *      hDevObject:     Handle to device object created with
++ *                      DEV_CreateDevice().
++ *      *phMgr:         Ptr to location to store handle.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hDevObject.
++ *  Requires:
++ *      phMgr != NULL.
++ *      DEV Initialized.
++ *  Ensures:
++ *      DSP_SOK:        *phMgr contains a handle to a channel manager object,
++ *                      or NULL.
++ *      else:           *phMgr is NULL.
++ */
++       extern DSP_STATUS DEV_GetChnlMgr(struct DEV_OBJECT *hDevObject,
++                                             OUT struct CHNL_MGR **phMgr);
++
++/*
++ *  ======== DEV_GetCmmMgr ========
++ *  Purpose:
++ *      Retrieve the handle to the shared memory manager created for this
++ *      device.
++ *  Parameters:
++ *      hDevObject:     Handle to device object created with
++ *                      DEV_CreateDevice().
++ *      *phMgr:         Ptr to location to store handle.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hDevObject.
++ *  Requires:
++ *      phMgr != NULL.
++ *      DEV Initialized.
++ *  Ensures:
++ *      DSP_SOK:        *phMgr contains a handle to a channel manager object,
++ *                      or NULL.
++ *      else:           *phMgr is NULL.
++ */
++       extern DSP_STATUS DEV_GetCmmMgr(struct DEV_OBJECT *hDevObject,
++                                            OUT struct CMM_OBJECT **phMgr);
++
++/*
++ *  ======== DEV_GetDmmMgr ========
++ *  Purpose:
++ *      Retrieve the handle to the dynamic memory manager created for this
++ *      device.
++ *  Parameters:
++ *      hDevObject:     Handle to device object created with
++ *                      DEV_CreateDevice().
++ *      *phMgr:         Ptr to location to store handle.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hDevObject.
++ *  Requires:
++ *      phMgr != NULL.
++ *      DEV Initialized.
++ *  Ensures:
++ *      DSP_SOK:        *phMgr contains a handle to a channel manager object,
++ *                      or NULL.
++ *      else:           *phMgr is NULL.
++ */
++       extern DSP_STATUS DEV_GetDmmMgr(struct DEV_OBJECT *hDevObject,
++                                            OUT struct DMM_OBJECT **phMgr);
++
++/*
++ *  ======== DEV_GetCodMgr ========
++ *  Purpose:
++ *      Retrieve the COD manager create for this device.
++ *  Parameters:
++ *      hDevObject:     Handle to device object created with
++ *                      DEV_CreateDevice().
++ *      *phCodMgr:      Ptr to location to store handle.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hDevObject.
++ *  Requires:
++ *      phCodMgr != NULL.
++ *      DEV Initialized.
++ *  Ensures:
++ *      DSP_SOK:        *phCodMgr contains a handle to a COD manager object.
++ *      else:           *phCodMgr is NULL.
++ */
++       extern DSP_STATUS DEV_GetCodMgr(struct DEV_OBJECT *hDevObject,
++                                           OUT struct COD_MANAGER **phCodMgr);
++
++/*
++ *  ======== DEV_GetDehMgr ========
++ *  Purpose:
++ *      Retrieve the DEH manager created for this device.
++ *  Parameters:
++ *      hDevObject: Handle to device object created with DEV_CreateDevice().
++ *      *phDehMgr:  Ptr to location to store handle.
++ *  Returns:
++ *      DSP_SOK:    Success.
++ *      DSP_EHANDLE:   Invalid hDevObject.
++ *  Requires:
++ *      phDehMgr != NULL.
++ *      DEH Initialized.
++ *  Ensures:
++ *      DSP_SOK:    *phDehMgr contains a handle to a DEH manager object.
++ *      else:       *phDehMgr is NULL.
++ */
++       extern DSP_STATUS DEV_GetDehMgr(struct DEV_OBJECT *hDevObject,
++                                            OUT struct DEH_MGR **phDehMgr);
++
++/*
++ *  ======== DEV_GetDevNode ========
++ *  Purpose:
++ *      Retrieve the platform specific device ID for this device.
++ *  Parameters:
++ *      hDevObject:     Handle to device object created with
++ *                      DEV_CreateDevice().
++ *      phDevNode:      Ptr to location to get the device node handle.
++ *  Returns:
++ *      DSP_SOK:        In Win95, returns a DEVNODE in *hDevNode; In NT, ???
++ *      DSP_EHANDLE:    Invalid hDevObject.
++ *  Requires:
++ *      phDevNode != NULL.
++ *      DEV Initialized.
++ *  Ensures:
++ *      DSP_SOK:        *phDevNode contains a platform specific device ID;
++ *      else:           *phDevNode is NULL.
++ */
++       extern DSP_STATUS DEV_GetDevNode(struct DEV_OBJECT *hDevObject,
++                                      OUT struct CFG_DEVNODE **phDevNode);
++
++/*
++ *  ======== DEV_GetDevType ========
++ *  Purpose:
++ *      Retrieve the platform specific device ID for this device.
++ *  Parameters:
++ *      hDevObject:     Handle to device object created with
++ *                      DEV_CreateDevice().
++ *      phDevNode:      Ptr to location to get the device node handle.
++ *  Returns:
++ *      DSP_SOK:        Success
++ *      DSP_EHANDLE:    Invalid hDevObject.
++ *  Requires:
++ *      phDevNode != NULL.
++ *      DEV Initialized.
++ *  Ensures:
++ *      DSP_SOK:        *phDevNode contains a platform specific device ID;
++ *      else:           *phDevNode is NULL.
++ */
++       extern DSP_STATUS DEV_GetDevType(struct DEV_OBJECT *hdevObject,
++                                             u32 *devType);
++
++/*
++ *  ======== DEV_GetFirst ========
++ *  Purpose:
++ *      Retrieve the first Device Object handle from an internal linked list of
++ *      of DEV_OBJECTs maintained by DEV.
++ *  Parameters:
++ *  Returns:
++ *      NULL if there are no device objects stored; else
++ *      a valid DEV_HOBJECT.
++ *  Requires:
++ *      No calls to DEV_CreateDevice or DEV_DestroyDevice (which my modify the
++ *      internal device object list) may occur between calls to DEV_GetFirst
++ *      and DEV_GetNext.
++ *  Ensures:
++ *      The DEV_HOBJECT returned is valid.
++ *      A subsequent call to DEV_GetNext will return the next device object in
++ *      the list.
++ */
++       extern struct DEV_OBJECT *DEV_GetFirst(void);
++
++/*
++ *  ======== DEV_GetIntfFxns ========
++ *  Purpose:
++ *      Retrieve the WMD interface function structure for the loaded WMD.
++ *  Parameters:
++ *      hDevObject:     Handle to device object created with
++ *                      DEV_CreateDevice().
++ *      *ppIntfFxns:    Ptr to location to store fxn interface.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hDevObject.
++ *  Requires:
++ *      ppIntfFxns != NULL.
++ *      DEV Initialized.
++ *  Ensures:
++ *      DSP_SOK:        *ppIntfFxns contains a pointer to the WMD interface;
++ *      else:           *ppIntfFxns is NULL.
++ */
++       extern DSP_STATUS DEV_GetIntfFxns(struct DEV_OBJECT *hDevObject,
++                              OUT struct WMD_DRV_INTERFACE **ppIntfFxns);
++
++/*
++ *  ======== DEV_GetIOMgr ========
++ *  Purpose:
++ *      Retrieve the handle to the IO manager created for this device.
++ *  Parameters:
++ *      hDevObject:     Handle to device object created with
++ *                      DEV_CreateDevice().
++ *      *phMgr:         Ptr to location to store handle.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hDevObject.
++ *  Requires:
++ *      phMgr != NULL.
++ *      DEV Initialized.
++ *  Ensures:
++ *      DSP_SOK:        *phMgr contains a handle to an IO manager object.
++ *      else:           *phMgr is NULL.
++ */
++       extern DSP_STATUS DEV_GetIOMgr(struct DEV_OBJECT *hDevObject,
++                                           OUT struct IO_MGR **phMgr);
++
++/*
++ *  ======== DEV_GetNext ========
++ *  Purpose:
++ *      Retrieve the next Device Object handle from an internal linked list of
++ *      of DEV_OBJECTs maintained by DEV, after having previously called
++ *      DEV_GetFirst() and zero or more DEV_GetNext
++ *  Parameters:
++ *      hDevObject: Handle to the device object returned from a previous
++ *                  call to DEV_GetFirst() or DEV_GetNext().
++ *  Returns:
++ *      NULL if there are no further device objects on the list or hDevObject
++ *      was invalid;
++ *      else the next valid DEV_HOBJECT in the list.
++ *  Requires:
++ *      No calls to DEV_CreateDevice or DEV_DestroyDevice (which my modify the
++ *      internal device object list) may occur between calls to DEV_GetFirst
++ *      and DEV_GetNext.
++ *  Ensures:
++ *      The DEV_HOBJECT returned is valid.
++ *      A subsequent call to DEV_GetNext will return the next device object in
++ *      the list.
++ */
++       extern struct DEV_OBJECT *DEV_GetNext(struct DEV_OBJECT
++                                                  *hDevObject);
++
++/*
++ *  ========= DEV_GetMsgMgr ========
++ *  Purpose:
++ *      Retrieve the MSG Manager Handle from the DevObject.
++ *  Parameters:
++ *      hDevObject: Handle to the Dev Object
++ *      phMsgMgr:   Location where MSG Manager handle will be returned.
++ *  Returns:
++ *  Requires:
++ *      DEV Initialized.
++ *      Valid hDevObject.
++ *      phNodeMgr != NULL.
++ *  Ensures:
++ */
++       extern void DEV_GetMsgMgr(struct DEV_OBJECT *hDevObject,
++                                      OUT struct MSG_MGR **phMsgMgr);
++
++/*
++ *  ========= DEV_GetNodeManager ========
++ *  Purpose:
++ *      Retrieve the Node Manager Handle from the DevObject. It is an
++ *      accessor function
++ *  Parameters:
++ *      hDevObject:     Handle to the Dev Object
++ *      phNodeMgr:      Location where Handle to the Node Manager will be
++ *                      returned..
++ *  Returns:
++ *      DSP_SOK:        Success
++ *      DSP_EHANDLE:    Invalid Dev Object handle.
++ *  Requires:
++ *      DEV Initialized.
++ *      phNodeMgr is not null
++ *  Ensures:
++ *      DSP_SOK:        *phNodeMgr contains a handle to a Node manager object.
++ *      else:           *phNodeMgr is NULL.
++ */
++       extern DSP_STATUS DEV_GetNodeManager(struct DEV_OBJECT
++                                      *hDevObject,
++                                      OUT struct NODE_MGR **phNodeMgr);
++
++/*
++ *  ======== DEV_GetSymbol ========
++ *  Purpose:
++ *      Get the value of a symbol in the currently loaded program.
++ *  Parameters:
++ *      hDevObject:     Handle to device object created with
++ *                      DEV_CreateDevice().
++ *      pstrSym:        Name of symbol to look up.
++ *      pulValue:       Ptr to symbol value.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hDevObject.
++ *      COD_E_NOSYMBOLSLOADED:  Symbols have not been loaded onto the board.
++ *      COD_E_SYMBOLNOTFOUND:   The symbol could not be found.
++ *  Requires:
++ *      pstrSym != NULL.
++ *      pulValue != NULL.
++ *      DEV Initialized.
++ *  Ensures:
++ *      DSP_SOK:        *pulValue contains the symbol value;
++ */
++       extern DSP_STATUS DEV_GetSymbol(struct DEV_OBJECT *hDevObject,
++                                            IN CONST char *pstrSym,
++                                            OUT u32 *pulValue);
++
++/*
++ *  ======== DEV_GetWMDContext ========
++ *  Purpose:
++ *      Retrieve the WMD Context handle, as returned by the WMD_Create fxn.
++ *  Parameters:
++ *      hDevObject:     Handle to device object created with DEV_CreateDevice()
++ *      *phWmdContext:  Ptr to location to store context handle.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hDevObject.
++ *  Requires:
++ *      phWmdContext != NULL.
++ *      DEV Initialized.
++ *  Ensures:
++ *      DSP_SOK:        *phWmdContext contains context handle;
++ *      else:           *phWmdContext is NULL;
++ */
++       extern DSP_STATUS DEV_GetWMDContext(struct DEV_OBJECT *hDevObject,
++                              OUT struct WMD_DEV_CONTEXT **phWmdContext);
++
++/*
++ *  ======== DEV_Exit ========
++ *  Purpose:
++ *      Decrement reference count, and free resources when reference count is
++ *      0.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      DEV is initialized.
++ *  Ensures:
++ *      When reference count == 0, DEV's private resources are freed.
++ */
++       extern void DEV_Exit(void);
++
++/*
++ *  ======== DEV_Init ========
++ *  Purpose:
++ *      Initialize DEV's private state, keeping a reference count on each call.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialized; FALSE if error occured.
++ *  Requires:
++ *  Ensures:
++ *      TRUE: A requirement for the other public DEV functions.
++ */
++       extern bool DEV_Init(void);
++
++/*
++ *  ======== DEV_IsLocked ========
++ *  Purpose:
++ *      Predicate function to determine if the device has been
++ *      locked by a client for exclusive access.
++ *  Parameters:
++ *      hDevObject:     Handle to device object created with
++ *                      DEV_CreateDevice().
++ *  Returns:
++ *      DSP_SOK:        TRUE: device has been locked.
++ *      DSP_SFALSE:     FALSE: device not locked.
++ *      DSP_EHANDLE:    hDevObject was invalid.
++ *  Requires:
++ *      DEV Initialized.
++ *  Ensures:
++ */
++       extern DSP_STATUS DEV_IsLocked(IN struct DEV_OBJECT *hDevObject);
++
++/*
++ *  ======== DEV_InsertProcObject ========
++ *  Purpose:
++ *      Inserts the Processor Object into the List of PROC Objects
++ *      kept in the DEV Object
++ *  Parameters:
++ *      hProcObject:    Handle to the Proc Object
++ *      hDevObject      Handle to the Dev Object
++ *      bAttachedNew    Specifies if there are already processors attached
++ *  Returns:
++ *      DSP_SOK:        Successfully inserted into the list
++ *  Requires:
++ *      hProcObject is not NULL
++ *      hDevObject is a valid handle to the DEV.
++ *      DEV Initialized.
++ *      List(of Proc object in Dev) Exists.
++ *  Ensures:
++ *      DSP_SOK & the PROC Object is inserted and the list is not empty
++ *  Details:
++ *      If the List of Proc Object is empty bAttachedNew is TRUE, it indicated
++ *      this is the first Processor attaching.
++ *      If it is False, there are already processors attached.
++ */
++       extern DSP_STATUS DEV_InsertProcObject(IN struct DEV_OBJECT
++                                                   *hDevObject,
++                                                   IN u32 hProcObject,
++                                                   OUT bool *
++                                                   pbAlreadyAttached);
++
++/*
++ *  ======== DEV_RemoveProcObject ========
++ *  Purpose:
++ *      Search for and remove a Proc object from the given list maintained
++ *      by the DEV
++ *  Parameters:
++ *      pProcObject:        Ptr to ProcObject to insert.
++ *      pDevObject:         Ptr to Dev Object where the list is.
++ *      pbAlreadyAttached:  Ptr to return the bool
++ *  Returns:
++ *      DSP_SOK:            If successful.
++ *      DSP_EFAIL           Failure to Remove the PROC Object from the list
++ *  Requires:
++ *      DevObject is Valid
++ *      hProcObject != 0
++ *      pDevObject->procList != NULL
++ *      !LST_IsEmpty(pDevObject->procList)
++ *      pbAlreadyAttached !=NULL
++ *  Ensures:
++ *  Details:
++ *      List will be deleted when the DEV is destroyed.
++ *
++ */
++       extern DSP_STATUS DEV_RemoveProcObject(struct DEV_OBJECT
++                                                   *hDevObject,
++                                                   u32 hProcObject);
++
++/*
++ *  ======== DEV_NotifyClients ========
++ *  Purpose:
++ *      Notify all clients of this device of a change in device status.
++ *      Clients may include multiple users of BRD, as well as CHNL.
++ *      This function is asychronous, and may be called by a timer event
++ *      set up by a watchdog timer.
++ *  Parameters:
++ *      hDevObject:  Handle to device object created with DEV_CreateDevice().
++ *      ulStatus:    A status word, most likely a BRD_STATUS.
++ *  Returns:
++ *      DSP_SOK:     All registered clients were asynchronously notified.
++ *      DSP_EINVALIDARG:   Invalid hDevObject.
++ *  Requires:
++ *      DEV Initialized.
++ *  Ensures:
++ *      DSP_SOK: Notifications are queued by the operating system to be
++ *      delivered to clients.  This function does not ensure that
++ *      the notifications will ever be delivered.
++ */
++       extern DSP_STATUS DEV_NotifyClients(struct DEV_OBJECT *hDevObject,
++                                                u32 ulStatus);
++
++
++
++/*
++ *  ======== DEV_RemoveDevice ========
++ *  Purpose:
++ *      Destroys the Device Object created by DEV_StartDevice.
++ *  Parameters:
++ *      hDevNode:       Device node as it is know to OS.
++ *  Returns:
++ *      DSP_SOK:        If success;
++ *      <error code>    Otherwise.
++ *  Requires:
++ *  Ensures:
++ */
++       extern DSP_STATUS DEV_RemoveDevice(struct CFG_DEVNODE *hDevNode);
++
++/*
++ *  ======== DEV_SetChnlMgr ========
++ *  Purpose:
++ *      Set the channel manager for this device.
++ *  Parameters:
++ *      hDevObject:     Handle to device object created with
++ *                      DEV_CreateDevice().
++ *      hMgr:           Handle to a channel manager, or NULL.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hDevObject.
++ *  Requires:
++ *      DEV Initialized.
++ *  Ensures:
++ */
++       extern DSP_STATUS DEV_SetChnlMgr(struct DEV_OBJECT *hDevObject,
++                                             struct CHNL_MGR *hMgr);
++
++/*
++ *  ======== DEV_SetMsgMgr ========
++ *  Purpose:
++ *      Set the Message manager for this device.
++ *  Parameters:
++ *      hDevObject: Handle to device object created with DEV_CreateDevice().
++ *      hMgr:       Handle to a message manager, or NULL.
++ *  Returns:
++ *  Requires:
++ *      DEV Initialized.
++ *  Ensures:
++ */
++       extern void DEV_SetMsgMgr(struct DEV_OBJECT *hDevObject,
++                                      struct MSG_MGR *hMgr);
++
++/*
++ *  ======== DEV_StartDevice ========
++ *  Purpose:
++ *      Initializes the new device with the WinBRIDGE environment.  This
++ *      involves querying CM for allocated resources, querying the registry
++ *      for necessary dsp resources (requested in the INF file), and using
++ *      this information to create a WinBRIDGE device object.
++ *  Parameters:
++ *      hDevNode:       Device node as it is know to OS.
++ *  Returns:
++ *      DSP_SOK:        If success;
++ *      <error code>    Otherwise.
++ *  Requires:
++ *      DEV initialized.
++ *  Ensures:
++ */
++       extern DSP_STATUS DEV_StartDevice(struct CFG_DEVNODE *hDevNode);
++
++#endif                                /* DEV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/devdefs.h b/arch/arm/plat-omap/include/dspbridge/devdefs.h
+new file mode 100644
+index 0000000..e9ff725
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/devdefs.h
+@@ -0,0 +1,35 @@
++/*
++ * devdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== devdefs.h ========
++ *  Purpose:
++ *      Definition of common include typedef between wmd.h and dev.h. Required
++ *      to break circular dependency between WMD and DEV include files.
++ *
++ *! Revision History:
++ *! ================
++ *! 12-Nov-1996 gp: Renamed from dev1.h.
++ *! 30-May-1996 gp: Broke out from dev.h
++ */
++
++#ifndef DEVDEFS_
++#define DEVDEFS_
++
++/* WCD Device Object */
++      struct DEV_OBJECT;
++
++#endif                                /* DEVDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/disp.h b/arch/arm/plat-omap/include/dspbridge/disp.h
+new file mode 100644
+index 0000000..e116734
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/disp.h
+@@ -0,0 +1,236 @@
++/*
++ * disp.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== disp.h ========
++ *
++ *  Description:
++ *      DSP/BIOS Bridge Node Dispatcher.
++ *
++ *  Public Functions:
++ *      DISP_Create
++ *      DISP_Delete
++ *      DISP_Exit
++ *      DISP_Init
++ *      DISP_NodeChangePriority
++ *      DISP_NodeCreate
++ *      DISP_NodeDelete
++ *      DISP_NodeRun
++ *
++ *! Revision History:
++ *! =================
++ *! 28-Jan-2003 map     Removed DISP_DoCinit().
++ *! 15-May-2002 jeh     Added DISP_DoCinit().
++ *! 24-Apr-2002 jeh     Added DISP_MemWrite().
++ *! 07-Sep-2001 jeh     Added DISP_MemCopy().
++ *! 10-May-2001 jeh     Code review cleanup.
++ *! 08-Aug-2000 jeh     Removed DISP_NodeTerminate since it no longer uses RMS.
++ *! 17-Jul-2000 jeh     Updates to function headers.
++ *! 19-Jun-2000 jeh     Created.
++ */
++
++#ifndef DISP_
++#define DISP_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/dispdefs.h>
++
++/*
++ *  ======== DISP_Create ========
++ *  Create a NODE Dispatcher object. This object handles the creation,
++ *  deletion, and execution of nodes on the DSP target, through communication
++ *  with the Resource Manager Server running on the target. Each NODE
++ *  Manager object should have exactly one NODE Dispatcher.
++ *
++ *  Parameters:
++ *      phDispObject:   Location to store node dispatcher object on output.
++ *      hDevObject:     Device for this processor.
++ *      pDispAttrs:     Node dispatcher attributes.
++ *  Returns:
++ *      DSP_SOK:                Success;
++ *      DSP_EMEMORY:            Insufficient memory for requested resources.
++ *      DSP_EFAIL:              Unable to create dispatcher.
++ *  Requires:
++ *      DISP_Init(void) called.
++ *      pDispAttrs != NULL.
++ *      hDevObject != NULL.
++ *      phDispObject != NULL.
++ *  Ensures:
++ *      DSP_SOK:        IsValid(*phDispObject).
++ *      error:          *phDispObject == NULL.
++ */
++      extern DSP_STATUS DISP_Create(OUT struct DISP_OBJECT **phDispObject,
++                                    struct DEV_OBJECT *hDevObject,
++                                    IN CONST struct DISP_ATTRS *pDispAttrs);
++
++/*
++ *  ======== DISP_Delete ========
++ *  Delete the NODE Dispatcher.
++ *
++ *  Parameters:
++ *      hDispObject:  Node Dispatcher object.
++ *  Returns:
++ *  Requires:
++ *      DISP_Init(void) called.
++ *      Valid hDispObject.
++ *  Ensures:
++ *      hDispObject is invalid.
++ */
++      extern void DISP_Delete(struct DISP_OBJECT *hDispObject);
++
++/*
++ *  ======== DISP_Exit ========
++ *  Discontinue usage of DISP module.
++ *
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      DISP_Init(void) previously called.
++ *  Ensures:
++ *      Any resources acquired in DISP_Init(void) will be freed when last DISP
++ *      client calls DISP_Exit(void).
++ */
++      extern void DISP_Exit(void);
++
++/*
++ *  ======== DISP_Init ========
++ *  Initialize the DISP module.
++ *
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialization succeeded, FALSE otherwise.
++ *  Ensures:
++ */
++      extern bool DISP_Init(void);
++
++/*
++ *  ======== DISP_NodeChangePriority ========
++ *  Change the priority of a node currently running on the target.
++ *
++ *  Parameters:
++ *      hDispObject:            Node Dispatcher object.
++ *      hNode:                  Node object representing a node currently
++ *                              allocated or running on the DSP.
++ *      ulFxnAddress:           Address of RMS function for changing priority.
++ *      nodeEnv:                Address of node's environment structure.
++ *      nPriority:              New priority level to set node's priority to.
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      DSP_ETIMEOUT:           A timeout occurred before the DSP responded.
++ *  Requires:
++ *      DISP_Init(void) called.
++ *      Valid hDispObject.
++ *      hNode != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS DISP_NodeChangePriority(struct DISP_OBJECT
++                                                *hDispObject,
++                                                struct NODE_OBJECT *hNode,
++                                                u32 ulFxnAddr,
++                                                NODE_ENV nodeEnv,
++                                                s32 nPriority);
++
++/*
++ *  ======== DISP_NodeCreate ========
++ *  Create a node on the DSP by remotely calling the node's create function.
++ *
++ *  Parameters:
++ *      hDispObject:    Node Dispatcher object.
++ *      hNode:          Node handle obtained from NODE_Allocate().
++ *      ulFxnAddr:      Address or RMS create node function.
++ *      ulCreateFxn:    Address of node's create function.
++ *      pArgs:          Arguments to pass to RMS node create function.
++ *      pNodeEnv:       Location to store node environment pointer on
++ *                      output.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_ETASK:      Unable to create the node's task or process on the DSP.
++ *      DSP_ESTREAM:    Stream creation failure on the DSP.
++ *      DSP_ETIMEOUT:   A timeout occurred before the DSP responded.
++ *      DSP_EUSER:      A user-defined failure occurred.
++ *      DSP_EFAIL:      A failure occurred, unable to create node.
++ *  Requires:
++ *      DISP_Init(void) called.
++ *      Valid hDispObject.
++ *      pArgs != NULL.
++ *      hNode != NULL.
++ *      pNodeEnv != NULL.
++ *      NODE_GetType(hNode) != NODE_DEVICE.
++ *  Ensures:
++ */
++      extern DSP_STATUS DISP_NodeCreate(struct DISP_OBJECT *hDispObject,
++                                        struct NODE_OBJECT *hNode,
++                                        u32 ulFxnAddr,
++                                        u32 ulCreateFxn,
++                                        IN CONST struct NODE_CREATEARGS
++                                        *pArgs,
++                                        OUT NODE_ENV *pNodeEnv);
++
++/*
++ *  ======== DISP_NodeDelete ========
++ *  Delete a node on the DSP by remotely calling the node's delete function.
++ *
++ *  Parameters:
++ *      hDispObject:    Node Dispatcher object.
++ *      hNode:          Node object representing a node currently
++ *                      loaded on the DSP.
++ *      ulFxnAddr:      Address or RMS delete node function.
++ *      ulDeleteFxn:    Address of node's delete function.
++ *      nodeEnv:        Address of node's environment structure.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_ETIMEOUT:   A timeout occurred before the DSP responded.
++ *  Requires:
++ *      DISP_Init(void) called.
++ *      Valid hDispObject.
++ *      hNode != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS DISP_NodeDelete(struct DISP_OBJECT *hDispObject,
++                                        struct NODE_OBJECT *hNode,
++                                        u32 ulFxnAddr,
++                                        u32 ulDeleteFxn, NODE_ENV nodeEnv);
++
++/*
++ *  ======== DISP_NodeRun ========
++ *  Start execution of a node's execute phase, or resume execution of a node
++ *  that has been suspended (via DISP_NodePause()) on the DSP.
++ *
++ *  Parameters:
++ *      hDispObject:    Node Dispatcher object.
++ *      hNode:          Node object representing a node to be executed
++ *                      on the DSP.
++ *      ulFxnAddr:      Address or RMS node execute function.
++ *      ulExecuteFxn:   Address of node's execute function.
++ *      nodeEnv:        Address of node's environment structure.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_ETIMEOUT:   A timeout occurred before the DSP responded.
++ *  Requires:
++ *      DISP_Init(void) called.
++ *      Valid hDispObject.
++ *      hNode != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS DISP_NodeRun(struct DISP_OBJECT *hDispObject,
++                                     struct NODE_OBJECT *hNode,
++                                     u32 ulFxnAddr,
++                                     u32 ulExecuteFxn, NODE_ENV nodeEnv);
++
++#endif                                /* DISP_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dispdefs.h b/arch/arm/plat-omap/include/dspbridge/dispdefs.h
+new file mode 100644
+index 0000000..401ad4f
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dispdefs.h
+@@ -0,0 +1,45 @@
++/*
++ * dispdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dispdefs.h ========
++ *  Description:
++ *      Global DISP constants and types, shared by PROCESSOR, NODE, and DISP.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Aug-2000 jeh     Added fields to DISP_ATTRS.
++ *! 06-Jul-2000 jeh     Created.
++ */
++
++#ifndef DISPDEFS_
++#define DISPDEFS_
++
++      struct DISP_OBJECT;
++
++/* Node Dispatcher attributes */
++      struct DISP_ATTRS {
++              u32 ulChnlOffset; /* Offset of channel ids reserved for RMS */
++              /* Size of buffer for sending data to RMS */
++              u32 ulChnlBufSize;
++              DSP_PROCFAMILY procFamily;      /* eg, 5000 */
++              DSP_PROCTYPE procType;  /* eg, 5510 */
++              HANDLE hReserved1;      /* Reserved for future use. */
++              u32 hReserved2; /* Reserved for future use. */
++      } ;
++
++#endif                                /* DISPDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dmm.h b/arch/arm/plat-omap/include/dspbridge/dmm.h
+new file mode 100644
+index 0000000..ef37668
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dmm.h
+@@ -0,0 +1,85 @@
++/*
++ * dmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dmm.h ========
++ *  Purpose:
++ *      The Dynamic Memory Mapping(DMM) module manages the DSP Virtual address
++ *      space that can be directly mapped to any MPU buffer or memory region
++ *
++ *  Public Functions:
++ *
++ *! Revision History:
++ *! ================
++ *! 20-Feb-2004 sb: Created.
++ *!
++ */
++
++#ifndef DMM_
++#define DMM_
++
++#include <dspbridge/dbdefs.h>
++
++      struct DMM_OBJECT;
++
++/* DMM attributes used in DMM_Create() */
++      struct DMM_MGRATTRS {
++              u32 reserved;
++      } ;
++
++#define DMMPOOLSIZE      0x4000000
++
++/*
++ *  ======== DMM_GetHandle ========
++ *  Purpose:
++ *      Return the dynamic memory manager object for this device.
++ *      This is typically called from the client process.
++ */
++
++      extern DSP_STATUS DMM_GetHandle(DSP_HPROCESSOR hProcessor,
++                                      OUT struct DMM_OBJECT **phDmmMgr);
++
++      extern DSP_STATUS DMM_ReserveMemory(struct DMM_OBJECT *hDmmMgr,
++                                          u32 size,
++                                          u32 *pRsvAddr);
++
++      extern DSP_STATUS DMM_UnReserveMemory(struct DMM_OBJECT *hDmmMgr,
++                                            u32 rsvAddr);
++
++      extern DSP_STATUS DMM_MapMemory(struct DMM_OBJECT *hDmmMgr, u32 addr,
++                                      u32 size);
++
++      extern DSP_STATUS DMM_UnMapMemory(struct DMM_OBJECT *hDmmMgr,
++                                        u32 addr,
++                                        u32 *pSize);
++
++      extern DSP_STATUS DMM_Destroy(struct DMM_OBJECT *hDmmMgr);
++
++      extern DSP_STATUS DMM_DeleteTables(struct DMM_OBJECT *hDmmMgr);
++
++      extern DSP_STATUS DMM_Create(OUT struct DMM_OBJECT **phDmmMgr,
++                                   struct DEV_OBJECT *hDevObject,
++                                   IN CONST struct DMM_MGRATTRS *pMgrAttrs);
++
++      extern bool DMM_Init(void);
++
++      extern void DMM_Exit(void);
++
++      extern DSP_STATUS DMM_CreateTables(struct DMM_OBJECT *hDmmMgr,
++                                              u32 addr, u32 size);
++      extern u32 *DMM_GetPhysicalAddrTable(void);
++#endif                                /* DMM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dpc.h b/arch/arm/plat-omap/include/dspbridge/dpc.h
+new file mode 100644
+index 0000000..8c20506
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dpc.h
+@@ -0,0 +1,167 @@
++/*
++ * dpc.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dpc.h ========
++ *  Purpose:
++ *      Deferred Procedure Call(DPC) Services.
++ *
++ *  Public Functions:
++ *      DPC_Cancel
++ *      DPC_Create
++ *      DPC_Destroy
++ *      DPC_Exit
++ *      DPC_Init
++ *      DPC_Schedule
++ *
++ *! Revision History:
++ *! ================
++ *! 31-Jan-2000 rr:  DPC_Destroy ensures Suceess and DPC Object is NULL.
++ *! 21-Jan-2000 ag:  Updated comments per code review.
++ *! 06-Jan-2000 ag:  Removed DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
++ *! 14-Jan-1998 gp:  Added DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
++ *! 18-Aug-1997 cr:  Added explicit CDECL identifiers.
++ *! 28-Jul-1996 gp:  Created.
++ */
++
++#ifndef DPC_
++#define DPC_
++
++      struct DPC_OBJECT;
++
++/*
++ *  ======== DPC_PROC ========
++ *  Purpose:
++ *      Deferred processing routine.  Typically scheduled from an ISR to
++ *      complete I/O processing.
++ *  Parameters:
++ *      pRefData:   Ptr to user data: passed in via ISR_ScheduleDPC.
++ *  Returns:
++ *  Requires:
++ *      The DPC should not block, or otherwise acquire resources.
++ *      Interrupts to the processor are enabled.
++ *      DPC_PROC executes in a critical section.
++ *  Ensures:
++ *      This DPC will not be reenterred on the same thread.
++ *      However, the DPC may take hardware interrupts during execution.
++ *      Interrupts to the processor are enabled.
++ */
++       typedef void(*DPC_PROC) (void *pRefData);
++
++/*
++ *  ======== DPC_Cancel ========
++ *  Purpose:
++ *      Cancel a DPC previously scheduled by DPC_Schedule.
++ *  Parameters:
++ *      hDPC:           A DPC object handle created in DPC_Create().
++ *  Returns:
++ *      DSP_SOK:        Scheduled DPC, if any, is cancelled.
++ *      DSP_SFALSE:     No DPC is currently scheduled for execution.
++ *      DSP_EHANDLE:    Invalid hDPC.
++ *  Requires:
++ *  Ensures:
++ *      If the DPC has already executed, is executing, or was not yet
++ *      scheduled, this function will have no effect.
++ */
++       extern DSP_STATUS DPC_Cancel(IN struct DPC_OBJECT *hDPC);
++
++/*
++ *  ======== DPC_Create ========
++ *  Purpose:
++ *      Create a DPC object, allowing a client's own DPC procedure to be
++ *      scheduled for a call with client reference data.
++ *  Parameters:
++ *      phDPC:          Pointer to location to store DPC object.
++ *      pfnDPC:         Client's DPC procedure.
++ *      pRefData:       Pointer to user-defined reference data.
++ *  Returns:
++ *      DSP_SOK:        DPC object created.
++ *      DSP_EPOINTER:   phDPC == NULL or pfnDPC == NULL.
++ *      DSP_EMEMORY:    Insufficient memory.
++ *  Requires:
++ *      Must not be called at interrupt time.
++ *  Ensures:
++ *      DSP_SOK: DPC object is created;
++ *      else: *phDPC is set to NULL.
++ */
++       extern DSP_STATUS DPC_Create(OUT struct DPC_OBJECT **phDPC,
++                                         IN DPC_PROC pfnDPC,
++                                         IN void *pRefData);
++
++/*
++ *  ======== DPC_Destroy ========
++ *  Purpose:
++ *      Cancel the last scheduled DPC, and deallocate a DPC object previously
++ *      allocated with DPC_Create().Frees the Object only if the thread and
++ *      the events are terminated successfuly.
++ *  Parameters:
++ *      hDPC:           A DPC object handle created in DPC_Create().
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hDPC.
++ *  Requires:
++ *      All DPC's scheduled for the DPC object must have completed their
++ *      processing.
++ *  Ensures:
++ *      (SUCCESS && hDPC is NULL) or DSP_EFAILED status
++ */
++       extern DSP_STATUS DPC_Destroy(IN struct DPC_OBJECT *hDPC);
++
++/*
++ *  ======== DPC_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the DPC module.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      DPC_Init(void) was previously called.
++ *  Ensures:
++ *      Resources acquired in DPC_Init(void) are freed.
++ */
++       extern void DPC_Exit(void);
++
++/*
++ *  ======== DPC_Init ========
++ *  Purpose:
++ *      Initialize the DPC module's private state.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialized; FALSE if error occured.
++ *  Requires:
++ *  Ensures:
++ *      A requirement for each of the other public DPC functions.
++ */
++       extern bool DPC_Init(void);
++
++/*
++ *  ======== DPC_Schedule ========
++ *  Purpose:
++ *      Schedule a deferred procedure call to be executed at a later time.
++ *      Latency and order of DPC execution is platform specific.
++ *  Parameters:
++ *      hDPC:           A DPC object handle created in DPC_Create().
++ *  Returns:
++ *      DSP_SOK:        An event is scheduled for deferred processing.
++ *      DSP_EHANDLE:    Invalid hDPC.
++ *  Requires:
++ *      See requirements for DPC_PROC.
++ *  Ensures:
++ *      DSP_SOK:        The DPC will not be called before this function returns.
++ */
++       extern DSP_STATUS DPC_Schedule(IN struct DPC_OBJECT *hDPC);
++
++#endif                                /* DPC_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/drv.h b/arch/arm/plat-omap/include/dspbridge/drv.h
+new file mode 100644
+index 0000000..c468461
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/drv.h
+@@ -0,0 +1,449 @@
++/*
++ * drv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== drv.h ========
++ *  Purpose:
++ *      DRV Resource allocation module. Driver Object gets Created
++ *      at the time of Loading. It holds the List of Device Objects
++ *      in the Syste,
++ *
++ *  Public Functions:
++ *      DRV_Create
++ *      DRV_Destroy
++ *      DRV_Exit
++ *      DRV_GetDevObject
++ *      DRV_GetDevExtension
++ *      DRV_GetFirstDevObject
++ *      DRV_GetNextDevObject
++ *      DRV_GetNextDevExtension
++ *      DRV_Init
++ *      DRV_InsertDevObject
++ *      DRV_RemoveDevObject
++ *      DRV_RequestResources
++ *      DRV_ReleaseResources
++ *
++ *! Revision History
++ *! ================
++ *! 10-Feb-2004 vp:  Added OMAP24xx specific definitions.
++ *! 14-Aug-2000 rr:  Cleaned up.
++ *! 27-Jul-2000 rr:  DRV_RequestResources split into two(Request and Release)
++ *!                  Device extension created to hold the DevNodeString.
++ *! 17-Jul-2000 rr:  Driver Object holds the list of Device Objects.
++ *!                  Added DRV_Create, DRV_Destroy, DRV_GetDevObject,
++ *!                  DRV_GetFirst/NextDevObject, DRV_Insert/RemoveDevObject.
++ *! 12-Nov-1999 rr:  New Flag defines for DRV_ASSIGN and DRV_RELEASE
++ *! 25-Oct-1999 rr:  Resource Structure removed.
++ *! 15-Oct-1999 rr:  New Resource structure created.
++ *! 05-Oct-1999 rr:  Added DRV_RequestResources
++ *!                  Removed fxn'sDRV_RegisterMiniDriver(),
++ *!                DRV_UnRegisterMiniDriver()
++ *!                  Removed Structures DSP_DRIVER & DRV_EXTENSION.
++ *!
++ *! 24-Sep-1999 rr:  Added DRV_EXTENSION and DSP_DRIVER structures.
++ *!
++ */
++
++#ifndef DRV_
++#define DRV_
++
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/drvdefs.h>
++
++#define DRV_ASSIGN     1
++#define DRV_RELEASE    0
++
++/* Provide the DSP Internal memory windows that can be accessed from L3 address
++ * space */
++
++#define OMAP_GEM_BASE   0x107F8000
++#define OMAP_DSP_SIZE   0x00720000
++
++/* MEM1 is L2 RAM + L2 Cache space */
++#define OMAP_DSP_MEM1_BASE 0x5C7F8000
++#define OMAP_DSP_MEM1_SIZE 0x18000
++#define OMAP_DSP_GEM1_BASE 0x107F8000
++
++
++/* MEM2 is L1P RAM/CACHE space */
++#define OMAP_DSP_MEM2_BASE 0x5CE00000
++#define OMAP_DSP_MEM2_SIZE 0x8000
++#define OMAP_DSP_GEM2_BASE 0x10E00000
++
++/* MEM3 is L1D RAM/CACHE space */
++#define OMAP_DSP_MEM3_BASE 0x5CF04000
++#define OMAP_DSP_MEM3_SIZE 0x14000
++#define OMAP_DSP_GEM3_BASE 0x10F04000
++
++
++#define OMAP_IVA2_PRM_BASE 0x48306000
++#define OMAP_IVA2_PRM_SIZE 0x1000
++
++#define OMAP_IVA2_CM_BASE 0x48004000
++#define OMAP_IVA2_CM_SIZE 0x1000
++
++#define OMAP_PER_CM_BASE 0x48005000
++#define OMAP_PER_CM_SIZE 0x1000
++
++#define OMAP_PER_PRM_BASE 0x48307000
++#define OMAP_PER_PRM_SIZE 0x1000
++
++#define OMAP_CORE_PRM_BASE 0x48306A00
++#define OMAP_CORE_PRM_SIZE 0x1000
++
++#define OMAP_SYSC_BASE 0x48002000
++#define OMAP_SYSC_SIZE 0x1000
++
++#define OMAP_MBOX_BASE 0x48094000
++#define OMAP_MBOX_SIZE 0x1000
++
++#define OMAP_DMMU_BASE 0x5D000000
++#define OMAP_DMMU_SIZE 0x1000
++
++#define OMAP_PRCM_VDD1_DOMAIN 1
++#define OMAP_PRCM_VDD2_DOMAIN 2
++
++#ifndef RES_CLEANUP_DISABLE
++
++/* GPP PROCESS CLEANUP Data structures */
++
++/* New structure (member of process context) abstracts NODE resource info */
++struct NODE_RES_OBJECT {
++      DSP_HNODE       hNode;
++      s32            nodeAllocated; /* Node status */
++      s32            heapAllocated; /* Heap status */
++      s32            streamsAllocated; /* Streams status */
++      struct NODE_RES_OBJECT         *next;
++} ;
++
++/* New structure (member of process context) abstracts DMM resource info */
++struct DMM_RES_OBJECT {
++      s32            dmmAllocated; /* DMM status */
++      u32           ulMpuAddr;
++      u32           ulDSPAddr;
++      u32           ulDSPResAddr;
++      u32           dmmSize;
++      HANDLE          hProcessor;
++      struct DMM_RES_OBJECT  *next;
++} ;
++
++/* New structure (member of process context) abstracts DMM resource info */
++struct DSPHEAP_RES_OBJECT {
++      s32            heapAllocated; /* DMM status */
++      u32           ulMpuAddr;
++      u32           ulDSPAddr;
++      u32           ulDSPResAddr;
++      u32           heapSize;
++      HANDLE          hProcessor;
++      struct DSPHEAP_RES_OBJECT  *next;
++} ;
++
++/* New structure (member of process context) abstracts stream resource info */
++struct STRM_RES_OBJECT {
++      s32                    streamAllocated; /* Stream status */
++      DSP_HSTREAM             hStream;
++      u32                    uNumBufs;
++      u32                    uDir;
++      struct STRM_RES_OBJECT         *next;
++} ;
++
++/* Overall Bridge process resource usage state */
++enum GPP_PROC_RES_STATE {
++      PROC_RES_ALLOCATED,
++      PROC_RES_FREED
++} ;
++
++/* Process Context */
++struct PROCESS_CONTEXT{
++      /* Process State */
++      enum GPP_PROC_RES_STATE resState;
++
++      /* Process ID (Same as UNIX process ID) */
++      u32 pid;
++
++      /* Pointer to next process context
++      * (To maintain a linked list of process contexts) */
++      struct PROCESS_CONTEXT *next;
++
++      /* Processor info to which the process is related */
++      DSP_HPROCESSOR hProcessor;
++
++      /* DSP Node resources */
++      struct NODE_RES_OBJECT *pNodeList;
++
++      /* DMM resources */
++      struct DMM_RES_OBJECT *pDMMList;
++
++      /* DSP Heap resources */
++      struct DSPHEAP_RES_OBJECT *pDSPHEAPList;
++
++      /* Stream resources */
++      struct STRM_RES_OBJECT *pSTRMList;
++} ;
++#endif
++
++/*
++ *  ======== DRV_Create ========
++ *  Purpose:
++ *      Creates the Driver Object. This is done during the driver loading.
++ *      There is only one Driver Object in the DSP/BIOS Bridge.
++ *  Parameters:
++ *      phDrvObject:    Location to store created DRV Object handle.
++ *  Returns:
++ *      DSP_SOK:        Sucess
++ *      DSP_EMEMORY:    Failed in Memory allocation
++ *      DSP_EFAIL:      General Failure
++ *  Requires:
++ *      DRV Initialized (cRefs > 0 )
++ *      phDrvObject != NULL.
++ *  Ensures:
++ *      DSP_SOK:        - *phDrvObject is a valid DRV interface to the device.
++ *                      - List of DevObject Created and Initialized.
++ *                      - List of DevNode String created and intialized.
++ *                      - Registry is updated with the DRV Object.
++ *      !DSP_SOK:       DRV Object not created
++ *  Details:
++ *      There is one Driver Object for the Driver representing
++ *      the driver itself. It contains the list of device
++ *      Objects and the list of Device Extensions in the system.
++ *      Also it can hold other neccessary
++ *      information in its storage area.
++ */
++      extern DSP_STATUS DRV_Create(struct DRV_OBJECT **phDrvObject);
++
++/*
++ *  ======== DRV_Destroy ========
++ *  Purpose:
++ *      destroys the Dev Object list, DrvExt list
++ *      and destroy the DRV object
++ *      Called upon driver unLoading.or unsuccesful loading of the driver.
++ *  Parameters:
++ *      hDrvObject:     Handle to Driver object .
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Failed to destroy DRV Object
++ *  Requires:
++ *      DRV Initialized (cRegs > 0 )
++ *      hDrvObject is not NULL and a valid DRV handle .
++ *      List of DevObject is Empty.
++ *      List of DrvExt is Empty
++ *  Ensures:
++ *      DSP_SOK:        - DRV Object destroyed and hDrvObject is not a valid
++ *                        DRV handle.
++ *                      - Registry is updated with "0" as the DRV Object.
++ */
++      extern DSP_STATUS DRV_Destroy(struct DRV_OBJECT *hDrvObject);
++
++/*
++ *  ======== DRV_Exit ========
++ *  Purpose:
++ *      Exit the DRV module, freeing any modules initialized in DRV_Init.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *  Ensures:
++ */
++      extern void DRV_Exit(void);
++
++/*
++ *  ======== DRV_GetFirstDevObject ========
++ *  Purpose:
++ *      Returns the Ptr to the FirstDev Object in the List
++ *  Parameters:
++ *  Requires:
++ *      DRV Initialized
++ *  Returns:
++ *      dwDevObject:  Ptr to the First Dev Object as a u32
++ *      0 if it fails to retrieve the First Dev Object
++ *  Ensures:
++ */
++      extern u32 DRV_GetFirstDevObject(void);
++
++/*
++ *  ======== DRV_GetFirstDevExtension ========
++ *  Purpose:
++ *      Returns the Ptr to the First Device Extension in the List
++ *  Parameters:
++ *  Requires:
++ *      DRV Initialized
++ *  Returns:
++ *      dwDevExtension:     Ptr to the First Device Extension as a u32
++ *      0:                  Failed to Get the Device Extension
++ *  Ensures:
++ */
++      extern u32 DRV_GetFirstDevExtension(void);
++
++/*
++ *  ======== DRV_GetDevObject ========
++ *  Purpose:
++ *      Given a index, returns a handle to DevObject from the list
++ *  Parameters:
++ *      hDrvObject:     Handle to the Manager
++ *      phDevObject:    Location to store the Dev Handle
++ *  Requires:
++ *      DRV Initialized
++ *      uIndex >= 0
++ *      hDrvObject is not NULL and Valid DRV Object
++ *      phDevObject is not NULL
++ *      Device Object List not Empty
++ *  Returns:
++ *      DSP_SOK:        Success
++ *      DSP_EFAIL:      Failed to Get the Dev Object
++ *  Ensures:
++ *      DSP_SOK:        *phDevObject != NULL
++ *      DSP_EFAIL:      *phDevObject = NULL
++ */
++      extern DSP_STATUS DRV_GetDevObject(u32 uIndex,
++                                         struct DRV_OBJECT *hDrvObject,
++                                         struct DEV_OBJECT **phDevObject);
++
++/*
++ *  ======== DRV_GetNextDevObject ========
++ *  Purpose:
++ *      Returns the Ptr to the Next Device Object from the the List
++ *  Parameters:
++ *      hDevObject:     Handle to the Device Object
++ *  Requires:
++ *      DRV Initialized
++ *      hDevObject != 0
++ *  Returns:
++ *      dwDevObject:    Ptr to the Next Dev Object as a u32
++ *      0:              If it fail to get the next Dev Object.
++ *  Ensures:
++ */
++      extern u32 DRV_GetNextDevObject(u32 hDevObject);
++
++/*
++ *  ======== DRV_GetNextDevExtension ========
++ *  Purpose:
++ *      Returns the Ptr to the Next Device Extension from the the List
++ *  Parameters:
++ *      hDevExtension:      Handle to the Device Extension
++ *  Requires:
++ *      DRV Initialized
++ *      hDevExtension != 0.
++ *  Returns:
++ *      dwDevExtension:     Ptr to the Next Dev Extension
++ *      0:                  If it fail to Get the next Dev Extension
++ *  Ensures:
++ */
++      extern u32 DRV_GetNextDevExtension(u32 hDevExtension);
++
++/*
++ *  ======== DRV_Init ========
++ *  Purpose:
++ *      Initialize the DRV module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if success; FALSE otherwise.
++ *  Requires:
++ *  Ensures:
++ */
++      extern DSP_STATUS DRV_Init(void);
++
++/*
++ *  ======== DRV_InsertDevObject ========
++ *  Purpose:
++ *      Insert a DeviceObject into the list of Driver object.
++ *  Parameters:
++ *      hDrvObject:     Handle to DrvObject
++ *      hDevObject:     Handle to DeviceObject to insert.
++ *  Returns:
++ *      DSP_SOK:        If successful.
++ *      DSP_EFAIL:      General Failure:
++ *  Requires:
++ *      hDrvObject != NULL and Valid DRV Handle.
++ *      hDevObject != NULL.
++ *  Ensures:
++ *      DSP_SOK:        Device Object is inserted and the List is not empty.
++ */
++      extern DSP_STATUS DRV_InsertDevObject(struct DRV_OBJECT *hDrvObject,
++                                            struct DEV_OBJECT *hDevObject);
++
++/*
++ *  ======== DRV_RemoveDevObject ========
++ *  Purpose:
++ *      Search for and remove a Device object from the given list of Device Obj
++ *      objects.
++ *  Parameters:
++ *      hDrvObject:     Handle to DrvObject
++ *      hDevObject:     Handle to DevObject to Remove
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Unable to find pDevObject.
++ *  Requires:
++ *      hDrvObject != NULL and a Valid DRV Handle.
++ *      hDevObject != NULL.
++ *      List exists and is not empty.
++ *  Ensures:
++ *      List either does not exist (NULL), or is not empty if it does exist.
++*/
++      extern DSP_STATUS DRV_RemoveDevObject(struct DRV_OBJECT *hDrvObject,
++                                            struct DEV_OBJECT *hDevObject);
++
++/*
++ *  ======== DRV_RequestResources ========
++ *  Purpose:
++ *      Assigns the Resources or Releases them.
++ *  Parameters:
++ *      dwContext:          Path to the driver Registry Key.
++ *      pDevNodeString:     Ptr to DevNode String stored in the Device Ext.
++ *  Returns:
++ *      TRUE if success; FALSE otherwise.
++ *  Requires:
++ *  Ensures:
++ *      The Resources are assigned based on Bus type.
++ *      The hardware is initialized. Resource information is
++ *      gathered from the Registry(ISA, PCMCIA)or scanned(PCI)
++ *      Resource structure is stored in the registry which will be
++ *      later used by the CFG module.
++ */
++      extern DSP_STATUS DRV_RequestResources(IN u32 dwContext,
++                                             OUT u32 *pDevNodeString);
++
++/*
++ *  ======== DRV_ReleaseResources ========
++ *  Purpose:
++ *      Assigns the Resources or Releases them.
++ *  Parameters:
++ *      dwContext:      Path to the driver Registry Key.
++ *      hDrvObject:     Handle to the Driver Object.
++ *  Returns:
++ *      TRUE if success; FALSE otherwise.
++ *  Requires:
++ *  Ensures:
++ *      The Resources are released based on Bus type.
++ *      Resource structure is deleted from the registry
++ */
++      extern DSP_STATUS DRV_ReleaseResources(IN u32 dwContext,
++                                             struct DRV_OBJECT *hDrvObject);
++
++/*
++ *  ======== DRV_ProcFreeDMMRes ========
++ *  Purpose:
++ *       Actual DMM De-Allocation.
++ *  Parameters:
++ *      hPCtxt:      Path to the driver Registry Key.
++ *  Returns:
++ *      DSP_SOK if success;
++ */
++
++
++      extern DSP_STATUS  DRV_ProcFreeDMMRes(HANDLE hPCtxt);
++
++#endif                                /* DRV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/drvdefs.h b/arch/arm/plat-omap/include/dspbridge/drvdefs.h
+new file mode 100644
+index 0000000..ed86010
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/drvdefs.h
+@@ -0,0 +1,34 @@
++/*
++ * drvdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== drvdefs.h ========
++ *  Purpose:
++ *      Definition of common include typedef between wmd.h and drv.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 17-Jul-2000 rr: Created
++ */
++
++#ifndef DRVDEFS_
++#define DRVDEFS_
++
++/* WCD Driver Object */
++      struct DRV_OBJECT;
++
++#endif                                /* DRVDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dspdrv.h b/arch/arm/plat-omap/include/dspbridge/dspdrv.h
+new file mode 100644
+index 0000000..f500ffb
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dspdrv.h
+@@ -0,0 +1,106 @@
++/*
++ * dspdrv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dspdrv.h ========
++ *  Purpose:
++ *      This is the Stream Interface for the DDSP Class driver.
++ *      All Device operations are performed via DeviceIOControl.
++ *      Read, Seek and Write not used.
++ *
++ *  Public Functions
++ *      DSP_Close
++ *      DSP_Deinit
++ *      DSP_Init
++ *      DSP_IOControl
++ *      DSP_Open
++ *      DSP_PowerUp
++ *      DSP_PowerDown
++ *
++ *! Revision History
++ *! ================
++ *! 28-Jan-2000 rr: Type void changed to Void.
++ *! 02-Dec-1999 rr: MAX_DEV define moved from wcdce.c file.Code cleaned up.
++ *! 12-Nov-1999 rr: "#include<wncnxerr.h> removed.
++ *! 05-Oct-1999 rr  Renamed the file name to wcdce.h Removed Bus Specific
++ *!                 code and #defines to PCCARD.h.
++ *! 24-Sep-1999 rr  Changed the DSP_COMMON_WINDOW_SIZE to 0x4000(16k) for the
++ *!                 Memory windows.
++ *! 16-Jul-1999 ag  Adapted from rkw's CAC Bullet driver.
++ *!
++ */
++
++#if !defined __DSPDRV_h__
++#define __DSPDRV_h__
++
++#define MAX_DEV     10                /* Max support of 10 devices */
++
++/*
++ *  ======== DSP_Close ========
++ *  Purpose:
++ *      Called when the client application/driver unloads the DDSP DLL. Upon
++ *      unloading, the DDSP DLL will call CloseFile().
++ *  Parameters:
++ *      dwDeviceContext:    Handle returned by XXX_Open used to identify
++ *                          the open context of the device
++ *  Returns:
++ *      TRUE indicates the device is successfully closed. FALSE indicates
++ *      otherwise.
++ *  Requires:
++ *      dwOpenContext!= NULL.
++ *  Ensures:The Application instance owned objects are cleaned up.
++ */
++extern bool DSP_Close(u32 dwDeviceContext);
++
++/*
++ *  ======== DSP_Deinit ========
++ *  Purpose:
++ *      This function is called by Device Manager to de-initialize a device.
++ *      This function is not called by applications.
++ *  Parameters:
++ *      dwDeviceContext:Handle to the device context. The XXX_Init function
++ *      creates and returns this identifier.
++ *  Returns:
++ *      TRUE indicates the device successfully de-initialized. Otherwise it
++ *      returns FALSE.
++ *  Requires:
++ *      dwDeviceContext!= NULL. For a built in device this should never
++ *      get called.
++ *  Ensures:
++ */
++extern bool DSP_Deinit(u32 dwDeviceContext);
++
++/*
++ *  ======== DSP_Init ========
++ *  Purpose:
++ *      This function is called by Device Manager to initialize a device.
++ *      This function is not called by applications
++ *  Parameters:
++ *      dwContext:  Specifies a pointer to a string containing the registry
++ *                  path to the active key for the stream interface driver.
++ *                  HKEY_LOCAL_MACHINE\Drivers\Active
++ *  Returns:
++ *      Returns a handle to the device context created. This is the our actual
++ *      Device Object representing the DSP Device instance.
++ *  Requires:
++ *  Ensures:
++ *      Succeeded:  device context > 0
++ *      Failed:     device Context = 0
++ */
++extern u32 DSP_Init(OUT u32 *initStatus);
++
++#endif
+diff --git a/arch/arm/plat-omap/include/dspbridge/dynamic_loader.h b/arch/arm/plat-omap/include/dspbridge/dynamic_loader.h
+new file mode 100644
+index 0000000..ea5f77f
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dynamic_loader.h
+@@ -0,0 +1,505 @@
++/*
++ * dynamic_loader.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef _DYNAMIC_LOADER_H_
++#define _DYNAMIC_LOADER_H_
++#include <linux/kernel.h>
++#include <linux/types.h>
++
++/*
++ * Dynamic Loader
++ *
++ * The function of the dynamic loader is to load a "module" containing
++ * instructions for a "target" processor into that processor.  In the process
++ * it assigns memory for the module, resolves symbol references made by the
++ * module, and remembers symbols defined by the module.
++ *
++ * The dynamic loader is parameterized for a particular system by 4 classes
++ * that supply the module and system specific functions it requires
++ */
++      /* The read functions for the module image to be loaded */
++      struct Dynamic_Loader_Stream;
++
++      /* This class defines "host" symbol and support functions */
++      struct Dynamic_Loader_Sym;
++
++      /* This class defines the allocator for "target" memory */
++      struct Dynamic_Loader_Allocate;
++
++      /* This class defines the copy-into-target-memory functions */
++      struct Dynamic_Loader_Initialize;
++
++/*
++ * Option flags to modify the behavior of module loading
++ */
++#define DLOAD_INITBSS 0x1     /* initialize BSS sections to zero */
++#define DLOAD_BIGEND 0x2      /* require big-endian load module */
++#define DLOAD_LITTLE 0x4      /* require little-endian load module */
++
++      typedef void *DLOAD_mhandle;    /* module handle for loaded modules */
++
++/*****************************************************************************
++ * Procedure Dynamic_Load_Module
++ *
++ * Parameters:
++ *  module  The input stream that supplies the module image
++ *  syms    Host-side symbol table and malloc/free functions
++ *  alloc   Target-side memory allocation
++ *  init    Target-side memory initialization, or NULL for symbol read only
++ *  options Option flags DLOAD_*
++ *  mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ *  The module image is read using *module.  Target storage for the new image is
++ * obtained from *alloc.  Symbols defined and referenced by the module are
++ * managed using *syms.  The image is then relocated and references resolved
++ * as necessary, and the resulting executable bits are placed into target memory
++ * using *init.
++ *
++ * Returns:
++ *  On a successful load, a module handle is placed in *mhandle, and zero is
++ * returned.  On error, the number of errors detected is returned.  Individual
++ * errors are reported during the load process using syms->Error_Report().
++ *****************************************************************************/
++      extern int Dynamic_Load_Module(
++                                     /* the source for the module image*/
++                                     struct Dynamic_Loader_Stream *module,
++                                     /* host support for symbols and storage*/
++                                     struct Dynamic_Loader_Sym *syms,
++                                     /* the target memory allocator*/
++                                     struct Dynamic_Loader_Allocate *alloc,
++                                     /* the target memory initializer*/
++                                     struct Dynamic_Loader_Initialize *init,
++                                     unsigned options,       /* option flags*/
++                                     /* the returned module handle*/
++                                     DLOAD_mhandle *mhandle
++          );
++
++/*****************************************************************************
++ * Procedure Dynamic_Open_Module
++ *
++ * Parameters:
++ *  module  The input stream that supplies the module image
++ *  syms    Host-side symbol table and malloc/free functions
++ *  alloc   Target-side memory allocation
++ *  init    Target-side memory initialization, or NULL for symbol read only
++ *  options Option flags DLOAD_*
++ *  mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ *  The module image is read using *module.  Target storage for the new image is
++ * obtained from *alloc.  Symbols defined and referenced by the module are
++ * managed using *syms.  The image is then relocated and references resolved
++ * as necessary, and the resulting executable bits are placed into target memory
++ * using *init.
++ *
++ * Returns:
++ *  On a successful load, a module handle is placed in *mhandle, and zero is
++ * returned.  On error, the number of errors detected is returned.  Individual
++ * errors are reported during the load process using syms->Error_Report().
++ *****************************************************************************/
++      extern int Dynamic_Open_Module(
++                                    /* the source for the module image */
++                                    struct Dynamic_Loader_Stream *module,
++                                    /* host support for symbols and storage */
++                                    struct Dynamic_Loader_Sym *syms,
++                                    /* the target memory allocator */
++                                    struct Dynamic_Loader_Allocate *alloc,
++                                    /* the target memory initializer */
++                                    struct Dynamic_Loader_Initialize *init,
++                                    unsigned options, /* option flags */
++                                    /* the returned module handle */
++                                    DLOAD_mhandle *mhandle
++      );
++
++/*****************************************************************************
++ * Procedure Dynamic_Unload_Module
++ *
++ * Parameters:
++ *  mhandle A module handle from Dynamic_Load_Module
++ *  syms    Host-side symbol table and malloc/free functions
++ *  alloc   Target-side memory allocation
++ *
++ * Effect:
++ *  The module specified by mhandle is unloaded.  Unloading causes all
++ * target memory to be deallocated, all symbols defined by the module to
++ * be purged, and any host-side storage used by the dynamic loader for
++ * this module to be released.
++ *
++ * Returns:
++ *  Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report().
++ *****************************************************************************/
++      extern int Dynamic_Unload_Module(DLOAD_mhandle mhandle, /* the module
++                                                               * handle*/
++                                       /* host support for symbols and
++                                        * storage */
++                                       struct Dynamic_Loader_Sym *syms,
++                                       /* the target memory allocator*/
++                                       struct Dynamic_Loader_Allocate *alloc,
++                                       /* the target memory initializer*/
++                                       struct Dynamic_Loader_Initialize *init
++          );
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader for input of the module image
++ *****************************************************************************
++ *****************************************************************************/
++      struct Dynamic_Loader_Stream {
++/* public: */
++    /*************************************************************************
++     * read_buffer
++     *
++     * PARAMETERS :
++     *  buffer  Pointer to the buffer to fill
++     *  bufsiz  Amount of data desired in sizeof() units
++     *
++     * EFFECT :
++     *  Reads the specified amount of data from the module input stream
++     * into the specified buffer.  Returns the amount of data read in sizeof()
++     * units (which if less than the specification, represents an error).
++     *
++     * NOTES:
++     *  In release 1 increments the file position by the number of bytes read
++     *
++     *************************************************************************/
++              int (*read_buffer) (struct Dynamic_Loader_Stream *thisptr,
++                                  void *buffer, unsigned bufsiz);
++
++    /*************************************************************************
++     * set_file_posn (release 1 only)
++     *
++     * PARAMETERS :
++     *  posn  Desired file position relative to start of file in sizeof() units.
++     *
++     * EFFECT :
++     *  Adjusts the internal state of the stream object so that the next
++     * read_buffer call will begin to read at the specified offset from
++     * the beginning of the input module.  Returns 0 for success, non-zero
++     * for failure.
++     *
++     *************************************************************************/
++              int (*set_file_posn) (struct Dynamic_Loader_Stream *thisptr,
++                                      /* to be eliminated in release 2*/
++                                      unsigned int posn);
++
++      };
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader for symbol table support and
++ * miscellaneous host-side functions
++ *****************************************************************************
++ *****************************************************************************/
++
++      typedef u32 LDR_ADDR;
++
++/*
++ * the structure of a symbol known to the dynamic loader
++ */
++      struct dynload_symbol {
++              LDR_ADDR value;
++      } ;
++
++      struct Dynamic_Loader_Sym {
++/* public: */
++    /*************************************************************************
++     * Find_Matching_Symbol
++     *
++     * PARAMETERS :
++     *  name    The name of the desired symbol
++     *
++     * EFFECT :
++     *  Locates a symbol matching the name specified.  A pointer to the
++     * symbol is returned if it exists; 0 is returned if no such symbol is
++     * found.
++     *
++     *************************************************************************/
++              struct dynload_symbol *(*Find_Matching_Symbol)
++                      (struct Dynamic_Loader_Sym *
++                                                       thisptr,
++                                                       const char *name);
++
++    /*************************************************************************
++     * Add_To_Symbol_Table
++     *
++     * PARAMETERS :
++     *  nname       Pointer to the name of the new symbol
++     *  moduleid    An opaque module id assigned by the dynamic loader
++     *
++     * EFFECT :
++     *  The new symbol is added to the table.  A pointer to the symbol is
++     * returned, or NULL is returned for failure.
++     *
++     * NOTES:
++     *  It is permissible for this function to return NULL; the effect is that
++     * the named symbol will not be available to resolve references in
++     * subsequent loads.  Returning NULL will not cause the current load
++     * to fail.
++     *************************************************************************/
++              struct dynload_symbol *(*Add_To_Symbol_Table)
++                                              (struct Dynamic_Loader_Sym *
++                                                      thisptr,
++                                                      const char *nname,
++                                                      unsigned moduleid);
++
++    /*************************************************************************
++     * Purge_Symbol_Table
++     *
++     * PARAMETERS :
++     *  moduleid    An opaque module id assigned by the dynamic loader
++     *
++     * EFFECT :
++     *  Each symbol in the symbol table whose moduleid matches the argument
++     * is removed from the table.
++     *************************************************************************/
++              void (*Purge_Symbol_Table) (struct Dynamic_Loader_Sym *thisptr,
++                                          unsigned moduleid);
++
++    /*************************************************************************
++     * Allocate
++     *
++     * PARAMETERS :
++     *  memsiz  size of desired memory in sizeof() units
++     *
++     * EFFECT :
++     *  Returns a pointer to some "host" memory for use by the dynamic
++     * loader, or NULL for failure.
++     * This function is serves as a replaceable form of "malloc" to
++     * allow the user to configure the memory usage of the dynamic loader.
++     *************************************************************************/
++              void *(*Allocate) (struct Dynamic_Loader_Sym *thisptr,
++                                 unsigned memsiz);
++
++    /*************************************************************************
++     * Deallocate
++     *
++     * PARAMETERS :
++     *  memptr  pointer to previously allocated memory
++     *
++     * EFFECT :
++     *  Releases the previously allocated "host" memory.
++     *************************************************************************/
++              void (*Deallocate) (struct Dynamic_Loader_Sym *thisptr,
++                                  void *memptr);
++
++    /*************************************************************************
++     * Error_Report
++     *
++     * PARAMETERS :
++     *  errstr  pointer to an error string
++     *  args    additional arguments
++     *
++     * EFFECT :
++     *  This function provides an error reporting interface for the dynamic
++     * loader.  The error string and arguments are designed as for the
++     * library function vprintf.
++     *************************************************************************/
++              void (*Error_Report) (struct Dynamic_Loader_Sym *thisptr,
++                                    const char *errstr, va_list args);
++
++      };                      /* class Dynamic_Loader_Sym */
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader to allocate and deallocate target memory.
++ *****************************************************************************
++ *****************************************************************************/
++
++      struct LDR_SECTION_INFO {
++              /* Name of the memory section assigned at build time */
++              const char *name;
++              LDR_ADDR run_addr;      /* execution address of the section */
++              LDR_ADDR load_addr;     /* load address of the section */
++              LDR_ADDR size;  /* size of the section in addressable units */
++#ifndef _BIG_ENDIAN
++              u16 page;       /* memory page or view */
++              u16 type;       /* one of the section types below */
++#else
++              u16 type;       /* one of the section types below */
++              u16 page;       /* memory page or view */
++#endif
++              /* a context field for use by Dynamic_Loader_Allocate;
++               *   ignored but maintained by the dynamic loader */
++              u32 context;
++      } ;
++
++/* use this macro to extract type of section from LDR_SECTION_INFO.type field */
++#define DLOAD_SECTION_TYPE(typeinfo) (typeinfo & 0xF)
++
++/* type of section to be allocated */
++#define DLOAD_TEXT 0
++#define DLOAD_DATA 1
++#define DLOAD_BSS 2
++      /* internal use only, run-time cinit will be of type DLOAD_DATA */
++#define DLOAD_CINIT 3
++
++      struct Dynamic_Loader_Allocate {
++/* public: */
++
++    /*************************************************************************
++    * Function allocate
++    *
++    * Parameters:
++    *   info        A pointer to an information block for the section
++    *   align       The alignment of the storage in target AUs
++    *
++    * Effect:
++    *   Allocates target memory for the specified section and fills in the
++    * load_addr and run_addr fields of the section info structure. Returns TRUE
++    * for success, FALSE for failure.
++    *
++    * Notes:
++    *   Frequently load_addr and run_addr are the same, but if they are not
++    * load_addr is used with Dynamic_Loader_Initialize, and run_addr is
++    * used for almost all relocations.  This function should always initialize
++    * both fields.
++    *************************************************************************/
++              int (*Allocate) (struct Dynamic_Loader_Allocate *thisptr,
++                               struct LDR_SECTION_INFO *info, unsigned align);
++
++    /*************************************************************************
++    * Function deallocate
++    *
++    * Parameters:
++    *   info        A pointer to an information block for the section
++    *
++    * Effect:
++    *   Releases the target memory previously allocated.
++    *
++    * Notes:
++    * The content of the info->name field is undefined on call to this function.
++    *************************************************************************/
++              void (*Deallocate) (struct Dynamic_Loader_Allocate *thisptr,
++                                  struct LDR_SECTION_INFO *info);
++
++      };                      /* class Dynamic_Loader_Allocate */
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader to load data into a target.  This class
++ * provides the interface-specific functions needed to load data.
++ *****************************************************************************
++ *****************************************************************************/
++
++      struct Dynamic_Loader_Initialize {
++/* public: */
++    /*************************************************************************
++    * Function connect
++    *
++    * Parameters:
++    *   none
++    *
++    * Effect:
++    *   Connect to the initialization interface. Returns TRUE for success,
++    * FALSE for failure.
++    *
++    * Notes:
++    *   This function is called prior to use of any other functions in
++    * this interface.
++    *************************************************************************/
++              int (*connect) (struct Dynamic_Loader_Initialize *thisptr);
++
++    /*************************************************************************
++    * Function readmem
++    *
++    * Parameters:
++    *   bufr        Pointer to a word-aligned buffer for the result
++    *   locn        Target address of first data element
++    *   info        Section info for the section in which the address resides
++    *   bytsiz      Size of the data to be read in sizeof() units
++    *
++    * Effect:
++    *   Fills the specified buffer with data from the target.  Returns TRUE for
++    * success, FALSE for failure.
++    *************************************************************************/
++              int (*readmem) (struct Dynamic_Loader_Initialize *thisptr,
++                              void *bufr,
++                              LDR_ADDR locn,
++                              struct LDR_SECTION_INFO *info,
++                              unsigned bytsiz);
++
++    /*************************************************************************
++    * Function writemem
++    *
++    * Parameters:
++    *   bufr        Pointer to a word-aligned buffer of data
++    *   locn        Target address of first data element to be written
++    *   info        Section info for the section in which the address resides
++    *   bytsiz      Size of the data to be written in sizeof() units
++    *
++    * Effect:
++    *   Writes the specified buffer to the target.  Returns TRUE for success,
++    * FALSE for failure.
++    *************************************************************************/
++              int (*writemem) (struct Dynamic_Loader_Initialize *thisptr,
++                               void *bufr,
++                               LDR_ADDR locn,
++                               struct LDR_SECTION_INFO *info,
++                               unsigned bytsiz);
++
++    /*************************************************************************
++    * Function fillmem
++    *
++    * Parameters:
++    *   locn        Target address of first data element to be written
++    *   info        Section info for the section in which the address resides
++    *   bytsiz      Size of the data to be written in sizeof() units
++    *   val         Value to be written in each byte
++    * Effect:
++    *   Fills the specified area of target memory.  Returns TRUE for success,
++    * FALSE for failure.
++    *************************************************************************/
++              int (*fillmem) (struct Dynamic_Loader_Initialize *thisptr,
++                              LDR_ADDR locn, struct LDR_SECTION_INFO *info,
++                              unsigned bytsiz, unsigned val);
++
++    /*************************************************************************
++    * Function execute
++    *
++    * Parameters:
++    *   start       Starting address
++    *
++    * Effect:
++    *   The target code at the specified starting address is executed.
++    *
++    * Notes:
++    *   This function is called at the end of the dynamic load process
++    * if the input module has specified a starting address.
++    *************************************************************************/
++              int (*execute) (struct Dynamic_Loader_Initialize *thisptr,
++                              LDR_ADDR start);
++
++    /*************************************************************************
++    * Function release
++    *
++    * Parameters:
++    *   none
++    *
++    * Effect:
++    *   Releases the connection to the load interface.
++    *
++    * Notes:
++    *   This function is called at the end of the dynamic load process.
++    *************************************************************************/
++              void (*release) (struct Dynamic_Loader_Initialize *thisptr);
++
++      };                      /* class Dynamic_Loader_Initialize */
++
++#endif                                /* _DYNAMIC_LOADER_H_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/errbase.h b/arch/arm/plat-omap/include/dspbridge/errbase.h
+new file mode 100644
+index 0000000..f04c005
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/errbase.h
+@@ -0,0 +1,509 @@
++/*
++ * errbase.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== errbase.h ========
++ *  Description:
++ *      Central repository for DSP/BIOS Bridge error and status code.
++ *
++ *  Error codes are of the form:
++ *      [<MODULE>]_E<ERRORCODE>
++ *
++ *  Success codes are of the form:
++ *      [<MODULE>]_S<SUCCESSCODE>
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Jan-2003 map Added DSP_SALREADYLOADED for persistent library checking
++ *! 23-Nov-2002 gp: Minor comment cleanup.
++ *! 13-May-2002 sg  Added DSP_SALREADYASLEEP and DSP_SALREADYWAKE.
++ *! 18-Feb-2002 mk: Added DSP_EOVERLAYMEMORY, EFWRITE, ENOSECT.
++ *! 31-Jan-2002 mk: Added definitions of DSP_STRUE and DSP_SFALSE.
++ *! 29-Jan-2002 mk: Added definition of CFG_E_INSUFFICIENTBUFSIZE.
++ *! 24-Oct-2001 sp: Consolidated all the error codes into this file.
++ *! 24-Jul-2001 mk: Type-casted all definitions of WSX_STATUS types for
++ *!                 removal of compile warnings.
++ *! 22-Nov-1999 kc: Changes from code review.
++ *! 18-Aug-1999 rr: Ported From WSX.
++ *! 29-May-1996 gp: Removed WCD_ and WMD_ error ranges. Redefined format of
++ *!                 error codes.
++ *! 10-May-1996 gp: Created.
++ */
++
++#ifndef ERRBASE_
++#define ERRBASE_
++
++/* Base of generic errors and component errors */
++#define DSP_SBASE               (DSP_STATUS)0x00008000
++#define DSP_EBASE               (DSP_STATUS)0x80008000
++
++#define DSP_COMP_EBASE          (DSP_STATUS)0x80040200
++#define DSP_COMP_ELAST          (DSP_STATUS)0x80047fff
++
++/* SUCCESS Codes */
++
++/* Generic success code */
++#define DSP_SOK                     (DSP_SBASE + 0)
++
++/* GPP is already attached to this DSP processor */
++#define DSP_SALREADYATTACHED        (DSP_SBASE + 1)
++
++/* This is the last object available for enumeration. */
++#define DSP_SENUMCOMPLETE           (DSP_SBASE + 2)
++
++/* The DSP is already asleep. */
++#define DSP_SALREADYASLEEP          (DSP_SBASE + 3)
++
++/* The DSP is already awake. */
++#define DSP_SALREADYAWAKE           (DSP_SBASE + 4)
++
++/* TRUE */
++#define DSP_STRUE                   (DSP_SBASE + 5)
++
++/* FALSE */
++#define DSP_SFALSE                  (DSP_SBASE + 6)
++
++/* A library contains no dependent library references */
++#define DSP_SNODEPENDENTLIBS        (DSP_SBASE + 7)
++
++/* A persistent library is already loaded by the dynamic loader */
++#define DSP_SALREADYLOADED          (DSP_SBASE + 8)
++
++/* Some error occured, but it is OK to continue */
++#define DSP_OKTO_CONTINUE          (DSP_SBASE + 9)
++
++/* FAILURE Codes */
++
++/* The caller does not have access privileges to call this function */
++#define DSP_EACCESSDENIED           (DSP_EBASE + 0)
++
++/* The Specified Connection already exists */
++#define DSP_EALREADYCONNECTED       (DSP_EBASE + 1)
++
++/* The GPP must be detached from the DSP before this function is called */
++#define DSP_EATTACHED               (DSP_EBASE + 2)
++
++/* During enumeration a change in the number or properties of the objects
++ * has occurred. */
++#define DSP_ECHANGEDURINGENUM       (DSP_EBASE + 3)
++
++/* An error occurred while parsing the DSP executable file */
++#define DSP_ECORRUPTFILE            (DSP_EBASE + 4)
++
++/* A failure occurred during a delete operation */
++#define DSP_EDELETE                 (DSP_EBASE + 5)
++
++/* The specified direction is invalid */
++#define DSP_EDIRECTION              (DSP_EBASE + 6)
++
++/* A stream has been issued the maximum number of buffers allowed in the
++ * stream at once ;  buffers must be reclaimed from the stream before any
++ * more can be issued. */
++#define DSP_ESTREAMFULL             (DSP_EBASE + 7)
++
++/* A general failure occurred */
++#define DSP_EFAIL                   (DSP_EBASE + 8)
++
++/* The specified executable file could not be found. */
++#define DSP_EFILE                   (DSP_EBASE + 9)
++
++/* The specified handle is invalid. */
++#define DSP_EHANDLE                 (DSP_EBASE + 0xa)
++
++/* An invalid argument was specified. */
++#define DSP_EINVALIDARG             (DSP_EBASE + 0xb)
++
++/* A memory allocation failure occurred. */
++#define DSP_EMEMORY                 (DSP_EBASE + 0xc)
++
++/* The requested operation is invalid for this node type. */
++#define DSP_ENODETYPE               (DSP_EBASE + 0xd)
++
++/* No error text was found for the specified error code. */
++#define DSP_ENOERRTEXT              (DSP_EBASE + 0xe)
++
++/* No more connections can be made for this node. */
++#define DSP_ENOMORECONNECTIONS      (DSP_EBASE + 0xf)
++
++/* The indicated operation is not supported. */
++#define DSP_ENOTIMPL                (DSP_EBASE + 0x10)
++
++/* I/O is currently pending. */
++#define DSP_EPENDING                (DSP_EBASE + 0x11)
++
++/* An invalid pointer was specified. */
++#define DSP_EPOINTER                (DSP_EBASE + 0x12)
++
++/* A parameter is specified outside its valid range. */
++#define DSP_ERANGE                  (DSP_EBASE + 0x13)
++
++/* An invalid size parameter was specified. */
++#define DSP_ESIZE                   (DSP_EBASE + 0x14)
++
++/* A stream creation failure occurred on the DSP. */
++#define DSP_ESTREAM                 (DSP_EBASE + 0x15)
++
++/* A task creation failure occurred on the DSP. */
++#define DSP_ETASK                   (DSP_EBASE + 0x16)
++
++/* A timeout occurred before the requested operation could complete. */
++
++#define DSP_ETIMEOUT                (DSP_EBASE + 0x17)
++
++/* A data truncation occurred, e.g., when requesting a descriptive error
++ * string, not enough space was allocated for the complete error message. */
++
++#define DSP_ETRUNCATED              (DSP_EBASE + 0x18)
++
++/* A parameter is invalid. */
++#define DSP_EVALUE                  (DSP_EBASE + 0x1a)
++
++/* The state of the specified object is incorrect for the requested
++ * operation. */
++#define DSP_EWRONGSTATE             (DSP_EBASE + 0x1b)
++
++/* Symbol not found in the COFF file.  DSPNode_Create will return this if
++ * the iAlg function table for an xDAIS socket is not found in the COFF file.
++ * In this case, force the symbol to be linked into the COFF file.
++ * DSPNode_Create, DSPNode_Execute, and DSPNode_Delete will return this if
++ * the create, execute, or delete phase function, respectively, could not be
++ * found in the COFF file. */
++#define DSP_ESYMBOL                 (DSP_EBASE + 0x1c)
++
++/* UUID not found in registry.  */
++#define DSP_EUUID                   (DSP_EBASE + 0x1d)
++
++/* Unable to read content of DCD data section ; this is typically caused by
++ * improperly configured nodes. */
++#define DSP_EDCDREADSECT            (DSP_EBASE + 0x1e)
++
++/* Unable to decode DCD data section content ; this is typically caused by
++ * changes to DSP/BIOS Bridge data structures. */
++#define DSP_EDCDPARSESECT           (DSP_EBASE + 0x1f)
++
++/* Unable to get pointer to DCD data section ; this is typically caused by
++ * improperly configured UUIDs. */
++#define DSP_EDCDGETSECT             (DSP_EBASE + 0x20)
++
++/* Unable to load file containing DCD data section ; this is typically
++ * caused by a missing COFF file. */
++#define DSP_EDCDLOADBASE            (DSP_EBASE + 0x21)
++
++/* The specified COFF file does not contain a valid node registration
++ * section. */
++#define DSP_EDCDNOAUTOREGISTER      (DSP_EBASE + 0x22)
++
++/* A requested resource is not available. */
++#define DSP_ERESOURCE               (DSP_EBASE + 0x28)
++
++/* A critical error has occurred, and the DSP is being re-started. */
++#define DSP_ERESTART                (DSP_EBASE + 0x29)
++
++/* A DSP memory free operation failed. */
++#define DSP_EFREE                   (DSP_EBASE + 0x2a)
++
++/* A DSP I/O free operation failed. */
++#define DSP_EIOFREE                 (DSP_EBASE + 0x2b)
++
++/* Multiple instances are not allowed. */
++#define DSP_EMULINST                (DSP_EBASE + 0x2c)
++
++/* A specified entity was not found.  */
++#define DSP_ENOTFOUND               (DSP_EBASE + 0x2d)
++
++/* A DSP I/O resource is not available. */
++#define DSP_EOUTOFIO                (DSP_EBASE + 0x2e)
++
++/* A shared memory buffer contained in a message or stream could not be
++ * mapped to the GPP client process's virtual space. */
++#define DSP_ETRANSLATE              (DSP_EBASE + 0x2f)
++
++/* File or section load write function failed to write to DSP */
++#define DSP_EFWRITE                 (DSP_EBASE + 0x31)
++
++/* Unable to find a named section in DSP executable */
++#define DSP_ENOSECT                 (DSP_EBASE + 0x32)
++
++/* Unable to open file */
++#define DSP_EFOPEN                  (DSP_EBASE + 0x33)
++
++/* Unable to read file */
++#define DSP_EFREAD                  (DSP_EBASE + 0x34)
++
++/* A non-existent memory segment identifier was specified */
++#define DSP_EOVERLAYMEMORY          (DSP_EBASE + 0x37)
++
++/* Invalid segment ID */
++#define DSP_EBADSEGID               (DSP_EBASE + 0x38)
++
++/* Invalid alignment */
++#define DSP_EALIGNMENT               (DSP_EBASE + 0x39)
++
++/* Invalid stream mode */
++#define DSP_ESTRMMODE               (DSP_EBASE + 0x3a)
++
++/* Nodes not connected */
++#define DSP_ENOTCONNECTED           (DSP_EBASE + 0x3b)
++
++/* Not shared memory */
++#define DSP_ENOTSHAREDMEM           (DSP_EBASE + 0x3c)
++
++/* Error occurred in a dynamic loader library function */
++#define DSP_EDYNLOAD                (DSP_EBASE + 0x3d)
++
++/* Device in 'sleep/suspend' mode due to DPM */
++#define DSP_EDPMSUSPEND             (DSP_EBASE + 0x3e)
++
++/* A node-specific error has occurred. */
++#define DSP_EUSER1                  (DSP_EBASE + 0x40)
++#define DSP_EUSER2                  (DSP_EBASE + 0x41)
++#define DSP_EUSER3                  (DSP_EBASE + 0x42)
++#define DSP_EUSER4                  (DSP_EBASE + 0x43)
++#define DSP_EUSER5                  (DSP_EBASE + 0x44)
++#define DSP_EUSER6                  (DSP_EBASE + 0x45)
++#define DSP_EUSER7                  (DSP_EBASE + 0x46)
++#define DSP_EUSER8                  (DSP_EBASE + 0x47)
++#define DSP_EUSER9                  (DSP_EBASE + 0x48)
++#define DSP_EUSER10                 (DSP_EBASE + 0x49)
++#define DSP_EUSER11                 (DSP_EBASE + 0x4a)
++#define DSP_EUSER12                 (DSP_EBASE + 0x4b)
++#define DSP_EUSER13                 (DSP_EBASE + 0x4c)
++#define DSP_EUSER14                 (DSP_EBASE + 0x4d)
++#define DSP_EUSER15                 (DSP_EBASE + 0x4e)
++#define DSP_EUSER16                 (DSP_EBASE + 0x4f)
++
++/* FAILURE Codes : DEV */
++#define DEV_EBASE                   (DSP_COMP_EBASE + 0x000)
++
++/* The mini-driver expected a newer version of the class driver. */
++#define DEV_E_NEWWMD                (DEV_EBASE + 0x00)
++
++/* WMD_DRV_Entry function returned a NULL function interface table. */
++#define DEV_E_NULLWMDINTF           (DEV_EBASE + 0x01)
++
++/* FAILURE Codes : LDR */
++#define LDR_EBASE                   (DSP_COMP_EBASE + 0x100)
++
++/* Insufficient memory to export class driver services. */
++#define LDR_E_NOMEMORY              (LDR_EBASE + 0x00)
++
++/* Unable to find WMD file in system directory. */
++#define LDR_E_FILEUNABLETOOPEN      (LDR_EBASE + 0x01)
++
++/* FAILURE Codes : CFG */
++#define CFG_EBASE                   (DSP_COMP_EBASE + 0x200)
++
++/* Invalid pointer passed into a configuration module function */
++#define CFG_E_INVALIDPOINTER        (CFG_EBASE + 0x00)
++
++/* Invalid device node handle passed into a configuration module function. */
++#define CFG_E_INVALIDHDEVNODE       (CFG_EBASE + 0x01)
++
++/* Unable to retrieve resource information from the registry. */
++#define CFG_E_RESOURCENOTAVAIL      (CFG_EBASE + 0x02)
++
++/* Unable to find board name key in registry. */
++#define CFG_E_INVALIDBOARDNAME      (CFG_EBASE + 0x03)
++
++/* Unable to find a device node in registry with given unit number. */
++#define CFG_E_INVALIDUNITNUM        (CFG_EBASE + 0x04)
++
++/* Insufficient buffer size */
++#define CFG_E_INSUFFICIENTBUFSIZE   (CFG_EBASE + 0x05)
++
++/* FAILURE Codes : BRD */
++#define BRD_EBASE                   (DSP_COMP_EBASE + 0x300)
++
++/* Board client does not have sufficient access rights for this operation. */
++#define BRD_E_ACCESSDENIED          (BRD_EBASE + 0x00)
++
++/* Unable to find trace buffer symbols in the DSP executable COFF file. */
++#define BRD_E_NOTRACEBUFFER         (BRD_EBASE + 0x01)
++
++/* Attempted to auto-start board, but no default DSP executable configured. */
++#define BRD_E_NOEXEC                (BRD_EBASE + 0x02)
++
++/* The operation failed because it was started from a wrong state */
++#define BRD_E_WRONGSTATE            (BRD_EBASE + 0x03)
++
++/* FAILURE Codes : COD */
++#define COD_EBASE                   (DSP_COMP_EBASE + 0x400)
++
++/* No symbol table is loaded for this board. */
++#define COD_E_NOSYMBOLSLOADED       (COD_EBASE + 0x00)
++
++/* Symbol not found in for this board. */
++#define COD_E_SYMBOLNOTFOUND        (COD_EBASE + 0x01)
++
++/* ZL DLL module is not exporting the correct function interface. */
++#define COD_E_NOZLFUNCTIONS         (COD_EBASE + 0x02)
++
++/* Unable to initialize the ZL COFF parsing module. */
++#define COD_E_ZLCREATEFAILED        (COD_EBASE + 0x03)
++
++/* Unable to open DSP executable COFF file. */
++#define COD_E_OPENFAILED            (COD_EBASE + 0x04)
++
++/* Unable to parse DSP executable COFF file. */
++#define COD_E_LOADFAILED            (COD_EBASE + 0x05)
++
++/* Unable to read DSP executable COFF file. */
++#define COD_E_READFAILED            (COD_EBASE + 0x06)
++
++/* FAILURE Codes : CHNL */
++#define CHNL_EBASE                  (DSP_COMP_EBASE + 0x500)
++
++/* Attempt to created channel manager with too many channels. */
++#define CHNL_E_MAXCHANNELS          (CHNL_EBASE + 0x00)
++
++/* No channel manager exists for this mini-driver. */
++#define CHNL_E_NOMGR                (CHNL_EBASE + 0x01)
++
++/* No free channels are available. */
++#define CHNL_E_OUTOFSTREAMS         (CHNL_EBASE + 0x02)
++
++/* Channel ID is out of range. */
++#define CHNL_E_BADCHANID            (CHNL_EBASE + 0x03)
++
++/* Channel is already in use. */
++#define CHNL_E_CHANBUSY             (CHNL_EBASE + 0x04)
++
++/* Invalid channel mode argument. */
++#define CHNL_E_BADMODE              (CHNL_EBASE + 0x05)
++
++/* dwTimeOut parameter was CHNL_IOCNOWAIT, yet no I/O completions were
++ * queued. */
++#define CHNL_E_NOIOC                (CHNL_EBASE + 0x06)
++
++/* I/O has been cancelled on this channel. */
++#define CHNL_E_CANCELLED            (CHNL_EBASE + 0x07)
++
++/* End of stream was already requested on this output channel. */
++#define CHNL_E_EOS                  (CHNL_EBASE + 0x09)
++
++/* Unable to create the channel event object. */
++#define CHNL_E_CREATEEVENT          (CHNL_EBASE + 0x0A)
++
++/* Board name and unit number do not identify a valid board name. */
++#define CHNL_E_BRDID                (CHNL_EBASE + 0x0B)
++
++/* Invalid IRQ configured for this WMD for this system. */
++#define CHNL_E_INVALIDIRQ           (CHNL_EBASE + 0x0C)
++
++/* DSP word size of zero configured for this device. */
++#define CHNL_E_INVALIDWORDSIZE      (CHNL_EBASE + 0x0D)
++
++/* A zero length memory base was specified for a shared memory class driver. */
++#define CHNL_E_INVALIDMEMBASE       (CHNL_EBASE + 0x0E)
++
++/* Memory map is not configured, or unable to map physical to linear
++ * address. */
++#define CHNL_E_NOMEMMAP             (CHNL_EBASE + 0x0F)
++
++/* Attempted to create a channel manager  when one already exists. */
++#define CHNL_E_MGREXISTS            (CHNL_EBASE + 0x10)
++
++/* Unable to plug channel ISR for configured IRQ. */
++#define CHNL_E_ISR                  (CHNL_EBASE + 0x11)
++
++/* No free I/O request packets are available. */
++#define CHNL_E_NOIORPS              (CHNL_EBASE + 0x12)
++
++/* Buffer size is larger than the size of physical channel. */
++#define CHNL_E_BUFSIZE              (CHNL_EBASE + 0x13)
++
++/* User cannot mark end of stream on an input channel. */
++#define CHNL_E_NOEOS                (CHNL_EBASE + 0x14)
++
++/* Wait for flush operation on an output channel timed out. */
++#define CHNL_E_WAITTIMEOUT          (CHNL_EBASE + 0x15)
++
++/* User supplied hEvent must be specified with pstrEventName attribute */
++#define CHNL_E_BADUSEREVENT         (CHNL_EBASE + 0x16)
++
++/* Illegal user event name specified */
++#define CHNL_E_USEREVENTNAME        (CHNL_EBASE + 0x17)
++
++/* Unable to prepare buffer specified */
++#define CHNL_E_PREPFAILED           (CHNL_EBASE + 0x18)
++
++/* Unable to Unprepare buffer specified */
++#define CHNL_E_UNPREPFAILED         (CHNL_EBASE + 0x19)
++
++/* FAILURE Codes : SYNC */
++#define SYNC_EBASE                  (DSP_COMP_EBASE + 0x600)
++
++/* Wait on a kernel event failed. */
++#define SYNC_E_FAIL                 (SYNC_EBASE + 0x00)
++
++/* Timeout expired while waiting for event to be signalled. */
++#define SYNC_E_TIMEOUT              (SYNC_EBASE + 0x01)
++
++/* FAILURE Codes : WMD */
++#define WMD_EBASE                   (DSP_COMP_EBASE + 0x700)
++
++/* A test of hardware assumptions or integrity failed. */
++#define WMD_E_HARDWARE              (WMD_EBASE + 0x00)
++
++/* One or more configuration parameters violated WMD hardware assumptions. */
++#define WMD_E_BADCONFIG             (WMD_EBASE + 0x01)
++
++/* Timeout occurred waiting for a response from the hardware. */
++#define WMD_E_TIMEOUT               (WMD_EBASE + 0x02)
++
++/* FAILURE Codes : REG */
++#define REG_EBASE                   (DSP_COMP_EBASE + 0x800)
++
++/* Invalid subkey parameter. */
++#define REG_E_INVALIDSUBKEY         (REG_EBASE + 0x00)
++
++/* Invalid entry parameter. */
++#define REG_E_INVALIDENTRY          (REG_EBASE + 0x01)
++
++/* No more registry values. */
++#define REG_E_NOMOREITEMS           (REG_EBASE + 0x02)
++
++/* Insufficient space to hold data in registry value. */
++#define REG_E_MOREDATA              (REG_EBASE + 0x03)
++
++/* FAILURE Codes : KFILE */
++#define KFILE_EBASE                 (DSP_COMP_EBASE + 0x900)
++
++/* Invalid file handle. */
++#define E_KFILE_INVALIDHANDLE       (KFILE_EBASE + 0x01)
++
++/* Bad file name. */
++#define E_KFILE_BADFILENAME         (KFILE_EBASE + 0x02)
++
++/* Invalid file mode. */
++#define E_KFILE_INVALIDMODE         (KFILE_EBASE + 0x03)
++
++/* No resources available. */
++#define E_KFILE_NORESOURCES         (KFILE_EBASE + 0x04)
++
++/* Invalid file buffer        . */
++#define E_KFILE_INVALIDBUFFER       (KFILE_EBASE + 0x05)
++
++/* Bad origin argument. */
++#define E_KFILE_BADORIGINFLAG       (KFILE_EBASE + 0x06)
++
++/* Invalid file offset value. */
++#define E_KFILE_INVALIDOFFSET       (KFILE_EBASE + 0x07)
++
++/* General KFILE error condition */
++#define E_KFILE_ERROR               (KFILE_EBASE + 0x08)
++
++#endif                                /* ERRBASE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gb.h b/arch/arm/plat-omap/include/dspbridge/gb.h
+new file mode 100644
+index 0000000..f147751
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gb.h
+@@ -0,0 +1,85 @@
++/*
++ * gb.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== gb.h ========
++ *  Generic bitmap manager.
++ *
++ *! Revision History
++ *! ================
++ */
++
++#ifndef GB_
++#define GB_
++
++#define GB_NOBITS (~0)
++#include <dspbridge/host_os.h>
++typedef s32 GB_BitNum;
++struct GB_TMap;
++
++/*
++ *  ======== GB_clear ========
++ *  Clear the bit in position bitn in the bitmap map.  Bit positions are
++ *  zero based.
++ */
++
++extern void GB_clear(struct GB_TMap *map, GB_BitNum bitn);
++
++/*
++ *  ======== GB_create ========
++ *  Create a bit map with len bits.  Initially all bits are cleared.
++ */
++
++extern struct GB_TMap *GB_create(GB_BitNum len);
++
++/*
++ *  ======== GB_delete ========
++ *  Delete previously created bit map
++ */
++
++extern void GB_delete(struct GB_TMap *map);
++
++/*
++ *  ======== GB_findandset ========
++ *  Finds a clear bit, sets it, and returns the position
++ */
++
++extern GB_BitNum GB_findandset(struct GB_TMap *map);
++
++/*
++ *  ======== GB_minclear ========
++ *  GB_minclear returns the minimum clear bit position.  If no bit is
++ *  clear, GB_minclear returns -1.
++ */
++extern GB_BitNum GB_minclear(struct GB_TMap *map);
++
++/*
++ *  ======== GB_set ========
++ *  Set the bit in position bitn in the bitmap map.  Bit positions are
++ *  zero based.
++ */
++
++extern void GB_set(struct GB_TMap *map, GB_BitNum bitn);
++
++/*
++ *  ======== GB_test ========
++ *  Returns TRUE if the bit in position bitn is set in map; otherwise
++ *  GB_test returns FALSE.  Bit positions are zero based.
++ */
++
++extern bool GB_test(struct GB_TMap *map, GB_BitNum bitn);
++
++#endif                                /*GB_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/getsection.h b/arch/arm/plat-omap/include/dspbridge/getsection.h
+new file mode 100644
+index 0000000..33ff50d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/getsection.h
+@@ -0,0 +1,118 @@
++/*
++ * getsection.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++#ifndef _GETSECTION_H_
++#define _GETSECTION_H_
++
++
++#include "dynamic_loader.h"
++
++/*
++ * Get Section Information
++ *
++ * This file provides an API add-on to the dynamic loader that allows the user
++ * to query section information and extract section data from dynamic load
++ * modules.
++ *
++ * NOTE:
++ * Functions in this API assume that the supplied Dynamic_Loader_Stream object
++ * supports the set_file_posn method.
++ */
++
++      /* opaque handle for module information */
++      typedef void *DLOAD_module_info;
++
++/*
++ * Procedure DLOAD_module_open
++ *
++ * Parameters:
++ *  module  The input stream that supplies the module image
++ *  syms    Host-side malloc/free and error reporting functions.
++ *          Other methods are unused.
++ *
++ * Effect:
++ *  Reads header information from a dynamic loader module using the specified
++ * stream object, and returns a handle for the module information.  This
++ * handle may be used in subsequent query calls to obtain information
++ * contained in the module.
++ *
++ * Returns:
++ *  NULL if an error is encountered, otherwise a module handle for use
++ * in subsequent operations.
++ */
++      extern DLOAD_module_info DLOAD_module_open(struct Dynamic_Loader_Stream
++                                                 *module,
++                                                 struct Dynamic_Loader_Sym
++                                                 *syms);
++
++/*
++ * Procedure DLOAD_GetSectionInfo
++ *
++ * Parameters:
++ *  minfo       Handle from DLOAD_module_open for this module
++ *  sectionName Pointer to the string name of the section desired
++ *  sectionInfo Address of a section info structure pointer to be initialized
++ *
++ * Effect:
++ *  Finds the specified section in the module information, and fills in
++ * the provided LDR_SECTION_INFO structure.
++ *
++ * Returns:
++ *  TRUE for success, FALSE for section not found
++ */
++      extern int DLOAD_GetSectionInfo(DLOAD_module_info minfo,
++                                      const char *sectionName,
++                                      const struct LDR_SECTION_INFO
++                                      ** const sectionInfo);
++
++/*
++ * Procedure DLOAD_GetSection
++ *
++ * Parameters:
++ *  minfo       Handle from DLOAD_module_open for this module
++ *  sectionInfo Pointer to a section info structure for the desired section
++ *  sectionData Buffer to contain the section initialized data
++ *
++ * Effect:
++ *  Copies the initialized data for the specified section into the
++ * supplied buffer.
++ *
++ * Returns:
++ *  TRUE for success, FALSE for section not found
++ */
++      extern int DLOAD_GetSection(DLOAD_module_info minfo,
++                                  const struct LDR_SECTION_INFO *sectionInfo,
++                                  void *sectionData);
++
++/*
++ * Procedure DLOAD_module_close
++ *
++ * Parameters:
++ *  minfo       Handle from DLOAD_module_open for this module
++ *
++ * Effect:
++ *  Releases any storage associated with the module handle.  On return,
++ * the module handle is invalid.
++ *
++ * Returns:
++ *  Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report(), where syms was
++ * an argument to DLOAD_module_open
++ */
++      extern void DLOAD_module_close(DLOAD_module_info minfo);
++
++#endif                                /* _GETSECTION_H_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gh.h b/arch/arm/plat-omap/include/dspbridge/gh.h
+new file mode 100644
+index 0000000..089a042
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gh.h
+@@ -0,0 +1,37 @@
++/*
++ * gh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== gh.h ========
++ *
++ *! Revision History
++ *! ================
++ */
++
++#ifndef GH_
++#define GH_
++#include <dspbridge/host_os.h>
++
++extern struct GH_THashTab *GH_create(u16 maxBucket, u16 valSize,
++              u16(*hash) (void *, u16), bool(*match) (void *, void *),
++              void(*delete) (void *));
++extern void GH_delete(struct GH_THashTab *hashTab);
++extern void GH_exit(void);
++extern void *GH_find(struct GH_THashTab *hashTab, void *key);
++extern void GH_init(void);
++extern void *GH_insert(struct GH_THashTab *hashTab, void *key, void *value);
++#endif                                /* GH_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gs.h b/arch/arm/plat-omap/include/dspbridge/gs.h
+new file mode 100644
+index 0000000..fd5ef27
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gs.h
+@@ -0,0 +1,64 @@
++/*
++ * gs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== gs.h ========
++ *  Memory allocation/release wrappers.  This module allows clients to
++ *  avoid OS spacific issues related to memory allocation.  It also provides
++ *  simple diagnostic capabilities to assist in the detection of memory
++ *  leaks.
++ *! Revision History
++ *! ================
++ */
++
++#ifndef GS_
++#define GS_
++
++/*
++ *  ======== GS_alloc ========
++ *  Alloc size bytes of space.  Returns pointer to space
++ *  allocated, otherwise NULL.
++ */
++extern void *GS_alloc(u32 size);
++
++/*
++ *  ======== GS_exit ========
++ *  Module exit.  Do not change to "#define GS_init()"; in
++ *  some environments this operation must actually do some work!
++ */
++extern void GS_exit(void);
++
++/*
++ *  ======== GS_free ========
++ *  Free space allocated by GS_alloc() or GS_calloc().
++ */
++extern void GS_free(void *ptr);
++
++/*
++ *  ======== GS_frees ========
++ *  Free space allocated by GS_alloc() or GS_calloc() and assert that
++ *  the size of the allocation is size bytes.
++ */
++extern void GS_frees(void *ptr, u32 size);
++
++/*
++ *  ======== GS_init ========
++ *  Module initialization.  Do not change to "#define GS_init()"; in
++ *  some environments this operation must actually do some work!
++ */
++extern void GS_init(void);
++
++#endif                                /*GS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gt.h b/arch/arm/plat-omap/include/dspbridge/gt.h
+new file mode 100644
+index 0000000..456c866
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gt.h
+@@ -0,0 +1,315 @@
++/*
++ * gt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== gt.h ========
++ *  Purpose:
++ *      There are two definitions that affect which portions of trace
++ *      are acutally compiled into the client: GT_TRACE and GT_ASSERT. If
++ *      GT_TRACE is set to 0 then all trace statements (except for assertions)
++ *      will be compiled out of the client. If GT_ASSERT is set to 0 then
++ *      assertions will be compiled out of the client. GT_ASSERT can not be
++ *      set to 0 unless GT_TRACE is also set to 0 (i.e. GT_TRACE == 1 implies
++ *      GT_ASSERT == 1).
++ *
++ *! Revision History
++ *! ================
++ *! 02-Feb-2000 rr: Renamed this file to gtce.h. GT CLASS and trace definitions
++ *!                 are WinCE Specific.
++ *! 03-Jan-1997       ge      Replaced "GT_" prefix to GT_Config structure members
++ *!                 to eliminate preprocessor confusion with other macros.
++ */
++#include <linux/types.h>
++#ifndef GT_
++#define GT_
++
++#ifndef GT_TRACE
++#define GT_TRACE 0        /* 0 = "trace compiled out"; 1 = "trace active" */
++#endif
++
++#include <dspbridge/host_os.h>
++
++#if !defined(GT_ASSERT) || GT_TRACE
++#define GT_ASSERT 1
++#endif
++
++struct GT_Config {
++      Fxn PRINTFXN;
++      Fxn PIDFXN;
++      Fxn TIDFXN;
++      Fxn ERRORFXN;
++};
++
++extern struct GT_Config *GT;
++
++struct GT_Mask {
++      char *modName;
++      u8 *flags;
++} ;
++
++/*
++ *  New GT Class defenitions.
++ *
++ *  The following are the explanations and how it could be used in the code
++ *
++ *  -   GT_ENTER    On Entry to Functions
++ *
++ *  -   GT_1CLASS   Display level of debugging status- Object/Automatic
++ *                  variables
++ *  -   GT_2CLASS   ---- do ----
++ *
++ *  -   GT_3CLASS   ---- do ---- + It can be used(recommended) for debug
++ *                status in the ISR, IST
++ *  -   GT_4CLASS   ---- do ----
++ *
++ *  -   GT_5CLASS   Display entry for module init/exit functions
++ *
++ *  -   GT_6CLASS   Warn whenever SERVICES function fails
++ *
++ *  -   GT_7CLASS   Warn failure of Critical failures
++ *
++ */
++
++#define GT_ENTER      ((u8)0x01)
++#define GT_1CLASS     ((u8)0x02)
++#define GT_2CLASS     ((u8)0x04)
++#define GT_3CLASS     ((u8)0x08)
++#define GT_4CLASS     ((u8)0x10)
++#define GT_5CLASS     ((u8)0x20)
++#define GT_6CLASS     ((u8)0x40)
++#define GT_7CLASS     ((u8)0x80)
++
++#ifdef _LINT_
++
++/* LINTLIBRARY */
++
++/*
++ *  ======== GT_assert ========
++ */
++/* ARGSUSED */
++void GT_assert(struct GT_Mask mask, s32 expr)
++{
++}
++
++/*
++ *  ======== GT_config ========
++ */
++/* ARGSUSED */
++void GT_config(struct GT_Config config)
++{
++}
++
++/*
++ *  ======== GT_create ========
++ */
++/* ARGSUSED */
++void GT_create(struct GT_Mask *mask, char *modName)
++{
++}
++
++/*
++ *  ======== GT_curLine ========
++ *  Purpose:
++ *      Returns the current source code line number. Is useful for performing
++ *      branch testing using trace.  For example,
++ *
++ *      GT_1trace(curTrace, GT_1CLASS,
++ *          "in module XX_mod, executing line %u\n", GT_curLine());
++ */
++/* ARGSUSED */
++u16 GT_curLine(void)
++{
++      return (u16)NULL;
++}
++
++/*
++ *  ======== GT_exit ========
++ */
++/* ARGSUSED */
++void GT_exit(void)
++{
++}
++
++/*
++ *  ======== GT_init ========
++ */
++/* ARGSUSED */
++void GT_init(void)
++{
++}
++
++/*
++ *  ======== GT_query ========
++ */
++/* ARGSUSED */
++bool GT_query(struct GT_Mask mask, u8 class)
++{
++      return false;
++}
++
++/*
++ *  ======== GT_set ========
++ *  sets trace mask according to settings
++ */
++
++/* ARGSUSED */
++void GT_set(char *settings)
++{
++}
++
++/*
++ *  ======== GT_setprintf ========
++ *  sets printf function
++ */
++
++/* ARGSUSED */
++void GT_setprintf(Fxn fxn)
++{
++}
++
++/* ARGSUSED */
++void GT_0trace(struct GT_Mask mask, u8 class, char *format)
++{
++}
++
++/* ARGSUSED */
++void GT_1trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_2trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_3trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_4trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_5trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_6trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++#else
++
++#define       GT_BOUND    26          /* 26 letters in alphabet */
++
++extern void _GT_create(struct GT_Mask *mask, char *modName);
++
++#define GT_exit()
++
++extern void GT_init(void);
++extern void _GT_set(char *str);
++extern s32 _GT_trace(struct GT_Mask *mask, char *format, ...);
++
++#if GT_ASSERT == 0
++
++#define GT_assert(mask, expr)
++#define GT_config(config)
++#define GT_configInit(config)
++#define GT_seterror(fxn)
++
++#else
++
++extern struct GT_Config _GT_params;
++
++#define GT_assert(mask, expr) \
++      (!(expr) ? \
++          printk("assertion violation: %s, line %d\n", \
++                          __FILE__, __LINE__), NULL : NULL)
++
++#define GT_config(config)     (_GT_params = *(config))
++#define GT_configInit(config) (*(config) = _GT_params)
++#define GT_seterror(fxn)      (_GT_params.ERRORFXN = (Fxn)(fxn))
++
++#endif
++
++#if GT_TRACE == 0
++
++#define GT_curLine()                ((u16)__LINE__)
++#define GT_create(mask, modName)
++#define GT_exit()
++#define GT_init()
++#define GT_set(settings)
++#define GT_setprintf(fxn)
++
++#define GT_query(mask, class)     false
++
++#define GT_0trace(mask, class, format)
++#define GT_1trace(mask, class, format, arg1)
++#define GT_2trace(mask, class, format, arg1, arg2)
++#define GT_3trace(mask, class, format, arg1, arg2, arg3)
++#define GT_4trace(mask, class, format, arg1, arg2, arg3, arg4)
++#define GT_5trace(mask, class, format, arg1, arg2, arg3, arg4, arg5)
++#define GT_6trace(mask, class, format, arg1, arg2, arg3, arg4, arg5, arg6)
++
++#else                         /* GT_TRACE == 1 */
++
++
++#define GT_create(mask, modName)    _GT_create((mask), (modName))
++#define GT_curLine()                ((u16)__LINE__)
++#define GT_set(settings)          _GT_set(settings)
++#define GT_setprintf(fxn)         (_GT_params.PRINTFXN = (Fxn)(fxn))
++
++#define GT_query(mask, class) ((*(mask).flags & (class)))
++
++#define GT_0trace(mask, class, format) \
++    ((*(mask).flags & (class)) ? \
++    _GT_trace(&(mask), (format)) : 0)
++
++#define GT_1trace(mask, class, format, arg1) \
++    ((*(mask).flags & (class)) ? \
++    _GT_trace(&(mask), (format), (arg1)) : 0)
++
++#define GT_2trace(mask, class, format, arg1, arg2) \
++    ((*(mask).flags & (class)) ? \
++    _GT_trace(&(mask), (format), (arg1), (arg2)) : 0)
++
++#define GT_3trace(mask, class, format, arg1, arg2, arg3) \
++    ((*(mask).flags & (class)) ? \
++    _GT_trace(&(mask), (format), (arg1), (arg2), (arg3)) : 0)
++
++#define GT_4trace(mask, class, format, arg1, arg2, arg3, arg4) \
++    ((*(mask).flags & (class)) ? \
++    _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4)) : 0)
++
++#define GT_5trace(mask, class, format, arg1, arg2, arg3, arg4, arg5) \
++    ((*(mask).flags & (class)) ? \
++    _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4), (arg5)) : 0)
++
++#define GT_6trace(mask, class, format, arg1, arg2, arg3, arg4, arg5, arg6) \
++    ((*(mask).flags & (class)) ? \
++    _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4), (arg5), \
++      (arg6)) : 0)
++
++#endif                                /* GT_TRACE */
++
++#endif                                /* _LINT_ */
++
++#endif                                /* GTCE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/host_os.h b/arch/arm/plat-omap/include/dspbridge/host_os.h
+new file mode 100644
+index 0000000..f539bd0
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/host_os.h
+@@ -0,0 +1,96 @@
++/*
++ * host_os.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== windows.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 08-Mar-2004 sb Added cacheflush.h to support Dynamic Memory Mapping feature
++ *! 16-Feb-2004 sb Added headers required for consistent_alloc
++ */
++
++#ifndef _HOST_OS_H_
++#define _HOST_OS_H_
++
++#include <linux/autoconf.h>
++#include <asm/system.h>
++#include <asm/atomic.h>
++#include <linux/semaphore.h>
++#include <linux/uaccess.h>
++#include <linux/irq.h>
++#include <linux/io.h>
++#include <linux/syscalls.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/stddef.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/file.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/ctype.h>
++#include <linux/mm.h>
++#include <linux/device.h>
++#include <linux/vmalloc.h>
++#include <linux/ioport.h>
++#include <linux/platform_device.h>
++#include <dspbridge/dbtype.h>
++#include <mach/clock.h>
++#include <linux/clk.h>
++#include <linux/pagemap.h>
++#include <asm/cacheflush.h>
++#include <linux/dma-mapping.h>
++
++/*  ----------------------------------- Macros */
++
++#define SEEK_SET        0     /* Seek from beginning of file.  */
++#define SEEK_CUR        1     /* Seek from current position.  */
++#define SEEK_END        2     /* Seek from end of file.  */
++
++/* TODO -- Remove, once BP defines them */
++#define INT_MAIL_MPU_IRQ        26
++#define INT_DSP_MMU_IRQ        28
++
++struct dspbridge_platform_data {
++      void    (*dsp_set_min_opp)(u8 opp_id);
++      u8      (*dsp_get_opp)(void);
++      void    (*cpu_set_freq)(unsigned long f);
++      unsigned long (*cpu_get_freq)(void);
++      unsigned long mpu_speed[6];
++
++      u32 phys_mempool_base;
++      u32 phys_mempool_size;
++};
++
++#define PRCM_VDD1 1
++
++extern struct platform_device *omap_dspbridge_dev;
++
++#if defined(CONFIG_MPU_BRIDGE) || defined(CONFIG_MPU_BRIDGE_MODULE)
++extern void dspbridge_reserve_sdram(void);
++#else
++static inline void dspbridge_reserve_sdram(void) {}
++#endif
++
++extern unsigned long dspbridge_get_mempool_base(void);
++#endif
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/io.h b/arch/arm/plat-omap/include/dspbridge/io.h
+new file mode 100644
+index 0000000..6dc63f2
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/io.h
+@@ -0,0 +1,132 @@
++/*
++ * io.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== io.h ========
++ *  Description:
++ *      The io module manages IO between CHNL and MSG.
++ *
++ *  Public Functions:
++ *      IO_Create
++ *      IO_Destroy
++ *      IO_Exit
++ *      IO_Init
++ *      IO_OnLoaded
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Nov-2000 jeh     Created.
++ */
++
++#ifndef IO_
++#define IO_
++
++#include <dspbridge/cfgdefs.h>
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/iodefs.h>
++
++/*
++ *  ======== IO_Create ========
++ *  Purpose:
++ *      Create an IO manager object, responsible for managing IO between
++ *      CHNL and MSG.
++ *  Parameters:
++ *      phChnlMgr:              Location to store a channel manager object on
++ *                              output.
++ *      hDevObject:             Handle to a device object.
++ *      pMgrAttrs:              IO manager attributes.
++ *      pMgrAttrs->bIRQ:        I/O IRQ number.
++ *      pMgrAttrs->fShared:     TRUE if the IRQ is shareable.
++ *      pMgrAttrs->uWordSize:   DSP Word size in equivalent PC bytes..
++ *  Returns:
++ *      DSP_SOK:                Success;
++ *      DSP_EMEMORY:            Insufficient memory for requested resources.
++ *      CHNL_E_ISR:             Unable to plug channel ISR for configured IRQ.
++ *      CHNL_E_INVALIDIRQ:      Invalid IRQ number. Must be 0 <= bIRQ <= 15.
++ *      CHNL_E_INVALIDWORDSIZE: Invalid DSP word size.  Must be > 0.
++ *      CHNL_E_INVALIDMEMBASE:  Invalid base address for DSP communications.
++ *  Requires:
++ *      IO_Init(void) called.
++ *      phIOMgr != NULL.
++ *      pMgrAttrs != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS IO_Create(OUT struct IO_MGR **phIOMgr,
++                                  struct DEV_OBJECT *hDevObject,
++                                  IN CONST struct IO_ATTRS *pMgrAttrs);
++
++/*
++ *  ======== IO_Destroy ========
++ *  Purpose:
++ *      Destroy the IO manager.
++ *  Parameters:
++ *      hIOMgr:         IOmanager object.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    hIOMgr was invalid.
++ *  Requires:
++ *      IO_Init(void) called.
++ *  Ensures:
++ */
++      extern DSP_STATUS IO_Destroy(struct IO_MGR *hIOMgr);
++
++/*
++ *  ======== IO_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the IO module.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      IO_Init(void) previously called.
++ *  Ensures:
++ *      Resources, if any acquired in IO_Init(void), are freed when the last
++ *      client of IO calls IO_Exit(void).
++ */
++      extern void IO_Exit(void);
++
++/*
++ *  ======== IO_Init ========
++ *  Purpose:
++ *      Initialize the IO module's private state.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialized; FALSE if error occurred.
++ *  Requires:
++ *  Ensures:
++ *      A requirement for each of the other public CHNL functions.
++ */
++      extern bool IO_Init(void);
++
++/*
++ *  ======== IO_OnLoaded ========
++ *  Purpose:
++ *      Called when a program is loaded so IO manager can update its
++ *      internal state.
++ *  Parameters:
++ *      hIOMgr:         IOmanager object.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    hIOMgr was invalid.
++ *  Requires:
++ *      IO_Init(void) called.
++ *  Ensures:
++ */
++      extern DSP_STATUS IO_OnLoaded(struct IO_MGR *hIOMgr);
++
++#endif                                /* CHNL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/io_sm.h b/arch/arm/plat-omap/include/dspbridge/io_sm.h
+new file mode 100644
+index 0000000..3dcbf74
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/io_sm.h
+@@ -0,0 +1,335 @@
++/*
++ * io_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== io_sm.h ========
++ *  Description:
++ *      IO dispatcher for a shared memory channel driver.
++ *      Also, includes macros to simulate SHM via port io calls.
++ *
++ *  Public Functions:
++ *      IO_Dispatch
++ *      IO_DPC
++ *      IO_ISR
++ *      IO_RequestChnl
++ *
++ *  Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 01-Mar-2004 vp: Added IVA releated functions.
++ *! 23-Apr-2003 sb: Fixed mailbox deadlock
++ *! 06-Feb-2003 kc  Added IO_DDMAClearChnlDesc and IO_DDZCClearChnlDesc.
++ *! 21-Dec-2001 ag  Removed unused param in IO_DDMAInitChnlDesc().
++ *                  Updated comments. Removed #ifdef CHNL_NOIPCINTR.
++ *! 05-Nov-2001 kc  Updated IO_CALLISR macro.
++ *! 01-May-2001 jeh Removed IO_RequestMsg.
++ *! 29-Mar-2001 ag  Added #ifdef CHNL_NOIPCINTR.
++ *! 04-Dec-2000 jeh Added IO_RequestMsg.
++ *! 26-Oct-2000 jeh Added IO_GetLong, IO_SetLong, IO_ReadValueLong, and
++ *!                 IO_WriteValueLong, for passing arg in SHM structure.
++ *! 20-Jan-2000 ag: Updated header comments per code review.
++ *! 05-Jan-2000 ag: Text format clean-up.
++ *! 02-Nov-1999 ag: Updated header descriptions.
++ *! 25-May-1999 jg: Removed assumption of 4 bytes / word.
++ *! 12-Aug-1996 gp: Created.
++ */
++
++#ifndef IOSM_
++#define IOSM_
++
++#include <dspbridge/_chnl_sm.h>
++#include <dspbridge/host_os.h>
++
++#include <dspbridge/iodefs.h>
++
++#define IO_INPUT            0
++#define IO_OUTPUT           1
++#define IO_SERVICE          2
++#define IO_MAXSERVICE       IO_SERVICE
++
++#define IO_MGRSIGNATURE     0x494f4D43        /* "IOGR" */
++
++#define DSPFieldAddr(type, field, base, wordsize) \
++    ((((s32)&(((type *)0)->field)) / wordsize) + (u32)base)
++
++/* Access can be different SM access word size (e.g. 16/32 bit words) */
++#define IO_SetValue(pContext, type, base, field, value) (base->field = value)
++#define IO_GetValue(pContext, type, base, field)      (base->field)
++#define IO_OrValue(pContext, type, base, field, value)  (base->field |= value)
++#define IO_AndValue(pContext, type, base, field, value) (base->field &= value)
++#define IO_SetLong(pContext, type, base, field, value)  (base->field = value)
++#define IO_GetLong(pContext, type, base, field)         (base->field)
++
++#define IO_DisableInterrupt(h)  CHNLSM_DisableInterrupt(h)
++#define IO_EnableInterrupt(h)   CHNLSM_EnableInterrupt(h)
++#define IO_CALLISR(h, pFlag, pwMBRegVal)   CHNLSM_ISR(h, pFlag, pwMBRegVal)
++
++/*
++ *  ======== IO_CancelChnl ========
++ *  Purpose:
++ *      Cancel IO on a given channel.
++ *  Parameters:
++ *      hIOMgr:     IO Manager.
++ *      ulChnl:     Index of channel to cancel IO on.
++ *  Returns:
++ *  Requires:
++ *      Valid hIOMgr.
++ *  Ensures:
++ */
++      extern void IO_CancelChnl(struct IO_MGR *hIOMgr, u32 ulChnl);
++
++/*
++ *  ======== IO_DPC ========
++ *  Purpose:
++ *      Deferred procedure call for shared memory channel driver ISR.  Carries
++ *      out the dispatch of I/O.
++ *  Parameters:
++ *      pRefData:   Pointer to reference data registered via a call to
++ *                  DPC_Create().
++ *  Returns:
++ *  Requires:
++ *      Must not block.
++ *      Must not acquire resources.
++ *      All data touched must be locked in memory if running in kernel mode.
++ *  Ensures:
++ *      Non-preemptible (but interruptible).
++ */
++      extern void IO_DPC(IN OUT void *pRefData);
++
++/*
++ *  ======== IO_ISR ========
++ *  Purpose:
++ *      Main interrupt handler for the shared memory WMD channel manager.
++ *      Calls the WMD's CHNLSM_ISR to determine if this interrupt is ours, then
++ *      schedules a DPC to dispatch I/O..
++ *  Parameters:
++ *      pRefData:   Pointer to the channel manager object for this board.
++ *                  Set in an initial call to ISR_Install().
++ *  Returns:
++ *      TRUE if interrupt handled; FALSE otherwise.
++ *  Requires:
++ *      Must be in locked memory if executing in kernel mode.
++ *      Must only call functions which are in locked memory if Kernel mode.
++ *      Must only call asynchronous services.
++ *      Interrupts are disabled and EOI for this interrupt has been sent.
++ *  Ensures:
++ */
++       irqreturn_t IO_ISR(int irq, IN void *pRefData);
++/*
++ *  ======== IO_RequestChnl ========
++ *  Purpose:
++ *      Request I/O from the DSP. Sets flags in shared memory, then interrupts
++ *      the DSP.
++ *  Parameters:
++ *      hIOMgr:     IO manager handle.
++ *      pChnl:      Ptr to the channel requesting I/O.
++ *      iMode:      Mode of channel: {IO_INPUT | IO_OUTPUT}.
++ *  Returns:
++ *  Requires:
++ *      pChnl != NULL
++ *  Ensures:
++ */
++      extern void IO_RequestChnl(struct IO_MGR *hIOMgr,
++                                 struct CHNL_OBJECT *pChnl,
++                                 u32 iMode, OUT u16 *pwMbVal);
++
++/*
++ *  ======== IO_Schedule ========
++ *  Purpose:
++ *      Schedule DPC for IO.
++ *  Parameters:
++ *      pIOMgr:     Ptr to a I/O manager.
++ *  Returns:
++ *  Requires:
++ *      pChnl != NULL
++ *  Ensures:
++ */
++      extern void IO_Schedule(struct IO_MGR *hIOMgr);
++
++/*
++ * DSP-DMA IO functions
++ */
++
++/*
++ *  ======== IO_DDMAInitChnlDesc ========
++ *  Purpose:
++ *      Initialize DSP DMA channel descriptor.
++ *  Parameters:
++ *      hIOMgr:         Handle to a I/O manager.
++ *      uDDMAChnlId:    DDMA channel identifier.
++ *      uNumDesc:       Number of buffer descriptors(equals # of IOReqs &
++ *                      Chirps)
++ *      pDsp:           Dsp address;
++ *  Returns:
++ *  Requires:
++ *     uDDMAChnlId < DDMA_MAXDDMACHNLS
++ *     uNumDesc > 0
++ *     pVa != NULL
++ *     pDspPa != NULL
++ *
++ *  Ensures:
++ */
++      extern void IO_DDMAInitChnlDesc(struct IO_MGR *hIOMgr, u32 uDDMAChnlId,
++                                      u32 uNumDesc, void *pDsp);
++
++/*
++ *  ======== IO_DDMAClearChnlDesc ========
++ *  Purpose:
++ *      Clear DSP DMA channel descriptor.
++ *  Parameters:
++ *      hIOMgr:         Handle to a I/O manager.
++ *      uDDMAChnlId:    DDMA channel identifier.
++ *  Returns:
++ *  Requires:
++ *     uDDMAChnlId < DDMA_MAXDDMACHNLS
++ *  Ensures:
++ */
++      extern void IO_DDMAClearChnlDesc(struct IO_MGR *hIOMgr,
++                                       u32 uDDMAChnlId);
++
++/*
++ *  ======== IO_DDMARequestChnl ========
++ *  Purpose:
++ *      Request channel DSP-DMA from the DSP. Sets up SM descriptors and
++ *      control fields in shared memory.
++ *  Parameters:
++ *      hIOMgr:     Handle to a I/O manager.
++ *      pChnl:      Ptr to channel object
++ *      pChirp:     Ptr to channel i/o request packet.
++ *  Returns:
++ *  Requires:
++ *      pChnl != NULL
++ *      pChnl->cIOReqs > 0
++ *      pChirp != NULL
++ *  Ensures:
++ */
++      extern void IO_DDMARequestChnl(struct IO_MGR *hIOMgr,
++                                     struct CHNL_OBJECT *pChnl,
++                                     struct CHNL_IRP *pChirp,
++                                     OUT u16 *pwMbVal);
++
++/*
++ * Zero-copy IO functions
++ */
++
++/*
++ *  ======== IO_DDZCInitChnlDesc ========
++ *  Purpose:
++ *      Initialize ZCPY channel descriptor.
++ *  Parameters:
++ *      hIOMgr:     Handle to a I/O manager.
++ *      uZId:       zero-copy channel identifier.
++ *  Returns:
++ *  Requires:
++ *     uDDMAChnlId < DDMA_MAXZCPYCHNLS
++ *     hIOMgr != Null
++ *  Ensures:
++ */
++      extern void IO_DDZCInitChnlDesc(struct IO_MGR *hIOMgr, u32 uZId);
++
++/*
++ *  ======== IO_DDZCClearChnlDesc ========
++ *  Purpose:
++ *      Clear DSP ZC channel descriptor.
++ *  Parameters:
++ *      hIOMgr:         Handle to a I/O manager.
++ *      uChnlId:        ZC channel identifier.
++ *  Returns:
++ *  Requires:
++ *      hIOMgr is valid
++ *      uChnlId < DDMA_MAXZCPYCHNLS
++ *  Ensures:
++ */
++      extern void IO_DDZCClearChnlDesc(struct IO_MGR *hIOMgr, u32 uChnlId);
++
++/*
++ *  ======== IO_DDZCRequestChnl ========
++ *  Purpose:
++ *      Request zero-copy channel transfer. Sets up SM descriptors and
++ *      control fields in shared memory.
++ *  Parameters:
++ *      hIOMgr:         Handle to a I/O manager.
++ *      pChnl:          Ptr to channel object
++ *      pChirp:         Ptr to channel i/o request packet.
++ *  Returns:
++ *  Requires:
++ *      pChnl != NULL
++ *      pChnl->cIOReqs > 0
++ *      pChirp != NULL
++ *  Ensures:
++ */
++      extern void IO_DDZCRequestChnl(struct IO_MGR *hIOMgr,
++                                     struct CHNL_OBJECT *pChnl,
++                                     struct CHNL_IRP *pChirp,
++                                     OUT u16 *pwMbVal);
++
++/*
++ *  ======== IO_SHMsetting ========
++ *  Purpose:
++ *      Sets the shared memory setting
++ *  Parameters:
++ *      hIOMgr:         Handle to a I/O manager.
++ *      desc:             Shared memory type
++ *      pArgs:          Ptr to SHM setting
++ *  Returns:
++ *  Requires:
++ *      hIOMgr != NULL
++ *      pArgs != NULL
++ *  Ensures:
++ */
++      extern DSP_STATUS IO_SHMsetting(IN struct IO_MGR *hIOMgr,
++                                      IN enum SHM_DESCTYPE desc,
++                                      IN void *pArgs);
++
++/*
++ *  Misc functions for the CHNL_IO shared memory library:
++ */
++
++/* Maximum channel bufsize that can be used. */
++      extern u32 IO_BufSize(struct IO_MGR *hIOMgr);
++
++      extern u32 IO_ReadValue(struct WMD_DEV_CONTEXT *hDevContext,
++                                u32 dwDSPAddr);
++
++      extern void IO_WriteValue(struct WMD_DEV_CONTEXT *hDevContext,
++                                u32 dwDSPAddr, u32 dwValue);
++
++      extern u32 IO_ReadValueLong(struct WMD_DEV_CONTEXT *hDevContext,
++                                    u32 dwDSPAddr);
++
++      extern void IO_WriteValueLong(struct WMD_DEV_CONTEXT *hDevContext,
++                                    u32 dwDSPAddr, u32 dwValue);
++
++      extern void IO_OrSetValue(struct WMD_DEV_CONTEXT *hDevContext,
++                                u32 dwDSPAddr, u32 dwValue);
++
++      extern void IO_AndSetValue(struct WMD_DEV_CONTEXT *hDevContext,
++                                 u32 dwDSPAddr, u32 dwValue);
++
++      extern void IO_IntrDSP2(IN struct IO_MGR *pIOMgr, IN u16 wMbVal);
++
++       extern void IO_SM_init(void);
++
++/*
++ *  ========PrintDspTraceBuffer ========
++ *      Print DSP tracebuffer.
++ */
++       extern DSP_STATUS PrintDspTraceBuffer(struct WMD_DEV_CONTEXT
++                                               *hWmdContext);
++
++#endif                                /* IOSM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/iodefs.h b/arch/arm/plat-omap/include/dspbridge/iodefs.h
+new file mode 100644
+index 0000000..f45890a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/iodefs.h
+@@ -0,0 +1,45 @@
++/*
++ * iodefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== iodefs.h ========
++ *  Description:
++ *      System-wide channel objects and constants.
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Nov-2000 jeh     Created.
++ */
++
++#ifndef IODEFS_
++#define IODEFS_
++
++#define IO_MAXIRQ   0xff      /* Arbitrarily large number. */
++
++/* IO Objects: */
++      struct IO_MGR;
++
++/* IO manager attributes: */
++      struct IO_ATTRS {
++              u8 bIRQ;        /* Channel's I/O IRQ number. */
++              bool fShared;   /* TRUE if the IRQ is shareable. */
++              u32 uWordSize;  /* DSP Word size. */
++              u32 dwSMBase;   /* Physical base address of shared memory. */
++              u32 uSMLength;  /* Size (in bytes) of shared memory. */
++      } ;
++
++#endif                                /* IODEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/kfile.h b/arch/arm/plat-omap/include/dspbridge/kfile.h
+new file mode 100644
+index 0000000..23c89b0
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/kfile.h
+@@ -0,0 +1,216 @@
++/*
++ * kfile.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== kfile.h ========
++ *  Purpose:
++ *      Provide file I/O management capabilities.
++ *
++ *  Public Functions:
++ *      KFILE_Close
++ *      KFILE_Exit
++ *      KFILE_Init
++ *      KFILE_Open
++ *      KFILE_Read
++ *      KFILE_Seek
++ *      KFILE_Tell
++ *      KFILE_Write
++ *
++ *  Notes:
++ *      The KFILE module is not like most of the other DSP/BIOS Bridge modules
++ *      in that it doesn't return WSX_STATUS type values.  Rather, it's
++ *      prototypes are meant to match the stdio file prototypes
++ *      (ie, fopen, fclose, etc.).
++ *
++ *! Revision History
++ *! ================
++ *! 29-Oct-1999 kc:  Clean up for code review.
++ *! 07-Jan-1998 cr:  Clean up for code review.
++ *! 15-Aug-1997 cr:  Added E_KFILE_ERROR for general error condition.
++ *! 04-Aug-1997 cr:  Added explicit CDECL descriptions.
++ *! 11-Nov-1996 cr:  Implemented changes based on code review.
++ *! 05-Nov-1996 cr:  Cleaned up for code review.
++ *! 29-May-1996 gp:  Added requirement that size != 0 in _Write() and _Read().
++ *! 28-May-1996 mg:  Changed return values for Read/Write.
++ *! 14-Dec-1995 cr:  Created.
++ */
++
++#ifndef KFILE_
++#define KFILE_
++
++/*
++ *  Constants for KFILE_Seek.  Note that these MUST be the same definitions as
++ *  those defined for fseek.
++ */
++#define KFILE_SEEK_SET          0x00  /* seek from beginning of file */
++#define KFILE_SEEK_CUR          0x01  /* seek from current position */
++#define KFILE_SEEK_END          0x02  /* seek from end of file */
++
++      struct KFILE_FileObj;
++
++/*
++ *  ======== KFILE_Close ========
++ *  Purpose:
++ *      This function closes a file's stream.
++ *  Parameters:
++ *      hFile:      Handle of the file stream returned by KFILE_Open.
++ *  Returns:
++ *      E_KFILE_INVALIDHANDLE:  bad handle.
++ *      0:                      success.
++ *      E_KFILE_ERROR:          unable to close specified handle.
++ *  Requires:
++ *      KFILE initialized.
++ *  Ensures:
++ */
++      extern s32 KFILE_Close(IN struct KFILE_FileObj *hFile);
++
++/*
++ *  ======== KFILE_Exit ========
++ *  Purpose:
++ *      Discontinue usage of module; free resources when reference count
++ *      reaches 0.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      KFILE initialized.
++ *  Ensures:
++ *      Resources used by module are freed when cRef reaches zero.
++ */
++      extern void KFILE_Exit(void);
++
++/*
++ *  ======== KFILE_Init ========
++ *  Purpose:
++ *      Initializes private state of KFILE module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if success, else FALSE.
++ *  Requires:
++ *  Ensures:
++ *      KFILE initialized.
++ */
++      extern bool KFILE_Init(void);
++
++/*
++ *  ======== KFILE_Open ========
++ *  Purpose:
++ *      Opens a file for use.
++ *  Parameters:
++ *      pszFileName:    Full path to name of the file to open.
++ *      pszMode:        String containing open status.  Only the first
++ *                      character of the string is examined, for either
++ *                      "r" (read) or "w" (write) mode.
++ *  Returns:
++ *      A valid file handle if success, else NULL.
++ *  Requires:
++ *      - KFILE initialized.
++ *      - pszMode != NULL.
++ *      - pszFileName != NULL.
++ *  Ensures:
++ */
++      extern struct KFILE_FileObj *KFILE_Open(IN CONST char *filename,
++                                     IN CONST char *mode);
++
++/*
++ *  ======== KFILE_Read ========
++ *  Purpose:
++ *      This function reads a specified number of bytes into a buffer.
++ *  Parameters:
++ *      pBuffer:    Array to which the file data is copied.
++ *      cSize:      Number of characters in each object.
++ *      cCount:     Number of objects to read in.
++ *      hFile:      Handle of the file stream returned by KFILE_Open.
++ *  Returns:
++ *      E_KFILE_INVALIDHANDLE:  bad file handle.
++ *      E_KFILE_ERROR:          general failure.
++ *      > 0:                    success; # of objects read from file.
++ *  Requires:
++ *      KFILE initialized.
++ *      pBuffer is a valid pointer.
++ *  Ensures:
++ */
++      extern s32 KFILE_Read(OUT void __user*buffer,
++                            IN s32 size, IN s32 count,
++                            IN struct KFILE_FileObj *hFile);
++
++/*
++ *  ======== KFILE_Seek ========
++ *  Purpose:
++ *      This function sets the file position indicator.  NOTE:  we don't
++ *      support seeking beyond the boundaries of a file.
++ *  Parameters:
++ *      hFile:      Handle of the file stream returned by KFILE_Open.
++ *      offset:     Number of bytes from the origin to move.
++ *      origin:     File reference point, one of the following values:
++ *                  KFILE_SEEK_SET:  Seek from beginning of file.
++ *                  KFILE_SEEK_CUR:  Seek from current position.
++ *                  KFILE_SEEK_END:  Seek from end of file.
++ *  Returns:
++ *      0: success.
++ *      E_KFILE_INVALIDHANDLE:  bad handle.
++ *      E_KFILE_BADORIGIN:      invalid origin paramater.
++ *      E_KFILE_ERROR:          general failure.
++ *  Requires:
++ *      KFILE initialized.
++ *  Ensures:
++ */
++      extern s32 KFILE_Seek(IN struct KFILE_FileObj *hFile,
++                            IN s32 offset, IN s32 origin);
++
++/*
++ *  ======== KFILE_Tell ========
++ *  Purpose:
++ *      This function reports the current value of the position indicator.
++ *  Parameters:
++ *      hFile:          Handle of the file stream returned by KFILE_Open.
++ *  Return value:
++ *      > 0: success; returns # of bytes the position indicator is from
++ *           beginning of file.
++ *      E_KFILE_ERROR:          general failure.
++ *      E_KFILE_INVALIDHANDLE:  bad file handle.
++ *  Requires:
++ *      KFILE initialized.
++ *  Ensures:
++ */
++      extern s32 KFILE_Tell(IN struct KFILE_FileObj *hFile);
++
++/*
++ *  ======== KFILE_Write ========
++ *  Purpose:
++ *      This function writes a number of objects to the stream.
++ *  Parameters:
++ *      pBuffer:    Array from which the file data is written.
++ *      cSize:      Number of characters in each object.
++ *      cCount:     Number of objects to write out.
++ *      hFile:      Handle of the file stream returned by KFILE_Open.
++ *  Returns:
++ *      E_KFILE_INVALIDHANDLE:  bad file handle.
++ *      E_KFILE_ERROR:          general failure.
++ *      > 0:                    success; # of objects written to file.
++ *  Requires:
++ *      KFILE initialized.
++ *      pBuffer != NULL.
++ *  Postcondition:
++ *      The file position indicator is advanced by the number of
++ *      characters written.
++ */
++      extern s32 KFILE_Write(OUT void *buffer,
++                             IN s32 size,
++                             IN s32 count,
++                             IN struct KFILE_FileObj *hFile);
++
++#endif                                /* KFILE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/ldr.h b/arch/arm/plat-omap/include/dspbridge/ldr.h
+new file mode 100644
+index 0000000..7e13c93
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/ldr.h
+@@ -0,0 +1,51 @@
++/*
++ * ldr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== ldr.h ========
++ *  Purpose:
++ *      Provide module loading services and symbol export services.
++ *
++ *  Public Functions:
++ *      LDR_Exit
++ *      LDR_FreeModule
++ *      LDR_GetProcAddress
++ *      LDR_Init
++ *      LDR_LoadModule
++ *
++ *  Notes:
++ *      This service is meant to be used by modules of the DSP/BIOS Bridge
++ *       class driver.
++ *
++ *! Revision History:
++ *! ================
++ *! 22-Nov-1999 kc: Changes from code review.
++ *! 12-Nov-1999 kc: Removed declaration of unused loader object.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 12-Jan-1998 cr: Cleaned up for code review.
++ *! 04-Aug-1997 cr: Added explicit CDECL identifiers.
++ *! 11-Nov-1996 cr: Cleaned up for code review.
++ *! 16-May-1996 gp: Created.
++ */
++
++#ifndef LDR_
++#define LDR_
++
++/* Loader objects: */
++      struct LDR_MODULE;
++
++#endif                                /* LDR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/list.h b/arch/arm/plat-omap/include/dspbridge/list.h
+new file mode 100644
+index 0000000..2e3f995
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/list.h
+@@ -0,0 +1,296 @@
++/*
++ * list.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== list.h ========
++ *  Purpose:
++ *      Declarations of list management control structures and definitions
++ *      of inline list management functions.
++ *
++ *  Public Functions:
++ *      LST_Create
++ *      LST_Delete
++ *      LST_Exit
++ *      LST_First
++ *      LST_GetHead
++ *      LST_InitElem
++ *      LST_Init
++ *      LST_InsertBefore
++ *      LST_IsEmpty
++ *      LST_Next
++ *      LST_PutTail
++ *      LST_RemoveElem
++ *
++ *  Notes:
++ *
++ *! Revision History
++ *! ================
++ *! 10-Aug-2000 ag:  Added LST_InsertBefore().
++ *! 29-Oct-1999 kc:  Cleaned up for code review.
++ *! 16-Aug-1997 cr:  added explicit identifiers.
++ *! 10-Aug-1996 gp:  Acquired from SMM for WinSPOX v.1.1; renamed identifiers.
++ *! 21-Oct-1994 dh4: Cleaned / commented for code review.
++ *! 08-Jun-1994 dh4: Converted to SPM (added extern "C").
++ */
++
++#ifndef LIST_
++#define LIST_
++
++#include <dspbridge/host_os.h>
++
++#define LST_IsEmpty(l)      (((l)->head.next == &(l)->head))
++
++      struct LST_ELEM {
++              struct LST_ELEM *next;
++              struct LST_ELEM *prev;
++              struct LST_ELEM *self;
++      } ;
++
++      struct LST_LIST {
++              struct LST_ELEM head;
++      } ;
++
++/*
++ *  ======== LST_Create ========
++ *  Purpose:
++ *      Allocates and initializes a circular list.
++ *  Details:
++ *      Uses portable MEM_Calloc() function to allocate a list containing
++ *      a single element and initializes that element to indicate that it
++ *      is the "end of the list" (i.e., the list is empty).
++ *      An empty list is indicated by the "next" pointer in the element
++ *      at the head of the list pointing to the head of the list, itself.
++ *  Parameters:
++ *  Returns:
++ *      Pointer to beginning of created list (success)
++ *      NULL --> Allocation failed
++ *  Requires:
++ *      LST initialized.
++ *  Ensures:
++ *  Notes:
++ *      The created list contains a single element.  This element is the
++ *      "empty" element, because its "next" and "prev" pointers point at
++ *      the same location (the element itself).
++ */
++      extern struct LST_LIST *LST_Create(void);
++
++/*
++ *  ======== LST_Delete ========
++ *  Purpose:
++ *      Removes a list by freeing its control structure's memory space.
++ *  Details:
++ *      Uses portable MEM_Free() function to deallocate the memory
++ *      block pointed at by the input parameter.
++ *  Parameters:
++ *      pList:  Pointer to list control structure of list to be deleted
++ *  Returns:
++ *      Void
++ *  Requires:
++ *      - LST initialized.
++ *      - pList != NULL.
++ *  Ensures:
++ *  Notes:
++ *      Must ONLY be used for empty lists, because it does not walk the
++ *      chain of list elements.  Calling this function on a non-empty list
++ *      will cause a memory leak.
++ */
++      extern void LST_Delete(IN struct LST_LIST *pList);
++
++/*
++ *  ======== LST_Exit ========
++ *  Purpose:
++ *      Discontinue usage of module; free resources when reference count
++ *      reaches 0.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      LST initialized.
++ *  Ensures:
++ *      Resources used by module are freed when cRef reaches zero.
++ */
++      extern void LST_Exit(void);
++
++/*
++ *  ======== LST_First ========
++ *  Purpose:
++ *      Returns a pointer to the first element of the list, or NULL if the list
++ *      is empty.
++ *  Parameters:
++ *      pList:  Pointer to list control structure.
++ *  Returns:
++ *      Pointer to first list element, or NULL.
++ *  Requires:
++ *      - LST initialized.
++ *      - pList != NULL.
++ *  Ensures:
++ */
++      extern struct LST_ELEM *LST_First(IN struct LST_LIST *pList);
++
++/*
++ *  ======== LST_GetHead ========
++ *  Purpose:
++ *      Pops the head off the list and returns a pointer to it.
++ *  Details:
++ *      If the list is empty, returns NULL.
++ *      Else, removes the element at the head of the list, making the next
++ *      element the head of the list.
++ *      The head is removed by making the tail element of the list point its
++ *      "next" pointer at the next element after the head, and by making the
++ *      "prev" pointer of the next element after the head point at the tail
++ *      element.  So the next element after the head becomes the new head of
++ *      the list.
++ *  Parameters:
++ *      pList:  Pointer to list control structure of list whose head
++ *              element is to be removed
++ *  Returns:
++ *      Pointer to element that was at the head of the list (success)
++ *      NULL          No elements in list
++ *  Requires:
++ *      - head.self must be correctly set to &head.
++ *      - LST initialized.
++ *      - pList != NULL.
++ *  Ensures:
++ *  Notes:
++ *      Because the tail of the list points forward (its "next" pointer) to
++ *      the head of the list, and the head of the list points backward (its
++ *      "prev" pointer) to the tail of the list, this list is circular.
++ */
++      extern struct LST_ELEM *LST_GetHead(IN struct LST_LIST *pList);
++
++/*
++ *  ======== LST_Init ========
++ *  Purpose:
++ *      Initializes private state of LST module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialized; FALSE otherwise.
++ *  Requires:
++ *  Ensures:
++ *      LST initialized.
++ */
++      extern bool LST_Init(void);
++
++/*
++ *  ======== LST_InitElem ========
++ *  Purpose:
++ *      Initializes a list element to default (cleared) values
++ *  Details:
++ *  Parameters:
++ *      pElem:  Pointer to list element to be reset
++ *  Returns:
++ *  Requires:
++ *      LST initialized.
++ *  Ensures:
++ *  Notes:
++ *      This function must not be called to "reset" an element in the middle
++ *      of a list chain -- that would break the chain.
++ *
++ */
++      extern void LST_InitElem(IN struct LST_ELEM *pListElem);
++
++/*
++ *  ======== LST_InsertBefore ========
++ *  Purpose:
++ *     Insert the element before the existing element.
++ *  Parameters:
++ *      pList:          Pointer to list control structure.
++ *      pElem:          Pointer to element in list to insert.
++ *      pElemExisting:  Pointer to existing list element.
++ *  Returns:
++ *  Requires:
++ *      - LST initialized.
++ *      - pList != NULL.
++ *      - pElem != NULL.
++ *      - pElemExisting != NULL.
++ *  Ensures:
++ */
++      extern void LST_InsertBefore(IN struct LST_LIST *pList,
++                                   IN struct LST_ELEM *pElem,
++                                   IN struct LST_ELEM *pElemExisting);
++
++/*
++ *  ======== LST_Next ========
++ *  Purpose:
++ *      Returns a pointer to the next element of the list, or NULL if the next
++ *      element is the head of the list or the list is empty.
++ *  Parameters:
++ *      pList:      Pointer to list control structure.
++ *      pCurElem:   Pointer to element in list to remove.
++ *  Returns:
++ *      Pointer to list element, or NULL.
++ *  Requires:
++ *      - LST initialized.
++ *      - pList != NULL.
++ *      - pCurElem != NULL.
++ *  Ensures:
++ */
++      extern struct LST_ELEM *LST_Next(IN struct LST_LIST *pList,
++                                       IN struct LST_ELEM *pCurElem);
++
++/*
++ *  ======== LST_PutTail ========
++ *  Purpose:
++ *      Adds the specified element to the tail of the list
++ *  Details:
++ *      Sets new element's "prev" pointer to the address previously held by
++ *      the head element's prev pointer.  This is the previous tail member of
++ *      the list.
++ *      Sets the new head's prev pointer to the address of the element.
++ *      Sets next pointer of the previous tail member of the list to point to
++ *      the new element (rather than the head, which it had been pointing at).
++ *      Sets new element's next pointer to the address of the head element.
++ *      Sets head's prev pointer to the address of the new element.
++ *  Parameters:
++ *      pList:  Pointer to list control structure to which *pElem will be
++ *              added
++ *      pElem:  Pointer to list element to be added
++ *  Returns:
++ *      Void
++ *  Requires:
++ *      *pElem and *pList must both exist.
++ *      pElem->self = pElem before pElem is passed to this function.
++ *      LST initialized.
++ *  Ensures:
++ *  Notes:
++ *      Because the tail is always "just before" the head of the list (the
++ *      tail's "next" pointer points at the head of the list, and the head's
++ *      "prev" pointer points at the tail of the list), the list is circular.
++ *  Warning: if pElem->self is not set beforehand, LST_GetHead() will
++ *      return an erroneous pointer when it is called for this element.
++ */
++      extern void LST_PutTail(IN struct LST_LIST *pList,
++                              IN struct LST_ELEM *pListElem);
++
++/*
++ *  ======== LST_RemoveElem ========
++ *  Purpose:
++ *      Removes (unlinks) the given element from the list, if the list is not
++ *      empty.  Does not free the list element.
++ *  Parameters:
++ *      pList:      Pointer to list control structure.
++ *      pCurElem:   Pointer to element in list to remove.
++ *  Returns:
++ *  Requires:
++ *      - LST initialized.
++ *      - pList != NULL.
++ *      - pCurElem != NULL.
++ *  Ensures:
++ */
++extern void LST_RemoveElem(IN struct LST_LIST *pList,
++                         IN struct LST_ELEM *pCurElem);
++
++#endif                                /* LIST_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mbx_sh.h b/arch/arm/plat-omap/include/dspbridge/mbx_sh.h
+new file mode 100644
+index 0000000..be0909e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mbx_sh.h
+@@ -0,0 +1,213 @@
++/*
++ * mbx_sh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== mbx_sh.h ========
++ *  Definitions for shared mailbox cmd/data values.(used on both
++ *     the GPP and DSP sides).
++ *
++ *  Bridge usage of OMAP mailbox 1 is determined by the "class" of the
++ *     mailbox interrupt's cmd value received. The class value are defined
++ *     as a bit (10 thru 15) being set.
++ *
++ *  Note: Only 16 bits of each  is used. Other 16 bit data reg available.
++ *
++ *   16 bit Mbx bit defns:
++ *
++ * A). Exception/Error handling (Module DEH) : class = 0.
++ *
++ *    15         10                  0
++ *   ---------------------------------
++ *   |0|0|0|0|0|0|x|x|x|x|x|x|x|x|x|x|
++ *   ---------------------------------
++ *   |  (class)  | (module specific) |
++ *
++ *
++ *
++ * B: DSP-DMA link driver channels (DDMA) : class = 1.
++ *
++ *    15         10                  0
++ *   ---------------------------------
++ *   |0|0|0|0|0|1|b|b|b|b|b|c|c|c|c|c|
++ *   ---------------------------------
++ *   |  (class)  | (module specific) |
++ *
++ *   where b -> buffer index  (32 DDMA buffers/chnl max)
++ *         c -> channel Id    (32 DDMA chnls max)
++ *
++ *
++ *
++ *
++ * C: Proc-copy link driver channels (PCPY) : class = 2.
++ *
++ *    15         10                  0
++ *   ---------------------------------
++ *   |0|0|0|0|1|0|x|x|x|x|x|x|x|x|x|x|
++ *   ---------------------------------
++ *   |  (class)  | (module specific) |
++ *
++ *
++ * D: Zero-copy link driver channels (DDZC) : class = 4.
++ *
++ *    15         10                  0
++ *   ---------------------------------
++ *   |0|0|0|1|0|0|x|x|x|x|x|c|c|c|c|c|
++ *   ---------------------------------
++ *   |  (class)  | (module specific) |
++ *
++ *   where x -> not used
++ *         c -> channel Id    (32 ZCPY chnls max)
++ *
++ *
++ * E: Power management : class = 8.
++ *
++ *    15         10                  0
++ *   ---------------------------------
++ *   |0|0|1|0|0|0|x|x|x|x|x|c|c|c|c|c|
++
++ *    0010 00xx xxxc cccc
++ *    0010 00nn pppp qqqq
++ *    nn:
++ *    00 = reserved
++ *    01 = pwr state change
++ *    10 = opp pre-change
++ *    11 = opp post-change
++ *
++ *    if nn = pwr state change:
++ *    pppp = don't care
++ *    qqqq:
++ *    0010 = hibernate
++ *    0010 0001 0000 0010
++ *    0110 = retention
++ *    0010 0001 0000 0110
++ *    others reserved
++ *
++ *    if nn = opp pre-change:
++ *    pppp = current opp
++ *    qqqq = next opp
++ *
++ *    if nn = opp post-change:
++ *    pppp = prev opp
++ *    qqqq = current opp
++ *
++ *   ---------------------------------
++ *   |  (class)  | (module specific) |
++ *
++ *   where x -> not used
++ *         c -> Power management command
++ *
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Sep-2002 mr  Added DEH reset const
++ *! 24-Apr-2002 sg  Added more PM commands.
++ *! 04-Mar-2002 gv  Added MBX_PM_CLASS
++ *! 22-Jan-2002 ag  Bug fix in MBX_SETZCPYVAL(x) macro.
++ *! 21-Dec-2001 ag  Added bit masks defns.
++ *! 17-Dec-2001 ag: created.
++ */
++
++#ifndef _MBX_SH_H
++#define _MBX_SH_H
++
++#define MBX_CLASS_MSK      0xFC00     /* Class bits are 10 thru 15 */
++#define MBX_VALUE_MSK      0x03FF     /* Value is 0 thru 9 */
++
++#define MBX_DEH_CLASS      0x0000     /* DEH owns Mbx INTR */
++#define MBX_DDMA_CLASS     0x0400     /* DSP-DMA link drvr chnls owns INTR */
++#define MBX_PCPY_CLASS     0x0800     /* PROC-COPY  " */
++#define MBX_ZCPY_CLASS     0x1000     /* ZERO-COPY  " */
++#define MBX_PM_CLASS       0x2000     /* Power Management */
++#define MBX_DBG_CLASS      0x4000     /* For debugging purpose */
++
++/*
++ * Exception Handler codes
++ * Magic code used to determine if DSP signaled exception.
++ */
++#define MBX_DEH_BASE        0x0
++#define MBX_DEH_USERS_BASE  0x100     /* 256 */
++#define MBX_DEH_LIMIT       0x3FF     /* 1023 */
++#define MBX_DEH_RESET       0x101     /* DSP RESET (DEH) */
++#define MBX_DEH_EMMU        0X103 /*DSP MMU FAULT RECOVERY*/
++
++/*
++ *  Link driver command/status codes.
++ */
++/* DSP-DMA */
++#define MBX_DDMA_NUMCHNLBITS 5        /* # chnl Id: # bits available */
++#define MBX_DDMA_CHNLSHIFT   0        /* # of bits to shift */
++#define MBX_DDMA_CHNLMSK     0x01F    /* bits 0 thru 4 */
++
++#define MBX_DDMA_NUMBUFBITS  5        /* buffer index: # of bits avail */
++#define MBX_DDMA_BUFSHIFT    (MBX_DDMA_NUMCHNLBITS + MBX_DDMA_CHNLSHIFT)
++#define MBX_DDMA_BUFMSK      0x3E0    /* bits 5 thru 9 */
++
++/* Zero-Copy */
++#define MBX_ZCPY_NUMCHNLBITS 5        /* # chnl Id: # bits available */
++#define MBX_ZCPY_CHNLSHIFT   0        /* # of bits to shift */
++#define MBX_ZCPY_CHNLMSK     0x01F    /* bits 0 thru 4 */
++
++/*  Power Management Commands */
++#define MBX_PM_DSPIDLE                  (MBX_PM_CLASS + 0x0)
++#define MBX_PM_DSPWAKEUP                (MBX_PM_CLASS + 0x1)
++#define MBX_PM_EMERGENCYSLEEP           (MBX_PM_CLASS + 0x2)
++#define MBX_PM_SLEEPUNTILRESTART        (MBX_PM_CLASS + 0x3)
++#define MBX_PM_DSPGLOBALIDLE_OFF        (MBX_PM_CLASS + 0x4)
++#define MBX_PM_DSPGLOBALIDLE_ON         (MBX_PM_CLASS + 0x5)
++#define MBX_PM_SETPOINT_PRENOTIFY       (MBX_PM_CLASS + 0x6)
++#define MBX_PM_SETPOINT_POSTNOTIFY      (MBX_PM_CLASS + 0x7)
++#define MBX_PM_DSPRETN                  (MBX_PM_CLASS + 0x8)
++#define MBX_PM_DSPRETENTION        (MBX_PM_CLASS + 0x8)
++#define MBX_PM_DSPHIBERNATE        (MBX_PM_CLASS + 0x9)
++#define MBX_PM_HIBERNATE_EN        (MBX_PM_CLASS + 0xA)
++#define MBX_PM_OPP_REQ                  (MBX_PM_CLASS + 0xB)
++#define MBX_PM_OPP_CHG                  (MBX_PM_CLASS + 0xC)
++
++#define MBX_PM_TYPE_MASK 0x0300
++#define MBX_PM_TYPE_PWR_CHNG 0x0100
++#define MBX_PM_TYPE_OPP_PRECHNG 0x0200
++#define MBX_PM_TYPE_OPP_POSTCHNG 0x0300
++#define MBX_PM_TYPE_OPP_MASK 0x0300
++#define MBX_PM_OPP_PRECHNG (MBX_PM_CLASS | MBX_PM_TYPE_OPP_PRECHNG)
++/* DSP to MPU */
++#define MBX_PM_OPP_CHNG(OPP) (MBX_PM_CLASS | MBX_PM_TYPE_OPP_PRECHNG | (OPP))
++#define MBX_PM_RET (MBX_PM_CLASS | MBX_PM_TYPE_PWR_CHNG | 0x0006)
++#define MBX_PM_HIB (MBX_PM_CLASS | MBX_PM_TYPE_PWR_CHNG | 0x0002)
++#define MBX_PM_OPP_1 0
++#define MBX_PM_OPP_2 1
++#define MBX_PM_OPP_3 2
++#define MBX_PM_OPP_4 3
++#define MBX_OLDOPP_EXTRACT(OPPMSG) ((0x00F0 & (OPPMSG)) >> 4)
++#define MBX_NEWOPP_EXTRACT(OPPMSG) (0x000F & (OPPMSG))
++#define MBX_PREVOPP_EXTRACT(OPPMSG) ((0x00F0 & (OPPMSG)) >> 4)
++#define MBX_CUROPP_EXTRACT(OPPMSG) (0x000F & (OPPMSG))
++
++/* Bridge Debug Commands */
++#define MBX_DBG_SYSPRINTF       (MBX_DBG_CLASS + 0x0)
++
++/*
++ * Useful macros
++ */
++/* DSP-DMA channel */
++#define MBX_SETDDMAVAL(x, y)  (MBX_DDMA_CLASS | (x << MBX_DDMA_BUFSHIFT) | \
++      (y << MBX_DDMA_CHNLSHIFT))
++
++/* Zero-Copy channel */
++#define MBX_SETZCPYVAL(x)  (MBX_ZCPY_CLASS | (x << MBX_ZCPY_CHNLSHIFT))
++
++#endif                                /* _MBX_SH_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mem.h b/arch/arm/plat-omap/include/dspbridge/mem.h
+new file mode 100644
+index 0000000..535ac3a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mem.h
+@@ -0,0 +1,340 @@
++/*
++ * mem.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== mem.h ========
++ *  Purpose:
++ *      Memory management and address mapping services for the DSP/BIOS Bridge
++ *      class driver and mini-driver.
++ *
++ *  Public Functions:
++ *      MEM_Alloc
++ *      MEM_AllocObject
++ *      MEM_AllocPhysMem
++ *      MEM_Calloc
++ *      MEM_Exit
++ *      MEM_FlushCache
++ *      MEM_Free
++ *      MEM_FreeObject
++ *      MEM_FreePhysMem
++ *      MEM_GetNumPages
++ *      MEM_Init
++ *      MEM_IsValidHandle
++ *      MEM_LinearAddress
++ *      MEM_PageLock
++ *      MEM_PageUnlock
++ *      MEM_UnMapLinearAddress
++ *      MEM_VirtualToPhysical
++ *
++ *  Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb: Added Alloc/Free PhysMem, FlushCache, VirtualToPhysical
++ *! 01-Sep-2001 ag: Cleaned up notes for MEM_LinearAddress() does not
++ *!                   require phys address to be page aligned!
++ *! 02-Dec-1999 rr: stdwin.h included for retail build
++ *! 12-Nov-1999 kc: Added warning about use of MEM_LinearAddress.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 10-Aug-1999 kc: Based on wsx-c18.
++ *! 07-Jan-1998 gp: Added MEM_AllocUMB and MEM_UMBFree for User Mapped Buffers
++ *!                 used by WMD_CHNL.
++ *! 23-Dec-1997 cr: Code review cleanup, removed dead Ring 3 code.
++ *! 04-Aug-1997 cr: Added explicit CDECL identifiers.
++ *! 01-Nov-1996 gp: Updated based on code review.
++ *! 04-Sep-1996 gp: Added MEM_PageLock() and MEM_PageUnlock() services.
++ *! 14-Aug-1996 mg: Added MEM_GetPhysAddr() and MEM_GetNumPages()
++ *! 25-Jul-1996 gp: Added MEM_IsValidHandle() macro.
++ *! 10-May-1996 gp: Added MEM_Calloc().
++ *! 25-Apr-1996 gp: Added MEM_PhysicalAddress()
++ *! 17-Apr-1996 gp: Added MEM_Exit function; updated to latest naming standard.
++ *! 08-Apr-1996 gp: Created.
++ */
++
++#ifndef MEM_
++#define MEM_
++
++#include <dspbridge/host_os.h>
++#include <dspbridge/memdefs.h>
++
++/*
++ *  ======== MEM_Alloc ========
++ *  Purpose:
++ *      Allocate memory from the paged or non-paged pools.
++ *  Parameters:
++ *      cBytes: Number of bytes to allocate.
++ *      type:   Type of memory to allocate; one of:
++ *              MEM_PAGED: Allocate from pageable memory.
++ *              MEM_NONPAGED: Allocate from page locked memory.
++ *  Returns:
++ *      Pointer to a block of memory;
++ *      NULL if memory couldn't be allocated, if cBytes == 0, or if type is
++ *      not one of MEM_PAGED or MEM_NONPAGED.
++ *  Requires:
++ *      MEM initialized.
++ *  Ensures:
++ *      The returned pointer, if not NULL, points to a valid memory block of
++ *      the size requested.
++ */
++      extern void *MEM_Alloc(IN u32 cBytes, IN enum MEM_POOLATTRS type);
++
++/*
++ *  ======== MEM_AllocObject ========
++ *  Purpose:
++ *      Allocate an object, and set it's signature.
++ *  Parameters:
++ *      pObj:       Pointer to the new object.
++ *      Obj:        Type of the object to allocate.
++ *      Signature:  Magic field value.  Must be non-zero.
++ *  Returns:
++ *  Requires:
++ *      Same requirements as MEM_Calloc(); and
++ *      The object structure has a dwSignature field.  The compiler ensures
++ *      this requirement.
++ *  Ensures:
++ *      A subsequent call to MEM_IsValidHandle() will succeed for this object.
++ */
++#define MEM_AllocObject(pObj, Obj, Signature)           \
++{                                                       \
++    pObj = MEM_Calloc(sizeof(Obj), MEM_NONPAGED);       \
++    if (pObj) {                                         \
++      pObj->dwSignature = Signature;                  \
++    }                                                   \
++}
++
++/*  ======== MEM_AllocPhysMem ========
++ *  Purpose:
++ *      Allocate physically contiguous, uncached memory
++ *  Parameters:
++ *      cBytes:     Number of bytes to allocate.
++ *      ulAlign:    Alignment Mask.
++ *      pPhysicalAddress: Physical address of allocated memory.
++ *  Returns:
++ *      Pointer to a block of memory;
++ *      NULL if memory couldn't be allocated, or if cBytes == 0.
++ *  Requires:
++ *      MEM initialized.
++ *  Ensures:
++ *      The returned pointer, if not NULL, points to a valid memory block of
++ *      the size requested.  Returned physical address refers to physical
++ *      location of memory.
++ */
++      extern void *MEM_AllocPhysMem(IN u32 cBytes,
++                                    IN u32 ulAlign,
++                                    OUT u32 *pPhysicalAddress);
++
++/*
++ *  ======== MEM_Calloc ========
++ *  Purpose:
++ *      Allocate zero-initialized memory from the paged or non-paged pools.
++ *  Parameters:
++ *      cBytes: Number of bytes to allocate.
++ *      type:   Type of memory to allocate; one of:
++ *              MEM_PAGED:   Allocate from pageable memory.
++ *              MEM_NONPAGED: Allocate from page locked memory.
++ *  Returns:
++ *      Pointer to a block of zeroed memory;
++ *      NULL if memory couldn't be allocated, if cBytes == 0, or if type is
++ *      not one of MEM_PAGED or MEM_NONPAGED.
++ *  Requires:
++ *      MEM initialized.
++ *  Ensures:
++ *      The returned pointer, if not NULL, points to a valid memory block
++ *      of the size requested.
++ */
++      extern void *MEM_Calloc(IN u32 cBytes, IN enum MEM_POOLATTRS type);
++
++/*
++ *  ======== MEM_Exit ========
++ *  Purpose:
++ *      Discontinue usage of module; free resources when reference count
++ *      reaches 0.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      MEM is initialized.
++ *  Ensures:
++ *      Resources used by module are freed when cRef reaches zero.
++ */
++      extern void MEM_Exit(void);
++
++/*
++ *  ======== MEM_FlushCache ========
++ *  Purpose:
++ *      Performs system cache sync with discard
++ *  Parameters:
++ *      pMemBuf:    Pointer to memory region to be flushed.
++ *      pMemBuf:    Size of the memory region to be flushed.
++ *  Returns:
++ *  Requires:
++ *      MEM is initialized.
++ *  Ensures:
++ *      Cache is synchronized
++ */
++      extern void MEM_FlushCache(void *pMemBuf, u32 cBytes, s32 FlushType);
++
++/*
++ *  ======== MEM_Free ========
++ *  Purpose:
++ *      Free the given block of system memory.
++ *  Parameters:
++ *      pMemBuf:    Pointer to memory allocated by MEM_Calloc/Alloc().
++ *  Returns:
++ *  Requires:
++ *      MEM initialized.
++ *      pMemBuf is a valid memory address returned by MEM_Calloc/Alloc().
++ *  Ensures:
++ *      pMemBuf is no longer a valid pointer to memory.
++ */
++      extern void MEM_Free(IN void *pMemBuf);
++
++/*
++ *  ======== MEM_FreePhysMem ========
++ *  Purpose:
++ *      Free the given block of physically contiguous memory.
++ *  Parameters:
++ *      pVirtualAddress:  Pointer to virtual memory region allocated
++ *      by MEM_AllocPhysMem().
++ *      pPhysicalAddress:  Pointer to physical memory region  allocated
++ *      by MEM_AllocPhysMem().
++ *      cBytes:  Size of the memory region allocated by MEM_AllocPhysMem().
++ *  Returns:
++ *  Requires:
++ *      MEM initialized.
++ *      pVirtualAddress is a valid memory address returned by
++ *          MEM_AllocPhysMem()
++ *  Ensures:
++ *      pVirtualAddress is no longer a valid pointer to memory.
++ */
++      extern void MEM_FreePhysMem(void *pVirtualAddress,
++                                  u32 pPhysicalAddress, u32 cBytes);
++
++/*
++ *  ======== MEM_FreeObject ========
++ *  Purpose:
++ *      Utility macro to invalidate an object's signature, and deallocate it.
++ *  Parameters:
++ *      pObj:   Pointer to the object to free.
++ *  Returns:
++ *  Requires:
++ *      Same requirements as MEM_Free().
++ *  Ensures:
++ *      A subsequent call to MEM_IsValidHandle() will fail for this object.
++ */
++#define MEM_FreeObject(pObj)    \
++{                               \
++    pObj->dwSignature = 0x00;   \
++    MEM_Free(pObj);             \
++}
++
++/*
++ *  ======== MEM_GetNumPages ========
++ *  Purpose:
++ *      Calculate the number of pages corresponding to the supplied buffer.
++ *  Parameters:
++ *      pAddr:  Linear (virtual) address of the buffer.
++ *      cBytes: Number of bytes in the buffer.
++ *  Returns:
++ *      Number of pages.
++ *  Requires:
++ *      MEM initialized.
++ *  Ensures:
++ *      If cBytes > 0, number of pages returned > 0.
++ */
++      extern s32 MEM_GetNumPages(IN void *pAddr, IN u32 cBytes);
++
++/*
++ *  ======== MEM_Init ========
++ *  Purpose:
++ *      Initializes private state of MEM module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialized; FALSE if error occured.
++ *  Requires:
++ *  Ensures:
++ *      MEM initialized.
++ */
++      extern bool MEM_Init(void);
++
++/*
++ *  ======== MEM_IsValidHandle ========
++ *  Purpose:
++ *      Validate the object handle.
++ *  Parameters:
++ *      hObj:   Handle to object created with MEM_AllocObject().
++ *      Sig:    Expected signature u32.
++ *  Returns:
++ *      TRUE if handle is valid; FALSE otherwise.
++ *  Requires:
++ *      The object structure has a dwSignature field. Ensured by compiler.
++ *  Ensures:
++ */
++#define MEM_IsValidHandle(hObj, Sig)                \
++     ((hObj != NULL) && (hObj->dwSignature == Sig))
++
++/*
++ *  ======== MEM_LinearAddress ========
++ *  Purpose:
++ *      Get the linear address corresponding to the given physical address.
++ *  Parameters:
++ *      pPhysAddr:  Physical address to be mapped.
++ *      cBytes:     Number of bytes in physical range to map.
++ *  Returns:
++ *      The corresponding linear address, or NULL if unsuccessful.
++ *  Requires:
++ *      MEM initialized.
++ *  Ensures:
++ *  Notes:
++ *      If valid linear address is returned, be sure to call
++ *      MEM_UnmapLinearAddress().
++ */
++#define MEM_LinearAddress(pPhyAddr, cBytes) pPhyAddr
++
++/*
++ *  ======== MEM_UnmapLinearAddress ========
++ *  Purpose:
++ *      Unmap the linear address mapped in MEM_LinearAddress.
++ *  Parameters:
++ *      pBaseAddr: Ptr to mapped memory (as returned by MEM_LinearAddress()).
++ *  Returns:
++ *  Requires:
++ *      - MEM initialized.
++ *      - pBaseAddr is a valid linear address mapped in MEM_LinearAddress.
++ *  Ensures:
++ *      - pBaseAddr no longer points to a valid linear address.
++ */
++#define MEM_UnmapLinearAddress(pBaseAddr)
++
++/*
++ *  ======== MEM_ExtPhysPoolInit ========
++ *  Purpose:
++ *      Uses the physical memory chunk passed for internal consitent memory
++ *      allocations.
++ *      physical address based on the page frame address.
++ *  Parameters:
++ *      poolPhysBase  starting address of the physical memory pool.
++ *      poolSize      size of the physical memory pool.
++ *  Returns:
++ *      none.
++ *  Requires:
++ *      - MEM initialized.
++ *      - valid physical address for the base and size > 0
++ */
++      extern void MEM_ExtPhysPoolInit(IN u32 poolPhysBase,
++                                      IN u32 poolSize);
++
++#endif                                /* MEM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/memdefs.h b/arch/arm/plat-omap/include/dspbridge/memdefs.h
+new file mode 100644
+index 0000000..a5bb259
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/memdefs.h
+@@ -0,0 +1,52 @@
++/*
++ * memdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== memdefs.h ========
++ *  Purpose:
++ *      Global MEM constants and types, shared between WSX, WCD, and WMD.
++ *
++ *! Revision History:
++ *! ================
++ *! 28-Aug-2001 ag:  Added MEM_[SET][GET]VIRTUALSEGID.
++ *! 10-Aug-1999 kc:  Based on wsx-c18.
++ *! 15-Nov-1996 gp:  Renamed from wsxmem.h and moved to kwinos.
++ *! 21-Aug-1996 cr:  Created from mem.h.
++ */
++
++#ifndef MEMDEFS_
++#define MEMDEFS_
++
++/* Memory Pool Attributes: */
++      enum MEM_POOLATTRS {
++              MEM_PAGED = 0,
++              MEM_NONPAGED = 1,
++              MEM_LARGEVIRTMEM = 2
++      } ;
++
++/*
++ *  MEM_VIRTUALSEGID is used by Node & Strm to access virtual address space in
++ *  the correct client process context.
++ */
++#define MEM_SETVIRTUALSEGID     0x10000000
++#define MEM_GETVIRTUALSEGID     0x20000000
++#define MEM_MASKVIRTUALSEGID    (MEM_SETVIRTUALSEGID | MEM_GETVIRTUALSEGID)
++
++#define TO_VIRTUAL_UNCACHED(x) x
++#define INTREG_TO_VIRTUAL_UNCACHED(x) x
++
++#endif                                /* MEMDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mgr.h b/arch/arm/plat-omap/include/dspbridge/mgr.h
+new file mode 100644
+index 0000000..24c4472
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mgr.h
+@@ -0,0 +1,234 @@
++/*
++ * mgr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== mgr.h ========
++ *  Description:
++ *      This is the Class driver RM module interface.
++ *
++ *  Public Functions:
++ *      MGR_Create
++ *      MGR_Destroy
++ *      MGR_EnumNodeInfo
++ *      MGR_EnumProcessorInfo
++ *      MGR_Exit
++ *      MGR_GetDCDHandle
++ *      MGR_Init
++ *
++ *  Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 15-Oct-2002 kc: Removed legacy PERF definitions.
++ *! 11-Jul-2001 jeh Added CFG_HDEVNODE parameter to MGR_Create().
++ *! 22-Nov-2000 kc: Added MGR_GetPerfData for acquiring PERF stats.
++ *! 03-Nov-2000 rr: Added MGR_GetDCDHandle. Modified after code review.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 14-Aug-2000 rr: Cleaned up.
++ *! 07-Aug-2000 rr: MGR_Create does the job of Loading DCD Dll.
++ *! 27-Jul-2000 rr: Updated to ver 0.8 of DSPAPI(types).
++ *! 20-Jun-2000 rr: Created.
++ */
++
++#ifndef MGR_
++#define MGR_
++
++#include <dspbridge/mgrpriv.h>
++
++#define MAX_EVENTS 32
++
++/*
++ *  ======== MGR_WaitForBridgeEvents ========
++ *  Purpose:
++ *      Block on any Bridge event(s)
++ *  Parameters:
++ *      aNotifications  : array of pointers to notification objects.
++ *      uCount          : number of elements in above array
++ *      puIndex         : index of signaled event object
++ *      uTimeout        : timeout interval in milliseocnds
++ *  Returns:
++ *      DSP_SOK         : Success.
++ *      DSP_ETIMEOUT    : Wait timed out. *puIndex is undetermined.
++ *  Details:
++ */
++
++      DSP_STATUS MGR_WaitForBridgeEvents(struct DSP_NOTIFICATION
++                                         **aNotifications,
++                                         u32 uCount, OUT u32 *puIndex,
++                                         u32 uTimeout);
++
++/*
++ *  ======== MGR_Create ========
++ *  Purpose:
++ *      Creates the Manager Object. This is done during the driver loading.
++ *      There is only one Manager Object in the DSP/BIOS Bridge.
++ *  Parameters:
++ *      phMgrObject:    Location to store created MGR Object handle.
++ *      hDevNode:       Device object as known to Windows system.
++ *  Returns:
++ *      DSP_SOK:        Success
++ *      DSP_EMEMORY:    Failed to Create the Object
++ *      DSP_EFAIL:      General Failure
++ *  Requires:
++ *      MGR Initialized (cRefs > 0 )
++ *      phMgrObject != NULL.
++ *  Ensures:
++ *      DSP_SOK:        *phMgrObject is a valid MGR interface to the device.
++ *                      MGR Object stores the DCD Manager Handle.
++ *                      MGR Object stored in the Regsitry.
++ *      !DSP_SOK:       MGR Object not created
++ *  Details:
++ *      DCD Dll is loaded and MGR Object stores the handle of the DLL.
++ */
++      extern DSP_STATUS MGR_Create(OUT struct MGR_OBJECT **hMgrObject,
++                                   struct CFG_DEVNODE *hDevNode);
++
++/*
++ *  ======== MGR_Destroy ========
++ *  Purpose:
++ *      Destroys the MGR object. Called upon driver unloading.
++ *  Parameters:
++ *      hMgrObject:     Handle to Manager object .
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *                      DCD Manager freed; MGR Object destroyed;
++ *                      MGR Object deleted from the Registry.
++ *      DSP_EFAIL:      Failed to destroy MGR Object
++ *  Requires:
++ *      MGR Initialized (cRefs > 0 )
++ *      hMgrObject is a valid MGR handle .
++ *  Ensures:
++ *      DSP_SOK:        MGR Object destroyed and hMgrObject is Invalid MGR
++ *                      Handle.
++ */
++      extern DSP_STATUS MGR_Destroy(struct MGR_OBJECT *hMgrObject);
++
++/*
++ *  ======== MGR_EnumNodeInfo ========
++ *  Purpose:
++ *      Enumerate and get configuration information about nodes configured
++ *      in the node database.
++ *  Parameters:
++ *      uNode:              The node index (base 0).
++ *      pNDBProps:          Ptr to the DSP_NDBPROPS structure for output.
++ *      uNDBPropsSize:      Size of the DSP_NDBPROPS structure.
++ *      puNumNodes:         Location where the number of nodes configured
++ *                          in the database will be returned.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EINVALIDARG:    Parameter uNode is > than the number of nodes.
++ *                          configutred in the system
++ *      DSP_ECHANGEDURINGENUM:  During Enumeration there has been a change in
++ *                              the number of nodes configured or in the
++ *                              the properties of the enumerated nodes.
++ *      DSP_EFAIL:          Failed to querry the Node Data Base
++ *  Requires:
++ *      pNDBPROPS is not null
++ *      uNDBPropsSize >= sizeof(DSP_NDBPROPS)
++ *      puNumNodes is not null
++ *      MGR Initialized (cRefs > 0 )
++ *  Ensures:
++ *      SUCCESS on successful retreival of data and *puNumNodes > 0 OR
++ *      DSP_FAILED  && *puNumNodes == 0.
++ *  Details:
++ */
++      extern DSP_STATUS MGR_EnumNodeInfo(u32 uNode,
++                                         OUT struct DSP_NDBPROPS *pNDBProps,
++                                         u32 uNDBPropsSize,
++                                         OUT u32 *puNumNodes);
++
++/*
++ *  ======== MGR_EnumProcessorInfo ========
++ *  Purpose:
++ *      Enumerate and get configuration information about available DSP
++ *      processors
++ *  Parameters:
++ *      uProcessor:         The processor index (zero-based).
++ *      pProcessorInfo:     Ptr to the DSP_PROCESSORINFO structure .
++ *      uProcessorInfoSize: Size of DSP_PROCESSORINFO structure.
++ *      puNumProcs:         Location where the number of DSPs configured
++ *                          in the database will be returned
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EINVALIDARG:    Parameter uProcessor is > than the number of
++ *                          DSP Processors in the system.
++ *      DSP_EFAIL:          Failed to querry the Node Data Base
++ *  Requires:
++ *      pProcessorInfo is not null
++ *      puNumProcs is not null
++ *      uProcessorInfoSize >= sizeof(DSP_PROCESSORINFO)
++ *      MGR Initialized (cRefs > 0 )
++ *  Ensures:
++ *      SUCCESS on successful retreival of data and *puNumProcs > 0 OR
++ *      DSP_FAILED && *puNumProcs == 0.
++ *  Details:
++ */
++      extern DSP_STATUS MGR_EnumProcessorInfo(u32 uProcessor,
++                                              OUT struct DSP_PROCESSORINFO *
++                                              pProcessorInfo,
++                                              u32 uProcessorInfoSize,
++                                              OUT u32 *puNumProcs);
++/*
++ *  ======== MGR_Exit ========
++ *  Purpose:
++ *      Decrement reference count, and free resources when reference count is
++ *      0.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      MGR is initialized.
++ *  Ensures:
++ *      When reference count == 0, MGR's private resources are freed.
++ */
++       extern void MGR_Exit(void);
++
++/*
++ *  ======== MGR_GetDCDHandle ========
++ *  Purpose:
++ *      Retrieves the MGR handle. Accessor Function
++ *  Parameters:
++ *      hMGRHandle:     Handle to the Manager Object
++ *      phDCDHandle:    Ptr to receive the DCD Handle.
++ *  Returns:
++ *      DSP_SOK:        Sucess
++ *      DSP_EFAIL:      Failure to get the Handle
++ *  Requires:
++ *      MGR is initialized.
++ *      phDCDHandle != NULL
++ *  Ensures:
++ *      DSP_SOK and *phDCDHandle != NULL ||
++ *      DSP_EFAIL and *phDCDHandle == NULL
++ */
++       extern DSP_STATUS MGR_GetDCDHandle(IN struct MGR_OBJECT
++                                               *hMGRHandle,
++                                               OUT u32 *phDCDHandle);
++
++/*
++ *  ======== MGR_Init ========
++ *  Purpose:
++ *      Initialize MGR's private state, keeping a reference count on each
++ *      call. Intializes the DCD.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialized; FALSE if error occured.
++ *  Requires:
++ *  Ensures:
++ *      TRUE: A requirement for the other public MGR functions.
++ */
++       extern bool MGR_Init(void);
++
++#endif                                /* MGR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mgrpriv.h b/arch/arm/plat-omap/include/dspbridge/mgrpriv.h
+new file mode 100644
+index 0000000..4a34086
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mgrpriv.h
+@@ -0,0 +1,55 @@
++/*
++ * mgrpriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== mgrpriv.h ========
++ *  Description:
++ *      Global MGR constants and types, shared by PROC, MGR, and WCD.
++ *
++ *! Revision History:
++ *! ================
++ *! 29-July-2001 ag: added MGR_PROCESSOREXTINFO.
++ *! 05-July-2000 rr: Created
++ */
++
++#ifndef MGRPRIV_
++#define MGRPRIV_
++
++/*
++ * OMAP1510 specific
++ */
++#define MGR_MAXTLBENTRIES  32
++
++/* RM MGR Object */
++      struct MGR_OBJECT;
++
++      struct MGR_TLBENTRY {
++              u32 ulDspVirt;  /* DSP virtual address */
++              u32 ulGppPhys;  /* GPP physical address */
++      } ;
++
++/*
++ *  The DSP_PROCESSOREXTINFO structure describes additional extended
++ *  capabilities of a DSP processor not exposed to user.
++ */
++      struct MGR_PROCESSOREXTINFO {
++              struct DSP_PROCESSORINFO tyBasic;    /* user processor info */
++              /* private dsp mmu entries */
++              struct MGR_TLBENTRY tyTlb[MGR_MAXTLBENTRIES];
++      } ;
++
++#endif                                /* MGRPRIV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/msg.h b/arch/arm/plat-omap/include/dspbridge/msg.h
+new file mode 100644
+index 0000000..f2872cc
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/msg.h
+@@ -0,0 +1,106 @@
++/*
++ * msg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== msg.h ========
++ *  Description:
++ *      DSP/BIOS Bridge MSG Module.
++ *
++ *  Public Functions:
++ *      MSG_Create
++ *      MSG_Delete
++ *      MSG_Exit
++ *      MSG_Init
++ *
++ *  Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 17-Nov-2000 jeh     Removed MSG_Get, MSG_Put, MSG_CreateQueue,
++ *!                     MSG_DeleteQueue, and MSG_RegisterNotify, since these
++ *!                     are now part of mini-driver.
++ *! 12-Sep-2000 jeh     Created.
++ */
++
++#ifndef MSG_
++#define MSG_
++
++#include <dspbridge/devdefs.h>
++#include <dspbridge/msgdefs.h>
++
++/*
++ *  ======== MSG_Create ========
++ *  Purpose:
++ *      Create an object to manage message queues. Only one of these objects
++ *      can exist per device object. The MSG manager must be created before
++ *      the IO Manager.
++ *  Parameters:
++ *      phMsgMgr:           Location to store MSG manager handle on output.
++ *      hDevObject:         The device object.
++ *      msgCallback:        Called whenever an RMS_EXIT message is received.
++ *  Returns:
++ *  Requires:
++ *      MSG_Init(void) called.
++ *      phMsgMgr != NULL.
++ *      hDevObject != NULL.
++ *      msgCallback != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++                                   struct DEV_OBJECT *hDevObject,
++                                   MSG_ONEXIT msgCallback);
++
++/*
++ *  ======== MSG_Delete ========
++ *  Purpose:
++ *      Delete a MSG manager allocated in MSG_Create().
++ *  Parameters:
++ *      hMsgMgr:            Handle returned from MSG_Create().
++ *  Returns:
++ *  Requires:
++ *      MSG_Init(void) called.
++ *      Valid hMsgMgr.
++ *  Ensures:
++ */
++      extern void MSG_Delete(struct MSG_MGR *hMsgMgr);
++
++/*
++ *  ======== MSG_Exit ========
++ *  Purpose:
++ *      Discontinue usage of MSG module.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      MSG_Init(void) successfully called before.
++ *  Ensures:
++ *      Any resources acquired in MSG_Init(void) will be freed when last MSG
++ *      client calls MSG_Exit(void).
++ */
++      extern void MSG_Exit(void);
++
++/*
++ *  ======== MSG_Init ========
++ *  Purpose:
++ *      Initialize the MSG module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialization succeeded, FALSE otherwise.
++ *  Ensures:
++ */
++      extern bool MSG_Init(void);
++
++#endif                                /* MSG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/msgdefs.h b/arch/arm/plat-omap/include/dspbridge/msgdefs.h
+new file mode 100644
+index 0000000..8ea4551
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/msgdefs.h
+@@ -0,0 +1,43 @@
++/*
++ * msgdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== msgdefs.h ========
++ *  Description:
++ *      Global MSG constants and types.
++ *
++ *! Revision History
++ *! ================
++ *! 09-May-2001 jeh Removed MSG_TODSP, MSG_FROMDSP.
++ *! 17-Nov-2000 jeh Added MSGMGR_SIGNATURE.
++ *! 12-Sep-2000 jeh Created.
++ */
++
++#ifndef MSGDEFS_
++#define MSGDEFS_
++
++#define MSGMGR_SIGNATURE    0x4d47534d        /* "MGSM" */
++
++/* MSG Objects: */
++      struct MSG_MGR;
++      struct MSG_QUEUE;
++
++/* Function prototype for callback to be called on RMS_EXIT message received */
++       typedef void(*MSG_ONEXIT) (HANDLE h, s32 nStatus);
++
++#endif                                /* MSGDEFS_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/nldr.h b/arch/arm/plat-omap/include/dspbridge/nldr.h
+new file mode 100644
+index 0000000..0915846
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nldr.h
+@@ -0,0 +1,81 @@
++/*
++ * nldr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== nldr.h ========
++ *
++ *  Description:
++ *      DSP/BIOS Bridge dynamic loader interface. See the file dldrdefs.h
++ *  for a description of these functions.
++ *
++ *  Public Functions:
++ *      NLDR_Allocate
++ *      NLDR_Create
++ *      NLDR_Delete
++ *      NLDR_Exit
++ *      NLDR_Free
++ *      NLDR_GetFxnAddr
++ *      NLDR_Init
++ *      NLDR_Load
++ *      NLDR_Unload
++ *
++ *  Notes:
++ *
++ *! Revision History
++ *! ================
++ *! 31-Jul-2002 jeh     Removed function header comments.
++ *! 17-Apr-2002 jeh     Created.
++ */
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/dbdcddef.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/rmm.h>
++#include <dspbridge/nldrdefs.h>
++
++#ifndef NLDR_
++#define NLDR_
++
++      extern DSP_STATUS NLDR_Allocate(struct NLDR_OBJECT *hNldr,
++                                      void *pPrivRef,
++                                      IN CONST struct DCD_NODEPROPS
++                                      *pNodeProps,
++                                      OUT struct NLDR_NODEOBJECT **phNldrNode,
++                                      IN bool *pfPhaseSplit);
++
++      extern DSP_STATUS NLDR_Create(OUT struct NLDR_OBJECT **phNldr,
++                                    struct DEV_OBJECT *hDevObject,
++                                    IN CONST struct NLDR_ATTRS *pAttrs);
++
++      extern void NLDR_Delete(struct NLDR_OBJECT *hNldr);
++      extern void NLDR_Exit(void);
++      extern void NLDR_Free(struct NLDR_NODEOBJECT *hNldrNode);
++
++      extern DSP_STATUS NLDR_GetFxnAddr(struct NLDR_NODEOBJECT *hNldrNode,
++                                        char *pstrFxn, u32 *pulAddr);
++
++      extern DSP_STATUS NLDR_GetRmmManager(struct NLDR_OBJECT *hNldrObject,
++                                           OUT struct RMM_TargetObj
++                                           **phRmmMgr);
++
++      extern bool NLDR_Init(void);
++      extern DSP_STATUS NLDR_Load(struct NLDR_NODEOBJECT *hNldrNode,
++                                  enum NLDR_PHASE phase);
++      extern DSP_STATUS NLDR_Unload(struct NLDR_NODEOBJECT *hNldrNode,
++                                  enum NLDR_PHASE phase);
++
++#endif                                /* NLDR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/nldrdefs.h b/arch/arm/plat-omap/include/dspbridge/nldrdefs.h
+new file mode 100644
+index 0000000..84b36a3
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nldrdefs.h
+@@ -0,0 +1,307 @@
++/*
++ * nldrdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== nldrdefs.h ========
++ *  Description:
++ *      Global Dynamic + static/overlay Node loader (NLDR) constants and types.
++ *
++ *! Revision History
++ *! ================
++ *! 07-Apr-2003 map     Consolidated dldrdefs.h into nldrdefs.h
++ *! 05-Aug-2002 jeh     Created.
++ */
++
++#ifndef NLDRDEFS_
++#define NLDRDEFS_
++
++#include <dspbridge/dbdcddef.h>
++#include <dspbridge/devdefs.h>
++
++#define NLDR_MAXPATHLENGTH       255
++/* NLDR Objects: */
++      struct  NLDR_OBJECT;
++      struct NLDR_NODEOBJECT;
++
++/*
++ *  ======== NLDR_LOADTYPE ========
++ *  Load types for a node. Must match values in node.h55.
++ */
++      enum NLDR_LOADTYPE {
++              NLDR_STATICLOAD,        /* Linked in base image, not overlay */
++              NLDR_DYNAMICLOAD,       /* Dynamically loaded node */
++              NLDR_OVLYLOAD   /* Linked in base image, overlay node */
++      } ;
++
++/*
++ *  ======== NLDR_OVLYFXN ========
++ *  Causes code or data to be copied from load address to run address. This
++ *  is the "COD_WRITEFXN" that gets passed to the DBLL_Library and is used as
++ *  the ZL write function.
++ *
++ *  Parameters:
++ *      pPrivRef:       Handle to identify the node.
++ *      ulDspRunAddr:   Run address of code or data.
++ *      ulDspLoadAddr:  Load address of code or data.
++ *      ulNumBytes:     Number of (GPP) bytes to copy.
++ *      nMemSpace:      RMS_CODE or RMS_DATA.
++ *  Returns:
++ *      ulNumBytes:     Success.
++ *      0:              Failure.
++ *  Requires:
++ *  Ensures:
++ */
++       typedef u32(*NLDR_OVLYFXN) (void *pPrivRef, u32 ulDspRunAddr,
++                                           u32 ulDspLoadAddr,
++                                           u32 ulNumBytes, u32 nMemSpace);
++
++/*
++ *  ======== NLDR_WRITEFXN ========
++ *  Write memory function. Used for dynamic load writes.
++ *  Parameters:
++ *      pPrivRef:       Handle to identify the node.
++ *      ulDspAddr:      Address of code or data.
++ *      pBuf:           Code or data to be written
++ *      ulNumBytes:     Number of (GPP) bytes to write.
++ *      nMemSpace:      DBLL_DATA or DBLL_CODE.
++ *  Returns:
++ *      ulNumBytes:     Success.
++ *      0:              Failure.
++ *  Requires:
++ *  Ensures:
++ */
++       typedef u32(*NLDR_WRITEFXN) (void *pPrivRef,
++                                            u32 ulDspAddr, void *pBuf,
++                                            u32 ulNumBytes, u32 nMemSpace);
++
++/*
++ *  ======== NLDR_ATTRS ========
++ *  Attributes passed to NLDR_Create function.
++ */
++      struct NLDR_ATTRS {
++              NLDR_OVLYFXN pfnOvly;
++              NLDR_WRITEFXN pfnWrite;
++              u16 usDSPWordSize;
++              u16 usDSPMauSize;
++      } ;
++
++/*
++ *  ======== NLDR_PHASE ========
++ *  Indicates node create, delete, or execute phase function.
++ */
++      enum NLDR_PHASE {
++              NLDR_CREATE,
++              NLDR_DELETE,
++              NLDR_EXECUTE,
++              NLDR_NOPHASE
++      } ;
++
++/*
++ *  Typedefs of loader functions imported from a DLL, or defined in a
++ *  function table.
++ */
++
++/*
++ *  ======== NLDR_Allocate ========
++ *  Allocate resources to manage the loading of a node on the DSP.
++ *
++ *  Parameters:
++ *      hNldr:          Handle of loader that will load the node.
++ *      pPrivRef:       Handle to identify the node.
++ *      pNodeProps:     Pointer to a DCD_NODEPROPS for the node.
++ *      phNldrNode:     Location to store node handle on output. This handle
++ *                      will be passed to NLDR_Load/NLDR_Unload.
++ *      pfPhaseSplit:   pointer to boolean variable referenced in node.c
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Insufficient memory on GPP.
++ *  Requires:
++ *      NLDR_Init(void) called.
++ *      Valid hNldr.
++ *      pNodeProps != NULL.
++ *      phNldrNode != NULL.
++ *  Ensures:
++ *      DSP_SOK:        IsValidNode(*phNldrNode).
++ *      error:          *phNldrNode == NULL.
++ */
++      typedef DSP_STATUS(*NLDR_ALLOCATEFXN) (struct NLDR_OBJECT *hNldr,
++                                             void *pPrivRef,
++                                             IN CONST struct DCD_NODEPROPS
++                                             *pNodeProps,
++                                             OUT struct NLDR_NODEOBJECT
++                                             **phNldrNode,
++                                             OUT bool *pfPhaseSplit);
++
++/*
++ *  ======== NLDR_Create ========
++ *  Create a loader object. This object handles the loading and unloading of
++ *  create, delete, and execute phase functions of nodes on the DSP target.
++ *
++ *  Parameters:
++ *      phNldr:         Location to store loader handle on output.
++ *      hDevObject:     Device for this processor.
++ *      pAttrs:         Loader attributes.
++ *  Returns:
++ *      DSP_SOK:        Success;
++ *      DSP_EMEMORY:    Insufficient memory for requested resources.
++ *  Requires:
++ *      NLDR_Init(void) called.
++ *      phNldr != NULL.
++ *      hDevObject != NULL.
++ *    pAttrs != NULL.
++ *  Ensures:
++ *      DSP_SOK:        Valid *phNldr.
++ *      error:          *phNldr == NULL.
++ */
++      typedef DSP_STATUS(*NLDR_CREATEFXN) (OUT struct NLDR_OBJECT **phNldr,
++                                           struct DEV_OBJECT *hDevObject,
++                                           IN CONST struct NLDR_ATTRS
++                                           *pAttrs);
++
++/*
++ *  ======== NLDR_Delete ========
++ *  Delete the NLDR loader.
++ *
++ *  Parameters:
++ *      hNldr:          Node manager object.
++ *  Returns:
++ *  Requires:
++ *      NLDR_Init(void) called.
++ *      Valid hNldr.
++ *  Ensures:
++ *    hNldr invalid
++ */
++      typedef void(*NLDR_DELETEFXN) (struct NLDR_OBJECT *hNldr);
++
++/*
++ *  ======== NLDR_Exit ========
++ *  Discontinue usage of NLDR module.
++ *
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      NLDR_Init(void) successfully called before.
++ *  Ensures:
++ *      Any resources acquired in NLDR_Init(void) will be freed when last NLDR
++ *      client calls NLDR_Exit(void).
++ */
++      typedef void(*NLDR_EXITFXN) (void);
++
++/*
++ *  ======== NLDR_Free ========
++ *  Free resources allocated in NLDR_Allocate.
++ *
++ *  Parameters:
++ *      hNldrNode:      Handle returned from NLDR_Allocate().
++ *  Returns:
++ *  Requires:
++ *      NLDR_Init(void) called.
++ *      Valid hNldrNode.
++ *  Ensures:
++ */
++      typedef void(*NLDR_FREEFXN) (struct NLDR_NODEOBJECT *hNldrNode);
++
++/*
++ *  ======== NLDR_GetFxnAddr ========
++ *  Get address of create, delete, or execute phase function of a node on
++ *  the DSP.
++ *
++ *  Parameters:
++ *      hNldrNode:      Handle returned from NLDR_Allocate().
++ *      pstrFxn:        Name of function.
++ *      pulAddr:        Location to store function address.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_ESYMBOL:    Address of function not found.
++ *  Requires:
++ *      NLDR_Init(void) called.
++ *      Valid hNldrNode.
++ *      pulAddr != NULL;
++ *      pstrFxn != NULL;
++ *  Ensures:
++ */
++      typedef DSP_STATUS(*NLDR_GETFXNADDRFXN) (struct NLDR_NODEOBJECT
++                                               *hNldrNode,
++                                               char *pstrFxn, u32 *pulAddr);
++
++/*
++ *  ======== NLDR_Init ========
++ *  Initialize the NLDR module.
++ *
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialization succeeded, FALSE otherwise.
++ *  Ensures:
++ */
++      typedef bool(*NLDR_INITFXN) (void);
++
++/*
++ *  ======== NLDR_Load ========
++ *  Load create, delete, or execute phase function of a node on the DSP.
++ *
++ *  Parameters:
++ *      hNldrNode:      Handle returned from NLDR_Allocate().
++ *      phase:          Type of function to load (create, delete, or execute).
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      DSP_EMEMORY:            Insufficient memory on GPP.
++ *      DSP_EOVERLAYMEMORY:     Can't overlay phase because overlay memory
++ *                              is already in use.
++ *      DSP_EDYNLOAD:           Failure in dynamic loader library.
++ *      DSP_EFWRITE:            Failed to write phase's code or date to target.
++ *  Requires:
++ *      NLDR_Init(void) called.
++ *      Valid hNldrNode.
++ *  Ensures:
++ */
++      typedef DSP_STATUS(*NLDR_LOADFXN) (struct NLDR_NODEOBJECT *hNldrNode,
++                                         enum NLDR_PHASE phase);
++
++/*
++ *  ======== NLDR_Unload ========
++ *  Unload create, delete, or execute phase function of a node on the DSP.
++ *
++ *  Parameters:
++ *      hNldrNode:      Handle returned from NLDR_Allocate().
++ *      phase:          Node function to unload (create, delete, or execute).
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Insufficient memory on GPP.
++ *  Requires:
++ *      NLDR_Init(void) called.
++ *      Valid hNldrNode.
++ *  Ensures:
++ */
++      typedef DSP_STATUS(*NLDR_UNLOADFXN) (struct NLDR_NODEOBJECT *hNldrNode,
++                                           enum NLDR_PHASE phase);
++
++/*
++ *  ======== NLDR_FXNS ========
++ */
++      struct NLDR_FXNS {
++              NLDR_ALLOCATEFXN pfnAllocate;
++              NLDR_CREATEFXN pfnCreate;
++              NLDR_DELETEFXN pfnDelete;
++              NLDR_EXITFXN pfnExit;
++              NLDR_FREEFXN pfnFree;
++              NLDR_GETFXNADDRFXN pfnGetFxnAddr;
++              NLDR_INITFXN pfnInit;
++              NLDR_LOADFXN pfnLoad;
++              NLDR_UNLOADFXN pfnUnload;
++      } ;
++
++#endif                                /* NLDRDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/node.h b/arch/arm/plat-omap/include/dspbridge/node.h
+new file mode 100644
+index 0000000..d253962
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/node.h
+@@ -0,0 +1,619 @@
++/*
++ * node.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== node.h ========
++ *  Description:
++ *      DSP/BIOS Bridge Node Manager.
++ *
++ *  Public Functions:
++ *      NODE_Allocate
++ *      NODE_AllocMsgBuf
++ *      NODE_ChangePriority
++ *      NODE_Connect
++ *      NODE_Create
++ *      NODE_CreateMgr
++ *      NODE_Delete
++ *      NODE_DeleteMgr
++ *      NODE_EnumNodes
++ *      NODE_Exit
++ *      NODE_FreeMsgBuf
++ *      NODE_GetAttr
++ *      NODE_GetMessage
++ *      NODE_GetProcessor
++ *      NODE_Init
++ *      NODE_OnExit
++ *      NODE_Pause
++ *      NODE_PutMessage
++ *      NODE_RegisterNotify
++ *      NODE_Run
++ *      NODE_Terminate
++ *
++ *  Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 23-Apr-2001 jeh     Updated with code review changes.
++ *! 16-Jan-2001 jeh     Added DSP_ESYMBOL, DSP_EUUID to return codes.
++ *! 17-Nov-2000 jeh     Added NODE_OnExit().
++ *! 27-Oct-2000 jeh     Added timeouts to NODE_GetMessage, NODE_PutMessage.
++ *! 12-Oct-2000 jeh     Changed NODE_EnumNodeInfo to NODE_EnumNodes. Removed
++ *!                     NODE_RegisterAllNodes().
++ *! 07-Sep-2000 jeh     Changed type HANDLE in NODE_RegisterNotify to
++ *!                     DSP_HNOTIFICATION. Added DSP_STRMATTR param to
++ *!                     NODE_Connect(). Removed NODE_GetMessageStream().
++ *! 17-Jul-2000 jeh     Updated function header descriptions.
++ *! 19-Jun-2000 jeh     Created.
++ */
++
++#ifndef NODE_
++#define NODE_
++
++#include <dspbridge/procpriv.h>
++
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/dispdefs.h>
++#include <dspbridge/nldrdefs.h>
++
++/*
++ *  ======== NODE_Allocate ========
++ *  Purpose:
++ *      Allocate GPP resources to manage a node on the DSP.
++ *  Parameters:
++ *      hProcessor:         Handle of processor that is allocating the node.
++ *      pNodeId:            Pointer to a DSP_UUID for the node.
++ *      pArgs:              Optional arguments to be passed to the node.
++ *      pAttrIn:            Optional pointer to node attributes (priority,
++ *                          timeout...)
++ *      phNode:             Location to store node handle on output.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EMEMORY:        Insufficient memory on GPP.
++ *      DSP_EUUID:          Node UUID has not been registered.
++ *      DSP_ESYMBOL:        iAlg functions not found for a DAIS node.
++ *      DSP_ERANGE:         pAttrIn != NULL and pAttrIn->iPriority out of
++ *                          range.
++ *      DSP_EFAIL:          A failure occured, unable to allocate node.
++ *      DSP_EWRONGSTATE:    Proccessor is not in the running state.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *      hProcessor != NULL.
++ *      pNodeId != NULL.
++ *      phNode != NULL.
++ *  Ensures:
++ *      DSP_SOK:            IsValidNode(*phNode).
++ *      error:              *phNode == NULL.
++ */
++      extern DSP_STATUS NODE_Allocate(struct PROC_OBJECT *hProcessor,
++                                      IN CONST struct DSP_UUID *pNodeId,
++                                      OPTIONAL IN CONST struct DSP_CBDATA
++                                      *pArgs,
++                                      OPTIONAL IN CONST struct DSP_NODEATTRIN
++                                      *pAttrIn,
++                                      OUT struct NODE_OBJECT **phNode);
++
++/*
++ *  ======== NODE_AllocMsgBuf ========
++ *  Purpose:
++ *      Allocate and Prepare a buffer whose descriptor will be passed to a
++ *      Node within a (DSP_MSG)message
++ *  Parameters:
++ *      hNode:          The node handle.
++ *      uSize:          The size of the buffer to be allocated.
++ *      pAttr:          Pointer to a DSP_BUFFERATTR structure.
++ *      pBuffer:        Location to store the address of the allocated
++ *                      buffer on output.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid node handle.
++ *      DSP_EMEMORY:    Insufficent memory.
++ *      DSP_EFAIL:      General Failure.
++ *      DSP_ESIZE:      Invalid Size.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *      pBuffer != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS NODE_AllocMsgBuf(struct NODE_OBJECT *hNode,
++                                         u32 uSize,
++                                         OPTIONAL struct DSP_BUFFERATTR
++                                         *pAttr,
++                                         OUT u8 **pBuffer);
++
++/*
++ *  ======== NODE_ChangePriority ========
++ *  Purpose:
++ *      Change the priority of an allocated node.
++ *  Parameters:
++ *      hNode:              Node handle returned from NODE_Allocate.
++ *      nPriority:          New priority level to set node's priority to.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EHANDLE:        Invalid hNode.
++ *      DSP_ERANGE:         nPriority is out of range.
++ *      DSP_ENODETYPE:      The specified node is not a task node.
++ *      DSP_EWRONGSTATE:    Node is not in the NODE_ALLOCATED, NODE_PAUSED,
++ *                          or NODE_RUNNING state.
++ *      DSP_ETIMEOUT:       A timeout occurred before the DSP responded.
++ *      DSP_ERESTART:       A critical error has occurred and the DSP is
++ *                          being restarted.
++ *      DSP_EFAIL:          Unable to change node's runtime priority level.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *  Ensures:
++ *      DSP_SOK && (Node's current priority == nPriority)
++ */
++      extern DSP_STATUS NODE_ChangePriority(struct NODE_OBJECT *hNode,
++                                            s32 nPriority);
++
++/*
++ *  ======== NODE_CloseOrphans ========
++ *  Purpose:
++ *      Delete all nodes whose owning processor is being destroyed.
++ *  Parameters:
++ *      hNodeMgr:       Node manager object.
++ *      hProc:          Handle to processor object being destroyed.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Unable to delete all nodes belonging to hProc.
++ *  Requires:
++ *      Valid hNodeMgr.
++ *      hProc != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS NODE_CloseOrphans(struct NODE_MGR *hNodeMgr,
++                                          struct PROC_OBJECT *hProc);
++
++/*
++ *  ======== NODE_Connect ========
++ *  Purpose:
++ *      Connect two nodes on the DSP, or a node on the DSP to the GPP. In the
++ *      case that the connnection is being made between a node on the DSP and
++ *      the GPP, one of the node handles (either hNode1 or hNode2) must be
++ *      the constant NODE_HGPPNODE.
++ *  Parameters:
++ *      hNode1:         Handle of first node to connect to second node. If
++ *                      this is a connection from the GPP to hNode2, hNode1
++ *                      must be the constant NODE_HGPPNODE. Otherwise, hNode1
++ *                      must be a node handle returned from a successful call
++ *                      to Node_Allocate().
++ *      hNode2:         Handle of second node. Must be either NODE_HGPPNODE
++ *                      if this is a connection from DSP node to GPP, or a
++ *                      node handle returned from a successful call to
++ *                      NODE_Allocate().
++ *      uStream1:       Output stream index on first node, to be connected
++ *                      to second node's input stream. Value must range from
++ *                      0 <= uStream1 < number of output streams.
++ *      uStream2:       Input stream index on second node. Value must range
++ *                      from 0 <= uStream2 < number of input streams.
++ *      pAttrs:         Stream attributes (NULL ==> use defaults).
++ *      pConnParam:     A pointer to a DSP_CBDATA structure that defines
++ *                      connection parameter for device nodes to pass to DSP
++ *                      side.
++ *                      If the value of this parameter is NULL, then this API
++ *                      behaves like DSPNode_Connect. This parameter will have
++ *                      length of the string and the null terminated string in
++ *                      DSP_CBDATA struct. This can be extended in future tp
++ *                      pass binary data.
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      DSP_EHANDLE:            Invalid hNode1 or hNode2.
++ *      DSP_EMEMORY:            Insufficient host memory.
++ *      DSP_EVALUE:             A stream index parameter is invalid.
++ *      DSP_EALREADYCONNECTED:  A connection already exists for one of the
++ *                              indices uStream1 or uStream2.
++ *      DSP_EWRONGSTATE:        Either hNode1 or hNode2 is not in the
++ *                              NODE_ALLOCATED state.
++ *      DSP_ENOMORECONNECTIONS: No more connections available.
++ *      DSP_EFAIL:              Attempt to make an illegal connection (eg,
++ *                              Device node to device node, or device node to
++ *                              GPP), the two nodes are on different DSPs.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *  Ensures:
++ */
++      extern DSP_STATUS NODE_Connect(struct NODE_OBJECT *hNode1,
++                                     u32 uStream1,
++                                     struct NODE_OBJECT *hNode2,
++                                     u32 uStream2,
++                                     OPTIONAL IN struct DSP_STRMATTR *pAttrs,
++                                     OPTIONAL IN struct DSP_CBDATA
++                                     *pConnParam);
++
++/*
++ *  ======== NODE_Create ========
++ *  Purpose:
++ *      Create a node on the DSP by remotely calling the node's create
++ *      function. If necessary, load code that contains the node's create
++ *      function.
++ *  Parameters:
++ *      hNode:              Node handle returned from NODE_Allocate().
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EHANDLE:        Invalid hNode.
++ *      DSP_ESYMBOL:        Create function not found in the COFF file.
++ *      DSP_EWRONGSTATE:    Node is not in the NODE_ALLOCATED state.
++ *      DSP_EMEMORY:        Memory allocation failure on the DSP.
++ *      DSP_ETASK:          Unable to create node's task or process on the DSP.
++ *      DSP_ESTREAM:        Stream creation failure on the DSP.
++ *      DSP_ETIMEOUT:       A timeout occurred before the DSP responded.
++ *      DSP_EUSER1-16:      A user-defined failure occurred on the DSP.
++ *      DSP_EFAIL:          A failure occurred, unable to create node.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *  Ensures:
++ */
++      extern DSP_STATUS NODE_Create(struct NODE_OBJECT *hNode);
++
++/*
++ *  ======== NODE_CreateMgr ========
++ *  Purpose:
++ *      Create a NODE Manager object. This object handles the creation,
++ *      deletion, and execution of nodes on the DSP target. The NODE Manager
++ *      also maintains a pipe map of used and available node connections.
++ *      Each DEV object should have exactly one NODE Manager object.
++ *
++ *  Parameters:
++ *      phNodeMgr:      Location to store node manager handle on output.
++ *      hDevObject:     Device for this processor.
++ *  Returns:
++ *      DSP_SOK:        Success;
++ *      DSP_EMEMORY:    Insufficient memory for requested resources.
++ *      DSP_EFAIL:      General failure.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *      phNodeMgr != NULL.
++ *      hDevObject != NULL.
++ *  Ensures:
++ *      DSP_SOK:        Valide *phNodeMgr.
++ *      error:          *phNodeMgr == NULL.
++ */
++      extern DSP_STATUS NODE_CreateMgr(OUT struct NODE_MGR **phNodeMgr,
++                                       struct DEV_OBJECT *hDevObject);
++
++/*
++ *  ======== NODE_Delete ========
++ *  Purpose:
++ *      Delete resources allocated in NODE_Allocate(). If the node was
++ *      created, delete the node on the DSP by remotely calling the node's
++ *      delete function. Loads the node's delete function if necessary.
++ *      GPP side resources are freed after node's delete function returns.
++ *  Parameters:
++ *      hNode:              Node handle returned from NODE_Allocate().
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EHANDLE:        Invalid hNode.
++ *      DSP_ETIMEOUT:       A timeout occurred before the DSP responded.
++ *      DSP_EDELETE:        A deletion failure occurred.
++ *      DSP_EUSER1-16:      Node specific failure occurred on the DSP.
++ *      DSP_EFAIL:          A failure occurred in deleting the node.
++ *      DSP_ESYMBOL:        Delete function not found in the COFF file.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *  Ensures:
++ *      DSP_SOK:            hNode is invalid.
++ */
++      extern DSP_STATUS NODE_Delete(struct NODE_OBJECT *hNode);
++
++/*
++ *  ======== NODE_DeleteMgr ========
++ *  Purpose:
++ *      Delete the NODE Manager.
++ *  Parameters:
++ *      hNodeMgr:       Node manager object.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *      Valid hNodeMgr.
++ *  Ensures:
++ */
++      extern DSP_STATUS NODE_DeleteMgr(struct NODE_MGR *hNodeMgr);
++
++/*
++ *  ======== NODE_EnumNodes ========
++ *  Purpose:
++ *      Enumerate the nodes currently allocated for the DSP.
++ *  Parameters:
++ *      hNodeMgr:       Node manager returned from NODE_CreateMgr().
++ *      aNodeTab:       Array to copy node handles into.
++ *      uNodeTabSize:   Number of handles that can be written to aNodeTab.
++ *      puNumNodes:     Location where number of node handles written to
++ *                      aNodeTab will be written.
++ *      puAllocated:    Location to write total number of allocated nodes.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_ESIZE:      aNodeTab is too small to hold all node handles.
++ *  Requires:
++ *      Valid hNodeMgr.
++ *      aNodeTab != NULL || uNodeTabSize == 0.
++ *      puNumNodes != NULL.
++ *      puAllocated != NULL.
++ *  Ensures:
++ *      - (DSP_ESIZE && *puNumNodes == 0)
++ *      - || (DSP_SOK && *puNumNodes <= uNodeTabSize)  &&
++ *        (*puAllocated == *puNumNodes)
++ */
++      extern DSP_STATUS NODE_EnumNodes(struct NODE_MGR *hNodeMgr,
++                                       IN DSP_HNODE *aNodeTab,
++                                       u32 uNodeTabSize,
++                                       OUT u32 *puNumNodes,
++                                       OUT u32 *puAllocated);
++
++/*
++ *  ======== NODE_Exit ========
++ *  Purpose:
++ *      Discontinue usage of NODE module.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      NODE_Init(void) successfully called before.
++ *  Ensures:
++ *      Any resources acquired in NODE_Init(void) will be freed when last NODE
++ *      client calls NODE_Exit(void).
++ */
++      extern void NODE_Exit(void);
++
++/*
++ *  ======== NODE_FreeMsgBuf ========
++ *  Purpose:
++ *      Free a message buffer previously allocated with NODE_AllocMsgBuf.
++ *  Parameters:
++ *      hNode:          The node handle.
++ *      pBuffer:        (Address) Buffer allocated by NODE_AllocMsgBuf.
++ *      pAttr:          Same buffer attributes passed to NODE_AllocMsgBuf.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid node handle.
++ *      DSP_EFAIL:      Failure to free the buffer.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *      pBuffer != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS NODE_FreeMsgBuf(struct NODE_OBJECT *hNode,
++                                        IN u8 *pBuffer,
++                                        OPTIONAL struct DSP_BUFFERATTR
++                                        *pAttr);
++
++/*
++ *  ======== NODE_GetAttr ========
++ *  Purpose:
++ *      Copy the current attributes of the specified node into a DSP_NODEATTR
++ *      structure.
++ *  Parameters:
++ *      hNode:          Node object allocated from NODE_Allocate().
++ *      pAttr:          Pointer to DSP_NODEATTR structure to copy node's
++ *                      attributes.
++ *      uAttrSize:      Size of pAttr.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hNode.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *      pAttr != NULL.
++ *  Ensures:
++ *      DSP_SOK:        *pAttrs contains the node's current attributes.
++ */
++      extern DSP_STATUS NODE_GetAttr(struct NODE_OBJECT *hNode,
++                                     OUT struct DSP_NODEATTR *pAttr,
++                                     u32 uAttrSize);
++
++/*
++ *  ======== NODE_GetMessage ========
++ *  Purpose:
++ *      Retrieve a message from a node on the DSP. The node must be either a
++ *      message node, task node, or XDAIS socket node.
++ *      If a message is not available, this function will block until a
++ *      message is available, or the node's timeout value is reached.
++ *  Parameters:
++ *      hNode:          Node handle returned from NODE_Allocate().
++ *      pMessage:       Pointer to DSP_MSG structure to copy the
++ *                      message into.
++ *      uTimeout:       Timeout in milliseconds to wait for message.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hNode.
++ *      DSP_ENODETYPE:  Cannot retrieve messages from this type of node.
++ *      DSP_ETIMEOUT:   Timeout occurred and no message is available.
++ *      DSP_EFAIL:      Error occurred while trying to retrieve a message.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *      pMessage != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS NODE_GetMessage(struct NODE_OBJECT *hNode,
++                                        OUT struct DSP_MSG *pMessage,
++                                        u32 uTimeout);
++
++/*
++ *  ======== NODE_GetNldrObj ========
++ *  Purpose:
++ *      Retrieve the Nldr manager
++ *  Parameters:
++ *      hNodeMgr:       Node Manager
++ *      phNldrObj:      Pointer to a Nldr manager handle
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hNode.
++ *  Ensures:
++ */
++      extern DSP_STATUS NODE_GetNldrObj(struct NODE_MGR *hNodeMgr,
++                                        OUT struct NLDR_OBJECT **phNldrObj);
++
++/*
++ *  ======== NODE_Init ========
++ *  Purpose:
++ *      Initialize the NODE module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialization succeeded, FALSE otherwise.
++ *  Ensures:
++ */
++      extern bool NODE_Init(void);
++
++/*
++ *  ======== NODE_OnExit ========
++ *  Purpose:
++ *      Gets called when RMS_EXIT is received for a node. PROC needs to pass
++ *      this function as a parameter to MSG_Create(). This function then gets
++ *      called by the mini-driver when an exit message for a node is received.
++ *  Parameters:
++ *      hNode:      Handle of the node that the exit message is for.
++ *      nStatus:    Return status of the node's execute phase.
++ *  Returns:
++ *  Ensures:
++ */
++      void NODE_OnExit(struct NODE_OBJECT *hNode, s32 nStatus);
++
++/*
++ *  ======== NODE_Pause ========
++ *  Purpose:
++ *      Suspend execution of a node currently running on the DSP.
++ *  Parameters:
++ *      hNode:              Node object representing a node currently
++ *                          running on the DSP.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EHANDLE:        Invalid hNode.
++ *      DSP_ENODETYPE:      Node is not a task or socket node.
++ *      DSP_ETIMEOUT:       A timeout occurred before the DSP responded.
++ *      DSP_EWRONGSTSATE:   Node is not in NODE_RUNNING state.
++ *      DSP_EFAIL:          Failed to pause node.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *  Ensures:
++ */
++      extern DSP_STATUS NODE_Pause(struct NODE_OBJECT *hNode);
++
++/*
++ *  ======== NODE_PutMessage ========
++ *  Purpose:
++ *      Send a message to a message node, task node, or XDAIS socket node.
++ *      This function will block until the message stream can accommodate
++ *      the message, or a timeout occurs. The message will be copied, so Msg
++ *      can be re-used immediately after return.
++ *  Parameters:
++ *      hNode:              Node handle returned by NODE_Allocate().
++ *      pMsg:               Location of message to be sent to the node.
++ *      uTimeout:           Timeout in msecs to wait.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EHANDLE:        Invalid hNode.
++ *      DSP_ENODETYPE:      Messages can't be sent to this type of node.
++ *      DSP_ETIMEOUT:       Timeout occurred before message could be set.
++ *      DSP_EWRONGSTATE:    Node is in invalid state for sending messages.
++ *      DSP_EFAIL:          Unable to send message.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *      pMsg != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS NODE_PutMessage(struct NODE_OBJECT *hNode,
++                                        IN CONST struct DSP_MSG *pMsg,
++                                        u32 uTimeout);
++
++/*
++ *  ======== NODE_RegisterNotify ========
++ *  Purpose:
++ *      Register to be notified on specific events for this node.
++ *  Parameters:
++ *      hNode:          Node handle returned by NODE_Allocate().
++ *      uEventMask:     Mask of types of events to be notified about.
++ *      uNotifyType:    Type of notification to be sent.
++ *      hNotification:  Handle to be used for notification.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hNode.
++ *      DSP_EMEMORY:    Insufficient memory on GPP.
++ *      DSP_EVALUE:     uEventMask is invalid.
++ *      DSP_ENOTIMPL:   Notification type specified by uNotifyType is not
++ *                      supported.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *      hNotification != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS NODE_RegisterNotify(struct NODE_OBJECT *hNode,
++                                            u32 uEventMask, u32 uNotifyType,
++                                            struct DSP_NOTIFICATION
++                                            *hNotification);
++
++/*
++ *  ======== NODE_Run ========
++ *  Purpose:
++ *      Start execution of a node's execute phase, or resume execution of
++ *      a node that has been suspended (via NODE_Pause()) on the DSP. Load
++ *      the node's execute function if necessary.
++ *  Parameters:
++ *      hNode:              Node object representing a node currently
++ *                          running on the DSP.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EHANDLE:        Invalid hNode.
++ *      DSP_ENODETYPE:      hNode doesn't represent a message, task or dais
++ *                          socket node.
++ *      DSP_ETIMEOUT:       A timeout occurred before the DSP responded.
++ *      DSP_EWRONGSTSATE:   Node is not in NODE_PAUSED or NODE_CREATED state.
++ *      DSP_EFAIL:          Unable to start or resume execution.
++ *      DSP_ESYMBOL:        Execute function not found in the COFF file.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *  Ensures:
++ */
++      extern DSP_STATUS NODE_Run(struct NODE_OBJECT *hNode);
++
++/*
++ *  ======== NODE_Terminate ========
++ *  Purpose:
++ *      Signal a node running on the DSP that it should exit its execute
++ *      phase function.
++ *  Parameters:
++ *      hNode:              Node object representing a node currently
++ *                          running on the DSP.
++ *      pStatus:            Location to store execute-phase function return
++ *                          value (DSP_EUSER1-16).
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EHANDLE:        Invalid hNode.
++ *      DSP_ETIMEOUT:       A timeout occurred before the DSP responded.
++ *      DSP_ENODETYPE:      Type of node specified cannot be terminated.
++ *      DSP_EWRONGSTATE:    Operation not valid for the current node state.
++ *      DSP_EFAIL:          Unable to terminate the node.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *      pStatus != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS NODE_Terminate(struct NODE_OBJECT *hNode,
++                                       OUT DSP_STATUS *pStatus);
++
++
++
++/*
++ *  ======== NODE_GetUUIDProps ========
++ *  Purpose:
++ *      Fetch Node properties given the UUID
++ *  Parameters:
++ *
++ */
++      extern DSP_STATUS NODE_GetUUIDProps(DSP_HPROCESSOR hProcessor,
++                                          IN CONST struct DSP_UUID *pNodeId,
++                                          OUT struct DSP_NDBPROPS
++                                          *pNodeProps);
++
++#endif                                /* NODE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/nodedefs.h b/arch/arm/plat-omap/include/dspbridge/nodedefs.h
+new file mode 100644
+index 0000000..cdc0c4b
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nodedefs.h
+@@ -0,0 +1,40 @@
++/*
++ * nodedefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== nodedefs.h ========
++ *  Description:
++ *      Global NODE constants and types, shared by PROCESSOR, NODE, and DISP.
++ *
++ *! Revision History
++ *! ================
++ *! 23-Apr-2001 jeh     Removed NODE_MGRATTRS.
++ *! 21-Sep-2000 jeh     Removed NODE_TYPE enum.
++ *! 17-Jul-2000 jeh     Changed order of node types to match rms_sh.h.
++ *! 20-Jun-2000 jeh     Created.
++ */
++
++#ifndef NODEDEFS_
++#define NODEDEFS_
++
++#define NODE_SUSPENDEDPRI -1
++
++/* NODE Objects: */
++      struct NODE_MGR;
++      struct NODE_OBJECT;
++
++#endif                                /* NODEDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/nodepriv.h b/arch/arm/plat-omap/include/dspbridge/nodepriv.h
+new file mode 100644
+index 0000000..d28b29b
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nodepriv.h
+@@ -0,0 +1,202 @@
++/*
++ * nodepriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== nodepriv.h ========
++ *  Description:
++ *      Private node header shared by NODE and DISP.
++ *
++ *  Public Functions:
++ *      NODE_GetChannelId
++ *      NODE_GetStrmMgr
++ *      NODE_GetTimeout
++ *      NODE_GetType
++ *      NODE_GetLoadType
++ *
++ *! Revision History
++ *! ================
++ *! 19-Nov-2002 map     Added NODE_GetLoadType
++ *! 13-Feb-2002 jeh     Added uSysStackSize to NODE_TASKARGS.
++ *! 23-Apr-2001 jeh     Removed unused typedefs, defines.
++ *! 10-Oct-2000 jeh     Added alignment to NODE_STRMDEF.
++ *! 20-Jun-2000 jeh     Created.
++ */
++
++#ifndef NODEPRIV_
++#define NODEPRIV_
++
++#include <dspbridge/strmdefs.h>
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/nldrdefs.h>
++
++/* DSP address of node environment structure */
++      typedef u32 NODE_ENV;
++
++/*
++ *  Node create structures
++ */
++
++/* Message node */
++      struct NODE_MSGARGS {
++              u32 uMaxMessages; /* Max # of simultaneous messages for node */
++              u32 uSegid;     /* Segment for allocating message buffers */
++              u32 uNotifyType;  /* Notify type (SEM_post, SWI_post, etc.) */
++              u32 uArgLength;  /* Length in 32-bit words of arg data block */
++              u8 *pData;      /* Argument data for node */
++      } ;
++
++      struct NODE_STRMDEF {
++              u32 uBufsize;   /* Size of buffers for SIO stream */
++              u32 uNumBufs;   /* max # of buffers in SIO stream at once */
++              u32 uSegid;     /* Memory segment id to allocate buffers */
++              u32 uTimeout;   /* Timeout for blocking SIO calls */
++              u32 uAlignment; /* Buffer alignment */
++              char *szDevice; /* Device name for stream */
++      } ;
++
++/* Task node */
++      struct NODE_TASKARGS {
++              struct NODE_MSGARGS msgArgs;
++              s32 nPriority;
++              u32 uStackSize;
++              u32 uSysStackSize;
++              u32 uStackSeg;
++              u32 uDSPHeapResAddr;    /* DSP virtual heap address */
++              u32 uDSPHeapAddr;       /* DSP virtual heap address */
++              u32 uHeapSize;  /* Heap size */
++              u32 uGPPHeapAddr;       /* GPP virtual heap address */
++              u32 uProfileID; /* Profile ID */
++              u32 uNumInputs;
++              u32 uNumOutputs;
++              u32 ulDaisArg;  /* Address of iAlg object */
++              struct NODE_STRMDEF *strmInDef;
++              struct NODE_STRMDEF *strmOutDef;
++      } ;
++
++/*
++ *  ======== NODE_CREATEARGS ========
++ */
++      struct NODE_CREATEARGS {
++              union {
++                      struct NODE_MSGARGS msgArgs;
++                      struct NODE_TASKARGS taskArgs;
++              } asa;
++      } ;
++
++/*
++ *  ======== NODE_GetChannelId ========
++ *  Purpose:
++ *      Get the channel index reserved for a stream connection between the
++ *      host and a node. This index is reserved when NODE_Connect() is called
++ *      to connect the node with the host. This index should be passed to
++ *      the CHNL_Open function when the stream is actually opened.
++ *  Parameters:
++ *      hNode:          Node object allocated from NODE_Allocate().
++ *      uDir:           Input (DSP_TONODE) or output (DSP_FROMNODE).
++ *      uIndex:         Stream index.
++ *      pulId:          Location to store channel index.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hNode.
++ *      DSP_ENODETYPE:  Not a task or DAIS socket node.
++ *      DSP_EVALUE:     The node's stream corresponding to uIndex and uDir
++ *                      is not a stream to or from the host.
++ *  Requires:
++ *      NODE_Init(void) called.
++ *      Valid uDir.
++ *      pulId != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS NODE_GetChannelId(struct NODE_OBJECT *hNode,
++                                          u32 uDir,
++                                          u32 uIndex, OUT u32 *pulId);
++
++/*
++ *  ======== NODE_GetStrmMgr ========
++ *  Purpose:
++ *      Get the STRM manager for a node.
++ *  Parameters:
++ *      hNode:          Node allocated with NODE_Allocate().
++ *      phStrmMgr:      Location to store STRM manager on output.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hNode.
++ *  Requires:
++ *      phStrmMgr != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS NODE_GetStrmMgr(struct NODE_OBJECT *hNode,
++                                        struct STRM_MGR **phStrmMgr);
++
++/*
++ *  ======== NODE_GetTimeout ========
++ *  Purpose:
++ *      Get the timeout value of a node.
++ *  Parameters:
++ *      hNode:      Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ *  Returns:
++ *      Node's timeout value.
++ *  Requires:
++ *      Valid hNode.
++ *  Ensures:
++ */
++      extern u32 NODE_GetTimeout(struct NODE_OBJECT *hNode);
++
++/*
++ *  ======== NODE_GetType ========
++ *  Purpose:
++ *      Get the type (device, message, task, or XDAIS socket) of a node.
++ *  Parameters:
++ *      hNode:      Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ *  Returns:
++ *      Node type:  NODE_DEVICE, NODE_TASK, NODE_XDAIS, or NODE_GPP.
++ *  Requires:
++ *      Valid hNode.
++ *  Ensures:
++ */
++      extern enum NODE_TYPE NODE_GetType(struct NODE_OBJECT *hNode);
++
++/*
++ *  ======== GetNodeInfo ========
++ *  Purpose:
++ *      Get node information without holding semaphore.
++ *  Parameters:
++ *      hNode:      Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ *  Returns:
++ *      Node info:  priority, device owner, no. of streams, execution state
++ *                  NDB properties.
++ *  Requires:
++ *      Valid hNode.
++ *  Ensures:
++ */
++      extern void GetNodeInfo(struct NODE_OBJECT *hNode,
++                              struct DSP_NODEINFO *pNodeInfo);
++
++/*
++ *  ======== NODE_GetLoadType ========
++ *  Purpose:
++ *      Get the load type (dynamic, overlay, static) of a node.
++ *  Parameters:
++ *      hNode:      Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ *  Returns:
++ *      Node type:  NLDR_DYNAMICLOAD, NLDR_OVLYLOAD, NLDR_STATICLOAD
++ *  Requires:
++ *      Valid hNode.
++ *  Ensures:
++ */
++      extern enum NLDR_LOADTYPE NODE_GetLoadType(struct NODE_OBJECT *hNode);
++
++#endif                                /* NODEPRIV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/ntfy.h b/arch/arm/plat-omap/include/dspbridge/ntfy.h
+new file mode 100644
+index 0000000..5a0992a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/ntfy.h
+@@ -0,0 +1,146 @@
++/*
++ * ntfy.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== ntfy.h ========
++ *  Purpose:
++ *      Manage lists of notification events.
++ *
++ *  Public Functions:
++ *      NTFY_Create
++ *      NTFY_Delete
++ *      NTFY_Exit
++ *      NTFY_Init
++ *      NTFY_Notify
++ *      NTFY_Register
++ *
++ *! Revision History:
++ *! =================
++ *! 05-Nov-2001 kc: Updated NTFY_Register.
++ *! 07-Sep-2000 jeh Created.
++ */
++
++#ifndef NTFY_
++#define NTFY_
++
++      struct NTFY_OBJECT;
++
++/*
++ *  ======== NTFY_Create ========
++ *  Purpose:
++ *      Create an empty list of notifications.
++ *  Parameters:
++ *      phNtfy:         Location to store handle on output.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Memory allocation failure.
++ *  Requires:
++ *      NTFY_Init(void) called.
++ *      phNtfy != NULL.
++ *  Ensures:
++ *      DSP_SUCCEEDED(status) <==>  IsValid(*phNtfy).
++ */
++      extern DSP_STATUS NTFY_Create(OUT struct NTFY_OBJECT **phNtfy);
++
++/*
++ *  ======== NTFY_Delete ========
++ *  Purpose:
++ *      Free resources allocated in NTFY_Create.
++ *  Parameters:
++ *      hNtfy:  Handle returned from NTFY_Create().
++ *  Returns:
++ *  Requires:
++ *      NTFY_Init(void) called.
++ *      IsValid(hNtfy).
++ *  Ensures:
++ */
++      extern void NTFY_Delete(IN struct NTFY_OBJECT *hNtfy);
++
++/*
++ *  ======== NTFY_Exit ========
++ *  Purpose:
++ *      Discontinue usage of NTFY module.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      NTFY_Init(void) successfully called before.
++ *  Ensures:
++ */
++      extern void NTFY_Exit(void);
++
++/*
++ *  ======== NTFY_Init ========
++ *  Purpose:
++ *      Initialize the NTFY module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialization succeeded, FALSE otherwise.
++ *  Ensures:
++ */
++      extern bool NTFY_Init(void);
++
++/*
++ *  ======== NTFY_Notify ========
++ *  Purpose:
++ *      Execute notify function (signal event or post message) for every
++ *      element in the notification list that is to be notified about the
++ *      event specified in uEventMask.
++ *  Parameters:
++ *      hNtfy:      Handle returned from NTFY_Create().
++ *      uEventMask: The type of event that has occurred.
++ *  Returns:
++ *  Requires:
++ *      NTFY_Init(void) called.
++ *      IsValid(hNtfy).
++ *  Ensures:
++ */
++      extern void NTFY_Notify(IN struct NTFY_OBJECT *hNtfy,
++                              IN u32 uEventMask);
++
++/*
++ *  ======== NTFY_Register ========
++ *  Purpose:
++ *      Add a notification element to the list. If the notification is already
++ *      registered, and uEventMask != 0, the notification will get posted for
++ *      events specified in the new event mask. If the notification is already
++ *      registered and uEventMask == 0, the notification will be unregistered.
++ *  Parameters:
++ *      hNtfy:              Handle returned from NTFY_Create().
++ *      hNotification:      Handle to a DSP_NOTIFICATION object.
++ *      uEventMask:         Events to be notified about.
++ *      uNotifyType:        Type of notification: DSP_SIGNALEVENT.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EMEMORY:        Insufficient memory.
++ *      DSP_EVALUE:         uEventMask is 0 and hNotification was not
++ *                          previously registered.
++ *      DSP_EHANDLE:        NULL hNotification, hNotification event name
++ *                          too long, or hNotification event name NULL.
++ *  Requires:
++ *      NTFY_Init(void) called.
++ *      IsValid(hNtfy).
++ *      hNotification != NULL.
++ *      uNotifyType is DSP_SIGNALEVENT
++ *  Ensures:
++ */
++      extern DSP_STATUS NTFY_Register(IN struct NTFY_OBJECT *hNtfy,
++                                      IN struct DSP_NOTIFICATION
++                                      *hNotification,
++                                      IN u32 uEventMask,
++                                      IN u32 uNotifyType);
++
++#endif                                /* NTFY_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/proc.h b/arch/arm/plat-omap/include/dspbridge/proc.h
+new file mode 100644
+index 0000000..486652e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/proc.h
+@@ -0,0 +1,648 @@
++/*
++ * proc.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== proc.h ========
++ *  Description:
++ *    This is the Class driver RM module interface.
++ *
++ *  Public Functions:
++ *      PROC_Attach
++ *      PROC_Create
++ *      PROC_Ctrl            (OEM-function)
++ *      PROC_Destroy
++ *      PROC_Detach
++ *      PROC_EnumNodes
++ *      PROC_Exit
++ *      PROC_FlushMemory
++ *      PROC_GetDevObject       (OEM-function)
++ *      PROC_GetResourceInfo
++ *      PROC_GetState
++ *      PROC_GetProcessorId
++ *      PROC_GetTrace    (OEM-function)
++ *      PROC_Init
++ *      PROC_Load            (OEM-function)
++ *      PROC_Map
++ *      PROC_NotifyAllclients
++ *      PROC_NotifyClients      (OEM-function)
++ *      PROC_RegisterNotify
++ *      PROC_ReserveMemory
++ *      PROC_Start          (OEM-function)
++ *      PROC_UnMap
++ *      PROC_UnReserveMemory
++ *
++ *  Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb  Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb  Added the Dynamic Memory Mapping APIs
++ *! 09-Feb-2003 vp: Added PROC_GetProcessorID function
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 28-Sep-2000 rr: Updated to Version 0.9.
++ *! 10-Aug-2000 rr: PROC_NotifyClients, PROC_GetProcessorHandle Added
++ *! 27-Jul-2000 rr: Updated to ver 0.8 of DSPAPI(types). GetTrace added.
++ *! 27-Jun-2000 rr: Created from dspapi.h
++ */
++
++#ifndef PROC_
++#define PROC_
++
++#include <dspbridge/cfgdefs.h>
++#include <dspbridge/devdefs.h>
++
++/*
++ *  ======== PROC_Attach ========
++ *  Purpose:
++ *      Prepare for communication with a particular DSP processor, and return
++ *      a handle to the processor object. The PROC Object gets created
++ *  Parameters:
++ *      uProcessor  :    The processor index (zero-based).
++ *      hMgrObject  :    Handle to the Manager Object
++ *      pAttrIn     :    Ptr to the DSP_PROCESSORATTRIN structure.
++ *                          A NULL value means use default values.
++ *      phProcessor :    Ptr to location to store processor handle.
++ *  Returns:
++ *      DSP_SOK     :    Success.
++ *      DSP_EFAIL   :    General failure.
++ *      DSP_EHANDLE :    Invalid processor handle.
++ *      DSP_SALREADYATTACHED:   Success; Processor already attached.
++ *  Requires:
++ *      phProcessor != NULL.
++ *      PROC Initialized.
++ *  Ensures:
++ *      DSP_EFAIL, and *phProcessor == NULL, OR
++ *      Success and *phProcessor is a Valid Processor handle OR
++ *      DSP_SALREADYATTACHED and *phProcessor is a Valid Processor.
++ *  Details:
++ *      When pAttrIn is NULL, the default timeout value is 10 seconds.
++ */
++      extern DSP_STATUS PROC_Attach(u32 uProcessor,
++                                    OPTIONAL CONST struct DSP_PROCESSORATTRIN
++                                    *pAttrIn,
++                                    OUT DSP_HPROCESSOR *phProcessor);
++
++/*
++ *  ======== PROC_AutoStart =========
++ *  Purpose:
++ *      A Particular device gets loaded with the default image
++ *      if the AutoStart flag is set.
++ *  Parameters:
++ *      hDevObject  :   Handle to the Device
++ *  Returns:
++ *      DSP_SOK     :   On Successful Loading
++ *      DSP_EFILE   :   No DSP exec file found.
++ *      DSP_EFAIL   :   General Failure
++ *  Requires:
++ *      hDevObject != NULL.
++ *      hDevNode != NULL.
++ *      PROC Initialized.
++ *  Ensures:
++ */
++      extern DSP_STATUS PROC_AutoStart(struct CFG_DEVNODE *hDevNode,
++                                       struct DEV_OBJECT *hDevObject);
++
++/*
++ *  ======== PROC_Ctrl ========
++ *  Purpose:
++ *      Pass control information to the GPP device driver managing the DSP
++ *      processor. This will be an OEM-only function, and not part of the
++ *      'Bridge application developer's API.
++ *  Parameters:
++ *      hProcessor  :       The processor handle.
++ *      dwCmd       :       Private driver IOCTL cmd ID.
++ *      pArgs       :       Ptr to an driver defined argument structure.
++ *  Returns:
++ *      DSP_SOK     :       SUCCESS
++ *      DSP_EHANDLE :       Invalid processor handle.
++ *      DSP_ETIMEOUT:       A Timeout Occured before the Control information
++ *                      could be sent.
++ *      DSP_EACCESSDENIED:  Client does not have the access rights required
++ *                      to call this function.
++ *      DSP_ERESTART:       A Critical error has occured and the DSP is being
++ *                      restarted.
++ *      DSP_EFAIL   :       General Failure.
++ *  Requires:
++ *      PROC Initialized.
++ *  Ensures
++ *  Details:
++ *      This function Calls WMD_BRD_Ioctl.
++ */
++      extern DSP_STATUS PROC_Ctrl(DSP_HPROCESSOR hProcessor,
++                                  u32 dwCmd, IN struct DSP_CBDATA *pArgs);
++
++/*
++ *  ======== PROC_Detach ========
++ *  Purpose:
++ *      Close a DSP processor and de-allocate all (GPP) resources reserved
++ *      for it. The Processor Object is deleted.
++ *  Parameters:
++ *      hProcessor  :   The processor handle.
++ *  Returns:
++ *      DSP_SOK     :   Success.
++ *      DSP_EHANDLE :   InValid Handle.
++ *      DSP_EFAIL   :   General failure.
++ *  Requires:
++ *      PROC Initialized.
++ *  Ensures:
++ *      PROC Object is destroyed.
++ */
++      extern DSP_STATUS PROC_Detach(DSP_HPROCESSOR hProcessor);
++
++/*
++ *  ======== PROC_EnumNodes ========
++ *  Purpose:
++ *      Enumerate the nodes currently allocated on a processor.
++ *  Parameters:
++ *      hProcessor  :   The processor handle.
++ *      aNodeTab    :   The first Location of an array allocated for node
++ *                  handles.
++ *      uNodeTabSize:   The number of (DSP_HNODE) handles that can be held
++ *                  to the memory the client has allocated for aNodeTab
++ *      puNumNodes  :   Location where DSPProcessor_EnumNodes will return
++ *                  the number of valid handles written to aNodeTab
++ *      puAllocated :   Location where DSPProcessor_EnumNodes will return
++ *                  the number of nodes that are allocated on the DSP.
++ *  Returns:
++ *      DSP_SOK     :   Success.
++ *      DSP_EHANDLE :   Invalid processor handle.
++ *      DSP_ESIZE   :   The amount of memory allocated for aNodeTab is
++ *                  insufficent. That is the number of nodes actually
++ *                  allocated on the DSP is greater than the value
++ *                  specified for uNodeTabSize.
++ *      DSP_EFAIL   :   Unable to get Resource Information.
++ *  Details:
++ *  Requires
++ *      puNumNodes is not NULL.
++ *      puAllocated is not NULL.
++ *      aNodeTab is not NULL.
++ *      PROC Initialized.
++ *  Ensures:
++ *  Details:
++ */
++      extern DSP_STATUS PROC_EnumNodes(DSP_HPROCESSOR hProcessor,
++                                       IN DSP_HNODE *aNodeTab,
++                                       IN u32 uNodeTabSize,
++                                       OUT u32 *puNumNodes,
++                                       OUT u32 *puAllocated);
++
++/*
++ *  ======== PROC_GetResourceInfo ========
++ *  Purpose:
++ *      Enumerate the resources currently available on a processor.
++ *  Parameters:
++ *      hProcessor  :       The processor handle.
++ *      uResourceType:      Type of resource .
++ *      pResourceInfo:      Ptr to the DSP_RESOURCEINFO structure.
++ *      uResourceInfoSize:  Size of the structure.
++ *  Returns:
++ *      DSP_SOK     :       Success.
++ *      DSP_EHANDLE :       Invalid processor handle.
++ *      DSP_EWRONGSTATE:    The processor is not in the PROC_RUNNING state.
++ *      DSP_ETIMEOUT:       A timeout occured before the DSP responded to the
++ *                      querry.
++ *      DSP_ERESTART:       A Critical error has occured and the DSP is being
++ *                      restarted.
++ *      DSP_EFAIL   :       Unable to get Resource Information
++ *  Requires:
++ *      pResourceInfo is not NULL.
++ *      Parameter uResourceType is Valid.[TBD]
++ *      uResourceInfoSize is >= sizeof DSP_RESOURCEINFO struct.
++ *      PROC Initialized.
++ *  Ensures:
++ *  Details:
++ *      This function currently returns
++ *      DSP_ENOTIMPL, and does not write any data to the pResourceInfo struct.
++ */
++      extern DSP_STATUS PROC_GetResourceInfo(DSP_HPROCESSOR hProcessor,
++                                             u32 uResourceType,
++                                             OUT struct DSP_RESOURCEINFO *
++                                             pResourceInfo,
++                                             u32 uResourceInfoSize);
++
++/*
++ *  ======== PROC_Exit ========
++ *  Purpose:
++ *      Decrement reference count, and free resources when reference count is
++ *      0.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      PROC is initialized.
++ *  Ensures:
++ *      When reference count == 0, PROC's private resources are freed.
++ */
++       extern void PROC_Exit(void);
++
++/*
++ * ======== PROC_GetDevObject =========
++ *  Purpose:
++ *      Returns the DEV Hanlde for a given Processor handle
++ *  Parameters:
++ *      hProcessor  :   Processor Handle
++ *      phDevObject :   Location to store the DEV Handle.
++ *  Returns:
++ *      DSP_SOK     :   Success; *phDevObject has Dev handle
++ *      DSP_EFAIL   :   Failure; *phDevObject is zero.
++ *  Requires:
++ *      phDevObject is not NULL
++ *      PROC Initialized.
++ *  Ensures:
++ *      DSP_SOK     :   *phDevObject is not NULL
++ *      DSP_EFAIL   :   *phDevObject is NULL.
++ */
++      extern DSP_STATUS PROC_GetDevObject(DSP_HPROCESSOR hProcessor,
++                                          struct DEV_OBJECT **phDevObject);
++
++/*
++ *  ======== PROC_Init ========
++ *  Purpose:
++ *      Initialize PROC's private state, keeping a reference count on each
++ *      call.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialized; FALSE if error occured.
++ *  Requires:
++ *  Ensures:
++ *      TRUE: A requirement for the other public PROC functions.
++ */
++       extern bool PROC_Init(void);
++
++/*
++ *  ======== PROC_GetState ========
++ *  Purpose:
++ *      Report the state of the specified DSP processor.
++ *  Parameters:
++ *      hProcessor  :   The processor handle.
++ *      pProcStatus :   Ptr to location to store the DSP_PROCESSORSTATE
++ *                  structure.
++ *      uStateInfoSize: Size of DSP_PROCESSORSTATE.
++ *  Returns:
++ *      DSP_SOK     :   Success.
++ *      DSP_EHANDLE :   Invalid processor handle.
++ *      DSP_EFAIL   :   General failure while querying processor state.
++ *  Requires:
++ *      pProcStatus is not NULL
++ *      uStateInfoSize is >= than the size of DSP_PROCESSORSTATE structure.
++ *      PROC Initialized.
++ *  Ensures:
++ *  Details:
++ */
++      extern DSP_STATUS PROC_GetState(DSP_HPROCESSOR hProcessor,
++                                      OUT struct DSP_PROCESSORSTATE
++                                      *pProcStatus,
++                                      u32 uStateInfoSize);
++
++/*
++ *  ======== PROC_GetProcessorID ========
++ *  Purpose:
++ *      Report the state of the specified DSP processor.
++ *  Parameters:
++ *      hProcessor  :   The processor handle.
++ *      procID      :   Processor ID
++ *
++ *  Returns:
++ *      DSP_SOK     :   Success.
++ *      DSP_EHANDLE :   Invalid processor handle.
++ *      DSP_EFAIL   :   General failure while querying processor state.
++ *  Requires:
++ *      pProcStatus is not NULL
++ *      uStateInfoSize is >= than the size of DSP_PROCESSORSTATE structure.
++ *      PROC Initialized.
++ *  Ensures:
++ *  Details:
++ */
++      extern DSP_STATUS PROC_GetProcessorId(DSP_HPROCESSOR hProcessor,
++                                            u32 *procID);
++
++/*
++ *  ======== PROC_GetTrace ========
++ *  Purpose:
++ *      Retrieve the trace buffer from the specified DSP processor.
++ *  Parameters:
++ *      hProcessor  :   The processor handle.
++ *      pBuf  :   Ptr to buffer to hold trace output.
++ *      uMaxSize    :   Maximum size of the output buffer.
++ *  Returns:
++ *      DSP_SOK     :   Success.
++ *      DSP_EHANDLE :   Invalid processor handle.
++ *      DSP_EFAIL   :   General failure while retireving processor trace
++ *                  Buffer.
++ *  Requires:
++ *      pBuf is not NULL
++ *      uMaxSize is > 0.
++ *      PROC Initialized.
++ *  Ensures:
++ *  Details:
++ */
++      extern DSP_STATUS PROC_GetTrace(DSP_HPROCESSOR hProcessor, u8 *pBuf,
++                                      u32 uMaxSize);
++
++/*
++ *  ======== PROC_Load ========
++ *  Purpose:
++ *      Reset a processor and load a new base program image.
++ *      This will be an OEM-only function.
++ *  Parameters:
++ *      hProcessor  :       The processor handle.
++ *      iArgc       :       The number of Arguments(strings)in the aArgV[]
++ *      aArgv       :       An Array of Arguments(Unicode Strings)
++ *      aEnvp       :       An Array of Environment settings(Unicode Strings)
++ *  Returns:
++ *      DSP_SOK     :       Success.
++ *      DSP_EFILE   :       The DSP Execuetable was not found.
++ *      DSP_EHANDLE :       Invalid processor handle.
++ *      DSP_ECORRUTFILE:    Unable to Parse the DSP Execuetable
++ *      DSP_EATTACHED:      Abort because a GPP Client is attached to the
++ *                      specified Processor
++ *      DSP_EACCESSDENIED:  Client does not have the required access rights
++ *                      to reset and load the Processor
++ *      DSP_EFAIL   :       Unable to Load the Processor
++ *  Requires:
++ *      aArgv is not NULL
++ *      iArgc is > 0
++ *      PROC Initialized.
++ *  Ensures:
++ *      Success and ProcState == PROC_LOADED
++ *      or DSP_FAILED status.
++ *  Details:
++ *      Does not implement access rights to control which GPP application
++ *      can load the processor.
++ */
++      extern DSP_STATUS PROC_Load(DSP_HPROCESSOR hProcessor,
++                                  IN CONST s32 iArgc, IN CONST char **aArgv,
++                                  IN CONST char **aEnvp);
++
++/*
++ *  ======== PROC_RegisterNotify ========
++ *  Purpose:
++ *      Register to be notified of specific processor events
++ *  Parameters:
++ *      hProcessor  :   The processor handle.
++ *      uEventMask  :   Mask of types of events to be notified about.
++ *      uNotifyType :   Type of notification to be sent.
++ *      hNotification:  Handle to be used for notification.
++ *  Returns:
++ *      DSP_SOK     :   Success.
++ *      DSP_EHANDLE :   Invalid processor handle or hNotification.
++ *      DSP_EVALUE  :   Parameter uEventMask is Invalid
++ *      DSP_ENOTIMP :   The notification type specified in uNotifyMask
++ *                  is not supported.
++ *      DSP_EFAIL   :   Unable to register for notification.
++ *  Requires:
++ *      hNotification is not NULL
++ *      PROC Initialized.
++ *  Ensures:
++ *  Details:
++ */
++      extern DSP_STATUS PROC_RegisterNotify(DSP_HPROCESSOR hProcessor,
++                                            u32 uEventMask, u32 uNotifyType,
++                                            struct DSP_NOTIFICATION
++                                            *hNotification);
++
++/*
++ *  ======== PROC_NotifyClients ========
++ *  Purpose:
++ *      Notify the Processor Clients
++ *  Parameters:
++ *      hProc       :   The processor handle.
++ *      uEvents     :   Event to be notified about.
++ *  Returns:
++ *      DSP_SOK     :   Success.
++ *      DSP_EHANDLE :   Invalid processor handle.
++ *      DSP_EFAIL   :   Failure to Set or Reset the Event
++ *  Requires:
++ *      uEvents is Supported or Valid type of Event
++ *      hProc is a valid handle
++ *      PROC Initialized.
++ *  Ensures:
++ */
++      extern DSP_STATUS PROC_NotifyClients(DSP_HPROCESSOR hProc,
++                                           u32 uEvents);
++
++/*
++ *  ======== PROC_NotifyAllClients ========
++ *  Purpose:
++ *      Notify the Processor Clients
++ *  Parameters:
++ *      hProc       :   The processor handle.
++ *      uEvents     :   Event to be notified about.
++ *  Returns:
++ *      DSP_SOK     :   Success.
++ *      DSP_EHANDLE :   Invalid processor handle.
++ *      DSP_EFAIL   :   Failure to Set or Reset the Event
++ *  Requires:
++ *      uEvents is Supported or Valid type of Event
++ *      hProc is a valid handle
++ *      PROC Initialized.
++ *  Ensures:
++ *  Details:
++ *      NODE And STRM would use this function to notify their clients
++ *      about the state changes in NODE or STRM.
++ */
++      extern DSP_STATUS PROC_NotifyAllClients(DSP_HPROCESSOR hProc,
++                                              u32 uEvents);
++
++/*
++ *  ======== PROC_Start ========
++ *  Purpose:
++ *      Start a processor running.
++ *      Processor must be in PROC_LOADED state.
++ *      This will be an OEM-only function, and not part of the 'Bridge
++ *      application developer's API.
++ *  Parameters:
++ *      hProcessor  :       The processor handle.
++ *  Returns:
++ *      DSP_SOK     :       Success.
++ *      DSP_EHANDLE :       Invalid processor handle.
++ *      DSP_EWRONGSTATE:    Processor is not in PROC_LOADED state.
++ *      DSP_EFAIL   :       Unable to start the processor.
++ *  Requires:
++ *      PROC Initialized.
++ *  Ensures:
++ *      Success and ProcState == PROC_RUNNING or DSP_FAILED status.
++ *  Details:
++ */
++      extern DSP_STATUS PROC_Start(DSP_HPROCESSOR hProcessor);
++
++/*
++ *  ======== PROC_Stop ========
++ *  Purpose:
++ *      Start a processor running.
++ *      Processor must be in PROC_LOADED state.
++ *      This will be an OEM-only function, and not part of the 'Bridge
++ *      application developer's API.
++ *  Parameters:
++ *      hProcessor  :       The processor handle.
++ *  Returns:
++ *      DSP_SOK     :       Success.
++ *      DSP_EHANDLE :       Invalid processor handle.
++ *      DSP_EWRONGSTATE:    Processor is not in PROC_LOADED state.
++ *      DSP_EFAIL   :       Unable to start the processor.
++ *  Requires:
++ *      PROC Initialized.
++ *  Ensures:
++ *      Success and ProcState == PROC_RUNNING or DSP_FAILED status.
++ *  Details:
++ */
++      extern DSP_STATUS PROC_Stop(DSP_HPROCESSOR hProcessor);
++
++/*
++ *  ======== PROC_FlushMemory ========
++ *  Purpose:
++ *      Flushes a buffer from the MPU data cache.
++ *  Parameters:
++ *      hProcessor      :   The processor handle.
++ *      pMpuAddr      :   Buffer start address
++ *      ulSize          :   Buffer size
++ *      ulFlags        :   Reserved.
++ *  Returns:
++ *      DSP_SOK        :   Success.
++ *      DSP_EHANDLE     :   Invalid processor handle.
++ *      DSP_EFAIL       :   General failure.
++ *  Requires:
++ *      PROC Initialized.
++ *  Ensures:
++ *  Details:
++ *      All the arguments are currently ignored.
++ */
++      extern DSP_STATUS PROC_FlushMemory(DSP_HPROCESSOR hProcessor,
++                                         void *pMpuAddr,
++                                         u32 ulSize, u32 ulFlags);
++
++
++/*
++ *  ======== PROC_InvalidateMemory ========
++ *  Purpose:
++ *      Invalidates a buffer from the MPU data cache.
++ *  Parameters:
++ *      hProcessor      :   The processor handle.
++ *      pMpuAddr      :   Buffer start address
++ *      ulSize          :   Buffer size
++ *  Returns:
++ *      DSP_SOK        :   Success.
++ *      DSP_EHANDLE     :   Invalid processor handle.
++ *      DSP_EFAIL       :   General failure.
++ *  Requires:
++ *      PROC Initialized.
++ *  Ensures:
++ *  Details:
++ *      All the arguments are currently ignored.
++ */
++      extern DSP_STATUS PROC_InvalidateMemory(DSP_HPROCESSOR hProcessor,
++                                         void *pMpuAddr,
++                                         u32 ulSize);
++
++/*
++ *  ======== PROC_Map ========
++ *  Purpose:
++ *      Maps a MPU buffer to DSP address space.
++ *  Parameters:
++ *      hProcessor      :   The processor handle.
++ *      pMpuAddr      :   Starting address of the memory region to map.
++ *      ulSize          :   Size of the memory region to map.
++ *      pReqAddr      :   Requested DSP start address. Offset-adjusted actual
++ *                      mapped address is in the last argument.
++ *      ppMapAddr       :   Ptr to DSP side mapped u8 address.
++ *      ulMapAttr       :   Optional endianness attributes, virt to phys flag.
++ *  Returns:
++ *      DSP_SOK        :   Success.
++ *      DSP_EHANDLE     :   Invalid processor handle.
++ *      DSP_EFAIL       :   General failure.
++ *      DSP_EMEMORY     :   MPU side memory allocation error.
++ *      DSP_ENOTFOUND   :   Cannot find a reserved region starting with this
++ *                  :   address.
++ *  Requires:
++ *      pMpuAddr is not NULL
++ *      ulSize is not zero
++ *      ppMapAddr is not NULL
++ *      PROC Initialized.
++ *  Ensures:
++ *  Details:
++ */
++      extern DSP_STATUS PROC_Map(DSP_HPROCESSOR hProcessor,
++                                 void *pMpuAddr,
++                                 u32 ulSize,
++                                 void *pReqAddr,
++                                 void **ppMapAddr, u32 ulMapAttr);
++
++/*
++ *  ======== PROC_ReserveMemory ========
++ *  Purpose:
++ *      Reserve a virtually contiguous region of DSP address space.
++ *  Parameters:
++ *      hProcessor      :   The processor handle.
++ *      ulSize          :   Size of the address space to reserve.
++ *      ppRsvAddr       :   Ptr to DSP side reserved u8 address.
++ *  Returns:
++ *      DSP_SOK        :   Success.
++ *      DSP_EHANDLE     :   Invalid processor handle.
++ *      DSP_EFAIL       :   General failure.
++ *      DSP_EMEMORY     :   Cannot reserve chunk of this size.
++ *  Requires:
++ *      ppRsvAddr is not NULL
++ *      PROC Initialized.
++ *  Ensures:
++ *  Details:
++ */
++      extern DSP_STATUS PROC_ReserveMemory(DSP_HPROCESSOR hProcessor,
++                                           u32 ulSize, void **ppRsvAddr);
++
++/*
++ *  ======== PROC_UnMap ========
++ *  Purpose:
++ *      Removes a MPU buffer mapping from the DSP address space.
++ *  Parameters:
++ *      hProcessor      :   The processor handle.
++ *      pMapAddr      :   Starting address of the mapped memory region.
++ *  Returns:
++ *      DSP_SOK        :   Success.
++ *      DSP_EHANDLE     :   Invalid processor handle.
++ *      DSP_EFAIL       :   General failure.
++ *      DSP_ENOTFOUND   :   Cannot find a mapped region starting with this
++ *                  :   address.
++ *  Requires:
++ *      pMapAddr is not NULL
++ *      PROC Initialized.
++ *  Ensures:
++ *  Details:
++ */
++      extern DSP_STATUS PROC_UnMap(DSP_HPROCESSOR hProcessor, void *pMapAddr);
++
++/*
++ *  ======== PROC_UnReserveMemory ========
++ *  Purpose:
++ *      Frees a previously reserved region of DSP address space.
++ *  Parameters:
++ *      hProcessor      :   The processor handle.
++ *      pRsvAddr      :   Ptr to DSP side reservedBYTE address.
++ *  Returns:
++ *      DSP_SOK        :   Success.
++ *      DSP_EHANDLE     :   Invalid processor handle.
++ *      DSP_EFAIL       :   General failure.
++ *      DSP_ENOTFOUND   :   Cannot find a reserved region starting with this
++ *                  :   address.
++ *  Requires:
++ *      pRsvAddr is not NULL
++ *      PROC Initialized.
++ *  Ensures:
++ *  Details:
++ */
++      extern DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor,
++                                             void *pRsvAddr);
++
++#endif                                /* PROC_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/procpriv.h b/arch/arm/plat-omap/include/dspbridge/procpriv.h
+new file mode 100644
+index 0000000..21d4b3e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/procpriv.h
+@@ -0,0 +1,35 @@
++/*
++ * procpriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== procpriv.h ========
++ *  Description:
++ *      Global PROC constants and types, shared by PROC, MGR, and WCD.
++ *
++ *! Revision History:
++ *! ================
++ *! 05-July-2000 rr: Created
++ */
++
++#ifndef PROCPRIV_
++#define PROCPRIV_
++
++/* RM PROC Object */
++      struct PROC_OBJECT;
++
++#endif                                /* PROCPRIV_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/pwr.h b/arch/arm/plat-omap/include/dspbridge/pwr.h
+new file mode 100644
+index 0000000..a6645ca
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/pwr.h
+@@ -0,0 +1,129 @@
++/*
++ * pwr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== pwr.h ========
++ *
++ *  Public Functions:
++ *
++ *      PWR_SleepDSP
++ *      PWR_WakeDSP
++ *
++ *  Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 06-Jun-2002 sg  Replaced dspdefs.h with includes of dbdefs.h and errbase.h.
++ *! 13-May-2002 sg  Added DSP_SAREADYASLEEP and DSP_SALREADYAWAKE.
++ *! 09-May-2002 sg  Updated, added timeouts.
++ *! 02-May-2002 sg  Initial.
++ */
++
++#ifndef PWR_
++#define PWR_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/pwr_sh.h>
++
++/*
++ *  ======== PWR_SleepDSP ========
++ *      Signal the DSP to go to sleep.
++ *
++ *  Parameters:
++ *      sleepCode:          New sleep state for DSP.  (Initially, valid codes
++ *                          are PWR_DEEPSLEEP or PWR_EMERGENCYDEEPSLEEP; both of
++ *                          these codes will simply put the DSP in deep sleep.)
++ *
++ *    timeout:            Maximum time (msec) that PWR should wait for
++ *                          confirmation that the DSP sleep state has been
++ *                          reached.  If PWR should simply send the command to
++ *                          the DSP to go to sleep and then return (i.e.,
++ *                          asynchrounous sleep), the timeout should be
++ *                          specified as zero.
++ *
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_SALREADYASLEEP: Success, but the DSP was already asleep.
++ *      DSP_EINVALIDARG:    The specified sleepCode is not supported.
++ *      DSP_ETIMEOUT:       A timeout occured while waiting for DSP sleep
++ *                          confirmation.
++ *      DSP_EFAIL:          General failure, unable to send sleep command to
++ *                          the DSP.
++ */
++      extern DSP_STATUS PWR_SleepDSP(IN CONST u32 sleepCode,
++                                     IN CONST u32 timeout);
++
++/*
++ *  ======== PWR_WakeDSP ========
++ *    Signal the DSP to wake from sleep.
++ *
++ *  Parameters:
++ *    timeout:            Maximum time (msec) that PWR should wait for
++ *                          confirmation that the DSP is awake.  If PWR should
++ *                          simply send a command to the DSP to wake and then
++ *                          return (i.e., asynchrounous wake), timeout should
++ *                          be specified as zero.
++ *
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_SALREADYAWAKE:  Success, but the DSP was already awake.
++ *      DSP_ETIMEOUT:       A timeout occured while waiting for wake
++ *                          confirmation.
++ *      DSP_EFAIL:          General failure, unable to send wake command to
++ *                          the DSP.
++ */
++      extern DSP_STATUS PWR_WakeDSP(IN CONST u32 timeout);
++
++/*
++ *  ======== PWR_PM_PreScale ========
++ *    Prescale notification to DSP.
++ *
++ *  Parameters:
++ *    voltage_domain:   The voltage domain for which notification is sent
++ *    level:                  The level of voltage domain
++ *
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_SALREADYAWAKE:  Success, but the DSP was already awake.
++ *      DSP_ETIMEOUT:       A timeout occured while waiting for wake
++ *                          confirmation.
++ *      DSP_EFAIL:          General failure, unable to send wake command to
++ *                          the DSP.
++ */
++      extern DSP_STATUS PWR_PM_PreScale(IN u16 voltage_domain, u32 level);
++
++/*
++ *  ======== PWR_PM_PostScale ========
++ *    PostScale notification to DSP.
++ *
++ *  Parameters:
++ *    voltage_domain:   The voltage domain for which notification is sent
++ *    level:                  The level of voltage domain
++ *
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_SALREADYAWAKE:  Success, but the DSP was already awake.
++ *      DSP_ETIMEOUT:       A timeout occured while waiting for wake
++ *                          confirmation.
++ *      DSP_EFAIL:          General failure, unable to send wake command to
++ *                          the DSP.
++ */
++      extern DSP_STATUS PWR_PM_PostScale(IN u16 voltage_domain,
++                                         u32 level);
++
++#endif                                /* PWR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/pwr_sh.h b/arch/arm/plat-omap/include/dspbridge/pwr_sh.h
+new file mode 100644
+index 0000000..40f1b84
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/pwr_sh.h
+@@ -0,0 +1,41 @@
++/*
++ * pwr_sh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== pwr_sh.h ========
++ *
++ *  Power Manager shared definitions (used on both GPP and DSP sides).
++ *
++ *! Revision History
++ *! ================
++ *! 17-Apr-2002 sg: Initial.
++ */
++
++#ifndef PWR_SH_
++#define PWR_SH_
++
++#include <dspbridge/mbx_sh.h>
++
++/* valid sleep command codes that can be sent by GPP via mailbox: */
++#define PWR_DEEPSLEEP           MBX_PM_DSPIDLE
++#define PWR_EMERGENCYDEEPSLEEP  MBX_PM_EMERGENCYSLEEP
++#define PWR_SLEEPUNTILRESTART   MBX_PM_SLEEPUNTILRESTART
++#define PWR_WAKEUP              MBX_PM_DSPWAKEUP
++#define PWR_AUTOENABLE          MBX_PM_PWRENABLE
++#define PWR_AUTODISABLE         MBX_PM_PWRDISABLE
++#define PWR_RETENTION             MBX_PM_DSPRETN
++
++#endif                                /* PWR_SH_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/reg.h b/arch/arm/plat-omap/include/dspbridge/reg.h
+new file mode 100644
+index 0000000..5b34952
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/reg.h
+@@ -0,0 +1,257 @@
++/*
++ * reg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== reg.h ========
++ *  Purpose:
++ *      Provide registry functions.
++ *
++ *  Public Functions:
++ *      REG_DeleteValue
++ *      REG_EnumKey
++ *      REG_EnumValue
++ *      REG_Exit
++ *      REG_GetValue
++ *      REG_Init
++ *      REG_SetValue
++ *
++ *! Revision History:
++ *! =================
++ *! 30-Oct-2000 kc: Updated REG_SetValue & REG_GetValue; renamed
++ *!                 REG_DeleteEntry to REG_DeleteValue.
++ *! 29-Sep-2000 kc: Updated a REG functions for code review.
++ *! 12-Aug-2000 kc: Renamed REG_EnumValue to REG_EnumKey. Re-implemented
++ *!                 REG_EnumValue.
++ *! 03-Feb-2000 rr: REG_EnumValue Fxn Added
++ *! 13-Dec-1999 rr: windows.h removed
++ *! 02-Dec-1999 rr: windows.h included for retail build
++ *! 22-Nov-1999 kc: Changes from code review.
++ *! 29-Dec-1997 cr: Changes from code review.
++ *! 27-Oct-1997 cr: Added REG_DeleteValue.
++ *! 20-Oct-1997 cr: Added ability to pass bValue = NULL to REG_GetValue
++ *!                 and return size of reg entry in pdwValueSize.
++ *! 29-Sep-1997 cr: Added REG_SetValue
++ *! 29-Aug-1997 cr: Created.
++ */
++
++#ifndef _REG_H
++#define _REG_H
++
++#include <linux/types.h>
++
++/*  ------------------------- Defines, Data Structures, Typedefs for Linux */
++#ifndef UNDER_CE
++
++#ifndef REG_SZ
++#define REG_SZ          1
++#endif
++
++#ifndef REG_BINARY
++#define REG_BINARY      3
++#endif
++
++#ifndef REG_DWORD
++#define REG_DWORD       4
++#endif
++
++#endif                                /* UNDER_CE */
++
++#define REG_MAXREGPATHLENGTH    255
++
++/*
++ *  ======== REG_DeleteValue ========
++ *  Purpose:
++ *      Deletes a registry entry. NOTE: A registry entry is not the same as
++ *      a registry key.
++ *  Parameters:
++ *      phKey:      Currently reserved; must be NULL.
++ *      pstrSubkey: Path to key to open.
++ *      pstrValue:  Name of entry to delete.
++ *  Returns:
++ *      DSP_SOK:    Success.
++ *      DSP_EFAIL:  General failure.
++ *  Requires:
++ *      - REG initialized.
++ *      - pstrSubkey & pstrValue are non-NULL values.
++ *      - phKey is NULL.
++ *      - length of pstrSubkey < REG_MAXREGPATHLENGTH.
++ *      - length of pstrValue < REG_MAXREGPATHLENGTH.
++ *  Ensures:
++ *  Details:
++ */
++      extern DSP_STATUS REG_DeleteValue(OPTIONAL IN HANDLE *phKey,
++                                        IN CONST char *pstrSubkey,
++                                        IN CONST char *pstrValue);
++
++/*
++ *  ======== REG_EnumKey ========
++ *  Purpose:
++ *      Enumerates subkeys of the specified path to the  registry key
++ *      Retrieves the  name of the subkey(given the index) and
++ *      appends with the orignal path to form the full path.
++ *  Parameters:
++ *      phKey:      Currently reserved; must be NULL.
++ *      pstrKey     The name of the registry key to be enumerated.
++ *      dwIndex     Specifies the index of the subkey to retrieve.
++ *      pstrSubkey: Pointer to buffer that receives full path name of the
++ *                  specified key + the sub-key
++ *      pdwValueSize:   Specifies bytes of memory pstrSubkey points to on input,
++ *                      on output, specifies actual memory bytes written into.
++ *                      If there is no sub key,pdwValueSize returns NULL.
++ *  Returns:
++ *      DSP_SOK:    Success.
++ *      DSP_EFAIL:  General failure.
++ *  Requires:
++ *      - REG initialized.
++ *      - pstrKey is non-NULL value.
++ *      - pdwValueSize is a valid pointer.
++ *      - phKey is NULL.
++ *      - length of pstrKey < REG_MAXREGPATHLENGTH.
++ *  Ensures:
++ *      - strlen(pstrSubkey) is > strlen(pstrKey) &&
++ *      - strlen(pstrSubkey) is < REG_MAXREGPATHLENGTH
++ */
++      extern DSP_STATUS REG_EnumKey(OPTIONAL IN HANDLE *phKey,
++                                    IN u32 dwIndex, IN CONST char *pstrKey,
++                                    IN OUT char *pstrSubkey,
++                                    IN OUT u32 *pdwValueSize);
++
++/*
++ *  ======== REG_EnumValue ========
++ *  Purpose:
++ *      Enumerates values of a specified key. Retrieves each value name and
++ *      the data associated with the value.
++ *  Parameters:
++ *      phKey:          Currently reserved; must be NULL.
++ *      dwIndex:        Specifies the index of the value to retrieve.
++ *      pstrKey:        The name of the registry key to be enumerated.
++ *      pstrValue:      Pointer to buffer that receives the name of the value.
++ *      pdwValueSize:   Specifies bytes of memory pstrValue points to on input,
++ *                      On output, specifies actual memory bytes written into.
++ *                      If there is no value, pdwValueSize returns NULL
++ *      pstrData:       Pointer to buffer that receives the data of a value.
++ *      pdwDataSize:    Specifies bytes of memory in pstrData on input and
++ *                      bytes of memory written into pstrData on output.
++ *                      If there is no data, pdwDataSize returns NULL.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      General failure.
++ *  Requires:
++ *      REG initialized.
++ *      phKey is NULL.
++ *      pstrKey is a non-NULL value.
++ *      pstrValue, pstrData, pdwValueSize and pdwDataSize are valid pointers.
++ *      Length of pstrKey is less than REG_MAXREGPATHLENGTH.
++ *  Ensures:
++ */
++      extern DSP_STATUS REG_EnumValue(IN HANDLE *phKey,
++                                      IN u32 dwIndex,
++                                      IN CONST char *pstrKey,
++                                      IN OUT char *pstrValue,
++                                      IN OUT u32 *pdwValueSize,
++                                      IN OUT char *pstrData,
++                                      IN OUT u32 *pdwDataSize);
++
++/*
++ *  ======== REG_Exit ========
++ *  Purpose:
++ *      Discontinue usage of module; free resources when reference count
++ *      reaches 0.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      REG initialized.
++ *  Ensures:
++ *      Resources used by module are freed when cRef reaches zero.
++ */
++      extern void REG_Exit(void);
++
++/*
++ *  ======== REG_GetValue ========
++ *  Purpose:
++ *      Retrieve a value from the registry.
++ *  Parameters:
++ *      phKey:          Currently reserved; must be NULL.
++ *      pstrSubkey:     Path to key to open.
++ *      pstrEntry:      Name of entry to retrieve.
++ *      pbValue:        Upon return, points to retrieved value.
++ *      pdwValueSize:   Specifies bytes of memory pbValue points to on input,
++ *                      on output, specifies actual memory bytes written into.
++ *                      If pbValue is NULL, pdwValueSize reports the size of
++ *                      the entry in pstrEntry.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      General failure.
++ *  Requires:
++ *      - REG initialized.
++ *      - pstrSubkey & pstrEntry are non-NULL values.
++ *      - pbValue is a valid pointer.
++ *      - phKey is NULL.
++ *      - length of pstrSubkey < REG_MAXREGPATHLENGTH.
++ *      - length of pstrEntry < REG_MAXREGPATHLENGTH.
++ *  Ensures:
++ */
++      extern DSP_STATUS REG_GetValue(OPTIONAL IN HANDLE *phKey,
++                                     IN CONST char *pstrSubkey,
++                                     IN CONST char *pstrEntry,
++                                     OUT u8 *pbValue,
++                                     IN OUT u32 *pdwValueSize);
++
++/*
++ *  ======== REG_Init ========
++ *  Purpose:
++ *      Initializes private state of REG module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialized; FALSE if error occured.
++ *  Requires:
++ *  Ensures:
++ *      REG initialized.
++ */
++      extern bool REG_Init(void);
++
++/*
++ *  ======== REG_SetValue ========
++ *  Purpose:
++ *      Set a value in the registry.
++ *  Parameters:
++ *      phKey:          Handle to open reg key, or NULL if pSubkey is full path.
++ *      pstrSubkey:     Path to key to open, could be based on phKey.
++ *      pstrEntry:      Name of entry to set.
++ *      dwType:         Data type of new registry value.
++ *      pbValue:        Points to buffer containing new data.
++ *      dwValueSize:    Specifies bytes of memory bValue points to.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      General failure.
++ *  Requires:
++ *      - REG initialized.
++ *      - pstrSubkey & pstrEntry are non-NULL values.
++ *      - pbValue is a valid pointer.
++ *      - phKey is NULL.
++ *      - dwValuSize > 0.
++ *      - length of pstrSubkey < REG_MAXREGPATHLENGTH.
++ *      - length of pstrEntry < REG_MAXREGPATHLENGTH.
++ *  Ensures:
++ */
++      extern DSP_STATUS REG_SetValue(OPTIONAL IN HANDLE *phKey,
++                                     IN CONST char *pstrSubKey,
++                                     IN CONST char *pstrEntry,
++                                     IN CONST u32 dwType,
++                                     IN u8 *pbValue, IN u32 dwValueSize);
++
++#endif                                /* _REG_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h b/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
+new file mode 100644
+index 0000000..b43fa16
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
+@@ -0,0 +1,88 @@
++/*
++ * resourcecleanup.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef RES_CLEANUP_DISABLE
++
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/drv.h>
++
++
++extern DSP_STATUS DRV_GetProcCtxtList(struct PROCESS_CONTEXT **pPctxt,
++                              struct DRV_OBJECT *hDrvObject);
++
++extern DSP_STATUS DRV_InsertProcContext(struct DRV_OBJECT *hDrVObject,
++                                      HANDLE hPCtxt);
++
++extern DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE pCtxt);
++
++extern DSP_STATUS DRV_RemoveAllNodeResElements(HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcUpdatestate(HANDLE pCtxt,
++                                    enum GPP_PROC_RES_STATE resState);
++
++extern DSP_STATUS DRV_ProcSetPID(HANDLE pCtxt, s32 hProcess);
++
++extern DSP_STATUS DRV_GetProcContext(u32 phProcess,
++                              struct DRV_OBJECT *hDrvObject,
++                              HANDLE hPCtxt, DSP_HNODE hNode,
++                              u32 pMapAddr);
++
++extern DSP_STATUS DRV_RemoveAllResources(HANDLE pPctxt);
++
++extern DSP_STATUS DRV_RemoveProcContext(struct DRV_OBJECT *hDRVObject,
++                                   HANDLE hPCtxt, HANDLE hProcess);
++
++extern DSP_STATUS DRV_GetNodeResElement(HANDLE hNode, HANDLE nodeRes,
++                                      HANDLE pCtxt);
++
++extern DSP_STATUS DRV_InsertNodeResElement(HANDLE hNode, HANDLE nodeRes,
++                                          HANDLE pCtxt);
++
++extern void DRV_ProcNodeUpdateHeapStatus(HANDLE hNodeRes, s32 status);
++
++extern DSP_STATUS DRV_RemoveNodeResElement(HANDLE nodeRes, HANDLE status);
++
++extern void DRV_ProcNodeUpdateStatus(HANDLE hNodeRes, s32 status);
++
++extern DSP_STATUS DRV_UpdateDMMResElement(HANDLE dmmRes, u32 pMpuAddr,
++                                        u32 ulSize, u32 pReqAddr,
++                                        u32 ppMapAddr, HANDLE hProcesso);
++
++extern DSP_STATUS DRV_InsertDMMResElement(HANDLE dmmRes, HANDLE pCtxt);
++
++extern DSP_STATUS DRV_GetDMMResElement(u32 pMapAddr, HANDLE dmmRes,
++                                     HANDLE pCtxt);
++
++extern DSP_STATUS DRV_RemoveDMMResElement(HANDLE dmmRes, HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcUpdateSTRMRes(u32 uNumBufs, HANDLE STRMRes,
++                                      HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcInsertSTRMResElement(HANDLE hStrm, HANDLE STRMRes,
++                                              HANDLE pPctxt);
++
++extern DSP_STATUS DRV_GetSTRMResElement(HANDLE hStrm, HANDLE STRMRes,
++                                      HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcRemoveSTRMResElement(HANDLE STRMRes, HANDLE pCtxt);
++
++extern DSP_STATUS DRV_RemoveAllSTRMResElements(HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcDisplayResInfo(u8 *pBuf, u32 *pSize);
++
++extern enum NODE_STATE NODE_GetState(HANDLE hNode);
++
++#endif
+diff --git a/arch/arm/plat-omap/include/dspbridge/rmm.h b/arch/arm/plat-omap/include/dspbridge/rmm.h
+new file mode 100644
+index 0000000..5b14b8f
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/rmm.h
+@@ -0,0 +1,199 @@
++/*
++ * rmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== rmm.h ========
++ *
++ *  This memory manager provides general heap management and arbitrary
++ *  alignment for any number of memory segments, and management of overlay
++ *  memory.
++ *
++ *  Public functions:
++ *      RMM_alloc
++ *      RMM_create
++ *      RMM_delete
++ *      RMM_exit
++ *      RMM_free
++ *      RMM_init
++ *
++ *! Revision History
++ *! ================
++ *! 25-Jun-2002 jeh     Added RMM_Addr. Removed RMM_reserve, RMM_stat.
++ *! 15-Oct-2001 jeh     Based on rm.h in gen tree.
++ */
++
++#ifndef RMM_
++#define RMM_
++
++/*
++ *  ======== RMM_Addr ========
++ *  DSP address + segid
++ */
++struct RMM_Addr {
++      u32 addr;
++      s32 segid;
++} ;
++
++/*
++ *  ======== RMM_Segment ========
++ *  Memory segment on the DSP available for remote allocations.
++ */
++struct RMM_Segment {
++      u32 base;               /* Base of the segment */
++      u32 length;             /* Size of the segment (target MAUs) */
++      s32 space;              /* Code or data */
++      u32 number;             /* Number of Allocated Blocks */
++} ;
++
++/*
++ *  ======== RMM_Target ========
++ */
++struct RMM_TargetObj;
++
++/*
++ *  ======== RMM_alloc ========
++ *
++ *  RMM_alloc is used to remotely allocate or reserve memory on the DSP.
++ *
++ *  Parameters:
++ *      target          - Target returned from RMM_create().
++ *      segid           - Memory segment to allocate from.
++ *      size            - Size (target MAUS) to allocate.
++ *      align           - alignment.
++ *      dspAddr         - If reserve is FALSE, the location to store allocated
++ *                        address on output, otherwise, the DSP address to
++ *                        reserve.
++ *      reserve         - If TRUE, reserve the memory specified by dspAddr.
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      DSP_EMEMORY:            Memory allocation on GPP failed.
++ *      DSP_EOVERLAYMEMORY:     Cannot "allocate" overlay memory because it's
++ *                              already in use.
++ *  Requires:
++ *      RMM initialized.
++ *      Valid target.
++ *      dspAddr != NULL.
++ *      size > 0
++ *      reserve || target->numSegs > 0.
++ *  Ensures:
++ */
++extern DSP_STATUS RMM_alloc(struct RMM_TargetObj *target, u32 segid, u32 size,
++                          u32 align, u32 *dspAdr, bool reserve);
++
++/*
++ *  ======== RMM_create ========
++ *  Create a target object with memory segments for remote allocation. If
++ *  segTab == NULL or numSegs == 0, memory can only be reserved through
++ *  RMM_alloc().
++ *
++ *  Parameters:
++ *      pTarget:        - Location to store target on output.
++ *      segTab:         - Table of memory segments.
++ *      numSegs:        - Number of memory segments.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Memory allocation failed.
++ *  Requires:
++ *      RMM initialized.
++ *      pTarget != NULL.
++ *      numSegs == 0 || segTab != NULL.
++ *  Ensures:
++ *      Success:        Valid *pTarget.
++ *      Failure:        *pTarget == NULL.
++ */
++extern DSP_STATUS RMM_create(struct RMM_TargetObj **pTarget,
++                           struct RMM_Segment segTab[], u32 numSegs);
++
++/*
++ *  ======== RMM_delete ========
++ *  Delete target allocated in RMM_create().
++ *
++ *  Parameters:
++ *      target          - Target returned from RMM_create().
++ *  Returns:
++ *  Requires:
++ *      RMM initialized.
++ *      Valid target.
++ *  Ensures:
++ */
++extern void RMM_delete(struct RMM_TargetObj *target);
++
++/*
++ *  ======== RMM_exit ========
++ *  Exit the RMM module
++ *
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      RMM_init successfully called.
++ *  Ensures:
++ */
++extern void RMM_exit(void);
++
++/*
++ *  ======== RMM_free ========
++ *  Free or unreserve memory allocated through RMM_alloc().
++ *
++ *  Parameters:
++ *      target:         - Target returned from RMM_create().
++ *      segid:          - Segment of memory to free.
++ *      dspAddr:        - Address to free or unreserve.
++ *      size:           - Size of memory to free or unreserve.
++ *      reserved:       - TRUE if memory was reserved only, otherwise FALSE.
++ *  Returns:
++ *  Requires:
++ *      RMM initialized.
++ *      Valid target.
++ *      reserved || segid < target->numSegs.
++ *      reserve || [dspAddr, dspAddr + size] is a valid memory range.
++ *  Ensures:
++ */
++extern bool RMM_free(struct RMM_TargetObj *target, u32 segid, u32 dspAddr,
++                   u32 size, bool reserved);
++
++/*
++ *  ======== RMM_init ========
++ *  Initialize the RMM module
++ *
++ *  Parameters:
++ *  Returns:
++ *      TRUE:   Success.
++ *      FALSE:  Failure.
++ *  Requires:
++ *  Ensures:
++ */
++extern bool RMM_init(void);
++
++/*
++ *  ======== RMM_stat ========
++ *  Obtain  memory segment status
++ *
++ *  Parameters:
++ *      segid:       Segment ID of the dynamic loading segment.
++ *      pMemStatBuf: Pointer to allocated buffer into which memory stats are
++ *                   placed.
++ *  Returns:
++ *      TRUE:   Success.
++ *      FALSE:  Failure.
++ *  Requires:
++ *      segid < target->numSegs
++ *  Ensures:
++ */
++extern bool RMM_stat(struct RMM_TargetObj *target, enum DSP_MEMTYPE segid,
++                   struct DSP_MEMSTAT *pMemStatBuf);
++
++#endif                                /* RMM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/rms_sh.h b/arch/arm/plat-omap/include/dspbridge/rms_sh.h
+new file mode 100644
+index 0000000..5d4b49a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/rms_sh.h
+@@ -0,0 +1,125 @@
++/*
++ * rms_sh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== rms_sh.h ========
++ *
++ *  DSP/BIOS Bridge Resource Manager Server shared definitions (used on both
++ *  GPP and DSP sides).
++ *
++ *! Revision History
++ *! ================
++ *! 24-Mar-2003 vp  Merged updates required for CCS2.2 transition.
++ *! 24-Feb-2003 kc  Rearranged order of node types to temporarily support
++ *!               legacy message node code
++ *! 23-Nov-2002 gp  Converted tabs -> spaces, to fix formatting.
++ *! 13-Feb-2002 jeh Added sysstacksize element to RMS_MoreTaskArgs.
++ *! 11-Dec-2000 sg  Added 'misc' element to RMS_MoreTaskArgs.
++ *! 04-Dec-2000 ag  Added RMS_BUFDESC command code.
++ *!                 C/R code value changed to allow ORing of system/user codes.
++ *! 10-Oct-2000 sg  Added 'align' field to RMS_StrmDef.
++ *! 09-Oct-2000 sg  Moved pre-defined message codes here from rmsdefs.h.
++ *! 02-Oct-2000 sg  Changed ticks to msec.
++ *! 24-Aug-2000 sg  Moved definitions that will be exposed to app developers
++ *!               to a separate file, rmsdefs.h.
++ *! 10-Aug-2000 sg  Added RMS_COMMANDBUFSIZE and RMS_RESPONSEBUFSIZE; added
++ *!               pre-defined command/response codes; more comments.
++ *! 09-Aug-2000 sg  Added RMS_ETASK.
++ *! 08-Aug-2000 jeh Define RMS_WORD for GPP, rename DSP_MSG to RMS_DSPMSG.
++ *!                 Added RMS_MsgArgs, RMS_MoreTaskArgs.
++ *! 25-Jul-2000 sg: Changed SIO to STRM.
++ *! 30-Jun-2000 sg: Initial.
++ */
++
++#ifndef RMS_SH_
++#define RMS_SH_
++
++#include <dspbridge/rmstypes.h>
++
++/* Node Types: */
++#define RMS_TASK                1     /* Task node */
++#define RMS_DAIS                2     /* xDAIS socket node */
++#define RMS_MSG                 3     /* Message node */
++
++/* Memory Types: */
++#define RMS_CODE                0     /* Program space */
++#define RMS_DATA                1     /* Data space */
++#define RMS_IO                        2       /* I/O space */
++
++/* RM Server Command and Response Buffer Sizes: */
++#define RMS_COMMANDBUFSIZE     256    /* Size of command buffer */
++#define RMS_RESPONSEBUFSIZE    16     /* Size of response buffer */
++
++/* Pre-Defined Command/Response Codes: */
++#define RMS_EXIT                0x80000000   /* GPP->Node: shutdown */
++#define RMS_EXITACK             0x40000000   /* Node->GPP: ack shutdown */
++#define RMS_BUFDESC             0x20000000   /* Arg1 SM buf, Arg2 is SM size */
++#define RMS_KILLTASK            0x10000000  /* GPP->Node: Kill Task */
++#define RMS_USER                0x0   /* Start of user-defined msg codes */
++#define RMS_MAXUSERCODES        0xfff /* Maximum user defined C/R Codes */
++
++
++/* RM Server RPC Command Structure: */
++      struct RMS_Command {
++              RMS_WORD fxn;   /* Server function address */
++              RMS_WORD arg1;  /* First argument */
++              RMS_WORD arg2;  /* Second argument */
++              RMS_WORD data;  /* Function-specific data array */
++      } ;
++
++/*
++ *  The RMS_StrmDef structure defines the parameters for both input and output
++ *  streams, and is passed to a node's create function.
++ */
++      struct RMS_StrmDef {
++              RMS_WORD bufsize;       /* Buffer size (in DSP words) */
++              RMS_WORD nbufs; /* Max number of bufs in stream */
++              RMS_WORD segid; /* Segment to allocate buffers */
++              RMS_WORD align; /* Alignment for allocated buffers */
++              RMS_WORD timeout;       /* Timeout (msec) for blocking calls */
++              RMS_CHAR name[1];       /* Device Name (terminated by '\0') */
++      } ;
++
++/* Message node create args structure: */
++      struct RMS_MsgArgs {
++              RMS_WORD maxMessages;   /* Max # simultaneous msgs to node */
++              RMS_WORD segid; /* Mem segment for NODE_allocMsgBuf */
++              RMS_WORD notifyType;    /* Type of message notification */
++              RMS_WORD argLength;     /* Length (in DSP chars) of arg data */
++              RMS_WORD argData;       /* Arg data for node */
++      } ;
++
++/* Partial task create args structure */
++      struct RMS_MoreTaskArgs {
++              RMS_WORD priority;      /* Task's runtime priority level */
++              RMS_WORD stackSize;     /* Task's stack size */
++              RMS_WORD sysstackSize;  /* Task's system stack size (55x) */
++              RMS_WORD stackSeg;      /* Memory segment for task's stack */
++              RMS_WORD heapAddr;   /* base address of the node memory heap in
++                                    * external memory (DSP virtual address) */
++              RMS_WORD heapSize;   /* size in MAUs of the node memory heap in
++                                    * external memory */
++              RMS_WORD misc;  /* Misc field.  Not used for 'normal'
++                               * task nodes; for xDAIS socket nodes
++                               * specifies the IALG_Fxn pointer.
++                               */
++              /* # input STRM definition structures */
++              RMS_WORD numInputStreams;
++      } ;
++
++#endif                                /* RMS_SH_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/rmstypes.h b/arch/arm/plat-omap/include/dspbridge/rmstypes.h
+new file mode 100644
+index 0000000..13d752e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/rmstypes.h
+@@ -0,0 +1,40 @@
++/*
++ * rmstypes.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== rmstypes.h ========
++ *
++ *  DSP/BIOS Bridge Resource Manager Server shared data type definitions.
++ *
++ *! Revision History
++ *! ================
++ *! 06-Oct-2000 sg  Added LgFxn type.
++ *! 05-Oct-2000 sg  Changed RMS_STATUS to LgUns.
++ *! 31-Aug-2000 sg  Added RMS_DSPMSG.
++ *! 25-Aug-2000 sg  Initial.
++ */
++
++#ifndef RMSTYPES_
++#define RMSTYPES_
++#include <linux/types.h>
++/*
++ *  DSP-side definitions.
++ */
++#include <dspbridge/std.h>
++typedef u32 RMS_WORD;
++typedef char RMS_CHAR;
++
++#endif                                /* RMSTYPES_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/services.h b/arch/arm/plat-omap/include/dspbridge/services.h
+new file mode 100644
+index 0000000..35bab0d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/services.h
+@@ -0,0 +1,63 @@
++/*
++ * services.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== services.h ========
++ *  Purpose:
++ *      Provide loading and unloading of SERVICES modules.
++ *
++ *  Public Functions:
++ *      SERVICES_Exit(void)
++ *      SERVICES_Init(void)
++ *
++ *! Revision History:
++ *! ================
++ *! 01-Feb-2000 kc: Created.
++ */
++
++#ifndef SERVICES_
++#define SERVICES_
++
++#include <dspbridge/host_os.h>
++/*
++ *  ======== SERVICES_Exit ========
++ *  Purpose:
++ *      Discontinue usage of module; free resources when reference count
++ *      reaches 0.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      SERVICES initialized.
++ *  Ensures:
++ *      Resources used by module are freed when cRef reaches zero.
++ */
++      extern void SERVICES_Exit(void);
++
++/*
++ *  ======== SERVICES_Init ========
++ *  Purpose:
++ *      Initializes SERVICES modules.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if all modules initialized; otherwise FALSE.
++ *  Requires:
++ *  Ensures:
++ *      SERVICES modules initialized.
++ */
++      extern bool SERVICES_Init(void);
++
++#endif                                /* SERVICES_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/std.h b/arch/arm/plat-omap/include/dspbridge/std.h
+new file mode 100644
+index 0000000..ec849f4
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/std.h
+@@ -0,0 +1,143 @@
++/*
++ * std.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== std.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 16-Feb-2004 vp    GNU compiler 3.x defines inline keyword. Added
++ *!                   appropriate macros not to redefine inline keyword in
++ *!                   this file.
++ *! 24-Oct-2002       ashu    defined _TI_ and _FIXED_ symbols for 28x.
++ *! 24-Oct-2002       ashu    defined _TI_ for 24x.
++ *! 01-Mar-2002 kln   changed LARGE_MODEL and Arg definition for 28x
++ *! 01-Feb-2002 kln   added definitions for 28x
++ *! 08-Dec-2000 kw:   added 'ArgToInt' and 'ArgToPtr' macros
++ *! 30-Nov-2000 mf:   Added _64_, _6x_; removed _7d_
++ *! 30-May-2000 srid: Added   __TMS320C55X__ for 55x; Arg is void * for 55 .
++ *! 18-Jun-1999 dr:   Added '_TI_', fixed __inline for SUN4, added inline
++ *! 10-Feb-1999 rt:   Added '55' support, changed 54's symbol to _TMS320C5XX
++ *! 29-Aug-1998 mf:   fixed typo, removed obsolete targets
++ *! 08-Jun-1998 mf:   _67_ is synonym for _7d_
++ *! 10-Oct-1997 rt;   added _7d_ for Raytheon C7DSP triggered by _TMS320C6700
++ *! 04-Aug-1997 cc:   added _29_ for _TMS320C2XX
++ *! 11-Jul-1997 dlr:  _5t_, and STD_SPOXTASK keyword for Tasking
++ *! 12-Jun-1997 mf:   _TMS320C60 -> _TMS320C6200
++ *! 13-Feb-1997 mf:   _62_, with 32-bit LgInt
++ *! 26-Nov-1996 kw:   merged bios-c00's and wsx-a27's <dspbridge/std.h> changes
++ *!                   *and* revision history
++ *! 12-Sep-1996 kw:   added C54x #ifdef's
++ *! 21-Aug-1996 mf:   removed #define main smain for _21_
++ *! 14-May-1996 gp:     def'd out INT, FLOAT, and COMPLEX defines for WSX.
++ *! 11-Apr-1996 kw:     define _W32_ based on _WIN32 (defined by MS compiler)
++ *! 07-Mar-1996 mg:     added Win32 support
++ *! 06-Sep-1995 dh:   added _77_ dynamic stack support via fxns77.h
++ *! 27-Jun-1995 dh:   added _77_ support
++ *! 16-Mar-1995 mf:   for _21_: #define main smain
++ *! 01-Mar-1995 mf:   set _20_ and _60_ (as well as _21_ for both)
++ *! 22-Feb-1995 mf:   Float is float for _SUN_ and _80_
++ *! 22-Dec-1994 mf:   Added _80_ definition, for PP or MP.
++ *! 09-Dec-1994 mf:   Added _53_ definition.
++ *!                   Added definitions of _30_, etc.
++ *! 23-Aug-1994 dh    removed _21_ special case (kw)
++ *! 17-Aug-1994 dh    added _51_ support
++ *! 03-Aug-1994 kw    updated _80_ support
++ *! 30-Jun-1994 kw    added _80_ support
++ *! 05-Apr-1994 kw:   Added _SUN_ to _FLOAT_ definition
++ *! 01-Mar-1994 kw:   Made Bool an int (was u16) for _56_ (more efficient).
++ *!                   Added _53_ support.
++ */
++
++#ifndef STD_
++#define STD_
++
++#include <linux/types.h>
++
++/*
++ *  ======== _TI_ ========
++ *  _TI_ is defined for all TI targets
++ */
++#if defined(_29_) || defined(_30_) || defined(_40_) || defined(_50_) || \
++    defined(_54_) || defined(_55_) || defined(_6x_) || defined(_80_) || \
++    defined(_28_) || defined(_24_)
++#define _TI_  1
++#endif
++
++/*
++ *  ======== _FLOAT_ ========
++ *  _FLOAT_ is defined for all targets that natively support floating point
++ */
++#if defined(_SUN_) || defined(_30_) || defined(_40_) || defined(_67_) || \
++    defined(_80_)
++#define _FLOAT_       1
++#endif
++
++/*
++ *  ======== _FIXED_ ========
++ *  _FIXED_ is defined for all fixed point target architectures
++ */
++#if defined(_29_) || defined(_50_) || defined(_54_) || defined(_55_) || \
++    defined(_62_) || defined(_64_) || defined(_28_)
++#define _FIXED_       1
++#endif
++
++/*
++ *  ======== _TARGET_ ========
++ *  _TARGET_ is defined for all target architectures (as opposed to
++ *  host-side software)
++ */
++#if defined(_FIXED_) || defined(_FLOAT_)
++#define _TARGET_ 1
++#endif
++
++/*
++ *  8, 16, 32-bit type definitions
++ *
++ *  Sm*       - 8-bit type
++ *  Md* - 16-bit type
++ *  Lg* - 32-bit type
++ *
++ *  *s32 - signed type
++ *  *u32 - unsigned type
++ *  *Bits - unsigned type (bit-maps)
++ */
++
++/*
++ *  Aliases for standard C types
++ */
++
++typedef s32(*Fxn) (void);             /* generic function type */
++
++#ifndef NULL
++#define NULL 0
++#endif
++
++
++/*
++ * These macros are used to cast 'Arg' types to 's32' or 'Ptr'.
++ * These macros were added for the 55x since Arg is not the same
++ * size as s32 and Ptr in 55x large model.
++ */
++#if defined(_28l_) || defined(_55l_)
++#define ArgToInt(A)   ((s32)((long)(A) & 0xffff))
++#define ArgToPtr(A)   ((Ptr)(A))
++#else
++#define ArgToInt(A)   ((s32)(A))
++#define ArgToPtr(A)   ((Ptr)(A))
++#endif
++
++#endif                                /* STD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/strm.h b/arch/arm/plat-omap/include/dspbridge/strm.h
+new file mode 100644
+index 0000000..5825615
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/strm.h
+@@ -0,0 +1,441 @@
++/*
++ * strm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== strm.h ========
++ *  Description:
++ *      DSPBridge Stream Manager.
++ *
++ *  Public Functions:
++ *      STRM_AllocateBuffer
++ *      STRM_Close
++ *      STRM_Create
++ *      STRM_Delete
++ *      STRM_Exit
++ *      STRM_FreeBuffer
++ *      STRM_GetEventHandle
++ *      STRM_GetInfo
++ *      STRM_Idle
++ *      STRM_Init
++ *      STRM_Issue
++ *      STRM_Open
++ *      STRM_PrepareBuffer
++ *      STRM_Reclaim
++ *      STRM_RegisterNotify
++ *      STRM_Select
++ *      STRM_UnprepareBuffer
++ *
++ *  Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 15-Nov-2001 ag  Changed DSP_STREAMINFO to STRM_INFO in STRM_GetInfo().
++ *!                 Added DSP_ESIZE error to STRM_AllocateBuffer().
++ *! 07-Jun-2001 sg  Made DSPStream_AllocateBuffer fxn name plural.
++ *! 10-May-2001 jeh Code review cleanup.
++ *! 13-Feb-2001 kc  DSP/BIOS Bridge name updates.
++ *! 06-Feb-2001 kc  Updated DBC_Ensure for STRM_Select().
++ *! 23-Oct-2000 jeh Allow NULL STRM_ATTRS passed to STRM_Open().
++ *! 25-Sep-2000 jeh Created.
++ */
++
++#ifndef STRM_
++#define STRM_
++
++#include <dspbridge/dev.h>
++
++#include <dspbridge/strmdefs.h>
++
++/*
++ *  ======== STRM_AllocateBuffer ========
++ *  Purpose:
++ *      Allocate data buffer(s) for use with a stream.
++ *  Parameter:
++ *      hStrm:          Stream handle returned from STRM_Open().
++ *      uSize:          Size (GPP bytes) of the buffer(s).
++ *      uNumBufs:       Number of buffers to allocate.
++ *      apBuffer:       Array to hold buffer addresses.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hStrm.
++ *      DSP_EMEMORY:    Insufficient memory.
++ *      DSP_EFAIL:      Failure occurred, unable to allocate buffers.
++ *      DSP_ESIZE:      uSize must be > 0 bytes.
++ *  Requires:
++ *      STRM_Init(void) called.
++ *      apBuffer != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS STRM_AllocateBuffer(struct STRM_OBJECT *hStrm,
++                                            u32 uSize,
++                                            OUT u8 **apBuffer,
++                                            u32 uNumBufs);
++
++/*
++ *  ======== STRM_Close ========
++ *  Purpose:
++ *      Close a stream opened with STRM_Open().
++ *  Parameter:
++ *      hStrm:          Stream handle returned from STRM_Open().
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hStrm.
++ *      DSP_EPENDING:   Some data buffers issued to the stream have not
++ *                      been reclaimed.
++ *      DSP_EFAIL:      Failure to close stream.
++ *  Requires:
++ *      STRM_Init(void) called.
++ *  Ensures:
++ */
++      extern DSP_STATUS STRM_Close(struct STRM_OBJECT *hStrm);
++
++/*
++ *  ======== STRM_Create ========
++ *  Purpose:
++ *      Create a STRM manager object. This object holds information about the
++ *      device needed to open streams.
++ *  Parameters:
++ *      phStrmMgr:      Location to store handle to STRM manager object on
++ *                      output.
++ *      hDev:           Device for this processor.
++ *  Returns:
++ *      DSP_SOK:        Success;
++ *      DSP_EMEMORY:    Insufficient memory for requested resources.
++ *      DSP_EFAIL:      General failure.
++ *  Requires:
++ *      STRM_Init(void) called.
++ *      phStrmMgr != NULL.
++ *      hDev != NULL.
++ *  Ensures:
++ *      DSP_SOK:        Valid *phStrmMgr.
++ *      error:          *phStrmMgr == NULL.
++ */
++      extern DSP_STATUS STRM_Create(OUT struct STRM_MGR **phStrmMgr,
++                                    struct DEV_OBJECT *hDev);
++
++/*
++ *  ======== STRM_Delete ========
++ *  Purpose:
++ *      Delete the STRM Object.
++ *  Parameters:
++ *      hStrmMgr:       Handle to STRM manager object from STRM_Create.
++ *  Returns:
++ *  Requires:
++ *      STRM_Init(void) called.
++ *      Valid hStrmMgr.
++ *  Ensures:
++ *      hStrmMgr is not valid.
++ */
++      extern void STRM_Delete(struct STRM_MGR *hStrmMgr);
++
++/*
++ *  ======== STRM_Exit ========
++ *  Purpose:
++ *      Discontinue usage of STRM module.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      STRM_Init(void) successfully called before.
++ *  Ensures:
++ */
++      extern void STRM_Exit(void);
++
++/*
++ *  ======== STRM_FreeBuffer ========
++ *  Purpose:
++ *      Free buffer(s) allocated with STRM_AllocateBuffer.
++ *  Parameter:
++ *      hStrm:          Stream handle returned from STRM_Open().
++ *      apBuffer:       Array containing buffer addresses.
++ *      uNumBufs:       Number of buffers to be freed.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid stream handle.
++ *      DSP_EFAIL:      Failure occurred, unable to free buffers.
++ *  Requires:
++ *      STRM_Init(void) called.
++ *      apBuffer != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS STRM_FreeBuffer(struct STRM_OBJECT *hStrm,
++                                        u8 **apBuffer, u32 uNumBufs);
++
++/*
++ *  ======== STRM_GetEventHandle ========
++ *  Purpose:
++ *      Get stream's user event handle. This function is used when closing
++ *      a stream, so the event can be closed.
++ *  Parameter:
++ *      hStrm:          Stream handle returned from STRM_Open().
++ *      phEvent:        Location to store event handle on output.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hStrm.
++ *  Requires:
++ *      STRM_Init(void) called.
++ *      phEvent != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS STRM_GetEventHandle(struct STRM_OBJECT *hStrm,
++                                            OUT HANDLE *phEvent);
++
++/*
++ *  ======== STRM_GetInfo ========
++ *  Purpose:
++ *      Get information about a stream. User's DSP_STREAMINFO is contained
++ *      in STRM_INFO struct. STRM_INFO also contains Bridge private info.
++ *  Parameters:
++ *      hStrm:              Stream handle returned from STRM_Open().
++ *      pStreamInfo:        Location to store stream info on output.
++ *      uSteamInfoSize:     Size of user's DSP_STREAMINFO structure.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EHANDLE:        Invalid hStrm.
++ *      DSP_ESIZE:          uStreamInfoSize < sizeof(DSP_STREAMINFO).
++ *      DSP_EFAIL:          Unable to get stream info.
++ *  Requires:
++ *      STRM_Init(void) called.
++ *      pStreamInfo != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS STRM_GetInfo(struct STRM_OBJECT *hStrm,
++                                     OUT struct STRM_INFO *pStreamInfo,
++                                     u32 uStreamInfoSize);
++
++/*
++ *  ======== STRM_Idle ========
++ *  Purpose:
++ *      Idle a stream and optionally flush output data buffers.
++ *      If this is an output stream and fFlush is TRUE, all data currently
++ *      enqueued will be discarded.
++ *      If this is an output stream and fFlush is FALSE, this function
++ *      will block until all currently buffered data is output, or the timeout
++ *      specified has been reached.
++ *      After a successful call to STRM_Idle(), all buffers can immediately
++ *      be reclaimed.
++ *  Parameters:
++ *      hStrm:          Stream handle returned from STRM_Open().
++ *      fFlush:         If TRUE, discard output buffers.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hStrm.
++ *      DSP_ETIMEOUT:   A timeout occurred before the stream could be idled.
++ *      DSP_ERESTART:   A critical error occurred, DSP is being restarted.
++ *      DSP_EFAIL:      Unable to idle stream.
++ *  Requires:
++ *      STRM_Init(void) called.
++ *  Ensures:
++ */
++      extern DSP_STATUS STRM_Idle(struct STRM_OBJECT *hStrm, bool fFlush);
++
++/*
++ *  ======== STRM_Init ========
++ *  Purpose:
++ *      Initialize the STRM module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialization succeeded, FALSE otherwise.
++ *  Requires:
++ *  Ensures:
++ */
++      extern bool STRM_Init(void);
++
++/*
++ *  ======== STRM_Issue ========
++ *  Purpose:
++ *      Send a buffer of data to a stream.
++ *  Parameters:
++ *      hStrm:              Stream handle returned from STRM_Open().
++ *      pBuf:               Pointer to buffer of data to be sent to the stream.
++ *      ulBytes:            Number of bytes of data in the buffer.
++ *      ulBufSize:          Actual buffer size in bytes.
++ *      dwArg:              A user argument that travels with the buffer.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EHANDLE:        Invalid hStrm.
++ *      DSP_ESTREAMFULL:    The stream is full.
++ *      DSP_EFAIL:          Failure occurred, unable to issue buffer.
++ *  Requires:
++ *      STRM_Init(void) called.
++ *      pBuf != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS STRM_Issue(struct STRM_OBJECT *hStrm, IN u8 *pBuf,
++                                   u32 ulBytes, u32 ulBufSize,
++                                   IN u32 dwArg);
++
++/*
++ *  ======== STRM_Open ========
++ *  Purpose:
++ *      Open a stream for sending/receiving data buffers to/from a task of
++ *      DAIS socket node on the DSP.
++ *  Parameters:
++ *      hNode:          Node handle returned from NODE_Allocate().
++ *      uDir:           DSP_TONODE or DSP_FROMNODE.
++ *      uIndex:         Stream index.
++ *      pAttr:          Pointer to structure containing attributes to be
++ *                      applied to stream. Cannot be NULL.
++ *      phStrm:         Location to store stream handle on output.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hNode.
++ *      DSP_EDIRECTION: Invalid uDir.
++ *      DSP_EVALUE:     Invalid uIndex.
++ *      DSP_ENODETYPE:  hNode is not a task or DAIS socket node.
++ *      DSP_EFAIL:      Unable to open stream.
++ *  Requires:
++ *      STRM_Init(void) called.
++ *      phStrm != NULL.
++ *      pAttr != NULL.
++ *  Ensures:
++ *      DSP_SOK:        *phStrm is valid.
++ *      error:          *phStrm == NULL.
++ */
++      extern DSP_STATUS STRM_Open(struct NODE_OBJECT *hNode, u32 uDir,
++                                  u32 uIndex, IN struct STRM_ATTR *pAttr,
++                                  OUT struct STRM_OBJECT **phStrm);
++
++/*
++ *  ======== STRM_PrepareBuffer ========
++ *  Purpose:
++ *      Prepare a data buffer not allocated by DSPStream_AllocateBuffers()
++ *      for use with a stream.
++ *  Parameter:
++ *      hStrm:          Stream handle returned from STRM_Open().
++ *      uSize:          Size (GPP bytes) of the buffer.
++ *      pBuffer:        Buffer address.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hStrm.
++ *      DSP_EFAIL:      Failure occurred, unable to prepare buffer.
++ *  Requires:
++ *      STRM_Init(void) called.
++ *      pBuffer != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS STRM_PrepareBuffer(struct STRM_OBJECT *hStrm,
++                                           u32 uSize,
++                                           u8 *pBuffer);
++
++/*
++ *  ======== STRM_Reclaim ========
++ *  Purpose:
++ *      Request a buffer back from a stream.
++ *  Parameters:
++ *      hStrm:          Stream handle returned from STRM_Open().
++ *      pBufPtr:        Location to store pointer to reclaimed buffer.
++ *      pulBytes:       Location where number of bytes of data in the
++ *                      buffer will be written.
++ *      pulBufSize:     Location where actual buffer size will be written.
++ *      pdwArg:         Location where user argument that travels with
++ *                      the buffer will be written.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hStrm.
++ *      DSP_ETIMEOUT:   A timeout occurred before a buffer could be
++ *                      retrieved.
++ *      DSP_EFAIL:      Failure occurred, unable to reclaim buffer.
++ *  Requires:
++ *      STRM_Init(void) called.
++ *      pBufPtr != NULL.
++ *      pulBytes != NULL.
++ *      pdwArg != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS STRM_Reclaim(struct STRM_OBJECT *hStrm,
++                                     OUT u8 **pBufPtr, u32 *pulBytes,
++                                     u32 *pulBufSize, u32 *pdwArg);
++
++/*
++ *  ======== STRM_RegisterNotify ========
++ *  Purpose:
++ *      Register to be notified on specific events for this stream.
++ *  Parameters:
++ *      hStrm:          Stream handle returned by STRM_Open().
++ *      uEventMask:     Mask of types of events to be notified about.
++ *      uNotifyType:    Type of notification to be sent.
++ *      hNotification:  Handle to be used for notification.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hStrm.
++ *      DSP_EMEMORY:    Insufficient memory on GPP.
++ *      DSP_EVALUE:     uEventMask is invalid.
++ *      DSP_ENOTIMPL:   Notification type specified by uNotifyType is not
++ *                      supported.
++ *  Requires:
++ *      STRM_Init(void) called.
++ *      hNotification != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS STRM_RegisterNotify(struct STRM_OBJECT *hStrm,
++                                            u32 uEventMask, u32 uNotifyType,
++                                            struct DSP_NOTIFICATION
++                                            *hNotification);
++
++/*
++ *  ======== STRM_Select ========
++ *  Purpose:
++ *      Select a ready stream.
++ *  Parameters:
++ *      aStrmTab:       Array of stream handles returned from STRM_Open().
++ *      nStrms:         Number of stream handles in array.
++ *      pMask:          Location to store mask of ready streams on output.
++ *      uTimeout:       Timeout value (milliseconds).
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_ERANGE:     nStrms out of range.
++
++ *      DSP_EHANDLE:    Invalid stream handle in array.
++ *      DSP_ETIMEOUT:   A timeout occurred before a stream became ready.
++ *      DSP_EFAIL:      Failure occurred, unable to select a stream.
++ *  Requires:
++ *      STRM_Init(void) called.
++ *      aStrmTab != NULL.
++ *      nStrms > 0.
++ *      pMask != NULL.
++ *  Ensures:
++ *      DSP_SOK:        *pMask != 0 || uTimeout == 0.
++ *      Error:          *pMask == 0.
++ */
++      extern DSP_STATUS STRM_Select(IN struct STRM_OBJECT **aStrmTab,
++                                    u32 nStrms,
++                                    OUT u32 *pMask, u32 uTimeout);
++
++/*
++ *  ======== STRM_UnprepareBuffer ========
++ *  Purpose:
++ *      Unprepare a data buffer that was previously prepared for a stream
++ *      with DSPStream_PrepareBuffer(), and that will no longer be used with
++ *      the stream.
++ *  Parameter:
++ *      hStrm:          Stream handle returned from STRM_Open().
++ *      uSize:          Size (GPP bytes) of the buffer.
++ *      pBuffer:        Buffer address.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hStrm.
++ *      DSP_EFAIL:      Failure occurred, unable to unprepare buffer.
++ *  Requires:
++ *      STRM_Init(void) called.
++ *      pBuffer != NULL.
++ *  Ensures:
++ */
++      extern DSP_STATUS STRM_UnprepareBuffer(struct STRM_OBJECT *hStrm,
++                                             u32 uSize,
++                                             u8 *pBuffer);
++
++#endif                                /* STRM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/strmdefs.h b/arch/arm/plat-omap/include/dspbridge/strmdefs.h
+new file mode 100644
+index 0000000..44d217a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/strmdefs.h
+@@ -0,0 +1,57 @@
++/*
++ * strmdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== strmdefs.h ========
++ *  Purpose:
++ *      Global STRM constants and types.
++ *
++ *! Revision History
++ *! ================
++ *! 19-Nov-2001 ag      Added STRM_INFO..
++ *! 25-Sep-2000 jeh     Created.
++ */
++
++#ifndef STRMDEFS_
++#define STRMDEFS_
++
++#define STRM_MAXEVTNAMELEN      32
++
++      struct STRM_MGR;
++
++      struct STRM_OBJECT;
++
++      struct STRM_ATTR {
++              HANDLE hUserEvent;
++              char *pstrEventName;
++              void *pVirtBase;        /* Process virtual base address of
++                                       * mapped SM */
++              u32 ulVirtSize; /* Size of virtual space in bytes */
++              struct DSP_STREAMATTRIN *pStreamAttrIn;
++      } ;
++
++      struct STRM_INFO {
++              enum DSP_STRMMODE lMode;        /* transport mode of
++                                       * stream(DMA, ZEROCOPY..) */
++              u32 uSegment;   /* Segment strm allocs from. 0 is local mem */
++              void *pVirtBase;        /* "      " Stream'process virt base */
++              struct DSP_STREAMINFO *pUser;   /* User's stream information
++                                               * returned */
++      } ;
++
++#endif                                /* STRMDEFS_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/sync.h b/arch/arm/plat-omap/include/dspbridge/sync.h
+new file mode 100644
+index 0000000..fa3ff8d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/sync.h
+@@ -0,0 +1,340 @@
++/*
++ * sync.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== sync.h ========
++ *  Purpose:
++ *      Provide synchronization services.
++ *
++ *  Public Functions:
++ *      SYNC_CloseEvent
++ *      SYNC_DeleteCS
++ *      SYNC_EnterCS
++ *      SYNC_Exit
++ *      SYNC_Init
++ *      SYNC_InitializeCS
++ *      SYNC_LeaveCS
++ *      SYNC_OpenEvent
++ *      SYNC_PostMessage
++ *      SYNC_ResetEvent
++ *      SYNC_SetEvent
++ *      SYNC_WaitOnEvent
++ *      SYNC_WaitOnMultipleEvents
++ *
++ *! Revision History:
++ *! ================
++ *! 05-Oct-2000 jeh Added SYNC_WaitOnMultipleEvents().
++ *! 01-Dec-1999 ag: Added #define SYNC_MAXNAMELENGTH.
++ *! 04-Nov-1999 kc: Added critical section functions and objects to SYNC.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 24-Sep-1999 kc: Added WinCE notes.
++ *! 20-Oct-1997 gp: Removed unused SYNC_ critical section and must complete fxns
++ *!                 Added SYNC_HOBJECT, SYNC_ATTRS, and object validation, and
++ *!                 merged SYNC_DestroyEvent into SYNC_CloseEvent, and merged
++ *!                 SYNC_CreateEvent into SYNC_OpenEvent.
++ *! 07-Oct-1997 gp: Added SYNC_Create/DestroyEvent (for NT testing).
++ *! 06-Oct-1997 gp: Added SYNC_OpenEvent.
++ *! 03-Jun-1997 gp: Added SYNC_{Begin|End}CritSection() functions.
++ *! 03-Jan-1997 gp: Added SYNC_INFINITE define.
++ *! 05-Aug-1996 gp: Created.
++ */
++
++#ifndef _SYNC_H
++#define _SYNC_H
++
++#define SIGNATURECS     0x53435953    /* "SYCS" (in reverse) */
++#define SIGNATUREDPCCS  0x53445953    /* "SYDS" (in reverse) */
++
++/* Special timeout value indicating an infinite wait: */
++#define SYNC_INFINITE  0xffffffff
++
++/* Maximum string length of a named event */
++#define SYNC_MAXNAMELENGTH 32
++
++/* Generic SYNC object: */
++      struct SYNC_OBJECT;
++
++/* Generic SYNC CS object: */
++struct SYNC_CSOBJECT {
++      u32 dwSignature;        /* used for object validation */
++      struct semaphore sem;
++} ;
++
++/* SYNC object attributes: */
++      struct SYNC_ATTRS {
++              HANDLE hUserEvent;    /* Platform's User Mode synch. object. */
++              HANDLE hKernelEvent;  /* Platform's Kernel Mode sync. object. */
++              u32 dwReserved1;        /* For future expansion.   */
++              u32 dwReserved2;        /* For future expansion.   */
++      } ;
++
++/*
++ *  ======== SYNC_CloseEvent ========
++ *  Purpose:
++ *      Close this event handle, freeing resources allocated in SYNC_OpenEvent
++ *      if necessary.
++ *  Parameters:
++ *      hEvent: Handle to a synchronization event, created/opened in
++ *              SYNC_OpenEvent.
++ *  Returns:
++ *      DSP_SOK:        Success;
++ *      DSP_EFAIL:      Failed to close event handle.
++ *      DSP_EHANDLE:    Invalid handle.
++ *  Requires:
++ *      SYNC initialized.
++ *  Ensures:
++ *      Any subsequent usage of hEvent would be invalid.
++ */
++      extern DSP_STATUS SYNC_CloseEvent(IN struct SYNC_OBJECT *hEvent);
++
++/*
++ *  ======== SYNC_DeleteCS ========
++ *  Purpose:
++ *      Delete a critical section.
++ *  Parameters:
++ *      hCSObj: critical section handle.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid handle.
++ *  Requires:
++ *  Ensures:
++ */
++      extern DSP_STATUS SYNC_DeleteCS(IN struct SYNC_CSOBJECT *hCSObj);
++
++/*
++ *  ======== SYNC_EnterCS ========
++ *  Purpose:
++ *      Enter the critical section.
++ *  Parameters:
++ *      hCSObj: critical section handle.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid handle.
++ *  Requires:
++ *  Ensures:
++ */
++      extern DSP_STATUS SYNC_EnterCS(IN struct SYNC_CSOBJECT *hCSObj);
++
++/*
++ *  ======== SYNC_Exit ========
++ *  Purpose:
++ *      Discontinue usage of module; free resources when reference count
++ *      reaches 0.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      SYNC initialized.
++ *  Ensures:
++ *      Resources used by module are freed when cRef reaches zero.
++ */
++      extern void SYNC_Exit(void);
++
++/*
++ *  ======== SYNC_Init ========
++ *  Purpose:
++ *      Initializes private state of SYNC module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if initialized; FALSE if error occured.
++ *  Requires:
++ *  Ensures:
++ *      SYNC initialized.
++ */
++      extern bool SYNC_Init(void);
++
++/*
++ *  ======== SYNC_InitializeCS ========
++ *  Purpose:
++ *      Initialize the critical section.
++ *  Parameters:
++ *      hCSObj: critical section handle.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Out of memory.
++ *  Requires:
++ *  Ensures:
++ */
++      extern DSP_STATUS SYNC_InitializeCS(OUT struct SYNC_CSOBJECT **phCSObj);
++
++/*
++ *  ======== SYNC_InitializeDPCCS ========
++ *  Purpose:
++ *      Initialize the critical section between process context and DPC.
++ *  Parameters:
++ *      hCSObj: critical section handle.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Out of memory.
++ *  Requires:
++ *  Ensures:
++ */
++      extern DSP_STATUS SYNC_InitializeDPCCS(OUT struct SYNC_CSOBJECT
++                                             **phCSObj);
++
++/*
++ *  ======== SYNC_LeaveCS ========
++ *  Purpose:
++ *      Leave the critical section.
++ *  Parameters:
++ *      hCSObj: critical section handle.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid handle.
++ *  Requires:
++ *  Ensures:
++ */
++      extern DSP_STATUS SYNC_LeaveCS(IN struct SYNC_CSOBJECT *hCSObj);
++
++/*
++ *  ======== SYNC_OpenEvent ========
++ *  Purpose:
++ *      Create/open and initialize an event object for thread synchronization,
++ *      which is initially in the non-signalled state.
++ *  Parameters:
++ *      phEvent:    Pointer to location to receive the event object handle.
++ *      pAttrs:     Pointer to SYNC_ATTRS object containing initial SYNC
++ *                  SYNC_OBJECT attributes.  If this pointer is NULL, then
++ *                  SYNC_OpenEvent will create and manage an OS specific
++ *                  syncronization object.
++ *          pAttrs->hUserEvent:  Platform's User Mode synchronization object.
++ *
++ *      The behaviour of the SYNC methods depend on the value of
++ *      the hUserEvent attr:
++ *
++ *      1. (hUserEvent == NULL):
++ *          A user mode event is created.
++ *      2. (hUserEvent != NULL):
++ *          A user mode event is supplied by the caller of SYNC_OpenEvent().
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Unable to create user mode event.
++ *      DSP_EMEMORY:    Insufficient memory.
++ *      DSP_EINVALIDARG SYNC_ATTRS values are invalid.
++ *  Requires:
++ *      - SYNC initialized.
++ *      - phEvent != NULL.
++ *  Ensures:
++ *      If function succeeded, pEvent->hEvent must be a valid event handle.
++ */
++      extern DSP_STATUS SYNC_OpenEvent(OUT struct SYNC_OBJECT **phEvent,
++                                       IN OPTIONAL struct SYNC_ATTRS
++                                       *pAttrs);
++
++/*
++ * ========= SYNC_PostMessage ========
++ *  Purpose:
++ *      To post a windows message
++ *  Parameters:
++ *      hWindow:    Handle to the window
++ *      uMsg:       Message to be posted
++ *  Returns:
++ *      DSP_SOK:        Success
++ *      DSP_EFAIL:      Post message failed
++ *      DSP_EHANDLE:    Invalid Window handle
++ *  Requires:
++ *      SYNC initialized
++ *  Ensures
++ */
++      extern DSP_STATUS SYNC_PostMessage(IN HANDLE hWindow, IN u32 uMsg);
++
++/*
++ *  ======== SYNC_ResetEvent ========
++ *  Purpose:
++ *      Reset a syncronization event object state to non-signalled.
++ *  Parameters:
++ *      hEvent:         Handle to a sync event.
++ *  Returns:
++ *      DSP_SOK:        Success;
++ *      DSP_EFAIL:      Failed to reset event.
++ *      DSP_EHANDLE:    Invalid handle.
++ *  Requires:
++ *      SYNC initialized.
++ *  Ensures:
++ */
++      extern DSP_STATUS SYNC_ResetEvent(IN struct SYNC_OBJECT *hEvent);
++
++/*
++ *  ======== SYNC_SetEvent ========
++ *  Purpose:
++ *      Signal the event.  Will unblock one waiting thread.
++ *  Parameters:
++ *      hEvent:         Handle to an event object.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Failed to signal event.
++ *      DSP_EHANDLE:    Invalid handle.
++ *  Requires:
++ *      SYNC initialized.
++ *  Ensures:
++ */
++      extern DSP_STATUS SYNC_SetEvent(IN struct SYNC_OBJECT *hEvent);
++
++/*
++ *  ======== SYNC_WaitOnEvent ========
++ *  Purpose:
++ *      Wait for an event to be signalled, up to the specified timeout.
++ *  Parameters:
++ *      hEvent:         Handle to an event object.
++ *      dwTimeOut:      The time-out interval, in milliseconds.
++ *                      The function returns if the interval elapses, even if
++ *                      the object's state is nonsignaled.
++ *                      If zero, the function tests the object's state and
++ *                      returns immediately.
++ *                      If SYNC_INFINITE, the function's time-out interval
++ *                      never elapses.
++ *  Returns:
++ *      DSP_SOK:        The object was signalled.
++ *      DSP_EHANDLE:    Invalid handle.
++ *      SYNC_E_FAIL:    Wait failed, possibly because the process terminated.
++ *      SYNC_E_TIMEOUT: Timeout expired while waiting for event to be signalled.
++ *  Requires:
++ *  Ensures:
++ */
++      extern DSP_STATUS SYNC_WaitOnEvent(IN struct SYNC_OBJECT *hEvent,
++                                         IN u32 dwTimeOut);
++
++/*
++ *  ======== SYNC_WaitOnMultipleEvents ========
++ *  Purpose:
++ *      Wait for any of an array of events to be signalled, up to the
++ *      specified timeout.
++ *      Note: dwTimeOut must be SYNC_INFINITE to signal infinite wait.
++ *  Parameters:
++ *      hSyncEvents:    Array of handles to event objects.
++ *      uCount:         Number of event handles.
++ *      dwTimeOut:      The time-out interval, in milliseconds.
++ *                      The function returns if the interval elapses, even if
++ *                      no event is signalled.
++ *                      If zero, the function tests the object's state and
++ *                      returns immediately.
++ *                      If SYNC_INFINITE, the function's time-out interval
++ *                      never elapses.
++ *      puIndex:        Location to store index of event that was signalled.
++ *  Returns:
++ *      DSP_SOK:        The object was signalled.
++ *      SYNC_E_FAIL:    Wait failed, possibly because the process terminated.
++ *      SYNC_E_TIMEOUT: Timeout expired before event was signalled.
++ *      DSP_EMEMORY:    Memory allocation failed.
++ *  Requires:
++ *  Ensures:
++ */
++      extern DSP_STATUS SYNC_WaitOnMultipleEvents(IN struct SYNC_OBJECT
++                                                  **hSyncEvents,
++                                                  IN u32 uCount,
++                                                  IN u32 dwTimeout,
++                                                  OUT u32 *puIndex);
++
++#endif                                /* _SYNC_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/util.h b/arch/arm/plat-omap/include/dspbridge/util.h
+new file mode 100644
+index 0000000..e6815ca
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/util.h
+@@ -0,0 +1,122 @@
++/*
++ * util.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== util.h ========
++ *  Purpose:
++ *      Provide general purpose utility functions.
++ *
++ *  Public Functions:
++ *      UTIL_CDTestDll
++ *      UTIL_CmdLineToArgs
++ *      UTIL_Exit
++ *      UTIL_GetSysInfo
++ *      UTIL_Init
++ */
++
++#ifndef _UTIL_H
++#define _UTIL_H
++
++#include <linux/delay.h>
++#include <linux/sched.h>
++
++#include <dspbridge/utildefs.h>
++
++/*
++ *  ======== UTIL_CDTestDll ========
++ *  Purpose:
++ *      Provides test entry point in class driver context.
++ *  Parameters:
++ *      cArgc:  test module command line input count.
++ *      ppArgv: test module command line args.
++ *  Returns:
++ *      0 if successful, a negative value otherwise.
++ *  Requires:
++ *      UTIL initialized.
++ *  Ensures:
++ */
++      extern u32 UTIL_CDTestDll(IN s32 cArgc, IN char **ppArgv);
++
++/*
++ *  ======== UTIL_CmdLineToArgs ========
++ *  Purpose:
++ *      This function re-creates C-style cmd line argc & argv from WinMain()
++ *      cmd line args.
++ *  Parameters:
++ *      s8 *pszProgName   - The name of the program currently being executed.
++ *      s8 *argv[]        - The argument vector.
++ *      s8 *pCmdLine      - The pointer to the command line.
++ *      bool fHasProgName   - Indicats whether a program name is supplied.
++ *  Returns:
++ *      Returns the number of arguments found.
++ *  Requires:
++ *      UTIL initialized.
++ *  Ensures:
++ */
++      extern s32 UTIL_CmdLineToArgs(IN char *pszProgName,
++                                    IN char *argv[UTIL_MAXARGVS],
++                                    IN char *pCmdLine, IN bool fHasProgName);
++
++/*
++ *  ======== UTIL_Exit ========
++ *  Purpose:
++ *      Discontinue usage of module; free resources when reference count
++ *      reaches 0.
++ *  Parameters:
++ *  Returns:
++ *  Requires:
++ *      UTIL initialized.
++ *  Ensures:
++ *      Resources used by module are freed when cRef reaches zero.
++ */
++      extern inline void UTIL_Exit(void)
++      {
++      }
++/*
++ *  ======== UTIL_GetSysInfo ========
++ *  Purpose:
++ *      This function return platform specific system information.
++ *
++ *  Parameters:
++ *      pSysInfo  - address to store the system information.
++ *  Returns:
++ *      DSP_SOK
++ *      S_FAIL
++ *  Requires:
++ *      UTIL initialized.
++ *      pSysInfo != NULL
++ *  Ensures:
++ */
++      extern DSP_STATUS UTIL_GetSysInfo(OUT struct UTIL_SYSINFO *pSysInfo);
++
++/*
++ *  ======== UTIL_Init ========
++ *  Purpose:
++ *      Initializes private state of UTIL module.
++ *  Parameters:
++ *  Returns:
++ *      TRUE if success, else FALSE.
++ *  Requires:
++ *  Ensures:
++ *      UTIL initialized.
++ */
++      extern inline bool UTIL_Init(void)
++      {
++              return true;
++      }
++
++#endif                                /* _UTIL_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/utildefs.h b/arch/arm/plat-omap/include/dspbridge/utildefs.h
+new file mode 100644
+index 0000000..bd53a5a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/utildefs.h
+@@ -0,0 +1,51 @@
++/*
++ * utildefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== utildefs.h ========
++ *  Purpose:
++ *      Global UTIL constants and types, shared between WCD and DSPSYS.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 kc  Removed wIOPort* entries from UTIL_HOSTCONFIG.
++ *! 12-Aug-2000 ag  Added UTIL_SYSINFO typedef.
++ *! 08-Oct-1999 rr  Adopted for WinCE where test fxns will be added in util.h
++ *! 26-Dec-1996 cr  Created.
++ */
++
++#ifndef UTILDEFS_
++#define UTILDEFS_
++
++/* constants taken from configmg.h */
++#define UTIL_MAXMEMREGS     9
++#define UTIL_MAXIOPORTS     20
++#define UTIL_MAXIRQS        7
++#define UTIL_MAXDMACHNLS    7
++
++/* misc. constants */
++#define UTIL_MAXARGVS       10
++
++/* Platform specific important info */
++      struct UTIL_SYSINFO {
++              /* Granularity of page protection; usually 1k or 4k */
++              u32 dwPageSize;
++              u32 dwAllocationGranularity; /* VM granularity, usually 64K */
++              u32 dwNumberOfProcessors;       /* Used as sanity check */
++      } ;
++
++#endif                                /* UTILDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/uuidutil.h b/arch/arm/plat-omap/include/dspbridge/uuidutil.h
+new file mode 100644
+index 0000000..af4aaec
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/uuidutil.h
+@@ -0,0 +1,74 @@
++/*
++ * uuidutil.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== uuidutil.h ========
++ *  Description:
++ *      This file contains the specification of UUID helper functions.
++ *
++ *! Revision History
++ *! ================
++ *! 09-Nov-2000 kc: Modified description of UUID utility functions.
++ *! 29-Sep-2000 kc: Appended "UUID_" prefix to UUID helper functions.
++ *! 10-Aug-2000 kc: Created.
++ *!
++ */
++
++#ifndef UUIDUTIL_
++#define UUIDUTIL_
++
++#define MAXUUIDLEN  37
++
++/*
++ *  ======== UUID_UuidToString ========
++ *  Purpose:
++ *      Converts a DSP_UUID to an ANSI string.
++ *  Parameters:
++ *      pUuid:      Pointer to a DSP_UUID object.
++ *      pszUuid:    Pointer to a buffer to receive a NULL-terminated UUID
++ *                  string.
++ *      size:     Maximum size of the pszUuid string.
++ *  Returns:
++ *  Requires:
++ *      pUuid & pszUuid are non-NULL values.
++ *  Ensures:
++ *      Lenghth of pszUuid is less than MAXUUIDLEN.
++ *  Details:
++ *      UUID string limit currently set at MAXUUIDLEN.
++ */
++      void UUID_UuidToString(IN struct DSP_UUID *pUuid, OUT char *pszUuid,
++                             s32 size);
++
++/*
++ *  ======== UUID_UuidFromString ========
++ *  Purpose:
++ *      Converts an ANSI string to a DSP_UUID.
++ *  Parameters:
++ *      pszUuid:    Pointer to a string that represents a DSP_UUID object.
++ *      pUuid:      Pointer to a DSP_UUID object.
++ *  Returns:
++ *  Requires:
++ *      pUuid & pszUuid are non-NULL values.
++ *  Ensures:
++ *  Details:
++ *      We assume the string representation of a UUID has the following format:
++ *      "12345678_1234_1234_1234_123456789abc".
++ */
++      extern void UUID_UuidFromString(IN char *pszUuid,
++                                      OUT struct DSP_UUID *pUuid);
++
++#endif                                /* UUIDUTIL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wcd.h b/arch/arm/plat-omap/include/dspbridge/wcd.h
+new file mode 100644
+index 0000000..5a7d47a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wcd.h
+@@ -0,0 +1,61 @@
++/*
++ * wcd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== wcd.h ========
++ *  Description:
++ *      'Bridge class driver library functions, object definitions, and
++ *      return error/status codes.  To be included by 'Bridge mini drivers.
++ *
++ *  Public Functions:
++ *      See mem.h and dbg.h.
++ *
++ *  Notes:
++ *      'Bridge Class Driver services exported to WMD's are initialized by the
++ *      WCD on behalf of the WMD.  WMD's must not call module Init/Exit
++ *      functions.
++ *
++ *      To ensure WMD binary compatibility across different platforms,
++ *      for the same processor, a WMD must restrict its usage of system
++ *      services to those exported by the 'Bridge class library.
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Jun-2000 jeh Added dev.h
++ *! 01-Nov-1999 ag: #WINCE# WCD_MAJOR_VERSION=8 & WCD_MINOR_VERSION=0 to match
++ *!               dll stamps.
++ *!                 0.80 - 0.89 Alpha, 0.90 - 0.99 Beta, 1.00 - 1.10 FCS.
++ *! 17-Sep-1997 gp: Changed size of CFG_HOSTRES structure; and ISR_Install API;
++ *!                 Changed WCD_MINOR_VERSION 3 -> 4.
++ *! 15-Sep-1997 gp: Moved WCD_(Un)registerMinidriver to drv.
++ *! 25-Jul-1997 cr: Added WCD_UnregisterMinidriver.
++ *! 22-Jul-1997 cr: Added WCD_RegisterMinidriver, WCD_MINOR_VERSION 2 -> 3.
++ *! 12-Nov-1996 gp: Defined port io macros.
++ *! 07-Nov-1996 gp: Updated for code review.
++ *! 16-Jul-1996 gp: Added CHNL fxns; updated WCD lib version to 2.
++ *! 10-May-1996 gp: Separated WMD def.s' into wmd.h.
++ *! 03-May-1996 gp: Created.
++ */
++
++#ifndef WCD_
++#define WCD_
++
++/* This WCD Library Version:  */
++#define WCD_MAJOR_VERSION   (u32)8    /* .8x - Alpha, .9x - Beta, 1.x FCS */
++#define WCD_MINOR_VERSION   (u32)0
++
++#endif                                /* WCD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wcdioctl.h b/arch/arm/plat-omap/include/dspbridge/wcdioctl.h
+new file mode 100644
+index 0000000..04b13ab
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wcdioctl.h
+@@ -0,0 +1,519 @@
++/*
++ * wcdioctl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== wcdioctl.h ========
++ *  Purpose:
++ *      Contains structures and commands that are used for interaction
++ *      between the DDSP API and class driver.
++ *
++ *! Revision History
++ *! ================
++ *! 19-Apr-2004 sb  Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb  Added the Dynamic Memory Mapping structs & offsets
++ *! 15-Oct-2002 kc  Updated definitions for private PERF module.
++ *! 16-Aug-2002 map Added ARGS_MGR_REGISTEROBJECT & ARGS_MGR_UNREGISTEROBJECT
++ *!            Added CMD_MGR_REGISTEROBJECT_OFFSET &
++ *!            CMD_MGR_UNREGISTEROBJECT_OFFSET
++ *! 15-Jan-2002 ag  Added actaul bufSize to ARGS_STRM_[RECLAIM][ISSUE].
++ *! 15-Nov-2001 ag  change to STRMINFO in ARGS_STRM_GETINFO.
++ *! 11-Sep-2001 ag  ARGS_CMM_GETHANDLE defn uses DSP_HPROCESSOR.
++ *! 23-Apr-2001 jeh Added pStatus to NODE_TERMINATE args.
++ *! 13-Feb-2001 kc  DSP/BIOS Bridge name updates.
++ *! 22-Nov-2000 kc: Added CMD_MGR_GETPERF_DATA_OFFSET for acquiring PERF stats.
++ *! 27-Oct-2000 jeh Added timeouts to NODE_GETMESSAGE, NODE_PUTMESSAGE args.
++ *!            Removed NODE_GETMESSAGESTRM args.
++ *! 11-Oct-2000 ag: Added SM mgr(CMM) args.
++ *! 27-Sep-2000 jeh Removed struct DSP_BUFFERATTR param from
++ *!               ARGS_STRM_ALLOCATEBUFFER.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 07-Sep-2000 jeh Changed HANDLE to DSP_HNOTIFICATION in RegisterNotify args.
++ *!            Added DSP_STRMATTR to DSPNode_Connect args.
++ *! 04-Aug-2000 rr: MEM and UTIL added to RM.
++ *! 27-Jul-2000 rr: NODE, MGR,STRM and PROC added
++ *! 27-Jun-2000 rr: Modifed to Use either PM or DSP/BIOS Bridge
++ *!            IFDEF to build for PM or DSP/BIOS Bridge
++ *! 28-Jan-2000 rr: NT_CMD_FROM_OFFSET moved out to dsptrap.h
++ *! 24-Jan-2000 rr: Merged with Scott's code.
++ *! 21-Jan-2000 sg: In ARGS_CHNL_GETMODE changed mode to be u32 to be
++ *!            consistent with chnldefs.h.
++ *! 11-Jan-2000 rr: CMD_CFG_GETCDVERSION_OFFSET added.
++ *! 12-Nov-1999 rr: CMD_BRD_MONITOR_OFFSET added
++ *! 09-Nov-1999 kc: Added MEMRY and enabled CMD_BRD_IOCTL_OFFSET.
++ *! 05-Nov-1999 ag: Added CHNL.
++ *! 02-Nov-1999 kc: Removed field from ARGS_UTIL_TESTDLL.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 08-Oct-1999 rr: Util control offsets added.
++ *! 13-Sep-1999 kc: Added ARGS_UTIL_TESTDLL for PM test infrastructure.
++ *! 19-Aug-1999 rr: Created from WSX. Minimal Implementaion of BRD_Start and BRD
++ *!            and BRD_Stop. IOCTL Offsets and CTRL Code.
++ */
++
++#ifndef WCDIOCTL_
++#define WCDIOCTL_
++
++#include <dspbridge/mem.h>
++#include <dspbridge/cmm.h>
++#include <dspbridge/strmdefs.h>
++#include <dspbridge/dbdcd.h>
++
++union Trapped_Args {
++
++      /* MGR Module */
++      struct {
++              u32 uNode;
++              struct DSP_NDBPROPS __user *pNDBProps;
++              u32 uNDBPropsSize;
++              u32 __user *puNumNodes;
++      } ARGS_MGR_ENUMNODE_INFO;
++
++      struct {
++              u32 uProcessor;
++              struct DSP_PROCESSORINFO __user *pProcessorInfo;
++              u32 uProcessorInfoSize;
++              u32 __user *puNumProcs;
++      } ARGS_MGR_ENUMPROC_INFO;
++
++      struct {
++              struct DSP_UUID *pUuid;
++              enum DSP_DCDOBJTYPE objType;
++              char *pszPathName;
++      } ARGS_MGR_REGISTEROBJECT;
++
++      struct {
++              struct DSP_UUID *pUuid;
++              enum DSP_DCDOBJTYPE objType;
++      } ARGS_MGR_UNREGISTEROBJECT;
++
++      struct {
++              struct DSP_NOTIFICATION  __user*__user *aNotifications;
++              u32 uCount;
++              u32 __user *puIndex;
++              u32 uTimeout;
++      } ARGS_MGR_WAIT;
++
++      /* PROC Module */
++      struct {
++              u32 uProcessor;
++              struct DSP_PROCESSORATTRIN __user *pAttrIn;
++              DSP_HPROCESSOR __user *phProcessor;
++      } ARGS_PROC_ATTACH;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              u32 dwCmd;
++              struct DSP_CBDATA __user *pArgs;
++      } ARGS_PROC_CTRL;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++      } ARGS_PROC_DETACH;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              DSP_HNODE __user *aNodeTab;
++              u32 uNodeTabSize;
++              u32 __user *puNumNodes;
++              u32 __user *puAllocated;
++      } ARGS_PROC_ENUMNODE_INFO;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              u32 uResourceType;
++              struct DSP_RESOURCEINFO *pResourceInfo;
++              u32 uResourceInfoSize;
++      } ARGS_PROC_ENUMRESOURCES;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              struct DSP_PROCESSORSTATE __user *pProcStatus;
++              u32 uStateInfoSize;
++      } ARGS_PROC_GETSTATE;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              u8 __user *pBuf;
++
++      #ifndef RES_CLEANUP_DISABLE
++          u8 __user *pSize;
++    #endif
++              u32 uMaxSize;
++      } ARGS_PROC_GETTRACE;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              s32 iArgc;
++              char __user*__user *aArgv;
++              char *__user *aEnvp;
++      } ARGS_PROC_LOAD;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              u32 uEventMask;
++              u32 uNotifyType;
++              struct DSP_NOTIFICATION __user *hNotification;
++      } ARGS_PROC_REGISTER_NOTIFY;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++      } ARGS_PROC_START;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              u32 ulSize;
++              void *__user *ppRsvAddr;
++      } ARGS_PROC_RSVMEM;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              u32 ulSize;
++              void *pRsvAddr;
++      } ARGS_PROC_UNRSVMEM;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              void *pMpuAddr;
++              u32 ulSize;
++              void *pReqAddr;
++              void *__user *ppMapAddr;
++              u32 ulMapAttr;
++      } ARGS_PROC_MAPMEM;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              u32 ulSize;
++              void *pMapAddr;
++      } ARGS_PROC_UNMAPMEM;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              void *pMpuAddr;
++              u32 ulSize;
++              u32 ulFlags;
++      } ARGS_PROC_FLUSHMEMORY;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++      } ARGS_PROC_STOP;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              void *pMpuAddr;
++              u32 ulSize;
++      } ARGS_PROC_INVALIDATEMEMORY;
++
++
++      /* NODE Module */
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              struct DSP_UUID __user *pNodeID;
++              struct DSP_CBDATA __user *pArgs;
++              struct DSP_NODEATTRIN __user *pAttrIn;
++              DSP_HNODE __user *phNode;
++      } ARGS_NODE_ALLOCATE;
++
++      struct {
++              DSP_HNODE hNode;
++              u32 uSize;
++              struct DSP_BUFFERATTR __user *pAttr;
++              u8 *__user *pBuffer;
++      } ARGS_NODE_ALLOCMSGBUF;
++
++      struct {
++              DSP_HNODE hNode;
++              s32 iPriority;
++      } ARGS_NODE_CHANGEPRIORITY;
++
++      struct {
++              DSP_HNODE hNode;
++              u32 uStream;
++              DSP_HNODE hOtherNode;
++              u32 uOtherStream;
++              struct DSP_STRMATTR __user *pAttrs;
++              struct DSP_CBDATA __user *pConnParam;
++      } ARGS_NODE_CONNECT;
++
++      struct {
++              DSP_HNODE hNode;
++      } ARGS_NODE_CREATE;
++
++      struct {
++              DSP_HNODE hNode;
++      } ARGS_NODE_DELETE;
++
++      struct {
++              DSP_HNODE hNode;
++              struct DSP_BUFFERATTR __user *pAttr;
++              u8 *pBuffer;
++      } ARGS_NODE_FREEMSGBUF;
++
++      struct {
++              DSP_HNODE hNode;
++              struct DSP_NODEATTR __user *pAttr;
++              u32 uAttrSize;
++      } ARGS_NODE_GETATTR;
++
++      struct {
++              DSP_HNODE hNode;
++              struct DSP_MSG __user *pMessage;
++              u32 uTimeout;
++      } ARGS_NODE_GETMESSAGE;
++
++      struct {
++              DSP_HNODE hNode;
++      } ARGS_NODE_PAUSE;
++
++      struct {
++              DSP_HNODE hNode;
++              struct DSP_MSG __user *pMessage;
++              u32 uTimeout;
++      } ARGS_NODE_PUTMESSAGE;
++
++      struct {
++              DSP_HNODE hNode;
++              u32 uEventMask;
++              u32 uNotifyType;
++              struct DSP_NOTIFICATION __user *hNotification;
++      } ARGS_NODE_REGISTERNOTIFY;
++
++      struct {
++              DSP_HNODE hNode;
++      } ARGS_NODE_RUN;
++
++      struct {
++              DSP_HNODE hNode;
++              DSP_STATUS __user *pStatus;
++      } ARGS_NODE_TERMINATE;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              struct DSP_UUID __user *pNodeID;
++              struct DSP_NDBPROPS __user *pNodeProps;
++      } ARGS_NODE_GETUUIDPROPS;
++
++      /* STRM module */
++
++      struct {
++              DSP_HSTREAM hStream;
++              u32 uSize;
++              u8 *__user *apBuffer;
++              u32 uNumBufs;
++      } ARGS_STRM_ALLOCATEBUFFER;
++
++      struct {
++              DSP_HSTREAM hStream;
++      } ARGS_STRM_CLOSE;
++
++      struct {
++              DSP_HSTREAM hStream;
++              u8 *__user *apBuffer;
++              u32 uNumBufs;
++      } ARGS_STRM_FREEBUFFER;
++
++      struct {
++              DSP_HSTREAM hStream;
++              HANDLE *phEvent;
++      } ARGS_STRM_GETEVENTHANDLE;
++
++      struct {
++              DSP_HSTREAM hStream;
++              struct STRM_INFO __user *pStreamInfo;
++              u32 uStreamInfoSize;
++      } ARGS_STRM_GETINFO;
++
++      struct {
++              DSP_HSTREAM hStream;
++              bool bFlush;
++      } ARGS_STRM_IDLE;
++
++      struct {
++              DSP_HSTREAM hStream;
++              u8 *pBuffer;
++              u32 dwBytes;
++              u32 dwBufSize;
++              u32 dwArg;
++      } ARGS_STRM_ISSUE;
++
++      struct {
++              DSP_HNODE hNode;
++              u32 uDirection;
++              u32 uIndex;
++              struct STRM_ATTR __user *pAttrIn;
++              DSP_HSTREAM __user *phStream;
++      } ARGS_STRM_OPEN;
++
++      struct {
++              DSP_HSTREAM hStream;
++              u8 *__user *pBufPtr;
++              u32 __user *pBytes;
++              u32 __user *pBufSize;
++              u32 __user *pdwArg;
++      } ARGS_STRM_RECLAIM;
++
++      struct {
++              DSP_HSTREAM hStream;
++              u32 uEventMask;
++              u32 uNotifyType;
++              struct DSP_NOTIFICATION __user *hNotification;
++      } ARGS_STRM_REGISTERNOTIFY;
++
++      struct {
++              DSP_HSTREAM __user *aStreamTab;
++              u32 nStreams;
++              u32 __user *pMask;
++              u32 uTimeout;
++      } ARGS_STRM_SELECT;
++
++      /* CMM Module */
++      struct {
++              struct CMM_OBJECT *hCmmMgr;
++              u32 uSize;
++              struct CMM_ATTRS *pAttrs;
++              OUT void **ppBufVA;
++      } ARGS_CMM_ALLOCBUF;
++
++      struct {
++              struct CMM_OBJECT *hCmmMgr;
++              void *pBufPA;
++              u32 ulSegId;
++      } ARGS_CMM_FREEBUF;
++
++      struct {
++              DSP_HPROCESSOR hProcessor;
++              struct CMM_OBJECT *__user *phCmmMgr;
++      } ARGS_CMM_GETHANDLE;
++
++      struct {
++              struct CMM_OBJECT *hCmmMgr;
++              struct CMM_INFO __user *pCmmInfo;
++      } ARGS_CMM_GETINFO;
++
++      /* MEM Module */
++      struct {
++              u32 cBytes;
++              enum MEM_POOLATTRS type;
++              void *pMem;
++      } ARGS_MEM_ALLOC;
++
++      struct {
++              u32 cBytes;
++              enum MEM_POOLATTRS type;
++              void *pMem;
++      } ARGS_MEM_CALLOC;
++
++      struct {
++              void *pMem;
++      } ARGS_MEM_FREE;
++
++      struct {
++              void *pBuffer;
++              u32 cSize;
++              void *pLockedBuffer;
++      } ARGS_MEM_PAGELOCK;
++
++      struct {
++              void *pBuffer;
++              u32 cSize;
++      } ARGS_MEM_PAGEUNLOCK;
++
++      /* UTIL module */
++      struct {
++              s32 cArgc;
++              char **ppArgv;
++      } ARGS_UTIL_TESTDLL;
++} ;
++
++#define CMD_BASE                  1
++
++/* MGR module offsets */
++#define CMD_MGR_BASE_OFFSET        CMD_BASE
++#define CMD_MGR_ENUMNODE_INFO_OFFSET    (CMD_MGR_BASE_OFFSET + 0)
++#define CMD_MGR_ENUMPROC_INFO_OFFSET    (CMD_MGR_BASE_OFFSET + 1)
++#define CMD_MGR_REGISTEROBJECT_OFFSET   (CMD_MGR_BASE_OFFSET + 2)
++#define CMD_MGR_UNREGISTEROBJECT_OFFSET (CMD_MGR_BASE_OFFSET + 3)
++#define CMD_MGR_WAIT_OFFSET        (CMD_MGR_BASE_OFFSET + 4)
++
++#ifndef RES_CLEANUP_DISABLE
++#define CMD_MGR_RESOUCES_OFFSET        (CMD_MGR_BASE_OFFSET + 5)
++#define CMD_MGR_END_OFFSET          CMD_MGR_RESOUCES_OFFSET
++#else
++#define CMD_MGR_END_OFFSET          CMD_MGR_WAIT_OFFSET
++#endif
++
++#define CMD_PROC_BASE_OFFSET      (CMD_MGR_END_OFFSET + 1)
++#define CMD_PROC_ATTACH_OFFSET          (CMD_PROC_BASE_OFFSET + 0)
++#define CMD_PROC_CTRL_OFFSET      (CMD_PROC_BASE_OFFSET + 1)
++#define CMD_PROC_DETACH_OFFSET          (CMD_PROC_BASE_OFFSET + 2)
++#define CMD_PROC_ENUMNODE_OFFSET      (CMD_PROC_BASE_OFFSET + 3)
++#define CMD_PROC_ENUMRESOURCES_OFFSET   (CMD_PROC_BASE_OFFSET + 4)
++#define CMD_PROC_GETSTATE_OFFSET      (CMD_PROC_BASE_OFFSET + 5)
++#define CMD_PROC_GETTRACE_OFFSET      (CMD_PROC_BASE_OFFSET + 6)
++#define CMD_PROC_LOAD_OFFSET      (CMD_PROC_BASE_OFFSET + 7)
++#define CMD_PROC_REGISTERNOTIFY_OFFSET  (CMD_PROC_BASE_OFFSET + 8)
++#define CMD_PROC_START_OFFSET    (CMD_PROC_BASE_OFFSET + 9)
++#define CMD_PROC_RSVMEM_OFFSET          (CMD_PROC_BASE_OFFSET + 10)
++#define CMD_PROC_UNRSVMEM_OFFSET      (CMD_PROC_BASE_OFFSET + 11)
++#define CMD_PROC_MAPMEM_OFFSET          (CMD_PROC_BASE_OFFSET + 12)
++#define CMD_PROC_UNMAPMEM_OFFSET      (CMD_PROC_BASE_OFFSET + 13)
++#define CMD_PROC_FLUSHMEMORY_OFFSET      (CMD_PROC_BASE_OFFSET + 14)
++#define CMD_PROC_STOP_OFFSET      (CMD_PROC_BASE_OFFSET + 15)
++#define CMD_PROC_INVALIDATEMEMORY_OFFSET (CMD_PROC_BASE_OFFSET + 16)
++#define CMD_PROC_END_OFFSET        CMD_PROC_INVALIDATEMEMORY_OFFSET
++
++
++#define CMD_NODE_BASE_OFFSET      (CMD_PROC_END_OFFSET + 1)
++#define CMD_NODE_ALLOCATE_OFFSET      (CMD_NODE_BASE_OFFSET + 0)
++#define CMD_NODE_ALLOCMSGBUF_OFFSET     (CMD_NODE_BASE_OFFSET + 1)
++#define CMD_NODE_CHANGEPRIORITY_OFFSET  (CMD_NODE_BASE_OFFSET + 2)
++#define CMD_NODE_CONNECT_OFFSET        (CMD_NODE_BASE_OFFSET + 3)
++#define CMD_NODE_CREATE_OFFSET          (CMD_NODE_BASE_OFFSET + 4)
++#define CMD_NODE_DELETE_OFFSET          (CMD_NODE_BASE_OFFSET + 5)
++#define CMD_NODE_FREEMSGBUF_OFFSET      (CMD_NODE_BASE_OFFSET + 6)
++#define CMD_NODE_GETATTR_OFFSET        (CMD_NODE_BASE_OFFSET + 7)
++#define CMD_NODE_GETMESSAGE_OFFSET      (CMD_NODE_BASE_OFFSET + 8)
++#define CMD_NODE_PAUSE_OFFSET    (CMD_NODE_BASE_OFFSET + 9)
++#define CMD_NODE_PUTMESSAGE_OFFSET      (CMD_NODE_BASE_OFFSET + 10)
++#define CMD_NODE_REGISTERNOTIFY_OFFSET  (CMD_NODE_BASE_OFFSET + 11)
++#define CMD_NODE_RUN_OFFSET        (CMD_NODE_BASE_OFFSET + 12)
++#define CMD_NODE_TERMINATE_OFFSET       (CMD_NODE_BASE_OFFSET + 13)
++#define CMD_NODE_GETUUIDPROPS_OFFSET    (CMD_NODE_BASE_OFFSET + 14)
++#define CMD_NODE_END_OFFSET        CMD_NODE_GETUUIDPROPS_OFFSET
++
++#define CMD_STRM_BASE_OFFSET      (CMD_NODE_END_OFFSET + 1)
++#define CMD_STRM_ALLOCATEBUFFER_OFFSET  (CMD_STRM_BASE_OFFSET + 0)
++#define CMD_STRM_CLOSE_OFFSET    (CMD_STRM_BASE_OFFSET + 1)
++#define CMD_STRM_FREEBUFFER_OFFSET      (CMD_STRM_BASE_OFFSET + 2)
++#define CMD_STRM_GETEVENTHANDLE_OFFSET  (CMD_STRM_BASE_OFFSET + 3)
++#define CMD_STRM_GETINFO_OFFSET        (CMD_STRM_BASE_OFFSET + 4)
++#define CMD_STRM_IDLE_OFFSET      (CMD_STRM_BASE_OFFSET + 5)
++#define CMD_STRM_ISSUE_OFFSET    (CMD_STRM_BASE_OFFSET + 6)
++#define CMD_STRM_OPEN_OFFSET      (CMD_STRM_BASE_OFFSET + 7)
++#define CMD_STRM_RECLAIM_OFFSET        (CMD_STRM_BASE_OFFSET + 8)
++#define CMD_STRM_REGISTERNOTIFY_OFFSET  (CMD_STRM_BASE_OFFSET + 9)
++#define CMD_STRM_SELECT_OFFSET          (CMD_STRM_BASE_OFFSET + 10)
++#define CMD_STRM_END_OFFSET        CMD_STRM_SELECT_OFFSET
++
++/* Communication Memory Manager (UCMM) */
++#define CMD_CMM_BASE_OFFSET        (CMD_STRM_END_OFFSET + 1)
++#define CMD_CMM_ALLOCBUF_OFFSET        (CMD_CMM_BASE_OFFSET + 0)
++#define CMD_CMM_FREEBUF_OFFSET          (CMD_CMM_BASE_OFFSET + 1)
++#define CMD_CMM_GETHANDLE_OFFSET      (CMD_CMM_BASE_OFFSET + 2)
++#define CMD_CMM_GETINFO_OFFSET          (CMD_CMM_BASE_OFFSET + 3)
++#define CMD_CMM_END_OFFSET          CMD_CMM_GETINFO_OFFSET
++
++#define CMD_BASE_END_OFFSET   CMD_CMM_END_OFFSET
++#endif                                /* WCDIOCTL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmd.h b/arch/arm/plat-omap/include/dspbridge/wmd.h
+new file mode 100644
+index 0000000..f584038
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmd.h
+@@ -0,0 +1,1193 @@
++/*
++ * wmd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== wmd.h ========
++ *  Purpose:
++ *      'Bridge mini driver entry point and interface function declarations.
++ *
++ *  Public Functions:
++ *      WMD_DRV_Entry
++ *
++ *  Notes:
++ *      The 'Bridge class driver obtains it's function interface to
++ *      the 'Bridge mini driver via a call to WMD_DRV_Entry().
++ *
++ *      'Bridge Class Driver services exported to WMD's are initialized by the
++ *      WCD on behalf of the WMD.
++ *
++ *      WMD function DBC Requires and Ensures are also made by the WCD on
++ *      behalf of the WMD, to simplify the WMD code.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb  Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb  Added the Dynamic Memory Mapping APIs - WMD_BRD_MemMap/UnMap
++ *! 01-Mar-2004 vp  Added filename argument to WMD_DRV_Entry function.
++ *! 29-Aug-2002 map Added WMD_BRD_MemWrite()
++ *! 26-Aug-2002 map Added WMD_BRD_MemCopy()
++ *! 07-Jan-2002 ag  Added cBufSize to WMD_CHNL_AddIOReq().
++ *! 05-Nov-2001 kc: Added error handling DEH functions.
++ *! 06-Dec-2000 jeh Added uEventMask to WMD_MSG_RegisterNotify().
++ *! 17-Nov-2000 jeh Added WMD_MSG and WMD_IO definitions.
++ *! 01-Nov-2000 jeh Added more error codes to WMD_CHNL_RegisterNotify().
++ *! 13-Oct-2000 jeh Added dwArg to WMD_CHNL_AddIOReq(), added WMD_CHNL_IDLE
++ *!                 and WMD_CHNL_RegisterNotify for DSPStream support.
++ *! 17-Jan-2000 rr: WMD_BRD_SETSTATE Added.
++ *! 30-Jul-1997 gp: Split wmd IOCTL space into reserved and private.
++ *! 07-Nov-1996 gp: Updated for code review.
++ *! 18-Oct-1996 gp: Added WMD_E_HARDWARE return code from WMD_BRD_Monitor.
++ *! 09-Sep-1996 gp: Subtly altered the semantics of WMD_CHNL_GetInfo().
++ *! 02-Aug-1996 gp: Ensured on BRD_Start that interrupts to the PC are enabled.
++ *! 11-Jul-1996 gp: Added CHNL interface. Note stronger DBC_Require conditions.
++ *! 29-May-1996 gp: Removed WCD_ prefix from functions imported from WCD.LIB.
++ *! 29-May-1996 gp: Made OUT param first in WMD_DEV_Create().
++ *! 09-May-1996 gp: Created.
++ */
++
++#ifndef WMD_
++#define WMD_
++
++#include <dspbridge/brddefs.h>
++#include <dspbridge/cfgdefs.h>
++#include <dspbridge/chnlpriv.h>
++#include <dspbridge/dehdefs.h>
++#include <dspbridge/devdefs.h>
++#include <dspbridge/iodefs.h>
++#include <dspbridge/msgdefs.h>
++
++/*
++ *  Any IOCTLS at or above this value are reserved for standard WMD
++ *  interfaces.
++ */
++#define WMD_RESERVEDIOCTLBASE   0x8000
++
++/* Handle to mini-driver's private device context.  */
++      struct WMD_DEV_CONTEXT;
++
++/*---------------------------------------------------------------------------*/
++/* 'Bridge MINI DRIVER FUNCTION TYPES                                        */
++/*---------------------------------------------------------------------------*/
++
++/*
++ *  ======== WMD_BRD_Monitor ========
++ *  Purpose:
++ *      Bring the board to the BRD_IDLE (monitor) state.
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device context.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      WMD_E_HARDWARE: A test of hardware assumptions/integrity failed.
++ *      WMD_E_TIMEOUT:  Timeout occured waiting for a response from hardware.
++ *      DSP_EFAIL:      Other, unspecified error.
++ *  Requires:
++ *      hDevContext != NULL
++ *  Ensures:
++ *      DSP_SOK:        Board is in BRD_IDLE state;
++ *      else:           Board state is indeterminate.
++ */
++       typedef DSP_STATUS(
++                         *WMD_BRD_MONITOR) (struct WMD_DEV_CONTEXT
++                         *hDevContext);
++
++/*
++ *  ======== WMD_BRD_SETSTATE ========
++ *  Purpose:
++ *      Sets the Mini driver state
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device info.
++ *      ulBrdState:     Board state
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Other, unspecified error.
++ *  Requires:
++ *      hDevContext != NULL;
++ *      ulBrdState  <= BRD_LASTSTATE.
++ *  Ensures:
++ *      ulBrdState  <= BRD_LASTSTATE.
++ *  Update the Board state to the specified state.
++ */
++       typedef DSP_STATUS(
++                         *WMD_BRD_SETSTATE) (struct WMD_DEV_CONTEXT
++                         *hDevContext, u32 ulBrdState);
++
++/*
++ *  ======== WMD_BRD_Start ========
++ *  Purpose:
++ *      Bring board to the BRD_RUNNING (start) state.
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device context.
++ *      dwDSPAddr:      DSP address at which to start execution.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      WMD_E_TIMEOUT:  Timeout occured waiting for a response from hardware.
++ *      DSP_EFAIL:      Other, unspecified error.
++ *  Requires:
++ *      hDevContext != NULL
++ *      Board is in monitor (BRD_IDLE) state.
++ *  Ensures:
++ *      DSP_SOK:        Board is in BRD_RUNNING state.
++ *                      Interrupts to the PC are enabled.
++ *      else:           Board state is indeterminate.
++ */
++       typedef DSP_STATUS(*WMD_BRD_START) (struct WMD_DEV_CONTEXT
++                                              *hDevContext, u32 dwDSPAddr);
++
++/*
++ *  ======== WMD_BRD_MemCopy ========
++ *  Purpose:
++ *  Copy memory from one DSP address to another
++ *  Parameters:
++ *      pDevContext:    Pointer to context handle
++ *  ulDspDestAddr:  DSP address to copy to
++ *  ulDspSrcAddr:   DSP address to copy from
++ *  ulNumBytes: Number of bytes to copy
++ *  ulMemType:  What section of memory to copy to
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Other, unspecified error.
++ *  Requires:
++ *      pDevContext != NULL
++ *  Ensures:
++ *      DSP_SOK:        Board is in BRD_RUNNING state.
++ *                      Interrupts to the PC are enabled.
++ *      else:           Board state is indeterminate.
++ */
++       typedef DSP_STATUS(*WMD_BRD_MEMCOPY) (struct WMD_DEV_CONTEXT
++                                           *hDevContext,
++                                           u32 ulDspDestAddr,
++                                           u32 ulDspSrcAddr,
++                                           u32 ulNumBytes, u32 ulMemType);
++/*
++ *  ======== WMD_BRD_MemWrite ========
++ *  Purpose:
++ *      Write a block of host memory into a DSP address, into a given memory
++ *      space.  Unlike WMD_BRD_Write, this API does reset the DSP
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device info.
++ *      dwDSPAddr:      Address on DSP board (Destination).
++ *      pHostBuf:       Pointer to host buffer (Source).
++ *      ulNumBytes:     Number of bytes to transfer.
++ *      ulMemType:      Memory space on DSP to which to transfer.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      WMD_E_TIMEOUT:  Timeout occured waiting for a response from hardware.
++ *      DSP_EFAIL:      Other, unspecified error.
++ *  Requires:
++ *      hDevContext != NULL;
++ *      pHostBuf != NULL.
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_BRD_MEMWRITE) (struct WMD_DEV_CONTEXT
++                                      *hDevContext,
++                                      IN u8 *pHostBuf,
++                                      u32 dwDSPAddr, u32 ulNumBytes,
++                                      u32 ulMemType);
++
++/*
++ *  ======== WMD_BRD_MemMap ========
++ *  Purpose:
++ *      Map a MPU memory region to a DSP/IVA memory space
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device info.
++ *      ulMpuAddr:      MPU memory region start address.
++ *      ulVirtAddr:     DSP/IVA memory region u8 address.
++ *      ulNumBytes:     Number of bytes to map.
++ *      mapAttrs:       Mapping attributes (e.g. endianness).
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Other, unspecified error.
++ *  Requires:
++ *      hDevContext != NULL;
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_BRD_MEMMAP) (struct WMD_DEV_CONTEXT
++                                      *hDevContext, u32 ulMpuAddr,
++                                      u32 ulVirtAddr, u32 ulNumBytes,
++                                      u32 ulMapAttrs);
++
++/*
++ *  ======== WMD_BRD_MemUnMap ========
++ *  Purpose:
++ *      UnMap an MPU memory region from DSP/IVA memory space
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device info.
++ *      ulVirtAddr:     DSP/IVA memory region u8 address.
++ *      ulNumBytes:     Number of bytes to unmap.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Other, unspecified error.
++ *  Requires:
++ *      hDevContext != NULL;
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_BRD_MEMUNMAP) (struct WMD_DEV_CONTEXT
++                                      *hDevContext,
++                                      u32 ulVirtAddr,
++                                      u32 ulNumBytes);
++
++/*
++ *  ======== WMD_BRD_Stop ========
++ *  Purpose:
++ *      Bring board to the BRD_STOPPED state.
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device context.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      WMD_E_TIMEOUT:  Timeout occured waiting for a response from hardware.
++ *      DSP_EFAIL:      Other, unspecified error.
++ *  Requires:
++ *      hDevContext != NULL
++ *  Ensures:
++ *      DSP_SOK:        Board is in BRD_STOPPED (stop) state;
++ *                      Interrupts to the PC are disabled.
++ *      else:           Board state is indeterminate.
++ */
++       typedef DSP_STATUS(*WMD_BRD_STOP) (struct WMD_DEV_CONTEXT
++                                      *hDevContext);
++
++/*
++ *  ======== WMD_BRD_Status ========
++ *  Purpose:
++ *      Report the current state of the board.
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device context.
++ *      pdwState:       Ptr to BRD status variable.
++ *  Returns:
++ *      DSP_SOK:
++ *  Requires:
++ *      pdwState != NULL;
++ *      hDevContext != NULL
++ *  Ensures:
++ *      *pdwState is one of {BRD_STOPPED, BRD_IDLE, BRD_RUNNING, BRD_UNKNOWN};
++ */
++       typedef DSP_STATUS(*
++                         WMD_BRD_STATUS) (struct WMD_DEV_CONTEXT *hDevContext,
++                                          OUT BRD_STATUS * pdwState);
++
++/*
++ *  ======== WMD_BRD_Read ========
++ *  Purpose:
++ *      Read a block of DSP memory, from a given memory space, into a host
++ *      buffer.
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device info.
++ *      pHostBuf:       Pointer to host buffer (Destination).
++ *      dwDSPAddr:      Address on DSP board (Source).
++ *      ulNumBytes:     Number of bytes to transfer.
++ *      ulMemType:      Memory space on DSP from which to transfer.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      WMD_E_TIMEOUT:  Timeout occured waiting for a response from hardware.
++ *      DSP_EFAIL:      Other, unspecified error.
++ *  Requires:
++ *      hDevContext != NULL;
++ *      pHostBuf != NULL.
++ *  Ensures:
++ *  Will not write more than ulNumBytes bytes into pHostBuf.
++ */
++typedef DSP_STATUS(*WMD_BRD_READ) (struct WMD_DEV_CONTEXT *hDevContext,
++                                                OUT u8 *pHostBuf,
++                                                u32 dwDSPAddr,
++                                                u32 ulNumBytes,
++                                                u32 ulMemType);
++
++/*
++ *  ======== WMD_BRD_Write ========
++ *  Purpose:
++ *      Write a block of host memory into a DSP address, into a given memory
++ *      space.
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device info.
++ *      dwDSPAddr:      Address on DSP board (Destination).
++ *      pHostBuf:       Pointer to host buffer (Source).
++ *      ulNumBytes:     Number of bytes to transfer.
++ *      ulMemType:      Memory space on DSP to which to transfer.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      WMD_E_TIMEOUT:  Timeout occured waiting for a response from hardware.
++ *      DSP_EFAIL:      Other, unspecified error.
++ *  Requires:
++ *      hDevContext != NULL;
++ *      pHostBuf != NULL.
++ *  Ensures:
++ */
++typedef DSP_STATUS(*WMD_BRD_WRITE)(struct WMD_DEV_CONTEXT *hDevContext,
++                                                 IN u8 *pHostBuf,
++                                                 u32 dwDSPAddr,
++                                                 u32 ulNumBytes,
++                                                 u32 ulMemType);
++
++/*
++ *  ======== WMD_CHNL_Create ========
++ *  Purpose:
++ *      Create a channel manager object, responsible for opening new channels
++ *      and closing old ones for a given 'Bridge board.
++ *  Parameters:
++ *      phChnlMgr:      Location to store a channel manager object on output.
++ *      hDevObject:     Handle to a device object.
++ *      pMgrAttrs:      Channel manager attributes.
++ *      pMgrAttrs->cChannels: Max channels
++ *      pMgrAttrs->bIRQ:      Channel's I/O IRQ number.
++ *      pMgrAttrs->fShared:   TRUE if the IRQ is shareable.
++ *      pMgrAttrs->uWordSize: DSP Word size in equivalent PC bytes..
++ *      pMgrAttrs->dwSMBase:  Base physical address of shared memory, if any.
++ *      pMgrAttrs->uSMLength: Bytes of shared memory block.
++ *  Returns:
++ *      DSP_SOK:            Success;
++ *      DSP_EMEMORY:        Insufficient memory for requested resources.
++ *      CHNL_E_ISR:         Unable to plug ISR for given IRQ.
++ *      CHNL_E_NOMEMMAP:    Couldn't map physical address to a virtual one.
++ *  Requires:
++ *      phChnlMgr != NULL.
++ *      pMgrAttrs != NULL
++ *      pMgrAttrs field are all valid:
++ *          0 < cChannels <= CHNL_MAXCHANNELS.
++ *          bIRQ <= 15.
++ *          uWordSize > 0.
++ *      IsValidHandle(hDevObject)
++ *      No channel manager exists for this board.
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_CHNL_CREATE)(OUT struct CHNL_MGR
++                                                  **phChnlMgr,
++                                                  struct DEV_OBJECT
++                                                  *hDevObject,
++                                                  IN CONST struct
++                                                  CHNL_MGRATTRS *pMgrAttrs);
++
++/*
++ *  ======== WMD_CHNL_Destroy ========
++ *  Purpose:
++ *      Close all open channels, and destroy the channel manager.
++ *  Parameters:
++ *      hChnlMgr:       Channel manager object.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    hChnlMgr was invalid.
++ *  Requires:
++ *  Ensures:
++ *      DSP_SOK: Cancels I/O on each open channel. Closes each open channel.
++ *          CHNL_Create may subsequently be called for the same device.
++ */
++       typedef DSP_STATUS(*WMD_CHNL_DESTROY) (struct CHNL_MGR
++                                                    *hChnlMgr);
++/*
++ *  ======== WMD_DEH_Notify ========
++ *  Purpose:
++ *      When notified of DSP error, take appropriate action.
++ *  Parameters:
++ *      hDehMgr:        Handle to DEH manager object.
++ *      ulEventMask:  Indicate the type of exception
++ *      dwErrInfo:     Error information
++ *  Returns:
++ *
++ *  Requires:
++ *      hDehMgr != NULL;
++ *     ulEventMask with a valid exception
++ *  Ensures:
++ */
++       typedef void (*WMD_DEH_NOTIFY)(struct DEH_MGR *hDehMgr,
++                                      u32 ulEventMask, u32 dwErrInfo);
++
++
++/*
++ *  ======== WMD_CHNL_Open ========
++ *  Purpose:
++ *      Open a new half-duplex channel to the DSP board.
++ *  Parameters:
++ *      phChnl:         Location to store a channel object handle.
++ *      hChnlMgr:       Handle to channel manager, as returned by CHNL_GetMgr().
++ *      uMode:          One of {CHNL_MODETODSP, CHNL_MODEFROMDSP} specifies
++ *                      direction of data transfer.
++ *      uChnlId:        If CHNL_PICKFREE is specified, the channel manager will
++ *                      select a free channel id (default);
++ *                      otherwise this field specifies the id of the channel.
++ *      pAttrs:         Channel attributes.  Attribute fields are as follows:
++ *      pAttrs->uIOReqs: Specifies the maximum number of I/O requests which can
++ *                      be pending at any given time. All request packets are
++ *                      preallocated when the channel is opened.
++ *      pAttrs->hEvent: This field allows the user to supply an auto reset
++ *                      event object for channel I/O completion notifications.
++ *                      It is the responsibility of the user to destroy this
++ *                      object AFTER closing the channel.
++ *                      This channel event object can be retrieved using
++ *                      CHNL_GetEventHandle().
++ *      pAttrs->hReserved: The kernel mode handle of this event object.
++ *
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      DSP_EHANDLE:            hChnlMgr is invalid.
++ *      DSP_EMEMORY:            Insufficient memory for requested resources.
++ *      DSP_EINVALIDARG:        Invalid number of IOReqs.
++ *      CHNL_E_OUTOFSTREAMS:    No free channels available.
++ *      CHNL_E_BADCHANID:       Channel ID is out of range.
++ *      CHNL_E_CHANBUSY:        Channel is in use.
++ *      CHNL_E_NOIORPS:         No free IO request packets available for
++ *                              queuing.
++ *  Requires:
++ *      phChnl != NULL.
++ *      pAttrs != NULL.
++ *      pAttrs->hEvent is a valid event handle.
++ *      pAttrs->hReserved is the kernel mode handle for pAttrs->hEvent.
++ *  Ensures:
++ *      DSP_SOK:                *phChnl is a valid channel.
++ *      else:                   *phChnl is set to NULL if (phChnl != NULL);
++ */
++       typedef DSP_STATUS(*WMD_CHNL_OPEN) (OUT struct CHNL_OBJECT
++                                                 **phChnl,
++                                                 struct CHNL_MGR *hChnlMgr,
++                                                 CHNL_MODE uMode,
++                                                 u32 uChnlId,
++                                                 CONST IN OPTIONAL struct
++                                                 CHNL_ATTRS *pAttrs);
++
++/*
++ *  ======== WMD_CHNL_Close ========
++ *  Purpose:
++ *      Ensures all pending I/O on this channel is cancelled, discards all
++ *      queued I/O completion notifications, then frees the resources allocated
++ *      for this channel, and makes the corresponding logical channel id
++ *      available for subsequent use.
++ *  Parameters:
++ *      hChnl:          Handle to a channel object.
++ *  Returns:
++ *      DSP_SOK:        Success;
++ *      DSP_EHANDLE:    Invalid hChnl.
++ *  Requires:
++ *      No thread must be blocked on this channel's I/O completion event.
++ *  Ensures:
++ *      DSP_SOK:        hChnl is no longer valid.
++ */
++       typedef DSP_STATUS(*WMD_CHNL_CLOSE) (struct CHNL_OBJECT *hChnl);
++
++/*
++ *  ======== WMD_CHNL_AddIOReq ========
++ *  Purpose:
++ *      Enqueue an I/O request for data transfer on a channel to the DSP.
++ *      The direction (mode) is specified in the channel object. Note the DSP
++ *      address is specified for channels opened in direct I/O mode.
++ *  Parameters:
++ *      hChnl:          Channel object handle.
++ *      pHostBuf:       Host buffer address source.
++ *      cBytes:         Number of PC bytes to transfer. A zero value indicates
++ *                      that this buffer is the last in the output channel.
++ *                      A zero value is invalid for an input channel.
++ *!     cBufSize:       Actual buffer size in host bytes.
++ *      dwDspAddr:      DSP address for transfer.  (Currently ignored).
++ *      dwArg:          A user argument that travels with the buffer.
++ *  Returns:
++ *      DSP_SOK:        Success;
++ *      DSP_EHANDLE:    Invalid hChnl.
++ *      DSP_EPOINTER:   pHostBuf is invalid.
++ *      CHNL_E_NOEOS:   User cannot mark EOS on an input channel.
++ *      CHNL_E_CANCELLED: I/O has been cancelled on this channel.  No further
++ *                      I/O is allowed.
++ *      CHNL_E_EOS:     End of stream was already marked on a previous
++ *                      IORequest on this channel.  No further I/O is expected.
++ *      CHNL_E_BUFSIZE: Buffer submitted to this output channel is larger than
++ *                      the size of the physical shared memory output window.
++ *  Requires:
++ *  Ensures:
++ *      DSP_SOK: The buffer will be transferred if the channel is ready;
++ *          otherwise, will be queued for transfer when the channel becomes
++ *          ready.  In any case, notifications of I/O completion are
++ *          asynchronous.
++ *          If cBytes is 0 for an output channel, subsequent CHNL_AddIOReq's
++ *          on this channel will fail with error code CHNL_E_EOS.  The
++ *          corresponding IOC for this I/O request will have its status flag
++ *          set to CHNL_IOCSTATEOS.
++ */
++       typedef DSP_STATUS(*WMD_CHNL_ADDIOREQ) (struct CHNL_OBJECT
++                                                     *hChnl,
++                                                     void *pHostBuf,
++                                                     u32 cBytes,
++                                                     u32 cBufSize,
++                                                     OPTIONAL u32 dwDspAddr,
++                                                     u32 dwArg);
++
++/*
++ *  ======== WMD_CHNL_GetIOC ========
++ *  Purpose:
++ *      Dequeue an I/O completion record, which contains information about the
++ *      completed I/O request.
++ *  Parameters:
++ *      hChnl:          Channel object handle.
++ *      dwTimeOut:      A value of CHNL_IOCNOWAIT will simply dequeue the
++ *                      first available IOC.
++ *      pIOC:           On output, contains host buffer address, bytes
++ *                      transferred, and status of I/O completion.
++ *      pIOC->status:   See chnldefs.h.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EHANDLE:    Invalid hChnl.
++ *      DSP_EPOINTER:   pIOC is invalid.
++ *      CHNL_E_NOIOC:   CHNL_IOCNOWAIT was specified as the dwTimeOut parameter
++ *                      yet no I/O completions were queued.
++ *  Requires:
++ *      dwTimeOut == CHNL_IOCNOWAIT.
++ *  Ensures:
++ *      DSP_SOK: if there are any remaining IOC's queued before this call
++ *          returns, the channel event object will be left in a signalled
++ *          state.
++ */
++       typedef DSP_STATUS(*WMD_CHNL_GETIOC) (struct CHNL_OBJECT *hChnl,
++                                                   u32 dwTimeOut,
++                                                   OUT struct CHNL_IOC *pIOC);
++
++/*
++ *  ======== WMD_CHNL_CancelIO ========
++ *  Purpose:
++ *      Return all I/O requests to the client which have not yet been
++ *      transferred.  The channel's I/O completion object is
++ *      signalled, and all the I/O requests are queued as IOC's, with the
++ *      status field set to CHNL_IOCSTATCANCEL.
++ *      This call is typically used in abort situations, and is a prelude to
++ *      CHNL_Close();
++ *  Parameters:
++ *      hChnl:          Channel object handle.
++ *  Returns:
++ *      DSP_SOK:        Success;
++ *      DSP_EHANDLE:    Invalid hChnl.
++ *  Requires:
++ *  Ensures:
++ *      Subsequent I/O requests to this channel will not be accepted.
++ */
++       typedef DSP_STATUS(*WMD_CHNL_CANCELIO) (struct CHNL_OBJECT
++                                                     *hChnl);
++
++/*
++ *  ======== WMD_CHNL_FlushIO ========
++ *  Purpose:
++ *      For an output stream (to the DSP), indicates if any IO requests are in
++ *      the output request queue.  For input streams (from the DSP), will
++ *      cancel all pending IO requests.
++ *  Parameters:
++ *      hChnl:              Channel object handle.
++ *      dwTimeOut:          Timeout value for flush operation.
++ *  Returns:
++ *      DSP_SOK:            Success;
++ *      S_CHNLIOREQUEST:    Returned if any IORequests are in the output queue.
++ *      DSP_EHANDLE:        Invalid hChnl.
++ *  Requires:
++ *  Ensures:
++ *      DSP_SOK:            No I/O requests will be pending on this channel.
++ */
++       typedef DSP_STATUS(*WMD_CHNL_FLUSHIO) (struct CHNL_OBJECT *hChnl,
++                                                    u32 dwTimeOut);
++
++/*
++ *  ======== WMD_CHNL_GetInfo ========
++ *  Purpose:
++ *      Retrieve information related to a channel.
++ *  Parameters:
++ *      hChnl:          Handle to a valid channel object, or NULL.
++ *      pInfo:          Location to store channel info.
++ *  Returns:
++ *      DSP_SOK:        Success;
++ *      DSP_EHANDLE:    Invalid hChnl.
++ *      DSP_EPOINTER:   pInfo == NULL.
++ *  Requires:
++ *  Ensures:
++ *      DSP_SOK:        pInfo points to a filled in CHNL_INFO struct,
++ *                      if (pInfo != NULL).
++ */
++       typedef DSP_STATUS(*WMD_CHNL_GETINFO) (struct CHNL_OBJECT *hChnl,
++                                                    OUT struct CHNL_INFO
++                                                    *pChnlInfo);
++
++/*
++ *  ======== WMD_CHNL_GetMgrInfo ========
++ *  Purpose:
++ *      Retrieve information related to the channel manager.
++ *  Parameters:
++ *      hChnlMgr:           Handle to a valid channel manager, or NULL.
++ *      uChnlID:            Channel ID.
++ *      pMgrInfo:           Location to store channel manager info.
++ *  Returns:
++ *      DSP_SOK:            Success;
++ *      DSP_EHANDLE:        Invalid hChnlMgr.
++ *      DSP_EPOINTER:       pMgrInfo == NULL.
++ *      CHNL_E_BADCHANID:   Invalid channel ID.
++ *  Requires:
++ *  Ensures:
++ *      DSP_SOK:            pMgrInfo points to a filled in CHNL_MGRINFO
++ *                          struct, if (pMgrInfo != NULL).
++ */
++       typedef DSP_STATUS(*WMD_CHNL_GETMGRINFO) (struct CHNL_MGR
++                                                       *hChnlMgr,
++                                                       u32 uChnlID,
++                                                       OUT struct CHNL_MGRINFO
++                                                       *pMgrInfo);
++
++/*
++ *  ======== WMD_CHNL_Idle ========
++ *  Purpose:
++ *      Idle a channel. If this is an input channel, or if this is an output
++ *      channel and fFlush is TRUE, all currently enqueued buffers will be
++ *      dequeued (data discarded for output channel).
++ *      If this is an output channel and fFlush is FALSE, this function
++ *      will block until all currently buffered data is output, or the timeout
++ *      specified has been reached.
++ *
++ *  Parameters:
++ *      hChnl:          Channel object handle.
++ *      dwTimeOut:      If output channel and fFlush is FALSE, timeout value
++ *                      to wait for buffers to be output. (Not used for
++ *                      input channel).
++ *      fFlush:         If output channel and fFlush is TRUE, discard any
++ *                      currently buffered data. If FALSE, wait for currently
++ *                      buffered data to be output, or timeout, whichever
++ *                      occurs first. fFlush is ignored for input channel.
++ *  Returns:
++ *      DSP_SOK:            Success;
++ *      DSP_EHANDLE:        Invalid hChnl.
++ *      CHNL_E_WAITTIMEOUT: Timeout occured before channel could be idled.
++ *  Requires:
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_CHNL_IDLE) (struct CHNL_OBJECT *hChnl,
++                                                 u32 dwTimeOut,
++                                                 bool fFlush);
++
++/*
++ *  ======== WMD_CHNL_RegisterNotify ========
++ *  Purpose:
++ *      Register for notification of events on a channel.
++ *  Parameters:
++ *      hChnl:          Channel object handle.
++ *      uEventMask:     Type of events to be notified about: IO completion
++ *                      (DSP_STREAMIOCOMPLETION) or end of stream
++ *                      (DSP_STREAMDONE).
++ *      uNotifyType:    DSP_SIGNALEVENT.
++ *      hNotification:  Handle of a DSP_NOTIFICATION object.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Insufficient memory.
++ *      DSP_EVALUE:     uEventMask is 0 and hNotification was not
++ *                      previously registered.
++ *      DSP_EHANDLE:    NULL hNotification, hNotification event name
++ *                      too long, or hNotification event name NULL.
++ *  Requires:
++ *      Valid hChnl.
++ *      hNotification != NULL.
++ *      (uEventMask & ~(DSP_STREAMIOCOMPLETION | DSP_STREAMDONE)) == 0.
++ *      uNotifyType == DSP_SIGNALEVENT.
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_CHNL_REGISTERNOTIFY)
++                              (struct CHNL_OBJECT *hChnl,
++                              u32 uEventMask,
++                              u32 uNotifyType,
++                              struct DSP_NOTIFICATION *hNotification);
++
++/*
++ *  ======== WMD_DEV_Create ========
++ *  Purpose:
++ *      Complete creation of the device object for this board.
++ *  Parameters:
++ *      phDevContext:   Ptr to location to store a WMD device context.
++ *      hDevObject:     Handle to a Device Object, created and managed by WCD.
++ *      pConfig:        Ptr to configuration parameters provided by the Windows
++ *                      Configuration Manager during device loading.
++ *      pDspConfig:     DSP resources, as specified in the registry key for this
++ *                      device.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EMEMORY:        Unable to allocate memory for device context.
++ *      WMD_E_BADCONFIG:    One or more of the host or DSP configuration
++ *                          parameters did not satisfy hardware assumptions
++ *                          made by this WMD.
++ *  Requires:
++ *      phDevContext != NULL;
++ *      hDevObject != NULL;
++ *      pConfig != NULL;
++ *      pDspConfig != NULL;
++ *      Fields in pConfig and pDspConfig contain valid values.
++ *  Ensures:
++ *      DSP_SOK:        All mini-driver specific DSP resource and other
++ *                      board context has been allocated.
++ *      DSP_EMEMORY:    WMD failed to allocate resources.
++ *                      Any acquired resources have been freed.  The WCD will
++ *                      not call WMD_DEV_Destroy() if WMD_DEV_Create() fails.
++ *  Details:
++ *      Called during the CONFIGMG's Device_Init phase. Based on host and
++ *      DSP configuration information, create a board context, a handle to
++ *      which is passed into other WMD BRD and CHNL functions.  The
++ *      board context contains state information for the device. Since the
++ *      addresses of all IN pointer parameters may be invalid when this
++ *      function returns, they must not be stored into the device context
++ *      structure.
++ */
++       typedef DSP_STATUS(*WMD_DEV_CREATE) (OUT struct WMD_DEV_CONTEXT
++                                                  **phDevContext,
++                                                  struct DEV_OBJECT
++                                                  *hDevObject,
++                                                  IN CONST struct CFG_HOSTRES
++                                                  *pConfig,
++                                                  IN CONST struct CFG_DSPRES
++                                                  *pDspConfig);
++
++/*
++ *  ======== WMD_DEV_Ctrl ========
++ *  Purpose:
++ *      Mini-driver specific interface.
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device info.
++ *      dwCmd:          WMD defined command code.
++ *      pArgs:          Pointer to an arbitrary argument structure.
++ *  Returns:
++ *      DSP_SOK or DSP_EFAIL. Actual command error codes should be passed back
++ *      in the pArgs structure, and are defined by the WMD implementor.
++ *  Requires:
++ *      All calls are currently assumed to be synchronous.  There are no
++ *      IOCTL completion routines provided.
++ *  Ensures:
++ */
++typedef DSP_STATUS(*WMD_DEV_CTRL)(struct WMD_DEV_CONTEXT *hDevContext,
++                                      u32 dwCmd,
++                                      IN OUT void *pArgs);
++
++/*
++ *  ======== WMD_DEV_Destroy ========
++ *  Purpose:
++ *      Deallocate WMD device extension structures and all other resources
++ *      acquired by the mini-driver.
++ *      No calls to other mini driver functions may subsequently
++ *      occur, except for WMD_DEV_Create().
++ *  Parameters:
++ *      hDevContext:    Handle to mini-driver defined device information.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Failed to release a resource previously acquired.
++ *  Requires:
++ *      hDevContext != NULL;
++ *  Ensures:
++ *      DSP_SOK: Device context is freed.
++ */
++       typedef DSP_STATUS(*WMD_DEV_DESTROY) (struct WMD_DEV_CONTEXT
++                                           *hDevContext);
++
++/*
++ *  ======== WMD_DEH_Create ========
++ *  Purpose:
++ *      Create an object that manages DSP exceptions from the GPP.
++ *  Parameters:
++ *      phDehMgr:       Location to store DEH manager on output.
++ *      hDevObject:     Handle to DEV object.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Memory allocation failure.
++ *      DSP_EFAIL:      Creation failed.
++ *  Requires:
++ *      hDevObject != NULL;
++ *      phDehMgr != NULL;
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_DEH_CREATE) (OUT struct DEH_MGR
++                                                  **phDehMgr,
++                                                  struct DEV_OBJECT
++                                                  *hDevObject);
++
++/*
++ *  ======== WMD_DEH_Destroy ========
++ *  Purpose:
++ *      Destroy the DEH object.
++ *  Parameters:
++ *      hDehMgr:        Handle to DEH manager object.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Destroy failed.
++ *  Requires:
++ *      hDehMgr != NULL;
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_DEH_DESTROY) (struct DEH_MGR *hDehMgr);
++
++/*
++ *  ======== WMD_DEH_RegisterNotify ========
++ *  Purpose:
++ *      Register for DEH event notification.
++ *  Parameters:
++ *      hDehMgr:        Handle to DEH manager object.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Destroy failed.
++ *  Requires:
++ *      hDehMgr != NULL;
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_DEH_REGISTERNOTIFY)
++                              (struct DEH_MGR *hDehMgr,
++                              u32 uEventMask, u32 uNotifyType,
++                              struct DSP_NOTIFICATION *hNotification);
++
++/*
++ *  ======== WMD_DEH_GetInfo ========
++ *  Purpose:
++ *      Get DSP exception info.
++ *  Parameters:
++ *      phDehMgr:       Location to store DEH manager on output.
++ *      pErrInfo:       Ptr to error info structure.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EFAIL:      Creation failed.
++ *  Requires:
++ *      phDehMgr != NULL;
++ *      pErrorInfo != NULL;
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_DEH_GETINFO) (struct DEH_MGR *phDehMgr,
++                                      struct DSP_ERRORINFO *pErrInfo);
++
++/*
++ *  ======== WMD_IO_Create ========
++ *  Purpose:
++ *      Create an object that manages I/O between CHNL and MSG.
++ *  Parameters:
++ *      phIOMgr:        Location to store IO manager on output.
++ *      hChnlMgr:       Handle to channel manager.
++ *      hMsgMgr:        Handle to message manager.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Memory allocation failure.
++ *      DSP_EFAIL:      Creation failed.
++ *  Requires:
++ *      hDevObject != NULL;
++ *      Channel manager already created;
++ *      Message manager already created;
++ *      pMgrAttrs != NULL;
++ *      phIOMgr != NULL;
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_IO_CREATE) (OUT struct IO_MGR **phIOMgr,
++                                      struct DEV_OBJECT *hDevObject,
++                                      IN CONST struct IO_ATTRS *pMgrAttrs);
++
++/*
++ *  ======== WMD_IO_Destroy ========
++ *  Purpose:
++ *      Destroy object created in WMD_IO_Create.
++ *  Parameters:
++ *      hIOMgr:         IO Manager.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Memory allocation failure.
++ *      DSP_EFAIL:      Creation failed.
++ *  Requires:
++ *      Valid hIOMgr;
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_IO_DESTROY) (struct IO_MGR *hIOMgr);
++
++/*
++ *  ======== WMD_IO_OnLoaded ========
++ *  Purpose:
++ *      Called whenever a program is loaded to update internal data. For
++ *      example, if shared memory is used, this function would update the
++ *      shared memory location and address.
++ *  Parameters:
++ *      hIOMgr:     IO Manager.
++ *  Returns:
++ *      DSP_SOK:    Success.
++ *      DSP_EFAIL:  Internal failure occurred.
++ *  Requires:
++ *      Valid hIOMgr;
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_IO_ONLOADED) (struct IO_MGR *hIOMgr);
++
++/*
++ *  ======== WMD_IO_GETPROCLOAD ========
++ *  Purpose:
++ *      Called to get the Processor's current and predicted load
++ *  Parameters:
++ *      hIOMgr:     IO Manager.
++ *      pProcLoadStat   Processor Load statistics
++ *  Returns:
++ *      DSP_SOK:    Success.
++ *      DSP_EFAIL:  Internal failure occurred.
++ *  Requires:
++ *      Valid hIOMgr;
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_IO_GETPROCLOAD)(struct IO_MGR *hIOMgr,
++                         struct DSP_PROCLOADSTAT *pProcLoadStat);
++
++/*
++ *  ======== WMD_MSG_Create ========
++ *  Purpose:
++ *      Create an object to manage message queues. Only one of these objects
++ *      can exist per device object.
++ *  Parameters:
++ *      phMsgMgr:           Location to store MSG manager on output.
++ *      hDevObject:         Handle to a device object.
++ *      msgCallback:        Called whenever an RMS_EXIT message is received.
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EMEMORY:        Insufficient memory.
++ *  Requires:
++ *      phMsgMgr != NULL.
++ *      msgCallback != NULL.
++ *      hDevObject != NULL.
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_MSG_CREATE)
++                              (OUT struct MSG_MGR **phMsgMgr,
++                              struct DEV_OBJECT *hDevObject,
++                              MSG_ONEXIT msgCallback);
++
++/*
++ *  ======== WMD_MSG_CreateQueue ========
++ *  Purpose:
++ *      Create a MSG queue for sending or receiving messages from a Message
++ *      node on the DSP.
++ *  Parameters:
++ *      hMsgMgr:            MSG queue manager handle returned from
++ *                          WMD_MSG_Create.
++ *      phMsgQueue:         Location to store MSG queue on output.
++ *      dwId:               Identifier for messages (node environment pointer).
++ *      uMaxMsgs:           Max number of simultaneous messages for the node.
++ *      h:                  Handle passed to hMsgMgr->msgCallback().
++ *  Returns:
++ *      DSP_SOK:            Success.
++ *      DSP_EMEMORY:        Insufficient memory.
++ *  Requires:
++ *      phMsgQueue != NULL.
++ *      h != NULL.
++ *      uMaxMsgs > 0.
++ *  Ensures:
++ *      phMsgQueue !=NULL <==> DSP_SOK.
++ */
++       typedef DSP_STATUS(*WMD_MSG_CREATEQUEUE)
++                              (struct MSG_MGR *hMsgMgr,
++                              OUT struct MSG_QUEUE **phMsgQueue,
++                              u32 dwId, u32 uMaxMsgs, HANDLE h);
++
++/*
++ *  ======== WMD_MSG_Delete ========
++ *  Purpose:
++ *      Delete a MSG manager allocated in WMD_MSG_Create().
++ *  Parameters:
++ *      hMsgMgr:    Handle returned from WMD_MSG_Create().
++ *  Returns:
++ *  Requires:
++ *      Valid hMsgMgr.
++ *  Ensures:
++ */
++       typedef void(*WMD_MSG_DELETE) (struct MSG_MGR *hMsgMgr);
++
++/*
++ *  ======== WMD_MSG_DeleteQueue ========
++ *  Purpose:
++ *      Delete a MSG queue allocated in WMD_MSG_CreateQueue.
++ *  Parameters:
++ *      hMsgQueue:  Handle to MSG queue returned from
++ *                  WMD_MSG_CreateQueue.
++ *  Returns:
++ *  Requires:
++ *      Valid hMsgQueue.
++ *  Ensures:
++ */
++       typedef void(*WMD_MSG_DELETEQUEUE) (struct MSG_QUEUE *hMsgQueue);
++
++/*
++ *  ======== WMD_MSG_Get ========
++ *  Purpose:
++ *      Get a message from a MSG queue.
++ *  Parameters:
++ *      hMsgQueue:     Handle to MSG queue returned from
++ *                     WMD_MSG_CreateQueue.
++ *      pMsg:          Location to copy message into.
++ *      uTimeout:      Timeout to wait for a message.
++ *  Returns:
++ *      DSP_SOK:       Success.
++ *      DSP_ETIMEOUT:  Timeout occurred.
++ *      DSP_EFAIL:     No frames available for message (uMaxMessages too
++ *                     small).
++ *  Requires:
++ *      Valid hMsgQueue.
++ *      pMsg != NULL.
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_MSG_GET) (struct MSG_QUEUE *hMsgQueue,
++                                               struct DSP_MSG *pMsg,
++                                               u32 uTimeout);
++
++/*
++ *  ======== WMD_MSG_Put ========
++ *  Purpose:
++ *      Put a message onto a MSG queue.
++ *  Parameters:
++ *      hMsgQueue:      Handle to MSG queue returned from
++ *                      WMD_MSG_CreateQueue.
++ *      pMsg:           Pointer to message.
++ *      uTimeout:       Timeout to wait for a message.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_ETIMEOUT:   Timeout occurred.
++ *      DSP_EFAIL:      No frames available for message (uMaxMessages too
++ *                      small).
++ *  Requires:
++ *      Valid hMsgQueue.
++ *      pMsg != NULL.
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_MSG_PUT) (struct MSG_QUEUE *hMsgQueue,
++                                               IN CONST struct DSP_MSG *pMsg,
++                                               u32 uTimeout);
++
++/*
++ *  ======== WMD_MSG_RegisterNotify ========
++ *  Purpose:
++ *      Register notification for when a message is ready.
++ *  Parameters:
++ *      hMsgQueue:      Handle to MSG queue returned from
++ *                      WMD_MSG_CreateQueue.
++ *      uEventMask:     Type of events to be notified about: Must be
++ *                      DSP_NODEMESSAGEREADY, or 0 to unregister.
++ *      uNotifyType:    DSP_SIGNALEVENT.
++ *      hNotification:  Handle of notification object.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Insufficient memory.
++ *  Requires:
++ *      Valid hMsgQueue.
++ *      hNotification != NULL.
++ *      uNotifyType == DSP_SIGNALEVENT.
++ *      uEventMask == DSP_NODEMESSAGEREADY || uEventMask == 0.
++ *  Ensures:
++ */
++       typedef DSP_STATUS(*WMD_MSG_REGISTERNOTIFY)
++                              (struct MSG_QUEUE *hMsgQueue,
++                              u32 uEventMask, u32 uNotifyType,
++                              struct DSP_NOTIFICATION *hNotification);
++
++/*
++ *  ======== WMD_MSG_SetQueueId ========
++ *  Purpose:
++ *      Set message queue id to node environment. Allows WMD_MSG_CreateQueue
++ *      to be called in NODE_Allocate, before the node environment is known.
++ *  Parameters:
++ *      hMsgQueue:  Handle to MSG queue returned from
++ *                  WMD_MSG_CreateQueue.
++ *      dwId:       Node environment pointer.
++ *  Returns:
++ *  Requires:
++ *      Valid hMsgQueue.
++ *      dwId != 0.
++ *  Ensures:
++ */
++       typedef void(*WMD_MSG_SETQUEUEID) (struct MSG_QUEUE *hMsgQueue,
++                                                u32 dwId);
++
++/*
++ *  'Bridge Mini Driver (WMD) interface function table.
++ *
++ *  The information in this table is filled in by the specific mini-driver,
++ *  and copied into the 'Bridge class driver's own space.  If any interface
++ *  function field is set to a value of NULL, then the class driver will
++ *  consider that function not implemented, and return the error code
++ *  DSP_ENOTIMPL when a WMD client attempts to call that function.
++ *
++ *  This function table contains WCD version numbers, which are used by the
++ *  WMD loader to help ensure backwards compatility between older WMD's and a
++ *  newer 'Bridge Class Driver.  These must be set to WCD_MAJOR_VERSION
++ *  and WCD_MINOR_VERSION, respectively.
++ *
++ *  A mini-driver need not export a CHNL interface.  In this case, *all* of
++ *  the WMD_CHNL_* entries must be set to NULL.
++ */
++      struct WMD_DRV_INTERFACE {
++              u32 dwWCDMajorVersion;  /* Set to WCD_MAJOR_VERSION. */
++              u32 dwWCDMinorVersion;  /* Set to WCD_MINOR_VERSION. */
++              WMD_DEV_CREATE pfnDevCreate;    /* Create device context     */
++              WMD_DEV_DESTROY pfnDevDestroy;  /* Destroy device context    */
++              WMD_DEV_CTRL pfnDevCntrl;       /* Optional vendor interface */
++              WMD_BRD_MONITOR pfnBrdMonitor;  /* Load and/or start monitor */
++              WMD_BRD_START pfnBrdStart;      /* Start DSP program.        */
++              WMD_BRD_STOP pfnBrdStop;        /* Stop/reset board.         */
++              WMD_BRD_STATUS pfnBrdStatus;    /* Get current board status. */
++              WMD_BRD_READ pfnBrdRead;        /* Read board memory         */
++              WMD_BRD_WRITE pfnBrdWrite;      /* Write board memory.       */
++              WMD_BRD_SETSTATE pfnBrdSetState;  /* Sets the Board State */
++              WMD_BRD_MEMCOPY pfnBrdMemCopy;   /* Copies DSP Memory         */
++              WMD_BRD_MEMWRITE pfnBrdMemWrite; /* Write DSP Memory w/o halt */
++              WMD_BRD_MEMMAP pfnBrdMemMap;     /* Maps MPU mem to DSP mem   */
++              WMD_BRD_MEMUNMAP pfnBrdMemUnMap; /* Unmaps MPU mem to DSP mem */
++              WMD_CHNL_CREATE pfnChnlCreate;   /* Create channel manager.   */
++              WMD_CHNL_DESTROY pfnChnlDestroy; /* Destroy channel manager.  */
++              WMD_CHNL_OPEN pfnChnlOpen;       /* Create a new channel.     */
++              WMD_CHNL_CLOSE pfnChnlClose;     /* Close a channel.          */
++              WMD_CHNL_ADDIOREQ pfnChnlAddIOReq; /* Req I/O on a channel. */
++              WMD_CHNL_GETIOC pfnChnlGetIOC;   /* Wait for I/O completion.  */
++              WMD_CHNL_CANCELIO pfnChnlCancelIO; /* Cancl I/O on a channel. */
++              WMD_CHNL_FLUSHIO pfnChnlFlushIO;        /* Flush I/O.         */
++              WMD_CHNL_GETINFO pfnChnlGetInfo; /* Get channel specific info */
++              /* Get channel manager info. */
++              WMD_CHNL_GETMGRINFO pfnChnlGetMgrInfo;
++              WMD_CHNL_IDLE pfnChnlIdle;      /* Idle the channel */
++              /* Register for notif. */
++              WMD_CHNL_REGISTERNOTIFY pfnChnlRegisterNotify;
++              WMD_DEH_CREATE pfnDehCreate;    /* Create DEH manager */
++              WMD_DEH_DESTROY pfnDehDestroy;  /* Destroy DEH manager */
++              WMD_DEH_NOTIFY pfnDehNotify;    /* Notify of DSP error */
++              /* register for deh notif. */
++              WMD_DEH_REGISTERNOTIFY pfnDehRegisterNotify;
++              WMD_DEH_GETINFO pfnDehGetInfo;  /* register for deh notif. */
++              WMD_IO_CREATE pfnIOCreate;      /* Create IO manager */
++              WMD_IO_DESTROY pfnIODestroy;    /* Destroy IO manager */
++              WMD_IO_ONLOADED pfnIOOnLoaded;  /* Notify of program loaded */
++              /* Get Processor's current and predicted load */
++              WMD_IO_GETPROCLOAD pfnIOGetProcLoad;
++              WMD_MSG_CREATE pfnMsgCreate;    /* Create message manager */
++              /* Create message queue */
++              WMD_MSG_CREATEQUEUE pfnMsgCreateQueue;
++              WMD_MSG_DELETE pfnMsgDelete;    /* Delete message manager */
++              /* Delete message queue */
++              WMD_MSG_DELETEQUEUE pfnMsgDeleteQueue;
++              WMD_MSG_GET pfnMsgGet;  /* Get a message */
++              WMD_MSG_PUT pfnMsgPut;  /* Send a message */
++              /* Register for notif. */
++              WMD_MSG_REGISTERNOTIFY pfnMsgRegisterNotify;
++              /* Set message queue id */
++              WMD_MSG_SETQUEUEID pfnMsgSetQueueId;
++      } ;
++
++/*
++ *  ======== WMD_DRV_Entry ========
++ *  Purpose:
++ *      Registers WMD functions with the class driver. Called only once
++ *      by the WCD.  The caller will first check WCD version compatibility, and
++ *      then copy the interface functions into its own memory space.
++ *  Parameters:
++ *      ppDrvInterface  Pointer to a location to receive a pointer to the
++ *                      mini driver interface.
++ *  Returns:
++ *  Requires:
++ *      The code segment this function resides in must expect to be discarded
++ *      after completion.
++ *  Ensures:
++ *      ppDrvInterface pointer initialized to WMD's function interface.
++ *      No system resources are acquired by this function.
++ *  Details:
++ *      Win95: Called during the Device_Init phase.
++ */
++       void WMD_DRV_Entry(OUT struct WMD_DRV_INTERFACE **ppDrvInterface,
++                               IN CONST char *pstrWMDFileName);
++
++#endif                                /* WMD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdchnl.h b/arch/arm/plat-omap/include/dspbridge/wmdchnl.h
+new file mode 100644
+index 0000000..2c1f072
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdchnl.h
+@@ -0,0 +1,90 @@
++/*
++ * wmdchnl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== wmdchnl.h ========
++ *  Description:
++ *      Declares the upper edge channel class library functions required by
++ *      all WMD / WCD driver interface tables.  These functions are implemented
++ *      by every class of WMD channel library.
++ *
++ *  Public Functions:
++ *
++ *  Notes:
++ *      The function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Jan-2002 ag  Added cBufSize to WMD_CHNL_AddIOReq().
++ *! 13-Oct-2000 jeh Added dwArg parameter to WMD_CHNL_AddIOReq(), added
++ *!                 WMD_CHNL_Idle and WMD_CHNL_RegisterNotify for DSPStream
++ *!                 support.
++ *! 11-Jul-1996 gp: Created.
++ */
++
++#ifndef WMDCHNL_
++#define WMDCHNL_
++
++      extern DSP_STATUS WMD_CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++                                        struct DEV_OBJECT *hDevObject,
++                                        IN CONST struct CHNL_MGRATTRS
++                                        *pMgrAttrs);
++
++      extern DSP_STATUS WMD_CHNL_Destroy(struct CHNL_MGR *hChnlMgr);
++
++      extern DSP_STATUS WMD_CHNL_Open(OUT struct CHNL_OBJECT **phChnl,
++                                      struct CHNL_MGR *hChnlMgr,
++                                      CHNL_MODE uMode,
++                                      u32 uChnlId,
++                                      CONST IN OPTIONAL struct CHNL_ATTRS
++                                      *pAttrs);
++
++      extern DSP_STATUS WMD_CHNL_Close(struct CHNL_OBJECT *hChnl);
++
++      extern DSP_STATUS WMD_CHNL_AddIOReq(struct CHNL_OBJECT *hChnl,
++                                          void *pHostBuf,
++                                          u32 cBytes, u32 cBufSize,
++                                          OPTIONAL u32 dwDspAddr,
++                                          u32 dwArg);
++
++      extern DSP_STATUS WMD_CHNL_GetIOC(struct CHNL_OBJECT *hChnl,
++                                        u32 dwTimeOut,
++                                        OUT struct CHNL_IOC *pIOC);
++
++      extern DSP_STATUS WMD_CHNL_CancelIO(struct CHNL_OBJECT *hChnl);
++
++      extern DSP_STATUS WMD_CHNL_FlushIO(struct CHNL_OBJECT *hChnl,
++                                         u32 dwTimeOut);
++
++      extern DSP_STATUS WMD_CHNL_GetInfo(struct CHNL_OBJECT *hChnl,
++                                         OUT struct CHNL_INFO *pInfo);
++
++      extern DSP_STATUS WMD_CHNL_GetMgrInfo(struct CHNL_MGR *hChnlMgr,
++                                            u32 uChnlID,
++                                            OUT struct CHNL_MGRINFO
++                                            *pMgrInfo);
++
++      extern DSP_STATUS WMD_CHNL_Idle(struct CHNL_OBJECT *hChnl,
++                                      u32 dwTimeOut, bool fFlush);
++
++      extern DSP_STATUS WMD_CHNL_RegisterNotify(struct CHNL_OBJECT *hChnl,
++                                                u32 uEventMask,
++                                                u32 uNotifyType,
++                                                struct DSP_NOTIFICATION
++                                                *hNotification);
++
++#endif                                /* WMDCHNL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmddeh.h b/arch/arm/plat-omap/include/dspbridge/wmddeh.h
+new file mode 100644
+index 0000000..dd50a3a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmddeh.h
+@@ -0,0 +1,64 @@
++/*
++ * wmddeh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== wmddeh.h ========
++ *  Description:
++ *      Defines upper edge DEH functions required by all WMD/WCD driver
++ *      interface tables.
++ *
++ *  Public Functions:
++ *      WMD_DEH_Create
++ *      IVA_DEH_Create
++ *      WMD_DEH_Destroy
++ *      WMD_DEH_GetInfo
++ *      WMD_DEH_RegisterNotify
++ *      WMD_DEH_Notify
++ *
++ *  Notes:
++ *      Function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Dec-2004 hn: added IVA_DEH_Create.
++ *! 13-Sep-2001 kc: created.
++ */
++
++#ifndef WMDDEH_
++#define WMDDEH_
++
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/dehdefs.h>
++
++      extern DSP_STATUS WMD_DEH_Create(OUT struct DEH_MGR **phDehMgr,
++                                       struct DEV_OBJECT *hDevObject);
++
++      extern DSP_STATUS WMD_DEH_Destroy(struct DEH_MGR *hDehMgr);
++
++      extern DSP_STATUS WMD_DEH_GetInfo(struct DEH_MGR *hDehMgr,
++                                        struct DSP_ERRORINFO *pErrInfo);
++
++      extern DSP_STATUS WMD_DEH_RegisterNotify(struct DEH_MGR *hDehMgr,
++                                               u32 uEventMask,
++                                               u32 uNotifyType,
++                                               struct DSP_NOTIFICATION
++                                               *hNotification);
++
++      extern void WMD_DEH_Notify(struct DEH_MGR *hDehMgr,
++                                 u32 ulEventMask, u32 dwErrInfo);
++#endif                                /* WMDDEH_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdio.h b/arch/arm/plat-omap/include/dspbridge/wmdio.h
+new file mode 100644
+index 0000000..8525474
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdio.h
+@@ -0,0 +1,53 @@
++/*
++ * wmdio.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== wmdio.h ========
++ *  Description:
++ *      Declares the upper edge IO  functions required by
++ *      all WMD / WCD driver interface tables.
++ *
++ *  Public Functions:
++ *
++ *  Notes:
++ *      Function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 27-Feb-2004 vp            Added IVA releated function.
++ *! 06-Nov-2000 jeh     Created.
++ */
++
++#ifndef WMDIO_
++#define WMDIO_
++
++#include <dspbridge/devdefs.h>
++#include <dspbridge/iodefs.h>
++
++      extern DSP_STATUS WMD_IO_Create(OUT struct IO_MGR **phIOMgr,
++                                      struct DEV_OBJECT *hDevObject,
++                                      IN CONST struct IO_ATTRS *pMgrAttrs);
++
++      extern DSP_STATUS WMD_IO_Destroy(struct IO_MGR *hIOMgr);
++
++      extern DSP_STATUS WMD_IO_OnLoaded(struct IO_MGR *hIOMgr);
++
++      extern DSP_STATUS IVA_IO_OnLoaded(struct IO_MGR *hIOMgr);
++      extern DSP_STATUS WMD_IO_GetProcLoad(IN struct IO_MGR *hIOMgr,
++                              OUT struct DSP_PROCLOADSTAT *pProcStat);
++
++#endif                                /* WMDIO_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdioctl.h b/arch/arm/plat-omap/include/dspbridge/wmdioctl.h
+new file mode 100644
+index 0000000..a41c61a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdioctl.h
+@@ -0,0 +1,91 @@
++/*
++ * wmdioctl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== wmdioctl.h ========
++ *  Description:
++ *    BRIDGE Minidriver BRD_IOCtl reserved command definitions.
++ *
++ *! Revision History
++ *! ================
++ *! 19-Apr-2004 sb   Updated HW typedefs
++ *! 16-Feb-2004 vp   Added MMU endianness attributes to WMDIOCTL_EXTPROC
++ *! 21-Mar-2003 sb   Changed WMDIOCTL_NUMOFMMUTLB from 7 to 32
++ *! 14-May-2001 sg   Added codes for PWR.
++ *! 10-Aug-2001 ag   Added _SETMMUCONFIG ioctl used for DSP-MMU init.
++ *! 16-Nov-1999 rajesh ?
++ *! 18-Jun-1998 ag   Moved EMIF, SDRAM_C, & CE space init to ENBLEXTMEM ioctl.
++ *!                  Added ENBLEXTMEM, RESETDSP, UNRESETDSP & ASSERTSIG ioctls.
++ *! 07-Jun-1998 ag   Added JTAG_SELECT, MAP_TBC, GET_CONFIGURATION ioctls.
++ *! 26-Jan-1998 jeh: Added START, RECV, and SEND ioctls.
++ *! 07-Nov-1997 nn:  Added command to interrupt DSP for interrupt test.
++ *! 20-Oct-1997 nn:  Added commands for getting and resetting interrupt count.
++ *! 17-Oct-1997 gp:  Moved to src/wmd. Standardized prefix.
++ *! 08-Oct-1997 nn:  Created.
++ */
++
++#ifndef WMDIOCTL_
++#define WMDIOCTL_
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/* Any IOCTLS at or above this value are reserved for standard WMD interfaces.*/
++#define WMDIOCTL_RESERVEDBASE       0x8000
++
++#define WMDIOCTL_CHNLREAD           (WMDIOCTL_RESERVEDBASE + 0x10)
++#define WMDIOCTL_CHNLWRITE          (WMDIOCTL_RESERVEDBASE + 0x20)
++#define WMDIOCTL_GETINTRCOUNT       (WMDIOCTL_RESERVEDBASE + 0x30)
++#define WMDIOCTL_RESETINTRCOUNT     (WMDIOCTL_RESERVEDBASE + 0x40)
++#define WMDIOCTL_INTERRUPTDSP       (WMDIOCTL_RESERVEDBASE + 0x50)
++#define WMDIOCTL_SETMMUCONFIG       (WMDIOCTL_RESERVEDBASE + 0x60)   /* DMMU */
++#define WMDIOCTL_PWRCONTROL         (WMDIOCTL_RESERVEDBASE + 0x70)   /* PWR */
++
++/* attention, modifiers:
++ * Some of these control enumerations are made visible to user for power
++ * control, so any changes to this list, should also be updated in the user
++ * header file 'dbdefs.h' ***/
++/* These ioctls are reserved for PWR power commands for the DSP */
++#define WMDIOCTL_DEEPSLEEP          (WMDIOCTL_PWRCONTROL + 0x0)
++#define WMDIOCTL_EMERGENCYSLEEP     (WMDIOCTL_PWRCONTROL + 0x1)
++#define WMDIOCTL_WAKEUP             (WMDIOCTL_PWRCONTROL + 0x2)
++#define WMDIOCTL_PWRENABLE          (WMDIOCTL_PWRCONTROL + 0x3)
++#define WMDIOCTL_PWRDISABLE         (WMDIOCTL_PWRCONTROL + 0x4)
++#define WMDIOCTL_CLK_CTRL                 (WMDIOCTL_PWRCONTROL + 0x7)
++#define WMDIOCTL_PWR_HIBERNATE (WMDIOCTL_PWRCONTROL + 0x8) /*DSP Initiated
++                                                          * Hibernate*/
++#define WMDIOCTL_PRESCALE_NOTIFY (WMDIOCTL_PWRCONTROL + 0x9)
++#define WMDIOCTL_POSTSCALE_NOTIFY (WMDIOCTL_PWRCONTROL + 0xA)
++#define WMDIOCTL_CONSTRAINT_REQUEST (WMDIOCTL_PWRCONTROL + 0xB)
++
++/* Number of actual DSP-MMU TLB entrries */
++#define WMDIOCTL_NUMOFMMUTLB        32
++
++struct WMDIOCTL_EXTPROC {
++      u32 ulDspVa;            /* DSP virtual address */
++      u32 ulGppPa;            /* GPP physical address */
++      /* GPP virtual address. __va does not work for ioremapped addresses */
++      u32 ulGppVa;
++      u32 ulSize;             /* Size of the mapped memory in bytes */
++      enum HW_Endianism_t endianism;
++      enum HW_MMUMixedSize_t mixedMode;
++      enum HW_ElementSize_t elemSize;
++};
++
++#endif                                /* WMDIOCTL_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdmsg.h b/arch/arm/plat-omap/include/dspbridge/wmdmsg.h
+new file mode 100644
+index 0000000..81198d4
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdmsg.h
+@@ -0,0 +1,70 @@
++/*
++ * wmdmsg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== wmdmsg.h ========
++ *  Description:
++ *      Declares the upper edge message class library functions required by
++ *      all WMD / WCD driver interface tables.  These functions are
++ *      implemented by every class of WMD channel library.
++ *
++ *  Public Functions:
++ *
++ *  Notes:
++ *      Function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 06-Dec-2000 jeh     Added uEventMask to WMD_MSG_RegisterNotify(). Added
++ *!                     WMD_MSG_SetQueueId().
++ *! 17-Nov-2000 jeh     Created.
++ */
++
++#ifndef WMDMSG_
++#define WMDMSG_
++
++#include <dspbridge/msgdefs.h>
++
++      extern DSP_STATUS WMD_MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++                                       struct DEV_OBJECT *hDevObject,
++                                       MSG_ONEXIT msgCallback);
++
++      extern DSP_STATUS WMD_MSG_CreateQueue(struct MSG_MGR *hMsgMgr,
++                                            OUT struct MSG_QUEUE **phMsgQueue,
++                                            u32 dwId, u32 uMaxMsgs,
++                                            HANDLE h);
++
++      extern void WMD_MSG_Delete(struct MSG_MGR *hMsgMgr);
++
++      extern void WMD_MSG_DeleteQueue(struct MSG_QUEUE *hMsgQueue);
++
++      extern DSP_STATUS WMD_MSG_Get(struct MSG_QUEUE *hMsgQueue,
++                                    struct DSP_MSG *pMsg, u32 uTimeout);
++
++      extern DSP_STATUS WMD_MSG_Put(struct MSG_QUEUE *hMsgQueue,
++                                    IN CONST struct DSP_MSG *pMsg,
++                                    u32 uTimeout);
++
++      extern DSP_STATUS WMD_MSG_RegisterNotify(struct MSG_QUEUE *hMsgQueue,
++                                               u32 uEventMask,
++                                               u32 uNotifyType,
++                                               struct DSP_NOTIFICATION
++                                               *hNotification);
++
++      extern void WMD_MSG_SetQueueId(struct MSG_QUEUE *hMsgQueue, u32 dwId);
++
++#endif                                /* WMDMSG_ */
+diff --git a/drivers/Makefile b/drivers/Makefile
+index fec4d8e..6fcee09 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -42,6 +42,7 @@ obj-$(CONFIG_PARPORT)                += parport/
+ obj-y                         += base/ block/ misc/ mfd/ net/ media/
+ obj-y                         += i2c/
+ obj-y                         += cbus/
++obj-$(CONFIG_MPU_BRIDGE)      += dsp/bridge/
+ obj-$(CONFIG_NUBUS)           += nubus/
+ obj-$(CONFIG_ATM)             += atm/
+ obj-y                         += macintosh/
+diff --git a/drivers/dsp/bridge/Kbuild b/drivers/dsp/bridge/Kbuild
+new file mode 100644
+index 0000000..3432ff2
+--- /dev/null
++++ b/drivers/dsp/bridge/Kbuild
+@@ -0,0 +1,39 @@
++obj-$(CONFIG_MPU_BRIDGE)      += bridgedriver.o
++
++libgen = gen/gb.o gen/gt.o gen/gs.o gen/gh.o gen/_gt_para.o gen/uuidutil.o
++libservices = services/csl.o services/mem.o services/list.o services/dpc.o \
++               services/kfile.o services/sync.o \
++              services/clk.o services/cfg.o services/reg.o \
++               services/regsup.o services/ntfy.o \
++              services/dbg.o services/services.o
++libwmd = wmd/chnl_sm.o wmd/msg_sm.o wmd/io_sm.o wmd/tiomap3430.o \
++              wmd/tiomap3430_pwr.o wmd/tiomap_sm.o wmd/tiomap_io.o \
++              wmd/mmu_fault.o wmd/ue_deh.o
++libpmgr = pmgr/chnl.o pmgr/io.o pmgr/msg.o pmgr/cod.o pmgr/dev.o pmgr/wcd.o \
++              pmgr/dmm.o pmgr/cmm.o pmgr/dbll.o
++librmgr = rmgr/dbdcd.o rmgr/disp.o rmgr/drv.o rmgr/mgr.o rmgr/node.o \
++              rmgr/proc.o rmgr/pwr.o rmgr/rmm.o rmgr/strm.o rmgr/dspdrv.o \
++              rmgr/nldr.o rmgr/drv_interface.o
++libdload = dynload/cload.o dynload/getsection.o dynload/reloc.o
++libhw = hw/hw_prcm.o hw/hw_dspssC64P.o hw/hw_mmu.o hw/hw_mbox.o
++
++bridgedriver-objs = $(libgen) $(libservices) $(libwmd) $(libpmgr) $(librmgr) \
++                      $(libdload) $(libhw)
++
++# Debug
++ifeq ($(CONFIG_BRIDGE_DEBUG),y)
++ccflags-y += -DGT_TRACE -DDEBUG
++endif
++
++#Machine dependent
++ccflags-y += -D_TI_ -D_DB_TIOMAP -DTMS32060 \
++              -DTICFG_PROC_VER -DTICFG_EVM_TYPE -DCHNL_SMCLASS \
++              -DCHNL_MESSAGES -DUSE_LEVEL_1_MACROS
++
++#Header files
++ccflags-y += -Idrivers/dsp/bridge/services
++ccflags-y += -Idrivers/dsp/bridge/wmd
++ccflags-y += -Idrivers/dsp/bridge/pmgr
++ccflags-y += -Idrivers/dsp/bridge/rmgr
++ccflags-y += -Idrivers/dsp/bridge/hw
++ccflags-y += -Iarch/arm
+diff --git a/drivers/dsp/bridge/Kconfig b/drivers/dsp/bridge/Kconfig
+new file mode 100644
+index 0000000..2fed82c
+--- /dev/null
++++ b/drivers/dsp/bridge/Kconfig
+@@ -0,0 +1,36 @@
++#
++# DSP Bridge Driver Support
++#
++
++menuconfig MPU_BRIDGE
++      tristate "DSP Bridge driver"
++      default n
++      help
++        DSP/BIOS Bridge is designed for platforms that contain a GPP and
++        one or more attached DSPs.  The GPP is considered the master or
++        "host" processor, and the attached DSPs are processing resources
++        that can be utilized by applications and drivers running on the GPP.
++
++config BRIDGE_DVFS
++      bool "Enable Bridge Dynamic Voltage and Frequency Scaling (DVFS)"
++      depends on MPU_BRIDGE && OMAP_PM_SRF
++      default n
++      help
++        DVFS allows DSP Bridge to initiate the operating point change to
++        scale the chip voltage and frequency in order to match the
++        performance and power consumption to the current processing
++        requirements.
++
++config BRIDGE_MEMPOOL_SIZE
++      hex "Physical memory pool size (Byte)"
++      depends on MPU_BRIDGE
++      default 0x600000
++      help
++        Allocate specified size of memory at booting time to avoid allocation
++        failure under heavy memory fragmentation after some use time.
++
++config BRIDGE_DEBUG
++      bool "DSP Bridge Debug Support"
++      depends on MPU_BRIDGE
++      help
++        Say Y to enable Bridge debugging capabilities
+diff --git a/drivers/dsp/bridge/dynload/cload.c b/drivers/dsp/bridge/dynload/cload.c
+new file mode 100644
+index 0000000..271ab81
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/cload.c
+@@ -0,0 +1,1854 @@
++/*
++ * cload.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include "header.h"
++
++#include "module_list.h"
++#define LINKER_MODULES_HEADER ("_" MODULES_HEADER)
++
++/*
++ * we use the fact that DOFF section records are shaped just like
++ * LDR_SECTION_INFO to reduce our section storage usage.  This macro marks
++ * the places where that assumption is made
++ */
++#define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct LDR_SECTION_INFO *)(pdoffsec))
++
++/*
++ * forward references
++ */
++static void dload_symbols(struct dload_state *dlthis);
++static void dload_data(struct dload_state *dlthis);
++static void allocate_sections(struct dload_state *dlthis);
++static void string_table_free(struct dload_state *dlthis);
++static void symbol_table_free(struct dload_state *dlthis);
++static void section_table_free(struct dload_state *dlthis);
++static void init_module_handle(struct dload_state *dlthis);
++#if BITS_PER_AU > BITS_PER_BYTE
++static char *unpack_name(struct dload_state *dlthis, u32 soffset);
++#endif
++
++static const char CINITNAME[] = { ".cinit" };
++static const char LOADER_DLLVIEW_ROOT[] = { "?DLModules?" };
++
++/*
++ * Error strings
++ */
++static const char E_READSTRM[] = { "Error reading %s from input stream" };
++static const char E_ALLOC[] = { "Syms->Allocate( %d ) failed" };
++static const char E_TGTALLOC[] =
++    { "Target memory allocate failed, section %s size " FMT_UI32 };
++static const char E_INITFAIL[] = { "%s to target address " FMT_UI32 " failed" };
++static const char E_DLVWRITE[] = { "Write to DLLview list failed" };
++static const char E_ICONNECT[] = { "Connect call to init interface failed" };
++static const char E_CHECKSUM[] = { "Checksum failed on %s" };
++
++/*************************************************************************
++ * Procedure dload_error
++ *
++ * Parameters:
++ *    errtxt  description of the error, printf style
++ *    ...             additional information
++ *
++ * Effect:
++ *    Reports or records the error as appropriate.
++ ************************************************************************/
++void dload_error(struct dload_state *dlthis, const char *errtxt, ...)
++{
++      va_list args;
++
++      va_start(args, errtxt);
++      dlthis->mysym->Error_Report(dlthis->mysym, errtxt, args);
++      va_end(args);
++      dlthis->dload_errcount += 1;
++
++}                             /* dload_error */
++
++#define DL_ERROR(zza, zzb) dload_error(dlthis, zza, zzb)
++
++/*************************************************************************
++ * Procedure dload_syms_error
++ *
++ * Parameters:
++ *    errtxt  description of the error, printf style
++ *    ...             additional information
++ *
++ * Effect:
++ *    Reports or records the error as appropriate.
++ ************************************************************************/
++void dload_syms_error(struct Dynamic_Loader_Sym *syms, const char *errtxt, ...)
++{
++      va_list args;
++
++      va_start(args, errtxt);
++      syms->Error_Report(syms, errtxt, args);
++      va_end(args);
++}
++
++/*************************************************************************
++ * Procedure Dynamic_Load_Module
++ *
++ * Parameters:
++ *    module  The input stream that supplies the module image
++ *    syms    Host-side symbol table and malloc/free functions
++ *    alloc   Target-side memory allocation
++ *    init    Target-side memory initialization
++ *    options Option flags DLOAD_*
++ *    mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ *    The module image is read using *module.  Target storage for the new
++ *    image is
++ * obtained from *alloc.  Symbols defined and referenced by the module are
++ * managed using *syms.  The image is then relocated and references
++ *    resolved as necessary, and the resulting executable bits are placed
++ *    into target memory using *init.
++ *
++ * Returns:
++ *    On a successful load, a module handle is placed in *mhandle,
++ *    and zero is returned.  On error, the number of errors detected is
++ *    returned.  Individual errors are reported during the load process
++ *    using syms->Error_Report().
++ ***********************************************************************/
++int Dynamic_Load_Module(struct Dynamic_Loader_Stream *module,
++                      struct Dynamic_Loader_Sym *syms ,
++                      struct Dynamic_Loader_Allocate *alloc,
++                      struct Dynamic_Loader_Initialize *init,
++                      unsigned options, DLOAD_mhandle *mhandle)
++{
++      register unsigned *dp, sz;
++      struct dload_state dl_state;    /* internal state for this call */
++
++      /* blast our internal state */
++      dp = (unsigned *)&dl_state;
++      for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
++              *dp++ = 0;
++
++      /* Enable _only_ BSS initialization if enabled by user */
++      if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
++              dl_state.myoptions = DLOAD_INITBSS;
++
++      /* Check that mandatory arguments are present */
++      if (!module || !syms) {
++              dload_error(&dl_state, "Required parameter is NULL");
++      } else {
++              dl_state.strm = module;
++              dl_state.mysym = syms;
++              dload_headers(&dl_state);
++              if (!dl_state.dload_errcount)
++                      dload_strings(&dl_state, false);
++              if (!dl_state.dload_errcount)
++                      dload_sections(&dl_state);
++
++              if (init && !dl_state.dload_errcount) {
++                      if (init->connect(init)) {
++                              dl_state.myio = init;
++                              dl_state.myalloc = alloc;
++                              /* do now, before reducing symbols */
++                              allocate_sections(&dl_state);
++                      } else
++                              dload_error(&dl_state, E_ICONNECT);
++              }
++
++              if (!dl_state.dload_errcount) {
++                      /* fix up entry point address */
++                      unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
++                      if (sref < dl_state.allocated_secn_count)
++                              dl_state.dfile_hdr.df_entrypt +=
++                                  dl_state.ldr_sections[sref].run_addr;
++
++                      dload_symbols(&dl_state);
++              }
++
++              if (init && !dl_state.dload_errcount)
++                      dload_data(&dl_state);
++
++              init_module_handle(&dl_state);
++
++              if (dl_state.myio) {
++                      if ((!dl_state.dload_errcount) &&
++                         (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF)) {
++                              if (init != NULL) {
++                                      if (!init->execute(init,
++                                         dl_state.dfile_hdr.df_entrypt))
++                                              dload_error(&dl_state,
++                                                  "Init->Execute Failed");
++                              } else {
++                                      dload_error(&dl_state, "init is NULL");
++                              }
++                      }
++                      init->release(init);
++              }
++
++              symbol_table_free(&dl_state);
++              section_table_free(&dl_state);
++              string_table_free(&dl_state);
++
++              if (dl_state.dload_errcount) {
++                      Dynamic_Unload_Module(dl_state.myhandle, syms, alloc,
++                                           init);
++                      dl_state.myhandle = NULL;
++              }
++      }
++
++      if (mhandle)
++              *mhandle = dl_state.myhandle;   /* give back the handle */
++
++      return dl_state.dload_errcount;
++}                             /* DLOAD_File */
++
++/*************************************************************************
++ * Procedure Dynamic_Open_Module
++ *
++ * Parameters:
++ *      module  The input stream that supplies the module image
++ *      syms    Host-side symbol table and malloc/free functions
++ *      alloc   Target-side memory allocation
++ *      init    Target-side memory initialization
++ *      options Option flags DLOAD_*
++ *      mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ *      The module image is read using *module.  Target storage for the new
++ *      image is
++ *    obtained from *alloc.  Symbols defined and referenced by the module are
++ *    managed using *syms.  The image is then relocated and references
++ *      resolved as necessary, and the resulting executable bits are placed
++ *      into target memory using *init.
++ *
++ * Returns:
++ *      On a successful load, a module handle is placed in *mhandle,
++ *      and zero is returned.  On error, the number of errors detected is
++ *      returned.  Individual errors are reported during the load process
++ *      using syms->Error_Report().
++ ***********************************************************************/
++int
++Dynamic_Open_Module(struct Dynamic_Loader_Stream *module,
++                  struct Dynamic_Loader_Sym *syms,
++                  struct Dynamic_Loader_Allocate *alloc,
++                  struct Dynamic_Loader_Initialize *init,
++                  unsigned options, DLOAD_mhandle *mhandle)
++{
++      register unsigned *dp, sz;
++      struct dload_state dl_state;   /* internal state for this call */
++
++      /* blast our internal state */
++      dp = (unsigned *)&dl_state;
++      for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
++              *dp++ = 0;
++
++      /* Enable _only_ BSS initialization if enabled by user */
++      if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
++              dl_state.myoptions = DLOAD_INITBSS;
++
++      /* Check that mandatory arguments are present */
++      if (!module || !syms) {
++              dload_error(&dl_state, "Required parameter is NULL");
++      } else {
++              dl_state.strm = module;
++              dl_state.mysym = syms;
++              dload_headers(&dl_state);
++              if (!dl_state.dload_errcount)
++                      dload_strings(&dl_state, false);
++              if (!dl_state.dload_errcount)
++                      dload_sections(&dl_state);
++
++              if (init && !dl_state.dload_errcount) {
++                      if (init->connect(init)) {
++                              dl_state.myio = init;
++                              dl_state.myalloc = alloc;
++                              /* do now, before reducing symbols */
++                              allocate_sections(&dl_state);
++                      } else
++                              dload_error(&dl_state, E_ICONNECT);
++              }
++
++              if (!dl_state.dload_errcount) {
++                      /* fix up entry point address */
++                      unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
++                      if (sref < dl_state.allocated_secn_count)
++                              dl_state.dfile_hdr.df_entrypt +=
++                                  dl_state.ldr_sections[sref].run_addr;
++
++                      dload_symbols(&dl_state);
++              }
++
++              init_module_handle(&dl_state);
++
++              if (dl_state.myio) {
++                      if ((!dl_state.dload_errcount)
++                          && (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF))
++                              if (!init->execute(init,
++                                 dl_state.dfile_hdr.df_entrypt))
++                                      dload_error(&dl_state,
++                                          "Init->Execute Failed");
++                      init->release(init);
++              }
++
++              symbol_table_free(&dl_state);
++              section_table_free(&dl_state);
++              string_table_free(&dl_state);
++
++              if (dl_state.dload_errcount) {
++                      Dynamic_Unload_Module(dl_state.myhandle, syms, alloc,
++                                            init);
++                      dl_state.myhandle = NULL;
++              }
++      }
++
++      if (mhandle)
++              *mhandle = dl_state.myhandle;   /* give back the handle */
++
++      return dl_state.dload_errcount;
++}                            /* DLOAD_File */
++
++/*************************************************************************
++ * Procedure dload_headers
++ *
++ * Parameters:
++ *    none
++ *
++ * Effect:
++ *    Loads the DOFF header and verify record.  Deals with any byte-order
++ * issues and checks them for validity.
++ ************************************************************************/
++#define COMBINED_HEADER_SIZE (sizeof(struct doff_filehdr_t)+ \
++                           sizeof(struct doff_verify_rec_t))
++
++void dload_headers(struct dload_state *dlthis)
++{
++      u32 map;
++
++      /* Read the header and the verify record as one.  If we don't get it
++         all, we're done */
++      if (dlthis->strm->read_buffer(dlthis->strm, &dlthis->dfile_hdr,
++          COMBINED_HEADER_SIZE) != COMBINED_HEADER_SIZE) {
++              DL_ERROR(E_READSTRM, "File Headers");
++              return;
++      }
++      /*
++       * Verify that we have the byte order of the file correct.
++       * If not, must fix it before we can continue
++       */
++      map = REORDER_MAP(dlthis->dfile_hdr.df_byte_reshuffle);
++      if (map != REORDER_MAP(BYTE_RESHUFFLE_VALUE)) {
++              /* input is either byte-shuffled or bad */
++              if ((map & 0xFCFCFCFC) == 0) {  /* no obviously bogus bits */
++                      dload_reorder(&dlthis->dfile_hdr, COMBINED_HEADER_SIZE,
++                                    map);
++              }
++              if (dlthis->dfile_hdr.df_byte_reshuffle !=
++                  BYTE_RESHUFFLE_VALUE) {
++                      /* didn't fix the problem, the byte swap map is bad */
++                      dload_error(dlthis,
++                                  "Bad byte swap map " FMT_UI32 " in header",
++                                  dlthis->dfile_hdr.df_byte_reshuffle);
++                      return;
++              }
++              dlthis->reorder_map = map;      /* keep map for future use */
++      }
++
++      /*
++       * Verify checksum of header and verify record
++       */
++      if (~dload_checksum(&dlthis->dfile_hdr,
++          sizeof(struct doff_filehdr_t)) ||
++          ~dload_checksum(&dlthis->verify,
++          sizeof(struct doff_verify_rec_t))) {
++              DL_ERROR(E_CHECKSUM, "header or verify record");
++              return;
++      }
++#if HOST_ENDIANNESS
++      dlthis->dfile_hdr.df_byte_reshuffle = map;      /* put back for later */
++#endif
++
++      /* Check for valid target ID */
++      if ((dlthis->dfile_hdr.df_target_id != TARGET_ID) &&
++        -(dlthis->dfile_hdr.df_target_id != TMS470_ID)) {
++              dload_error(dlthis, "Bad target ID 0x%x and TARGET_ID 0x%x",
++                          dlthis->dfile_hdr.df_target_id, TARGET_ID);
++              return;
++      }
++      /* Check for valid file format */
++      if ((dlthis->dfile_hdr.df_doff_version != DOFF0)) {
++              dload_error(dlthis, "Bad DOFF version 0x%x",
++                          dlthis->dfile_hdr.df_doff_version);
++              return;
++      }
++
++      /*
++       * Apply reasonableness checks to count fields
++       */
++      if (dlthis->dfile_hdr.df_strtab_size > MAX_REASONABLE_STRINGTAB) {
++              dload_error(dlthis, "Excessive string table size " FMT_UI32,
++                          dlthis->dfile_hdr.df_strtab_size);
++              return;
++      }
++      if (dlthis->dfile_hdr.df_no_scns > MAX_REASONABLE_SECTIONS) {
++              dload_error(dlthis, "Excessive section count 0x%x",
++                          dlthis->dfile_hdr.df_no_scns);
++              return;
++      }
++#ifndef TARGET_ENDIANNESS
++      /*
++       * Check that endianness does not disagree with explicit specification
++       */
++      if ((dlthis->dfile_hdr.df_flags >> ALIGN_COFF_ENDIANNESS) &
++          dlthis->myoptions & ENDIANNESS_MASK) {
++              dload_error(dlthis,
++                          "Input endianness disagrees with specified option");
++              return;
++      }
++      dlthis->big_e_target = dlthis->dfile_hdr.df_flags & DF_BIG;
++#endif
++
++}                             /* dload_headers */
++
++/*    COFF Section Processing
++ *
++ *    COFF sections are read in and retained intact.  Each record is embedded
++ *    in a new structure that records the updated load and
++ *    run addresses of the section  */
++
++static const char SECN_ERRID[] = { "section" };
++
++/*************************************************************************
++ * Procedure dload_sections
++ *
++ * Parameters:
++ *    none
++ *
++ * Effect:
++ *    Loads the section records into an internal table.
++ ************************************************************************/
++void
++dload_sections(struct dload_state *dlthis)
++{
++      s16 siz;
++      struct doff_scnhdr_t *shp;
++      unsigned nsecs = dlthis->dfile_hdr.df_no_scns;
++
++      /* allocate space for the DOFF section records */
++      siz = nsecs * sizeof(struct doff_scnhdr_t);
++      shp = (struct doff_scnhdr_t *)dlthis->mysym->Allocate(dlthis->mysym,
++             siz);
++      if (!shp) {             /* not enough storage */
++              DL_ERROR(E_ALLOC, siz);
++              return;
++      }
++      dlthis->sect_hdrs = shp;
++
++      /* read in the section records */
++      if (dlthis->strm->read_buffer(dlthis->strm, shp, siz) != siz) {
++              DL_ERROR(E_READSTRM, SECN_ERRID);
++              return;
++      }
++
++      /* if we need to fix up byte order, do it now */
++      if (dlthis->reorder_map)
++              dload_reorder(shp, siz, dlthis->reorder_map);
++
++      /* check for validity */
++      if (~dload_checksum(dlthis->sect_hdrs, siz) !=
++          dlthis->verify.dv_scn_rec_checksum) {
++              DL_ERROR(E_CHECKSUM, SECN_ERRID);
++              return;
++      }
++
++}                             /* dload_sections */
++
++/*****************************************************************************
++ * Procedure allocate_sections
++ *
++ * Parameters:
++ *    alloc   target memory allocator class
++ *
++ * Effect:
++ *    Assigns new (target) addresses for sections
++ *****************************************************************************/
++static void allocate_sections(struct dload_state *dlthis)
++{
++      u16 curr_sect, nsecs, siz;
++      struct doff_scnhdr_t *shp;
++      struct LDR_SECTION_INFO *asecs;
++      struct my_handle *hndl;
++      nsecs = dlthis->dfile_hdr.df_no_scns;
++      if (!nsecs)
++              return;
++      if ((dlthis->myalloc == NULL) &&
++         (dlthis->dfile_hdr.df_target_scns > 0)) {
++              DL_ERROR("Arg 3 (alloc) required but NULL", 0);
++              return;
++      }
++      /* allocate space for the module handle, which we will
++       *      keep for unload purposes */
++      siz = dlthis->dfile_hdr.df_target_scns *
++            sizeof(struct LDR_SECTION_INFO) + MY_HANDLE_SIZE;
++      hndl = (struct my_handle *)dlthis->mysym->Allocate(dlthis->mysym, siz);
++      if (!hndl) {            /* not enough storage */
++              DL_ERROR(E_ALLOC, siz);
++              return;
++      }
++      /* initialize the handle header */
++      hndl->dm.hnext = hndl->dm.hprev = hndl; /* circular list */
++      hndl->dm.hroot = NULL;
++      hndl->dm.dbthis = 0;
++      dlthis->myhandle = hndl;        /* save away for return */
++      /* pointer to the section list of allocated sections */
++      dlthis->ldr_sections = asecs = hndl->secns;
++      /* * Insert names into all sections, make copies of
++         the sections we allocate */
++      shp = dlthis->sect_hdrs;
++      for (curr_sect = 0; curr_sect < nsecs; curr_sect++) {
++              u32 soffset = shp->ds_offset;
++#if BITS_PER_AU <= BITS_PER_BYTE
++              /* attempt to insert the name of this section */
++              if (soffset < dlthis->dfile_hdr.df_strtab_size)
++                      DOFFSEC_IS_LDRSEC(shp)->name = dlthis->str_head +
++                                                             soffset;
++              else {
++                      dload_error(dlthis, "Bad name offset in section %d",
++                                  curr_sect);
++                      DOFFSEC_IS_LDRSEC(shp)->name = NULL;
++              }
++#endif
++              /* allocate target storage for sections that require it */
++              if (DS_NEEDS_ALLOCATION(shp)) {
++                      *asecs = *DOFFSEC_IS_LDRSEC(shp);
++                      asecs->context = 0;     /* zero the context field */
++#if BITS_PER_AU > BITS_PER_BYTE
++                      asecs->name = unpack_name(dlthis, soffset);
++                      dlthis->debug_string_size = soffset + dlthis->temp_len;
++#else
++                      dlthis->debug_string_size = soffset;
++#endif
++              if (dlthis->myalloc != NULL) {
++                      if (!dlthis->myalloc->Allocate(dlthis->myalloc, asecs,
++                                   DS_ALIGNMENT(asecs->type))) {
++                              dload_error(dlthis, E_TGTALLOC, asecs->name,
++                                          asecs->size);
++                              return;
++                      }
++                      }
++                      /* keep address deltas in original section table */
++                      shp->ds_vaddr = asecs->load_addr - shp->ds_vaddr;
++                      shp->ds_paddr = asecs->run_addr - shp->ds_paddr;
++                      dlthis->allocated_secn_count += 1;
++              }               /* allocate target storage */
++              shp += 1;
++              asecs += 1;
++      }
++#if BITS_PER_AU <= BITS_PER_BYTE
++      dlthis->debug_string_size +=
++          strlen(dlthis->str_head + dlthis->debug_string_size) + 1;
++#endif
++}                             /* allocate sections */
++
++/*************************************************************************
++ * Procedure section_table_free
++ *
++ * Parameters:
++ *    none
++ *
++ * Effect:
++ *    Frees any state used by the symbol table.
++ *
++ * WARNING:
++ *    This routine is not allowed to declare errors!
++ ************************************************************************/
++static void section_table_free(struct dload_state *dlthis)
++{
++      struct doff_scnhdr_t *shp;
++
++      shp = dlthis->sect_hdrs;
++      if (shp)
++              dlthis->mysym->Deallocate(dlthis->mysym, shp);
++
++}                             /* section_table_free */
++
++/*************************************************************************
++ * Procedure dload_strings
++ *
++ * Parameters:
++ *  sec_names_only   If true only read in the "section names"
++ *                 portion of the string table
++ *
++ * Effect:
++ *    Loads the DOFF string table into memory. DOFF keeps all strings in a
++ * big unsorted array.  We just read that array into memory in bulk.
++ ************************************************************************/
++static const char S_STRINGTBL[] = { "string table" };
++void dload_strings(struct dload_state *dlthis, boolean sec_names_only)
++{
++      u32 ssiz;
++      char *strbuf;
++
++      if (sec_names_only) {
++              ssiz = BYTE_TO_HOST(DOFF_ALIGN
++                                 (dlthis->dfile_hdr.df_scn_name_size));
++      } else {
++              ssiz = BYTE_TO_HOST(DOFF_ALIGN
++                                 (dlthis->dfile_hdr.df_strtab_size));
++      }
++      if (ssiz == 0)
++              return;
++
++      /* get some memory for the string table */
++#if BITS_PER_AU > BITS_PER_BYTE
++      strbuf = (char *)dlthis->mysym->Allocate(dlthis->mysym, ssiz +
++                                           dlthis->dfile_hdr.df_max_str_len);
++#else
++      strbuf = (char *)dlthis->mysym->Allocate(dlthis->mysym, ssiz);
++#endif
++      if (strbuf == NULL) {
++              DL_ERROR(E_ALLOC, ssiz);
++              return;
++      }
++      dlthis->str_head = strbuf;
++#if BITS_PER_AU > BITS_PER_BYTE
++      dlthis->str_temp = strbuf + ssiz;
++#endif
++      /* read in the strings and verify them */
++      if ((unsigned)(dlthis->strm->read_buffer(dlthis->strm, strbuf,
++          ssiz)) != ssiz) {
++              DL_ERROR(E_READSTRM, S_STRINGTBL);
++      }
++      /* if we need to fix up byte order, do it now */
++#ifndef _BIG_ENDIAN
++      if (dlthis->reorder_map)
++              dload_reorder(strbuf, ssiz, dlthis->reorder_map);
++
++      if ((!sec_names_only) && (~dload_checksum(strbuf, ssiz) !=
++           dlthis->verify.dv_str_tab_checksum)) {
++              DL_ERROR(E_CHECKSUM, S_STRINGTBL);
++      }
++#else
++      if (dlthis->dfile_hdr.df_byte_reshuffle !=
++          HOST_BYTE_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
++              /* put strings in big-endian order, not in PC order */
++              dload_reorder(strbuf, ssiz, HOST_BYTE_ORDER(dlthis->dfile_hdr.
++                                            df_byte_reshuffle));
++      }
++      if ((!sec_names_only) && (~dload_reverse_checksum(strbuf, ssiz) !=
++           dlthis->verify.dv_str_tab_checksum)) {
++              DL_ERROR(E_CHECKSUM, S_STRINGTBL);
++      }
++#endif
++}                             /* dload_strings */
++
++/*************************************************************************
++ * Procedure string_table_free
++ *
++ * Parameters:
++ *    none
++ *
++ * Effect:
++ *    Frees any state used by the string table.
++ *
++ * WARNING:
++ *    This routine is not allowed to declare errors!
++ *************************************************************************/
++static void string_table_free(struct dload_state *dlthis)
++{
++      if (dlthis->str_head)
++              dlthis->mysym->Deallocate(dlthis->mysym, dlthis->str_head);
++
++}                             /* string_table_free */
++
++/*
++ * Symbol Table Maintenance Functions
++ *
++ * COFF symbols are read by dload_symbols(), which is called after
++ * sections have been allocated.  Symbols which might be used in
++ * relocation (ie, not debug info) are retained in an internal temporary
++ * compressed table (type Local_Symbol). A particular symbol is recovered
++ * by index by calling dload_find_symbol().  dload_find_symbol
++ * reconstructs a more explicit representation (type SLOTVEC) which is
++ * used by reloc.c
++ */
++/* real size of debug header */
++#define DBG_HDR_SIZE (sizeof(struct dll_module) - sizeof(struct dll_sect))
++
++static const char SYM_ERRID[] = { "symbol" };
++
++/**************************************************************************
++ * Procedure dload_symbols
++ *
++ * Parameters:
++ *    none
++ *
++ * Effect:
++ *    Reads in symbols and retains ones that might be needed for relocation
++ * purposes.
++ ************************************************************************/
++/* size of symbol buffer no bigger than target data buffer, to limit stack
++ * usage*/
++#define MY_SYM_BUF_SIZ (BYTE_TO_HOST(IMAGE_PACKET_SIZE)/\
++                      sizeof(struct doff_syment_t))
++
++static void dload_symbols(struct dload_state *dlthis)
++{
++      u32 s_count, siz, dsiz, symbols_left;
++      u32 checks;
++      struct Local_Symbol *sp;
++      struct dynload_symbol *symp;
++      struct dynload_symbol *newsym;
++
++      s_count = dlthis->dfile_hdr.df_no_syms;
++      if (s_count == 0)
++              return;
++
++      /* We keep a local symbol table for all of the symbols in the input.
++       * This table contains only section & value info, as we do not have
++       * to do any name processing for locals.  We reuse this storage
++       * as a temporary for .dllview record construction.
++       * Allocate storage for the whole table.*/
++      siz = s_count * sizeof(struct Local_Symbol);
++      dsiz = DBG_HDR_SIZE +
++              (sizeof(struct dll_sect) * dlthis->allocated_secn_count) +
++          BYTE_TO_HOST_ROUND(dlthis->debug_string_size + 1);
++      if (dsiz > siz)
++              siz = dsiz;     /* larger of symbols and .dllview temp */
++      sp = (struct Local_Symbol *)dlthis->mysym->Allocate(dlthis->mysym, siz);
++      if (!sp) {
++              DL_ERROR(E_ALLOC, siz);
++              return;
++      }
++      dlthis->local_symtab = sp;
++      /* Read the symbols in the input, store them in the table, and post any
++       * globals to the global symbol table.  In the process, externals
++         become defined from the global symbol table */
++      checks = dlthis->verify.dv_sym_tab_checksum;
++      symbols_left = s_count;
++      do {                    /* read all symbols */
++              char *sname;
++              u32 val;
++              s32 delta;
++              struct doff_syment_t *input_sym;
++              unsigned syms_in_buf;
++              struct doff_syment_t my_sym_buf[MY_SYM_BUF_SIZ];
++              input_sym = my_sym_buf;
++              syms_in_buf = symbols_left > MY_SYM_BUF_SIZ ?
++                                           MY_SYM_BUF_SIZ : symbols_left;
++              siz = syms_in_buf * sizeof(struct doff_syment_t);
++              if (dlthis->strm->read_buffer(dlthis->strm, input_sym, siz) !=
++                                            siz) {
++                      DL_ERROR(E_READSTRM, SYM_ERRID);
++                      return;
++              }
++              if (dlthis->reorder_map)
++                      dload_reorder(input_sym, siz, dlthis->reorder_map);
++
++              checks += dload_checksum(input_sym, siz);
++              do {            /* process symbols in buffer */
++                      symbols_left -= 1;
++                      /* attempt to derive the name of this symbol */
++                      sname = NULL;
++                      if (input_sym->dn_offset > 0) {
++#if BITS_PER_AU <= BITS_PER_BYTE
++                              if ((u32) input_sym->dn_offset <
++                                  dlthis->dfile_hdr.df_strtab_size)
++                                      sname = dlthis->str_head +
++                                           BYTE_TO_HOST(input_sym->dn_offset);
++                              else
++                                      dload_error(dlthis,
++                                               "Bad name offset in symbol %d",
++                                               symbols_left);
++#else
++                              sname = unpack_name(dlthis,
++                                                 input_sym->dn_offset);
++#endif
++                      }
++                      val = input_sym->dn_value;
++                      delta = 0;
++                      sp->sclass = input_sym->dn_sclass;
++                      sp->secnn = input_sym->dn_scnum;
++                      /* if this is an undefined symbol,
++                       * define it (or fail) now        */
++                      if (sp->secnn == DN_UNDEF) {
++                                      /* pointless for static undefined */
++                              if (input_sym->dn_sclass != DN_EXT)
++                                      goto loop_cont;
++
++                              /* try to define symbol from previously
++                               * loaded images                          */
++                              symp = dlthis->mysym->Find_Matching_Symbol
++                                                    (dlthis->mysym, sname);
++                              if (!symp) {
++                                      DL_ERROR
++                                              ("Undefined external symbol %s",
++                                               sname);
++                                      goto loop_cont;
++                              }
++                              val = delta = symp->value;
++                              goto loop_cont;
++                      }
++                      /* symbol defined by this module */
++                      if (sp->secnn > 0) {   /* symbol references a section */
++                              if ((unsigned)sp->secnn <=
++                                  dlthis->allocated_secn_count) {
++                                      /* section was allocated */
++                                      struct doff_scnhdr_t *srefp =
++                                                           &dlthis->sect_hdrs
++                                                           [sp->secnn - 1];
++
++                                      if (input_sym->dn_sclass ==
++                                          DN_STATLAB ||
++                                          input_sym->dn_sclass == DN_EXTLAB){
++                                              /* load */
++                                              delta = srefp->ds_vaddr;
++                                      } else {
++                                              /* run */
++                                              delta = srefp->ds_paddr;
++                                      }
++                                      val += delta;
++                              }
++                              goto loop_itr;
++                      }
++                      /* This symbol is an absolute symbol */
++                      if (sp->secnn == DN_ABS && ((sp->sclass == DN_EXT) ||
++                                                 (sp->sclass == DN_EXTLAB))) {
++                              symp = dlthis->mysym->Find_Matching_Symbol
++                                                    (dlthis->mysym, sname);
++                              if (!symp)
++                                      goto loop_itr;
++                              /* This absolute symbol is already defined.  */
++                              if (symp->value == input_sym->dn_value) {
++                                      /* If symbol values are equal, continue
++                                       * but don't add to the global symbol
++                                       * table                             */
++                                      sp->value = val;
++                                      sp->delta = delta;
++                                      sp += 1;
++                                      input_sym += 1;
++                                      continue;
++                              } else {
++                                      /* If symbol values are not equal,
++                                       * return with redefinition error */
++                                      DL_ERROR("Absolute symbol %s is "
++                                         "defined multiple times with "
++                                         "different values", sname);
++                                      return;
++                              }
++                      }
++loop_itr:
++                      /* if this is a global symbol, post it to the
++                       * global table                        */
++                      if (input_sym->dn_sclass == DN_EXT ||
++                          input_sym->dn_sclass == DN_EXTLAB) {
++                              /* Keep this global symbol for subsequent
++                               * modules. Don't complain on error, to allow
++                               * symbol API to suppress global symbols */
++                              if (!sname)
++                                      goto loop_cont;
++
++                              newsym = dlthis->mysym->Add_To_Symbol_Table
++                                                  (dlthis->mysym, sname,
++                                                  (unsigned)dlthis->myhandle);
++                              if (newsym)
++                                      newsym->value = val;
++
++                      }       /* global */
++loop_cont:
++                      sp->value = val;
++                      sp->delta = delta;
++                      sp += 1;
++                      input_sym += 1;
++              } while ((syms_in_buf -= 1) > 0); /* process sym in buffer */
++      } while (symbols_left > 0);     /* read all symbols */
++      if (~checks)
++              dload_error(dlthis, "Checksum of symbols failed");
++
++}                             /* dload_symbols */
++
++/*****************************************************************************
++ * Procedure symbol_table_free
++ *
++ * Parameters:
++ *    none
++ *
++ * Effect:
++ *    Frees any state used by the symbol table.
++ *
++ * WARNING:
++ *    This routine is not allowed to declare errors!
++ *****************************************************************************/
++static void symbol_table_free(struct dload_state *dlthis)
++{
++      if (dlthis->local_symtab) {
++              if (dlthis->dload_errcount) {   /* blow off our symbols */
++                      dlthis->mysym->Purge_Symbol_Table(dlthis->mysym,
++                                                 (unsigned)dlthis->myhandle);
++              }
++              dlthis->mysym->Deallocate(dlthis->mysym, dlthis->local_symtab);
++      }
++}                             /* symbol_table_free */
++
++/* .cinit Processing
++ *
++ * The dynamic loader does .cinit interpretation.  cload_cinit()
++ * acts as a special write-to-target function, in that it takes relocated
++ * data from the normal data flow, and interprets it as .cinit actions.
++ * Because the normal data flow does not  necessarily process the whole
++ * .cinit section in one buffer, cload_cinit() must be prepared to
++ * interpret the data piecemeal.  A state machine is used for this
++ * purpose.
++ */
++
++/* The following are only for use by reloc.c and things it calls */
++static const struct LDR_SECTION_INFO CINIT_INFO_INIT = { CINITNAME, 0, 0,
++                                      (LDR_ADDR) -1, 0, DLOAD_BSS, 0 };
++
++/*************************************************************************
++ * Procedure cload_cinit
++ *
++ * Parameters:
++ *    ipacket         Pointer to data packet to be loaded
++ *
++ * Effect:
++ *    Interprets the data in the buffer as .cinit data, and performs the
++ * appropriate initializations.
++ ************************************************************************/
++static void cload_cinit(struct dload_state *dlthis,
++                      struct image_packet_t *ipacket)
++{
++#if TDATA_TO_HOST(CINIT_COUNT)*BITS_PER_AU > 16
++      s32 init_count, left;
++#else
++      s16 init_count, left;
++#endif
++      unsigned char *pktp = ipacket->i_bits;
++      unsigned char *pktend = pktp +
++                              BYTE_TO_HOST_ROUND(ipacket->i_packet_size);
++      int temp;
++      LDR_ADDR atmp;
++      struct LDR_SECTION_INFO cinit_info;
++
++      /*  PROCESS ALL THE INITIALIZATION RECORDS IN THE BUFFER.  */
++      while (true) {
++              left = pktend - pktp;
++              switch (dlthis->cinit_state) {
++              case CI_count:  /* count field */
++                      if (left < TDATA_TO_HOST(CINIT_COUNT))
++                              goto loopexit;
++                      temp = dload_unpack(dlthis, (TgtAU_t *)pktp,
++                                      CINIT_COUNT * TDATA_AU_BITS, 0,
++                                      ROP_SGN);
++                      pktp += TDATA_TO_HOST(CINIT_COUNT);
++                      /* negative signifies BSS table, zero means done */
++                      if (temp <= 0) {
++                              dlthis->cinit_state = CI_done;
++                              break;
++                      }
++                      dlthis->cinit_count = temp;
++                      dlthis->cinit_state = CI_address;
++                      break;
++#if CINIT_ALIGN < CINIT_ADDRESS
++              case CI_partaddress:
++                      pktp -= TDATA_TO_HOST(CINIT_ALIGN);
++                      /* back up pointer into space courtesy of caller */
++                      *(uint16_t *)pktp = dlthis->cinit_addr;
++                      /* stuff in saved bits  !! FALL THRU !! */
++#endif
++              case CI_address:        /* Address field for a copy packet */
++                      if (left < TDATA_TO_HOST(CINIT_ADDRESS)) {
++#if CINIT_ALIGN < CINIT_ADDRESS
++                              if (left == TDATA_TO_HOST(CINIT_ALIGN)) {
++                                      /* address broken into halves */
++                                      dlthis->cinit_addr = *(uint16_t *)pktp;
++                                      /* remember 1st half */
++                                      dlthis->cinit_state = CI_partaddress;
++                                      left = 0;
++                              }
++#endif
++                              goto loopexit;
++                      }
++                      atmp = dload_unpack(dlthis, (TgtAU_t *)pktp,
++                                      CINIT_ADDRESS * TDATA_AU_BITS, 0,
++                                      ROP_UNS);
++                      pktp += TDATA_TO_HOST(CINIT_ADDRESS);
++#if CINIT_PAGE_BITS > 0
++                      dlthis->cinit_page = atmp &
++                                           ((1 << CINIT_PAGE_BITS) - 1);
++                      atmp >>= CINIT_PAGE_BITS;
++#else
++                      dlthis->cinit_page = CINIT_DEFAULT_PAGE;
++#endif
++                      dlthis->cinit_addr = atmp;
++                      dlthis->cinit_state = CI_copy;
++                      break;
++              case CI_copy:   /* copy bits to the target */
++                      init_count = HOST_TO_TDATA(left);
++                      if (init_count > dlthis->cinit_count)
++                              init_count = dlthis->cinit_count;
++                      if (init_count == 0)
++                              goto loopexit;  /* get more bits */
++                      cinit_info = CINIT_INFO_INIT;
++                      cinit_info.page = dlthis->cinit_page;
++                      if (!dlthis->myio->writemem(dlthis->myio, pktp,
++                                      TDATA_TO_TADDR(dlthis->cinit_addr),
++                                      &cinit_info,
++                                      TDATA_TO_HOST(init_count))) {
++                              dload_error(dlthis, E_INITFAIL, "write",
++                                          dlthis->cinit_addr);
++                      }
++                      dlthis->cinit_count -= init_count;
++                      if (dlthis->cinit_count  <= 0) {
++                              dlthis->cinit_state = CI_count;
++                              init_count = (init_count + CINIT_ALIGN - 1) &
++                                           -CINIT_ALIGN;
++                              /* align to next init */
++                      }
++                      pktp += TDATA_TO_HOST(init_count);
++                      dlthis->cinit_addr += init_count;
++                      break;
++              case CI_done:   /* no more .cinit to do */
++                      return;
++              }               /* switch (cinit_state) */
++      }                       /* while */
++
++loopexit:
++      if (left > 0) {
++              dload_error(dlthis, "%d bytes left over in cinit packet", left);
++              dlthis->cinit_state = CI_done;  /* left over bytes are bad */
++      }
++}                             /* cload_cinit */
++
++/*    Functions to interface to reloc.c
++ *
++ * reloc.c is the relocation module borrowed from the linker, with
++ * minimal (we hope) changes for our purposes.  cload_sect_data() invokes
++ * this module on a section to relocate and load the image data for that
++ * section.  The actual read and write actions are supplied by the global
++ * routines below.
++ */
++
++/************************************************************************
++ * Procedure relocate_packet
++ *
++ * Parameters:
++ *    ipacket         Pointer to an image packet to relocate
++ *
++ * Effect:
++ *    Performs the required relocations on the packet.  Returns a checksum
++ * of the relocation operations.
++ ************************************************************************/
++#define MY_RELOC_BUF_SIZ 8
++/* careful! exists at the same time as the image buffer*/
++static int relocate_packet(struct dload_state *dlthis,
++                         struct image_packet_t *ipacket, u32 *checks)
++{
++      u32 rnum;
++
++      rnum = ipacket->i_num_relocs;
++      do {                    /* all relocs */
++              unsigned rinbuf;
++              int siz;
++              struct reloc_record_t *rp, rrec[MY_RELOC_BUF_SIZ];
++              rp = rrec;
++              rinbuf = rnum > MY_RELOC_BUF_SIZ ? MY_RELOC_BUF_SIZ : rnum;
++              siz = rinbuf * sizeof(struct reloc_record_t);
++              if (dlthis->strm->read_buffer(dlthis->strm, rp, siz) != siz) {
++                      DL_ERROR(E_READSTRM, "relocation");
++                      return 0;
++              }
++              /* reorder the bytes if need be */
++              if (dlthis->reorder_map)
++                      dload_reorder(rp, siz, dlthis->reorder_map);
++
++              *checks += dload_checksum(rp, siz);
++              do {
++                      /* perform the relocation operation */
++                      dload_relocate(dlthis, (TgtAU_t *) ipacket->i_bits, rp);
++                      rp += 1;
++                      rnum -= 1;
++              } while ((rinbuf -= 1) > 0);
++      } while (rnum > 0);     /* all relocs */
++      return 1;
++}                             /* dload_read_reloc */
++
++#define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
++
++/* VERY dangerous */
++static const char IMAGEPAK[] = { "image packet" };
++
++/*************************************************************************
++ * Procedure dload_data
++ *
++ * Parameters:
++ *    none
++ *
++ * Effect:
++ *    Read image data from input file, relocate it, and download it to the
++ *    target.
++ ************************************************************************/
++static void dload_data(struct dload_state *dlthis)
++{
++      u16 curr_sect;
++      struct doff_scnhdr_t *sptr = dlthis->sect_hdrs;
++      struct LDR_SECTION_INFO *lptr = dlthis->ldr_sections;
++#ifdef OPT_ZERO_COPY_LOADER
++      boolean bZeroCopy = false;
++#endif
++      u8 *pDest;
++
++      struct {
++              struct image_packet_t ipacket;
++              u8 bufr[BYTE_TO_HOST(IMAGE_PACKET_SIZE)];
++      } ibuf;
++
++      /* Indicates whether CINIT processing has occurred */
++      boolean cinit_processed = false;
++
++      /* Loop through the sections and load them one at a time.
++       */
++      for (curr_sect = 0; curr_sect < dlthis->dfile_hdr.df_no_scns;
++           curr_sect += 1) {
++              if (DS_NEEDS_DOWNLOAD(sptr)) {
++                      s32 nip;
++                      LDR_ADDR image_offset = 0;
++                      /* set relocation info for this section */
++                      if (curr_sect < dlthis->allocated_secn_count)
++                              dlthis->delta_runaddr = sptr->ds_paddr;
++                      else {
++                              lptr = DOFFSEC_IS_LDRSEC(sptr);
++                              dlthis->delta_runaddr = 0;
++                      }
++                      dlthis->image_secn = lptr;
++#if BITS_PER_AU > BITS_PER_BYTE
++                      lptr->name = unpack_name(dlthis, sptr->ds_offset);
++#endif
++                      nip = sptr->ds_nipacks;
++                      while ((nip -= 1) >= 0) {       /* process packets */
++
++                              s32 ipsize;
++                              u32 checks;
++                              /* get the fixed header bits */
++                              if (dlthis->strm->read_buffer(dlthis->strm,
++                                  &ibuf.ipacket, IPH_SIZE) != IPH_SIZE) {
++                                      DL_ERROR(E_READSTRM, IMAGEPAK);
++                                      return;
++                              }
++                              /* reorder the header if need be */
++                              if (dlthis->reorder_map) {
++                                      dload_reorder(&ibuf.ipacket, IPH_SIZE,
++                                                    dlthis->reorder_map);
++                              }
++                              /* now read the rest of the packet */
++                              ipsize =
++                                  BYTE_TO_HOST(DOFF_ALIGN
++                                              (ibuf.ipacket.i_packet_size));
++                              if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
++                                      DL_ERROR("Bad image packet size %d",
++                                              ipsize);
++                                      return;
++                              }
++                              pDest = ibuf.bufr;
++#ifdef OPT_ZERO_COPY_LOADER
++                              bZeroCopy = false;
++                              if (DLOAD_SECT_TYPE(sptr) != DLOAD_CINIT) {
++                                      dlthis->myio->writemem(dlthis->myio,
++                                              &pDest, lptr->load_addr +
++                                              image_offset, lptr, 0);
++                              bZeroCopy = (pDest != ibuf.bufr);
++                              }
++#endif
++              /* End of determination */
++
++                              if (dlthis->strm->read_buffer(dlthis->strm,
++                                  ibuf.bufr, ipsize) != ipsize) {
++                                      DL_ERROR(E_READSTRM, IMAGEPAK);
++                                      return;
++                              }
++                              ibuf.ipacket.i_bits = pDest;
++
++                              /* reorder the bytes if need be */
++#if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
++                              if (dlthis->reorder_map) {
++                                      dload_reorder(pDest, ipsize,
++                                                   dlthis->reorder_map);
++                              }
++                              checks = dload_checksum(pDest, ipsize);
++#else
++                              if (dlthis->dfile_hdr.df_byte_reshuffle !=
++                                  TARGET_ORDER(REORDER_MAP
++                                  (BYTE_RESHUFFLE_VALUE))) {
++                                      /* put image bytes in big-endian order,
++                                       * not PC order */
++                                      dload_reorder(pDest, ipsize,
++                                      TARGET_ORDER
++                                      (dlthis->dfile_hdr.df_byte_reshuffle));
++                              }
++#if TARGET_AU_BITS > 8
++                              checks = dload_reverse_checksum_16(pDest,
++                                                                 ipsize);
++#else
++                              checks = dload_reverse_checksum(pDest,
++                                                              ipsize);
++#endif
++#endif
++
++                              checks += dload_checksum(&ibuf.ipacket,
++                                                      IPH_SIZE);
++                              /* relocate the image bits as needed */
++                              if (ibuf.ipacket.i_num_relocs) {
++                                      dlthis->image_offset = image_offset;
++                                      if (!relocate_packet(dlthis,
++                                          &ibuf.ipacket, &checks))
++                                              return; /* serious error */
++                              }
++                              if (~checks)
++                                      DL_ERROR(E_CHECKSUM, IMAGEPAK);
++                              /* stuff the result into target memory */
++                              if (DLOAD_SECT_TYPE(sptr) == DLOAD_CINIT) {
++                                      cload_cinit(dlthis, &ibuf.ipacket);
++                                      cinit_processed = true;
++                              } else {
++#ifdef OPT_ZERO_COPY_LOADER
++                                  if (!bZeroCopy) {
++#endif
++
++                                      if (!dlthis->myio->writemem
++                                         (dlthis->myio, ibuf.bufr,
++                                         lptr->load_addr + image_offset, lptr,
++                                         BYTE_TO_HOST
++                                         (ibuf.ipacket.i_packet_size))) {
++                                              DL_ERROR(
++                                              "Write to " FMT_UI32 " failed",
++                                              lptr->load_addr + image_offset);
++                                      }
++#ifdef OPT_ZERO_COPY_LOADER
++                              }
++#endif
++
++                              }
++                              image_offset +=
++                                    BYTE_TO_TADDR(ibuf.ipacket.i_packet_size);
++                      }       /* process packets */
++                      /* if this is a BSS section, we may want to fill it */
++                      if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
++                              goto loop_cont;
++
++                      if (!(dlthis->myoptions & DLOAD_INITBSS))
++                              goto loop_cont;
++
++                      if (cinit_processed) {
++                              /* Don't clear BSS after load-time
++                               * initialization */
++                              DL_ERROR
++                                ("Zero-initialization at " FMT_UI32 " after "
++                                "load-time initialization!", lptr->load_addr);
++                              goto loop_cont;
++                      }
++                      /* fill the .bss area */
++                      dlthis->myio->fillmem(dlthis->myio,
++                                            TADDR_TO_HOST(lptr->load_addr),
++                                            lptr, TADDR_TO_HOST(lptr->size),
++                                            dload_fill_bss);
++                      goto loop_cont;
++              } /* if DS_DOWNLOAD_MASK */
++              /* If not loading, but BSS, zero initialize */
++              if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
++                      goto loop_cont;
++
++              if (!(dlthis->myoptions & DLOAD_INITBSS))
++                      goto loop_cont;
++
++              if (curr_sect >= dlthis->allocated_secn_count)
++                      lptr = DOFFSEC_IS_LDRSEC(sptr);
++
++              if (cinit_processed) {
++                      /*Don't clear BSS after load-time initialization */
++                      DL_ERROR(
++                       "Zero-initialization at " FMT_UI32 " attempted after "
++                       "load-time initialization!", lptr->load_addr);
++                      goto loop_cont;
++              }
++              /* fill the .bss area */
++              dlthis->myio->fillmem(dlthis->myio,
++                                   TADDR_TO_HOST(lptr->load_addr), lptr,
++                                   TADDR_TO_HOST(lptr->size), dload_fill_bss);
++loop_cont:
++              sptr += 1;
++              lptr += 1;
++      }                       /* load sections */
++}                             /* dload_data */
++
++/*************************************************************************
++ * Procedure dload_reorder
++ *
++ * Parameters:
++ *    data    32-bit aligned pointer to data to be byte-swapped
++ *    dsiz    size of the data to be reordered in sizeof() units.
++ *    map             32-bit map defining how to reorder the data.  Value
++ *                    must be REORDER_MAP() of some permutation
++ *                    of 0x00 01 02 03
++ *
++ * Effect:
++ *    Re-arranges the bytes in each word according to the map specified.
++ *
++ ************************************************************************/
++/* mask for byte shift count */
++#define SHIFT_COUNT_MASK (3 << LOG_BITS_PER_BYTE)
++
++void dload_reorder(void *data, int dsiz, unsigned int map)
++{
++      register u32 tmp, tmap, datv;
++      u32 *dp = (u32 *)data;
++
++      map <<= LOG_BITS_PER_BYTE;      /* align map with SHIFT_COUNT_MASK */
++      do {
++              tmp = 0;
++              datv = *dp;
++              tmap = map;
++              do {
++                      tmp |= (datv & BYTE_MASK) << (tmap & SHIFT_COUNT_MASK);
++                      tmap >>= BITS_PER_BYTE;
++              } while (datv >>= BITS_PER_BYTE);
++              *dp++ = tmp;
++      } while ((dsiz -= sizeof(u32)) > 0);
++}                             /* dload_reorder */
++
++/*************************************************************************
++ * Procedure dload_checksum
++ *
++ * Parameters:
++ *    data    32-bit aligned pointer to data to be checksummed
++ *    siz             size of the data to be checksummed in sizeof() units.
++ *
++ * Effect:
++ *    Returns a checksum of the specified block
++ *
++ ************************************************************************/
++u32 dload_checksum(void *data, unsigned siz)
++{
++      u32 sum;
++      u32 *dp;
++      int left;
++
++      sum = 0;
++      dp = (u32 *)data;
++      for (left = siz; left > 0; left -= sizeof(u32))
++              sum += *dp++;
++      return sum;
++}                             /* dload_checksum */
++
++#if HOST_ENDIANNESS
++/*************************************************************************
++ * Procedure dload_reverse_checksum
++ *
++ * Parameters:
++ *    data    32-bit aligned pointer to data to be checksummed
++ *    siz             size of the data to be checksummed in sizeof() units.
++ *
++ * Effect:
++ *    Returns a checksum of the specified block, which is assumed to be bytes
++ * in big-endian order.
++ *
++ * Notes:
++ *    In a big-endian host, things like the string table are stored as bytes
++ * in host order. But dllcreate always checksums in little-endian order.
++ * It is most efficient to just handle the difference a word at a time.
++ *
++ ***********************************************************************/
++u32 dload_reverse_checksum(void *data, unsigned siz)
++{
++      u32 sum, temp;
++      u32 *dp;
++      int left;
++
++      sum = 0;
++      dp = (u32 *)data;
++
++      for (left = siz; left > 0; left -= sizeof(u32)) {
++              temp = *dp++;
++              sum += temp << BITS_PER_BYTE * 3;
++              sum += temp >> BITS_PER_BYTE * 3;
++              sum += (temp >> BITS_PER_BYTE) & (BYTE_MASK << BITS_PER_BYTE);
++              sum += (temp & (BYTE_MASK << BITS_PER_BYTE)) << BITS_PER_BYTE;
++      }
++
++      return sum;
++}                             /* dload_reverse_checksum */
++
++#if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
++u32 dload_reverse_checksum_16(void *data, unsigned siz)
++{
++      uint_fast32_t sum, temp;
++      u32 *dp;
++      int left;
++
++      sum = 0;
++      dp = (u32 *)data;
++
++      for (left = siz; left > 0; left -= sizeof(u32)) {
++              temp = *dp++;
++              sum += temp << BITS_PER_BYTE * 2;
++              sum += temp >> BITS_PER_BYTE * 2;
++      }
++
++      return sum;
++}                             /* dload_reverse_checksum_16 */
++#endif
++#endif
++
++/*************************************************************************
++ * Procedure swap_words
++ *
++ * Parameters:
++ *    data    32-bit aligned pointer to data to be swapped
++ *    siz     size of the data to be swapped.
++ *    bitmap  Bit map of how to swap each 32-bit word; 1 => 2 shorts,
++ *            0 => 1 long
++ *
++ * Effect:
++ *    Swaps the specified data according to the specified map
++ *
++ ************************************************************************/
++static void swap_words(void *data, unsigned siz, unsigned bitmap)
++{
++      register int i;
++#if TARGET_AU_BITS < 16
++      register u16 *sp;
++#endif
++      register u32 *lp;
++
++      siz /= sizeof(u16);
++
++#if TARGET_AU_BITS < 16
++      /* pass 1: do all the bytes */
++      i = siz;
++      sp = (u16 *) data;
++      do {
++              register u16 tmp;
++              tmp = *sp;
++              *sp++ = SWAP16BY8(tmp);
++      } while ((i -= 1) > 0);
++#endif
++
++#if TARGET_AU_BITS < 32
++      /* pass 2: fixup the 32-bit words */
++      i = siz >> 1;
++      lp = (u32 *) data;
++      do {
++              if ((bitmap & 1) == 0) {
++                      register u32 tmp;
++                      tmp = *lp;
++                      *lp = SWAP32BY16(tmp);
++              }
++              lp += 1;
++              bitmap >>= 1;
++      } while ((i -= 1) > 0);
++#endif
++}                             /* swap_words */
++
++/*************************************************************************
++ * Procedure copy_tgt_strings
++ *
++ * Parameters:
++ *    dstp            Destination address.  Assumed to be 32-bit aligned
++ *    srcp            Source address.  Assumed to be 32-bit aligned
++ *    charcount       Number of characters to copy.
++ *
++ * Effect:
++ *    Copies strings from the source (which is in usual .dof file order on
++ * the loading processor) to the destination buffer (which should be in proper
++ * target addressable unit order).  Makes sure the last string in the
++ * buffer is NULL terminated (for safety).
++ * Returns the first unused destination address.
++ ************************************************************************/
++static char *copy_tgt_strings(void *dstp, void *srcp, unsigned charcount)
++{
++      register TgtAU_t *src = (TgtAU_t *)srcp;
++      register TgtAU_t *dst = (TgtAU_t *)dstp;
++      register int cnt = charcount;
++      do {
++#if TARGET_AU_BITS <= BITS_PER_AU
++              /* byte-swapping issues may exist for strings on target */
++              *dst++ = *src++;
++#elif TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)
++              register TgtAU_t tmp;
++              tmp = *src++;
++              *dst++ = SWAP16BY8(tmp);  /* right for TARGET_AU_BITS == 16 */
++#else
++              *dst++ = *src++;
++#endif
++      } while ((cnt -= (sizeof(TgtAU_t) * BITS_PER_AU / BITS_PER_BYTE)) > 0);
++      /*apply force to make sure that the string table has null terminator */
++#if (BITS_PER_AU == BITS_PER_BYTE) && (TARGET_AU_BITS == BITS_PER_BYTE)
++      dst[-1] = 0;
++#elif TARGET_BIG_ENDIAN
++      dst[-1] &= ~BYTE_MASK;  /*  big-endian */
++#else
++      dst[-1] &= (1 << (BITS_PER_AU - BITS_PER_BYTE)) - 1; /* little endian */
++#endif
++      return (char *)dst;
++}                             /* copy_tgt_strings */
++
++/*************************************************************************
++ * Procedure init_module_handle
++ *
++ * Parameters:
++ *    none
++ *
++ * Effect:
++ *    Initializes the module handle we use to enable unloading, and installs
++ * the debug information required by the target.
++ *
++ * Notes:
++ * The handle returned from Dynamic_Load_Module needs to encapsulate all the
++ * allocations done for the module, and enable them plus the modules symbols to
++ * be deallocated.
++ *
++ ************************************************************************/
++#ifndef _BIG_ENDIAN
++static const struct LDR_SECTION_INFO DLLVIEW_INFO_INIT = { ".dllview", 0, 0,
++                              (LDR_ADDR) -1, DBG_LIST_PAGE, DLOAD_DATA, 0 };
++#else
++static const struct LDR_SECTION_INFO DLLVIEW_INFO_INIT = { ".dllview", 0, 0,
++                              (LDR_ADDR) -1, DLOAD_DATA, DBG_LIST_PAGE, 0 };
++#endif
++static void init_module_handle(struct dload_state *dlthis)
++{
++      struct my_handle *hndl;
++      u16 curr_sect;
++      struct LDR_SECTION_INFO *asecs;
++      struct dll_module *dbmod;
++      struct dll_sect *dbsec;
++      struct dbg_mirror_root *mlist;
++      register char *cp;
++      struct modules_header mhdr;
++      struct LDR_SECTION_INFO dllview_info;
++      struct dynload_symbol *debug_mirror_sym;
++      hndl = dlthis->myhandle;
++      if (!hndl)
++              return;         /* must be errors detected, so forget it */
++      hndl->secn_count = dlthis->allocated_secn_count << 1;
++#ifndef TARGET_ENDIANNESS
++      if (dlthis->big_e_target)
++              hndl->secn_count += 1;  /* flag for big-endian */
++#endif
++      if (dlthis->dload_errcount)
++              return;         /* abandon if errors detected */
++       /* Locate the symbol that names the header for the CCS debug list
++       of modules. If not found, we just don't generate the debug record.
++       If found, we create our modules list.  We make sure to create the
++       LOADER_DLLVIEW_ROOT even if there is no relocation info to record,
++       just to try to put both symbols in the same symbol table and
++       module.*/
++      debug_mirror_sym = dlthis->mysym->Find_Matching_Symbol(dlthis->mysym,
++                                              LOADER_DLLVIEW_ROOT);
++      if (!debug_mirror_sym) {
++              struct dynload_symbol *dlmodsym;
++              struct dbg_mirror_root *mlst;
++
++              /* our root symbol is not yet present;
++                 check if we have DLModules defined */
++              dlmodsym = dlthis->mysym->Find_Matching_Symbol(dlthis->mysym,
++                                                      LINKER_MODULES_HEADER);
++              if (!dlmodsym)
++                      return; /* no DLModules list so no debug info */
++              /* if we have DLModules defined, construct our header */
++              mlst = (struct dbg_mirror_root *)
++                      dlthis->mysym->Allocate(dlthis->mysym,
++                      sizeof(struct dbg_mirror_root));
++              if (!mlst) {
++                      DL_ERROR(E_ALLOC, sizeof(struct dbg_mirror_root));
++                      return;
++              }
++              mlst->hnext = NULL;
++              mlst->changes = 0;
++              mlst->refcount = 0;
++              mlst->dbthis = TDATA_TO_TADDR(dlmodsym->value);
++              /* add our root symbol */
++              debug_mirror_sym = dlthis->mysym->Add_To_Symbol_Table
++                      (dlthis->mysym, LOADER_DLLVIEW_ROOT,
++                      (unsigned)dlthis->myhandle);
++              if (!debug_mirror_sym) {
++                      /* failed, recover memory */
++                      dlthis->mysym->Deallocate(dlthis->mysym, mlst);
++                      return;
++              }
++              debug_mirror_sym->value = (u32)mlst;
++      }
++       /* First create the DLLview record and stuff it into the buffer.
++       Then write it to the DSP.  Record pertinent locations in our hndl,
++        and add it to the per-processor list of handles with debug info.*/
++#ifndef DEBUG_HEADER_IN_LOADER
++      mlist = (struct dbg_mirror_root *)debug_mirror_sym->value;
++      if (!mlist)
++              return;
++#else
++      mlist = (struct dbg_mirror_root *)&debug_list_header;
++#endif
++      hndl->dm.hroot = mlist; /* set pointer to root into our handle */
++      if (!dlthis->allocated_secn_count)
++              return;         /* no load addresses to be recorded */
++      /* reuse temporary symbol storage */
++      dbmod = (struct dll_module *) dlthis->local_symtab;
++       /* Create the DLLview record in the memory we retain for our handle*/
++      dbmod->num_sects = dlthis->allocated_secn_count;
++      dbmod->timestamp = dlthis->verify.dv_timdat;
++      dbmod->version = INIT_VERSION;
++      dbmod->verification = VERIFICATION;
++      asecs = dlthis->ldr_sections;
++      dbsec = dbmod->sects;
++      for (curr_sect = dlthis->allocated_secn_count;
++           curr_sect > 0; curr_sect -= 1) {
++              dbsec->sect_load_adr = asecs->load_addr;
++              dbsec->sect_run_adr = asecs->run_addr;
++              dbsec += 1;
++              asecs += 1;
++      }
++      /* now cram in the names */
++      cp = copy_tgt_strings(dbsec, dlthis->str_head,
++                            dlthis->debug_string_size);
++
++      /* round off the size of the debug record, and remember same */
++      hndl->dm.dbsiz = HOST_TO_TDATA_ROUND(cp - (char *)dbmod);
++      *cp = 0;                /* strictly to make our test harness happy */
++      dllview_info = DLLVIEW_INFO_INIT;
++      dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
++      /* Initialize memory context to default heap */
++      dllview_info.context = 0;
++      hndl->dm.context = 0;
++      /* fill in next pointer and size */
++      if (mlist->hnext) {
++              dbmod->next_module = TADDR_TO_TDATA(mlist->hnext->dm.dbthis);
++              dbmod->next_module_size = mlist->hnext->dm.dbsiz;
++      } else {
++              dbmod->next_module_size = 0;
++              dbmod->next_module = 0;
++      }
++      /* allocate memory for on-DSP DLLview debug record */
++      if (!dlthis->myalloc)
++              return;
++      if (!dlthis->myalloc->Allocate(dlthis->myalloc, &dllview_info,
++                   HOST_TO_TADDR(sizeof(u32)))) {
++              return;
++      }
++      /* Store load address of .dllview section */
++      hndl->dm.dbthis = dllview_info.load_addr;
++      /* Store memory context (segid) in which .dllview section
++       * was  allocated */
++      hndl->dm.context = dllview_info.context;
++      mlist->refcount += 1;
++      /* swap bytes in the entire debug record, but not the string table */
++      if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
++              swap_words(dbmod, (char *)dbsec - (char *)dbmod,
++                         DLL_MODULE_BITMAP);
++      }
++       /* Update the DLLview list on the DSP write new record */
++      if (!dlthis->myio->writemem(dlthis->myio, dbmod,
++              dllview_info.load_addr, &dllview_info,
++              TADDR_TO_HOST(dllview_info.size))) {
++              return;
++      }
++      /* write new header */
++      mhdr.first_module_size = hndl->dm.dbsiz;
++      mhdr.first_module = TADDR_TO_TDATA(dllview_info.load_addr);
++      /* swap bytes in the module header, if needed */
++      if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
++              swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
++                         MODULES_HEADER_BITMAP);
++      }
++      dllview_info = DLLVIEW_INFO_INIT;
++      if (!dlthis->myio->writemem(dlthis->myio, &mhdr, mlist->dbthis,
++                      &dllview_info, sizeof(struct modules_header) -
++                                     sizeof(u16))) {
++              return;
++      }
++       /* Add the module handle to this processor's list
++              of handles with debug info */
++      hndl->dm.hnext = mlist->hnext;
++      if (hndl->dm.hnext)
++              hndl->dm.hnext->dm.hprev = hndl;
++      hndl->dm.hprev = (struct my_handle *) mlist;
++      mlist->hnext = hndl;    /* insert after root*/
++}                             /* init_module_handle */
++
++/*************************************************************************
++ * Procedure Dynamic_Unload_Module
++ *
++ * Parameters:
++ *    mhandle A module handle from Dynamic_Load_Module
++ *    syms    Host-side symbol table and malloc/free functions
++ *    alloc   Target-side memory allocation
++ *
++ * Effect:
++ *    The module specified by mhandle is unloaded.  Unloading causes all
++ * target memory to be deallocated, all symbols defined by the module to
++ * be purged, and any host-side storage used by the dynamic loader for
++ * this module to be released.
++ *
++ * Returns:
++ *    Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report().
++ ************************************************************************/
++int Dynamic_Unload_Module(DLOAD_mhandle mhandle,
++              struct Dynamic_Loader_Sym *syms,
++              struct Dynamic_Loader_Allocate *alloc,
++              struct Dynamic_Loader_Initialize *init)
++{
++      s16 curr_sect;
++      struct LDR_SECTION_INFO *asecs;
++      struct my_handle *hndl;
++      struct dbg_mirror_root *root;
++      unsigned errcount = 0;
++      struct LDR_SECTION_INFO dllview_info = DLLVIEW_INFO_INIT;
++      struct modules_header mhdr;
++
++      hndl = (struct my_handle *)mhandle;
++      if (!hndl)
++              return 0;       /* if handle is null, nothing to do */
++       /* Clear out the module symbols
++       * Note that if this is the module that defined MODULES_HEADER
++        (the head of the target debug list)
++       * then this operation will blow away that symbol.
++       It will therefore be impossible for subsequent
++       * operations to add entries to this un-referenceable list.*/
++      if (!syms)
++              return 1;
++      syms->Purge_Symbol_Table(syms, (unsigned) hndl);
++       /* Deallocate target memory for sections */
++      asecs = hndl->secns;
++      if (alloc)
++              for (curr_sect = (hndl->secn_count >> 1); curr_sect > 0;
++                   curr_sect -= 1) {
++                      asecs->name = NULL;
++                      alloc->Deallocate(alloc, asecs++);
++              }
++      root = hndl->dm.hroot;
++      if (!root) {
++              /* there is a debug list containing this module */
++              goto func_end;
++      }
++      if (!hndl->dm.dbthis) { /* target-side dllview record exists */
++              goto loop_end;
++      }
++      /* Retrieve memory context in which .dllview was allocated */
++      dllview_info.context = hndl->dm.context;
++      if (hndl->dm.hprev == hndl)
++              goto exitunltgt;
++
++      /* target-side dllview record is in list */
++      /* dequeue this record from our GPP-side mirror list */
++      hndl->dm.hprev->dm.hnext = hndl->dm.hnext;
++      if (hndl->dm.hnext)
++              hndl->dm.hnext->dm.hprev = hndl->dm.hprev;
++       /* Update next_module of previous entry in target list
++       * We are using mhdr here as a surrogate for either a
++       struct modules_header or a dll_module   */
++      if (hndl->dm.hnext) {
++              mhdr.first_module = TADDR_TO_TDATA(hndl->dm.hnext->dm.dbthis);
++              mhdr.first_module_size = hndl->dm.hnext->dm.dbsiz;
++      } else {
++              mhdr.first_module = 0;
++              mhdr.first_module_size = 0;
++      }
++      if (!init)
++              goto exitunltgt;
++
++      if (!init->connect(init)) {
++              dload_syms_error(syms, E_ICONNECT);
++              errcount += 1;
++              goto exitunltgt;
++      }
++      /* swap bytes in the module header, if needed */
++      if (TARGET_ENDIANNESS_DIFFERS(hndl->secn_count & 0x1)) {
++              swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
++                         MODULES_HEADER_BITMAP);
++      }
++      if (!init->writemem(init, &mhdr, hndl->dm.hprev->dm.dbthis,
++                          &dllview_info, sizeof(struct modules_header) -
++                          sizeof(mhdr.update_flag))) {
++              dload_syms_error(syms, E_DLVWRITE);
++              errcount += 1;
++      }
++      /* update change counter */
++      root->changes += 1;
++      if (!init->writemem(init, &(root->changes),
++                              root->dbthis + HOST_TO_TADDR
++                                    (sizeof(mhdr.first_module) +
++                                    sizeof(mhdr.first_module_size)),
++                                    &dllview_info,
++                                    sizeof(mhdr.update_flag))) {
++              dload_syms_error(syms, E_DLVWRITE);
++              errcount += 1;
++      }
++      init->release(init);
++exitunltgt:
++      /* release target storage */
++      dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
++      dllview_info.load_addr = hndl->dm.dbthis;
++      if (alloc)
++              alloc->Deallocate(alloc, &dllview_info);
++      root->refcount -= 1;
++      /* target-side dllview record exists */
++loop_end:
++#ifndef DEBUG_HEADER_IN_LOADER
++      if (root->refcount <= 0) {
++              /* if all references gone, blow off the header */
++              /* our root symbol may be gone due to the Purge above,
++                 but if not, do not destroy the root */
++              if (syms->Find_Matching_Symbol
++                      (syms, LOADER_DLLVIEW_ROOT) == NULL)
++                      syms->Deallocate(syms, root);
++      }
++#endif
++func_end:
++      /* there is a debug list containing this module */
++      syms->Deallocate(syms, mhandle);        /* release our storage */
++      return errcount;
++}                             /* Dynamic_Unload_Module */
++
++#if BITS_PER_AU > BITS_PER_BYTE
++/*************************************************************************
++ * Procedure unpack_name
++ *
++ * Parameters:
++ *    soffset Byte offset into the string table
++ *
++ * Effect:
++ *    Returns a pointer to the string specified by the offset supplied, or
++ * NULL for error.
++ *
++ ************************************************************************/
++static char *unpack_name(struct dload_state *dlthis, u32 soffset)
++{
++      u8 tmp, *src;
++      char *dst;
++
++      if (soffset >= dlthis->dfile_hdr.df_strtab_size) {
++              dload_error(dlthis, "Bad string table offset " FMT_UI32,
++                          soffset);
++              return NULL;
++      }
++      src = (uint_least8_t *)dlthis->str_head +
++          (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
++      dst = dlthis->str_temp;
++      if (soffset & 1)
++              *dst++ = *src++;        /* only 1 character in first word */
++      do {
++              tmp = *src++;
++              *dst = (tmp >> BITS_PER_BYTE);
++              if (!(*dst++))
++                      break;
++      } while ((*dst++ = tmp & BYTE_MASK));
++      dlthis->temp_len = dst - dlthis->str_temp;
++      /* squirrel away length including terminating null */
++      return dlthis->str_temp;
++}                             /* unpack_name */
++#endif
+diff --git a/drivers/dsp/bridge/dynload/dlclasses_hdr.h b/drivers/dsp/bridge/dynload/dlclasses_hdr.h
+new file mode 100644
+index 0000000..04f136e
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/dlclasses_hdr.h
+@@ -0,0 +1,41 @@
++/*
++ * dlclasses_hdr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef _DLCLASSES_HDR_H
++#define _DLCLASSES_HDR_H
++
++/*****************************************************************************
++ *****************************************************************************
++ *
++ *                          DLCLASSES_HDR.H
++ *
++ * Sample classes in support of the dynamic loader
++ *
++ * These are just concrete derivations of the virtual ones in dynamic_loader.h
++ * with a few additional interfaces for init, etc.
++ *****************************************************************************
++ *****************************************************************************/
++
++#include <dspbridge/dynamic_loader.h>
++
++#include "DLstream.h"
++#include "DLsymtab.h"
++#include "DLalloc.h"
++#include "DLinit.h"
++
++#endif                                /* _DLCLASSES_HDR_H */
+diff --git a/drivers/dsp/bridge/dynload/dload_internal.h b/drivers/dsp/bridge/dynload/dload_internal.h
+new file mode 100644
+index 0000000..78f5058
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/dload_internal.h
+@@ -0,0 +1,237 @@
++/*
++ * dload_internal.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef __DLOAD_INTERNAL__
++#define __DLOAD_INTERNAL__
++
++#include <linux/types.h>
++
++/*
++ * Internal state definitions for the dynamic loader
++ */
++
++#define TRUE 1
++#define FALSE 0
++typedef int boolean;
++
++
++/* type used for relocation intermediate results */
++typedef s32 RVALUE;
++
++/* unsigned version of same; must have at least as many bits */
++typedef u32 URVALUE;
++
++/*
++ * Dynamic loader configuration constants
++ */
++/* error issued if input has more sections than this limit */
++#define REASONABLE_SECTION_LIMIT 100
++
++/* (Addressable unit) value used to clear BSS section */
++#define dload_fill_bss 0
++
++/*
++ * Reorder maps explained (?)
++ *
++ * The doff file format defines a 32-bit pattern used to determine the
++ * byte order of an image being read.  That value is
++ * BYTE_RESHUFFLE_VALUE == 0x00010203
++ * For purposes of the reorder routine, we would rather have the all-is-OK
++ * for 32-bits pattern be 0x03020100.  This first macro makes the
++ * translation from doff file header value to MAP value: */
++#define REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
++/* This translation is made in dload_headers.  Thereafter, the all-is-OK
++ * value for the maps stored in dlthis is REORDER_MAP(BYTE_RESHUFFLE_VALUE).
++ * But sadly, not all bits of the doff file are 32-bit integers.
++ * The notable exceptions are strings and image bits.
++ * Strings obey host byte order: */
++#if defined(_BIG_ENDIAN)
++#define HOST_BYTE_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
++#else
++#define HOST_BYTE_ORDER(cookedmap) (cookedmap)
++#endif
++/* Target bits consist of target AUs (could be bytes, or 16-bits,
++ * or 32-bits) stored as an array in host order.  A target order
++ * map is defined by: */
++#if !defined(_BIG_ENDIAN) || TARGET_AU_BITS > 16
++#define TARGET_ORDER(cookedmap) (cookedmap)
++#elif TARGET_AU_BITS > 8
++#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x2020202)
++#else
++#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
++#endif
++
++/* forward declaration for handle returned by dynamic loader */
++struct my_handle;
++
++/*
++ * a list of module handles, which mirrors the debug list on the target
++ */
++struct dbg_mirror_root {
++      /* must be same as dbg_mirror_list; __DLModules address on target */
++      u32 dbthis;
++      struct my_handle *hnext;        /* must be same as dbg_mirror_list */
++      u16 changes;    /* change counter */
++      u16 refcount;   /* number of modules referencing this root */
++} ;
++
++struct dbg_mirror_list {
++      u32 dbthis;
++      struct my_handle *hnext, *hprev;
++      struct dbg_mirror_root *hroot;
++      u16 dbsiz;
++      u32 context;    /* Save context for .dllview memory allocation */
++} ;
++
++#define VARIABLE_SIZE 1
++/*
++ * the structure we actually return as an opaque module handle
++ */
++struct my_handle {
++      struct dbg_mirror_list dm;      /* !!! must be first !!! */
++      /* sections following << 1, LSB is set for big-endian target */
++      u16 secn_count;
++      struct LDR_SECTION_INFO secns[VARIABLE_SIZE];
++} ;
++#define MY_HANDLE_SIZE (sizeof(struct my_handle) -\
++                      sizeof(struct LDR_SECTION_INFO))
++/* real size of my_handle */
++
++/*
++ * reduced symbol structure used for symbols during relocation
++ */
++struct Local_Symbol {
++      s32 value;      /* Relocated symbol value */
++      s32 delta;      /* Original value in input file */
++      s16 secnn;              /* section number */
++      s16 sclass;             /* symbol class */
++} ;
++
++/*
++ * States of the .cinit state machine
++ */
++enum cinit_mode {
++      CI_count = 0,           /* expecting a count */
++      CI_address,             /* expecting an address */
++#if CINIT_ALIGN < CINIT_ADDRESS       /* handle case of partial address field */
++      CI_partaddress,         /* have only part of the address */
++#endif
++      CI_copy,                /* in the middle of copying data */
++      CI_done                 /* end of .cinit table */
++};
++
++/*
++ * The internal state of the dynamic loader, which is passed around as
++ * an object
++ */
++struct dload_state {
++      struct Dynamic_Loader_Stream *strm;     /* The module input stream */
++      struct Dynamic_Loader_Sym *mysym;       /* Symbols for this session */
++      struct Dynamic_Loader_Allocate *myalloc; /* target memory allocator */
++      struct Dynamic_Loader_Initialize *myio; /* target memory initializer */
++      unsigned myoptions;     /* Options parameter Dynamic_Load_Module */
++
++      char *str_head;         /* Pointer to string table */
++#if BITS_PER_AU > BITS_PER_BYTE
++      char *str_temp;         /* Pointer to temporary buffer for strings */
++      /* big enough to hold longest string */
++      unsigned temp_len;      /* length of last temporary string */
++      char *xstrings;         /* Pointer to buffer for expanded */
++      /* strings for sec names */
++#endif
++      /* Total size of strings for DLLView section names */
++      unsigned debug_string_size;
++      /* Pointer to parallel section info for allocated sections only */
++      struct doff_scnhdr_t *sect_hdrs;        /* Pointer to section table */
++      struct LDR_SECTION_INFO *ldr_sections;
++#if TMS32060
++      /* The address of the start of the .bss section */
++      LDR_ADDR bss_run_base;
++#endif
++      struct Local_Symbol *local_symtab;      /* Relocation symbol table */
++
++      /* pointer to DL section info for the section being relocated */
++      struct LDR_SECTION_INFO *image_secn;
++      /* change in run address for current section during relocation */
++      LDR_ADDR delta_runaddr;
++      LDR_ADDR image_offset;  /* offset of current packet in section */
++      enum cinit_mode cinit_state;    /* current state of cload_cinit() */
++      int cinit_count;        /* the current count */
++      LDR_ADDR cinit_addr;    /* the current address */
++      s16 cinit_page; /* the current page */
++      /* Handle to be returned by Dynamic_Load_Module */
++      struct my_handle *myhandle;
++      unsigned dload_errcount;        /* Total # of errors reported so far */
++      /* Number of target sections that require allocation and relocation */
++      unsigned allocated_secn_count;
++#ifndef TARGET_ENDIANNESS
++      boolean big_e_target;   /* Target data in big-endian format */
++#endif
++      /* map for reordering bytes, 0 if not needed */
++      u32 reorder_map;
++      struct doff_filehdr_t dfile_hdr;        /* DOFF file header structure */
++      struct doff_verify_rec_t verify;        /* Verify record */
++
++      int relstkidx;          /* index into relocation value stack */
++      /* relocation value stack used in relexp.c */
++      RVALUE relstk[STATIC_EXPR_STK_SIZE];
++
++} ;
++
++#ifdef TARGET_ENDIANNESS
++#define TARGET_BIG_ENDIAN TARGET_ENDIANNESS
++#else
++#define TARGET_BIG_ENDIAN (dlthis->big_e_target)
++#endif
++
++/*
++ * Exports from cload.c to rest of the world
++ */
++extern void dload_error(struct dload_state *dlthis, const char *errtxt, ...);
++extern void dload_syms_error(struct Dynamic_Loader_Sym *syms,
++                           const char *errtxt, ...);
++extern void dload_headers(struct dload_state *dlthis);
++extern void dload_strings(struct dload_state *dlthis, boolean sec_names_only);
++extern void dload_sections(struct dload_state *dlthis);
++extern void dload_reorder(void *data, int dsiz, u32 map);
++extern u32 dload_checksum(void *data, unsigned siz);
++
++#if HOST_ENDIANNESS
++extern uint32_t dload_reverse_checksum(void *data, unsigned siz);
++#if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
++extern uint32_t dload_reverse_checksum_16(void *data, unsigned siz);
++#endif
++#endif
++
++#define is_data_scn(zzz) (DLOAD_SECTION_TYPE((zzz)->type) != DLOAD_TEXT)
++#define is_data_scn_num(zzz) \
++              (DLOAD_SECT_TYPE(&dlthis->sect_hdrs[(zzz)-1]) != DLOAD_TEXT)
++
++/*
++ * exported by reloc.c
++ */
++extern void dload_relocate(struct dload_state *dlthis, TgtAU_t *data,
++                         struct reloc_record_t *rp);
++
++extern RVALUE dload_unpack(struct dload_state *dlthis, TgtAU_t *data,
++                         int fieldsz, int offset, unsigned sgn);
++
++extern int dload_repack(struct dload_state *dlthis, RVALUE val, TgtAU_t *data,
++                      int fieldsz, int offset, unsigned sgn);
++
++#endif                                /* __DLOAD_INTERNAL__ */
+diff --git a/drivers/dsp/bridge/dynload/doff.h b/drivers/dsp/bridge/dynload/doff.h
+new file mode 100644
+index 0000000..2b8fc37
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/doff.h
+@@ -0,0 +1,347 @@
++/*
++ * doff.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*****************************************************************************/
++/*  DOFF.H - Structures & definitions used for dynamically                   */
++/*           loaded modules file format.  This format is a reformatted       */
++/*           version of COFF.(see coff.h for details)  It optimizes the      */
++/*           layout for the dynamic loader.                                  */
++/*                                                                           */
++/*  .dof files, when viewed as a sequence of 32-bit integers, look the same  */
++/*  on big-endian and little-endian machines.                                */
++/*****************************************************************************/
++#ifndef _DOFF_H
++#define _DOFF_H
++
++#ifndef UINT32_C
++#define UINT32_C(zzz) ((u32)zzz)
++#endif
++
++#define BYTE_RESHUFFLE_VALUE UINT32_C(0x00010203)
++
++/* DOFF file header containing fields categorizing the remainder of the file */
++struct doff_filehdr_t {
++
++      /* string table size, including filename, in bytes   */
++      u32 df_strtab_size;
++
++      /* entry point if one exists */
++      u32 df_entrypt;
++
++      /* identifies byte ordering of file;
++       * always set to BYTE_RESHUFFLE_VALUE  */
++      u32 df_byte_reshuffle;
++
++      /* Size of the string table up to and including the last section name */
++      /* Size includes the name of the COFF file also     */
++      u32 df_scn_name_size;
++
++#ifndef _BIG_ENDIAN
++      /* number of symbols */
++      u16 df_no_syms;
++
++      /* length in bytes of the longest string, including terminating NULL */
++      /* excludes the name of the file     */
++      u16 df_max_str_len;
++
++      /* total number of sections including no-load ones   */
++      u16 df_no_scns;
++
++      /* number of sections containing target code allocated or downloaded */
++      u16 df_target_scns;
++
++      /* unique id for dll file format & version   */
++      u16 df_doff_version;
++
++      /* identifies ISA */
++      u16 df_target_id;
++
++      /* useful file flags */
++      u16 df_flags;
++
++      /* section reference for entry point, N_UNDEF for none,   */
++      /* N_ABS for absolute address */
++      s16 df_entry_secn;
++#else
++      /* length of the longest string, including terminating NULL  */
++      u16 df_max_str_len;
++
++      /* number of symbols */
++      u16 df_no_syms;
++
++      /* number of sections containing target code allocated or downloaded */
++      u16 df_target_scns;
++
++      /* total number of sections including no-load ones */
++      u16 df_no_scns;
++
++      /* identifies ISA */
++      u16 df_target_id;
++
++      /* unique id for dll file format & version */
++      u16 df_doff_version;
++
++      /* section reference for entry point, N_UNDEF for none,  */
++      /* N_ABS for absolute address */
++      s16 df_entry_secn;
++
++      /* useful file flags */
++      u16 df_flags;
++#endif
++      /* checksum for file header record */
++      u32 df_checksum;
++
++} ;
++
++/* flags in the df_flags field */
++#define  DF_LITTLE   0x100
++#define  DF_BIG      0x200
++#define  DF_BYTE_ORDER (DF_LITTLE | DF_BIG)
++
++/* Supported processors */
++#define TMS470_ID   0x97
++#define LEAD_ID     0x98
++#define TMS32060_ID 0x99
++#define LEAD3_ID    0x9c
++
++/* Primary processor for loading */
++#if TMS32060
++#define TARGET_ID   TMS32060_ID
++#endif
++
++/* Verification record containing values used to test integrity of the bits */
++struct doff_verify_rec_t {
++
++      /* time and date stamp */
++      u32 dv_timdat;
++
++      /* checksum for all section records */
++      u32 dv_scn_rec_checksum;
++
++      /* checksum for string table */
++      u32 dv_str_tab_checksum;
++
++      /* checksum for symbol table */
++      u32 dv_sym_tab_checksum;
++
++      /* checksum for verification record */
++      u32 dv_verify_rec_checksum;
++
++} ;
++
++/* String table is an array of null-terminated strings.  The first entry is
++ * the filename, which is added by DLLcreate.  No new structure definitions
++ * are required.
++ */
++
++/* Section Records including information on the corresponding image packets */
++/*
++ *      !!WARNING!!
++ *
++ * This structure is expected to match in form LDR_SECTION_INFO in
++ * dynamic_loader.h
++ */
++
++struct doff_scnhdr_t {
++
++      s32 ds_offset;  /* offset into string table of name    */
++      s32 ds_paddr;   /* RUN address, in target AU           */
++      s32 ds_vaddr;   /* LOAD address, in target AU          */
++      s32 ds_size;    /* section size, in target AU          */
++#ifndef _BIG_ENDIAN
++      u16 ds_page;    /* memory page id                      */
++      u16 ds_flags;   /* section flags                       */
++#else
++      u16 ds_flags;   /* section flags                       */
++      u16 ds_page;    /* memory page id                      */
++#endif
++      u32 ds_first_pkt_offset;
++      /* Absolute byte offset into the file  */
++      /* where the first image record resides */
++
++      s32 ds_nipacks; /* number of image packets             */
++
++};
++
++/* Symbol table entry */
++struct doff_syment_t {
++
++      s32 dn_offset;  /* offset into string table of name    */
++      s32 dn_value;   /* value of symbol                     */
++#ifndef _BIG_ENDIAN
++      s16 dn_scnum;   /* section number                      */
++      s16 dn_sclass;  /* storage class                       */
++#else
++      s16 dn_sclass;  /* storage class                       */
++      s16 dn_scnum;   /* section number, 1-based             */
++#endif
++
++} ;
++
++/* special values for dn_scnum */
++#define  DN_UNDEF  0          /* undefined symbol               */
++#define  DN_ABS    (-1)               /* value of symbol is absolute    */
++/* special values for dn_sclass */
++#define DN_EXT     2
++#define DN_STATLAB 20
++#define DN_EXTLAB  21
++
++/* Default value of image bits in packet */
++/* Configurable by user on the command line */
++#define IMAGE_PACKET_SIZE 1024
++
++/* An image packet contains a chunk of data from a section along with */
++/* information necessary for its processing.                          */
++struct image_packet_t {
++
++      s32 i_num_relocs;       /* number of relocations for   */
++      /* this packet                 */
++
++      s32 i_packet_size;      /* number of bytes in array    */
++      /* "bits" occupied  by         */
++      /* valid data.  Could be       */
++      /* < IMAGE_PACKET_SIZE to      */
++      /* prevent splitting a         */
++      /* relocation across packets.  */
++      /* Last packet of a section    */
++      /* will most likely contain    */
++      /* < IMAGE_PACKET_SIZE bytes   */
++      /* of valid data               */
++
++      s32 i_checksum; /* Checksum for image packet   */
++      /* and the corresponding       */
++      /* relocation records          */
++
++      u8 *i_bits;     /* Actual data in section      */
++
++};
++
++/* The relocation structure definition matches the COFF version.  Offsets  */
++/* however are relative to the image packet base not the section base.     */
++struct reloc_record_t {
++
++      s32 r_vaddr;
++
++      /* expressed in target AUs          */
++
++      union {
++              struct {
++#ifndef _BIG_ENDIAN
++                      u8 _offset;     /* bit offset of rel fld      */
++                      u8 _fieldsz;    /* size of rel fld            */
++                      u8 _wordsz;     /* # bytes containing rel fld */
++                      u8 _dum1;
++                      u16 _dum2;
++                      u16 _type;
++#else
++                      unsigned _dum1:8;
++                      unsigned _wordsz:8;     /* # bytes containing rel fld */
++                      unsigned _fieldsz:8;    /* size of rel fld            */
++                      unsigned _offset:8;     /* bit offset of rel fld      */
++                      u16 _type;
++                      u16 _dum2;
++#endif
++              } _r_field;
++
++              struct {
++                      u32 _spc;       /* image packet relative PC   */
++#ifndef _BIG_ENDIAN
++                      u16 _dum;
++                      u16 _type;      /* relocation type            */
++#else
++                      u16 _type;      /* relocation type            */
++                      u16 _dum;
++#endif
++              } _r_spc;
++
++              struct {
++                      u32 _uval;      /* constant value             */
++#ifndef _BIG_ENDIAN
++                      u16 _dum;
++                      u16 _type;      /* relocation type            */
++#else
++                      u16 _type;      /* relocation type            */
++                      u16 _dum;
++#endif
++              } _r_uval;
++
++              struct {
++                      s32 _symndx;    /* 32-bit sym tbl index       */
++#ifndef _BIG_ENDIAN
++                      u16 _disp;      /* extra addr encode data     */
++                      u16 _type;      /* relocation type            */
++#else
++                      u16 _type;      /* relocation type            */
++                      u16 _disp;      /* extra addr encode data     */
++#endif
++              } _r_sym;
++      } _u_reloc;
++
++} ;
++
++/* abbreviations for convenience */
++#ifndef r_type
++#define r_type      _u_reloc._r_sym._type
++#define r_uval      _u_reloc._r_uval._uval
++#define r_symndx    _u_reloc._r_sym._symndx
++#define r_offset    _u_reloc._r_field._offset
++#define r_fieldsz   _u_reloc._r_field._fieldsz
++#define r_wordsz    _u_reloc._r_field._wordsz
++#define r_disp      _u_reloc._r_sym._disp
++#endif
++
++/*****************************************************************************/
++/*                                                                           */
++/* Important DOFF macros used for file processing                            */
++/*                                                                           */
++/*****************************************************************************/
++
++/* DOFF Versions */
++#define         DOFF0                       0
++
++/* Return the address/size >= to addr that is at a 32-bit boundary           */
++/* This assumes that a byte is 8 bits                                        */
++#define         DOFF_ALIGN(addr)            (((addr) + 3) & ~UINT32_C(3))
++
++/*****************************************************************************/
++/*                                                                           */
++/* The DOFF section header flags field is laid out as follows:               */
++/*                                                                           */
++/*  Bits 0-3 : Section Type                                                  */
++/*  Bit    4 : Set when section requires target memory to be allocated by DL */
++/*  Bit    5 : Set when section requires downloading                         */
++/*  Bits 8-11: Alignment, same as COFF                                       */
++/*                                                                           */
++/*****************************************************************************/
++
++/* Enum for DOFF section types (bits 0-3 of flag): See dynamic_loader.h      */
++
++/* Macros to help processing of sections                                     */
++#define DLOAD_SECT_TYPE(s_hdr)      ((s_hdr)->ds_flags & 0xF)
++
++/* DS_ALLOCATE indicates whether a section needs space on the target         */
++#define DS_ALLOCATE_MASK            0x10
++#define DS_NEEDS_ALLOCATION(s_hdr)  ((s_hdr)->ds_flags & DS_ALLOCATE_MASK)
++
++/* DS_DOWNLOAD indicates that the loader needs to copy bits                  */
++#define DS_DOWNLOAD_MASK            0x20
++#define DS_NEEDS_DOWNLOAD(s_hdr)    ((s_hdr)->ds_flags & DS_DOWNLOAD_MASK)
++
++/* Section alignment requirement in AUs */
++#define DS_ALIGNMENT(ds_flags) (1 << (((ds_flags) >> 8) & 0xF))
++
++#endif                                /* _DOFF_H */
+diff --git a/drivers/dsp/bridge/dynload/getsection.c b/drivers/dsp/bridge/dynload/getsection.c
+new file mode 100644
+index 0000000..78a301a
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/getsection.c
+@@ -0,0 +1,412 @@
++/*
++ * getsection.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#include <dspbridge/getsection.h>
++#include "header.h"
++
++/*
++ * Error strings
++ */
++static const char E_READSTRM[] = { "Error reading %s from input stream" };
++static const char E_SEEK[] = { "Set file position to %d failed" };
++static const char E_ISIZ[] = { "Bad image packet size %d" };
++static const char E_CHECKSUM[] = { "Checksum failed on %s" };
++static const char E_RELOC[] = { "DLOAD_GetSection unable to read"
++      "sections containing relocation entries"};
++#if BITS_PER_AU > BITS_PER_BYTE
++static const char E_ALLOC[] = { "Syms->Allocate( %d ) failed" };
++static const char E_STBL[] = { "Bad string table offset " FMT_UI32 };
++#endif
++
++/*
++ * we use the fact that DOFF section records are shaped just like
++ * LDR_SECTION_INFO to reduce our section storage usage.  These macros
++ * marks the places where that assumption is made
++ */
++#define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct LDR_SECTION_INFO *)(pdoffsec))
++#define LDRSEC_IS_DOFFSEC(ldrsec) ((struct doff_scnhdr_t *)(ldrsec))
++
++/***************************************************************/
++/********************* SUPPORT FUNCTIONS ***********************/
++/***************************************************************/
++
++#if BITS_PER_AU > BITS_PER_BYTE
++/**************************************************************************
++ * Procedure unpack_sec_name
++ *
++ * Parameters:
++ *  dlthis            Handle from DLOAD_module_open for this module
++ *    soffset     Byte offset into the string table
++ *  dst         Place to store the expanded string
++ *
++ * Effect:
++ *    Stores a string from the string table into the destination, expanding
++ * it in the process.  Returns a pointer just past the end of the stored
++ * string on success, or NULL on failure.
++ *
++ *************************************************************************/
++static char *unpack_sec_name(struct dload_state *dlthis,
++                           u32 soffset, char *dst)
++{
++      u8 tmp, *src;
++
++      if (soffset >= dlthis->dfile_hdr.df_scn_name_size) {
++              dload_error(dlthis, E_STBL, soffset);
++              return NULL;
++      }
++      src = (u8 *)dlthis->str_head +
++          (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
++      if (soffset & 1)
++              *dst++ = *src++;        /* only 1 character in first word */
++      do {
++              tmp = *src++;
++              *dst = (tmp >> BITS_PER_BYTE)
++              if (!(*dst++))
++                      break;
++      } while ((*dst++ = tmp & BYTE_MASK));
++
++      return dst;
++}
++
++/**************************************************************************
++ * Procedure expand_sec_names
++ *
++ * Parameters:
++ *  dlthis            Handle from DLOAD_module_open for this module
++ *
++ * Effect:
++ *    Allocates a buffer, unpacks and copies strings from string table into it.
++ * Stores a pointer to the buffer into a state variable.
++ **************************************************************************/
++static void expand_sec_names(struct dload_state *dlthis)
++{
++      char *xstrings, *curr, *next;
++      u32 xsize;
++      u16 sec;
++      struct LDR_SECTION_INFO *shp;
++      /* assume worst-case size requirement */
++      xsize = dlthis->dfile_hdr.df_max_str_len * dlthis->dfile_hdr.df_no_scns;
++      xstrings = (char *)dlthis->mysym->Allocate(dlthis->mysym, xsize);
++      if (xstrings == NULL) {
++              dload_error(dlthis, E_ALLOC, xsize);
++              return;
++      }
++      dlthis->xstrings = xstrings;
++      /* For each sec, copy and expand its name */
++      curr = xstrings;
++      for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
++              shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
++              next = unpack_sec_name(dlthis, *(u32 *) &shp->name, curr);
++              if (next == NULL)
++                      break;  /* error */
++              shp->name = curr;
++              curr = next;
++      }
++}
++
++#endif
++
++/***************************************************************/
++/********************* EXPORTED FUNCTIONS **********************/
++/***************************************************************/
++
++/**************************************************************************
++ * Procedure DLOAD_module_open
++ *
++ * Parameters:
++ *    module  The input stream that supplies the module image
++ *    syms    Host-side malloc/free and error reporting functions.
++ *                    Other methods are unused.
++ *
++ * Effect:
++ *    Reads header information from a dynamic loader module using the
++    specified
++ * stream object, and returns a handle for the module information.  This
++ * handle may be used in subsequent query calls to obtain information
++ * contained in the module.
++ *
++ * Returns:
++ *    NULL if an error is encountered, otherwise a module handle for use
++ * in subsequent operations.
++ **************************************************************************/
++DLOAD_module_info DLOAD_module_open(struct Dynamic_Loader_Stream *module,
++                                  struct Dynamic_Loader_Sym *syms)
++{
++      struct dload_state *dlthis;     /* internal state for this call */
++      unsigned *dp, sz;
++      u32 sec_start;
++#if BITS_PER_AU <= BITS_PER_BYTE
++      u16 sec;
++#endif
++
++      /* Check that mandatory arguments are present */
++      if (!module || !syms) {
++              if (syms != NULL)
++                      dload_syms_error(syms, "Required parameter is NULL");
++
++              return NULL;
++      }
++
++      dlthis = (struct dload_state *)
++               syms->Allocate(syms, sizeof(struct dload_state));
++      if (!dlthis) {
++              /* not enough storage */
++              dload_syms_error(syms, "Can't allocate module info");
++              return NULL;
++      }
++
++      /* clear our internal state */
++      dp = (unsigned *)dlthis;
++      for (sz = sizeof(struct dload_state) / sizeof(unsigned);
++           sz > 0; sz -= 1)
++              *dp++ = 0;
++
++      dlthis->strm = module;
++      dlthis->mysym = syms;
++
++      /* read in the doff image and store in our state variable */
++      dload_headers(dlthis);
++
++      if (!dlthis->dload_errcount)
++              dload_strings(dlthis, true);
++
++      /* skip ahead past the unread portion of the string table */
++      sec_start = sizeof(struct doff_filehdr_t) +
++                  sizeof(struct doff_verify_rec_t) +
++                  BYTE_TO_HOST(DOFF_ALIGN(dlthis->dfile_hdr.df_strtab_size));
++
++      if (dlthis->strm->set_file_posn(dlthis->strm, sec_start) != 0) {
++              dload_error(dlthis, E_SEEK, sec_start);
++              return NULL;
++      }
++
++      if (!dlthis->dload_errcount)
++              dload_sections(dlthis);
++
++      if (dlthis->dload_errcount) {
++              DLOAD_module_close(dlthis);     /* errors, blow off our state */
++              dlthis = NULL;
++              return NULL;
++      }
++#if BITS_PER_AU > BITS_PER_BYTE
++      /* Expand all section names from the string table into the   */
++      /* state variable, and convert section names from a relative */
++      /* string table offset to a pointers to the expanded string. */
++      expand_sec_names(dlthis);
++#else
++      /* Convert section names from a relative string table offset */
++      /* to a pointer into the string table.                       */
++      for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
++              struct LDR_SECTION_INFO *shp =
++                  DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
++              shp->name = dlthis->str_head + *(u32 *)&shp->name;
++      }
++#endif
++
++      return dlthis;
++}
++
++/***************************************************************************
++ * Procedure DLOAD_GetSectionInfo
++ *
++ * Parameters:
++ *  minfo             Handle from DLOAD_module_open for this module
++ *    sectionName     Pointer to the string name of the section desired
++ *    sectionInfo     Address of a section info structure pointer to be
++ *                    initialized
++ *
++ * Effect:
++ *    Finds the specified section in the module information, and initializes
++ * the provided struct LDR_SECTION_INFO pointer.
++ *
++ * Returns:
++ *    true for success, false for section not found
++ **************************************************************************/
++int DLOAD_GetSectionInfo(DLOAD_module_info minfo, const char *sectionName,
++                   const struct LDR_SECTION_INFO **const sectionInfo)
++{
++      struct dload_state *dlthis;
++      struct LDR_SECTION_INFO *shp;
++      u16 sec;
++
++      dlthis = (struct dload_state *)minfo;
++      if (!dlthis)
++              return false;
++
++      for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
++              shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
++              if (strcmp(sectionName, shp->name) == 0) {
++                      *sectionInfo = shp;
++                      return true;
++              }
++      }
++
++      return false;
++}
++
++#define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
++#define REVERSE_REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
++
++/**************************************************************************
++ * Procedure DLOAD_GetSection
++ *
++ * Parameters:
++ *  minfo             Handle from DLOAD_module_open for this module
++ *    sectionInfo     Pointer to a section info structure for the desired
++ *                    section
++ *    sectionData     Buffer to contain the section initialized data
++ *
++ * Effect:
++ *    Copies the initialized data for the specified section into the
++ * supplied buffer.
++ *
++ * Returns:
++ *    true for success, false for section not found
++ **************************************************************************/
++int DLOAD_GetSection(DLOAD_module_info minfo,
++               const struct LDR_SECTION_INFO *sectionInfo, void *sectionData)
++{
++      struct dload_state *dlthis;
++      u32 pos;
++      struct doff_scnhdr_t *sptr = NULL;
++      s32 nip;
++      struct image_packet_t ipacket;
++      s32 ipsize;
++      u32 checks;
++      s8 *dest = (s8 *)sectionData;
++
++      dlthis = (struct dload_state *)minfo;
++      if (!dlthis)
++              return false;
++      sptr = LDRSEC_IS_DOFFSEC(sectionInfo);
++      if (sptr == NULL)
++              return false;
++
++      /* skip ahead to the start of the first packet */
++      pos = BYTE_TO_HOST(DOFF_ALIGN((u32) sptr->ds_first_pkt_offset));
++      if (dlthis->strm->set_file_posn(dlthis->strm, pos) != 0) {
++              dload_error(dlthis, E_SEEK, pos);
++              return false;
++      }
++
++      nip = sptr->ds_nipacks;
++      while ((nip -= 1) >= 0) {       /* for each packet */
++              /* get the fixed header bits */
++              if (dlthis->strm->
++                  read_buffer(dlthis->strm, &ipacket, IPH_SIZE) != IPH_SIZE) {
++                      dload_error(dlthis, E_READSTRM, "image packet");
++                      return false;
++              }
++              /* reorder the header if need be */
++              if (dlthis->reorder_map)
++                      dload_reorder(&ipacket, IPH_SIZE, dlthis->reorder_map);
++
++              /* Now read the packet image bits. Note: round the size up to
++               * the next multiple of 4 bytes; this is what checksum
++               * routines want. */
++              ipsize = BYTE_TO_HOST(DOFF_ALIGN(ipacket.i_packet_size));
++              if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
++                      dload_error(dlthis, E_ISIZ, ipsize);
++                      return false;
++              }
++              if (dlthis->strm->read_buffer
++                  (dlthis->strm, dest, ipsize) != ipsize) {
++                      dload_error(dlthis, E_READSTRM, "image packet");
++                      return false;
++              }
++              /* reorder the bytes if need be */
++#if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
++              if (dlthis->reorder_map)
++                      dload_reorder(dest, ipsize, dlthis->reorder_map);
++
++              checks = dload_checksum(dest, ipsize);
++#else
++              if (dlthis->dfile_hdr.df_byte_reshuffle !=
++                  TARGET_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
++                      /* put image bytes in big-endian order, not PC order */
++                      dload_reorder(dest, ipsize,
++                                    TARGET_ORDER(dlthis->dfile_hdr.
++                                    df_byte_reshuffle));
++              }
++#if TARGET_AU_BITS > 8
++              checks = dload_reverse_checksum_16(dest, ipsize);
++#else
++              checks = dload_reverse_checksum(dest, ipsize);
++#endif
++#endif
++              checks += dload_checksum(&ipacket, IPH_SIZE);
++
++              /* NYI: unable to handle relocation entries here.  Reloc
++               * entries referring to fields that span the packet boundaries
++               * may result in packets of sizes that are not multiple of
++               * 4 bytes. Our checksum implementation works on 32-bit words
++               * only.     */
++              if (ipacket.i_num_relocs != 0) {
++                      dload_error(dlthis, E_RELOC, ipsize);
++                      return false;
++              }
++
++              if (~checks) {
++                      dload_error(dlthis, E_CHECKSUM, "image packet");
++                      return false;
++              }
++
++              /*Advance destination ptr by the size of the just-read packet*/
++              dest += ipsize;
++      }
++
++      return true;
++}
++
++/***************************************************************************
++ * Procedure DLOAD_module_close
++ *
++ * Parameters:
++ *  minfo             Handle from DLOAD_module_open for this module
++ *
++ * Effect:
++ *    Releases any storage associated with the module handle.  On return,
++ * the module handle is invalid.
++ *
++ * Returns:
++ *    Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report(), where syms was
++ * an argument to DLOAD_module_open
++ **************************************************************************/
++void DLOAD_module_close(DLOAD_module_info minfo)
++{
++      struct dload_state *dlthis;
++
++      dlthis = (struct dload_state *)minfo;
++      if (!dlthis)
++              return;
++
++      if (dlthis->str_head)
++              dlthis->mysym->Deallocate(dlthis->mysym, dlthis->str_head);
++
++      if (dlthis->sect_hdrs)
++              dlthis->mysym->Deallocate(dlthis->mysym, dlthis->sect_hdrs);
++
++#if BITS_PER_AU > BITS_PER_BYTE
++      if (dlthis->xstrings)
++              dlthis->mysym->Deallocate(dlthis->mysym, dlthis->xstrings);
++
++#endif
++
++      dlthis->mysym->Deallocate(dlthis->mysym, dlthis);
++}
+diff --git a/drivers/dsp/bridge/dynload/header.h b/drivers/dsp/bridge/dynload/header.h
+new file mode 100644
+index 0000000..0de744b
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/header.h
+@@ -0,0 +1,59 @@
++/*
++ * header.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#define TRUE 1
++#define FALSE 0
++#ifndef NULL
++#define NULL 0
++#endif
++
++#include <linux/string.h>
++#define DL_STRCMP  strcmp
++
++/* maximum parenthesis nesting in relocation stack expressions */
++#define STATIC_EXPR_STK_SIZE 10
++
++#include <linux/types.h>
++typedef unsigned int            uint_least32_t;
++typedef unsigned short int    uint_least16_t;
++
++#include "doff.h"
++#include <dspbridge/dynamic_loader.h>
++#include "params.h"
++#include "dload_internal.h"
++#include "reloc_table.h"
++
++/*
++ * Plausibility limits
++ *
++ * These limits are imposed upon the input DOFF file as a check for validity.
++ * They are hard limits, in that the load will fail if they are exceeded.
++ * The numbers selected are arbitrary, in that the loader implementation does
++ * not require these limits.
++ */
++
++/* maximum number of bytes in string table */
++#define MAX_REASONABLE_STRINGTAB (0x100000)
++/* maximum number of code,data,etc. sections */
++#define MAX_REASONABLE_SECTIONS (200)
++/* maximum number of linker symbols */
++#define MAX_REASONABLE_SYMBOLS (100000)
++
++/* shift count to align F_BIG with DLOAD_LITTLE */
++#define ALIGN_COFF_ENDIANNESS 7
++#define ENDIANNESS_MASK (DF_BYTE_ORDER >> ALIGN_COFF_ENDIANNESS)
+diff --git a/drivers/dsp/bridge/dynload/module_list.h b/drivers/dsp/bridge/dynload/module_list.h
+new file mode 100644
+index 0000000..9c4876a
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/module_list.h
+@@ -0,0 +1,161 @@
++/*
++ * dspbridge/mpu_driver/src/dynload/module_list.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*============================================================================
++ Filename:     module_list.h
++
++ Copyright (C) 2002 Texas Instruments Incorporated
++
++
++ This C header file gives the layout of the data structure created by the
++ dynamic loader to describe the set of modules loaded into the DSP.
++
++ Linked List Structure:
++ ----------------------
++ The data structure defined here is a singly-linked list.  The list
++ represents the set of modules which are currently loaded in the DSP memory.
++ The first entry in the list is a header record which contains a flag
++ representing the state of the list.  The rest of the entries in the list
++ are module records.
++
++ Global symbol  _DLModules designates the first record in the list (i.e. the
++ header record).  This symbol must be defined in any program that wishes to
++ use DLLview plug-in.
++
++ String Representation:
++ ----------------------
++ The string names of the module and its sections are stored in a block of
++ memory which follows the module record itself.  The strings are ordered:
++ module name first, followed by section names in order from the first
++ section to the last.  String names are tightly packed arrays of 8-bit
++ characters (two characters per 16-bit word on the C55x).  Strings are
++ zero-byte-terminated.
++
++ Creating and updating the list:
++-------------------------------
++ Upon loading a new module into the DSP memory the dynamic loader inserts a
++new module record as the first module record in the list.  The fields of
++ this module record are initialized to reflect the properties of the module.
++ The dynamic loader does NOT increment the flag/counter in the list's header
++ record.
++
++ Upon unloading a module from the DSP memory the dynamic loader removes the
++module's record from this list.  The dynamic loader also increments the
++ flag/counter in the list's header record to indicate that the list has been
++ changed.
++
++============================================================================*/
++
++#ifndef _MODULE_LIST_H_
++#define _MODULE_LIST_H_
++
++#include <linux/types.h>
++
++/* Global pointer to the modules_header structure*/
++#define MODULES_HEADER "_DLModules"
++#define MODULES_HEADER_NO_UNDERSCORE "DLModules"
++
++/* Initial version number*/
++#define INIT_VERSION 1
++
++/* Verification number -- to be recorded in each module record */
++#define VERIFICATION 0x79
++
++/* forward declarations */
++struct dll_module;
++struct dll_sect;
++
++/* the first entry in the list is the modules_header record;
++ * its address is contained in the global _DLModules pointer */
++struct modules_header {
++
++      /* Address of the first dll_module record in the list or NULL.
++       Note: for C55x this is a word address (C55x data is word-addressable)*/
++      u32 first_module;
++
++      /* Combined storage size (in target addressable units) of the
++       * dll_module record which follows this header record, or zero
++       * if the list is empty.  This size includes the module's string table.
++       * Note: for C55x the unit is a 16-bit word */
++      u16 first_module_size;
++
++      /* Counter is incremented whenever a module record is removed from
++       * the list */
++      u16 update_flag;
++
++} ;
++
++/* for each 32-bits in above structure, a bitmap, LSB first, whose bits are:
++ * 0 => a 32-bit value, 1 => 2 16-bit values */
++#define MODULES_HEADER_BITMAP 0x2 /* swapping bitmap for type modules_header */
++
++/* information recorded about each section in a module */
++struct dll_sect {
++
++      /* Load-time address of the section.
++       * Note: for C55x this is a byte address for program sections, and
++       * a word address for data sections.  C55x program memory is
++       * byte-addressable, while data memory is word-addressable. */
++      u32 sect_load_adr;
++
++      /* Run-time address of the section.
++       * Note 1: for C55x this is a byte address for program sections, and
++       * a word address for data sections.
++       * Note 2: for C55x two most significant bits of this field indicate
++       * the section type: '00' for a code section, '11' for a data section
++       * (C55 addresses are really only 24-bits wide). */
++      u32 sect_run_adr;
++
++} ;
++
++/* the rest of the entries in the list are module records */
++struct dll_module {
++
++      /* Address of the next dll_module record in the list, or 0 if this is
++       * the last record in the list.
++       * Note: for C55x this is a word address (C55x data is
++       * word-addressable) */
++      u32 next_module;
++
++      /* Combined storage size (in target addressable units) of the
++       * dll_module record which follows this one, or zero if this is the
++       * last record in the list.  This size includes the module's string
++       * table.
++       * Note: for C55x the unit is a 16-bit word. */
++      u16 next_module_size;
++
++      /* version number of the tooling; set to INIT_VERSION for Phase 1 */
++      u16 version;
++
++      /* the verification word; set to VERIFICATION */
++      u16 verification;
++
++      /* Number of sections in the sects array */
++      u16 num_sects;
++
++      /* Module's "unique" id; copy of the timestamp from the host
++       * COFF file */
++      u32 timestamp;
++
++      /* Array of num_sects elements of the module's section records */
++      struct dll_sect sects[1];
++} ;
++
++/* for each 32 bits in above structure, a bitmap, LSB first, whose bits are:
++ * 0 => a 32-bit value, 1 => 2 16-bit values */
++#define DLL_MODULE_BITMAP 0x6 /* swapping bitmap for type dll_module */
++
++#endif                                /* _MODULE_LIST_H_ */
+diff --git a/drivers/dsp/bridge/dynload/params.h b/drivers/dsp/bridge/dynload/params.h
+new file mode 100644
+index 0000000..ade430d
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/params.h
+@@ -0,0 +1,231 @@
++/*
++ * params.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++/******************************************************************************
++ *
++ * This file defines host and target properties for all machines
++ * supported by the dynamic loader.  To be tedious...
++ *
++ *            host == the machine on which the dynamic loader runs
++ *            target == the machine that the dynamic loader is loading
++ *
++ * Host and target may or may not be the same, depending upon the particular
++ * use.
++ *****************************************************************************/
++
++/******************************************************************************
++ *
++ *                                                    Host Properties
++ *
++ *****************************************************************************/
++
++#define BITS_PER_BYTE 8               /* bits in the standard PC/SUN byte */
++#define LOG_BITS_PER_BYTE 3   /* log base 2 of same */
++#define BYTE_MASK ((1U<<BITS_PER_BYTE)-1)
++
++#if defined(__TMS320C55X__) || defined(_TMS320C5XX)
++#define BITS_PER_AU 16
++#define LOG_BITS_PER_AU 4
++ /* use this print string in error messages for uint32_t */
++#define FMT_UI32 "0x%lx"
++#define FMT8_UI32 "%08lx"     /* same but no 0x, fixed width field */
++#else
++#define BITS_PER_AU 8 /* bits in the smallest addressable data storage unit */
++#define LOG_BITS_PER_AU 3  /* log base 2 of the same; useful for shift counts */
++#define FMT_UI32 "0x%x"
++#define FMT8_UI32 "%08x"
++#endif
++
++/* generic fastest method for swapping bytes and shorts */
++#define SWAP32BY16(zz) (((zz) << 16) | ((zz) >> 16))
++#define SWAP16BY8(zz) (((zz) << 8) | ((zz) >> 8))
++
++/* !! don't be tempted to insert type definitions here; use <stdint.h> !! */
++
++/******************************************************************************
++ *
++ *                                                    Target Properties
++ *
++ *****************************************************************************/
++
++
++/*--------------------------------------------------------------------------*/
++/* TMS320C6x Target Specific Parameters (byte-addressable)                  */
++/*--------------------------------------------------------------------------*/
++#if TMS32060
++#define MEMORG          0x0L  /* Size of configured memory  */
++#define MEMSIZE         0x0L  /* (full address space)  */
++
++#define CINIT_ALIGN     8     /* alignment of cinit record in TDATA AUs */
++#define CINIT_COUNT   4       /* width of count field in TDATA AUs */
++#define CINIT_ADDRESS 4       /* width of address field in TDATA AUs */
++#define CINIT_PAGE_BITS       0       /* Number of LSBs of address that
++                               * are page number */
++
++#define LENIENT_SIGNED_RELEXPS 0      /* DOES SIGNED ALLOW MAX UNSIGNED   */
++
++#undef TARGET_ENDIANNESS      /* may be big or little endian */
++
++/* align a target address to a word boundary */
++#define TARGET_WORD_ALIGN(zz) (((zz) + 0x3) & -0x4)
++#endif
++
++
++/*--------------------------------------------------------------------------
++ *
++ *                    DEFAULT SETTINGS and DERIVED PROPERTIES
++ *
++ * This section establishes defaults for values not specified above
++ *--------------------------------------------------------------------------*/
++#ifndef TARGET_AU_BITS
++#define TARGET_AU_BITS 8      /* width of the target addressable unit */
++#define LOG_TARGET_AU_BITS 3  /* log2 of same */
++#endif
++
++#ifndef CINIT_DEFAULT_PAGE
++#define CINIT_DEFAULT_PAGE 0  /* default .cinit page number */
++#endif
++
++#ifndef DATA_RUN2LOAD
++#define DATA_RUN2LOAD(zz) (zz)        /* translate data run address to load address */
++#endif
++
++#ifndef DBG_LIST_PAGE
++#define DBG_LIST_PAGE 0               /* page number for .dllview section */
++#endif
++
++#ifndef TARGET_WORD_ALIGN
++/* align a target address to a word boundary */
++#define TARGET_WORD_ALIGN(zz) (zz)
++#endif
++
++#ifndef TDATA_TO_TADDR
++#define TDATA_TO_TADDR(zz) (zz)       /* target data address to target AU address */
++#define TADDR_TO_TDATA(zz) (zz)       /* target AU address to target data address */
++#define TDATA_AU_BITS TARGET_AU_BITS  /* bits per data AU */
++#define LOG_TDATA_AU_BITS     LOG_TARGET_AU_BITS
++#endif
++
++/*
++ *
++ * Useful properties and conversions derived from the above
++ *
++ */
++
++/*
++ * Conversions between host and target addresses
++ */
++#if LOG_BITS_PER_AU == LOG_TARGET_AU_BITS
++/* translate target addressable unit to host address */
++#define TADDR_TO_HOST(x) (x)
++/* translate host address to target addressable unit */
++#define HOST_TO_TADDR(x) (x)
++#elif LOG_BITS_PER_AU > LOG_TARGET_AU_BITS
++#define TADDR_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
++#define HOST_TO_TADDR(x) ((x) << (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
++#else
++#define TADDR_TO_HOST(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
++#define HOST_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
++#endif
++
++#if LOG_BITS_PER_AU == LOG_TDATA_AU_BITS
++/* translate target addressable unit to host address */
++#define TDATA_TO_HOST(x) (x)
++/* translate host address to target addressable unit */
++#define HOST_TO_TDATA(x) (x)
++/* translate host address to target addressable unit, round up */
++#define HOST_TO_TDATA_ROUND(x) (x)
++/* byte offset to host offset, rounded up for TDATA size */
++#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
++#elif LOG_BITS_PER_AU > LOG_TDATA_AU_BITS
++#define TDATA_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
++#define HOST_TO_TDATA(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
++#define HOST_TO_TDATA_ROUND(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
++#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
++#else
++#define TDATA_TO_HOST(x) ((x) << (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
++#define HOST_TO_TDATA(x) ((x) >> (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
++#define HOST_TO_TDATA_ROUND(x) (((x) +\
++                              (1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))-1) >>\
++                              (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
++#define BYTE_TO_HOST_TDATA_ROUND(x) (BYTE_TO_HOST((x) +\
++      (1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_BYTE))-1) &\
++      -(TDATA_AU_BITS/BITS_PER_AU))
++#endif
++
++/*
++ * Input in DOFF format is always expresed in bytes, regardless of loading host
++ * so we wind up converting from bytes to target and host units even when the
++ * host is not a byte machine.
++ */
++#if LOG_BITS_PER_AU == LOG_BITS_PER_BYTE
++#define BYTE_TO_HOST(x) (x)
++#define BYTE_TO_HOST_ROUND(x) (x)
++#define HOST_TO_BYTE(x) (x)
++#elif LOG_BITS_PER_AU >= LOG_BITS_PER_BYTE
++#define BYTE_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
++#define BYTE_TO_HOST_ROUND(x) ((x + (BITS_PER_AU/BITS_PER_BYTE-1)) >>\
++                            (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
++#define HOST_TO_BYTE(x) ((x) << (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
++#else
++/* lets not try to deal with sub-8-bit byte machines */
++#endif
++
++#if LOG_TARGET_AU_BITS == LOG_BITS_PER_BYTE
++/* translate target addressable unit to byte address */
++#define TADDR_TO_BYTE(x) (x)
++/* translate byte address to target addressable unit */
++#define BYTE_TO_TADDR(x) (x)
++#elif LOG_TARGET_AU_BITS > LOG_BITS_PER_BYTE
++#define TADDR_TO_BYTE(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
++#define BYTE_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
++#else
++/* lets not try to deal with sub-8-bit byte machines */
++#endif
++
++#ifdef _BIG_ENDIAN
++#define HOST_ENDIANNESS 1
++#else
++#define HOST_ENDIANNESS 0
++#endif
++
++#ifdef TARGET_ENDIANNESS
++#define TARGET_ENDIANNESS_DIFFERS(rtend) (HOST_ENDIANNESS^TARGET_ENDIANNESS)
++#elif HOST_ENDIANNESS
++#define TARGET_ENDIANNESS_DIFFERS(rtend) (!(rtend))
++#else
++#define TARGET_ENDIANNESS_DIFFERS(rtend) (rtend)
++#endif
++
++/* the unit in which we process target image data */
++#if TARGET_AU_BITS <= 8
++typedef u8 TgtAU_t;
++#elif TARGET_AU_BITS <= 16
++typedef u16 TgtAU_t;
++#else
++typedef u32 TgtAU_t;
++#endif
++
++/* size of that unit */
++#if TARGET_AU_BITS < BITS_PER_AU
++#define TGTAU_BITS BITS_PER_AU
++#define LOG_TGTAU_BITS LOG_BITS_PER_AU
++#else
++#define TGTAU_BITS TARGET_AU_BITS
++#define LOG_TGTAU_BITS LOG_TARGET_AU_BITS
++#endif
+diff --git a/drivers/dsp/bridge/dynload/reloc.c b/drivers/dsp/bridge/dynload/reloc.c
+new file mode 100644
+index 0000000..54e460e
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/reloc.c
+@@ -0,0 +1,425 @@
++/*
++ * reloc.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include "header.h"
++
++#if TMS32060
++/* the magic symbol for the start of BSS */
++static const char BSSSYMBOL[] = {".bss"};
++#endif
++
++#if TMS32060
++#include "reloc_table_c6000.c"
++#endif
++
++#if TMS32060
++/* From coff.h - ignore these relocation operations */
++#define R_C60ALIGN     0x76       /* C60: Alignment info for compressor   */
++#define R_C60FPHEAD    0x77       /* C60: Explicit assembly directive     */
++#define R_C60NOCMP    0x100       /* C60: Don't compress this code scn    */
++#endif
++
++/**************************************************************************
++ * Procedure dload_unpack
++ *
++ * Parameters:
++ *    data    pointer to storage unit containing lowest host address of
++ *            image data
++ *    fieldsz Size of bit field, 0 < fieldsz <= sizeof(RVALUE)*BITS_PER_AU
++ *    offset  Offset from LSB, 0 <= offset < BITS_PER_AU
++ *    sgn     Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
++ *
++ * Effect:
++ *    Extracts the specified field and returns it.
++ **************************************************************************/
++RVALUE dload_unpack(struct dload_state *dlthis, TgtAU_t *data, int fieldsz,
++                  int offset, unsigned sgn)
++{
++      register RVALUE objval;
++      register int shift, direction;
++      register TgtAU_t *dp = data;
++
++      fieldsz -= 1;   /* avoid nastiness with 32-bit shift of 32-bit value*/
++      /* * collect up enough bits to contain the desired field */
++      if (TARGET_BIG_ENDIAN) {
++              dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
++              direction = -1;
++      } else
++              direction = 1;
++      objval = *dp >> offset;
++      shift = TGTAU_BITS - offset;
++      while (shift <= fieldsz) {
++              dp += direction;
++              objval += (RVALUE)*dp << shift;
++              shift += TGTAU_BITS;
++      }
++
++      /* * sign or zero extend the value appropriately */
++      if (sgn == ROP_UNS)
++              objval &= (2 << fieldsz) - 1;
++      else {
++              shift = sizeof(RVALUE) * BITS_PER_AU-1 - fieldsz;
++              objval = (objval << shift) >> shift;
++      }
++
++      return objval;
++
++} /* dload_unpack */
++
++
++/**************************************************************************
++ * Procedure dload_repack
++ *
++ * Parameters:
++ *    val             Value to insert
++ *    data    Pointer to storage unit containing lowest host address of
++ *            image data
++ *    fieldsz Size of bit field, 0 < fieldsz <= sizeof(RVALUE)*BITS_PER_AU
++ *    offset  Offset from LSB, 0 <= offset < BITS_PER_AU
++ *    sgn     Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
++ *
++ * Effect:
++ *    Stuffs the specified value in the specified field.  Returns 0 for
++ *    success
++ * or 1 if the value will not fit in the specified field according to the
++ * specified signedness rule.
++ **************************************************************************/
++static const unsigned char ovf_limit[] = {1, 2, 2};
++int dload_repack(struct dload_state *dlthis, RVALUE val, TgtAU_t *data,
++               int fieldsz, int offset, unsigned sgn)
++{
++      register URVALUE objval, mask;
++      register int shift, direction;
++      register TgtAU_t *dp = data;
++
++
++      fieldsz -= 1;   /* avoid nastiness with 32-bit shift of 32-bit value */
++      /* clip the bits */
++      mask = ((UINT32_C(2) << fieldsz) - 1);
++      objval = (val & mask);
++      /* * store the bits through the specified mask */
++      if (TARGET_BIG_ENDIAN) {
++              dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
++              direction = -1;
++      } else
++              direction = 1;
++
++      /* insert LSBs */
++      *dp = (*dp & ~(mask << offset)) + (objval << offset);
++      shift = TGTAU_BITS-offset;
++      /* align mask and objval with AU boundary */
++      objval >>= shift;
++      mask >>= shift;
++
++      while (mask) {
++              dp += direction;
++              *dp = (*dp & ~mask) + objval;
++              objval >>= TGTAU_BITS;
++              mask >>= TGTAU_BITS;
++      }
++
++      /*
++       * check for overflow
++       */
++      if (sgn) {
++              unsigned tmp = (val >> fieldsz) + (sgn & 0x1);
++              if (tmp > ovf_limit[sgn-1])
++                      return 1;
++      }
++      return 0;
++
++} /* dload_repack */
++
++/* lookup table for the scaling amount in a C6x instruction */
++#if TMS32060
++#define SCALE_BITS 4          /* there are 4 bits in the scale field */
++#define SCALE_MASK 0x7                /* we really only use the bottom 3 bits */
++static const u8 C60_Scale[SCALE_MASK+1] = {
++      1, 0, 0, 0, 1, 1, 2, 2
++};
++#endif
++
++/**************************************************************************
++ * Procedure dload_relocate
++ *
++ * Parameters:
++ *    data    Pointer to base of image data
++ *    rp              Pointer to relocation operation
++ *
++ * Effect:
++ *    Performs the specified relocation operation
++ **************************************************************************/
++void dload_relocate(struct dload_state *dlthis, TgtAU_t *data,
++                  struct reloc_record_t *rp)
++{
++      RVALUE val = 0;
++      RVALUE reloc_amt = 0;
++      unsigned int fieldsz = 0;
++      unsigned int offset = 0;
++      unsigned int reloc_info = 0;
++      unsigned int reloc_action = 0;
++      register int rx = 0;
++      RVALUE    *stackp = NULL;
++      int top;
++      struct Local_Symbol *svp = NULL;
++#ifdef RFV_SCALE
++      unsigned int scale = 0;
++#endif
++
++      rx = HASH_FUNC(rp->r_type);
++      while (rop_map1[rx] != rp->r_type) {
++              rx = HASH_L(rop_map2[rx]);
++              if (rx < 0) {
++#if TMS32060
++              switch (rp->r_type) {
++              case R_C60ALIGN:
++              case R_C60NOCMP:
++              case R_C60FPHEAD:
++                  /* Ignore these reloc types and return */
++                  break;
++              default:
++                  /* Unknown reloc type, print error and return */
++                  dload_error(dlthis, "Bad coff operator 0x%x", rp->r_type);
++          }
++#else
++          dload_error(dlthis, "Bad coff operator 0x%x", rp->r_type);
++#endif
++          return;
++              }
++      }
++      rx = HASH_I(rop_map2[rx]);
++      if ((rx < (sizeof(rop_action)/sizeof(uint_least16_t)))
++         && (rx < (sizeof(rop_info)/sizeof(uint_least16_t))) && (rx > 0)) {
++              reloc_action = rop_action[rx]; reloc_info = rop_info[rx];
++      } else {
++          dload_error(dlthis, "Buffer Overflow - Array Index Out of Bounds");
++      }
++
++      /* Compute the relocation amount for the referenced symbol, if any */
++      reloc_amt = rp->r_uval;
++      if (RFV_SYM(reloc_info)) {      /* relocation uses a symbol reference */
++              if ((u32)rp->r_symndx < dlthis->dfile_hdr.df_no_syms) {
++                      /* real symbol reference */
++                      svp = &dlthis->local_symtab[rp->r_symndx];
++                      reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
++                                  svp->delta : svp->value;
++              }
++              /* reloc references current section */
++              else if (rp->r_symndx == -1)
++                      reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
++                        dlthis->delta_runaddr : dlthis->image_secn->run_addr;
++      }       /* relocation uses a symbol reference */
++      /* Handle stack adjustment */
++      val = 0;
++      top = RFV_STK(reloc_info);
++      if (top) {
++              top += dlthis->relstkidx - RSTK_UOP;
++              if (top >= STATIC_EXPR_STK_SIZE) {
++                      dload_error(dlthis,
++                      "Expression stack overflow in %s at offset "
++                      FMT_UI32, dlthis->image_secn->name,
++                      rp->r_vaddr + dlthis->image_offset);
++                      return;
++              }
++              val = dlthis->relstk[dlthis->relstkidx];
++              dlthis->relstkidx = top;
++              stackp = &dlthis->relstk[top];
++      }
++      /* Derive field position and size, if we need them */
++      if (reloc_info & ROP_RW) {      /* read or write action in our future */
++              fieldsz = RFV_WIDTH(reloc_action);
++              if (fieldsz) {  /* field info from table */
++                      offset = RFV_POSN(reloc_action);
++                      if (TARGET_BIG_ENDIAN)
++                              /* make sure r_vaddr is the lowest target
++                               * address containing bits */
++                              rp->r_vaddr += RFV_BIGOFF(reloc_info);
++              } else {        /* field info from relocation op */
++                      fieldsz = rp->r_fieldsz; offset = rp->r_offset;
++                      if (TARGET_BIG_ENDIAN)
++                              /* make sure r_vaddr is the lowest target
++                                 address containing bits */
++                              rp->r_vaddr += (rp->r_wordsz - offset - fieldsz)
++                                              >> LOG_TARGET_AU_BITS;
++              }
++              data = (TgtAU_t *)((char *)data + TADDR_TO_HOST(rp->r_vaddr));
++              /* compute lowest host location of referenced data */
++#if BITS_PER_AU > TARGET_AU_BITS
++              /* conversion from target address to host address may lose
++                 address bits; add loss to offset */
++              if (TARGET_BIG_ENDIAN) {
++                      offset += -((rp->r_vaddr << LOG_TARGET_AU_BITS) +
++                                offset + fieldsz) &
++                                (BITS_PER_AU-TARGET_AU_BITS);
++              } else {
++                      offset += (rp->r_vaddr << LOG_TARGET_AU_BITS) &
++                                (BITS_PER_AU-1);
++              }
++#endif
++#ifdef RFV_SCALE
++              scale = RFV_SCALE(reloc_info);
++#endif
++      }
++      /* read the object value from the current image, if so ordered */
++      if (reloc_info & ROP_R) {    /* relocation reads current image value */
++              val = dload_unpack(dlthis, data, fieldsz, offset,
++                    RFV_SIGN(reloc_info));
++#ifdef RFV_SCALE
++              val <<= scale;
++#endif
++      }
++      /* perform the necessary arithmetic */
++      switch (RFV_ACTION(reloc_action)) {     /* relocation actions */
++      case RACT_VAL:
++              break;
++      case RACT_ASGN:
++              val = reloc_amt;
++              break;
++      case RACT_ADD:
++              val += reloc_amt;
++              break;
++      case RACT_PCR:
++              /*-----------------------------------------------------------
++               * Handle special cases of jumping from absolute sections
++               * (special reloc type) or to absolute destination
++               * (symndx == -1).  In either case, set the appropriate
++               * relocation amount to 0.
++               *-----------------------------------------------------------*/
++              if (rp->r_symndx == -1)
++                      reloc_amt = 0;
++              val += reloc_amt - dlthis->delta_runaddr;
++              break;
++      case RACT_ADDISP:
++              val += rp->r_disp + reloc_amt;
++              break;
++      case RACT_ASGPC:
++              val = dlthis->image_secn->run_addr + reloc_amt;
++              break;
++      case RACT_PLUS:
++              if (stackp != NULL)
++                      val += *stackp;
++              break;
++      case RACT_SUB:
++              if (stackp != NULL)
++                      val = *stackp - val;
++              break;
++      case RACT_NEG:
++              val = -val;
++              break;
++      case RACT_MPY:
++              if (stackp != NULL)
++                      val *= *stackp;
++              break;
++      case RACT_DIV:
++              if (stackp != NULL)
++                      val = *stackp / val;
++              break;
++      case RACT_MOD:
++              if (stackp != NULL)
++                      val = *stackp % val;
++              break;
++      case RACT_SR:
++              if (val >= sizeof(RVALUE) * BITS_PER_AU)
++                      val = 0;
++              else if (stackp != NULL)
++                      val = (URVALUE)*stackp >> val;
++              break;
++      case RACT_ASR:
++              if (val >= sizeof(RVALUE)*BITS_PER_AU)
++                      val = sizeof(RVALUE)*BITS_PER_AU - 1;
++              else if (stackp != NULL)
++                      val = *stackp >> val;
++              break;
++      case RACT_SL:
++              if (val >= sizeof(RVALUE)*BITS_PER_AU)
++                      val = 0;
++              else if (stackp != NULL)
++                      val = *stackp << val;
++              break;
++      case RACT_AND:
++              if (stackp != NULL)
++                      val &= *stackp;
++              break;
++      case RACT_OR:
++              if (stackp != NULL)
++                      val |= *stackp;
++              break;
++      case RACT_XOR:
++              if (stackp != NULL)
++                      val ^= *stackp;
++              break;
++      case RACT_NOT:
++              val = ~val;
++              break;
++#if TMS32060
++      case RACT_C6SECT:
++              /* actually needed address of secn containing symbol */
++              if (svp != NULL) {
++                      if (rp->r_symndx >= 0)
++                              if (svp->secnn > 0)
++                                      reloc_amt = dlthis->ldr_sections
++                                              [svp->secnn-1].run_addr;
++              }
++      /* !!! FALL THRU !!! */
++      case RACT_C6BASE:
++              if (dlthis->bss_run_base == 0) {
++                      struct dynload_symbol *symp;
++                      symp = dlthis->mysym->Find_Matching_Symbol
++                              (dlthis->mysym, BSSSYMBOL);
++                      /* lookup value of global BSS base */
++                      if (symp)
++                              dlthis->bss_run_base = symp->value;
++                      else
++                              dload_error(dlthis,
++                                   "Global BSS base referenced in %s offset"\
++                                   FMT_UI32 " but not defined",
++                                   dlthis->image_secn->name,
++                                   rp->r_vaddr + dlthis->image_offset);
++              }
++              reloc_amt -= dlthis->bss_run_base;
++              /* !!! FALL THRU !!! */
++      case RACT_C6DSPL:
++              /* scale factor determined by 3 LSBs of field */
++              scale = C60_Scale[val & SCALE_MASK];
++              offset += SCALE_BITS;
++              fieldsz -= SCALE_BITS;
++              val >>= SCALE_BITS;     /* ignore the scale field hereafter */
++              val <<= scale;
++              val += reloc_amt;               /* do the usual relocation */
++              if (((1 << scale)-1) & val)
++                      dload_error(dlthis,
++                              "Unaligned reference in %s offset " FMT_UI32,
++                              dlthis->image_secn->name,
++                              rp->r_vaddr + dlthis->image_offset);
++              break;
++#endif
++      }       /* relocation actions */
++      /* * Put back result as required */
++      if (reloc_info & ROP_W) {       /* relocation writes image value */
++#ifdef RFV_SCALE
++              val >>= scale;
++#endif
++              if (dload_repack(dlthis, val, data, fieldsz, offset,
++                 RFV_SIGN(reloc_info))) {
++                      dload_error(dlthis, "Relocation value " FMT_UI32
++                          " overflows %d bits in %s offset " FMT_UI32, val,
++                          fieldsz, dlthis->image_secn->name,
++                          dlthis->image_offset + rp->r_vaddr);
++              }
++      } else if (top)
++              *stackp = val;
++} /* reloc_value */
++
+diff --git a/drivers/dsp/bridge/dynload/reloc_table.h b/drivers/dsp/bridge/dynload/reloc_table.h
+new file mode 100644
+index 0000000..6326146
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/reloc_table.h
+@@ -0,0 +1,102 @@
++/*
++ * reloc_table.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef __RELOC_TABLE_H__
++#define __RELOC_TABLE_H__
++/*
++ * Table of relocation operator properties
++ */
++#include <linux/types.h>
++
++/* How does this relocation operation access the program image? */
++#define ROP_N 0               /* does not access image */
++#define ROP_R 1               /* read from image */
++#define ROP_W 2               /* write to image */
++#define ROP_RW        3               /* read from and write to image */
++
++/* For program image access, what are the overflow rules for the bit field? */
++/* Beware! Procedure repack depends on this encoding */
++#define ROP_ANY       0               /* no overflow ever, just truncate the value */
++#define ROP_SGN       1               /* signed field */
++#define ROP_UNS       2               /* unsigned field */
++#define ROP_MAX 3       /* allow maximum range of either signed or unsigned */
++
++/* How does the relocation operation use the symbol reference */
++#define ROP_IGN       0               /* no symbol is referenced */
++#define ROP_LIT 0             /* use rp->r_uval literal field */
++#define ROP_SYM       1               /* symbol value is used in relocation */
++#define ROP_SYMD 2            /* delta value vs last link is used */
++
++/* How does the reloc op use the stack? */
++#define RSTK_N 0              /* Does not use */
++#define RSTK_POP 1            /* Does a POP */
++#define RSTK_UOP 2            /* Unary op, stack position unaffected */
++#define RSTK_PSH 3            /* Does a push */
++
++/*
++ * Computational actions performed by the dynamic loader
++ */
++enum Dload_Actions {
++      RACT_VAL,    /* don't alter the current val (from stack or mem fetch) */
++      RACT_ASGN,   /* set value to reference amount (from symbol reference) */
++      RACT_ADD,               /* add reference to value */
++      RACT_PCR,               /* add reference minus PC delta to value */
++      RACT_ADDISP,            /* add reference plus r_disp */
++      RACT_ASGPC,     /* set value to section address plus reference */
++
++      RACT_PLUS,              /* stack + */
++      RACT_SUB,               /* stack - */
++      RACT_NEG,               /* stack unary - */
++
++      RACT_MPY,               /* stack * */
++      RACT_DIV,               /* stack / */
++      RACT_MOD,               /* stack % */
++
++      RACT_SR,                /* stack unsigned >> */
++      RACT_ASR,               /* stack signed >> */
++      RACT_SL,                /* stack << */
++      RACT_AND,               /* stack & */
++      RACT_OR,                /* stack | */
++      RACT_XOR,               /* stack ^ */
++      RACT_NOT,               /* stack ~ */
++      RACT_C6SECT,            /* for C60 R_SECT op */
++      RACT_C6BASE,            /* for C60 R_BASE op */
++      RACT_C6DSPL,            /* for C60 scaled 15-bit displacement */
++      RACT_PCR23T             /* for ARM Thumb long branch */
++};
++
++/*
++ * macros used to extract values
++ */
++#define RFV_POSN(aaa) ((aaa) & 0xF)
++#define RFV_WIDTH(aaa) (((aaa) >> 4) & 0x3F)
++#define RFV_ACTION(aaa) ((aaa) >> 10)
++
++#define RFV_SIGN(iii) (((iii) >> 2) & 0x3)
++#define RFV_SYM(iii) (((iii) >> 4) & 0x3)
++#define RFV_STK(iii) (((iii) >> 6) & 0x3)
++#define RFV_ACCS(iii) ((iii) & 0x3)
++
++#if (TMS32060)
++#define RFV_SCALE(iii) ((iii) >> 11)
++#define RFV_BIGOFF(iii) (((iii) >> 8) & 0x7)
++#else
++#define RFV_BIGOFF(iii) ((iii) >> 8)
++#endif
++
++#endif                                /* __RELOC_TABLE_H__ */
+diff --git a/drivers/dsp/bridge/dynload/reloc_table_c6000.c b/drivers/dsp/bridge/dynload/reloc_table_c6000.c
+new file mode 100644
+index 0000000..978834c
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/reloc_table_c6000.c
+@@ -0,0 +1,258 @@
++/*
++ * reloc_table_c6000.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/* Tables generated for c6000 */
++
++#define HASH_FUNC(zz) (((((zz) + 1) * UINT32_C(1845)) >> 11) & 63)
++#define HASH_L(zz) ((zz) >> 8)
++#define HASH_I(zz) ((zz) & 0xFF)
++
++static const u16 rop_map1[] = {
++      0,
++      1,
++      2,
++      20,
++      4,
++      5,
++      6,
++      15,
++      80,
++      81,
++      82,
++      83,
++      84,
++      85,
++      86,
++      87,
++      17,
++      18,
++      19,
++      21,
++      16,
++      16394,
++      16404,
++      65535,
++      65535,
++      65535,
++      65535,
++      65535,
++      65535,
++      32,
++      65535,
++      65535,
++      65535,
++      65535,
++      65535,
++      65535,
++      40,
++      112,
++      113,
++      65535,
++      16384,
++      16385,
++      16386,
++      16387,
++      16388,
++      16389,
++      16390,
++      16391,
++      16392,
++      16393,
++      16395,
++      16396,
++      16397,
++      16398,
++      16399,
++      16400,
++      16401,
++      16402,
++      16403,
++      16405,
++      16406,
++      65535,
++      65535,
++      65535
++};
++
++static const s16 rop_map2[] = {
++      -256,
++      -255,
++      -254,
++      -245,
++      -253,
++      -252,
++      -251,
++      -250,
++      -241,
++      -240,
++      -239,
++      -238,
++      -237,
++      -236,
++      1813,
++      5142,
++      -248,
++      -247,
++      778,
++      -244,
++      -249,
++      -221,
++      -211,
++      -1,
++      -1,
++      -1,
++      -1,
++      -1,
++      -1,
++      -243,
++      -1,
++      -1,
++      -1,
++      -1,
++      -1,
++      -1,
++      -242,
++      -233,
++      -232,
++      -1,
++      -231,
++      -230,
++      -229,
++      -228,
++      -227,
++      -226,
++      -225,
++      -224,
++      -223,
++      5410,
++      -220,
++      -219,
++      -218,
++      -217,
++      -216,
++      -215,
++      -214,
++      -213,
++      5676,
++      -210,
++      -209,
++      -1,
++      -1,
++      -1
++};
++
++static const u16 rop_action[] = {
++      2560,
++      2304,
++      2304,
++      2432,
++      2432,
++      2560,
++      2176,
++      2304,
++      2560,
++      3200,
++      3328,
++      3584,
++      3456,
++      2304,
++      4208,
++      20788,
++      21812,
++      3415,
++      3245,
++      2311,
++      4359,
++      19764,
++      2311,
++      3191,
++      3280,
++      6656,
++      7680,
++      8704,
++      9728,
++      10752,
++      11776,
++      12800,
++      13824,
++      14848,
++      15872,
++      16896,
++      17920,
++      18944,
++      0,
++      0,
++      0,
++      0,
++      1536,
++      1536,
++      1536,
++      5632,
++      512,
++      0
++};
++
++static const u16 rop_info[] = {
++      0,
++      35,
++      35,
++      35,
++      35,
++      35,
++      35,
++      35,
++      35,
++      39,
++      39,
++      39,
++      39,
++      35,
++      34,
++      283,
++      299,
++      4135,
++      4391,
++      291,
++      33059,
++      283,
++      295,
++      4647,
++      4135,
++      64,
++      64,
++      128,
++      64,
++      64,
++      64,
++      64,
++      64,
++      64,
++      64,
++      64,
++      64,
++      128,
++      201,
++      197,
++      74,
++      70,
++      208,
++      196,
++      200,
++      192,
++      192,
++      66
++};
+diff --git a/drivers/dsp/bridge/gen/_gt_para.c b/drivers/dsp/bridge/gen/_gt_para.c
+new file mode 100644
+index 0000000..181fe41
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/_gt_para.c
+@@ -0,0 +1,107 @@
++/*
++ * _gt_para.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== _gt_para.c ========
++ *  Description:
++ *      Configuration parameters for GT.  This file is separated from
++ *      gt.c so that GT_assert() can reference the error function without
++ *      forcing the linker to include all the code for GT_set(), GT_init(),
++ *      etc. into a fully bound image.  Thus, GT_assert() can be retained in
++ *      a program for which GT_?trace() has been compiled out.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 vp: Code Review Updates.
++ *! 18-Oct-2002 sb: Ported to Linux platform.
++ *! 03-Jul-2001 rr: Removed kfuncs.h because of build errors.
++ *! 07-Dec-1999 ag: Fxn error now causes a WinCE DebugBreak;
++ *! 30-Aug-1999 ag: Now uses GP_printf for printf and error.
++ *!
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- Function Prototypes */
++static void error(char *msg, ...);
++static s32 GT_nop(void);
++
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++
++struct GT_Config _GT_params = {
++      (Fxn) printk,           /* printf */
++      (Fxn) NULL,             /* procid */
++      (Fxn) GT_nop,           /* taskid */
++      (Fxn) error,            /* error */
++};
++
++/*  ----------------------------------- Globals */
++struct GT_Config *GT = &_GT_params;
++
++/*
++ *  ======== GT_nop ========
++ */
++static s32 GT_nop(void)
++{
++      return 0;
++}
++
++/*
++ * ======== error ========
++ *  purpose:
++ *      Prints error onto the standard output.
++ */
++static void error(char *fmt, ...)
++{
++      s32 arg1, arg2, arg3, arg4, arg5, arg6;
++
++      va_list va;
++
++      va_start(va, fmt);
++
++      arg1 = va_arg(va, s32);
++      arg2 = va_arg(va, s32);
++      arg3 = va_arg(va, s32);
++      arg4 = va_arg(va, s32);
++      arg5 = va_arg(va, s32);
++      arg6 = va_arg(va, s32);
++
++      va_end(va);
++
++      printk("ERROR: ");
++      printk(fmt, arg1, arg2, arg3, arg4, arg5, arg6);
++
++#if defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)
++      if (in_interrupt()) {
++              printk(KERN_INFO "Not stopping after error since ISR/DPC "
++                      "are disabled\n");
++      } else {
++              set_current_state(TASK_INTERRUPTIBLE);
++              flush_signals(current);
++              schedule();
++              flush_signals(current);
++              printk(KERN_INFO "Signaled in error function\n");
++      }
++#endif
++}
+diff --git a/drivers/dsp/bridge/gen/gb.c b/drivers/dsp/bridge/gen/gb.c
+new file mode 100644
+index 0000000..1d21e97
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gb.c
+@@ -0,0 +1,182 @@
++/*
++ * gb.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== gb.c ========
++ *  Description: Generic bitmap operations.
++ *
++ *! Revision History
++ *! ================
++ *! 24-Feb-2003 vp  Code review updates.
++ *! 17-Dec-2002 map Fixed GB_minset(), GB_empty(), and GB_full(),
++ *!                 to ensure only 'len' bits are considered in the map
++ *! 18-Oct-2002 sb  Ported to Linux platform.
++ *! 06-Dec-2001 jeh Fixed bug in GB_minclear().
++ *!
++ */
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <linux/types.h>
++/*  ----------------------------------- This */
++#include <dspbridge/gs.h>
++#include <dspbridge/gb.h>
++
++typedef GB_BitNum GB_WordNum;
++
++struct GB_TMap {
++      GB_BitNum len;
++      GB_WordNum wcnt;
++      u32 *words;
++};
++
++/*
++ *  ======== GB_clear ========
++ *  purpose:
++ *      Clears a bit in the bit map.
++ */
++
++void GB_clear(struct GB_TMap *map, GB_BitNum bitn)
++{
++      u32 mask;
++
++      mask = 1L << (bitn % BITS_PER_LONG);
++      map->words[bitn / BITS_PER_LONG] &= ~mask;
++}
++
++/*
++ *  ======== GB_create ========
++ *  purpose:
++ *      Creates a bit map.
++ */
++
++struct GB_TMap *GB_create(GB_BitNum len)
++{
++      struct GB_TMap *map;
++      GB_WordNum i;
++      map = (struct GB_TMap *)GS_alloc(sizeof(struct GB_TMap));
++      if (map != NULL) {
++              map->len = len;
++              map->wcnt = len / BITS_PER_LONG + 1;
++              map->words = (u32 *)GS_alloc(map->wcnt * sizeof(u32));
++              if (map->words != NULL) {
++                      for (i = 0; i < map->wcnt; i++)
++                              map->words[i] = 0L;
++
++              } else {
++                      GS_frees(map, sizeof(struct GB_TMap));
++                      map = NULL;
++              }
++      }
++
++      return map;
++}
++
++/*
++ *  ======== GB_delete ========
++ *  purpose:
++ *      Frees a bit map.
++ */
++
++void GB_delete(struct GB_TMap *map)
++{
++      GS_frees(map->words, map->wcnt * sizeof(u32));
++      GS_frees(map, sizeof(struct GB_TMap));
++}
++
++/*
++ *  ======== GB_findandset ========
++ *  purpose:
++ *      Finds a free bit and sets it.
++ */
++GB_BitNum GB_findandset(struct GB_TMap *map)
++{
++      GB_BitNum bitn;
++
++      bitn = GB_minclear(map);
++
++      if (bitn != GB_NOBITS)
++              GB_set(map, bitn);
++
++      return bitn;
++}
++
++/*
++ *  ======== GB_minclear ========
++ *  purpose:
++ *      returns the location of the first unset bit in the bit map.
++ */
++GB_BitNum GB_minclear(struct GB_TMap *map)
++{
++      GB_BitNum bit_location = 0;
++      GB_BitNum bitAcc = 0;
++      GB_WordNum i;
++      GB_BitNum bit;
++      u32 *word;
++
++      for (word = map->words, i = 0; i < map->wcnt; word++, i++) {
++              if (~*word) {
++                      for (bit = 0; bit < BITS_PER_LONG; bit++, bitAcc++) {
++                              if (bitAcc == map->len)
++                                      return GB_NOBITS;
++
++                              if (~*word & (1L << bit)) {
++                                      bit_location = i * BITS_PER_LONG + bit;
++                                      return bit_location;
++                              }
++
++                      }
++              } else {
++                      bitAcc += BITS_PER_LONG;
++              }
++      }
++
++      return GB_NOBITS;
++}
++
++/*
++ *  ======== GB_set ========
++ *  purpose:
++ *      Sets a bit in the bit map.
++ */
++
++void GB_set(struct GB_TMap *map, GB_BitNum bitn)
++{
++      u32 mask;
++
++      mask = 1L << (bitn % BITS_PER_LONG);
++      map->words[bitn / BITS_PER_LONG] |= mask;
++}
++
++/*
++ *  ======== GB_test ========
++ *  purpose:
++ *      Returns true if the bit is set in the specified location.
++ */
++
++bool GB_test(struct GB_TMap *map, GB_BitNum bitn)
++{
++      bool state;
++      u32 mask;
++      u32 word;
++
++      mask = 1L << (bitn % BITS_PER_LONG);
++      word = map->words[bitn / BITS_PER_LONG];
++      state = word & mask ? TRUE : FALSE;
++
++      return state;
++}
+diff --git a/drivers/dsp/bridge/gen/gh.c b/drivers/dsp/bridge/gen/gh.c
+new file mode 100644
+index 0000000..a20ae16
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gh.c
+@@ -0,0 +1,191 @@
++/*
++ * gh.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== gh.c ========
++ */
++
++#include <dspbridge/std.h>
++
++#include <dspbridge/host_os.h>
++
++#include <dspbridge/gs.h>
++
++#include <dspbridge/gh.h>
++
++struct Elem {
++      struct Elem *next;
++      u8 data[1];
++};
++
++struct GH_THashTab {
++      u16 maxBucket;
++      u16 valSize;
++      struct Elem **buckets;
++       u16(*hash) (void *, u16);
++       bool(*match) (void *, void *);
++       void(*delete) (void *);
++};
++
++static void Nop(void *p);
++static s32 curInit;
++static void myfree(void *ptr, s32 size);
++
++/*
++ *  ======== GH_create ========
++ */
++
++struct GH_THashTab *GH_create(u16 maxBucket, u16 valSize,
++              u16(*hash)(void *, u16), bool(*match)(void *, void *),
++              void(*delete)(void *))
++{
++      struct GH_THashTab *hashTab;
++      u16 i;
++      hashTab = (struct GH_THashTab *)GS_alloc(sizeof(struct GH_THashTab));
++      if (hashTab == NULL)
++              return NULL;
++      hashTab->maxBucket = maxBucket;
++      hashTab->valSize = valSize;
++      hashTab->hash = hash;
++      hashTab->match = match;
++      hashTab->delete = delete == NULL ? Nop : delete;
++
++      hashTab->buckets = (struct Elem **)
++                         GS_alloc(sizeof(struct Elem *) * maxBucket);
++      if (hashTab->buckets == NULL) {
++              GH_delete(hashTab);
++              return NULL;
++      }
++
++      for (i = 0; i < maxBucket; i++)
++              hashTab->buckets[i] = NULL;
++
++      return hashTab;
++}
++
++/*
++ *  ======== GH_delete ========
++ */
++void GH_delete(struct GH_THashTab *hashTab)
++{
++      struct Elem *elem, *next;
++      u16 i;
++
++      if (hashTab != NULL) {
++              if (hashTab->buckets != NULL) {
++                      for (i = 0; i < hashTab->maxBucket; i++) {
++                              for (elem = hashTab->buckets[i]; elem != NULL;
++                                  elem = next) {
++                                      next = elem->next;
++                                      (*hashTab->delete) (elem->data);
++                                      myfree(elem, sizeof(struct Elem) - 1 +
++                                            hashTab->valSize);
++                              }
++                      }
++
++                      myfree(hashTab->buckets, sizeof(struct Elem *)
++                            * hashTab->maxBucket);
++              }
++
++              myfree(hashTab, sizeof(struct GH_THashTab));
++      }
++}
++
++/*
++ *  ======== GH_exit ========
++ */
++
++void GH_exit(void)
++{
++      if (curInit-- == 1)
++              GS_exit();
++
++}
++
++/*
++ *  ======== GH_find ========
++ */
++
++void *GH_find(struct GH_THashTab *hashTab, void *key)
++{
++      struct Elem *elem;
++
++      elem = hashTab->buckets[(*hashTab->hash)(key, hashTab->maxBucket)];
++
++      for (; elem; elem = elem->next) {
++              if ((*hashTab->match)(key, elem->data))
++                      return elem->data;
++      }
++
++      return NULL;
++}
++
++/*
++ *  ======== GH_init ========
++ */
++
++void GH_init(void)
++{
++      if (curInit++ == 0)
++              GS_init();
++}
++
++/*
++ *  ======== GH_insert ========
++ */
++
++void *GH_insert(struct GH_THashTab *hashTab, void *key, void *value)
++{
++      struct Elem *elem;
++      u16 i;
++      char *src, *dst;
++
++      elem = (struct Elem *)GS_alloc(sizeof(struct Elem) - 1 +
++              hashTab->valSize);
++      if (elem != NULL) {
++
++              dst = (char *)elem->data;
++              src = (char *)value;
++              for (i = 0; i < hashTab->valSize; i++)
++                      *dst++ = *src++;
++
++              i = (*hashTab->hash)(key, hashTab->maxBucket);
++              elem->next = hashTab->buckets[i];
++              hashTab->buckets[i] = elem;
++
++              return elem->data;
++      }
++
++      return NULL;
++}
++
++/*
++ *  ======== Nop ========
++ */
++/* ARGSUSED */
++static void Nop(void *p)
++{
++      p = p;                  /* stifle compiler warning */
++}
++
++/*
++ *  ======== myfree ========
++ */
++static void myfree(void *ptr, s32 size)
++{
++      GS_free(ptr);
++}
+diff --git a/drivers/dsp/bridge/gen/gs.c b/drivers/dsp/bridge/gen/gs.c
+new file mode 100644
+index 0000000..ef5f923
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gs.c
+@@ -0,0 +1,108 @@
++/*
++ * gs.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== gs.c ========
++ *  Description:
++ *      General storage memory allocator services.
++ *
++ *! Revision History
++ *! ================
++ *! 29-Sep-1999 ag:  Un-commented MEM_Init in GS_init().
++ *! 14-May-1997 mg:  Modified to use new GS API for GS_free() and GS_frees().
++ *! 06-Nov-1996 gp:  Re-commented MEM_Init in GS_init(). GS needs GS_Exit().
++ *! 21-Oct-1996 db:  Un-commented MEM_Init in GS_init().
++ *! 21-May-1996 mg:  Created from original stdlib implementation.
++ */
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <linux/types.h>
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/gs.h>
++
++/*  ----------------------------------- Globals */
++static u32 cumsize;
++
++/*
++ *  ======== GS_alloc ========
++ *  purpose:
++ *      Allocates memory of the specified size.
++ */
++void *GS_alloc(u32 size)
++{
++      void *p;
++
++      p = MEM_Calloc(size, MEM_PAGED);
++      if (p == NULL)
++              return NULL;
++      cumsize += size;
++      return p;
++}
++
++/*
++ *  ======== GS_exit ========
++ *  purpose:
++ *      Discontinue the usage of the GS module.
++ */
++void GS_exit(void)
++{
++      MEM_Exit();
++}
++
++/*
++ *  ======== GS_free ========
++ *  purpose:
++ *      Frees the memory.
++ */
++void GS_free(void *ptr)
++{
++      MEM_Free(ptr);
++      /* ack! no size info */
++      /* cumsize -= size; */
++}
++
++/*
++ *  ======== GS_frees ========
++ *  purpose:
++ *      Frees the memory.
++ */
++void GS_frees(void *ptr, u32 size)
++{
++      MEM_Free(ptr);
++      cumsize -= size;
++}
++
++/*
++ *  ======== GS_init ========
++ *  purpose:
++ *      Initializes the GS module.
++ */
++void GS_init(void)
++{
++      static bool curInit;
++
++      if (curInit == false) {
++              curInit = true;
++
++              MEM_Init();
++      }
++}
+diff --git a/drivers/dsp/bridge/gen/gt.c b/drivers/dsp/bridge/gen/gt.c
+new file mode 100644
+index 0000000..452d6e6
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gt.c
+@@ -0,0 +1,348 @@
++/*
++ * gt.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gt.c ========
++ * Description: This module implements the trace mechanism for bridge.
++ *
++ *! Revision History
++ *! ================
++ *! 16-May-1997 dr    Changed GT_Config member names to conform to coding
++ *!                   standards.
++ *! 23-Apr-1997 ge    Check for GT->TIDFXN for NULL before calling it.
++ *! 03-Jan-1997       ge      Changed GT_Config structure member names to eliminate
++ *!                   preprocessor confusion with other macros.
++ */
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/gt.h>
++
++#define GT_WILD       '*'
++
++#define GT_CLEAR      '='
++#define GT_ON         '+'
++#define GT_OFF                '-'
++
++enum GT_State {
++      GT_SEP,
++      GT_FIRST,
++      GT_SECOND,
++      GT_OP,
++      GT_DIGITS
++} ;
++
++#ifdef CONFIG_BRIDGE_DEBUG
++static char *GT_1format = "%s - %d: ";
++static char *GT_2format = "%s - %d(%d): ";
++#endif /* CONFIG_BRIDGE_DEBUG */
++
++static unsigned char *GT_tMask[GT_BOUND];
++
++static bool curInit;
++static char *separator;
++static unsigned char tabMem[GT_BOUND][sizeof(unsigned char) * GT_BOUND];
++
++static void error(char *string);
++static void setMask(s16 index1, s16 index2, char op, unsigned char mask);
++
++/*
++ *  ======== _GT_create ========
++ *  purpose:
++ *      Creates GT mask.
++ */
++void _GT_create(struct GT_Mask *mask, char *modName)
++{
++      mask->modName = modName;
++      mask->flags = &(GT_tMask[modName[0] - 'A'][modName[1] - 'A']);
++}
++
++/*
++ *  ======== GT_init ========
++ *  purpose:
++ *      Initializes GT module.
++ */
++#ifdef GT_init
++#undef GT_init
++#endif
++void GT_init(void)
++{
++      register unsigned char index1;
++      register unsigned char index2;
++
++      if (!curInit) {
++              curInit = true;
++
++              separator = " ,;/";
++
++              for (index1 = 0; index1 < GT_BOUND; index1++) {
++                      GT_tMask[index1] = tabMem[index1];
++                      for (index2 = 0; index2 < GT_BOUND; index2++) {
++                              /* no tracing */
++                              GT_tMask[index1][index2] = 0x00;
++                      }
++              }
++      }
++}
++
++/*
++ *  ======== _GT_set ========
++ *  purpose:
++ *      Sets the trace string format.
++ */
++
++void _GT_set(char *str)
++{
++      enum GT_State state;
++      char *sep;
++      s16 index1 = GT_BOUND;  /* indicates all values */
++      s16 index2 = GT_BOUND;  /* indicates all values */
++      char op = GT_CLEAR;
++      bool maskValid;
++      s16 digit;
++      register unsigned char mask = 0x0;      /* no tracing */
++
++      if (str == NULL)
++              return;
++
++      maskValid = false;
++      state = GT_SEP;
++      while (*str != '\0') {
++              switch ((s32) state) {
++              case (s32) GT_SEP:
++                      maskValid = false;
++                      sep = separator;
++                      while (*sep != '\0') {
++                              if (*str == *sep) {
++                                      str++;
++                                      break;
++                              } else {
++                                      sep++;
++                              }
++                      }
++                      if (*sep == '\0')
++                              state = GT_FIRST;
++
++                      break;
++              case (s32) GT_FIRST:
++                      if (*str == GT_WILD) {
++                              /* indicates all values */
++                              index1 = GT_BOUND;
++                              /* indicates all values */
++                              index2 = GT_BOUND;
++                              state = GT_OP;
++                      } else {
++                              if (*str >= 'a')
++                                      index1 = (s16) (*str - 'a');
++                              else
++                                      index1 = (s16) (*str - 'A');
++                              if ((index1 >= 0) && (index1 < GT_BOUND))
++                                      state = GT_SECOND;
++                              else
++                                      state = GT_SEP;
++                      }
++                      str++;
++                      break;
++              case (s32) GT_SECOND:
++                      if (*str == GT_WILD) {
++                              index2 = GT_BOUND;   /* indicates all values */
++                              state = GT_OP;
++                              str++;
++                      } else {
++                              if (*str >= 'a')
++                                      index2 = (s16) (*str - 'a');
++                              else
++                                      index2 = (s16) (*str - 'A');
++                              if ((index2 >= 0) && (index2 < GT_BOUND)) {
++                                      state = GT_OP;
++                                      str++;
++                              } else {
++                                      state = GT_SEP;
++                              }
++                      }
++                      break;
++              case (s32) GT_OP:
++                      op = *str;
++                      mask = 0x0;     /* no tracing */
++                      switch (op) {
++                      case (s32) GT_CLEAR:
++                              maskValid = true;
++                      case (s32) GT_ON:
++                      case (s32) GT_OFF:
++                              state = GT_DIGITS;
++                              str++;
++                              break;
++                      default:
++                              state = GT_SEP;
++                              break;
++                      }
++                      break;
++              case (s32) GT_DIGITS:
++                      digit = (s16) (*str - '0');
++                      if ((digit >= 0) && (digit <= 7)) {
++                              mask |= (0x01 << digit);
++                              maskValid = true;
++                              str++;
++                      } else {
++                              if (maskValid == true) {
++                                      setMask(index1, index2, op, mask);
++                                      maskValid = false;
++                              }
++                              state = GT_SEP;
++                      }
++                      break;
++              default:
++                      error("illegal trace mask");
++                      break;
++              }
++      }
++
++      if (maskValid)
++              setMask(index1, index2, op, mask);
++}
++
++/*
++ *  ======== _GT_trace ========
++ *  purpose:
++ *      Prints the input string onto standard output
++ */
++
++s32 _GT_trace(struct GT_Mask *mask, char *format, ...)
++{
++      s32 arg1, arg2, arg3, arg4, arg5, arg6;
++      va_list va;
++
++      va_start(va, format);
++
++      arg1 = va_arg(va, s32);
++      arg2 = va_arg(va, s32);
++      arg3 = va_arg(va, s32);
++      arg4 = va_arg(va, s32);
++      arg5 = va_arg(va, s32);
++      arg6 = va_arg(va, s32);
++
++      va_end(va);
++#ifdef DEBUG
++      if (GT->PIDFXN == NULL) {
++              printk(GT_1format, mask->modName, GT->TIDFXN ?
++              (*GT->TIDFXN)() : 0);
++      } else {
++              printk(GT_2format, mask->modName, (*GT->PIDFXN)(),
++              GT->TIDFXN ? (*GT->TIDFXN)() : 0);
++      }
++#endif
++      printk(format, arg1, arg2, arg3, arg4, arg5, arg6);
++
++      return 0;
++}
++
++/*
++ *  ======== error ========
++ *  purpose:
++ *      Prints errors onto the standard output.
++ */
++static void error(char *string)
++{
++      printk("GT: %s", string);
++}
++
++/*
++ *  ======== setmask ========
++ *  purpose:
++ *      Sets mask for the GT module.
++ */
++
++static void setMask(s16 index1, s16 index2, char op, u8 mask)
++{
++      register s16 index;
++
++      if (index1 < GT_BOUND) {
++              if (index2 < GT_BOUND) {
++                      switch (op) {
++                      case (s32) GT_CLEAR:
++                              GT_tMask[index1][index2] = mask;
++                              break;
++                      case (s32) GT_ON:
++                              GT_tMask[index1][index2] |= mask;
++                              break;
++                      case (s32) GT_OFF:
++                              GT_tMask[index1][index2] &= ~mask;
++                              break;
++                      default:
++                              error("illegal trace mask");
++                              break;
++                      }
++              } else {
++                      for (index2--; index2 >= 0; index2--) {
++                              switch (op) {
++                              case (s32) GT_CLEAR:
++                                      GT_tMask[index1][index2] = mask;
++                                      break;
++                              case (s32) GT_ON:
++                                      GT_tMask[index1][index2] |= mask;
++                                      break;
++                              case (s32) GT_OFF:
++                                      GT_tMask[index1][index2] &= ~mask;
++                                      break;
++                              default:
++                                      error("illegal trace mask");
++                                      break;
++                              }
++                      }
++              }
++      } else {
++              for (index1--; index1 >= 0; index1--) {
++                      if (index2 < GT_BOUND) {
++                              switch (op) {
++                              case (s32) GT_CLEAR:
++                                      GT_tMask[index1][index2] = mask;
++                                      break;
++                              case (s32) GT_ON:
++                                      GT_tMask[index1][index2] |= mask;
++                                      break;
++                              case (s32) GT_OFF:
++                                      GT_tMask[index1][index2] &= ~mask;
++                                      break;
++                              default:
++                                      error("illegal trace mask");
++                                      break;
++                              }
++                      } else {
++                              index = GT_BOUND;
++                              for (index--; index >= 0; index--) {
++                                      switch (op) {
++                                      case (s32) GT_CLEAR:
++                                              GT_tMask[index1][index] = mask;
++                                              break;
++                                      case (s32) GT_ON:
++                                              GT_tMask[index1][index] |= mask;
++                                              break;
++                                      case (s32) GT_OFF:
++                                              GT_tMask[index1][index] &=
++                                                  ~mask;
++                                              break;
++                                      default:
++                                              error("illegal trace mask");
++                                              break;
++                                      }
++                              }
++                      }
++              }
++      }
++}
+diff --git a/drivers/dsp/bridge/gen/uuidutil.c b/drivers/dsp/bridge/gen/uuidutil.c
+new file mode 100644
+index 0000000..a45f448
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/uuidutil.c
+@@ -0,0 +1,238 @@
++/*
++ * uuidutil.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== uuidutil.c ========
++ *  Description:
++ *  This file contains the implementation of UUID helper functions.
++ *
++ *! Revision History
++ *! ================
++ *! 23-Feb-2003 vp: Code review updates.
++ *! 18-Oct-2003 vp: Ported to Linux platform.
++ *! 31-Aug-2000 rr: UUID_UuidFromString bug fixed.
++ *! 29-Aug-2000 rr: Modified UUID_UuidFromString.
++ *! 09-Nov-2000 kc: Modified UUID_UuidFromString to simplify implementation.
++ *! 30-Oct-2000 kc: Modified UUID utility module function prefix.
++ *! 10-Aug-2000 kc: Created.
++ *!
++ */
++
++/*  ----------------------------------- Host OS  */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/uuidutil.h>
++
++/*
++ *  ======== UUID_UuidToString ========
++ *  Purpose:
++ *      Converts a struct DSP_UUID to a string.
++ *      Note: snprintf format specifier is:
++ *      %[flags] [width] [.precision] [{h | l | I64 | L}]type
++ */
++void UUID_UuidToString(IN struct DSP_UUID *pUuid, OUT char *pszUuid,
++                     IN s32 size)
++{
++      s32 i;                  /* return result from snprintf. */
++
++      DBC_Require(pUuid && pszUuid);
++
++      i = snprintf(pszUuid, size,
++                   "%.8X_%.4X_%.4X_%.2X%.2X_%.2X%.2X%.2X%.2X%.2X%.2X",
++                   pUuid->ulData1, pUuid->usData2, pUuid->usData3,
++                   pUuid->ucData4, pUuid->ucData5, pUuid->ucData6[0],
++                   pUuid->ucData6[1], pUuid->ucData6[2], pUuid->ucData6[3],
++                   pUuid->ucData6[4], pUuid->ucData6[5]);
++
++      DBC_Ensure(i != -1);
++}
++
++/*
++ *  ======== htoi ========
++ *  Purpose:
++ *      Converts a hex value to a decimal integer.
++ */
++
++static int htoi(char c)
++{
++      switch (c) {
++      case '0':
++              return 0;
++      case '1':
++              return 1;
++      case '2':
++              return 2;
++      case '3':
++              return 3;
++      case '4':
++              return 4;
++      case '5':
++              return 5;
++      case '6':
++              return 6;
++      case '7':
++              return 7;
++      case '8':
++              return 8;
++      case '9':
++              return 9;
++      case 'A':
++              return 10;
++      case 'B':
++              return 11;
++      case 'C':
++              return 12;
++      case 'D':
++              return 13;
++      case 'E':
++              return 14;
++      case 'F':
++              return 15;
++      case 'a':
++              return 10;
++      case 'b':
++              return 11;
++      case 'c':
++              return 12;
++      case 'd':
++              return 13;
++      case 'e':
++              return 14;
++      case 'f':
++              return 15;
++      }
++      return 0;
++}
++
++/*
++ *  ======== UUID_UuidFromString ========
++ *  Purpose:
++ *      Converts a string to a struct DSP_UUID.
++ */
++void UUID_UuidFromString(IN char *pszUuid, OUT struct DSP_UUID *pUuid)
++{
++      char c;
++      s32 i, j;
++      s32 result;
++      char *temp = pszUuid;
++
++      result = 0;
++      for (i = 0; i < 8; i++) {
++              /* Get first character in string */
++              c = *temp;
++
++              /* Increase the results by new value */
++              result *= 16;
++              result += htoi(c);
++
++              /* Go to next character in string */
++              temp++;
++      }
++      pUuid->ulData1 = result;
++
++      /* Step over underscore */
++      temp++;
++
++      result = 0;
++      for (i = 0; i < 4; i++) {
++              /* Get first character in string */
++              c = *temp;
++
++              /* Increase the results by new value */
++              result *= 16;
++              result += htoi(c);
++
++              /* Go to next character in string */
++              temp++;
++      }
++      pUuid->usData2 = (u16)result;
++
++      /* Step over underscore */
++      temp++;
++
++      result = 0;
++      for (i = 0; i < 4; i++) {
++              /* Get first character in string */
++              c = *temp;
++
++              /* Increase the results by new value */
++              result *= 16;
++              result += htoi(c);
++
++              /* Go to next character in string */
++              temp++;
++      }
++      pUuid->usData3 = (u16)result;
++
++      /* Step over underscore */
++      temp++;
++
++      result = 0;
++      for (i = 0; i < 2; i++) {
++              /* Get first character in string */
++              c = *temp;
++
++              /* Increase the results by new value */
++              result *= 16;
++              result += htoi(c);
++
++              /* Go to next character in string */
++              temp++;
++      }
++      pUuid->ucData4 = (u8)result;
++
++      result = 0;
++      for (i = 0; i < 2; i++) {
++              /* Get first character in string */
++              c = *temp;
++
++              /* Increase the results by new value */
++              result *= 16;
++              result += htoi(c);
++
++              /* Go to next character in string */
++              temp++;
++      }
++      pUuid->ucData5 = (u8)result;
++
++      /* Step over underscore */
++      temp++;
++
++      for (j = 0; j < 6; j++) {
++              result = 0;
++              for (i = 0; i < 2; i++) {
++                      /* Get first character in string */
++                      c = *temp;
++
++                      /* Increase the results by new value */
++                      result *= 16;
++                      result += htoi(c);
++
++                      /* Go to next character in string */
++                      temp++;
++              }
++              pUuid->ucData6[j] = (u8)result;
++      }
++}
+diff --git a/drivers/dsp/bridge/hw/EasiGlobal.h b/drivers/dsp/bridge/hw/EasiGlobal.h
+new file mode 100644
+index 0000000..b023826
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/EasiGlobal.h
+@@ -0,0 +1,42 @@
++/*
++ * EasiGlobal.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef __EASIGLOBAL_H
++#define __EASIGLOBAL_H
++#include <linux/types.h>
++
++/*
++ * DEFINE:        READ_ONLY, WRITE_ONLY &  READ_WRITE
++ *
++ * DESCRIPTION: Defines used to describe register types for EASI-checker tests.
++ */
++
++#define READ_ONLY    1
++#define WRITE_ONLY   2
++#define READ_WRITE   3
++
++/*
++ * MACRO:        _DEBUG_LEVEL_1_EASI
++ *
++ * DESCRIPTION:  A MACRO which can be used to indicate that a particular beach
++ *               register access function was called.
++ *
++ * NOTE:         We currently dont use this functionality.
++ */
++#define _DEBUG_LEVEL_1_EASI(easiNum)     ((void)0)
++
++#endif        /* __EASIGLOBAL_H */
++
+diff --git a/drivers/dsp/bridge/hw/GlobalTypes.h b/drivers/dsp/bridge/hw/GlobalTypes.h
+new file mode 100644
+index 0000000..9004a37
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/GlobalTypes.h
+@@ -0,0 +1,325 @@
++/*
++ * GlobalTypes.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== GlobalTypes.h ========
++ *  Description:
++ *      Global HW definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __GLOBALTYPES_H
++#define __GLOBALTYPES_H
++
++/*
++ * Definition: TRUE, FALSE
++ *
++ * DESCRIPTION:  Boolean Definitions
++ */
++#ifndef TRUE
++#define FALSE 0
++#define TRUE  (!(FALSE))
++#endif
++
++/*
++ * Definition: NULL
++ *
++ * DESCRIPTION:  Invalid pointer
++ */
++#ifndef NULL
++#define NULL  (void *)0
++#endif
++
++/*
++ * Definition: RET_CODE_BASE
++ *
++ * DESCRIPTION:  Base value for return code offsets
++ */
++#define RET_CODE_BASE 0
++
++/*
++ * Definition: *BIT_OFFSET
++ *
++ * DESCRIPTION:  offset in bytes from start of 32-bit word.
++ */
++#define LOWER_16BIT_OFFSET      0
++#define UPPER_16BIT_OFFSET      2
++
++#define LOWER_8BIT_OFFSET        0
++#define LOWER_MIDDLE_8BIT_OFFSET    1
++#define UPPER_MIDDLE_8BIT_OFFSET    2
++#define UPPER_8BIT_OFFSET        3
++
++#define LOWER_8BIT_OF16_OFFSET      0
++#define UPPER_8BIT_OF16_OFFSET      1
++
++/*
++ * Definition: *BIT_SHIFT
++ *
++ * DESCRIPTION:  offset in bits from start of 32-bit word.
++ */
++#define LOWER_16BIT_SHIFT       0
++#define UPPER_16BIT_SHIFT       16
++
++#define LOWER_8BIT_SHIFT         0
++#define LOWER_MIDDLE_8BIT_SHIFT    8
++#define UPPER_MIDDLE_8BIT_SHIFT    16
++#define UPPER_8BIT_SHIFT         24
++
++#define LOWER_8BIT_OF16_SHIFT      0
++#define UPPER_8BIT_OF16_SHIFT      8
++
++
++/*
++ * Definition: LOWER_16BIT_MASK
++ *
++ * DESCRIPTION: 16 bit mask used for inclusion of lower 16 bits i.e. mask out
++ *            the upper 16 bits
++ */
++#define LOWER_16BIT_MASK      0x0000FFFF
++
++
++/*
++ * Definition: LOWER_8BIT_MASK
++ *
++ * DESCRIPTION: 8 bit masks used for inclusion of 8 bits i.e. mask out
++ *            the upper 16 bits
++ */
++#define LOWER_8BIT_MASK          0x000000FF
++
++/*
++ * Definition: RETURN_32BITS_FROM_16LOWER_AND_16UPPER(lower16Bits, upper16Bits)
++ *
++ * DESCRIPTION: Returns a 32 bit value given a 16 bit lower value and a 16
++ *            bit upper value
++ */
++#define RETURN_32BITS_FROM_16LOWER_AND_16UPPER(lower16Bits,upper16Bits)\
++    (((((u32)lower16Bits)  & LOWER_16BIT_MASK)) | \
++     (((((u32)upper16Bits) & LOWER_16BIT_MASK) << UPPER_16BIT_SHIFT)))
++
++/*
++ * Definition: RETURN_16BITS_FROM_8LOWER_AND_8UPPER(lower16Bits, upper16Bits)
++ *
++ * DESCRIPTION:  Returns a 16 bit value given a 8 bit lower value and a 8
++ *           bit upper value
++ */
++#define RETURN_16BITS_FROM_8LOWER_AND_8UPPER(lower8Bits,upper8Bits)\
++    (((((u32)lower8Bits)  & LOWER_8BIT_MASK)) | \
++     (((((u32)upper8Bits) & LOWER_8BIT_MASK) << UPPER_8BIT_OF16_SHIFT)))
++
++/*
++ * Definition: RETURN_32BITS_FROM_4_8BIT_VALUES(lower8Bits, lowerMiddle8Bits,
++ *                                    lowerUpper8Bits, upper8Bits)
++ *
++ * DESCRIPTION:  Returns a 32 bit value given four 8 bit values
++ */
++#define RETURN_32BITS_FROM_4_8BIT_VALUES(lower8Bits, lowerMiddle8Bits,\
++      lowerUpper8Bits, upper8Bits)\
++      (((((u32)lower8Bits) & LOWER_8BIT_MASK)) | \
++      (((((u32)lowerMiddle8Bits) & LOWER_8BIT_MASK) <<\
++              LOWER_MIDDLE_8BIT_SHIFT)) | \
++      (((((u32)lowerUpper8Bits) & LOWER_8BIT_MASK) <<\
++              UPPER_MIDDLE_8BIT_SHIFT)) | \
++      (((((u32)upper8Bits) & LOWER_8BIT_MASK) <<\
++              UPPER_8BIT_SHIFT)))
++
++/*
++ * Definition: READ_LOWER_16BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION:  Returns a 16 lower bits of 32bit value
++ */
++#define READ_LOWER_16BITS_OF_32(value32bits)\
++    ((u16)((u32)(value32bits) & LOWER_16BIT_MASK))
++
++/*
++ * Definition: READ_UPPER_16BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION:  Returns a 16 lower bits of 32bit value
++ */
++#define READ_UPPER_16BITS_OF_32(value32bits)\
++      (((u16)((u32)(value32bits) >> UPPER_16BIT_SHIFT)) &\
++      LOWER_16BIT_MASK)
++
++
++/*
++ * Definition: READ_LOWER_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION:  Returns a 8 lower bits of 32bit value
++ */
++#define READ_LOWER_8BITS_OF_32(value32bits)\
++    ((u8)((u32)(value32bits) & LOWER_8BIT_MASK))
++
++/*
++ * Definition: READ_LOWER_MIDDLE_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION:  Returns a 8 lower middle bits of 32bit value
++ */
++#define READ_LOWER_MIDDLE_8BITS_OF_32(value32bits)\
++      (((u8)((u32)(value32bits) >> LOWER_MIDDLE_8BIT_SHIFT)) &\
++      LOWER_8BIT_MASK)
++
++/*
++ * Definition: READ_LOWER_MIDDLE_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION:  Returns a 8 lower middle bits of 32bit value
++ */
++#define READ_UPPER_MIDDLE_8BITS_OF_32(value32bits)\
++      (((u8)((u32)(value32bits) >> LOWER_MIDDLE_8BIT_SHIFT)) &\
++      LOWER_8BIT_MASK)
++
++/*
++ * Definition: READ_UPPER_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION:  Returns a 8 upper bits of 32bit value
++ */
++#define READ_UPPER_8BITS_OF_32(value32bits)\
++    (((u8)((u32)(value32bits) >> UPPER_8BIT_SHIFT)) & LOWER_8BIT_MASK)
++
++
++/*
++ * Definition: READ_LOWER_8BITS_OF_16(value16bits)
++ *
++ * DESCRIPTION:  Returns a 8 lower bits of 16bit value
++ */
++#define READ_LOWER_8BITS_OF_16(value16bits)\
++    ((u8)((u16)(value16bits) & LOWER_8BIT_MASK))
++
++/*
++ * Definition: READ_UPPER_8BITS_OF_16(value32bits)
++ *
++ * DESCRIPTION:  Returns a 8 upper bits of 16bit value
++ */
++#define READ_UPPER_8BITS_OF_16(value16bits)\
++    (((u8)((u32)(value16bits) >> UPPER_8BIT_SHIFT)) & LOWER_8BIT_MASK)
++
++
++
++/* UWORD16:  16 bit tpyes */
++
++
++/* REG_UWORD8, REG_WORD8: 8 bit register types */
++typedef volatile unsigned char  REG_UWORD8;
++typedef volatile signed   char  REG_WORD8;
++
++/* REG_UWORD16, REG_WORD16: 16 bit register types */
++#ifndef OMAPBRIDGE_TYPES
++typedef volatile unsigned short REG_UWORD16;
++#endif
++typedef volatile        short REG_WORD16;
++
++/* REG_UWORD32, REG_WORD32: 32 bit register types */
++typedef volatile unsigned long  REG_UWORD32;
++
++/* FLOAT
++ *
++ * Type to be used for floating point calculation. Note that floating point
++ * calculation is very CPU expensive, and you should only  use if you
++ * absolutely need this. */
++
++
++/* boolean_t:  Boolean Type True, False */
++/* ReturnCode_t:  Return codes to be returned by all library functions */
++typedef enum ReturnCode_label {
++    RET_OK = 0,
++    RET_FAIL = -1,
++    RET_BAD_NULL_PARAM = -2,
++    RET_PARAM_OUT_OF_RANGE = -3,
++    RET_INVALID_ID = -4,
++    RET_EMPTY = -5,
++    RET_FULL = -6,
++    RET_TIMEOUT = -7,
++    RET_INVALID_OPERATION = -8,
++
++    /* Add new error codes at end of above list */
++
++    RET_NUM_RET_CODES     /* this should ALWAYS be LAST entry */
++} ReturnCode_t, *pReturnCode_t;
++
++/* MACRO: RD_MEM_8, WR_MEM_8
++ *
++ * DESCRIPTION:  32 bit memory access macros
++ */
++#define RD_MEM_8(addr)        ((u8)(*((u8 *)(addr))))
++#define WR_MEM_8(addr, data)  (*((u8 *)(addr)) = (u8)(data))
++
++/* MACRO: RD_MEM_8_VOLATILE, WR_MEM_8_VOLATILE
++ *
++ * DESCRIPTION:  8 bit register access macros
++ */
++#define RD_MEM_8_VOLATILE(addr)       ((u8)(*((REG_UWORD8 *)(addr))))
++#define WR_MEM_8_VOLATILE(addr, data) (*((REG_UWORD8 *)(addr)) = (u8)(data))
++
++
++/*
++ * MACRO: RD_MEM_16, WR_MEM_16
++ *
++ * DESCRIPTION:  16 bit memory access macros
++ */
++#define RD_MEM_16(addr)       ((u16)(*((u16 *)(addr))))
++#define WR_MEM_16(addr, data) (*((u16 *)(addr)) = (u16)(data))
++
++/*
++ * MACRO: RD_MEM_16_VOLATILE, WR_MEM_16_VOLATILE
++ *
++ * DESCRIPTION:  16 bit register access macros
++ */
++#define RD_MEM_16_VOLATILE(addr)      ((u16)(*((REG_UWORD16 *)(addr))))
++#define WR_MEM_16_VOLATILE(addr, data)        (*((REG_UWORD16 *)(addr)) =\
++                                      (u16)(data))
++
++/*
++ * MACRO: RD_MEM_32, WR_MEM_32
++ *
++ * DESCRIPTION:  32 bit memory access macros
++ */
++#define RD_MEM_32(addr)       ((u32)(*((u32 *)(addr))))
++#define WR_MEM_32(addr, data) (*((u32 *)(addr)) = (u32)(data))
++
++/*
++ * MACRO: RD_MEM_32_VOLATILE, WR_MEM_32_VOLATILE
++ *
++ * DESCRIPTION:  32 bit register access macros
++ */
++#define RD_MEM_32_VOLATILE(addr)      ((u32)(*((REG_UWORD32 *)(addr))))
++#define WR_MEM_32_VOLATILE(addr, data)        (*((REG_UWORD32 *)(addr)) =\
++                                      (u32)(data))
++
++/* Not sure if this all belongs here */
++
++#define CHECK_RETURN_VALUE(actualValue, expectedValue,  returnCodeIfMismatch,\
++      spyCodeIfMisMatch)
++#define CHECK_RETURN_VALUE_RET(actualValue, expectedValue, returnCodeIfMismatch)
++#define CHECK_RETURN_VALUE_RES(actualValue, expectedValue, spyCodeIfMisMatch)
++#define CHECK_RETURN_VALUE_RET_VOID(actualValue, expectedValue,\
++      spyCodeIfMisMatch)
++
++#define CHECK_INPUT_PARAM(actualValue, invalidValue, returnCodeIfMismatch,\
++      spyCodeIfMisMatch)
++#define CHECK_INPUT_PARAM_NO_SPY(actualValue, invalidValue,\
++      returnCodeIfMismatch)
++#define CHECK_INPUT_RANGE(actualValue, minValidValue, maxValidValue,\
++      returnCodeIfMismatch, spyCodeIfMisMatch)
++#define CHECK_INPUT_RANGE_NO_SPY(actualValue, minValidValue, maxValidValue,\
++      returnCodeIfMismatch)
++#define CHECK_INPUT_RANGE_MIN0(actualValue, maxValidValue,\
++      returnCodeIfMismatch, spyCodeIfMisMatch)
++#define CHECK_INPUT_RANGE_NO_SPY_MIN0(actualValue, maxValidValue,\
++      returnCodeIfMismatch)
++
++#endif        /* __GLOBALTYPES_H */
+diff --git a/drivers/dsp/bridge/hw/IPIAccInt.h b/drivers/dsp/bridge/hw/IPIAccInt.h
+new file mode 100644
+index 0000000..b88a58c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/IPIAccInt.h
+@@ -0,0 +1,41 @@
++/*
++ * IPIAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _IPI_ACC_INT_H
++#define _IPI_ACC_INT_H
++
++/* Bitfield mask and offset declarations */
++#define SYSC_IVA2BOOTMOD_OFFSET                   0x404
++#define SYSC_IVA2BOOTADDR_OFFSET                0x400
++#define SYSC_IVA2BOOTADDR_MASK                 0xfffffc00
++
++
++/* The following represent the enumerated values for each bitfield */
++
++enum IPIIPI_SYSCONFIGAutoIdleE {
++      IPIIPI_SYSCONFIGAutoIdleclkfree = 0x0000,
++      IPIIPI_SYSCONFIGAutoIdleautoclkgate = 0x0001
++} ;
++
++enum IPIIPI_ENTRYElemSizeValueE {
++      IPIIPI_ENTRYElemSizeValueElemSz8b = 0x0000,
++      IPIIPI_ENTRYElemSizeValueElemSz16b = 0x0001,
++      IPIIPI_ENTRYElemSizeValueElemSz32b = 0x0002,
++      IPIIPI_ENTRYElemSizeValueReserved = 0x0003
++} ;
++
++#endif                                /* _IPI_ACC_INT_H */
++/* EOF */
+diff --git a/drivers/dsp/bridge/hw/IVA2RegAcM.h b/drivers/dsp/bridge/hw/IVA2RegAcM.h
+new file mode 100644
+index 0000000..6c1e300
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/IVA2RegAcM.h
+@@ -0,0 +1,28 @@
++/*
++ * IVA1RegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef _IVA2_REG_ACM_H
++#define _IVA2_REG_ACM_H
++
++#include <GlobalTypes.h>
++#include <EasiGlobal.h>
++
++#define SYSC_IVA2BOOTMOD_OFFSET           0x404
++#define SYSC_IVA2BOOTADDR_OFFSET          0x400
++
++#endif
+diff --git a/drivers/dsp/bridge/hw/MLBAccInt.h b/drivers/dsp/bridge/hw/MLBAccInt.h
+new file mode 100644
+index 0000000..7a03c6a
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MLBAccInt.h
+@@ -0,0 +1,132 @@
++/*
++ * MLBAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++#ifndef _MLB_ACC_INT_H
++#define _MLB_ACC_INT_H
++
++/* Mappings of level 1 EASI function numbers to function names */
++
++#define EASIL1_MLBMAILBOX_SYSCONFIGReadRegister32   (MLB_BASE_EASIL1 + 3)
++#define EASIL1_MLBMAILBOX_SYSCONFIGWriteRegister32  (MLB_BASE_EASIL1 + 4)
++#define EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeRead32   (MLB_BASE_EASIL1 + 7)
++#define EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeWrite32  (MLB_BASE_EASIL1 + 17)
++#define EASIL1_MLBMAILBOX_SYSCONFIGSoftResetWrite32 (MLB_BASE_EASIL1 + 29)
++#define EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleRead32 \
++                                              (MLB_BASE_EASIL1 + 33)
++#define EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleWrite32   (MLB_BASE_EASIL1 + 39)
++#define EASIL1_MLBMAILBOX_SYSSTATUSResetDoneRead32  (MLB_BASE_EASIL1 + 44)
++#define EASIL1_MLBMAILBOX_MESSAGE___0_15ReadRegister32 \
++                                              (MLB_BASE_EASIL1 + 50)
++#define EASIL1_MLBMAILBOX_MESSAGE___0_15WriteRegister32  \
++                                              (MLB_BASE_EASIL1 + 51)
++#define EASIL1_MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32  \
++                                              (MLB_BASE_EASIL1 + 56)
++#define EASIL1_MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32 \
++                                              (MLB_BASE_EASIL1 + 57)
++#define EASIL1_MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32  \
++                                              (MLB_BASE_EASIL1 + 60)
++#define EASIL1_MLBMAILBOX_IRQSTATUS___0_3ReadRegister32  \
++                                              (MLB_BASE_EASIL1 + 62)
++#define EASIL1_MLBMAILBOX_IRQSTATUS___0_3WriteRegister32 \
++                                              (MLB_BASE_EASIL1 + 63)
++#define EASIL1_MLBMAILBOX_IRQENABLE___0_3ReadRegister32    \
++                                              (MLB_BASE_EASIL1 + 192)
++#define EASIL1_MLBMAILBOX_IRQENABLE___0_3WriteRegister32   \
++                                              (MLB_BASE_EASIL1 + 193)
++
++/* Register set MAILBOX_MESSAGE___REGSET_0_15 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET    (u32)(0x0040)
++#define MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP   (u32)(0x0004)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_MESSAGE___REGSET_0_15 */
++
++#define MLB_MAILBOX_MESSAGE___0_15_OFFSET   (u32)(0x0)
++
++
++/* Register set MAILBOX_FIFOSTATUS___REGSET_0_15 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET  (u32)(0x0080)
++#define MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP   (u32)(0x0004)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_FIFOSTATUS___REGSET_0_15 */
++
++#define MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET    (u32)(0x0)
++
++
++/* Register set MAILBOX_MSGSTATUS___REGSET_0_15 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_MSGSTATUS___REGSET_0_15_OFFSET  (u32)(0x00c0)
++#define MLB_MAILBOX_MSGSTATUS___REGSET_0_15_STEP    (u32)(0x0004)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_MSGSTATUS___REGSET_0_15 */
++
++#define MLB_MAILBOX_MSGSTATUS___0_15_OFFSET    (u32)(0x0)
++
++
++/* Register set MAILBOX_IRQSTATUS___REGSET_0_3 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET        (u32)(0x0100)
++#define MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP          (u32)(0x0008)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_IRQSTATUS___REGSET_0_3 */
++
++#define MLB_MAILBOX_IRQSTATUS___0_3_OFFSET        (u32)(0x0)
++
++
++/* Register set MAILBOX_IRQENABLE___REGSET_0_3 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET     (u32)(0x0104)
++#define MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP     (u32)(0x0008)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_IRQENABLE___REGSET_0_3 */
++
++#define MLB_MAILBOX_IRQENABLE___0_3_OFFSET          (u32)(0x0)
++
++
++/* Register offset address definitions */
++
++#define MLB_MAILBOX_SYSCONFIG_OFFSET            (u32)(0x10)
++#define MLB_MAILBOX_SYSSTATUS_OFFSET            (u32)(0x14)
++
++
++/* Bitfield mask and offset declarations */
++
++#define MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK        (u32)(0x18)
++#define MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET      (u32)(3)
++#define MLB_MAILBOX_SYSCONFIG_SoftReset_MASK        (u32)(0x2)
++#define MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET      (u32)(1)
++#define MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK          (u32)(0x1)
++#define MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET        (u32)(0)
++#define MLB_MAILBOX_SYSSTATUS_ResetDone_MASK         (u32)(0x1)
++#define MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET         (u32)(0)
++#define MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_MASK   (u32)(0x1)
++#define MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_OFFSET  (u32)(0)
++#define MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_MASK    (u32)(0x7f)
++#define MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_OFFSET    (u32)(0)
++
++#endif /* _MLB_ACC_INT_H */
+diff --git a/drivers/dsp/bridge/hw/MLBRegAcM.h b/drivers/dsp/bridge/hw/MLBRegAcM.h
+new file mode 100644
+index 0000000..747a2e1
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MLBRegAcM.h
+@@ -0,0 +1,200 @@
++/*
++ * MLBRegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _MLB_REG_ACM_H
++#define _MLB_REG_ACM_H
++
++#include <GlobalTypes.h>
++#include <EasiGlobal.h>
++#include "MLBAccInt.h"
++
++#if defined(USE_LEVEL_1_MACROS)
++
++#define MLBMAILBOX_SYSCONFIGReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGReadRegister32),\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+ \
++      MLB_MAILBOX_SYSCONFIG_OFFSET))
++
++
++#define MLBMAILBOX_SYSCONFIGWriteRegister32(baseAddress, value)\
++{\
++    const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGWriteRegister32);\
++    WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSCONFIGSIdleModeRead32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeRead32),\
++      (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++      (MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
++      MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >>\
++      MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET))
++
++
++#define MLBMAILBOX_SYSCONFIGSIdleModeWrite32(baseAddress, value)\
++{\
++    const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress)) +\
++                          offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeWrite32);\
++    data &= ~(MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK);\
++    newValue <<= MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET;\
++    newValue &= MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSCONFIGSoftResetWrite32(baseAddress, value)\
++{\
++    const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++    register u32 data =\
++    RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSoftResetWrite32);\
++    data &= ~(MLB_MAILBOX_SYSCONFIG_SoftReset_MASK);\
++    newValue <<= MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET;\
++    newValue &= MLB_MAILBOX_SYSCONFIG_SoftReset_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSCONFIGAutoIdleRead32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleRead32),\
++      (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++      (MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
++      MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK) >>\
++      MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET))
++
++
++#define MLBMAILBOX_SYSCONFIGAutoIdleWrite32(baseAddress, value)\
++{\
++    const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++    register u32 data =\
++    RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleWrite32);\
++    data &= ~(MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK);\
++    newValue <<= MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET;\
++    newValue &= MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSSTATUSResetDoneRead32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSSTATUSResetDoneRead32),\
++      (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++      (MLB_MAILBOX_SYSSTATUS_OFFSET)))) &\
++      MLB_MAILBOX_SYSSTATUS_ResetDone_MASK) >>\
++      MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET))
++
++
++#define MLBMAILBOX_MESSAGE___0_15ReadRegister32(baseAddress, bank)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_MESSAGE___0_15ReadRegister32),\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++      (MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
++      MLB_MAILBOX_MESSAGE___0_15_OFFSET+(\
++      (bank)*MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP))))
++
++
++#define MLBMAILBOX_MESSAGE___0_15WriteRegister32(baseAddress, bank, value)\
++{\
++    const u32 offset = MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
++    MLB_MAILBOX_MESSAGE___0_15_OFFSET +\
++    ((bank)*MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_MESSAGE___0_15WriteRegister32);\
++    WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32(baseAddress, bank)\
++    (_DEBUG_LEVEL_1_EASI(\
++      EASIL1_MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32),\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++      (MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET +\
++      MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET+\
++      ((bank)*MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP))))
++
++
++#define MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32(baseAddress, bank)\
++    (_DEBUG_LEVEL_1_EASI(\
++      EASIL1_MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32),\
++      (((RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++      (MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET +\
++      MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET+\
++      ((bank)*MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP)))) &\
++      MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_MASK) >>\
++      MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_OFFSET))
++
++
++#define MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32(baseAddress, bank)\
++    (_DEBUG_LEVEL_1_EASI(\
++      EASIL1_MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32),\
++      (((RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++      (MLB_MAILBOX_MSGSTATUS___REGSET_0_15_OFFSET +\
++      MLB_MAILBOX_MSGSTATUS___0_15_OFFSET+\
++      ((bank)*MLB_MAILBOX_MSGSTATUS___REGSET_0_15_STEP)))) &\
++      MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_MASK) >>\
++      MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_OFFSET))
++
++
++#define MLBMAILBOX_IRQSTATUS___0_3ReadRegister32(baseAddress, bank)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQSTATUS___0_3ReadRegister32),\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++      (MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
++      MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+\
++      ((bank)*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP))))
++
++
++#define MLBMAILBOX_IRQSTATUS___0_3WriteRegister32(baseAddress, bank, value)\
++{\
++    const u32 offset = MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
++    MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
++    ((bank)*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQSTATUS___0_3WriteRegister32);\
++    WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_IRQENABLE___0_3ReadRegister32(baseAddress, bank)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQENABLE___0_3ReadRegister32),\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++      (MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
++      MLB_MAILBOX_IRQENABLE___0_3_OFFSET+\
++       ((bank)*MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP))))
++
++
++#define MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, bank, value)\
++{\
++    const u32 offset = MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
++      MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
++      ((bank)*MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQENABLE___0_3WriteRegister32);\
++    WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#endif        /* USE_LEVEL_1_MACROS */
++
++#endif /* _MLB_REG_ACM_H */
+diff --git a/drivers/dsp/bridge/hw/MMUAccInt.h b/drivers/dsp/bridge/hw/MMUAccInt.h
+new file mode 100644
+index 0000000..6ca1573
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MMUAccInt.h
+@@ -0,0 +1,76 @@
++/*
++ * MMUAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _MMU_ACC_INT_H
++#define _MMU_ACC_INT_H
++
++/* Mappings of level 1 EASI function numbers to function names */
++
++#define EASIL1_MMUMMU_SYSCONFIGReadRegister32 (MMU_BASE_EASIL1 + 3)
++#define EASIL1_MMUMMU_SYSCONFIGIdleModeWrite32  (MMU_BASE_EASIL1 + 17)
++#define EASIL1_MMUMMU_SYSCONFIGAutoIdleWrite32    (MMU_BASE_EASIL1 + 39)
++#define EASIL1_MMUMMU_IRQSTATUSWriteRegister32   (MMU_BASE_EASIL1 + 51)
++#define EASIL1_MMUMMU_IRQENABLEReadRegister32 (MMU_BASE_EASIL1 + 102)
++#define EASIL1_MMUMMU_IRQENABLEWriteRegister32 (MMU_BASE_EASIL1 + 103)
++#define EASIL1_MMUMMU_WALKING_STTWLRunningRead32 (MMU_BASE_EASIL1 + 156)
++#define EASIL1_MMUMMU_CNTLTWLEnableRead32 (MMU_BASE_EASIL1 + 174)
++#define EASIL1_MMUMMU_CNTLTWLEnableWrite32   (MMU_BASE_EASIL1 + 180)
++#define EASIL1_MMUMMU_CNTLMMUEnableWrite32     (MMU_BASE_EASIL1 + 190)
++#define EASIL1_MMUMMU_FAULT_ADReadRegister32   (MMU_BASE_EASIL1 + 194)
++#define EASIL1_MMUMMU_TTBWriteRegister32  (MMU_BASE_EASIL1 + 198)
++#define EASIL1_MMUMMU_LOCKReadRegister32   (MMU_BASE_EASIL1 + 203)
++#define EASIL1_MMUMMU_LOCKWriteRegister32  (MMU_BASE_EASIL1 + 204)
++#define EASIL1_MMUMMU_LOCKBaseValueRead32  (MMU_BASE_EASIL1 + 205)
++#define EASIL1_MMUMMU_LOCKCurrentVictimRead32 (MMU_BASE_EASIL1 + 209)
++#define EASIL1_MMUMMU_LOCKCurrentVictimWrite32 (MMU_BASE_EASIL1 + 211)
++#define EASIL1_MMUMMU_LOCKCurrentVictimSet32  (MMU_BASE_EASIL1 + 212)
++#define EASIL1_MMUMMU_LD_TLBReadRegister32    (MMU_BASE_EASIL1 + 213)
++#define EASIL1_MMUMMU_LD_TLBWriteRegister32   (MMU_BASE_EASIL1 + 214)
++#define EASIL1_MMUMMU_CAMWriteRegister32   (MMU_BASE_EASIL1 + 226)
++#define EASIL1_MMUMMU_RAMWriteRegister32 (MMU_BASE_EASIL1 + 268)
++#define EASIL1_MMUMMU_FLUSH_ENTRYWriteRegister32  (MMU_BASE_EASIL1 + 322)
++
++/* Register offset address definitions */
++#define MMU_MMU_SYSCONFIG_OFFSET   0x10
++#define MMU_MMU_IRQSTATUS_OFFSET  0x18
++#define MMU_MMU_IRQENABLE_OFFSET    0x1c
++#define MMU_MMU_WALKING_ST_OFFSET 0x40
++#define MMU_MMU_CNTL_OFFSET   0x44
++#define MMU_MMU_FAULT_AD_OFFSET  0x48
++#define MMU_MMU_TTB_OFFSET  0x4c
++#define MMU_MMU_LOCK_OFFSET   0x50
++#define MMU_MMU_LD_TLB_OFFSET  0x54
++#define MMU_MMU_CAM_OFFSET   0x58
++#define MMU_MMU_RAM_OFFSET   0x5c
++#define MMU_MMU_GFLUSH_OFFSET  0x60
++#define MMU_MMU_FLUSH_ENTRY_OFFSET  0x64
++/* Bitfield mask and offset declarations */
++#define MMU_MMU_SYSCONFIG_IdleMode_MASK  0x18
++#define MMU_MMU_SYSCONFIG_IdleMode_OFFSET  3
++#define MMU_MMU_SYSCONFIG_AutoIdle_MASK  0x1
++#define MMU_MMU_SYSCONFIG_AutoIdle_OFFSET   0
++#define MMU_MMU_WALKING_ST_TWLRunning_MASK 0x1
++#define MMU_MMU_WALKING_ST_TWLRunning_OFFSET  0
++#define MMU_MMU_CNTL_TWLEnable_MASK 0x4
++#define MMU_MMU_CNTL_TWLEnable_OFFSET 2
++#define MMU_MMU_CNTL_MMUEnable_MASK    0x2
++#define MMU_MMU_CNTL_MMUEnable_OFFSET   1
++#define MMU_MMU_LOCK_BaseValue_MASK 0xfc00
++#define MMU_MMU_LOCK_BaseValue_OFFSET   10
++#define MMU_MMU_LOCK_CurrentVictim_MASK   0x3f0
++#define MMU_MMU_LOCK_CurrentVictim_OFFSET    4
++
++#endif /* _MMU_ACC_INT_H */
+diff --git a/drivers/dsp/bridge/hw/MMURegAcM.h b/drivers/dsp/bridge/hw/MMURegAcM.h
+new file mode 100644
+index 0000000..e46fdcb
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MMURegAcM.h
+@@ -0,0 +1,253 @@
++/*
++ * MMURegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++#ifndef _MMU_REG_ACM_H
++#define _MMU_REG_ACM_H
++
++#include <GlobalTypes.h>
++
++#include <EasiGlobal.h>
++
++#include "MMUAccInt.h"
++
++#if defined(USE_LEVEL_1_MACROS)
++
++
++#define MMUMMU_SYSCONFIGReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_SYSCONFIGReadRegister32),\
++      RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_SYSCONFIG_OFFSET))
++
++
++#define MMUMMU_SYSCONFIGIdleModeWrite32(baseAddress, value)\
++{\
++    const u32 offset = MMU_MMU_SYSCONFIG_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++    register u32 newValue = (value);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_SYSCONFIGIdleModeWrite32);\
++    data &= ~(MMU_MMU_SYSCONFIG_IdleMode_MASK);\
++    newValue <<= MMU_MMU_SYSCONFIG_IdleMode_OFFSET;\
++    newValue &= MMU_MMU_SYSCONFIG_IdleMode_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_SYSCONFIGAutoIdleWrite32(baseAddress, value)\
++{\
++    const u32 offset = MMU_MMU_SYSCONFIG_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++    register u32 newValue = (value);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_SYSCONFIGAutoIdleWrite32);\
++    data &= ~(MMU_MMU_SYSCONFIG_AutoIdle_MASK);\
++    newValue <<= MMU_MMU_SYSCONFIG_AutoIdle_OFFSET;\
++    newValue &= MMU_MMU_SYSCONFIG_AutoIdle_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_IRQSTATUSReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQSTATUSReadRegister32),\
++      RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_IRQSTATUS_OFFSET))
++
++
++#define MMUMMU_IRQSTATUSWriteRegister32(baseAddress, value)\
++{\
++    const u32 offset = MMU_MMU_IRQSTATUS_OFFSET;\
++    register u32 newValue = (value);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQSTATUSWriteRegister32);\
++    WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_IRQENABLEReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQENABLEReadRegister32),\
++      RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_IRQENABLE_OFFSET))
++
++
++#define MMUMMU_IRQENABLEWriteRegister32(baseAddress, value)\
++{\
++    const u32 offset = MMU_MMU_IRQENABLE_OFFSET;\
++    register u32 newValue = (value);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQENABLEWriteRegister32);\
++    WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_WALKING_STTWLRunningRead32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_WALKING_STTWLRunningRead32),\
++      (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_WALKING_ST_OFFSET))))\
++      & MMU_MMU_WALKING_ST_TWLRunning_MASK) >>\
++      MMU_MMU_WALKING_ST_TWLRunning_OFFSET))
++
++
++#define MMUMMU_CNTLTWLEnableRead32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CNTLTWLEnableRead32),\
++      (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_CNTL_OFFSET)))) &\
++      MMU_MMU_CNTL_TWLEnable_MASK) >>\
++      MMU_MMU_CNTL_TWLEnable_OFFSET))
++
++
++#define MMUMMU_CNTLTWLEnableWrite32(baseAddress, value)\
++{\
++    const u32 offset = MMU_MMU_CNTL_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++    register u32 newValue = (value);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CNTLTWLEnableWrite32);\
++    data &= ~(MMU_MMU_CNTL_TWLEnable_MASK);\
++    newValue <<= MMU_MMU_CNTL_TWLEnable_OFFSET;\
++    newValue &= MMU_MMU_CNTL_TWLEnable_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_CNTLMMUEnableWrite32(baseAddress, value)\
++{\
++    const u32 offset = MMU_MMU_CNTL_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++    register u32 newValue = (value);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CNTLMMUEnableWrite32);\
++    data &= ~(MMU_MMU_CNTL_MMUEnable_MASK);\
++    newValue <<= MMU_MMU_CNTL_MMUEnable_OFFSET;\
++    newValue &= MMU_MMU_CNTL_MMUEnable_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_FAULT_ADReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_FAULT_ADReadRegister32),\
++      RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_FAULT_AD_OFFSET))
++
++
++#define MMUMMU_TTBWriteRegister32(baseAddress, value)\
++{\
++    const u32 offset = MMU_MMU_TTB_OFFSET;\
++    register u32 newValue = (value);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_TTBWriteRegister32);\
++    WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKReadRegister32),\
++      RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_LOCK_OFFSET))
++
++
++#define MMUMMU_LOCKWriteRegister32(baseAddress, value)\
++{\
++    const u32 offset = MMU_MMU_LOCK_OFFSET;\
++    register u32 newValue = (value);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKWriteRegister32);\
++    WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKBaseValueRead32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKBaseValueRead32),\
++      (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_LOCK_OFFSET)))) &\
++      MMU_MMU_LOCK_BaseValue_MASK) >>\
++      MMU_MMU_LOCK_BaseValue_OFFSET))
++
++
++#define MMUMMU_LOCKBaseValueWrite32(baseAddress, value)\
++{\
++    const u32 offset = MMU_MMU_LOCK_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++    register u32 newValue = (value);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKBaseValueWrite32);\
++    data &= ~(MMU_MMU_LOCK_BaseValue_MASK);\
++    newValue <<= MMU_MMU_LOCK_BaseValue_OFFSET;\
++    newValue &= MMU_MMU_LOCK_BaseValue_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKCurrentVictimRead32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKCurrentVictimRead32),\
++      (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_LOCK_OFFSET)))) &\
++      MMU_MMU_LOCK_CurrentVictim_MASK) >>\
++      MMU_MMU_LOCK_CurrentVictim_OFFSET))
++
++
++#define MMUMMU_LOCKCurrentVictimWrite32(baseAddress, value)\
++{\
++    const u32 offset = MMU_MMU_LOCK_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++    register u32 newValue = (value);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKCurrentVictimWrite32);\
++    data &= ~(MMU_MMU_LOCK_CurrentVictim_MASK);\
++    newValue <<= MMU_MMU_LOCK_CurrentVictim_OFFSET;\
++    newValue &= MMU_MMU_LOCK_CurrentVictim_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKCurrentVictimSet32(var, value)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKCurrentVictimSet32),\
++      (((var) & ~(MMU_MMU_LOCK_CurrentVictim_MASK)) |\
++      (((value) << MMU_MMU_LOCK_CurrentVictim_OFFSET) &\
++      MMU_MMU_LOCK_CurrentVictim_MASK)))
++
++
++#define MMUMMU_LD_TLBReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LD_TLBReadRegister32),\
++      RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_LD_TLB_OFFSET))
++
++
++#define MMUMMU_LD_TLBWriteRegister32(baseAddress, value)\
++{\
++    const u32 offset = MMU_MMU_LD_TLB_OFFSET;\
++    register u32 newValue = (value);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LD_TLBWriteRegister32);\
++    WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_CAMWriteRegister32(baseAddress, value)\
++{\
++    const u32 offset = MMU_MMU_CAM_OFFSET;\
++    register u32 newValue = (value);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CAMWriteRegister32);\
++    WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_RAMWriteRegister32(baseAddress, value)\
++{\
++    const u32 offset = MMU_MMU_RAM_OFFSET;\
++    register u32 newValue = (value);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_RAMWriteRegister32);\
++    WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_FLUSH_ENTRYWriteRegister32(baseAddress, value)\
++{\
++    const u32 offset = MMU_MMU_FLUSH_ENTRY_OFFSET;\
++    register u32 newValue = (value);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_FLUSH_ENTRYWriteRegister32);\
++    WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#endif        /* USE_LEVEL_1_MACROS */
++
++#endif /* _MMU_REG_ACM_H */
+diff --git a/drivers/dsp/bridge/hw/PRCMAccInt.h b/drivers/dsp/bridge/hw/PRCMAccInt.h
+new file mode 100644
+index 0000000..42baa68
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/PRCMAccInt.h
+@@ -0,0 +1,300 @@
++/*
++ * PRCMAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _PRCM_ACC_INT_H
++#define _PRCM_ACC_INT_H
++
++/* Mappings of level 1 EASI function numbers to function names */
++
++#define EASIL1_PRCMPRCM_CLKCFG_CTRLValid_configWriteClk_valid32  \
++                                              (PRCM_BASE_EASIL1 + 349)
++#define EASIL1_PRCMCM_FCLKEN1_COREReadRegister32      (PRCM_BASE_EASIL1 + 743)
++#define EASIL1_PRCMCM_FCLKEN1_COREEN_GPT8Write32      (PRCM_BASE_EASIL1 + 951)
++#define EASIL1_PRCMCM_FCLKEN1_COREEN_GPT7Write32      (PRCM_BASE_EASIL1 + 961)
++#define EASIL1_PRCMCM_ICLKEN1_COREReadRegister32      \
++                                              (PRCM_BASE_EASIL1 + 1087)
++#define EASIL1_PRCMCM_ICLKEN1_COREEN_MAILBOXESWrite32 \
++                                              (PRCM_BASE_EASIL1 + 1105)
++#define EASIL1_PRCMCM_ICLKEN1_COREEN_GPT8Write32      \
++                                              (PRCM_BASE_EASIL1 + 1305)
++#define EASIL1_PRCMCM_ICLKEN1_COREEN_GPT7Write32      \
++                                              (PRCM_BASE_EASIL1 + 1315)
++#define EASIL1_PRCMCM_CLKSEL1_CORECLKSEL_L3ReadIssel132       \
++                                              (PRCM_BASE_EASIL1 + 2261)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8Write32k32       \
++                                              (PRCM_BASE_EASIL1 + 2364)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteSys32       \
++                                              (PRCM_BASE_EASIL1 + 2365)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteExt32       \
++                                              (PRCM_BASE_EASIL1 + 2366)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7Write32k32       \
++                                              (PRCM_BASE_EASIL1 + 2380)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteSys32       \
++                                              (PRCM_BASE_EASIL1 + 2381)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteExt32       \
++                                              (PRCM_BASE_EASIL1 + 2382)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteSys32       \
++                                              (PRCM_BASE_EASIL1 + 2397)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteExt32       \
++                                              (PRCM_BASE_EASIL1 + 2398)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteSys32       \
++                                              (PRCM_BASE_EASIL1 + 2413)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteExt32       \
++                                              (PRCM_BASE_EASIL1 + 2414)
++#define EASIL1_PRCMCM_CLKSEL1_PLLAPLLs_ClkinRead32    \
++                                              (PRCM_BASE_EASIL1 + 3747)
++#define EASIL1_PRCMCM_FCLKEN_DSPEN_DSPWrite32 (PRCM_BASE_EASIL1 + 3834)
++#define EASIL1_PRCMCM_ICLKEN_DSPEN_DSP_IPIWrite32     \
++                                              (PRCM_BASE_EASIL1 + 3846)
++#define EASIL1_PRCMCM_IDLEST_DSPReadRegister32        (PRCM_BASE_EASIL1 + 3850)
++#define EASIL1_PRCMCM_IDLEST_DSPST_IPIRead32  (PRCM_BASE_EASIL1 + 3857)
++#define EASIL1_PRCMCM_IDLEST_DSPST_DSPRead32  (PRCM_BASE_EASIL1 + 3863)
++#define EASIL1_PRCMCM_AUTOIDLE_DSPAUTO_DSP_IPIWrite32 \
++                                              (PRCM_BASE_EASIL1 + 3877)
++#define EASIL1_PRCMCM_CLKSEL_DSPSYNC_DSPWrite32       (PRCM_BASE_EASIL1 + 3927)
++#define EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSP_IFWrite32  \
++                                              (PRCM_BASE_EASIL1 + 3941)
++#define EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSPWrite32     \
++                                              (PRCM_BASE_EASIL1 + 3965)
++#define EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPRead32        \
++                                              (PRCM_BASE_EASIL1 + 3987)
++#define EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPWrite32       \
++                                              (PRCM_BASE_EASIL1 + 3993)
++#define EASIL1_PRCMRM_RSTCTRL_DSPReadRegister32       (PRCM_BASE_EASIL1 + 3997)
++#define EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32      \
++                                              (PRCM_BASE_EASIL1 + 4025)
++#define EASIL1_PRCMRM_RSTST_DSPReadRegister32 (PRCM_BASE_EASIL1 + 4029)
++#define EASIL1_PRCMRM_RSTST_DSPWriteRegister32        (PRCM_BASE_EASIL1 + 4030)
++#define EASIL1_PRCMPM_PWSTCTRL_DSPForceStateWrite32   \
++                                              (PRCM_BASE_EASIL1 + 4165)
++#define EASIL1_PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32        \
++                                              (PRCM_BASE_EASIL1 + 4193)
++#define EASIL1_PRCMPM_PWSTST_DSPReadRegister32        (PRCM_BASE_EASIL1 + 4197)
++#define EASIL1_PRCMPM_PWSTST_DSPInTransitionRead32    \
++                                              (PRCM_BASE_EASIL1 + 4198)
++#define EASIL1_PRCMPM_PWSTST_DSPPowerStateStGet32     \
++                                              (PRCM_BASE_EASIL1 + 4235)
++#define EASIL1_CM_FCLKEN_PER_GPT5WriteRegister32      \
++                                              (PRCM_BASE_EASIL1 + 4368)
++#define EASIL1_CM_ICLKEN_PER_GPT5WriteRegister32      \
++                                              (PRCM_BASE_EASIL1 + 4370)
++#define EASIL1_CM_CLKSEL_PER_GPT5Write32k32   (PRCM_BASE_EASIL1 + 4372)
++#define EASIL1_CM_CLKSEL_PER_GPT6Write32k32   (PRCM_BASE_EASIL1 + 4373)
++#define EASIL1_PRCMCM_CLKSTCTRL_IVA2WriteRegister32   \
++                                              (PRCM_BASE_EASIL1 + 4374)
++#define EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32        \
++                                              (PRCM_BASE_EASIL1 + 4375)
++#define EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32       \
++                                              (PRCM_BASE_EASIL1 + 4376)
++#define EASIL1_PRCMPM_PWSTST_IVA2InTransitionRead32   \
++                                              (PRCM_BASE_EASIL1 + 4377)
++#define EASIL1_PRCMPM_PWSTST_IVA2PowerStateStGet32    \
++                                              (PRCM_BASE_EASIL1 + 4378)
++#define EASIL1_PRCMPM_PWSTST_IVA2ReadRegister32       (PRCM_BASE_EASIL1 + 4379)
++
++/* Register offset address definitions */
++
++#define PRCM_PRCM_CLKCFG_CTRL_OFFSET        (u32)(0x80)
++#define PRCM_CM_FCLKEN1_CORE_OFFSET          (u32)(0x200)
++#define PRCM_CM_ICLKEN1_CORE_OFFSET          (u32)(0x210)
++#define PRCM_CM_CLKSEL2_CORE_OFFSET          (u32)(0x244)
++#define PRCM_CM_CLKSEL1_PLL_OFFSET           (u32)(0x540)
++#define PRCM_CM_ICLKEN_DSP_OFFSET            (u32)(0x810)
++#define PRCM_CM_IDLEST_DSP_OFFSET            (u32)(0x820)
++#define PRCM_CM_AUTOIDLE_DSP_OFFSET          (u32)(0x830)
++#define PRCM_CM_CLKSEL_DSP_OFFSET            (u32)(0x840)
++#define PRCM_CM_CLKSTCTRL_DSP_OFFSET         (u32)(0x848)
++#define PRCM_RM_RSTCTRL_DSP_OFFSET           (u32)(0x850)
++#define PRCM_RM_RSTST_DSP_OFFSET             (u32)(0x858)
++#define PRCM_PM_PWSTCTRL_DSP_OFFSET          (u32)(0x8e0)
++#define PRCM_PM_PWSTST_DSP_OFFSET            (u32)(0x8e4)
++#define PRCM_PM_PWSTST_IVA2_OFFSET            (u32)(0xE4)
++#define PRCM_PM_PWSTCTRL_IVA2_OFFSET          (u32)(0xE0)
++#define PRCM_CM_CLKSTCTRL_IVA2_OFFSET         (u32)(0x48)
++#define CM_CLKSEL_PER_OFFSET                            (u32)(0x40)
++
++/* Bitfield mask and offset declarations */
++
++#define PRCM_PRCM_CLKCFG_CTRL_Valid_config_MASK         (u32)(0x1)
++#define PRCM_PRCM_CLKCFG_CTRL_Valid_config_OFFSET       (u32)(0)
++
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT8_MASK               (u32)(0x400)
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT8_OFFSET             (u32)(10)
++
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT7_MASK               (u32)(0x200)
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT7_OFFSET             (u32)(9)
++
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT8_MASK               (u32)(0x400)
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT8_OFFSET             (u32)(10)
++
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT7_MASK               (u32)(0x200)
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT7_OFFSET             (u32)(9)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK           (u32)(0xc000)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET         (u32)(14)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK           (u32)(0x3000)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET         (u32)(12)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_MASK           (u32)(0xc00)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_OFFSET         (u32)(10)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_MASK           (u32)(0x300)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_OFFSET         (u32)(8)
++
++#define PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_MASK            (u32)(0x3800000)
++#define PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_OFFSET          (u32)(23)
++
++#define PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_MASK              (u32)(0x2)
++#define PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_OFFSET            (u32)(1)
++
++#define PRCM_CM_IDLEST_DSP_ST_IPI_MASK                  (u32)(0x2)
++#define PRCM_CM_IDLEST_DSP_ST_IPI_OFFSET                (u32)(1)
++
++#define PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_MASK          (u32)(0x2)
++#define PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_OFFSET        (u32)(1)
++
++#define PRCM_CM_CLKSEL_DSP_SYNC_DSP_MASK                (u32)(0x80)
++#define PRCM_CM_CLKSEL_DSP_SYNC_DSP_OFFSET              (u32)(7)
++
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_MASK           (u32)(0x60)
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_OFFSET         (u32)(5)
++
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_MASK              (u32)(0x1f)
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_OFFSET            (u32)(0)
++
++#define PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK        (u32)(0x1)
++#define PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_OFFSET      (u32)(0)
++
++#define PRCM_PM_PWSTCTRL_DSP_ForceState_MASK            (u32)(0x40000)
++#define PRCM_PM_PWSTCTRL_DSP_ForceState_OFFSET          (u32)(18)
++
++#define PRCM_PM_PWSTCTRL_DSP_PowerState_MASK            (u32)(0x3)
++#define PRCM_PM_PWSTCTRL_DSP_PowerState_OFFSET          (u32)(0)
++
++#define PRCM_PM_PWSTCTRL_IVA2_PowerState_MASK            (u32)(0x3)
++#define PRCM_PM_PWSTCTRL_IVA2_PowerState_OFFSET          (u32)(0)
++
++#define PRCM_PM_PWSTST_DSP_InTransition_MASK            (u32)(0x100000)
++#define PRCM_PM_PWSTST_DSP_InTransition_OFFSET          (u32)(20)
++
++#define PRCM_PM_PWSTST_IVA2_InTransition_MASK            (u32)(0x100000)
++#define PRCM_PM_PWSTST_IVA2_InTransition_OFFSET          (u32)(20)
++
++#define PRCM_PM_PWSTST_DSP_PowerStateSt_MASK            (u32)(0x3)
++#define PRCM_PM_PWSTST_DSP_PowerStateSt_OFFSET          (u32)(0)
++
++#define PRCM_PM_PWSTST_IVA2_PowerStateSt_MASK            (u32)(0x3)
++#define PRCM_PM_PWSTST_IVA2_PowerStateSt_OFFSET          (u32)(0)
++
++#define CM_FCLKEN_PER_OFFSET          (u32)(0x0)
++#define CM_FCLKEN_PER_GPT5_OFFSET         (u32)(6)
++#define CM_FCLKEN_PER_GPT5_MASK     (u32)(0x40)
++
++#define CM_FCLKEN_PER_GPT6_OFFSET   (u32)(7)
++#define CM_FCLKEN_PER_GPT6_MASK      (u32)(0x80)
++
++#define CM_ICLKEN_PER_OFFSET          (u32)(0x10)
++#define CM_ICLKEN_PER_GPT5_OFFSET  (u32)(6)
++#define CM_ICLKEN_PER_GPT5_MASK     (u32)(0x40)
++
++#define CM_ICLKEN_PER_GPT6_OFFSET  (u32)(7)
++#define CM_ICLKEN_PER_GPT6_MASK     (u32)(0x80)
++
++#define CM_CLKSEL_PER_GPT5_OFFSET   (u32)(3)
++#define CM_CLKSEL_PER_GPT5_MASK      (u32)(0x8)
++
++#define CM_CLKSEL_PER_GPT6_OFFSET   (u32)(4)
++#define CM_CLKSEL_PER_GPT6_MASK       (u32)(0x10)
++
++
++#define CM_FCLKEN_IVA2_OFFSET         (u32)(0x0)
++#define CM_FCLKEN_IVA2_EN_MASK        (u32)(0x1)
++#define CM_FCLKEN_IVA2_EN_OFFSET      (u32)(0x0)
++
++#define CM_IDLEST_IVA2_OFFSET                 (u32)(0x20)
++#define CM_IDLEST_IVA2_ST_IVA2_MASK (u32) (0x01)
++#define CM_IDLEST_IVA2_ST_IVA2_OFFSET (u32) (0x00)
++
++#define CM_FCLKEN1_CORE_OFFSET        (u32)(0xA00)
++
++#define CM_ICLKEN1_CORE_OFFSET        (u32)(0xA10)
++#define CM_ICLKEN1_CORE_EN_MAILBOXES_MASK  (u32)(0x00000080)   /* bit 7 */
++#define CM_ICLKEN1_CORE_EN_MAILBOXES_OFFSET   (u32)(7)
++
++#define CM_CLKSTCTRL_IVA2_OFFSET (u32)(0x0)
++#define CM_CLKSTCTRL_IVA2_MASK    (u32)(0x3)
++
++
++#define PRM_RSTCTRL_IVA2_OFFSET       (u32)(0x50)
++#define PRM_RSTCTRL_IVA2_RST1_MASK    (u32)(0x1)
++#define PRM_RSTCTRL_IVA2_RST1_OFFSET  (u32)(0x0)
++#define PRM_RSTCTRL_IVA2_RST2_MASK    (u32)(0x2)
++#define PRM_RSTCTRL_IVA2_RST2_OFFSET  (u32)(0x1)
++#define PRM_RSTCTRL_IVA2_RST3_MASK    (u32)(0x4)
++#define PRM_RSTCTRL_IVA2_RST3_OFFSET  (u32)(0x2)
++
++
++/* The following represent the enumerated values for each bitfield */
++
++enum PRCMPRCM_CLKCFG_CTRLValid_configE {
++    PRCMPRCM_CLKCFG_CTRLValid_configUpdated = 0x0000,
++    PRCMPRCM_CLKCFG_CTRLValid_configClk_valid = 0x0001
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT8E {
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT832k = 0x0000,
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT8Sys = 0x0001,
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT8Ext = 0x0002,
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT8Reserved = 0x0003
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT7E {
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT732k = 0x0000,
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT7Sys = 0x0001,
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT7Ext = 0x0002,
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT7Reserved = 0x0003
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT6E {
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT632k = 0x0000,
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT6Sys = 0x0001,
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT6Ext = 0x0002,
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT6Reserved = 0x0003
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT5E {
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT532k = 0x0000,
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT5Sys = 0x0001,
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT5Ext = 0x0002,
++    PRCMCM_CLKSEL2_CORECLKSEL_GPT5Reserved = 0x0003
++} ;
++
++enum PRCMPM_PWSTCTRL_DSPPowerStateE {
++    PRCMPM_PWSTCTRL_DSPPowerStateON = 0x0000,
++    PRCMPM_PWSTCTRL_DSPPowerStateRET = 0x0001,
++    PRCMPM_PWSTCTRL_DSPPowerStateReserved = 0x0002,
++    PRCMPM_PWSTCTRL_DSPPowerStateOFF = 0x0003
++} ;
++
++enum PRCMPM_PWSTCTRL_IVA2PowerStateE {
++    PRCMPM_PWSTCTRL_IVA2PowerStateON = 0x0003,
++    PRCMPM_PWSTCTRL_IVA2PowerStateRET = 0x0001,
++    PRCMPM_PWSTCTRL_IVA2PowerStateReserved = 0x0002,
++    PRCMPM_PWSTCTRL_IVA2PowerStateOFF = 0x0000
++} ;
++
++#endif /* _PRCM_ACC_INT_H */
+diff --git a/drivers/dsp/bridge/hw/PRCMRegAcM.h b/drivers/dsp/bridge/hw/PRCMRegAcM.h
+new file mode 100644
+index 0000000..91cb33c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/PRCMRegAcM.h
+@@ -0,0 +1,669 @@
++/*
++ * PRCMRegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _PRCM_REG_ACM_H
++#define _PRCM_REG_ACM_H
++
++#include <GlobalTypes.h>
++
++#include <EasiGlobal.h>
++
++#include "PRCMAccInt.h"
++
++#if defined(USE_LEVEL_1_MACROS)
++
++#define PRCMPRCM_CLKCFG_CTRLValid_configWriteClk_valid32(baseAddress)\
++{\
++    const u32 offset = PRCM_PRCM_CLKCFG_CTRL_OFFSET;\
++    const u32 newValue = \
++      (u32)PRCMPRCM_CLKCFG_CTRLValid_configClk_valid <<\
++      PRCM_PRCM_CLKCFG_CTRL_Valid_config_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(\
++      EASIL1_PRCMPRCM_CLKCFG_CTRLValid_configWriteClk_valid32);\
++    data &= ~(PRCM_PRCM_CLKCFG_CTRL_Valid_config_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define CM_FCLKEN_PERReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREReadRegister32),\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_FCLKEN_PER_OFFSET))
++
++
++#define CM_ICLKEN_PERReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREReadRegister32),\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_ICLKEN_PER_OFFSET))
++
++
++#define CM_FCLKEN_PER_GPT5WriteRegister32(baseAddress,value)\
++{\
++    const u32 offset = CM_FCLKEN_PER_OFFSET;\
++    register u32 data = \
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_CM_FCLKEN_PER_GPT5WriteRegister32);\
++   data &= ~(CM_FCLKEN_PER_GPT5_MASK);\
++   newValue <<= CM_FCLKEN_PER_GPT5_OFFSET;\
++   newValue &= CM_FCLKEN_PER_GPT5_MASK;\
++   newValue |= data;\
++    WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_FCLKEN_PER_GPT6WriteRegister32(baseAddress,value)\
++{\
++    const u32 offset = CM_FCLKEN_PER_OFFSET;\
++    register u32 data =\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_CM_FCLKEN_PER_GPT5WriteRegister32);\
++   data &= ~(CM_FCLKEN_PER_GPT6_MASK);\
++   newValue <<= CM_FCLKEN_PER_GPT6_OFFSET;\
++   newValue &= CM_FCLKEN_PER_GPT6_MASK;\
++   newValue |= data;\
++    WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_ICLKEN_PER_GPT5WriteRegister32(baseAddress,value)\
++{\
++    const u32 offset = CM_ICLKEN_PER_OFFSET;\
++    register u32 data = \
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_CM_ICLKEN_PER_GPT5WriteRegister32);\
++   data &= ~(CM_ICLKEN_PER_GPT5_MASK);\
++   newValue <<= CM_ICLKEN_PER_GPT5_OFFSET;\
++   newValue &= CM_ICLKEN_PER_GPT5_MASK;\
++   newValue |= data;\
++    WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_ICLKEN_PER_GPT6WriteRegister32(baseAddress,value)\
++{\
++    const u32 offset = CM_ICLKEN_PER_OFFSET;\
++    register u32 data = \
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_CM_ICLKEN_PER_GPT5WriteRegister32);\
++   data &= ~(CM_ICLKEN_PER_GPT6_MASK);\
++   newValue <<= CM_ICLKEN_PER_GPT6_OFFSET;\
++   newValue &= CM_ICLKEN_PER_GPT6_MASK;\
++   newValue |= data;\
++    WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_FCLKEN1_COREReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREReadRegister32),\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_FCLKEN1_CORE_OFFSET))
++
++
++#define PRCMCM_FCLKEN1_COREEN_GPT8Write32(baseAddress,value)\
++{\
++    const u32 offset = PRCM_CM_FCLKEN1_CORE_OFFSET;\
++    register u32 data = \
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREEN_GPT8Write32);\
++    data &= ~(PRCM_CM_FCLKEN1_CORE_EN_GPT8_MASK);\
++    newValue <<= PRCM_CM_FCLKEN1_CORE_EN_GPT8_OFFSET;\
++    newValue &= PRCM_CM_FCLKEN1_CORE_EN_GPT8_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_FCLKEN1_COREEN_GPT7Write32(baseAddress,value)\
++{\
++    const u32 offset = PRCM_CM_FCLKEN1_CORE_OFFSET;\
++    register u32 data = \
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREEN_GPT7Write32);\
++    data &= ~(PRCM_CM_FCLKEN1_CORE_EN_GPT7_MASK);\
++    newValue <<= PRCM_CM_FCLKEN1_CORE_EN_GPT7_OFFSET;\
++    newValue &= PRCM_CM_FCLKEN1_CORE_EN_GPT7_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define CM_ICLKEN1_COREReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREReadRegister32),\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_ICLKEN1_CORE_OFFSET))
++
++
++#define  CM_ICLKEN1_COREEN_MAILBOXESWrite32(baseAddress, value)\
++{\
++    const u32 offset = CM_ICLKEN1_CORE_OFFSET;\
++    register u32 data = \
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREEN_MAILBOXESWrite32);\
++    data &= ~(CM_ICLKEN1_CORE_EN_MAILBOXES_MASK);\
++    newValue <<= CM_ICLKEN1_CORE_EN_MAILBOXES_OFFSET;\
++    newValue &= CM_ICLKEN1_CORE_EN_MAILBOXES_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_ICLKEN1_COREEN_GPT8Write32(baseAddress, value)\
++{\
++    const u32 offset = PRCM_CM_ICLKEN1_CORE_OFFSET;\
++    register u32 data = \
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREEN_GPT8Write32);\
++    data &= ~(PRCM_CM_ICLKEN1_CORE_EN_GPT8_MASK);\
++    newValue <<= PRCM_CM_ICLKEN1_CORE_EN_GPT8_OFFSET;\
++    newValue &= PRCM_CM_ICLKEN1_CORE_EN_GPT8_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_ICLKEN1_COREEN_GPT7Write32(baseAddress, value)\
++{\
++    const u32 offset = PRCM_CM_ICLKEN1_CORE_OFFSET;\
++    register u32 data =\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREEN_GPT7Write32);\
++    data &= ~(PRCM_CM_ICLKEN1_CORE_EN_GPT7_MASK);\
++    newValue <<= PRCM_CM_ICLKEN1_CORE_EN_GPT7_OFFSET;\
++    newValue &= PRCM_CM_ICLKEN1_CORE_EN_GPT7_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT8Write32k32(baseAddress)\
++{\
++    const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++    const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT832k <<\
++      PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8Write32k32);\
++    data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteSys32(baseAddress)\
++{\
++    const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++    const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT8Sys <<\
++      PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteSys32);\
++    data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteExt32(baseAddress)\
++{\
++    const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++    const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT8Ext <<\
++      PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteExt32);\
++    data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT7Write32k32(baseAddress)\
++{\
++    const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++    const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT732k <<\
++      PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7Write32k32);\
++    data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteSys32(baseAddress)\
++{\
++    const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++    const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT7Sys <<\
++      PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteSys32);\
++    data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteExt32(baseAddress)\
++{\
++    const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++    const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT7Ext <<\
++      PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteExt32);\
++    data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteSys32(baseAddress)\
++{\
++    const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++    const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT6Sys <<\
++      PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteSys32);\
++    data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteExt32(baseAddress)\
++{\
++    const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++    const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT6Ext <<\
++      PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteExt32);\
++    data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define CM_CLKSEL_PER_GPT5Write32k32(baseAddress)\
++{\
++    const u32 offset = CM_CLKSEL_PER_OFFSET;\
++    const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT532k <<\
++      CM_CLKSEL_PER_GPT5_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_CM_CLKSEL_PER_GPT5Write32k32);\
++    data &= ~(CM_CLKSEL_PER_GPT5_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define CM_CLKSEL_PER_GPT6Write32k32(baseAddress)\
++{\
++    const u32 offset = CM_CLKSEL_PER_OFFSET;\
++    const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT532k <<\
++      CM_CLKSEL_PER_GPT6_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_CM_CLKSEL_PER_GPT6Write32k32);\
++    data &= ~(CM_CLKSEL_PER_GPT6_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteSys32(baseAddress)\
++{\
++    const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++    const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT5Sys <<\
++      PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteSys32);\
++    data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteExt32(baseAddress)\
++{\
++    const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++    const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT5Ext <<\
++      PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteExt32);\
++    data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL1_PLLAPLLs_ClkinRead32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL1_PLLAPLLs_ClkinRead32),\
++      (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++      (PRCM_CM_CLKSEL1_PLL_OFFSET)))) &\
++      PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_MASK) >>\
++      PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_OFFSET))
++
++
++#define CM_FCLKEN_IVA2EN_DSPWrite32(baseAddress,value)\
++{\
++    const u32 offset = CM_FCLKEN_IVA2_OFFSET;\
++    register u32 data = \
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN_DSPEN_DSPWrite32);\
++    data &= ~(CM_FCLKEN_IVA2_EN_MASK);\
++    newValue <<= CM_FCLKEN_IVA2_EN_OFFSET;\
++    newValue &= CM_FCLKEN_IVA2_EN_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_ICLKEN_DSPEN_DSP_IPIWrite32(baseAddress, value)\
++{\
++    const u32 offset = PRCM_CM_ICLKEN_DSP_OFFSET;\
++    register u32 data = \
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN_DSPEN_DSP_IPIWrite32);\
++    data &= ~(PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_MASK);\
++    newValue <<= PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_OFFSET;\
++    newValue &= PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_IDLEST_DSPReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_IDLEST_DSPReadRegister32),\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_CM_IDLEST_DSP_OFFSET))
++
++
++#define PRCMCM_IDLEST_DSPST_IPIRead32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_IDLEST_DSPST_IPIRead32),\
++      (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++      (PRCM_CM_IDLEST_DSP_OFFSET)))) &\
++      PRCM_CM_IDLEST_DSP_ST_IPI_MASK) >>\
++      PRCM_CM_IDLEST_DSP_ST_IPI_OFFSET))
++
++
++#define PRM_IDLEST_IVA2ST_IVA2Read32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_IDLEST_DSPST_DSPRead32),\
++      (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++        (CM_IDLEST_IVA2_OFFSET)))) &\
++      CM_IDLEST_IVA2_ST_IVA2_MASK) >>\
++      CM_IDLEST_IVA2_ST_IVA2_OFFSET))
++
++
++#define PRCMCM_AUTOIDLE_DSPAUTO_DSP_IPIWrite32(baseAddress, value)\
++{\
++    const u32 offset = PRCM_CM_AUTOIDLE_DSP_OFFSET;\
++    register u32 data =\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_AUTOIDLE_DSPAUTO_DSP_IPIWrite32);\
++    data &= ~(PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_MASK);\
++    newValue <<= PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_OFFSET;\
++    newValue &= PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL_DSPSYNC_DSPWrite32(baseAddress,value)\
++{\
++    const u32 offset = PRCM_CM_CLKSEL_DSP_OFFSET;\
++    register u32 data = \
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL_DSPSYNC_DSPWrite32);\
++    data &= ~(PRCM_CM_CLKSEL_DSP_SYNC_DSP_MASK);\
++    newValue <<= PRCM_CM_CLKSEL_DSP_SYNC_DSP_OFFSET;\
++    newValue &= PRCM_CM_CLKSEL_DSP_SYNC_DSP_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL_DSPCLKSEL_DSP_IFWrite32(baseAddress, value)\
++{\
++    const u32 offset = PRCM_CM_CLKSEL_DSP_OFFSET;\
++    register u32 data = \
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSP_IFWrite32);\
++    data &= ~(PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_MASK);\
++    newValue <<= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_OFFSET;\
++    newValue &= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL_DSPCLKSEL_DSPWrite32(baseAddress, value)\
++{\
++    const u32 offset = PRCM_CM_CLKSEL_DSP_OFFSET;\
++    register u32 data = \
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSPWrite32);\
++    data &= ~(PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_MASK);\
++    newValue <<= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_OFFSET;\
++    newValue &= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSTCTRL_IVA2WriteRegister32(baseAddress, value)\
++{\
++    const u32 offset = PRCM_CM_CLKSTCTRL_IVA2_OFFSET;\
++    register u32 data = \
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSTCTRL_IVA2WriteRegister32);\
++    data &= ~(CM_CLKSTCTRL_IVA2_MASK);\
++    newValue <<= CM_CLKSTCTRL_IVA2_OFFSET;\
++    newValue &= CM_CLKSTCTRL_IVA2_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSTCTRL_DSPAutostate_DSPRead32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPRead32),\
++      (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++      (PRCM_CM_CLKSTCTRL_DSP_OFFSET)))) &\
++      PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK) >>\
++      PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_OFFSET))
++
++
++#define PRCMCM_CLKSTCTRL_DSPAutostate_DSPWrite32(baseAddress, value)\
++{\
++    const u32 offset = PRCM_CM_CLKSTCTRL_DSP_OFFSET;\
++    register u32 data = \
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPWrite32);\
++    data &= ~(PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK);\
++    newValue <<= PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_OFFSET;\
++    newValue &= PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMRM_RSTCTRL_DSPReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPReadRegister32),\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_RM_RSTCTRL_DSP_OFFSET))
++
++
++#define PRM_RSTCTRL_IVA2RST1_DSPWrite32(baseAddress,value)\
++{\
++    const u32 offset = PRM_RSTCTRL_IVA2_OFFSET;\
++    register u32 data =\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32);\
++    data &= ~(PRM_RSTCTRL_IVA2_RST1_MASK);\
++    newValue <<= PRM_RSTCTRL_IVA2_RST1_OFFSET;\
++    newValue &= PRM_RSTCTRL_IVA2_RST1_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRM_RSTCTRL_IVA2RST2_DSPWrite32(baseAddress,value)\
++{\
++    const u32 offset = PRM_RSTCTRL_IVA2_OFFSET;\
++    register u32 data =\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32);\
++    data &= ~(PRM_RSTCTRL_IVA2_RST2_MASK);\
++    newValue <<= PRM_RSTCTRL_IVA2_RST2_OFFSET;\
++    newValue &= PRM_RSTCTRL_IVA2_RST2_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRM_RSTCTRL_IVA2RST3_DSPWrite32(baseAddress,value)\
++{\
++    const u32 offset = PRM_RSTCTRL_IVA2_OFFSET;\
++    register u32 data =\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32);\
++    data &= ~(PRM_RSTCTRL_IVA2_RST3_MASK);\
++    newValue <<= PRM_RSTCTRL_IVA2_RST3_OFFSET;\
++    newValue &= PRM_RSTCTRL_IVA2_RST3_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMRM_RSTST_DSPReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTST_DSPReadRegister32),\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_RM_RSTST_DSP_OFFSET))
++
++
++#define PRCMRM_RSTST_DSPWriteRegister32(baseAddress,value)\
++{\
++    const u32 offset = PRCM_RM_RSTST_DSP_OFFSET;\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTST_DSPWriteRegister32);\
++    WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define PRCMPM_PWSTCTRL_DSPForceStateWrite32(baseAddress, value)\
++{\
++    const u32 offset = PRCM_PM_PWSTCTRL_DSP_OFFSET;\
++    register u32 data = \
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++    register u32 newValue = ((u32)(value));\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_DSPForceStateWrite32);\
++    data &= ~(PRCM_PM_PWSTCTRL_DSP_ForceState_MASK);\
++    newValue <<= PRCM_PM_PWSTCTRL_DSP_ForceState_OFFSET;\
++    newValue &= PRCM_PM_PWSTCTRL_DSP_ForceState_MASK;\
++    newValue |= data;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32(baseAddress)\
++{\
++    const u32 offset = PRCM_PM_PWSTCTRL_IVA2_OFFSET;\
++    const u32 newValue = (u32)PRCMPM_PWSTCTRL_IVA2PowerStateON <<\
++      PRCM_PM_PWSTCTRL_IVA2_PowerState_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32);\
++    data &= ~(PRCM_PM_PWSTCTRL_IVA2_PowerState_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32(baseAddress)\
++{\
++    const u32 offset = PRCM_PM_PWSTCTRL_IVA2_OFFSET;\
++    const u32 newValue = (u32)PRCMPM_PWSTCTRL_IVA2PowerStateOFF <<\
++      PRCM_PM_PWSTCTRL_IVA2_PowerState_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32);\
++    data &= ~(PRCM_PM_PWSTCTRL_IVA2_PowerState_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32(baseAddress)\
++{\
++    const u32 offset = PRCM_PM_PWSTCTRL_DSP_OFFSET;\
++    const u32 newValue = (u32)PRCMPM_PWSTCTRL_DSPPowerStateRET <<\
++      PRCM_PM_PWSTCTRL_DSP_PowerState_OFFSET;\
++    register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++    _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32);\
++    data &= ~(PRCM_PM_PWSTCTRL_DSP_PowerState_MASK);\
++    data |= newValue;\
++    WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMPM_PWSTST_DSPReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_DSPReadRegister32),\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_PM_PWSTST_DSP_OFFSET))
++
++
++#define PRCMPM_PWSTST_IVA2ReadRegister32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_IVA2ReadRegister32),\
++      RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_PM_PWSTST_IVA2_OFFSET))
++
++
++#define PRCMPM_PWSTST_DSPInTransitionRead32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_DSPInTransitionRead32),\
++      (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++      (PRCM_PM_PWSTST_DSP_OFFSET)))) &\
++      PRCM_PM_PWSTST_DSP_InTransition_MASK) >>\
++      PRCM_PM_PWSTST_DSP_InTransition_OFFSET))
++
++
++#define PRCMPM_PWSTST_IVA2InTransitionRead32(baseAddress)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_IVA2InTransitionRead32),\
++      (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++      (PRCM_PM_PWSTST_IVA2_OFFSET)))) &\
++      PRCM_PM_PWSTST_IVA2_InTransition_MASK) >>\
++      PRCM_PM_PWSTST_IVA2_InTransition_OFFSET))
++
++
++#define PRCMPM_PWSTST_DSPPowerStateStGet32(var)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_DSPPowerStateStGet32),\
++      (u32)((((u32)(var)) & PRCM_PM_PWSTST_DSP_PowerStateSt_MASK) >>\
++      PRCM_PM_PWSTST_DSP_PowerStateSt_OFFSET))
++
++
++#define PRCMPM_PWSTST_IVA2PowerStateStGet32(var)\
++    (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_IVA2PowerStateStGet32),\
++      (u32)((((u32)(var)) & PRCM_PM_PWSTST_IVA2_PowerStateSt_MASK) >>\
++      PRCM_PM_PWSTST_IVA2_PowerStateSt_OFFSET))
++
++
++#endif  /* USE_LEVEL_1_MACROS */
++
++#endif /* _PRCM_REG_ACM_H */
+diff --git a/drivers/dsp/bridge/hw/hw_defs.h b/drivers/dsp/bridge/hw/hw_defs.h
+new file mode 100644
+index 0000000..a973f5c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_defs.h
+@@ -0,0 +1,73 @@
++/*
++ * hw_defs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== hw_defs.h ========
++ *  Description:
++ *      Global HW definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 19 Apr 2004 sb: Added generic page size, endianness and element size defns
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __HW_DEFS_H
++#define __HW_DEFS_H
++
++#include <GlobalTypes.h>
++
++/* Page size */
++#define HW_PAGE_SIZE_4KB   0x1000
++#define HW_PAGE_SIZE_64KB  0x10000
++#define HW_PAGE_SIZE_1MB   0x100000
++#define HW_PAGE_SIZE_16MB  0x1000000
++
++/* HW_STATUS:  return type for HW API */
++typedef long HW_STATUS;
++
++/* HW_SetClear_t:  Enumerated Type used to set and clear any bit */
++enum HW_SetClear_t {
++    HW_CLEAR,
++    HW_SET
++} ;
++
++/* HW_Endianism_t:  Enumerated Type used to specify the endianism
++ *            Do NOT change these values. They are used as bit fields. */
++enum HW_Endianism_t {
++    HW_LITTLE_ENDIAN,
++    HW_BIG_ENDIAN
++
++} ;
++
++/* HW_ElementSize_t:  Enumerated Type used to specify the element size
++ *            Do NOT change these values. They are used as bit fields. */
++enum HW_ElementSize_t {
++    HW_ELEM_SIZE_8BIT,
++    HW_ELEM_SIZE_16BIT,
++    HW_ELEM_SIZE_32BIT,
++    HW_ELEM_SIZE_64BIT
++
++} ;
++
++/* HW_IdleMode_t:  Enumerated Type used to specify Idle modes */
++      enum HW_IdleMode_t {
++              HW_FORCE_IDLE,
++              HW_NO_IDLE,
++              HW_SMART_IDLE
++      } ;
++
++#endif  /* __HW_DEFS_H */
+diff --git a/drivers/dsp/bridge/hw/hw_dspssC64P.c b/drivers/dsp/bridge/hw/hw_dspssC64P.c
+new file mode 100644
+index 0000000..a4b7c30
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_dspssC64P.c
+@@ -0,0 +1,55 @@
++/*
++ * hw_dspss64P.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== hw_dspss64P.c ========
++ *  Description:
++ *      API definitions to configure DSP Subsystem modules like IPI
++ *
++ *! Revision History:
++ *! ================
++ *! 19 Apr 2004 sb: Implemented HW_DSPSS_IPIEndianismSet
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++/* PROJECT SPECIFIC INCLUDE FILES */
++#include <GlobalTypes.h>
++#include <hw_defs.h>
++#include <hw_dspssC64P.h>
++#include <IVA2RegAcM.h>
++#include <IPIAccInt.h>
++
++/* HW FUNCTIONS */
++HW_STATUS HW_DSPSS_BootModeSet(const u32 baseAddress,
++                    enum HW_DSPSYSC_BootMode_t bootMode,
++                    const u32 bootAddress)
++{
++      HW_STATUS status = RET_OK;
++      u32 offset = SYSC_IVA2BOOTMOD_OFFSET;
++      u32 alignedBootAddr;
++
++      /* if Boot mode it DIRECT BOOT, check that the bootAddress is
++       * aligned to atleast 1K :: TODO */
++      WR_MEM_32_VOLATILE((baseAddress) + offset, bootMode);
++
++      offset = SYSC_IVA2BOOTADDR_OFFSET;
++
++      alignedBootAddr = bootAddress & SYSC_IVA2BOOTADDR_MASK;
++
++      WR_MEM_32_VOLATILE((baseAddress) + offset, alignedBootAddr);
++
++      return status;
++}
+diff --git a/drivers/dsp/bridge/hw/hw_dspssC64P.h b/drivers/dsp/bridge/hw/hw_dspssC64P.h
+new file mode 100644
+index 0000000..493effd
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_dspssC64P.h
+@@ -0,0 +1,48 @@
++/*
++ * hw_dspssC64P.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== hw_dspss.h ========
++ *  Description:
++ *      DSP Subsystem API declarations
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb: Removed redundant argument from HW_DSPSS_IPIEndianismSet
++ *!               Moved endianness and element size to generic hw_defs.h
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#ifndef __HW_DSPSS_H
++#define __HW_DSPSS_H
++#include <linux/types.h>
++
++      enum HW_DSPSYSC_BootMode_t {
++              HW_DSPSYSC_DIRECTBOOT = 0x0,
++              HW_DSPSYSC_IDLEBOOT = 0x1,
++              HW_DSPSYSC_SELFLOOPBOOT = 0x2,
++              HW_DSPSYSC_USRBOOTSTRAP = 0x3,
++              HW_DSPSYSC_DEFAULTRESTORE = 0x4
++      } ;
++
++#define HW_DSP_IDLEBOOT_ADDR   0x007E0000
++
++      extern HW_STATUS HW_DSPSS_BootModeSet(const u32 baseAddress,
++                                      enum HW_DSPSYSC_BootMode_t bootMode,
++                                      const u32 bootAddress);
++
++#endif                                /* __HW_DSPSS_H */
+diff --git a/drivers/dsp/bridge/hw/hw_mbox.c b/drivers/dsp/bridge/hw/hw_mbox.c
+new file mode 100644
+index 0000000..9f14f34
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mbox.c
+@@ -0,0 +1,244 @@
++/*
++ * hw_mbox.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== hw_mbox.c ========
++ *  Description:
++ *      Mailbox messaging & configuration API definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#include <GlobalTypes.h>
++#include "MLBRegAcM.h"
++#include <hw_defs.h>
++#include <hw_mbox.h>
++
++/* width in bits of MBOX Id */
++#define HW_MBOX_ID_WIDTH         2
++
++struct MAILBOX_CONTEXT mboxsetting = {0x4, 0x1, 0x1};
++
++/* Saves the mailbox context */
++HW_STATUS HW_MBOX_saveSettings(u32 baseAddress)
++{
++      HW_STATUS status = RET_OK;
++
++      mboxsetting.sysconfig = MLBMAILBOX_SYSCONFIGReadRegister32(baseAddress);
++      /* Get current enable status */
++      mboxsetting.irqEnable0 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++                               (baseAddress, HW_MBOX_U0_ARM);
++      mboxsetting.irqEnable1 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++                               (baseAddress, HW_MBOX_U1_DSP1);
++      return status;
++}
++
++/* Restores the mailbox context */
++HW_STATUS HW_MBOX_restoreSettings(u32 baseAddress)
++{
++       HW_STATUS status = RET_OK;
++      /* Restor IRQ enable status */
++      MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, HW_MBOX_U0_ARM,
++                                               mboxsetting.irqEnable0);
++      MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, HW_MBOX_U1_DSP1,
++                                               mboxsetting.irqEnable1);
++      /* Restore Sysconfig register */
++      MLBMAILBOX_SYSCONFIGWriteRegister32(baseAddress, mboxsetting.sysconfig);
++      return status;
++}
++
++/* Reads a u32 from the sub module message box Specified. if there are no
++ * messages in the mailbox then and error is returned. */
++HW_STATUS HW_MBOX_MsgRead(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++                              u32 *const pReadValue)
++{
++      HW_STATUS status = RET_OK;
++
++      /* Check input parameters */
++      CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++                    RES_INVALID_INPUT_PARAM);
++      CHECK_INPUT_PARAM(pReadValue, NULL, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++                    RES_INVALID_INPUT_PARAM);
++      CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++                         RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++      /* Read 32-bit message in mail box */
++      *pReadValue = MLBMAILBOX_MESSAGE___0_15ReadRegister32(baseAddress,
++                                                       (u32)mailBoxId);
++
++      return status;
++}
++
++/* Writes a u32 from the sub module message box Specified. */
++HW_STATUS HW_MBOX_MsgWrite(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++                      const u32 writeValue)
++{
++      HW_STATUS status = RET_OK;
++
++      /* Check input parameters */
++      CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++                      RES_INVALID_INPUT_PARAM);
++      CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++                      RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++      /* Write 32-bit value to mailbox */
++      MLBMAILBOX_MESSAGE___0_15WriteRegister32(baseAddress, (u32)mailBoxId,
++                                          (u32)writeValue);
++
++      return status;
++}
++
++/* Gets number of messages in a specified mailbox. */
++HW_STATUS HW_MBOX_NumMsgGet(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++                              u32 *const pNumMsg)
++{
++      HW_STATUS status = RET_OK;
++
++      /* Check input parameters */
++      CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++                    RES_INVALID_INPUT_PARAM);
++      CHECK_INPUT_PARAM(pNumMsg,  NULL, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++                    RES_INVALID_INPUT_PARAM);
++
++      CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++                         RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++      /* Get number of messages available for MailBox */
++      *pNumMsg = MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32(baseAddress,
++                                                        (u32)mailBoxId);
++
++      return status;
++}
++
++/* Enables the specified IRQ. */
++HW_STATUS HW_MBOX_EventEnable(const u32       baseAddress,
++                              const HW_MBOX_Id_t mailBoxId,
++                              const HW_MBOX_UserId_t userId,
++                              const u32 events)
++{
++      HW_STATUS status = RET_OK;
++      u32 irqEnableReg;
++
++      /* Check input parameters */
++      CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++                        RES_INVALID_INPUT_PARAM);
++      CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++                       RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++      CHECK_INPUT_RANGE_MIN0(enableIrq, HW_MBOX_INT_MAX, RET_INVALID_ID,
++                       RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++      CHECK_INPUT_RANGE_MIN0(userId, HW_MBOX_USER_MAX, RET_INVALID_ID,
++                       RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++      /* Get current enable status */
++      irqEnableReg = MLBMAILBOX_IRQENABLE___0_3ReadRegister32(baseAddress,
++                                                           (u32)userId);
++
++      /* update enable value */
++      irqEnableReg |= ((u32)(events)) << (((u32)(mailBoxId)) *
++                      HW_MBOX_ID_WIDTH);
++
++      /* write new enable status */
++      MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, (u32)userId,
++                                               (u32)irqEnableReg);
++
++      mboxsetting.sysconfig = MLBMAILBOX_SYSCONFIGReadRegister32(baseAddress);
++      /* Get current enable status */
++      mboxsetting.irqEnable0 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++                              (baseAddress, HW_MBOX_U0_ARM);
++      mboxsetting.irqEnable1 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++                              (baseAddress, HW_MBOX_U1_DSP1);
++      return status;
++}
++
++/* Disables the specified IRQ. */
++HW_STATUS HW_MBOX_EventDisable(const u32 baseAddress,
++                              const HW_MBOX_Id_t mailBoxId,
++                              const HW_MBOX_UserId_t userId,
++                              const u32 events)
++{
++      HW_STATUS status = RET_OK;
++      u32 irqDisableReg;
++
++      /* Check input parameters */
++      CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++                    RES_INVALID_INPUT_PARAM);
++      CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++                   RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++      CHECK_INPUT_RANGE_MIN0(disableIrq, HW_MBOX_INT_MAX, RET_INVALID_ID,
++                   RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++      CHECK_INPUT_RANGE_MIN0(userId, HW_MBOX_USER_MAX, RET_INVALID_ID,
++                   RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++      /* Get current enable status */
++      irqDisableReg = MLBMAILBOX_IRQENABLE___0_3ReadRegister32(baseAddress,
++                  (u32)userId);
++
++      /* update enable value */
++      irqDisableReg &= ~(((u32)(events)) << (((u32)(mailBoxId)) *
++                   HW_MBOX_ID_WIDTH));
++
++      /* write new enable status */
++      MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, (u32)userId,
++                                           (u32)irqDisableReg);
++
++      return status;
++}
++
++/* Sets the status of the specified IRQ. */
++HW_STATUS HW_MBOX_EventAck(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++                      const HW_MBOX_UserId_t userId, const u32 event)
++{
++      HW_STATUS status = RET_OK;
++      u32 irqStatusReg;
++
++      /* Check input parameters */
++      CHECK_INPUT_PARAM(baseAddress,   0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++                    RES_INVALID_INPUT_PARAM);
++
++      CHECK_INPUT_RANGE_MIN0(irqStatus, HW_MBOX_INT_MAX, RET_INVALID_ID,
++                   RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++      CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++                   RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++      CHECK_INPUT_RANGE_MIN0(userId, HW_MBOX_USER_MAX, RET_INVALID_ID,
++                   RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++      /* calculate status to write */
++      irqStatusReg = ((u32)event) << (((u32)(mailBoxId)) *
++                 HW_MBOX_ID_WIDTH);
++
++      /* clear Irq Status for specified mailbox/User Id */
++      MLBMAILBOX_IRQSTATUS___0_3WriteRegister32(baseAddress, (u32)userId,
++                                           (u32)irqStatusReg);
++
++      /*
++       * FIXME: Replace all this custom register access with standard
++       * __raw_read/write().
++       *
++       * FIXME: Replace all interrupt handlers with standard linux style
++       * interrupt handlers.
++       *
++       * FIXME: Replace direct access to PRCM registers with omap standard
++       * PRCM register access.
++       *
++       * Flush posted write for the irq status to avoid spurious interrupts.
++       */
++      MLBMAILBOX_IRQSTATUS___0_3ReadRegister32(baseAddress, (u32)userId);
++
++      return status;
++}
+diff --git a/drivers/dsp/bridge/hw/hw_mbox.h b/drivers/dsp/bridge/hw/hw_mbox.h
+new file mode 100644
+index 0000000..d2981d3
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mbox.h
+@@ -0,0 +1,323 @@
++/*
++ * hw_mbox.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== hw_mbox.h ========
++ *  Description:
++ *      HW Mailbox API and types definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __MBOX_H
++#define __MBOX_H
++
++/* Bitmasks for Mailbox interrupt sources */
++#define HW_MBOX_INT_NEW_MSG    0x1
++#define HW_MBOX_INT_NOT_FULL   0x2
++#define HW_MBOX_INT_ALL       0x3
++
++/* Maximum number of messages that mailbox can hald at a time. */
++#define HW_MBOX_MAX_NUM_MESSAGES   4
++
++/* HW_MBOX_Id_t: Enumerated Type used to specify Mailbox Sub Module Id Number */
++typedef enum HW_MBOX_Id_label {
++    HW_MBOX_ID_0,
++    HW_MBOX_ID_1,
++    HW_MBOX_ID_2,
++    HW_MBOX_ID_3,
++    HW_MBOX_ID_4,
++    HW_MBOX_ID_5
++
++} HW_MBOX_Id_t, *pHW_MBOX_Id_t;
++
++/* HW_MBOX_UserId_t:  Enumerated Type used to specify Mail box User Id */
++typedef enum HW_MBOX_UserId_label {
++    HW_MBOX_U0_ARM,
++    HW_MBOX_U1_DSP1,
++    HW_MBOX_U2_DSP2,
++    HW_MBOX_U3_ARM
++
++} HW_MBOX_UserId_t, *pHW_MBOX_UserId_t;
++
++/* Mailbox context settings */
++struct MAILBOX_CONTEXT {
++      u32 sysconfig;
++      u32 irqEnable0;
++      u32 irqEnable1;
++};
++
++/*
++* FUNCTION      : HW_MBOX_MsgRead
++*
++* INPUTS:
++*
++*   Identifier  : baseAddress
++*   Type      : const u32
++*   Description : Base Address of instance of Mailbox module
++*
++*   Identifier  : mailBoxId
++*   Type      : const HW_MBOX_Id_t
++*   Description : Mail Box Sub module Id to read
++*
++* OUTPUTS:
++*
++*   Identifier  : pReadValue
++*   Type      : u32 *const
++*   Description : Value read from MailBox
++*
++* RETURNS:
++*
++*   Type      : ReturnCode_t
++*   Description : RET_OK            No errors occured
++*              RET_BAD_NULL_PARAM  Address/ptr Paramater was set to 0/NULL
++*              RET_INVALID_ID      Invalid Id used
++*              RET_EMPTY         Mailbox empty
++*
++* PURPOSE:      : this function reads a u32 from the sub module message
++*              box Specified. if there are no messages in the mailbox
++*              then and error is returned.
++*/
++extern HW_STATUS HW_MBOX_MsgRead(const u32 baseAddress,
++                              const HW_MBOX_Id_t mailBoxId,
++                              u32 *const pReadValue);
++
++/*
++* FUNCTION      : HW_MBOX_MsgWrite
++*
++* INPUTS:
++*
++*   Identifier  : baseAddress
++*   Type      : const u32
++*   Description : Base Address of instance of Mailbox module
++*
++*   Identifier  : mailBoxId
++*   Type      : const HW_MBOX_Id_t
++*   Description : Mail Box Sub module Id to write
++*
++*   Identifier  : writeValue
++*   Type      : const u32
++*   Description : Value to write to MailBox
++*
++* RETURNS:
++*
++*   Type      : ReturnCode_t
++*   Description : RET_OK            No errors occured
++*              RET_BAD_NULL_PARAM  Address/pointer Paramater was set to 0/NULL
++*              RET_INVALID_ID      Invalid Id used
++*
++* PURPOSE:      : this function writes a u32 from the sub module message
++*              box Specified.
++*/
++extern HW_STATUS HW_MBOX_MsgWrite(
++                    const u32  baseAddress,
++                    const HW_MBOX_Id_t   mailBoxId,
++                    const u32  writeValue
++                );
++
++/*
++* FUNCTION      : HW_MBOX_NumMsgGet
++*
++* INPUTS:
++*
++*   Identifier  : baseAddress
++*   Type      : const u32
++*   Description : Base Address of instance of Mailbox module
++*
++*   Identifier  : mailBoxId
++*   Type      : const HW_MBOX_Id_t
++*   Description : Mail Box Sub module Id to get num messages
++*
++* OUTPUTS:
++*
++*   Identifier  : pNumMsg
++*   Type      : u32 *const
++*   Description : Number of messages in mailbox
++*
++* RETURNS:
++*
++*   Type      : ReturnCode_t
++*   Description : RET_OK            No errors occured
++*              RET_BAD_NULL_PARAM  Address/pointer Paramater was set to 0/NULL
++*              RET_INVALID_ID      Inavlid ID input at parameter
++*
++* PURPOSE:      : this function gets number of messages in a specified mailbox.
++*/
++extern HW_STATUS HW_MBOX_NumMsgGet(
++                    const u32  baseAddress,
++                    const HW_MBOX_Id_t   mailBoxId,
++                    u32 *const        pNumMsg
++                );
++
++/*
++* FUNCTION      : HW_MBOX_EventEnable
++*
++* INPUTS:
++*
++*   Identifier  : baseAddress
++*   Type      : const u32
++*              RET_BAD_NULL_PARAM  Address/pointer Paramater was set to 0/NULL
++*
++*   Identifier  : mailBoxId
++*   Type      : const HW_MBOX_Id_t
++*   Description : Mail Box Sub module Id to enable
++*
++*   Identifier  : userId
++*   Type      : const HW_MBOX_UserId_t
++*   Description : Mail box User Id to enable
++*
++*   Identifier  : enableIrq
++*   Type      : const u32
++*   Description : Irq value to enable
++*
++* RETURNS:
++*
++*   Type      : ReturnCode_t
++*   Description : RET_OK            No errors occured
++*              RET_BAD_NULL_PARAM  A Pointer Paramater was set to NULL
++*              RET_INVALID_ID      Invalid Id used
++*
++* PURPOSE:      : this function enables the specified IRQ.
++*/
++extern HW_STATUS HW_MBOX_EventEnable(
++                    const u32      baseAddress,
++                    const HW_MBOX_Id_t       mailBoxId,
++                    const HW_MBOX_UserId_t   userId,
++                    const u32      events
++                );
++
++/*
++* FUNCTION      : HW_MBOX_EventDisable
++*
++* INPUTS:
++*
++*   Identifier  : baseAddress
++*   Type      : const u32
++*              RET_BAD_NULL_PARAM  Address/pointer Paramater was set to 0/NULL
++*
++*   Identifier  : mailBoxId
++*   Type      : const HW_MBOX_Id_t
++*   Description : Mail Box Sub module Id to disable
++*
++*   Identifier  : userId
++*   Type      : const HW_MBOX_UserId_t
++*   Description : Mail box User Id to disable
++*
++*   Identifier  : enableIrq
++*   Type      : const u32
++*   Description : Irq value to disable
++*
++* RETURNS:
++*
++*   Type      : ReturnCode_t
++*   Description : RET_OK            No errors occured
++*              RET_BAD_NULL_PARAM  A Pointer Paramater was set to NULL
++*              RET_INVALID_ID      Invalid Id used
++*
++* PURPOSE:      : this function disables the specified IRQ.
++*/
++extern HW_STATUS HW_MBOX_EventDisable(
++                    const u32      baseAddress,
++                    const HW_MBOX_Id_t       mailBoxId,
++                    const HW_MBOX_UserId_t   userId,
++                    const u32      events
++                );
++
++/*
++* FUNCTION      : HW_MBOX_EventAck
++*
++* INPUTS:
++*
++*   Identifier  : baseAddress
++*   Type      : const u32
++*   Description : Base Address of instance of Mailbox module
++*
++*   Identifier  : mailBoxId
++*   Type      : const HW_MBOX_Id_t
++*   Description : Mail Box Sub module Id to set
++*
++*   Identifier  : userId
++*   Type      : const HW_MBOX_UserId_t
++*   Description : Mail box User Id to set
++*
++*   Identifier  : irqStatus
++*   Type      : const u32
++*   Description : The value to write IRQ status
++*
++* OUTPUTS:
++*
++* RETURNS:
++*
++*   Type      : ReturnCode_t
++*   Description : RET_OK            No errors occured
++*              RET_BAD_NULL_PARAM  Address Paramater was set to 0
++*              RET_INVALID_ID      Invalid Id used
++*
++* PURPOSE:      : this function sets the status of the specified IRQ.
++*/
++extern HW_STATUS HW_MBOX_EventAck(
++                    const u32       baseAddress,
++                    const HW_MBOX_Id_t        mailBoxId,
++                    const HW_MBOX_UserId_t    userId,
++                    const u32       event
++                );
++
++/*
++* FUNCTION      : HW_MBOX_saveSettings
++*
++* INPUTS:
++*
++*   Identifier  : baseAddress
++*   Type      : const u32
++*   Description : Base Address of instance of Mailbox module
++*
++*
++* RETURNS:
++*
++*   Type      : ReturnCode_t
++*   Description : RET_OK            No errors occured
++*              RET_BAD_NULL_PARAM  Address/pointer Paramater was set to 0/NULL
++*              RET_INVALID_ID      Invalid Id used
++*              RET_EMPTY         Mailbox empty
++*
++* PURPOSE:      : this function saves the context of mailbox
++*/
++extern HW_STATUS HW_MBOX_saveSettings(u32    baseAddres);
++
++/*
++* FUNCTION      : HW_MBOX_restoreSettings
++*
++* INPUTS:
++*
++*   Identifier  : baseAddress
++*   Type      : const u32
++*   Description : Base Address of instance of Mailbox module
++*
++*
++* RETURNS:
++*
++*   Type      : ReturnCode_t
++*   Description : RET_OK            No errors occured
++*              RET_BAD_NULL_PARAM  Address/pointer Paramater was set to 0/NULL
++*              RET_INVALID_ID      Invalid Id used
++*              RET_EMPTY         Mailbox empty
++*
++* PURPOSE:      : this function restores the context of mailbox
++*/
++extern HW_STATUS HW_MBOX_restoreSettings(u32    baseAddres);
++
++#endif  /* __MBOX_H */
+diff --git a/drivers/dsp/bridge/hw/hw_mmu.c b/drivers/dsp/bridge/hw/hw_mmu.c
+new file mode 100644
+index 0000000..ab65de0
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mmu.c
+@@ -0,0 +1,598 @@
++/*
++ * hw_mmu.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== hw_mmu.c ========
++ *  Description:
++ *      API definitions to setup MMU TLB and PTE
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb  TLBAdd and TLBFlush input the page size in bytes instead
++                  of an enum. TLBAdd inputs mapping attributes struct instead
++                  of individual arguments.
++                  Removed MMU.h and other cosmetic updates.
++ *! 08-Mar-2004 sb  Added the Page Table Management APIs
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#include <GlobalTypes.h>
++#include "MMURegAcM.h"
++#include <hw_defs.h>
++#include <hw_mmu.h>
++#include <linux/types.h>
++
++#define MMU_BASE_VAL_MASK     0xFC00
++#define MMU_PAGE_MAX       3
++#define MMU_ELEMENTSIZE_MAX      3
++#define MMU_ADDR_MASK     0xFFFFF000
++#define MMU_TTB_MASK       0xFFFFC000
++#define MMU_SECTION_ADDR_MASK    0xFFF00000
++#define MMU_SSECTION_ADDR_MASK   0xFF000000
++#define MMU_PAGE_TABLE_MASK      0xFFFFFC00
++#define MMU_LARGE_PAGE_MASK      0xFFFF0000
++#define MMU_SMALL_PAGE_MASK      0xFFFFF000
++
++#define MMU_LOAD_TLB  0x00000001
++
++/* HW_MMUPageSize_t:  Enumerated Type used to specify the MMU Page Size(SLSS) */
++enum HW_MMUPageSize_t {
++    HW_MMU_SECTION,
++    HW_MMU_LARGE_PAGE,
++    HW_MMU_SMALL_PAGE,
++    HW_MMU_SUPERSECTION
++} ;
++
++/*
++* FUNCTION          : MMU_FlushEntry
++*
++* INPUTS:
++*
++*       Identifier      : baseAddress
++*       Type          : const u32
++*       Description     : Base Address of instance of MMU module
++*
++* RETURNS:
++*
++*       Type          : HW_STATUS
++*       Description     : RET_OK               -- No errors occured
++*                      RET_BAD_NULL_PARAM     -- A Pointer
++*                                             Paramater was set to NULL
++*
++* PURPOSE:          : Flush the TLB entry pointed by the
++*                     lock counter register
++*                     even if this entry is set protected
++*
++* METHOD:            : Check the Input parameter and Flush a
++*                      single entry in the TLB.
++*/
++static HW_STATUS MMU_FlushEntry(const u32 baseAddress);
++
++/*
++* FUNCTION          : MMU_SetCAMEntry
++*
++* INPUTS:
++*
++*       Identifier      : baseAddress
++*       TypE          : const u32
++*       Description     : Base Address of instance of MMU module
++*
++*       Identifier      : pageSize
++*       TypE          : const u32
++*       Description     : It indicates the page size
++*
++*       Identifier      : preservedBit
++*       Type          : const u32
++*       Description     : It indicates the TLB entry is preserved entry
++*                                                     or not
++*
++*       Identifier      : validBit
++*       Type          : const u32
++*       Description     : It indicates the TLB entry is valid entry or not
++*
++*
++*       Identifier      : virtualAddrTag
++*       Type          : const u32
++*       Description     : virtual Address
++*
++* RETURNS:
++*
++*       Type          : HW_STATUS
++*       Description     : RET_OK               -- No errors occured
++*                      RET_BAD_NULL_PARAM     -- A Pointer Paramater
++*                                                was set to NULL
++*                      RET_PARAM_OUT_OF_RANGE -- Input Parameter out
++*                                                of Range
++*
++* PURPOSE:            : Set MMU_CAM reg
++*
++* METHOD:             : Check the Input parameters and set the CAM entry.
++*/
++static HW_STATUS MMU_SetCAMEntry(const u32    baseAddress,
++                                 const u32    pageSize,
++                                 const u32    preservedBit,
++                                 const u32    validBit,
++                                 const u32    virtualAddrTag);
++
++/*
++* FUNCTION          : MMU_SetRAMEntry
++*
++* INPUTS:
++*
++*       Identifier      : baseAddress
++*       Type          : const u32
++*       Description     : Base Address of instance of MMU module
++*
++*       Identifier      : physicalAddr
++*       Type          : const u32
++*       Description     : Physical Address to which the corresponding
++*                      virtual   Address shouldpoint
++*
++*       Identifier      : endianism
++*       Type          : HW_Endianism_t
++*       Description     : endianism for the given page
++*
++*       Identifier      : elementSize
++*       Type          : HW_ElementSize_t
++*       Description     : The element size ( 8,16, 32 or 64 bit)
++*
++*       Identifier      : mixedSize
++*       Type          : HW_MMUMixedSize_t
++*       Description     : Element Size to follow CPU or TLB
++*
++* RETURNS:
++*
++*       Type          : HW_STATUS
++*       Description     : RET_OK               -- No errors occured
++*                      RET_BAD_NULL_PARAM     -- A Pointer Paramater
++*                                                     was set to NULL
++*                      RET_PARAM_OUT_OF_RANGE -- Input Parameter
++*                                                     out of Range
++*
++* PURPOSE:          : Set MMU_CAM reg
++*
++* METHOD:            : Check the Input parameters and set the RAM entry.
++*/
++static HW_STATUS MMU_SetRAMEntry(const u32    baseAddress,
++                                 const u32    physicalAddr,
++                                 enum HW_Endianism_t      endianism,
++                                 enum HW_ElementSize_t    elementSize,
++                                 enum HW_MMUMixedSize_t   mixedSize);
++
++/* HW FUNCTIONS */
++
++HW_STATUS HW_MMU_Enable(const u32 baseAddress)
++{
++    HW_STATUS status = RET_OK;
++
++    MMUMMU_CNTLMMUEnableWrite32(baseAddress, HW_SET);
++
++    return status;
++}
++
++HW_STATUS HW_MMU_Disable(const u32 baseAddress)
++{
++    HW_STATUS status = RET_OK;
++
++    MMUMMU_CNTLMMUEnableWrite32(baseAddress, HW_CLEAR);
++
++    return status;
++}
++
++HW_STATUS HW_MMU_NumLockedSet(const u32 baseAddress,
++                              u32 numLockedEntries)
++{
++    HW_STATUS status = RET_OK;
++
++    MMUMMU_LOCKBaseValueWrite32(baseAddress, numLockedEntries);
++
++    return status;
++}
++
++HW_STATUS HW_MMU_VictimNumSet(const u32 baseAddress,
++                              u32 victimEntryNum)
++{
++    HW_STATUS status = RET_OK;
++
++    MMUMMU_LOCKCurrentVictimWrite32(baseAddress, victimEntryNum);
++
++    return status;
++}
++
++HW_STATUS HW_MMU_EventAck(const u32 baseAddress, u32 irqMask)
++{
++    HW_STATUS status = RET_OK;
++
++    MMUMMU_IRQSTATUSWriteRegister32(baseAddress, irqMask);
++
++    return status;
++}
++
++HW_STATUS HW_MMU_EventDisable(const u32 baseAddress,
++                              u32 irqMask)
++{
++    HW_STATUS status = RET_OK;
++    u32 irqReg;
++
++    irqReg = MMUMMU_IRQENABLEReadRegister32(baseAddress);
++
++    MMUMMU_IRQENABLEWriteRegister32(baseAddress, irqReg & ~irqMask);
++
++    return status;
++}
++
++HW_STATUS HW_MMU_EventEnable(const u32 baseAddress, u32 irqMask)
++{
++    HW_STATUS status = RET_OK;
++    u32 irqReg;
++
++    irqReg = MMUMMU_IRQENABLEReadRegister32(baseAddress);
++
++    MMUMMU_IRQENABLEWriteRegister32(baseAddress, irqReg | irqMask);
++
++    return status;
++}
++
++
++HW_STATUS HW_MMU_EventStatus(const u32 baseAddress, u32 *irqMask)
++{
++    HW_STATUS status = RET_OK;
++
++    *irqMask = MMUMMU_IRQSTATUSReadRegister32(baseAddress);
++
++    return status;
++}
++
++
++HW_STATUS HW_MMU_FaultAddrRead(const u32 baseAddress, u32 *addr)
++{
++    HW_STATUS status = RET_OK;
++
++    /*Check the input Parameters*/
++    CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++                    RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++    /* read values from register */
++    *addr = MMUMMU_FAULT_ADReadRegister32(baseAddress);
++
++    return status;
++}
++
++HW_STATUS HW_MMU_TTBSet(const u32 baseAddress, u32 TTBPhysAddr)
++{
++    HW_STATUS status = RET_OK;
++    u32 loadTTB;
++
++   /*Check the input Parameters*/
++   CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++                   RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++   loadTTB = TTBPhysAddr & ~0x7FUL;
++   /* write values to register */
++   MMUMMU_TTBWriteRegister32(baseAddress, loadTTB);
++
++   return status;
++}
++
++HW_STATUS HW_MMU_TWLEnable(const u32 baseAddress)
++{
++    HW_STATUS status = RET_OK;
++
++    MMUMMU_CNTLTWLEnableWrite32(baseAddress, HW_SET);
++
++    return status;
++}
++
++HW_STATUS HW_MMU_TWLDisable(const u32 baseAddress)
++{
++    HW_STATUS status = RET_OK;
++
++    MMUMMU_CNTLTWLEnableWrite32(baseAddress, HW_CLEAR);
++
++    return status;
++}
++
++HW_STATUS HW_MMU_TLBFlush(const u32 baseAddress, u32 virtualAddr,
++                           u32 pageSize)
++{
++    HW_STATUS status = RET_OK;
++    u32 virtualAddrTag;
++    enum HW_MMUPageSize_t pgSizeBits;
++
++    switch (pageSize) {
++    case HW_PAGE_SIZE_4KB:
++      pgSizeBits = HW_MMU_SMALL_PAGE;
++      break;
++
++    case HW_PAGE_SIZE_64KB:
++      pgSizeBits = HW_MMU_LARGE_PAGE;
++      break;
++
++    case HW_PAGE_SIZE_1MB:
++      pgSizeBits = HW_MMU_SECTION;
++      break;
++
++    case HW_PAGE_SIZE_16MB:
++      pgSizeBits = HW_MMU_SUPERSECTION;
++      break;
++
++    default:
++      return RET_FAIL;
++    }
++
++    /* Generate the 20-bit tag from virtual address */
++    virtualAddrTag = ((virtualAddr & MMU_ADDR_MASK) >> 12);
++
++    MMU_SetCAMEntry(baseAddress, pgSizeBits, 0, 0, virtualAddrTag);
++
++    MMU_FlushEntry(baseAddress);
++
++    return status;
++}
++
++HW_STATUS HW_MMU_TLBAdd(const u32     baseAddress,
++                         u32        physicalAddr,
++                         u32        virtualAddr,
++                         u32        pageSize,
++                         u32        entryNum,
++                         struct HW_MMUMapAttrs_t    *mapAttrs,
++                         enum HW_SetClear_t       preservedBit,
++                         enum HW_SetClear_t       validBit)
++{
++    HW_STATUS  status = RET_OK;
++    u32 lockReg;
++    u32 virtualAddrTag;
++    enum HW_MMUPageSize_t mmuPgSize;
++
++    /*Check the input Parameters*/
++    CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++                    RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++    CHECK_INPUT_RANGE_MIN0(pageSize, MMU_PAGE_MAX, RET_PARAM_OUT_OF_RANGE,
++                         RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++    CHECK_INPUT_RANGE_MIN0(mapAttrs->elementSize, MMU_ELEMENTSIZE_MAX,
++                      RET_PARAM_OUT_OF_RANGE, RES_MMU_BASE +
++                      RES_INVALID_INPUT_PARAM);
++
++    switch (pageSize) {
++    case HW_PAGE_SIZE_4KB:
++      mmuPgSize = HW_MMU_SMALL_PAGE;
++      break;
++
++    case HW_PAGE_SIZE_64KB:
++      mmuPgSize = HW_MMU_LARGE_PAGE;
++      break;
++
++    case HW_PAGE_SIZE_1MB:
++      mmuPgSize = HW_MMU_SECTION;
++      break;
++
++    case HW_PAGE_SIZE_16MB:
++      mmuPgSize = HW_MMU_SUPERSECTION;
++      break;
++
++    default:
++      return RET_FAIL;
++    }
++
++    lockReg = MMUMMU_LOCKReadRegister32(baseAddress);
++
++    /* Generate the 20-bit tag from virtual address */
++    virtualAddrTag = ((virtualAddr & MMU_ADDR_MASK) >> 12);
++
++    /* Write the fields in the CAM Entry Register */
++    MMU_SetCAMEntry(baseAddress,  mmuPgSize, preservedBit, validBit,
++                  virtualAddrTag);
++
++    /* Write the different fields of the RAM Entry Register */
++    /* endianism of the page,Element Size of the page (8, 16, 32, 64 bit)*/
++    MMU_SetRAMEntry(baseAddress, physicalAddr, mapAttrs->endianism,
++                  mapAttrs->elementSize, mapAttrs->mixedSize);
++
++    /* Update the MMU Lock Register */
++    /* currentVictim between lockedBaseValue and (MMU_Entries_Number - 1)*/
++    MMUMMU_LOCKCurrentVictimWrite32(baseAddress, entryNum);
++
++    /* Enable loading of an entry in TLB by writing 1
++         into LD_TLB_REG register */
++    MMUMMU_LD_TLBWriteRegister32(baseAddress, MMU_LOAD_TLB);
++
++
++    MMUMMU_LOCKWriteRegister32(baseAddress, lockReg);
++
++    return status;
++}
++
++HW_STATUS HW_MMU_PteSet(const u32     pgTblVa,
++                         u32        physicalAddr,
++                         u32        virtualAddr,
++                         u32        pageSize,
++                         struct HW_MMUMapAttrs_t    *mapAttrs)
++{
++    HW_STATUS status = RET_OK;
++    u32 pteAddr, pteVal;
++    s32 numEntries = 1;
++
++    switch (pageSize) {
++    case HW_PAGE_SIZE_4KB:
++      pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++                                  virtualAddr & MMU_SMALL_PAGE_MASK);
++      pteVal = ((physicalAddr & MMU_SMALL_PAGE_MASK) |
++                  (mapAttrs->endianism << 9) |
++                  (mapAttrs->elementSize << 4) |
++                  (mapAttrs->mixedSize << 11) | 2
++                );
++      break;
++
++    case HW_PAGE_SIZE_64KB:
++      numEntries = 16;
++      pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++                                  virtualAddr & MMU_LARGE_PAGE_MASK);
++      pteVal = ((physicalAddr & MMU_LARGE_PAGE_MASK) |
++                  (mapAttrs->endianism << 9) |
++                  (mapAttrs->elementSize << 4) |
++                  (mapAttrs->mixedSize << 11) | 1
++                );
++      break;
++
++    case HW_PAGE_SIZE_1MB:
++      pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++                                  virtualAddr & MMU_SECTION_ADDR_MASK);
++      pteVal = ((((physicalAddr & MMU_SECTION_ADDR_MASK) |
++                   (mapAttrs->endianism << 15) |
++                   (mapAttrs->elementSize << 10) |
++                   (mapAttrs->mixedSize << 17)) &
++                   ~0x40000) | 0x2
++               );
++      break;
++
++    case HW_PAGE_SIZE_16MB:
++      numEntries = 16;
++      pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++                                  virtualAddr & MMU_SSECTION_ADDR_MASK);
++      pteVal = (((physicalAddr & MMU_SSECTION_ADDR_MASK) |
++                    (mapAttrs->endianism << 15) |
++                    (mapAttrs->elementSize << 10) |
++                    (mapAttrs->mixedSize << 17)
++                  ) | 0x40000 | 0x2
++                );
++      break;
++
++    case HW_MMU_COARSE_PAGE_SIZE:
++      pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++                                  virtualAddr & MMU_SECTION_ADDR_MASK);
++      pteVal = (physicalAddr & MMU_PAGE_TABLE_MASK) | 1;
++      break;
++
++    default:
++      return RET_FAIL;
++    }
++
++    while (--numEntries >= 0)
++      ((u32 *)pteAddr)[numEntries] = pteVal;
++
++    return status;
++}
++
++HW_STATUS HW_MMU_PteClear(const u32  pgTblVa,
++                           u32        virtualAddr,
++                           u32        pgSize)
++{
++    HW_STATUS status = RET_OK;
++    u32 pteAddr;
++    s32 numEntries = 1;
++
++    switch (pgSize) {
++    case HW_PAGE_SIZE_4KB:
++      pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++                                  virtualAddr & MMU_SMALL_PAGE_MASK);
++      break;
++
++    case HW_PAGE_SIZE_64KB:
++      numEntries = 16;
++      pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++                                  virtualAddr & MMU_LARGE_PAGE_MASK);
++      break;
++
++    case HW_PAGE_SIZE_1MB:
++    case HW_MMU_COARSE_PAGE_SIZE:
++      pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++                                  virtualAddr & MMU_SECTION_ADDR_MASK);
++      break;
++
++    case HW_PAGE_SIZE_16MB:
++      numEntries = 16;
++      pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++                                  virtualAddr & MMU_SSECTION_ADDR_MASK);
++      break;
++
++    default:
++      return RET_FAIL;
++    }
++
++    while (--numEntries >= 0)
++      ((u32 *)pteAddr)[numEntries] = 0;
++
++    return status;
++}
++
++/* MMU_FlushEntry */
++static HW_STATUS MMU_FlushEntry(const u32 baseAddress)
++{
++   HW_STATUS status = RET_OK;
++   u32 flushEntryData = 0x1;
++
++   /*Check the input Parameters*/
++   CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++                   RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++   /* write values to register */
++   MMUMMU_FLUSH_ENTRYWriteRegister32(baseAddress, flushEntryData);
++
++   return status;
++}
++
++/* MMU_SetCAMEntry */
++static HW_STATUS MMU_SetCAMEntry(const u32    baseAddress,
++                                 const u32    pageSize,
++                                 const u32    preservedBit,
++                                 const u32    validBit,
++                                 const u32    virtualAddrTag)
++{
++   HW_STATUS status = RET_OK;
++   u32 mmuCamReg;
++
++   /*Check the input Parameters*/
++   CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++                   RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++   mmuCamReg = (virtualAddrTag << 12);
++   mmuCamReg = (mmuCamReg) | (pageSize) |  (validBit << 2) |
++             (preservedBit << 3) ;
++
++   /* write values to register */
++   MMUMMU_CAMWriteRegister32(baseAddress, mmuCamReg);
++
++   return status;
++}
++
++/* MMU_SetRAMEntry */
++static HW_STATUS MMU_SetRAMEntry(const u32       baseAddress,
++                                 const u32       physicalAddr,
++                                 enum HW_Endianism_t     endianism,
++                                 enum HW_ElementSize_t   elementSize,
++                                 enum HW_MMUMixedSize_t  mixedSize)
++{
++   HW_STATUS status = RET_OK;
++   u32 mmuRamReg;
++
++   /*Check the input Parameters*/
++   CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++                   RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++   CHECK_INPUT_RANGE_MIN0(elementSize, MMU_ELEMENTSIZE_MAX,
++                 RET_PARAM_OUT_OF_RANGE, RES_MMU_BASE +
++                 RES_INVALID_INPUT_PARAM);
++
++
++   mmuRamReg = (physicalAddr & MMU_ADDR_MASK);
++   mmuRamReg = (mmuRamReg) | ((endianism << 9) |  (elementSize << 7) |
++             (mixedSize << 6));
++
++   /* write values to register */
++   MMUMMU_RAMWriteRegister32(baseAddress, mmuRamReg);
++
++   return status;
++
++}
+diff --git a/drivers/dsp/bridge/hw/hw_mmu.h b/drivers/dsp/bridge/hw/hw_mmu.h
+new file mode 100644
+index 0000000..a3dd2a8
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mmu.h
+@@ -0,0 +1,177 @@
++/*
++ * hw_mmu.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== hw_mmu.h ========
++ *  Description:
++ *      MMU types and API declarations
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb  Moved & renamed endianness, page size, element size
++                  TLBAdd takes in MMUMapAttrs instead of separate arguments
++ *! 08-Mar-2004 sb  Added the Page Table management APIs
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __HW_MMU_H
++#define __HW_MMU_H
++
++#include <linux/types.h>
++
++/* Bitmasks for interrupt sources */
++#define HW_MMU_TRANSLATION_FAULT   0x2
++#define HW_MMU_ALL_INTERRUPTS      0x1F
++
++#define HW_MMU_COARSE_PAGE_SIZE 0x400
++
++/* HW_MMUMixedSize_t:  Enumerated Type used to specify whether to follow
++                      CPU/TLB Element size */
++enum HW_MMUMixedSize_t {
++      HW_MMU_TLBES,
++      HW_MMU_CPUES
++
++} ;
++
++/* HW_MMUMapAttrs_t:  Struct containing MMU mapping attributes */
++struct HW_MMUMapAttrs_t {
++      enum HW_Endianism_t     endianism;
++      enum HW_ElementSize_t   elementSize;
++      enum HW_MMUMixedSize_t  mixedSize;
++      bool donotlockmpupage;
++} ;
++
++extern HW_STATUS HW_MMU_Enable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_Disable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_NumLockedSet(const u32 baseAddress,
++                                      u32 numLockedEntries);
++
++extern HW_STATUS HW_MMU_VictimNumSet(const u32 baseAddress,
++                                      u32 victimEntryNum);
++
++/* For MMU faults */
++extern HW_STATUS HW_MMU_EventAck(const u32 baseAddress,
++                                  u32 irqMask);
++
++extern HW_STATUS HW_MMU_EventDisable(const u32 baseAddress,
++                                      u32 irqMask);
++
++extern HW_STATUS HW_MMU_EventEnable(const u32 baseAddress,
++                                     u32 irqMask);
++
++extern HW_STATUS HW_MMU_EventStatus(const u32 baseAddress,
++                                     u32 *irqMask);
++
++extern HW_STATUS HW_MMU_FaultAddrRead(const u32 baseAddress,
++                                       u32 *addr);
++
++/* Set the TT base address */
++extern HW_STATUS HW_MMU_TTBSet(const u32 baseAddress,
++                                u32 TTBPhysAddr);
++
++extern HW_STATUS HW_MMU_TWLEnable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_TWLDisable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_TLBFlush(const u32 baseAddress,
++                                  u32 virtualAddr,
++                                  u32 pageSize);
++
++extern HW_STATUS HW_MMU_TLBAdd(const u32     baseAddress,
++                                u32      physicalAddr,
++                                u32      virtualAddr,
++                                u32      pageSize,
++                                u32       entryNum,
++                                struct HW_MMUMapAttrs_t *mapAttrs,
++                                enum HW_SetClear_t    preservedBit,
++                                enum HW_SetClear_t    validBit);
++
++
++/* For PTEs */
++extern HW_STATUS HW_MMU_PteSet(const u32     pgTblVa,
++                                u32      physicalAddr,
++                                u32      virtualAddr,
++                                u32      pageSize,
++                                struct HW_MMUMapAttrs_t *mapAttrs);
++
++extern HW_STATUS HW_MMU_PteClear(const u32   pgTblVa,
++                                  u32  pgSize,
++                                  u32  virtualAddr);
++
++static inline u32 HW_MMU_PteAddrL1(u32 L1_base, u32 va)
++{
++      u32 pteAddr;
++      u32 VA_31_to_20;
++
++      VA_31_to_20  = va >> (20 - 2); /* Left-shift by 2 here itself */
++      VA_31_to_20 &= 0xFFFFFFFCUL;
++      pteAddr = L1_base + VA_31_to_20;
++
++      return pteAddr;
++}
++
++static inline u32 HW_MMU_PteAddrL2(u32 L2_base, u32 va)
++{
++      u32 pteAddr;
++
++      pteAddr = (L2_base & 0xFFFFFC00) | ((va >> 10) & 0x3FC);
++
++      return pteAddr;
++}
++
++static inline u32 HW_MMU_PteCoarseL1(u32 pteVal)
++{
++      u32 pteCoarse;
++
++      pteCoarse = pteVal & 0xFFFFFC00;
++
++      return pteCoarse;
++}
++
++static inline u32 HW_MMU_PteSizeL1(u32 pteVal)
++{
++      u32 pteSize = 0;
++
++      if ((pteVal & 0x3) == 0x1) {
++              /* Points to L2 PT */
++              pteSize = HW_MMU_COARSE_PAGE_SIZE;
++      }
++
++      if ((pteVal & 0x3) == 0x2) {
++              if (pteVal & (1 << 18))
++                      pteSize = HW_PAGE_SIZE_16MB;
++              else
++                      pteSize = HW_PAGE_SIZE_1MB;
++      }
++
++      return pteSize;
++}
++
++static inline u32 HW_MMU_PteSizeL2(u32 pteVal)
++{
++    u32 pteSize = 0;
++
++    if (pteVal & 0x2)
++      pteSize = HW_PAGE_SIZE_4KB;
++    else if (pteVal & 0x1)
++      pteSize = HW_PAGE_SIZE_64KB;
++
++    return pteSize;
++}
++
++#endif  /* __HW_MMU_H */
+diff --git a/drivers/dsp/bridge/hw/hw_prcm.c b/drivers/dsp/bridge/hw/hw_prcm.c
+new file mode 100644
+index 0000000..61ff08f
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_prcm.c
+@@ -0,0 +1,167 @@
++/*
++ * hw_prcm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== hw_prcm.c ========
++ *  Description:
++ *      API definitions to configure PRCM (Power, Reset & Clocks Manager)
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#include <GlobalTypes.h>
++#include "PRCMRegAcM.h"
++#include <hw_defs.h>
++#include <hw_prcm.h>
++
++static HW_STATUS HW_RST_WriteVal(const u32 baseAddress,
++                                  enum HW_RstModule_t r,
++                                  enum HW_SetClear_t val);
++
++HW_STATUS HW_RST_Reset(const u32 baseAddress, enum HW_RstModule_t r)
++{
++      return HW_RST_WriteVal(baseAddress, r, HW_SET);
++}
++
++HW_STATUS HW_RST_UnReset(const u32 baseAddress, enum HW_RstModule_t r)
++{
++      return HW_RST_WriteVal(baseAddress, r, HW_CLEAR);
++}
++
++static HW_STATUS HW_RST_WriteVal(const u32 baseAddress,
++                                  enum HW_RstModule_t r,
++                                  enum HW_SetClear_t val)
++{
++      HW_STATUS status = RET_OK;
++
++      switch (r) {
++      case HW_RST1_IVA2:
++          PRM_RSTCTRL_IVA2RST1_DSPWrite32(baseAddress, val);
++          break;
++      case HW_RST2_IVA2:
++          PRM_RSTCTRL_IVA2RST2_DSPWrite32(baseAddress, val);
++          break;
++      case HW_RST3_IVA2:
++          PRM_RSTCTRL_IVA2RST3_DSPWrite32(baseAddress, val);
++          break;
++      default:
++          status = RET_FAIL;
++          break;
++      }
++      return status;
++}
++
++HW_STATUS HW_PWR_IVA2StateGet(const u32 baseAddress, enum HW_PwrModule_t p,
++                              enum HW_PwrState_t *value)
++{
++      HW_STATUS status = RET_OK;
++      u32 temp;
++
++      switch (p) {
++      case HW_PWR_DOMAIN_DSP:
++              /* wait until Transition is complete */
++              do {
++                      /* mdelay(1); */
++                      temp = PRCMPM_PWSTST_IVA2InTransitionRead32
++                              (baseAddress);
++
++              } while (temp);
++
++              temp = PRCMPM_PWSTST_IVA2ReadRegister32(baseAddress);
++              *value = PRCMPM_PWSTST_IVA2PowerStateStGet32(temp);
++              break;
++
++      default:
++              status = RET_FAIL;
++              break;
++      }
++      return status;
++}
++
++HW_STATUS HW_PWRST_IVA2RegGet(const u32 baseAddress, u32 *value)
++{
++      HW_STATUS status = RET_OK;
++
++      *value = PRCMPM_PWSTST_IVA2ReadRegister32(baseAddress);
++
++      return status;
++}
++
++
++HW_STATUS HW_PWR_IVA2PowerStateSet(const u32 baseAddress,
++                                   enum HW_PwrModule_t p,
++                                   enum HW_PwrState_t value)
++{
++      HW_STATUS status = RET_OK;
++
++      switch (p) {
++      case HW_PWR_DOMAIN_DSP:
++              switch (value) {
++              case HW_PWR_STATE_ON:
++                      PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32(baseAddress);
++                      break;
++              case HW_PWR_STATE_RET:
++                      PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32(baseAddress);
++                      break;
++              case HW_PWR_STATE_OFF:
++                      PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32(baseAddress);
++                      break;
++              default:
++                      status = RET_FAIL;
++                      break;
++              }
++              break;
++
++      default:
++              status = RET_FAIL;
++              break;
++      }
++
++      return status;
++}
++
++HW_STATUS HW_PWR_CLKCTRL_IVA2RegSet(const u32 baseAddress,
++                                    enum HW_TransitionState_t val)
++{
++      HW_STATUS status = RET_OK;
++
++      PRCMCM_CLKSTCTRL_IVA2WriteRegister32(baseAddress, val);
++
++      return status;
++
++}
++
++HW_STATUS HW_RSTST_RegGet(const u32 baseAddress, enum HW_RstModule_t m,
++                          u32 *value)
++{
++      HW_STATUS status = RET_OK;
++
++      *value = PRCMRM_RSTST_DSPReadRegister32(baseAddress);
++
++      return status;
++}
++
++HW_STATUS HW_RSTCTRL_RegGet(const u32 baseAddress, enum HW_RstModule_t m,
++                            u32 *value)
++{
++      HW_STATUS status = RET_OK;
++
++      *value = PRCMRM_RSTCTRL_DSPReadRegister32(baseAddress);
++
++      return status;
++}
+diff --git a/drivers/dsp/bridge/hw/hw_prcm.h b/drivers/dsp/bridge/hw/hw_prcm.h
+new file mode 100644
+index 0000000..928486c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_prcm.h
+@@ -0,0 +1,168 @@
++/*
++ * hw_prcm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== hw_prcm.h ========
++ *  Description:
++ *      PRCM types and API declarations
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#ifndef __HW_PRCM_H
++#define __HW_PRCM_H
++
++/* HW_ClkModule:  Enumerated Type used to specify the clock domain */
++
++enum HW_ClkModule_t {
++/* DSP Domain */
++    HW_CLK_DSP_CPU,
++    HW_CLK_DSP_IPI_MMU,
++    HW_CLK_IVA_ARM,
++    HW_CLK_IVA_COP,   /* IVA Coprocessor */
++
++/* Core Domain */
++    HW_CLK_FN_WDT4,   /* Functional Clock */
++    HW_CLK_FN_WDT3,
++    HW_CLK_FN_UART2,
++    HW_CLK_FN_UART1,
++    HW_CLK_GPT5,
++    HW_CLK_GPT6,
++    HW_CLK_GPT7,
++    HW_CLK_GPT8,
++
++    HW_CLK_IF_WDT4,   /* Interface Clock */
++    HW_CLK_IF_WDT3,
++    HW_CLK_IF_UART2,
++    HW_CLK_IF_UART1,
++    HW_CLK_IF_MBOX
++
++} ;
++
++enum HW_ClkSubsys_t {
++    HW_CLK_DSPSS,
++    HW_CLK_IVASS
++} ;
++
++/* HW_GPtimers:  General purpose timers */
++enum HW_GPtimer_t {
++    HW_GPT5 = 5,
++    HW_GPT6 = 6,
++    HW_GPT7 = 7,
++    HW_GPT8 = 8
++} ;
++
++
++/* GP timers Input clock type:  General purpose timers */
++enum HW_Clocktype_t {
++    HW_CLK_32KHz = 0,
++    HW_CLK_SYS   = 1,
++    HW_CLK_EXT   = 2
++} ;
++
++/* HW_ClkDiv:  Clock divisors */
++enum HW_ClkDiv_t {
++    HW_CLK_DIV_1 = 0x1,
++    HW_CLK_DIV_2 = 0x2,
++    HW_CLK_DIV_3 = 0x3,
++    HW_CLK_DIV_4 = 0x4,
++    HW_CLK_DIV_6 = 0x6,
++    HW_CLK_DIV_8 = 0x8,
++    HW_CLK_DIV_12 = 0xC
++} ;
++
++/* HW_RstModule:  Enumerated Type used to specify the module to be reset */
++enum HW_RstModule_t {
++    HW_RST1_IVA2,  /* Reset the DSP */
++    HW_RST2_IVA2,  /* Reset MMU and LEON HWa */
++    HW_RST3_IVA2   /* Reset LEON sequencer */
++} ;
++
++/* HW_PwrModule:  Enumerated Type used to specify the power domain */
++enum HW_PwrModule_t {
++/* Domains */
++    HW_PWR_DOMAIN_CORE,
++    HW_PWR_DOMAIN_MPU,
++    HW_PWR_DOMAIN_WAKEUP,
++    HW_PWR_DOMAIN_DSP,
++
++/* Sub-domains */
++    HW_PWR_DSP_IPI,   /* IPI = Intrusive Port Interface */
++    HW_PWR_IVA_ISP     /* ISP = Intrusive Slave Port */
++} ;
++
++enum HW_PwrState_t {
++    HW_PWR_STATE_OFF,
++    HW_PWR_STATE_RET,
++    HW_PWR_STATE_INACT,
++    HW_PWR_STATE_ON = 3
++} ;
++
++enum HW_ForceState_t {
++    HW_FORCE_OFF,
++    HW_FORCE_ON
++} ;
++
++enum HW_IdleState_t {
++    HW_ACTIVE,
++    HW_STANDBY
++
++} ;
++
++enum HW_TransitionState_t {
++    HW_AUTOTRANS_DIS,
++    HW_SW_SUP_SLEEP,
++    HW_SW_SUP_WAKEUP,
++    HW_AUTOTRANS_EN
++} ;
++
++
++extern HW_STATUS HW_RST_Reset(const u32 baseAddress,
++                               enum HW_RstModule_t r);
++
++extern HW_STATUS HW_RST_UnReset(const u32 baseAddress,
++                                 enum HW_RstModule_t r);
++
++extern HW_STATUS HW_RSTCTRL_RegGet(const u32 baseAddress,
++                                           enum HW_RstModule_t p,
++                                           u32 *value);
++extern HW_STATUS HW_RSTST_RegGet(const u32 baseAddress,
++                                         enum HW_RstModule_t p, u32 *value);
++
++extern HW_STATUS HW_PWR_PowerStateSet(const u32 baseAddress,
++                                              enum HW_PwrModule_t p,
++                                              enum HW_PwrState_t value);
++
++extern HW_STATUS HW_CLK_SetInputClock(const u32 baseAddress,
++                                      enum HW_GPtimer_t gpt,
++                                      enum HW_Clocktype_t c);
++
++extern HW_STATUS HW_PWR_IVA2StateGet(const u32 baseAddress,
++                                      enum HW_PwrModule_t p,
++                                      enum HW_PwrState_t *value);
++
++extern HW_STATUS HW_PWRST_IVA2RegGet(const u32 baseAddress, u32 *value);
++
++extern HW_STATUS HW_PWR_IVA2PowerStateSet(const u32 baseAddress,
++                                          enum HW_PwrModule_t p,
++                                          enum HW_PwrState_t value);
++
++extern HW_STATUS HW_PWR_CLKCTRL_IVA2RegSet(const u32 baseAddress,
++                                           enum HW_TransitionState_t val);
++
++#endif  /* __HW_PRCM_H */
+diff --git a/drivers/dsp/bridge/pmgr/chnl.c b/drivers/dsp/bridge/pmgr/chnl.c
+new file mode 100644
+index 0000000..6b5a0d9
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/chnl.c
+@@ -0,0 +1,260 @@
++/*
++ * chnl.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== chnl.c ========
++ *  Description:
++ *      WCD channel interface: multiplexes data streams through the single
++ *      physical link managed by a 'Bridge mini-driver.
++ *
++ *  Public Functions:
++ *      CHNL_Close
++ *      CHNL_CloseOrphans
++ *      CHNL_Create
++ *      CHNL_Destroy
++ *      CHNL_Exit
++ *      CHNL_GetHandle
++ *      CHNL_GetProcessHandle
++ *      CHNL_Init
++ *      CHNL_Open
++ *
++ *  Notes:
++ *      This interface is basically a pass through to the WMD CHNL functions,
++ *      except for the CHNL_Get() accessor functions which call
++ *      WMD_CHNL_GetInfo().
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 07-Jan-2002 ag  CHNL_CloseOrphans() now closes supported # of channels.
++ *! 17-Nov-2000 jeh Removed IRQ, shared memory stuff from CHNL_Create.
++ *! 28-Feb-2000 rr: New GT USage Implementation
++ *! 03-Feb-2000 rr: GT and Module init/exit Changes.(Done up front from
++ *!               SERVICES)
++ *! 21-Jan-2000 ag: Added code review comments.
++ *! 13-Jan-2000 rr: CFG_Get/SetPrivateDword renamed to CFG_Get/SetDevObject.
++ *! 08-Dec-1999 ag: CHNL_[Alloc|Free]Buffer bufs taken from client process heap.
++ *! 02-Dec-1999 ag: Implemented CHNL_GetEventHandle().
++ *! 17-Nov-1999 ag: CHNL_AllocBuffer() allocs extra word for process mapping.
++ *! 28-Oct-1999 ag: WinCE port. Search for "WinCE" for changes(TBR).
++ *! 07-Jan-1998 gp: CHNL_[Alloc|Free]Buffer now call MEM_UMB functions.
++ *! 22-Oct-1997 gp: Removed requirement in CHNL_Open that hReserved1 != NULL.
++ *! 30-Aug-1997 cr: Renamed cfg.h wbwcd.h b/c of WINNT file name collision.
++ *! 10-Mar-1997 gp: Added GT trace.
++ *! 14-Jan-1997 gp: Updated based on code review feedback.
++ *! 03-Jan-1997 gp: Moved CHNL_AllocBuffer/CHNL_FreeBuffer code from udspsys.
++ *! 14-Dec-1996 gp: Added uChnlId parameter to CHNL_Open().
++ *! 09-Sep-1996 gp: Added CHNL_GetProcessHandle().
++ *! 15-Jul-1996 gp: Created.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/proc.h>
++#include <dspbridge/dev.h>
++
++/*  ----------------------------------- Others */
++#include <dspbridge/chnlpriv.h>
++#include <chnlobj.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/chnl.h>
++
++/*  ----------------------------------- Globals */
++static u32 cRefs;
++#if GT_TRACE
++static struct GT_Mask CHNL_DebugMask = { NULL, NULL };        /* WCD CHNL Mask */
++#endif
++
++
++
++/*
++ *  ======== CHNL_Create ========
++ *  Purpose:
++ *      Create a channel manager object, responsible for opening new channels
++ *      and closing old ones for a given 'Bridge board.
++ */
++DSP_STATUS CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++                     struct DEV_OBJECT *hDevObject,
++                     IN CONST struct CHNL_MGRATTRS *pMgrAttrs)
++{
++      DSP_STATUS status;
++      struct CHNL_MGR *hChnlMgr;
++      struct CHNL_MGR_ *pChnlMgr = NULL;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phChnlMgr != NULL);
++      DBC_Require(pMgrAttrs != NULL);
++
++      GT_3trace(CHNL_DebugMask, GT_ENTER,
++                "Entered CHNL_Create: phChnlMgr: 0x%x\t"
++                "hDevObject: 0x%x\tpMgrAttrs:0x%x\n",
++                phChnlMgr, hDevObject, pMgrAttrs);
++
++      *phChnlMgr = NULL;
++
++      /* Validate args: */
++      if ((0 < pMgrAttrs->cChannels) &&
++         (pMgrAttrs->cChannels <= CHNL_MAXCHANNELS)) {
++              status = DSP_SOK;
++      } else if (pMgrAttrs->cChannels == 0) {
++              status = DSP_EINVALIDARG;
++              GT_0trace(CHNL_DebugMask, GT_7CLASS,
++                        "CHNL_Create:Invalid Args\n");
++      } else {
++              status = CHNL_E_MAXCHANNELS;
++              GT_0trace(CHNL_DebugMask, GT_7CLASS,
++                        "CHNL_Create:Error Max Channels\n");
++      }
++      if (pMgrAttrs->uWordSize == 0) {
++              status = CHNL_E_INVALIDWORDSIZE;
++              GT_0trace(CHNL_DebugMask, GT_7CLASS,
++                        "CHNL_Create:Invalid Word size\n");
++      }
++      if (DSP_SUCCEEDED(status)) {
++              status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
++              if (DSP_SUCCEEDED(status) && hChnlMgr != NULL)
++                      status = CHNL_E_MGREXISTS;
++
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              struct WMD_DRV_INTERFACE *pIntfFxns;
++              DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++              /* Let WMD channel module finish the create: */
++              status = (*pIntfFxns->pfnChnlCreate)(&hChnlMgr, hDevObject,
++                        pMgrAttrs);
++              if (DSP_SUCCEEDED(status)) {
++                      /* Fill in WCD channel module's fields of the
++                       * CHNL_MGR structure */
++                      pChnlMgr = (struct CHNL_MGR_ *)hChnlMgr;
++                      pChnlMgr->pIntfFxns = pIntfFxns;
++                      /* Finally, return the new channel manager handle: */
++                      *phChnlMgr = hChnlMgr;
++                      GT_1trace(CHNL_DebugMask, GT_1CLASS,
++                                "CHNL_Create: Success pChnlMgr:"
++                                "0x%x\n", pChnlMgr);
++              }
++      }
++
++      GT_2trace(CHNL_DebugMask, GT_ENTER,
++                "Exiting CHNL_Create: pChnlMgr: 0x%x,"
++                "status: 0x%x\n", pChnlMgr, status);
++      DBC_Ensure(DSP_FAILED(status) || CHNL_IsValidMgr(pChnlMgr));
++
++      return status;
++}
++
++/*
++ *  ======== CHNL_Destroy ========
++ *  Purpose:
++ *      Close all open channels, and destroy the channel manager.
++ */
++DSP_STATUS CHNL_Destroy(struct CHNL_MGR *hChnlMgr)
++{
++      struct CHNL_MGR_ *pChnlMgr = (struct CHNL_MGR_ *)hChnlMgr;
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      DSP_STATUS status;
++
++      DBC_Require(cRefs > 0);
++
++      GT_1trace(CHNL_DebugMask, GT_ENTER,
++                "Entered CHNL_Destroy: hChnlMgr: 0x%x\n", hChnlMgr);
++      if (CHNL_IsValidMgr(pChnlMgr)) {
++              pIntfFxns = pChnlMgr->pIntfFxns;
++              /* Let WMD channel module destroy the CHNL_MGR: */
++              status = (*pIntfFxns->pfnChnlDestroy)(hChnlMgr);
++      } else {
++              GT_0trace(CHNL_DebugMask, GT_7CLASS,
++                        "CHNL_Destroy:Invalid Handle\n");
++              status = DSP_EHANDLE;
++      }
++
++      GT_2trace(CHNL_DebugMask, GT_ENTER,
++                "Exiting CHNL_Destroy: pChnlMgr: 0x%x,"
++                " status:0x%x\n", pChnlMgr, status);
++      DBC_Ensure(DSP_FAILED(status) || !CHNL_IsValidMgr(pChnlMgr));
++
++      return status;
++}
++
++/*
++ *  ======== CHNL_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the CHNL module.
++ */
++void CHNL_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      cRefs--;
++
++      GT_1trace(CHNL_DebugMask, GT_5CLASS,
++                "Entered CHNL_Exit, ref count: 0x%x\n", cRefs);
++
++      DBC_Ensure(cRefs >= 0);
++}
++
++
++/*
++ *  ======== CHNL_Init ========
++ *  Purpose:
++ *      Initialize the CHNL module's private state.
++ */
++bool CHNL_Init(void)
++{
++      bool fRetval = true;
++
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++              DBC_Assert(!CHNL_DebugMask.flags);
++              GT_create(&CHNL_DebugMask, "CH");   /* "CH" for CHannel */
++      }
++
++      if (fRetval)
++              cRefs++;
++
++      GT_1trace(CHNL_DebugMask, GT_5CLASS,
++                "Entered CHNL_Init, ref count: 0x%x\n",
++                cRefs);
++
++      DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++      return fRetval;
++}
++
++
+diff --git a/drivers/dsp/bridge/pmgr/chnlobj.h b/drivers/dsp/bridge/pmgr/chnlobj.h
+new file mode 100644
+index 0000000..da74c96
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/chnlobj.h
+@@ -0,0 +1,71 @@
++/*
++ * chnlobj.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== chnlobj.h ========
++ *  Description:
++ *      Structure subcomponents of channel class library channel objects which
++ *      are exposed to class driver from mini-driver.
++ *
++ *  Public Functions:
++ *      None.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa   PMGR Code review comments incorporated.
++ *! 17-Nov-2000 jeh     Removed some fields from CHNL_MGR_ to match CHNL_MGR
++ *!                     structure defined in _chnl_sm.h.
++ *! 16-Jan-1997 gp:     Created from chnlpriv.h
++ */
++
++#ifndef CHNLOBJ_
++#define CHNLOBJ_
++
++#include <dspbridge/chnldefs.h>
++#include <dspbridge/wmd.h>
++
++/* Object validateion macros: */
++#define CHNL_IsValidMgr(h) \
++              ((h != NULL) && ((h)->dwSignature == CHNL_MGRSIGNATURE))
++
++#define CHNL_IsValidChnl(h)\
++              ((h != NULL) && ((h)->dwSignature == CHNL_SIGNATURE))
++
++/*
++ *  This struct is the first field in a CHNL_MGR struct, as implemented in
++ *  a WMD channel class library.  Other, implementation specific fields
++ *  follow this structure in memory.
++ */
++struct CHNL_MGR_ {
++      /* These must be the first fields in a CHNL_MGR struct: */
++      u32 dwSignature;        /* Used for object validation.   */
++      struct WMD_DRV_INTERFACE *pIntfFxns;    /* Function interface to WMD. */
++} ;
++
++/*
++ *  This struct is the first field in a CHNL_OBJECT struct, as implemented in
++ *  a WMD channel class library.  Other, implementation specific fields
++ *  follow this structure in memory.
++ */
++struct CHNL_OBJECT_ {
++      /* These must be the first fields in a CHNL_OBJECT struct: */
++      u32 dwSignature;        /* Used for object validation.      */
++      struct CHNL_MGR_ *pChnlMgr;     /* Pointer back to channel manager. */
++} ;
++
++#endif                                /* CHNLOBJ_ */
++
+diff --git a/drivers/dsp/bridge/pmgr/cmm.c b/drivers/dsp/bridge/pmgr/cmm.c
+new file mode 100644
+index 0000000..99a2432
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/cmm.c
+@@ -0,0 +1,1291 @@
++/*
++ * cmm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== cmm.c ========
++ *  Purpose:
++ *      The Communication(Shared) Memory Management(CMM) module provides
++ *      shared memory management services for DSP/BIOS Bridge data streaming
++ *      and messaging.
++ *
++ *      Multiple shared memory segments can be registered with CMM.
++ *      Each registered SM segment is represented by a SM "allocator" that
++ *      describes a block of physically contiguous shared memory used for
++ *      future allocations by CMM.
++ *
++ *      Memory is coelesced back to the appropriate heap when a buffer is
++ *      freed.
++ *
++ *  Public Functions:
++ *      CMM_CallocBuf
++ *      CMM_Create
++ *      CMM_Destroy
++ *      CMM_Exit
++ *      CMM_FreeBuf
++ *      CMM_GetHandle
++ *      CMM_GetInfo
++ *      CMM_Init
++ *      CMM_RegisterGPPSMSeg
++ *      CMM_UnRegisterGPPSMSeg
++ *
++ *      The CMM_Xlator[xxx] routines below are used by Node and Stream
++ *      to perform SM address translation to the client process address space.
++ *      A "translator" object is created by a node/stream for each SM seg used.
++ *
++ *  Translator Routines:
++ *      CMM_XlatorAllocBuf
++ *      CMM_XlatorCreate
++ *      CMM_XlatorDelete
++ *      CMM_XlatorFreeBuf
++ *      CMM_XlatorInfo
++ *      CMM_XlatorTranslate
++ *
++ *  Private Functions:
++ *      AddToFreeList
++ *      GetAllocator
++ *      GetFreeBlock
++ *      GetNode
++ *      GetSlot
++ *      UnRegisterGPPSMSeg
++ *
++ *  Notes:
++ *      Va: Virtual address.
++ *      Pa: Physical or kernel system address.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 16-Feb-2002 ag  Code review cleanup.
++ *!                 PreOMAP address translation no longner supported.
++ *! 30-Jan-2002 ag  Updates to CMM_XlatorTranslate() per TII, ANSI C++
++ *!                 warnings.
++ *! 27-Jan-2002 ag  Removed unused CMM_[Alloc][Free]Desc() & #ifdef USELOOKUP,
++ *!                 & unused VALIDATECMM and VaPaConvert().
++ *!                 Removed bFastXlate from CMM_XLATOR. Always fast lookup.
++ *! 03-Jan-2002 ag  Clear SM in CMM_AllocBuf(). Renamed to CMM_CallocBuf().
++ *! 13-Nov-2001 ag  Now delete pNodeFreeListHead and nodes in CMM_Destroy().
++ *! 28-Aug-2001 ag  CMM_GetHandle() returns CMM Mgr hndle given HPROCESSOR.
++ *!                 Removed unused CMM_[Un]RegisterDSPSMSeg() &
++ *                  CMM_[Un}ReserveVirtSpace fxns. Some cleanup.
++ *! 12-Aug-2001 ag  Exposed CMM_UnRegisterGPP[DSP]SMSeg.
++ *! 13-Feb-2001 kc  DSP/BIOS Bridge name update.
++ *! 21-Dec-2000 rr  GetFreeBlock checks for pAllocator.
++ *! 09-Dec-2000 ag  Added GPPPA2DSPPA, DSPPA2GPPPA macros.
++ *! 05-Dec-2000 ag  CMM_XlatorDelete() optionally frees SM bufs and descriptors.
++ *! 30-Oct-2000 ag  Buf size bug fixed in CMM_AllocBuf() causing leak.
++ *!                 Revamped XlatorTranslate() routine.
++ *! 10-Oct-2000 ag  Added CMM_Xlator[xxx] functions.
++ *! 02-Aug-2000 ag  Created.
++ *!
++ */
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/util.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/proc.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/cmm.h>
++
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++/* Object signatures */
++#define CMMSIGNATURE       0x004d4d43 /* "CMM"   (in reverse) */
++#define SMEMSIGNATURE      0x4D454D53 /* "SMEM"  SM space     */
++#define CMMXLATESIGNATURE  0x584d4d43 /* "CMMX"  CMM Xlator   */
++
++#define NEXT_PA(pNode)   (pNode->dwPA + pNode->ulSize)
++
++/* Other bus/platform translations */
++#define DSPPA2GPPPA(base, x, y)  ((x)+(y))
++#define GPPPA2DSPPA(base, x, y)  ((x)-(y))
++
++/*
++ *  Allocators define a block of contiguous memory used for future allocations.
++ *
++ *      sma - shared memory allocator.
++ *      vma - virtual memory allocator.(not used).
++ */
++struct CMM_ALLOCATOR {        /* sma */
++      u32 dwSignature;        /* SMA allocator signature SMEMSIGNATURE */
++      unsigned int dwSmBase;          /* Start of physical SM block */
++      u32 ulSmSize;           /* Size of SM block in bytes */
++      unsigned int dwVmBase;          /* Start of VM block. (Dev driver
++                               * context for 'sma') */
++      u32 dwDSPPhysAddrOffset;        /* DSP PA to GPP PA offset for this
++                                       * SM space */
++      /* CMM_ADDTO[SUBFROM]DSPPA, _POMAPEMIF2DSPBUS */
++      enum CMM_CNVTTYPE cFactor;
++      unsigned int dwDSPBase; /* DSP virt base byte address */
++      u32 ulDSPSize;  /* DSP seg size in bytes */
++      struct CMM_OBJECT *hCmmMgr;     /* back ref to parent mgr */
++      struct LST_LIST *pFreeListHead; /* node list of available memory */
++      struct LST_LIST *pInUseListHead;        /* node list of memory in use */
++} ;
++
++struct CMM_XLATOR {   /* Pa<->Va translator object */
++      u32 dwSignature;        /* "CMMX" */
++      struct CMM_OBJECT *hCmmMgr;  /* CMM object this translator associated */
++      /*
++       *  Client process virtual base address that corresponds to phys SM
++       *  base address for translator's ulSegId.
++       *  Only 1 segment ID currently supported.
++       */
++      unsigned int dwVirtBase;        /* virtual base address */
++      u32 ulVirtSize; /* size of virt space in bytes */
++      u32 ulSegId;            /* Segment Id */
++} ;
++
++/* CMM Mgr */
++struct CMM_OBJECT {
++      u32 dwSignature;        /* Used for object validation */
++      /*
++       * Cmm Lock is used to serialize access mem manager for multi-threads.
++       */
++      struct SYNC_CSOBJECT *hCmmLock; /* Lock to access cmm mgr */
++      struct LST_LIST *pNodeFreeListHead;     /* Free list of memory nodes */
++      u32 ulMinBlockSize;     /* Min SM block; default 16 bytes */
++      u32 dwPageSize; /* Memory Page size (1k/4k) */
++      /* GPP SM segment ptrs */
++      struct CMM_ALLOCATOR *paGPPSMSegTab[CMM_MAXGPPSEGS];
++} ;
++
++/* Default CMM Mgr attributes */
++static struct CMM_MGRATTRS CMM_DFLTMGRATTRS = {
++      16      /* ulMinBlockSize, min block size(bytes) allocated by cmm mgr */
++};
++
++/* Default allocation attributes */
++static struct CMM_ATTRS CMM_DFLTALCTATTRS = {
++      1                       /* ulSegId, default segment Id for allocator */
++};
++
++/* Address translator default attrs */
++static struct CMM_XLATORATTRS CMM_DFLTXLATORATTRS = {
++      1,      /* ulSegId, does not have to match CMM_DFLTALCTATTRS ulSegId */
++      0,                      /* dwDSPBufs */
++      0,                      /* dwDSPBufSize */
++      NULL,                   /* pVmBase */
++      0,                      /* dwVmSize */
++};
++
++/* SM node representing a block of memory. */
++struct CMM_MNODE {
++      struct LST_ELEM link;           /* must be 1st element */
++      u32 dwPA;               /* Phys addr */
++      u32 dwVA;               /* Virtual address in device process context */
++      u32 ulSize;             /* SM block size in bytes */
++       u32 hClientProc;        /* Process that allocated this mem block */
++} ;
++
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CMM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs;             /* module reference count */
++
++/*  ----------------------------------- Function Prototypes */
++static void AddToFreeList(struct CMM_ALLOCATOR *pAllocator,
++                        struct CMM_MNODE *pNode);
++static struct CMM_ALLOCATOR *GetAllocator(struct CMM_OBJECT *pCmmMgr,
++                                        u32 ulSegId);
++static struct CMM_MNODE *GetFreeBlock(struct CMM_ALLOCATOR *pAllocator,
++                                    u32 uSize);
++static struct CMM_MNODE *GetNode(struct CMM_OBJECT *pCmmMgr, u32 dwPA,
++                               u32 dwVA, u32 ulSize);
++/* get available slot for new allocator */
++static s32 GetSlot(struct CMM_OBJECT *hCmmMgr);
++static void UnRegisterGPPSMSeg(struct CMM_ALLOCATOR *pSMA);
++
++/*
++ *  ======== CMM_CallocBuf ========
++ *  Purpose:
++ *      Allocate a SM buffer, zero contents, and return the physical address
++ *      and optional driver context virtual address(ppBufVA).
++ *
++ *      The freelist is sorted in increasing size order. Get the first
++ *      block that satifies the request and sort the remaining back on
++ *      the freelist; if large enough. The kept block is placed on the
++ *      inUseList.
++ */
++void *CMM_CallocBuf(struct CMM_OBJECT *hCmmMgr, u32 uSize,
++                  struct CMM_ATTRS *pAttrs, OUT void **ppBufVA)
++{
++      struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++      void *pBufPA = NULL;
++      struct CMM_MNODE *pNode = NULL;
++      struct CMM_MNODE *pNewNode = NULL;
++      struct CMM_ALLOCATOR *pAllocator = NULL;
++      u32 uDeltaSize;
++      u8 *pByte = NULL;
++      s32 cnt;
++
++      if (pAttrs == NULL)
++              pAttrs = &CMM_DFLTALCTATTRS;
++
++      if (ppBufVA != NULL)
++              *ppBufVA = NULL;
++
++      if ((MEM_IsValidHandle(pCmmMgr, CMMSIGNATURE)) && (uSize != 0)) {
++              if (pAttrs->ulSegId > 0) {
++                      /* SegId > 0 is SM  */
++                      /* get the allocator object for this segment id */
++                      pAllocator = GetAllocator(pCmmMgr, pAttrs->ulSegId);
++                      /* keep block size a multiple of ulMinBlockSize */
++                      uSize = ((uSize - 1) & ~(pCmmMgr->ulMinBlockSize - 1))
++                              + pCmmMgr->ulMinBlockSize;
++                      SYNC_EnterCS(pCmmMgr->hCmmLock);
++                      pNode = GetFreeBlock(pAllocator, uSize);
++              }
++              if (pNode) {
++                      uDeltaSize = (pNode->ulSize - uSize);
++                      if (uDeltaSize >= pCmmMgr->ulMinBlockSize) {
++                              /* create a new block with the leftovers and
++                               * add to freelist */
++                              pNewNode = GetNode(pCmmMgr, pNode->dwPA + uSize,
++                                         pNode->dwVA + uSize,
++                                         (u32)uDeltaSize);
++                              /* leftovers go free */
++                              AddToFreeList(pAllocator, pNewNode);
++                              /* adjust our node's size */
++                              pNode->ulSize = uSize;
++                      }
++                      /* Tag node with client process requesting allocation
++                       * We'll need to free up a process's alloc'd SM if the
++                       * client process goes away.
++                       */
++                       /* Return PID instead of process handle */
++                       pNode->hClientProc = current->pid;
++
++                      /* put our node on InUse list */
++                      LST_PutTail(pAllocator->pInUseListHead,
++                                 (struct LST_ELEM *)pNode);
++                      pBufPA = (void *)pNode->dwPA;   /* physical address */
++                      /* clear mem */
++                      pByte = (u8 *)pNode->dwVA;
++                      for (cnt = 0; cnt < (s32) uSize; cnt++, pByte++)
++                              *pByte = 0;
++
++                      if (ppBufVA != NULL) {
++                              /* Virtual address */
++                              *ppBufVA = (void *)pNode->dwVA;
++                      }
++              }
++              GT_3trace(CMM_debugMask, GT_3CLASS,
++                        "CMM_CallocBuf dwPA %x, dwVA %x uSize"
++                        "%x\n", pNode->dwPA, pNode->dwVA, uSize);
++              SYNC_LeaveCS(pCmmMgr->hCmmLock);
++      }
++      return pBufPA;
++}
++
++/*
++ *  ======== CMM_Create ========
++ *  Purpose:
++ *      Create a communication memory manager object.
++ */
++DSP_STATUS CMM_Create(OUT struct CMM_OBJECT **phCmmMgr,
++                    struct DEV_OBJECT *hDevObject,
++                    IN CONST struct CMM_MGRATTRS *pMgrAttrs)
++{
++      struct CMM_OBJECT *pCmmObject = NULL;
++      DSP_STATUS status = DSP_SOK;
++      struct UTIL_SYSINFO sysInfo;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phCmmMgr != NULL);
++
++      GT_3trace(CMM_debugMask, GT_ENTER,
++                "CMM_Create: phCmmMgr: 0x%x\thDevObject: "
++                "0x%x\tpMgrAttrs: 0x%x\n", phCmmMgr, hDevObject, pMgrAttrs);
++      *phCmmMgr = NULL;
++      /* create, zero, and tag a cmm mgr object */
++      MEM_AllocObject(pCmmObject, struct CMM_OBJECT, CMMSIGNATURE);
++      if (pCmmObject != NULL) {
++              if (pMgrAttrs == NULL)
++                      pMgrAttrs = &CMM_DFLTMGRATTRS;  /* set defaults */
++
++              /* 4 bytes minimum */
++              DBC_Assert(pMgrAttrs->ulMinBlockSize >= 4);
++              /* save away smallest block allocation for this cmm mgr */
++              pCmmObject->ulMinBlockSize = pMgrAttrs->ulMinBlockSize;
++              /* save away the systems memory page size */
++              sysInfo.dwPageSize = PAGE_SIZE;
++              sysInfo.dwAllocationGranularity = PAGE_SIZE;
++              sysInfo.dwNumberOfProcessors = 1;
++              if (DSP_SUCCEEDED(status)) {
++                      GT_1trace(CMM_debugMask, GT_5CLASS,
++                                "CMM_Create: Got system page size"
++                                "= 0x%x\t\n", sysInfo.dwPageSize);
++                      pCmmObject->dwPageSize = sysInfo.dwPageSize;
++              } else {
++                      GT_0trace(CMM_debugMask, GT_7CLASS,
++                                "CMM_Create: failed to get system"
++                                "page size\n");
++                      pCmmObject->dwPageSize = 0;
++                      status = DSP_EFAIL;
++              }
++              /* Note: DSP SM seg table(aDSPSMSegTab[]) zero'd by
++               * MEM_AllocObject */
++              if (DSP_SUCCEEDED(status)) {
++                      /* create node free list */
++                      pCmmObject->pNodeFreeListHead = LST_Create();
++                      if (pCmmObject->pNodeFreeListHead == NULL) {
++                              GT_0trace(CMM_debugMask, GT_7CLASS,
++                                        "CMM_Create: LST_Create() "
++                                        "failed \n");
++                              status = DSP_EMEMORY;
++                      }
++              }
++              if (DSP_SUCCEEDED(status))
++                      status = SYNC_InitializeCS(&pCmmObject->hCmmLock);
++
++              if (DSP_SUCCEEDED(status))
++                      *phCmmMgr = pCmmObject;
++              else
++                      CMM_Destroy(pCmmObject, true);
++
++      } else {
++              GT_0trace(CMM_debugMask, GT_6CLASS,
++                        "CMM_Create: Object Allocation "
++                        "Failure(CMM Object)\n");
++              status = DSP_EMEMORY;
++      }
++      return status;
++}
++
++/*
++ *  ======== CMM_Destroy ========
++ *  Purpose:
++ *      Release the communication memory manager resources.
++ */
++DSP_STATUS CMM_Destroy(struct CMM_OBJECT *hCmmMgr, bool bForce)
++{
++      struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++      struct CMM_INFO tempInfo;
++      DSP_STATUS status = DSP_SOK;
++      s32 nSlot;
++      struct CMM_MNODE *pNode;
++
++      DBC_Require(cRefs > 0);
++      if (!MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++              status = DSP_EHANDLE;
++              return status;
++      }
++      SYNC_EnterCS(pCmmMgr->hCmmLock);
++      /* If not force then fail if outstanding allocations exist */
++      if (!bForce) {
++              /* Check for outstanding memory allocations */
++              status = CMM_GetInfo(hCmmMgr, &tempInfo);
++              if (DSP_SUCCEEDED(status)) {
++                      if (tempInfo.ulTotalInUseCnt > 0) {
++                              /* outstanding allocations */
++                              status = DSP_EFAIL;
++                      }
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* UnRegister SM allocator */
++              for (nSlot = 0; nSlot < CMM_MAXGPPSEGS; nSlot++) {
++                      if (pCmmMgr->paGPPSMSegTab[nSlot] != NULL) {
++                              UnRegisterGPPSMSeg(pCmmMgr->
++                                                 paGPPSMSegTab[nSlot]);
++                              /* Set slot to NULL for future reuse */
++                              pCmmMgr->paGPPSMSegTab[nSlot] = NULL;
++                      }
++              }
++      }
++      if (pCmmMgr->pNodeFreeListHead != NULL) {
++              /* Free the free nodes */
++              while (!LST_IsEmpty(pCmmMgr->pNodeFreeListHead)) {
++                      /* (struct LST_ELEM*) pNode =
++                       * LST_GetHead(pCmmMgr->pNodeFreeListHead);*/
++                      pNode = (struct CMM_MNODE *)LST_GetHead(pCmmMgr->
++                               pNodeFreeListHead);
++                      MEM_Free(pNode);
++              }
++              /* delete NodeFreeList list */
++              LST_Delete(pCmmMgr->pNodeFreeListHead);
++      }
++      SYNC_LeaveCS(pCmmMgr->hCmmLock);
++      if (DSP_SUCCEEDED(status)) {
++              /* delete CS & cmm mgr object */
++              SYNC_DeleteCS(pCmmMgr->hCmmLock);
++              MEM_FreeObject(pCmmMgr);
++      }
++      return status;
++}
++
++/*
++ *  ======== CMM_Exit ========
++ *  Purpose:
++ *      Discontinue usage of module; free resources when reference count
++ *      reaches 0.
++ */
++void CMM_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      cRefs--;
++
++      GT_1trace(CMM_debugMask, GT_ENTER,
++                "exiting CMM_Exit,ref count:0x%x\n", cRefs);
++}
++
++/*
++ *  ======== CMM_FreeBuf ========
++ *  Purpose:
++ *      Free the given buffer.
++ */
++DSP_STATUS CMM_FreeBuf(struct CMM_OBJECT *hCmmMgr, void *pBufPA, u32 ulSegId)
++{
++      struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++      DSP_STATUS status = DSP_EPOINTER;
++      struct CMM_MNODE *pCurNode = NULL;
++      struct CMM_ALLOCATOR *pAllocator = NULL;
++      struct CMM_ATTRS *pAttrs;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pBufPA != NULL);
++      GT_1trace(CMM_debugMask, GT_ENTER, "CMM_FreeBuf pBufPA %x\n", pBufPA);
++      if (ulSegId == 0) {
++              pAttrs = &CMM_DFLTALCTATTRS;
++              ulSegId = pAttrs->ulSegId;
++      }
++      if (!(MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) || !(ulSegId > 0)) {
++              status = DSP_EHANDLE;
++              return status;
++      }
++      /* get the allocator for this segment id */
++      pAllocator = GetAllocator(pCmmMgr, ulSegId);
++      if (pAllocator != NULL) {
++              SYNC_EnterCS(pCmmMgr->hCmmLock);
++              pCurNode = (struct CMM_MNODE *)LST_First(pAllocator->
++                          pInUseListHead);
++              while (pCurNode) {
++                      if ((u32)pBufPA == pCurNode->dwPA) {
++                              /* Found it */
++                              LST_RemoveElem(pAllocator->pInUseListHead,
++                                            (struct LST_ELEM *)pCurNode);
++                              /* back to freelist */
++                              AddToFreeList(pAllocator, pCurNode);
++                              status = DSP_SOK;       /* all right! */
++                              break;
++                      }
++                      /* next node. */
++                      pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++                                 pInUseListHead, (struct LST_ELEM *)pCurNode);
++              }
++              SYNC_LeaveCS(pCmmMgr->hCmmLock);
++      }
++      return status;
++}
++
++/*
++ *  ======== CMM_GetHandle ========
++ *  Purpose:
++ *      Return the communication memory manager object for this device.
++ *      This is typically called from the client process.
++ */
++DSP_STATUS CMM_GetHandle(DSP_HPROCESSOR hProcessor,
++                      OUT struct CMM_OBJECT **phCmmMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *hDevObject;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phCmmMgr != NULL);
++      if (hProcessor != NULL)
++              status = PROC_GetDevObject(hProcessor, &hDevObject);
++      else
++              hDevObject = DEV_GetFirst();    /* default */
++
++      if (DSP_SUCCEEDED(status))
++              status = DEV_GetCmmMgr(hDevObject, phCmmMgr);
++
++      return status;
++}
++
++/*
++ *  ======== CMM_GetInfo ========
++ *  Purpose:
++ *      Return the current memory utilization information.
++ */
++DSP_STATUS CMM_GetInfo(struct CMM_OBJECT *hCmmMgr,
++                     OUT struct CMM_INFO *pCmmInfo)
++{
++      struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++      u32 ulSeg;
++      DSP_STATUS status = DSP_SOK;
++      struct CMM_ALLOCATOR *pAltr;
++      struct CMM_MNODE *pCurNode = NULL;
++
++      DBC_Require(pCmmInfo != NULL);
++
++      if (!MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++              status = DSP_EHANDLE;
++              return status;
++      }
++      SYNC_EnterCS(pCmmMgr->hCmmLock);
++      pCmmInfo->ulNumGPPSMSegs = 0;   /* # of SM segments */
++      pCmmInfo->ulTotalInUseCnt = 0;  /* Total # of outstanding alloc */
++      pCmmInfo->ulMinBlockSize = pCmmMgr->ulMinBlockSize; /* min block size */
++      /* check SM memory segments */
++      for (ulSeg = 1; ulSeg <= CMM_MAXGPPSEGS; ulSeg++) {
++              /* get the allocator object for this segment id */
++              pAltr = GetAllocator(pCmmMgr, ulSeg);
++              if (pAltr != NULL) {
++                      pCmmInfo->ulNumGPPSMSegs++;
++                      pCmmInfo->segInfo[ulSeg - 1].dwSegBasePa =
++                              pAltr->dwSmBase - pAltr->ulDSPSize;
++                      pCmmInfo->segInfo[ulSeg - 1].ulTotalSegSize =
++                              pAltr->ulDSPSize + pAltr->ulSmSize;
++                      pCmmInfo->segInfo[ulSeg - 1].dwGPPBasePA =
++                              pAltr->dwSmBase;
++                      pCmmInfo->segInfo[ulSeg - 1].ulGPPSize =
++                              pAltr->ulSmSize;
++                      pCmmInfo->segInfo[ulSeg - 1].dwDSPBaseVA =
++                              pAltr->dwDSPBase;
++                      pCmmInfo->segInfo[ulSeg - 1].ulDSPSize =
++                              pAltr->ulDSPSize;
++                      pCmmInfo->segInfo[ulSeg - 1].dwSegBaseVa =
++                              pAltr->dwVmBase - pAltr->ulDSPSize;
++                      pCmmInfo->segInfo[ulSeg - 1].ulInUseCnt = 0;
++                      pCurNode = (struct CMM_MNODE *)LST_First(pAltr->
++                              pInUseListHead);
++                      /* Count inUse blocks */
++                      while (pCurNode) {
++                              pCmmInfo->ulTotalInUseCnt++;
++                              pCmmInfo->segInfo[ulSeg - 1].ulInUseCnt++;
++                              /* next node. */
++                              pCurNode = (struct CMM_MNODE *)LST_Next(pAltr->
++                                      pInUseListHead,
++                                      (struct LST_ELEM *)pCurNode);
++                      }
++              }
++      }               /* end for */
++      SYNC_LeaveCS(pCmmMgr->hCmmLock);
++      return status;
++}
++
++/*
++ *  ======== CMM_Init ========
++ *  Purpose:
++ *      Initializes private state of CMM module.
++ */
++bool CMM_Init(void)
++{
++      bool fRetval = true;
++
++      DBC_Require(cRefs >= 0);
++      if (cRefs == 0) {
++              /* Set the Trace mask */
++              /* "CM" for Comm Memory manager */
++              GT_create(&CMM_debugMask, "CM");
++      }
++      if (fRetval)
++              cRefs++;
++
++      GT_1trace(CMM_debugMask, GT_ENTER,
++                "Entered CMM_Init,ref count:0x%x\n", cRefs);
++
++      DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++      return fRetval;
++}
++
++/*
++ *  ======== CMM_RegisterGPPSMSeg ========
++ *  Purpose:
++ *      Register a block of SM with the CMM to be used for later GPP SM
++ *      allocations.
++ */
++DSP_STATUS CMM_RegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr, u32 dwGPPBasePA,
++                              u32 ulSize, u32 dwDSPAddrOffset,
++                              enum CMM_CNVTTYPE cFactor, u32 dwDSPBase,
++                              u32 ulDSPSize, u32 *pulSegId,
++                              u32 dwGPPBaseVA)
++{
++      struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++      struct CMM_ALLOCATOR *pSMA = NULL;
++      DSP_STATUS status = DSP_SOK;
++      struct CMM_MNODE *pNewNode;
++      s32 nSlot;
++
++      DBC_Require(ulSize > 0);
++      DBC_Require(pulSegId != NULL);
++      DBC_Require(dwGPPBasePA != 0);
++      DBC_Require(dwGPPBaseVA != 0);
++      DBC_Require((cFactor <= CMM_ADDTODSPPA) &&
++                 (cFactor >= CMM_SUBFROMDSPPA));
++      GT_6trace(CMM_debugMask, GT_ENTER,
++                "CMM_RegisterGPPSMSeg dwGPPBasePA %x "
++                "ulSize %x dwDSPAddrOffset %x dwDSPBase %x ulDSPSize %x "
++                "dwGPPBaseVA %x\n", dwGPPBasePA, ulSize, dwDSPAddrOffset,
++                dwDSPBase, ulDSPSize, dwGPPBaseVA);
++      if (!MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++              status = DSP_EHANDLE;
++              return status;
++      }
++      /* make sure we have room for another allocator */
++      SYNC_EnterCS(pCmmMgr->hCmmLock);
++      nSlot = GetSlot(pCmmMgr);
++      if (nSlot < 0) {
++              /* get a slot number */
++              status = DSP_EFAIL;
++              goto func_end;
++      }
++      /* Check if input ulSize is big enough to alloc at least one block */
++      if (DSP_SUCCEEDED(status)) {
++              if (ulSize < pCmmMgr->ulMinBlockSize) {
++                      GT_0trace(CMM_debugMask, GT_7CLASS,
++                                "CMM_RegisterGPPSMSeg: "
++                                "ulSize too small\n");
++                      status = DSP_EINVALIDARG;
++                      goto func_end;
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* create, zero, and tag an SM allocator object */
++              MEM_AllocObject(pSMA, struct CMM_ALLOCATOR, SMEMSIGNATURE);
++      }
++      if (pSMA != NULL) {
++              pSMA->hCmmMgr = hCmmMgr;        /* ref to parent */
++              pSMA->dwSmBase = dwGPPBasePA;   /* SM Base phys */
++              pSMA->ulSmSize = ulSize;        /* SM segment size in bytes */
++              pSMA->dwVmBase = dwGPPBaseVA;
++              pSMA->dwDSPPhysAddrOffset = dwDSPAddrOffset;
++              pSMA->cFactor = cFactor;
++              pSMA->dwDSPBase = dwDSPBase;
++              pSMA->ulDSPSize = ulDSPSize;
++              if (pSMA->dwVmBase == 0) {
++                      GT_0trace(CMM_debugMask, GT_7CLASS,
++                                "CMM_RegisterGPPSMSeg: Error"
++                                "MEM_LinearAddress()\n");
++                      status = DSP_EFAIL;
++                      goto func_end;
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      /* return the actual segment identifier */
++                      *pulSegId = (u32) nSlot + 1;
++                      /* create memory free list */
++                      pSMA->pFreeListHead = LST_Create();
++                      if (pSMA->pFreeListHead == NULL) {
++                              GT_0trace(CMM_debugMask, GT_7CLASS,
++                                        "CMM_RegisterGPPSMSeg: "
++                                        "Out Of Memory \n");
++                              status = DSP_EMEMORY;
++                              goto func_end;
++                      }
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      /* create memory in-use list */
++                      pSMA->pInUseListHead = LST_Create();
++                      if (pSMA->pInUseListHead == NULL) {
++                              GT_0trace(CMM_debugMask, GT_7CLASS,
++                                        "CMM_RegisterGPPSMSeg: "
++                                        "LST_Create failed\n");
++                              status = DSP_EMEMORY;
++                              goto func_end;
++                      }
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      /* Get a mem node for this hunk-o-memory */
++                      pNewNode = GetNode(pCmmMgr, dwGPPBasePA,
++                                         pSMA->dwVmBase, ulSize);
++                      /* Place node on the SM allocator's free list */
++                      if (pNewNode) {
++                              LST_PutTail(pSMA->pFreeListHead,
++                                         (struct LST_ELEM *)pNewNode);
++                      } else {
++                              status = DSP_EMEMORY;
++                              goto func_end;
++                      }
++              }
++              if (DSP_FAILED(status)) {
++                      /* Cleanup allocator */
++                      UnRegisterGPPSMSeg(pSMA);
++              }
++      } else {
++              GT_0trace(CMM_debugMask, GT_6CLASS,
++                        "CMM_RegisterGPPSMSeg: SMA Object "
++                        "Allocation Failure\n");
++              status = DSP_EMEMORY;
++              goto func_end;
++      }
++       /* make entry */
++      if (DSP_SUCCEEDED(status))
++              pCmmMgr->paGPPSMSegTab[nSlot] = pSMA;
++
++func_end:
++      SYNC_LeaveCS(pCmmMgr->hCmmLock);
++      return status;
++}
++
++/*
++ *  ======== CMM_UnRegisterGPPSMSeg ========
++ *  Purpose:
++ *      UnRegister GPP SM segments with the CMM.
++ */
++DSP_STATUS CMM_UnRegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr, u32 ulSegId)
++{
++      struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++      DSP_STATUS status = DSP_SOK;
++      struct CMM_ALLOCATOR *pSMA;
++      u32 ulId = ulSegId;
++
++      DBC_Require(ulSegId > 0);
++      if (MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++              if (ulSegId == CMM_ALLSEGMENTS)
++                      ulId = 1;
++
++              if ((ulId > 0) && (ulId <= CMM_MAXGPPSEGS)) {
++                      while (ulId <= CMM_MAXGPPSEGS) {
++                              SYNC_EnterCS(pCmmMgr->hCmmLock);
++                              /* slot = segId-1 */
++                              pSMA = pCmmMgr->paGPPSMSegTab[ulId - 1];
++                              if (pSMA != NULL) {
++                                      UnRegisterGPPSMSeg(pSMA);
++                                      /* Set alctr ptr to NULL for future
++                                       * reuse */
++                                      pCmmMgr->paGPPSMSegTab[ulId - 1] = NULL;
++                              } else if (ulSegId != CMM_ALLSEGMENTS) {
++                                      status = DSP_EFAIL;
++                              }
++                              SYNC_LeaveCS(pCmmMgr->hCmmLock);
++                              if (ulSegId != CMM_ALLSEGMENTS)
++                                      break;
++
++                              ulId++;
++                      }       /* end while */
++              } else {
++                      status = DSP_EINVALIDARG;
++                      GT_0trace(CMM_debugMask, GT_7CLASS,
++                                "CMM_UnRegisterGPPSMSeg: Bad "
++                                "segment Id\n");
++              }
++      } else {
++              status = DSP_EHANDLE;
++      }
++      return status;
++}
++
++/*
++ *  ======== UnRegisterGPPSMSeg ========
++ *  Purpose:
++ *      UnRegister the SM allocator by freeing all its resources and
++ *      nulling cmm mgr table entry.
++ *  Note:
++ *      This routine is always called within cmm lock crit sect.
++ */
++static void UnRegisterGPPSMSeg(struct CMM_ALLOCATOR *pSMA)
++{
++      struct CMM_MNODE *pCurNode = NULL;
++      struct CMM_MNODE *pNextNode = NULL;
++
++      DBC_Require(pSMA != NULL);
++      if (pSMA->pFreeListHead != NULL) {
++              /* free nodes on free list */
++              pCurNode = (struct CMM_MNODE *)LST_First(pSMA->pFreeListHead);
++              while (pCurNode) {
++                      pNextNode = (struct CMM_MNODE *)LST_Next(pSMA->
++                                   pFreeListHead,
++                                  (struct LST_ELEM *)pCurNode);
++                      LST_RemoveElem(pSMA->pFreeListHead,
++                                    (struct LST_ELEM *)pCurNode);
++                      MEM_Free((void *) pCurNode);
++                      /* next node. */
++                      pCurNode = pNextNode;
++              }
++              LST_Delete(pSMA->pFreeListHead);        /* delete freelist */
++              /* free nodes on InUse list */
++              pCurNode = (struct CMM_MNODE *)LST_First(pSMA->pInUseListHead);
++              while (pCurNode) {
++                      pNextNode = (struct CMM_MNODE *)LST_Next(pSMA->
++                                  pInUseListHead,
++                                  (struct LST_ELEM *)pCurNode);
++                      LST_RemoveElem(pSMA->pInUseListHead,
++                                    (struct LST_ELEM *)pCurNode);
++                      MEM_Free((void *) pCurNode);
++                      /* next node. */
++                      pCurNode = pNextNode;
++              }
++              LST_Delete(pSMA->pInUseListHead);       /* delete InUse list */
++      }
++      if ((void *) pSMA->dwVmBase != NULL)
++              MEM_UnmapLinearAddress((void *) pSMA->dwVmBase);
++
++      /* Free allocator itself */
++      MEM_FreeObject(pSMA);
++}
++
++/*
++ *  ======== GetSlot ========
++ *  Purpose:
++ *      An available slot # is returned. Returns negative on failure.
++ */
++static s32 GetSlot(struct CMM_OBJECT *pCmmMgr)
++{
++      s32 nSlot = -1;         /* neg on failure */
++      DBC_Require(pCmmMgr != NULL);
++      /* get first available slot in cmm mgr SMSegTab[] */
++      for (nSlot = 0; nSlot < CMM_MAXGPPSEGS; nSlot++) {
++              if (pCmmMgr->paGPPSMSegTab[nSlot] == NULL)
++                      break;
++
++      }
++      if (nSlot == CMM_MAXGPPSEGS) {
++              GT_0trace(CMM_debugMask, GT_7CLASS,
++                        "CMM_RegisterGPPSMSeg: Allocator "
++                        "entry failure, max exceeded\n");
++              nSlot = -1;     /* failed */
++      }
++      return nSlot;
++}
++
++/*
++ *  ======== GetNode ========
++ *  Purpose:
++ *      Get a memory node from freelist or create a new one.
++ */
++static struct CMM_MNODE *GetNode(struct CMM_OBJECT *pCmmMgr, u32 dwPA,
++                               u32 dwVA, u32 ulSize)
++{
++      struct CMM_MNODE *pNode = NULL;
++
++      DBC_Require(pCmmMgr != NULL);
++      DBC_Require(dwPA != 0);
++      DBC_Require(dwVA != 0);
++      DBC_Require(ulSize != 0);
++      /* Check cmm mgr's node freelist */
++      if (LST_IsEmpty(pCmmMgr->pNodeFreeListHead)) {
++              pNode = (struct CMM_MNODE *)MEM_Calloc(sizeof(struct CMM_MNODE),
++                      MEM_PAGED);
++      } else {
++              /* surely a valid element */
++              /* (struct LST_ELEM*) pNode = LST_GetHead(pCmmMgr->
++               * pNodeFreeListHead);*/
++              pNode = (struct CMM_MNODE *)LST_GetHead(pCmmMgr->
++                      pNodeFreeListHead);
++      }
++      if (pNode == NULL) {
++              GT_0trace(CMM_debugMask, GT_7CLASS, "GetNode: Out Of Memory\n");
++      } else {
++              LST_InitElem((struct LST_ELEM *) pNode);        /* set self */
++              pNode->dwPA = dwPA;     /* Physical addr of start of block */
++              pNode->dwVA = dwVA;     /* Virtual   "            "        */
++              pNode->ulSize = ulSize; /* Size of block */
++      }
++      return pNode;
++}
++
++/*
++ *  ======== DeleteNode ========
++ *  Purpose:
++ *      Put a memory node on the cmm nodelist for later use.
++ *      Doesn't actually delete the node. Heap thrashing friendly.
++ */
++static void DeleteNode(struct CMM_OBJECT *pCmmMgr, struct CMM_MNODE *pNode)
++{
++      DBC_Require(pNode != NULL);
++      LST_InitElem((struct LST_ELEM *) pNode);        /* init .self ptr */
++      LST_PutTail(pCmmMgr->pNodeFreeListHead, (struct LST_ELEM *) pNode);
++}
++
++/*
++ * ====== GetFreeBlock ========
++ *  Purpose:
++ *      Scan the free block list and return the first block that satisfies
++ *      the size.
++ */
++static struct CMM_MNODE *GetFreeBlock(struct CMM_ALLOCATOR *pAllocator,
++                                    u32 uSize)
++{
++      if (pAllocator) {
++              struct CMM_MNODE *pCurNode = (struct CMM_MNODE *)
++                                      LST_First(pAllocator->pFreeListHead);
++              while (pCurNode) {
++                      if (uSize <= (u32) pCurNode->ulSize) {
++                              LST_RemoveElem(pAllocator->pFreeListHead,
++                                            (struct LST_ELEM *)pCurNode);
++                              return pCurNode;
++                      }
++                      /* next node. */
++                      pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++                                  pFreeListHead, (struct LST_ELEM *)pCurNode);
++              }
++      }
++      return NULL;
++}
++
++/*
++ *  ======== AddToFreeList ========
++ *  Purpose:
++ *      Coelesce node into the freelist in ascending size order.
++ */
++static void AddToFreeList(struct CMM_ALLOCATOR *pAllocator,
++                        struct CMM_MNODE *pNode)
++{
++      struct CMM_MNODE *pNodePrev = NULL;
++      struct CMM_MNODE *pNodeNext = NULL;
++      struct CMM_MNODE *pCurNode;
++      u32 dwThisPA;
++      u32 dwNextPA;
++
++      DBC_Require(pNode != NULL);
++      DBC_Require(pAllocator != NULL);
++      dwThisPA = pNode->dwPA;
++      dwNextPA = NEXT_PA(pNode);
++      pCurNode = (struct CMM_MNODE *)LST_First(pAllocator->pFreeListHead);
++      while (pCurNode) {
++              if (dwThisPA == NEXT_PA(pCurNode)) {
++                      /* found the block ahead of this one */
++                      pNodePrev = pCurNode;
++              } else if (dwNextPA == pCurNode->dwPA) {
++                      pNodeNext = pCurNode;
++              }
++              if ((pNodePrev == NULL) || (pNodeNext == NULL)) {
++                      /* next node. */
++                      pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++                                  pFreeListHead, (struct LST_ELEM *)pCurNode);
++              } else {
++                      /* got 'em */
++                      break;
++              }
++      }                       /* while */
++      if (pNodePrev != NULL) {
++              /* combine with previous block */
++              LST_RemoveElem(pAllocator->pFreeListHead,
++                            (struct LST_ELEM *)pNodePrev);
++              /* grow node to hold both */
++              pNode->ulSize += pNodePrev->ulSize;
++              pNode->dwPA = pNodePrev->dwPA;
++              pNode->dwVA = pNodePrev->dwVA;
++              /* place node on mgr nodeFreeList */
++              DeleteNode((struct CMM_OBJECT *)pAllocator->hCmmMgr, pNodePrev);
++      }
++      if (pNodeNext != NULL) {
++              /* combine with next block */
++              LST_RemoveElem(pAllocator->pFreeListHead,
++                            (struct LST_ELEM *)pNodeNext);
++              /* grow da node */
++              pNode->ulSize += pNodeNext->ulSize;
++              /* place node on mgr nodeFreeList */
++              DeleteNode((struct CMM_OBJECT *)pAllocator->hCmmMgr, pNodeNext);
++      }
++      /* Now, let's add to freelist in increasing size order */
++      pCurNode = (struct CMM_MNODE *)LST_First(pAllocator->pFreeListHead);
++      while (pCurNode) {
++              if (pNode->ulSize <= pCurNode->ulSize)
++                      break;
++
++              /* next node. */
++              pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++                         pFreeListHead, (struct LST_ELEM *)pCurNode);
++      }
++      /* if pCurNode is NULL then add our pNode to the end of the freelist */
++      if (pCurNode == NULL) {
++              LST_PutTail(pAllocator->pFreeListHead,
++                         (struct LST_ELEM *)pNode);
++      } else {
++              /* insert our node before the current traversed node */
++              LST_InsertBefore(pAllocator->pFreeListHead,
++                              (struct LST_ELEM *)pNode,
++                              (struct LST_ELEM *)pCurNode);
++      }
++}
++
++/*
++ * ======== GetAllocator ========
++ *  Purpose:
++ *      Return the allocator for the given SM Segid.
++ *      SegIds:  1,2,3..max.
++ */
++static struct CMM_ALLOCATOR *GetAllocator(struct CMM_OBJECT *pCmmMgr,
++                                        u32 ulSegId)
++{
++      struct CMM_ALLOCATOR *pAllocator = NULL;
++
++      DBC_Require(pCmmMgr != NULL);
++      DBC_Require((ulSegId > 0) && (ulSegId <= CMM_MAXGPPSEGS));
++      pAllocator = pCmmMgr->paGPPSMSegTab[ulSegId - 1];
++      if (pAllocator != NULL) {
++              /* make sure it's for real */
++              if (!MEM_IsValidHandle(pAllocator, SMEMSIGNATURE)) {
++                      pAllocator = NULL;
++                      DBC_Assert(false);
++              }
++      }
++      return pAllocator;
++}
++
++/*
++ *  ======== CMM_XlatorCreate ========
++ *  Purpose:
++ *      Create an address translator object.
++ */
++DSP_STATUS CMM_XlatorCreate(OUT struct CMM_XLATOROBJECT **phXlator,
++                              struct CMM_OBJECT *hCmmMgr,
++                              struct CMM_XLATORATTRS *pXlatorAttrs)
++{
++      struct CMM_XLATOR *pXlatorObject = NULL;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phXlator != NULL);
++      DBC_Require(hCmmMgr != NULL);
++      GT_3trace(CMM_debugMask, GT_ENTER,
++                "CMM_XlatorCreate: phXlator: 0x%x\t"
++                "phCmmMgr: 0x%x\tpXlAttrs: 0x%x\n", phXlator,
++                hCmmMgr, pXlatorAttrs);
++      *phXlator = NULL;
++      if (pXlatorAttrs == NULL)
++              pXlatorAttrs = &CMM_DFLTXLATORATTRS;    /* set defaults */
++
++      MEM_AllocObject(pXlatorObject, struct CMM_XLATOR, CMMXLATESIGNATURE);
++      if (pXlatorObject != NULL) {
++              pXlatorObject->hCmmMgr = hCmmMgr;       /* ref back to CMM */
++              pXlatorObject->ulSegId = pXlatorAttrs->ulSegId; /* SM segId */
++      } else {
++              GT_0trace(CMM_debugMask, GT_6CLASS,
++                        "CMM_XlatorCreate: Object Allocation"
++                        "Failure(CMM Xlator)\n");
++              status = DSP_EMEMORY;
++      }
++      if (DSP_SUCCEEDED(status))
++              *phXlator = (struct CMM_XLATOROBJECT *) pXlatorObject;
++
++      return status;
++}
++
++/*
++ *  ======== CMM_XlatorDelete ========
++ *  Purpose:
++ *      Free the Xlator resources.
++ *      VM gets freed later.
++ */
++DSP_STATUS CMM_XlatorDelete(struct CMM_XLATOROBJECT *hXlator, bool bForce)
++{
++      struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++
++      if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++              MEM_FreeObject(pXlator);
++      } else {
++              status = DSP_EHANDLE;
++      }
++
++      return status;
++}
++
++/*
++ *  ======== CMM_XlatorAllocBuf ========
++ */
++void *CMM_XlatorAllocBuf(struct CMM_XLATOROBJECT *hXlator, void *pVaBuf,
++                      u32 uPaSize)
++{
++      struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++      void *pBuf = NULL;
++      struct CMM_ATTRS attrs;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(hXlator != NULL);
++      DBC_Require(pXlator->hCmmMgr != NULL);
++      DBC_Require(pVaBuf != NULL);
++      DBC_Require(uPaSize > 0);
++      DBC_Require(pXlator->ulSegId > 0);
++
++      if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++              attrs.ulSegId = pXlator->ulSegId;
++              *(volatile u32 *)pVaBuf = 0;
++              /* Alloc SM */
++              pBuf = CMM_CallocBuf(pXlator->hCmmMgr, uPaSize, &attrs,  NULL);
++              if (pBuf) {
++                      /* convert to translator(node/strm) process Virtual
++                       * address */
++                      *(volatile u32 **)pVaBuf =
++                               (u32 *)CMM_XlatorTranslate(hXlator,
++                                                            pBuf, CMM_PA2VA);
++              }
++      }
++      return pBuf;
++}
++
++/*
++ *  ======== CMM_XlatorFreeBuf ========
++ *  Purpose:
++ *      Free the given SM buffer and descriptor.
++ *      Does not free virtual memory.
++ */
++DSP_STATUS CMM_XlatorFreeBuf(struct CMM_XLATOROBJECT *hXlator, void *pBufVa)
++{
++      struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++      DSP_STATUS status = DSP_EFAIL;
++      void *pBufPa = NULL;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pBufVa != NULL);
++      DBC_Require(pXlator->ulSegId > 0);
++
++      if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++              /* convert Va to Pa so we can free it. */
++              pBufPa = CMM_XlatorTranslate(hXlator, pBufVa, CMM_VA2PA);
++              if (pBufPa) {
++                      status = CMM_FreeBuf(pXlator->hCmmMgr, pBufPa,
++                                           pXlator->ulSegId);
++                      if (DSP_FAILED(status)) {
++                              /* Uh oh, this shouldn't happen. Descriptor
++                               * gone! */
++                              GT_2trace(CMM_debugMask, GT_7CLASS,
++                                      "Cannot free DMA/ZCPY buffer"
++                                      "not allocated by MPU. PA %x, VA %x\n",
++                                      pBufPa, pBufVa);
++                              DBC_Assert(false);   /* CMM is leaking mem! */
++                      }
++              }
++      }
++      return status;
++}
++
++/*
++ *  ======== CMM_XlatorInfo ========
++ *  Purpose:
++ *      Set/Get translator info.
++ */
++DSP_STATUS CMM_XlatorInfo(struct CMM_XLATOROBJECT *hXlator, IN OUT u8 **pAddr,
++                       u32 ulSize, u32 uSegId, bool bSetInfo)
++{
++      struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pAddr != NULL);
++      DBC_Require((uSegId > 0) && (uSegId <= CMM_MAXGPPSEGS));
++
++      if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++              if (bSetInfo) {
++                      /* set translators virtual address range */
++                      pXlator->dwVirtBase = (u32)*pAddr;
++                      pXlator->ulVirtSize = ulSize;
++                      GT_2trace(CMM_debugMask, GT_3CLASS,
++                                "pXlator->dwVirtBase %x, "
++                                "ulVirtSize %x\n", pXlator->dwVirtBase,
++                                pXlator->ulVirtSize);
++              } else {        /* return virt base address */
++                      *pAddr = (u8 *)pXlator->dwVirtBase;
++              }
++      } else {
++              status = DSP_EHANDLE;
++      }
++      return status;
++}
++
++/*
++ *  ======== CMM_XlatorTranslate ========
++ */
++void *CMM_XlatorTranslate(struct CMM_XLATOROBJECT *hXlator, void *pAddr,
++                        enum CMM_XLATETYPE xType)
++{
++      u32 dwAddrXlate = 0;
++      struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++      struct CMM_OBJECT *pCmmMgr = NULL;
++      struct CMM_ALLOCATOR *pAlctr = NULL;
++      u32 dwOffset = 0;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pAddr != NULL);
++      DBC_Require((xType >= CMM_VA2PA) && (xType <= CMM_DSPPA2PA));
++
++      if (!MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE))
++              goto loop_cont;
++
++      pCmmMgr = (struct CMM_OBJECT *)pXlator->hCmmMgr;
++      /* get this translator's default SM allocator */
++      DBC_Assert(pXlator->ulSegId > 0);
++      pAlctr = pCmmMgr->paGPPSMSegTab[pXlator->ulSegId - 1];
++      if (!MEM_IsValidHandle(pAlctr, SMEMSIGNATURE))
++              goto loop_cont;
++
++      if ((xType == CMM_VA2DSPPA) || (xType == CMM_VA2PA) ||
++          (xType == CMM_PA2VA)) {
++              if (xType == CMM_PA2VA) {
++                      /* Gpp Va = Va Base + offset */
++                      dwOffset = (u8 *)pAddr - (u8 *)(pAlctr->dwSmBase -
++                                  pAlctr->ulDSPSize);
++                      dwAddrXlate = pXlator->dwVirtBase + dwOffset;
++                      /* Check if translated Va base is in range */
++                      if ((dwAddrXlate < pXlator->dwVirtBase) ||
++                         (dwAddrXlate >=
++                         (pXlator->dwVirtBase + pXlator->ulVirtSize))) {
++                              dwAddrXlate = 0;        /* bad address */
++                              GT_0trace(CMM_debugMask, GT_7CLASS,
++                                        "CMM_XlatorTranslate: "
++                                        "Virt addr out of range\n");
++                      }
++              } else {
++                      /* Gpp PA =  Gpp Base + offset */
++                      dwOffset = (u8 *)pAddr - (u8 *)pXlator->dwVirtBase;
++                      dwAddrXlate = pAlctr->dwSmBase - pAlctr->ulDSPSize +
++                                    dwOffset;
++              }
++      } else {
++              dwAddrXlate = (u32)pAddr;
++      }
++       /*Now convert address to proper target physical address if needed*/
++      if ((xType == CMM_VA2DSPPA) || (xType == CMM_PA2DSPPA)) {
++              /* Got Gpp Pa now, convert to DSP Pa */
++              dwAddrXlate = GPPPA2DSPPA((pAlctr->dwSmBase - pAlctr->
++                                       ulDSPSize), dwAddrXlate,
++                                       pAlctr->dwDSPPhysAddrOffset *
++                                       pAlctr->cFactor);
++      } else if (xType == CMM_DSPPA2PA) {
++              /* Got DSP Pa, convert to GPP Pa */
++              dwAddrXlate = DSPPA2GPPPA(pAlctr->dwSmBase - pAlctr->ulDSPSize,
++                                        dwAddrXlate,
++                                        pAlctr->dwDSPPhysAddrOffset *
++                                        pAlctr->cFactor);
++      }
++loop_cont:
++      if (!dwAddrXlate) {
++              GT_2trace(CMM_debugMask, GT_7CLASS,
++                        "CMM_XlatorTranslate: Can't translate"
++                        " address: 0x%x xType %x\n", pAddr, xType);
++      } else {
++              GT_3trace(CMM_debugMask, GT_3CLASS,
++                        "CMM_XlatorTranslate: pAddr %x, xType"
++                        " %x, dwAddrXlate %x\n", pAddr, xType, dwAddrXlate);
++      }
++      return (void *)dwAddrXlate;
++}
+diff --git a/drivers/dsp/bridge/pmgr/cod.c b/drivers/dsp/bridge/pmgr/cod.c
+new file mode 100644
+index 0000000..6363f1e
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/cod.c
+@@ -0,0 +1,683 @@
++/*
++ * cod.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== cod.c ========
++ *  This module implements DSP code management for the DSP/BIOS Bridge
++ *  environment. It is mostly a thin wrapper.
++ *
++ *  This module provides an interface for loading both static and
++ *  dynamic code objects onto DSP systems.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Apr-2003 map: Consolidated DBL to DBLL loader name
++ *! 24-Feb-2003 swa: PMGR Code review comments incorporated.
++ *! 18-Apr-2002 jeh: Added DBL function tables.
++ *! 20-Nov-2001 jeh: Removed call to ZL_loadArgs function.
++ *! 19-Oct-2001 jeh: Access DBL as a static library. Added COD_GetBaseLib,
++ *!             COD_GetLoader, removed COD_LoadSection, COD_UnloadSection.
++ *! 07-Sep-2001 jeh: Added COD_LoadSection(), COD_UnloadSection().
++ *! 07-Aug-2001 rr:  hMgr->baseLib is updated after zlopen in COD_LoadBase.
++ *! 18-Apr-2001 jeh: Check for fLoaded flag before ZL_unload, to allow
++ *!             COD_OpenBase to be used.
++ *! 11-Jan-2001 jeh: Added COD_OpenBase (not used yet, since there is an
++ *!             occasional crash).
++ *! 02-Aug-2000 kc:  Added COD_ReadSection to COD module. Incorporates use
++ *!             of ZL_readSect (new function in ZL module).
++ *! 28-Feb-2000 rr:  New GT Usage Implementation
++ *! 08-Dec-1999 ag:  Removed x86 specific __asm int 3.
++ *! 02-Oct-1999 ag:  Added #ifdef DEBUGINT3COD for debug.
++ *! 20-Sep-1999 ag:  Removed call to GT_set().
++ *! 04-Jun-1997 cr:  Added validation of argc/argv pair in COD_LoadBase, as it
++ *!                is a requirement to ZL_loadArgs.
++ *! 31-May-1997 cr:  Changed COD_LoadBase argc value from u32 to int, added
++ *!          DSP_ENOTIMPL return value to COD_Create when attrs != NULL.
++ *! 29-May-1997 cr:  Added debugging support.
++ *! 24-Oct-1996 gp:  Added COD_GetSection().
++ *! 18-Jun-1996 gp:  Updated GetSymValue() to check for lib; updated E_ codes.
++ *! 12-Jun-1996 gp:  Imported CSL_ services for strcpyn(); Added ref counting.
++ *! 20-May-1996 mg:  Adapted for new MEM and LDR modules.
++ *! 08-May-1996 mg:  Created.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/kfile.h>
++#include <dspbridge/ldr.h>
++#include <dspbridge/mem.h>
++
++/*  ----------------------------------- Platform Manager */
++/* Include appropriate loader header file */
++#include <dspbridge/dbll.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/cod.h>
++
++/* magic number for handle validation */
++#define MAGIC  0xc001beef
++
++/* macro to validate COD manager handles */
++#define IsValid(h)    ((h) != NULL && (h)->ulMagic == MAGIC)
++
++/*
++ *  ======== COD_MANAGER ========
++ */
++struct COD_MANAGER {
++      struct DBLL_TarObj *target;
++      struct DBLL_LibraryObj *baseLib;
++      bool fLoaded;           /* Base library loaded? */
++      u32 ulEntry;
++      struct LDR_MODULE *hDll;
++      struct DBLL_Fxns fxns;
++      struct DBLL_Attrs attrs;
++      char szZLFile[COD_MAXPATHLENGTH];
++      u32 ulMagic;
++} ;
++
++/*
++ *  ======== COD_LIBRARYOBJ ========
++ */
++struct COD_LIBRARYOBJ {
++      struct DBLL_LibraryObj *dbllLib;
++      struct COD_MANAGER *hCodMgr;
++} ;
++
++static u32 cRefs = 0L;
++
++#if GT_TRACE
++static struct GT_Mask COD_debugMask = { NULL, NULL };
++#endif
++
++static struct DBLL_Fxns dbllFxns = {
++      (DBLL_CloseFxn) DBLL_close,
++      (DBLL_CreateFxn) DBLL_create,
++      (DBLL_DeleteFxn) DBLL_delete,
++      (DBLL_ExitFxn) DBLL_exit,
++      (DBLL_GetAttrsFxn) DBLL_getAttrs,
++      (DBLL_GetAddrFxn) DBLL_getAddr,
++      (DBLL_GetCAddrFxn) DBLL_getCAddr,
++      (DBLL_GetSectFxn) DBLL_getSect,
++      (DBLL_InitFxn) DBLL_init,
++      (DBLL_LoadFxn) DBLL_load,
++      (DBLL_LoadSectFxn) DBLL_loadSect,
++      (DBLL_OpenFxn) DBLL_open,
++      (DBLL_ReadSectFxn) DBLL_readSect,
++      (DBLL_SetAttrsFxn) DBLL_setAttrs,
++      (DBLL_UnloadFxn) DBLL_unload,
++      (DBLL_UnloadSectFxn) DBLL_unloadSect,
++};
++
++static bool NoOp(void);
++
++/*
++ *  ======== COD_Close ========
++ */
++void COD_Close(struct COD_LIBRARYOBJ *lib)
++{
++      struct COD_MANAGER *hMgr;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(lib != NULL);
++      DBC_Require(IsValid(((struct COD_LIBRARYOBJ *)lib)->hCodMgr));
++
++      hMgr = lib->hCodMgr;
++      hMgr->fxns.closeFxn(lib->dbllLib);
++
++      MEM_Free(lib);
++}
++
++/*
++ *  ======== COD_Create ========
++ *  Purpose:
++ *      Create an object to manage code on a DSP system.
++ *      This object can be used to load an initial program image with
++ *      arguments that can later be expanded with
++ *      dynamically loaded object files.
++ *
++ */
++DSP_STATUS COD_Create(OUT struct COD_MANAGER **phMgr, char *pstrDummyFile,
++                   IN OPTIONAL CONST struct COD_ATTRS *attrs)
++{
++      struct COD_MANAGER *hMgrNew;
++      struct DBLL_Attrs zlAttrs;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phMgr != NULL);
++
++      GT_3trace(COD_debugMask, GT_ENTER,
++                "Entered COD_Create, Args: \t\nphMgr: "
++                "0x%x\t\npstrDummyFile: 0x%x\t\nattr: 0x%x\n",
++                phMgr, pstrDummyFile, attrs);
++      /* assume failure */
++      *phMgr = NULL;
++
++      /* we don't support non-default attrs yet */
++      if (attrs != NULL)
++              return DSP_ENOTIMPL;
++
++      hMgrNew = MEM_Calloc(sizeof(struct COD_MANAGER), MEM_NONPAGED);
++      if (hMgrNew == NULL) {
++              GT_0trace(COD_debugMask, GT_7CLASS,
++                        "COD_Create: Out Of Memory\n");
++              return DSP_EMEMORY;
++      }
++
++      hMgrNew->ulMagic = MAGIC;
++
++      /* Set up loader functions */
++      hMgrNew->fxns = dbllFxns;
++
++      /* initialize the ZL module */
++      hMgrNew->fxns.initFxn();
++
++      zlAttrs.alloc = (DBLL_AllocFxn)NoOp;
++      zlAttrs.free = (DBLL_FreeFxn)NoOp;
++      zlAttrs.fread = (DBLL_ReadFxn)KFILE_Read;
++      zlAttrs.fseek = (DBLL_SeekFxn)KFILE_Seek;
++      zlAttrs.ftell = (DBLL_TellFxn)KFILE_Tell;
++      zlAttrs.fclose = (DBLL_FCloseFxn)KFILE_Close;
++      zlAttrs.fopen = (DBLL_FOpenFxn)KFILE_Open;
++      zlAttrs.symLookup = NULL;
++      zlAttrs.baseImage = true;
++      zlAttrs.logWrite = NULL;
++      zlAttrs.logWriteHandle = NULL;
++      zlAttrs.write = NULL;
++      zlAttrs.rmmHandle = NULL;
++      zlAttrs.wHandle = NULL;
++      zlAttrs.symHandle = NULL;
++      zlAttrs.symArg = NULL;
++
++      hMgrNew->attrs = zlAttrs;
++
++      status = hMgrNew->fxns.createFxn(&hMgrNew->target, &zlAttrs);
++
++      if (DSP_FAILED(status)) {
++              COD_Delete(hMgrNew);
++              GT_1trace(COD_debugMask, GT_7CLASS,
++                        "COD_Create:ZL Create Failed: 0x%x\n", status);
++              return COD_E_ZLCREATEFAILED;
++      }
++
++      /* return the new manager */
++      *phMgr = hMgrNew;
++      GT_1trace(COD_debugMask, GT_1CLASS,
++                "COD_Create: Success CodMgr: 0x%x\n", *phMgr);
++      return DSP_SOK;
++}
++
++/*
++ *  ======== COD_Delete ========
++ *  Purpose:
++ *      Delete a code manager object.
++ */
++void COD_Delete(struct COD_MANAGER *hMgr)
++{
++      DBC_Require(cRefs > 0);
++      DBC_Require(IsValid(hMgr));
++
++      GT_1trace(COD_debugMask, GT_ENTER, "COD_Delete:hMgr 0x%x\n", hMgr);
++      if (hMgr->baseLib) {
++              if (hMgr->fLoaded)
++                      hMgr->fxns.unloadFxn(hMgr->baseLib, &hMgr->attrs);
++
++              hMgr->fxns.closeFxn(hMgr->baseLib);
++      }
++      if (hMgr->target) {
++              hMgr->fxns.deleteFxn(hMgr->target);
++              hMgr->fxns.exitFxn();
++      }
++      hMgr->ulMagic = ~MAGIC;
++      MEM_Free(hMgr);
++}
++
++/*
++ *  ======== COD_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the COD module.
++ *
++ */
++void COD_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      cRefs--;
++
++      GT_1trace(COD_debugMask, GT_ENTER,
++                "Entered COD_Exit, ref count:  0x%x\n", cRefs);
++
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== COD_GetBaseLib ========
++ *  Purpose:
++ *      Get handle to the base image DBL library.
++ */
++DSP_STATUS COD_GetBaseLib(struct COD_MANAGER *hManager,
++                              struct DBLL_LibraryObj **plib)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(IsValid(hManager));
++      DBC_Require(plib != NULL);
++
++      *plib = (struct DBLL_LibraryObj *) hManager->baseLib;
++
++      return status;
++}
++
++/*
++ *  ======== COD_GetBaseName ========
++ */
++DSP_STATUS COD_GetBaseName(struct COD_MANAGER *hManager, char *pszName,
++                              u32 uSize)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(IsValid(hManager));
++      DBC_Require(pszName != NULL);
++
++      if (uSize <= COD_MAXPATHLENGTH)
++               strncpy(pszName, hManager->szZLFile, uSize);
++      else
++              status = DSP_EFAIL;
++
++      return status;
++}
++
++/*
++ *  ======== COD_GetEntry ========
++ *  Purpose:
++ *      Retrieve the entry point of a loaded DSP program image
++ *
++ */
++DSP_STATUS COD_GetEntry(struct COD_MANAGER *hManager, u32 *pulEntry)
++{
++      DBC_Require(cRefs > 0);
++      DBC_Require(IsValid(hManager));
++      DBC_Require(pulEntry != NULL);
++
++      *pulEntry = hManager->ulEntry;
++
++      GT_1trace(COD_debugMask, GT_ENTER, "COD_GetEntry:ulEntr 0x%x\n",
++                *pulEntry);
++
++      return DSP_SOK;
++}
++
++/*
++ *  ======== COD_GetLoader ========
++ *  Purpose:
++ *      Get handle to the DBLL loader.
++ */
++DSP_STATUS COD_GetLoader(struct COD_MANAGER *hManager,
++                             struct DBLL_TarObj **phLoader)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(IsValid(hManager));
++      DBC_Require(phLoader != NULL);
++
++      *phLoader = (struct DBLL_TarObj *)hManager->target;
++
++      return status;
++}
++
++/*
++ *  ======== COD_GetSection ========
++ *  Purpose:
++ *      Retrieve the starting address and length of a section in the COFF file
++ *      given the section name.
++ */
++DSP_STATUS COD_GetSection(struct COD_LIBRARYOBJ *lib, IN char *pstrSect,
++                        OUT u32 *puAddr, OUT u32 *puLen)
++{
++      struct COD_MANAGER *hManager;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(lib != NULL);
++      DBC_Require(IsValid(lib->hCodMgr));
++      DBC_Require(pstrSect != NULL);
++      DBC_Require(puAddr != NULL);
++      DBC_Require(puLen != NULL);
++
++      GT_4trace(COD_debugMask, GT_ENTER,
++                "Entered COD_GetSection Args \t\n lib: "
++                "0x%x\t\npstrsect: 0x%x\t\npuAddr: 0x%x\t\npuLen: 0x%x\n",
++                lib, pstrSect, puAddr, puLen);
++      *puAddr = 0;
++      *puLen = 0;
++      if (lib != NULL) {
++              hManager = lib->hCodMgr;
++              status = hManager->fxns.getSectFxn(lib->dbllLib, pstrSect,
++                                                 puAddr, puLen);
++              if (DSP_FAILED(status)) {
++                      GT_1trace(COD_debugMask, GT_7CLASS,
++                               "COD_GetSection: Section %s not"
++                               "found\n", pstrSect);
++              }
++      } else {
++              status = COD_E_NOSYMBOLSLOADED;
++              GT_0trace(COD_debugMask, GT_7CLASS,
++                        "COD_GetSection:No Symbols loaded\n");
++      }
++
++      DBC_Ensure(DSP_SUCCEEDED(status) || ((*puAddr == 0) && (*puLen == 0)));
++
++      return status;
++}
++
++/*
++ *  ======== COD_GetSymValue ========
++ *  Purpose:
++ *      Retrieve the value for the specified symbol. The symbol is first
++ *      searched for literally and then, if not found, searched for as a
++ *      C symbol.
++ *
++ */
++DSP_STATUS COD_GetSymValue(struct COD_MANAGER *hMgr, char *pstrSym,
++                         u32 *pulValue)
++{
++      struct DBLL_Symbol *pSym;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(IsValid(hMgr));
++      DBC_Require(pstrSym != NULL);
++      DBC_Require(pulValue != NULL);
++
++      GT_3trace(COD_debugMask, GT_ENTER, "Entered COD_GetSymValue Args \t\n"
++                "hMgr: 0x%x\t\npstrSym: 0x%x\t\npulValue: 0x%x\n",
++                hMgr, pstrSym, pulValue);
++      if (hMgr->baseLib) {
++              if (!hMgr->fxns.getAddrFxn(hMgr->baseLib, pstrSym, &pSym)) {
++                      if (!hMgr->fxns.getCAddrFxn(hMgr->baseLib, pstrSym,
++                          &pSym)) {
++                              GT_0trace(COD_debugMask, GT_7CLASS,
++                                        "COD_GetSymValue: "
++                                        "Symbols not found\n");
++                              return COD_E_SYMBOLNOTFOUND;
++                      }
++              }
++      } else {
++              GT_0trace(COD_debugMask, GT_7CLASS, "COD_GetSymValue: "
++                       "No Symbols loaded\n");
++              return COD_E_NOSYMBOLSLOADED;
++      }
++
++      *pulValue = pSym->value;
++
++      return DSP_SOK;
++}
++
++/*
++ *  ======== COD_Init ========
++ *  Purpose:
++ *      Initialize the COD module's private state.
++ *
++ */
++bool COD_Init(void)
++{
++      bool fRetVal = true;
++
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++              DBC_Assert(!COD_debugMask.flags);
++              GT_create(&COD_debugMask, "CO");
++      }
++
++      if (fRetVal)
++              cRefs++;
++
++
++      GT_1trace(COD_debugMask, GT_1CLASS,
++                "Entered COD_Init, ref count: 0x%x\n", cRefs);
++      DBC_Ensure((fRetVal && cRefs > 0) || (!fRetVal && cRefs >= 0));
++      return fRetVal;
++}
++
++/*
++ *  ======== COD_LoadBase ========
++ *  Purpose:
++ *      Load the initial program image, optionally with command-line arguments,
++ *      on the DSP system managed by the supplied handle. The program to be
++ *      loaded must be the first element of the args array and must be a fully
++ *      qualified pathname.
++ *  Details:
++ *      if nArgc doesn't match the number of arguments in the aArgs array, the
++ *      aArgs array is searched for a NULL terminating entry, and argc is
++ *      recalculated to reflect this.  In this way, we can support NULL
++ *      terminating aArgs arrays, if nArgc is very large.
++ */
++DSP_STATUS COD_LoadBase(struct COD_MANAGER *hMgr, u32 nArgc, char *aArgs[],
++                      COD_WRITEFXN pfnWrite, void *pArb, char *envp[])
++{
++      DBLL_Flags flags;
++      struct DBLL_Attrs saveAttrs;
++      struct DBLL_Attrs newAttrs;
++      DSP_STATUS status;
++      u32 i;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(IsValid(hMgr));
++      DBC_Require(nArgc > 0);
++      DBC_Require(aArgs != NULL);
++      DBC_Require(aArgs[0] != NULL);
++      DBC_Require(pfnWrite != NULL);
++      DBC_Require(hMgr->baseLib != NULL);
++
++      GT_6trace(COD_debugMask, GT_ENTER,
++               "Entered COD_LoadBase, hMgr:  0x%x\n \t"
++               "nArgc:  0x%x\n\taArgs:  0x%x\n\tpfnWrite:  0x%x\n\tpArb:"
++               " 0x%x\n \tenvp:  0x%x\n", hMgr, nArgc, aArgs, pfnWrite,
++               pArb, envp);
++      /*
++       *  Make sure every argv[] stated in argc has a value, or change argc to
++       *  reflect true number in NULL terminated argv array.
++       */
++      for (i = 0; i < nArgc; i++) {
++              if (aArgs[i] == NULL) {
++                      nArgc = i;
++                      break;
++              }
++      }
++
++      /* set the write function for this operation */
++      hMgr->fxns.getAttrsFxn(hMgr->target, &saveAttrs);
++
++      newAttrs = saveAttrs;
++      newAttrs.write = (DBLL_WriteFxn)pfnWrite;
++      newAttrs.wHandle = pArb;
++      newAttrs.alloc = (DBLL_AllocFxn)NoOp;
++      newAttrs.free = (DBLL_FreeFxn)NoOp;
++      newAttrs.logWrite = NULL;
++      newAttrs.logWriteHandle = NULL;
++
++      /* Load the image */
++      flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
++      status = hMgr->fxns.loadFxn(hMgr->baseLib, flags, &newAttrs,
++               &hMgr->ulEntry);
++      if (DSP_FAILED(status)) {
++              hMgr->fxns.closeFxn(hMgr->baseLib);
++              GT_1trace(COD_debugMask, GT_7CLASS,
++                        "COD_LoadBase: COD Load failed: "
++                        "0x%x\n", status);
++      }
++      if (DSP_SUCCEEDED(status))
++              hMgr->fLoaded = true;
++      else
++              hMgr->baseLib = NULL;
++
++      return status;
++}
++
++/*
++ *  ======== COD_Open ========
++ *      Open library for reading sections.
++ */
++DSP_STATUS COD_Open(struct COD_MANAGER *hMgr, IN char *pszCoffPath,
++                  COD_FLAGS flags, struct COD_LIBRARYOBJ **pLib)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct COD_LIBRARYOBJ *lib = NULL;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(IsValid(hMgr));
++      DBC_Require(pszCoffPath != NULL);
++      DBC_Require(flags == COD_NOLOAD || flags == COD_SYMB);
++      DBC_Require(pLib != NULL);
++
++      GT_4trace(COD_debugMask, GT_ENTER, "Entered COD_Open, hMgr: 0x%x\n\t "
++                "pszCoffPath:  0x%x\tflags: 0x%x\tlib: 0x%x\n", hMgr,
++                pszCoffPath, flags, pLib);
++
++      *pLib = NULL;
++
++      lib = MEM_Calloc(sizeof(struct COD_LIBRARYOBJ), MEM_NONPAGED);
++      if (lib == NULL) {
++              GT_0trace(COD_debugMask, GT_7CLASS,
++                       "COD_Open: Out Of Memory\n");
++              status = DSP_EMEMORY;
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              lib->hCodMgr = hMgr;
++              status = hMgr->fxns.openFxn(hMgr->target, pszCoffPath, flags,
++                                         &lib->dbllLib);
++              if (DSP_FAILED(status)) {
++                      GT_1trace(COD_debugMask, GT_7CLASS,
++                               "COD_Open failed: 0x%x\n", status);
++              } else {
++                      *pLib = lib;
++              }
++      }
++
++      return status;
++}
++
++/*
++ *  ======== COD_OpenBase ========
++ *  Purpose:
++ *      Open base image for reading sections.
++ */
++DSP_STATUS COD_OpenBase(struct COD_MANAGER *hMgr, IN char *pszCoffPath,
++                      DBLL_Flags flags)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DBLL_LibraryObj *lib;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(IsValid(hMgr));
++      DBC_Require(pszCoffPath != NULL);
++
++      GT_2trace(COD_debugMask, GT_ENTER,
++                "Entered COD_OpenBase, hMgr:  0x%x\n\t"
++                "pszCoffPath:  0x%x\n", hMgr, pszCoffPath);
++
++      /* if we previously opened a base image, close it now */
++      if (hMgr->baseLib) {
++              if (hMgr->fLoaded) {
++                      GT_0trace(COD_debugMask, GT_7CLASS,
++                               "Base Image is already loaded. "
++                               "Unloading it...\n");
++                      hMgr->fxns.unloadFxn(hMgr->baseLib, &hMgr->attrs);
++                      hMgr->fLoaded = false;
++              }
++              hMgr->fxns.closeFxn(hMgr->baseLib);
++              hMgr->baseLib = NULL;
++      } else {
++              GT_0trace(COD_debugMask, GT_1CLASS,
++                       "COD_OpenBase: Opening the base image ...\n");
++      }
++      status = hMgr->fxns.openFxn(hMgr->target, pszCoffPath, flags, &lib);
++      if (DSP_FAILED(status)) {
++              GT_0trace(COD_debugMask, GT_7CLASS,
++                       "COD_OpenBase: COD Open failed\n");
++      } else {
++              /* hang onto the library for subsequent sym table usage */
++              hMgr->baseLib = lib;
++               strncpy(hMgr->szZLFile, pszCoffPath, COD_MAXPATHLENGTH);
++      }
++
++      return status;
++}
++
++/*
++ *  ======== COD_ReadSection ========
++ *  Purpose:
++ *      Retrieve the content of a code section given the section name.
++ */
++DSP_STATUS COD_ReadSection(struct COD_LIBRARYOBJ *lib, IN char *pstrSect,
++                         OUT char *pstrContent, IN u32 cContentSize)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(lib != NULL);
++      DBC_Require(IsValid(lib->hCodMgr));
++      DBC_Require(pstrSect != NULL);
++      DBC_Require(pstrContent != NULL);
++
++      GT_4trace(COD_debugMask, GT_ENTER, "Entered COD_ReadSection Args: 0x%x,"
++               " 0x%x, 0x%x, 0x%x\n", lib, pstrSect, pstrContent,
++               cContentSize);
++
++      if (lib != NULL) {
++              status = lib->hCodMgr->fxns.readSectFxn(lib->dbllLib, pstrSect,
++                                                      pstrContent,
++                                                      cContentSize);
++              if (DSP_FAILED(status)) {
++                      GT_1trace(COD_debugMask, GT_7CLASS,
++                               "COD_ReadSection failed: 0x%lx\n", status);
++              }
++      } else {
++              status = COD_E_NOSYMBOLSLOADED;
++              GT_0trace(COD_debugMask, GT_7CLASS,
++                        "COD_ReadSection: No Symbols loaded\n");
++      }
++      return status;
++}
++
++/*
++ *  ======== NoOp ========
++ *  Purpose:
++ *      No Operation.
++ *
++ */
++static bool NoOp(void)
++{
++      return true;
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dbl.c b/drivers/dsp/bridge/pmgr/dbl.c
+new file mode 100644
+index 0000000..641b011
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dbl.c
+@@ -0,0 +1,1385 @@
++/*
++ * dbl.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dbl.c ========
++ *  Dynamic BOF Loader library. Contains functions related to
++ *  loading and unloading symbols/code/data on DSP.
++ *  Also contains other support functions.
++ *
++ *! Revision History
++ *! ================
++ *! 24-Feb-2003 swa   PMGR Code review comments incorporated.
++ *! 24-May-2002 jeh     Free DCD sects in DBL_close().
++ *! 19-Mar-2002 jeh     Changes made to match dynamic loader (dbll.c): Pass
++ *!                DBL_Library to DBL_getAddr() instead of DBL_Target,
++ *!                eliminate scope param, use DBL_Symbol. Pass attrs to
++ *!                DBL_load(), DBL_unload().
++ *! 20-Nov-2001 jeh     Removed DBL_loadArgs().
++ *! 07-Sep-2001 jeh     Added overlay support.
++ *! 31-Jul-2001 jeh     Include windows.h.
++ *! 06-Jun-2001 jeh     Created.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/kfile.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/dbof.h>
++#include <dspbridge/dbl.h>
++
++#define DBL_TARGSIGNATURE      0x544c4244     /* "TLBD" */
++#define DBL_LIBSIGNATURE       0x4c4c4244     /* "LLBD" */
++
++#define C54TARG        0
++#define C55TARG        1
++#define NUMTARGS      2
++
++#define C54MAGIC      0x98    /* Magic number for TI C54 COF  */
++#define C55MAGIC      0x9c    /* Magic number for LEAD3 (C55) COF  */
++
++/* Three task phases */
++#define CREATEPHASE 0
++#define DELETEPHASE 1
++#define EXECUTEPHASE 2
++#define NONE 3                /* For overlay section with phase not specified */
++
++/* Default load buffer size */
++#define LOADBUFSIZE     0x800
++
++#define SWAPLONG(x) ((((x) << 24) & 0xFF000000) | (((x) << 8) & 0xFF0000L) | \
++                    (((x) >> 8) & 0xFF00L) | (((x) >> 24) & 0xFF))
++
++#define SWAPWORD(x) ((((x) << 8) & 0xFF00) | (((x) >> 8) & 0xFF))
++
++/*
++ *  Macros for accessing the following types of overlay data within a
++ *  structure of type OvlyData:
++ *      - Overlay data not associated with a particular phase
++ *      - Create phase overlay data
++ *      - Delete phase overlay data
++ *      - Execute phase overlay data
++ */
++#define numOtherSects(pOvlyData)    ((pOvlyData)->hdr.dbofHdr.numOtherSects)
++#define numCreateSects(pOvlyData)   ((pOvlyData)->hdr.dbofHdr.numCreateSects)
++#define numDeleteSects(pOvlyData)   ((pOvlyData)->hdr.dbofHdr.numDeleteSects)
++#define numExecuteSects(pOvlyData)  ((pOvlyData)->hdr.dbofHdr.numExecuteSects)
++#define otherOffset(pOvlyData)      0
++#define createOffset(pOvlyData)     ((pOvlyData)->hdr.dbofHdr.numOtherSects)
++#define deleteOffset(pOvlyData)     (createOffset(pOvlyData) + \
++                                   (pOvlyData->hdr.dbofHdr.numCreateSects))
++#define executeOffset(pOvlyData)    (deleteOffset(pOvlyData) + \
++                                   (pOvlyData->hdr.dbofHdr.numDeleteSects))
++/*
++ *  ======== OvlyHdr ========
++ */
++struct OvlyHdr {
++      struct DBOF_OvlySectHdr dbofHdr;
++      char *pName;            /* Name of overlay section */
++      u16 createRef;  /* Reference count for create phase */
++      u16 deleteRef;  /* Reference count for delete phase */
++      u16 executeRef;         /* Execute phase ref count */
++      u16 otherRef;           /* Unspecified phase ref count */
++} ;
++
++/*
++ *  ======== OvlyData ========
++ */
++struct OvlyData {
++      struct OvlyHdr hdr;
++      struct DBOF_OvlySectData data[1];
++} ;
++
++/*
++ *  ======== Symbol ========
++ */
++struct Symbol {
++      struct DBL_Symbol sym;
++      char *pSymName;
++};
++
++/*
++ *  ======== DCDSect ========
++ */
++struct DCDSect {
++      struct DBOF_DCDSectHdr sectHdr;
++      char *pData;
++} ;
++
++/*
++ *  ======== DBL_TargetObj ========
++ */
++struct DBL_TargetObj {
++      u32 dwSignature;        /* For object validation */
++      struct DBL_Attrs dblAttrs;      /* file read, write, etc. functions */
++      char *pBuf;             /* Load buffer */
++};
++
++/*
++ *  ======== TargetInfo ========
++ */
++struct TargetInfo {
++      u16 dspType;            /* eg, C54TARG, C55TARG */
++      u32 magic;              /* COFF magic number, identifies target type */
++      u16 wordSize;   /* Size of a DSP word */
++      u16 mauSize;            /* Size of minimum addressable unit */
++      u16 charSize;   /* For C55x, mausize = 1, but charsize = 2 */
++} ;
++
++/*
++ *  ======== DBL_LibraryObj ========
++ *  Represents a library loaded on a target.
++ */
++struct DBL_LibraryObj {
++      u32 dwSignature;        /* For object validation */
++      struct DBL_TargetObj *pTarget;  /* Target for this library */
++      struct KFILE_FileObj *file;     /* DBOF file handle */
++      bool byteSwapped;       /* Are bytes swapped? */
++      struct DBOF_FileHdr fileHdr;    /* Header of DBOF file */
++      u16 nSymbols;           /* Number of DSP/Bridge symbols */
++      struct Symbol *symbols;         /* Table of DSP/Bridge symbols */
++      u16 nDCDSects;  /* Number of DCD sections */
++      u16 nOvlySects;         /* Number of overlay nodes */
++      struct DCDSect *dcdSects;       /* DCD section data */
++      struct OvlyData **ppOvlyData;   /* Array of overlay section data */
++      struct TargetInfo *pTargetInfo;         /* Entry in targetTab[] below */
++} ;
++
++#if GT_TRACE
++static struct GT_Mask DBL_debugMask = { NULL, NULL };         /* GT trace variable */
++#endif
++
++static u32 cRefs;             /* module reference count */
++
++static u32 magicTab[NUMTARGS] = { C54MAGIC, C55MAGIC };
++
++static struct TargetInfo targetTab[] = {
++      /* targ     magic       wordsize    mausize    charsize */
++      {C54TARG, C54MAGIC, 2, 2, 2},   /* C54  */
++      {C55TARG, C55MAGIC, 2, 1, 2},   /* C55  */
++};
++
++static void freeSects(struct DBL_TargetObj *dbl, struct OvlyData *pOvlyData,
++                   s32 offset, s32 nSects);
++static DSP_STATUS loadSect(struct DBL_TargetObj *dbl,
++                        struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readDCDSects(struct DBL_TargetObj *dbl,
++                            struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readHeader(struct DBL_TargetObj *dbl,
++                          struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readOvlySects(struct DBL_TargetObj *dbl,
++                              struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readSymbols(struct DBL_TargetObj *dbl,
++                           struct DBL_LibraryObj *pdblLib);
++
++/*
++ *  ======== DBL_close ========
++ *  Purpose:
++ *    Close library opened with DBL_open.
++ */
++void DBL_close(struct DBL_LibraryObj *lib)
++{
++      struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++      u16 i;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++
++      GT_1trace(DBL_debugMask, GT_ENTER, "DBL_close: lib: 0x%x\n", lib);
++
++      /* Free symbols */
++      if (pdblLib->symbols) {
++              for (i = 0; i < pdblLib->nSymbols; i++) {
++                      if (pdblLib->symbols[i].pSymName)
++                              MEM_Free(pdblLib->symbols[i].pSymName);
++
++              }
++              MEM_Free(pdblLib->symbols);
++      }
++
++      /* Free DCD sects */
++      if (pdblLib->dcdSects) {
++              for (i = 0; i < pdblLib->nDCDSects; i++) {
++                      if (pdblLib->dcdSects[i].pData)
++                              MEM_Free(pdblLib->dcdSects[i].pData);
++
++              }
++              MEM_Free(pdblLib->dcdSects);
++      }
++
++      /* Free overlay sects */
++      if (pdblLib->ppOvlyData) {
++              for (i = 0;  i < pdblLib->nOvlySects;  i++) {
++                      if (pdblLib->ppOvlyData[i]) {
++                              if (pdblLib->ppOvlyData[i]->hdr.pName) {
++                                      MEM_Free(pdblLib->ppOvlyData[i]->
++                                              hdr.pName);
++                              }
++                              MEM_Free(pdblLib->ppOvlyData[i]);
++                      }
++              }
++              MEM_Free(pdblLib->ppOvlyData);
++      }
++
++      /* Close the file */
++      if (pdblLib->file)
++              (*pdblLib->pTarget->dblAttrs.fclose) (pdblLib->file);
++
++
++      MEM_FreeObject(pdblLib);
++}
++
++/*
++ *  ======== DBL_create ========
++ *  Purpose:
++ *    Create a target object by specifying the alloc, free, and
++ *    write functions for the target.
++ */
++DSP_STATUS DBL_create(struct DBL_TargetObj **pTarget, struct DBL_Attrs *pAttrs)
++{
++      struct DBL_TargetObj *pdblTarget = NULL;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pAttrs != NULL);
++      DBC_Require(pTarget != NULL);
++
++      GT_2trace(DBL_debugMask, GT_ENTER,
++               "DBL_create: pTarget: 0x%x pAttrs: 0x%x\n",
++               pTarget, pAttrs);
++      /* Allocate DBL target object */
++      MEM_AllocObject(pdblTarget, struct DBL_TargetObj, DBL_TARGSIGNATURE);
++      if (pdblTarget == NULL) {
++              GT_0trace(DBL_debugMask, GT_6CLASS,
++                       "DBL_create: Memory allocation failed\n");
++              status = DSP_EMEMORY;
++      } else {
++              pdblTarget->dblAttrs = *pAttrs;
++              /* Allocate buffer for loading target */
++              pdblTarget->pBuf = MEM_Calloc(LOADBUFSIZE, MEM_PAGED);
++              if (pdblTarget->pBuf == NULL)
++                      status = DSP_EMEMORY;
++
++      }
++      if (DSP_SUCCEEDED(status)) {
++              *pTarget = pdblTarget;
++      } else {
++              *pTarget = NULL;
++              if (pdblTarget)
++                      DBL_delete(pdblTarget);
++
++      }
++      DBC_Ensure(DSP_SUCCEEDED(status) &&
++                ((MEM_IsValidHandle((*pTarget), DBL_TARGSIGNATURE)) ||
++                (DSP_FAILED(status) && *pTarget == NULL)));
++      return status;
++}
++
++/*
++ *  ======== DBL_delete ========
++ *  Purpose:
++ *    Delete target object and free resources for any loaded libraries.
++ */
++void DBL_delete(struct DBL_TargetObj *target)
++{
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++
++      GT_1trace(DBL_debugMask, GT_ENTER,
++               "DBL_delete: target: 0x%x\n", target);
++
++      if (target->pBuf)
++              MEM_Free(target->pBuf);
++
++      MEM_FreeObject(target);
++}
++
++/*
++ *  ======== DBL_exit ========
++ *  Purpose
++ *    Discontinue usage of DBL module.
++ */
++void DBL_exit()
++{
++      DBC_Require(cRefs > 0);
++      cRefs--;
++      GT_1trace(DBL_debugMask, GT_5CLASS,
++               "DBL_exit() ref count: 0x%x\n", cRefs);
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== DBL_getAddr ========
++ *  Purpose:
++ *    Get address of name in the specified library.
++ */
++bool DBL_getAddr(struct DBL_LibraryObj *lib, char *name,
++              struct DBL_Symbol **ppSym)
++{
++      bool retVal = false;
++      struct Symbol *symbol;
++      u16 i;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++      DBC_Require(name != NULL);
++      DBC_Require(ppSym != NULL);
++
++      GT_3trace(DBL_debugMask, GT_ENTER,
++               "DBL_getAddr: libt: 0x%x name: %s pAddr: "
++               "0x%x\n", lib, name, ppSym);
++      for (i = 0; i < lib->nSymbols; i++) {
++              symbol = &lib->symbols[i];
++              if (CSL_Strcmp(name, symbol->pSymName) == 0) {
++                      /* Found it */
++                      *ppSym = &lib->symbols[i].sym;
++                      retVal = true;
++                      break;
++              }
++      }
++      return retVal;
++}
++
++/*
++ *  ======== DBL_getAttrs ========
++ *  Purpose:
++ *    Retrieve the attributes of the target.
++ */
++void DBL_getAttrs(struct DBL_TargetObj *target, struct DBL_Attrs *pAttrs)
++{
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++      DBC_Require(pAttrs != NULL);
++      GT_2trace(DBL_debugMask, GT_ENTER, "DBL_getAttrs: target: 0x%x pAttrs: "
++                "0x%x\n", target, pAttrs);
++      *pAttrs = target->dblAttrs;
++}
++
++/*
++ *  ======== DBL_getCAddr ========
++ *  Purpose:
++ *    Get address of "C" name in the specified library.
++ */
++bool DBL_getCAddr(struct DBL_LibraryObj *lib, char *name,
++               struct DBL_Symbol **ppSym)
++{
++      bool retVal = false;
++      struct Symbol *symbol;
++      u16 i;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++      DBC_Require(name != NULL);
++      DBC_Require(ppSym != NULL);
++
++      GT_3trace(DBL_debugMask, GT_ENTER,
++               "DBL_getCAddr: target: 0x%x name:%s pAddr:"
++               " 0x%x\n", lib, name, ppSym);
++      for (i = 0;  i < lib->nSymbols;  i++) {
++              symbol = &lib->symbols[i];
++              if ((CSL_Strcmp(name, symbol->pSymName) == 0) ||
++                  (CSL_Strcmp(name, symbol->pSymName + 1) == 0 &&
++                   symbol->pSymName[0] == '_')) {
++                      /* Found it */
++                      *ppSym = &lib->symbols[i].sym;
++                      retVal = true;
++                      break;
++              }
++      }
++      return retVal;
++}
++
++/*
++ *  ======== DBL_getEntry ========
++ *  Purpose:
++ *    Get program entry point.
++ *
++ */
++bool DBL_getEntry(struct DBL_LibraryObj *lib, u32 *pEntry)
++{
++      struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++      DBC_Require(pEntry != NULL);
++
++      GT_2trace(DBL_debugMask, GT_ENTER,
++               "DBL_getEntry: lib: 0x%x pEntry: 0x%x\n", lib, pEntry);
++      *pEntry = pdblLib->fileHdr.entry;
++
++      return true;
++}
++
++/*
++ *  ======== DBL_getSect ========
++ *  Purpose:
++ *    Get address and size of a named section.
++ */
++DSP_STATUS DBL_getSect(struct DBL_LibraryObj *lib, char *name, u32 *pAddr,
++                    u32 *pSize)
++{
++      struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++      u16 i;
++      DSP_STATUS status = DSP_ENOSECT;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(name != NULL);
++      DBC_Require(pAddr != NULL);
++      DBC_Require(pSize != NULL);
++      DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++
++      GT_4trace(DBL_debugMask, GT_ENTER,
++               "DBL_getSect: lib: 0x%x name: %s pAddr:"
++               " 0x%x pSize: 0x%x\n", lib, name, pAddr, pSize);
++
++      /*
++       *  Check for DCD and overlay sections. Overlay loader uses DBL_getSect
++       *  to determine whether or not a node has overlay sections.
++       *  DCD section names begin with '.'
++       */
++      if (name[0] == '.') {
++              /* Get DCD section size (address is 0, since it's a NOLOAD). */
++              for (i = 0; i < pdblLib->nDCDSects; i++) {
++                      if (CSL_Strcmp(pdblLib->dcdSects[i].sectHdr.name,
++                         name) == 0) {
++                              *pAddr = 0;
++                              *pSize = pdblLib->dcdSects[i].sectHdr.size *
++                                       pdblLib->pTargetInfo->mauSize;
++                              status = DSP_SOK;
++                              break;
++                      }
++              }
++      } else {
++              /* Check for overlay section */
++              for (i = 0;  i < pdblLib->nOvlySects;  i++) {
++                      if (CSL_Strcmp(pdblLib->ppOvlyData[i]->hdr.pName,
++                         name) == 0) {
++                              /* Address and size are meaningless */
++                              *pAddr = 0;
++                              *pSize = 0;
++                              status = DSP_SOK;
++                              break;
++                      }
++              }
++      }
++
++      return status;
++}
++
++/*
++ *  ======== DBL_init ========
++ *  Purpose:
++ *    Initialize DBL module.
++ */
++bool DBL_init(void)
++{
++      bool retVal = true;
++
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++              DBC_Assert(!DBL_debugMask.flags);
++              GT_create(&DBL_debugMask, "BL");        /* "BL" for dBL */
++
++      }
++
++      if (retVal)
++              cRefs++;
++
++
++      GT_1trace(DBL_debugMask, GT_5CLASS, "DBL_init(), ref count:  0x%x\n",
++                cRefs);
++
++      DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
++
++      return retVal;
++}
++
++/*
++ *  ======== DBL_load ========
++ *  Purpose:
++ *    Add symbols/code/data defined in file to that already present
++ *    on the target.
++ */
++DSP_STATUS DBL_load(struct DBL_LibraryObj *lib, DBL_Flags flags,
++                 struct DBL_Attrs *attrs, u32 *pEntry)
++{
++      struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++      struct DBL_TargetObj *dbl;
++      u16 i;
++      u16 nSects;
++      DSP_STATUS status = DSP_EFAIL;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++      DBC_Require(pEntry != NULL);
++      DBC_Require(attrs != NULL);
++
++      GT_4trace(DBL_debugMask, GT_ENTER, "DBL_load: lib: 0x%x flags: "
++               "0x%x attrs: 0x%x pEntry: 0x%x\n", lib, flags, attrs, pEntry);
++
++      dbl = pdblLib->pTarget;
++      *pEntry = pdblLib->fileHdr.entry;
++      nSects = pdblLib->fileHdr.numSects;
++      dbl->dblAttrs = *attrs;
++
++      for (i = 0; i < nSects; i++) {
++              /* Load the section at the current file offset */
++              status = loadSect(dbl, lib);
++              if (DSP_FAILED(status))
++                      break;
++
++      }
++
++      /* Done with file, we can close it */
++      if (pdblLib->file) {
++              (*pdblLib->pTarget->dblAttrs.fclose) (pdblLib->file);
++              pdblLib->file = NULL;
++      }
++      return status;
++}
++
++/*
++ *  ======== DBL_loadSect ========
++ *  Purpose:
++ *    Load a named section from an library (for overlay support).
++ */
++DSP_STATUS DBL_loadSect(struct DBL_LibraryObj *lib, char *sectName,
++                      struct DBL_Attrs *attrs)
++{
++      struct DBL_TargetObj *dbl;
++      s32 i;
++      s32 phase;
++      s32 offset = -1;
++      s32 nSects = -1;
++      s32 allocdSects = 0;
++      u32 loadAddr;
++      u32 runAddr;
++      u32 size;
++      u32 space;
++      u32 ulBytes;
++      u16 mauSize;
++      u16 wordSize;
++      u16 *phaseRef = NULL;
++      u16 *otherRef = NULL;
++      char *name = NULL;
++      struct OvlyData *pOvlyData;
++      DSP_STATUS status = DSP_ENOSECT;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++      DBC_Require(sectName != NULL);
++      DBC_Require(attrs != NULL);
++      DBC_Require(attrs->write != NULL);
++      GT_3trace(DBL_debugMask, GT_ENTER,
++               "DBL_loadSect: lib: 0x%x sectName: %s "
++               "attrs: 0x%x\n", lib, sectName, attrs);
++      dbl = lib->pTarget;
++      mauSize = lib->pTargetInfo->mauSize;
++      wordSize = lib->pTargetInfo->wordSize;
++      /* Check for match of sect name in overlay table */
++      for (i = 0; i < lib->nOvlySects; i++) {
++              name = lib->ppOvlyData[i]->hdr.pName;
++              if (!CSL_Strncmp(name, sectName, CSL_Strlen(name))) {
++                      /* Match found */
++                      status = DSP_SOK;
++                      break;
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              DBC_Assert(i < lib->nOvlySects);
++              pOvlyData = lib->ppOvlyData[i];
++              /*
++               *  If node overlay, phase will be encoded in name. If not node
++               *  overlay, set phase to NONE.
++               */
++              phase = (CSL_Strcmp(name, sectName)) ?
++                      CSL_Atoi(sectName + CSL_Strlen(sectName) - 1) : NONE;
++               /*  Get reference count of node phase to be loaded, offset into
++               *  overlay data array, and number of sections to overlay.  */
++              switch (phase) {
++              case NONE:
++                      /* Not a node overlay */
++                      phaseRef = &pOvlyData->hdr.otherRef;
++                      nSects = numOtherSects(pOvlyData);
++                      offset = otherOffset(pOvlyData);
++                      break;
++              case CREATEPHASE:
++                      phaseRef = &pOvlyData->hdr.createRef;
++                      otherRef = &pOvlyData->hdr.otherRef;
++                      if (*otherRef) {
++                              /* The overlay sections where node phase was
++                               * not specified, have already been loaded.  */
++                              nSects = numCreateSects(pOvlyData);
++                              offset = createOffset(pOvlyData);
++                      } else {
++                              /* Overlay sections where node phase was not
++                               * specified get loaded at create time, along
++                               * with create sects.  */
++                              nSects = numCreateSects(pOvlyData) +
++                                       numOtherSects(pOvlyData);
++                              offset = otherOffset(pOvlyData);
++                      }
++                      break;
++              case DELETEPHASE:
++                      phaseRef = &pOvlyData->hdr.deleteRef;
++                      nSects = numDeleteSects(pOvlyData);
++                      offset = deleteOffset(pOvlyData);
++                      break;
++              case EXECUTEPHASE:
++                      phaseRef = &pOvlyData->hdr.executeRef;
++                      nSects = numExecuteSects(pOvlyData);
++                      offset = executeOffset(pOvlyData);
++                      break;
++              default:
++                      /* ERROR */
++                      DBC_Assert(false);
++                      break;
++              }
++              /* Do overlay if reference count is 0 */
++              if (!(*phaseRef)) {
++                      /* "Allocate" all sections */
++                      for (i = 0; i < nSects; i++) {
++                              runAddr = pOvlyData->data[offset + i].runAddr;
++                              size = pOvlyData->data[offset + i].size;
++                              space = pOvlyData->data[offset + i].page;
++                              status = (dbl->dblAttrs.alloc)(dbl->dblAttrs.
++                                       rmmHandle, space, size, 0,
++                                       &runAddr, true);
++                              if (DSP_FAILED(status))
++                                      break;
++
++                              allocdSects++;
++                      }
++                      if (DSP_SUCCEEDED(status)) {
++                              /* Load sections */
++                              for (i = 0; i < nSects; i++) {
++                                      loadAddr = pOvlyData->data[offset + i].
++                                                 loadAddr;
++                                      runAddr = pOvlyData->data[offset + i].
++                                                runAddr;
++                                      size = pOvlyData->data[offset + i].
++                                              size;
++                                      space = pOvlyData->data[offset + i].
++                                              page;
++                                      /* Convert to word address, call
++                                       * write function */
++                                      loadAddr /= (wordSize / mauSize);
++                                      runAddr /= (wordSize / mauSize);
++                                      ulBytes = size * mauSize;
++                                      if ((*attrs->write)(attrs->wHandle,
++                                         runAddr, (void *)loadAddr, ulBytes,
++                                         space) != ulBytes) {
++                                              GT_0trace(DBL_debugMask,
++                                                      GT_6CLASS,
++                                                      "DBL_loadSect: write"
++                                                      " failed\n");
++                                              status = DSP_EFWRITE;
++                                              break;
++                                      }
++                              }
++                      }
++                      /* Free sections on failure */
++                      if (DSP_FAILED(status))
++                              freeSects(dbl, pOvlyData, offset, allocdSects);
++
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Increment reference counts */
++              if (otherRef)
++                      *otherRef = *otherRef + 1;
++
++              *phaseRef = *phaseRef + 1;
++      }
++      return status;
++}
++
++/*
++ *  ======== DBL_open ========
++ *  Purpose:
++ *    DBL_open() returns a library handle that can be used to
++ *    load/unload the symbols/code/data via DBL_load()/DBL_unload().
++ */
++DSP_STATUS DBL_open(struct DBL_TargetObj *target, char *file, DBL_Flags flags,
++                 struct DBL_LibraryObj **pLib)
++{
++      struct DBL_LibraryObj *pdblLib = NULL;
++      u16 nSymbols;
++      u16 nDCDSects;
++      DSP_STATUS status = DSP_SOK;
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++      DBC_Require(target->dblAttrs.fopen != NULL);
++      DBC_Require(file != NULL);
++      DBC_Require(pLib != NULL);
++
++      GT_3trace(DBL_debugMask, GT_ENTER, "DBL_open: target: 0x%x file: %s "
++               "pLib: 0x%x\n", target, file, pLib);
++      /* Allocate DBL library object */
++      MEM_AllocObject(pdblLib, struct DBL_LibraryObj, DBL_LIBSIGNATURE);
++      if (pdblLib == NULL)
++              status = DSP_EMEMORY;
++
++      /* Open the file */
++      if (DSP_SUCCEEDED(status)) {
++              pdblLib->pTarget = target;
++              pdblLib->file = (*target->dblAttrs.fopen)(file, "rb");
++              if (pdblLib->file == NULL)
++                      status = DSP_EFOPEN;
++
++      }
++      /* Read file header */
++      if (DSP_SUCCEEDED(status)) {
++              status = readHeader(target, pdblLib);
++              if (DSP_FAILED(status)) {
++                      GT_0trace(DBL_debugMask, GT_6CLASS,
++                               "DBL_open(): Failed to read file header\n");
++              }
++      }
++      /* Allocate symbol table */
++      if (DSP_SUCCEEDED(status)) {
++              nSymbols = pdblLib->nSymbols = pdblLib->fileHdr.numSymbols;
++              pdblLib->symbols = MEM_Calloc(nSymbols * sizeof(struct Symbol),
++                                           MEM_PAGED);
++              if (pdblLib->symbols == NULL)
++                      status = DSP_EMEMORY;
++
++      }
++      /* Read all the symbols */
++      if (DSP_SUCCEEDED(status)) {
++              status = readSymbols(target, pdblLib);
++              if (DSP_FAILED(status)) {
++                      GT_0trace(DBL_debugMask, GT_6CLASS,
++                               "DBL_open(): Failed to read symbols\n");
++              }
++      }
++      /* Allocate DCD sect table */
++      if (DSP_SUCCEEDED(status)) {
++              nDCDSects = pdblLib->nDCDSects = pdblLib->fileHdr.numDCDSects;
++              pdblLib->dcdSects = MEM_Calloc(nDCDSects *
++                                       sizeof(struct DCDSect), MEM_PAGED);
++              if (pdblLib->dcdSects == NULL)
++                      status = DSP_EMEMORY;
++
++      }
++      /* Read DCD sections */
++      if (DSP_SUCCEEDED(status)) {
++              status = readDCDSects(target, pdblLib);
++              if (DSP_FAILED(status)) {
++                      GT_0trace(DBL_debugMask, GT_6CLASS,
++                               "DBL_open(): Failed to read DCD sections\n");
++              }
++      }
++      /* Read overlay sections */
++      if (DSP_SUCCEEDED(status)) {
++              status = readOvlySects(target, pdblLib);
++              if (DSP_FAILED(status)) {
++                      GT_0trace(DBL_debugMask, GT_6CLASS,
++                               "DBL_open(): Failed to read "
++                               "overlay sections\n");
++              }
++      }
++      if (DSP_FAILED(status)) {
++              *pLib = NULL;
++              if (pdblLib != NULL)
++                      DBL_close((struct DBL_LibraryObj *) pdblLib);
++
++      } else {
++              *pLib = pdblLib;
++      }
++      DBC_Ensure((DSP_SUCCEEDED(status) &&
++                (MEM_IsValidHandle((*pLib), DBL_LIBSIGNATURE))) ||
++                (DSP_FAILED(status) && *pLib == NULL));
++      return status;
++}
++
++/*
++ *  ======== DBL_readSect ========
++ *  Purpose:
++ *    Read COFF section into a character buffer.
++ */
++DSP_STATUS DBL_readSect(struct DBL_LibraryObj *lib, char *name, char *pContent,
++                      u32 size)
++{
++      struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++      u16 i;
++      u32 mauSize;
++      u32 max;
++      DSP_STATUS status = DSP_ENOSECT;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++      DBC_Require(name != NULL);
++      DBC_Require(pContent != NULL);
++      DBC_Require(size != 0);
++      GT_4trace(DBL_debugMask, GT_ENTER, "DBL_readSect: lib: 0x%x name: %s "
++               "pContent: 0x%x size: 0x%x\n", lib, name, pContent, size);
++
++      mauSize = pdblLib->pTargetInfo->mauSize;
++
++      /* Attempt to find match with DCD section names. */
++      for (i = 0; i < pdblLib->nDCDSects; i++) {
++              if (CSL_Strcmp(pdblLib->dcdSects[i].sectHdr.name, name) == 0) {
++                      /* Match found */
++                      max = pdblLib->dcdSects[i].sectHdr.size * mauSize;
++                      max = (max > size) ? size : max;
++                      memcpy(pContent, pdblLib->dcdSects[i].pData, max);
++                      status = DSP_SOK;
++                      break;
++              }
++      }
++
++      return status;
++}
++
++/*
++ *  ======== DBL_setAttrs ========
++ *  Purpose:
++ *    Set the attributes of the target.
++ */
++void DBL_setAttrs(struct DBL_TargetObj *target, struct DBL_Attrs *pAttrs)
++{
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++      DBC_Require(pAttrs != NULL);
++
++      GT_2trace(DBL_debugMask, GT_ENTER, "DBL_setAttrs: target: 0x%x pAttrs: "
++               "0x%x\n", target, pAttrs);
++
++      target->dblAttrs = *pAttrs;
++}
++
++/*
++ *  ======== DBL_unload ========
++ *  Purpose:
++ *    Remove the symbols/code/data corresponding to the library lib.
++ */
++void DBL_unload(struct DBL_LibraryObj *lib, struct DBL_Attrs *attrs)
++{
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++
++      GT_1trace(DBL_debugMask, GT_ENTER, "DBL_unload: lib: 0x%x\n", lib);
++
++      /* Nothing to do for static loading */
++}
++
++/*
++ *  ======== DBL_unloadSect ========
++ *  Purpose:
++ *    Unload a named section from an library (for overlay support).
++ */
++DSP_STATUS DBL_unloadSect(struct DBL_LibraryObj *lib, char *sectName,
++                        struct DBL_Attrs *attrs)
++{
++      struct DBL_TargetObj *dbl;
++      s32 i;
++      s32 phase;
++      s32 offset = -1;
++      s32 nSects = -1;
++      u16 *phaseRef = NULL;
++      u16 *otherRef = NULL;
++      char *pName = NULL;
++      struct OvlyData *pOvlyData;
++      DSP_STATUS status = DSP_ENOSECT;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++      DBC_Require(sectName != NULL);
++
++      GT_2trace(DBL_debugMask, GT_ENTER,
++               "DBL_unloadSect: lib: 0x%x sectName: %s\n", lib, sectName);
++      dbl = lib->pTarget;
++      /* Check for match of sect name in overlay table */
++      for (i = 0; i < lib->nOvlySects; i++) {
++              pName = lib->ppOvlyData[i]->hdr.pName;
++              if (!CSL_Strncmp(pName, sectName, CSL_Strlen(pName))) {
++                      /* Match found */
++                      status = DSP_SOK;
++                      break;
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              DBC_Assert(i < lib->nOvlySects);
++              pOvlyData = lib->ppOvlyData[i];
++              /* If node overlay, phase will be encoded in name. */
++              phase = (CSL_Strcmp(pName, sectName)) ?
++                      CSL_Atoi(sectName + CSL_Strlen(sectName) - 1) : NONE;
++              switch (phase) {
++              case NONE:
++                      nSects = numOtherSects(pOvlyData);
++                      phaseRef = &pOvlyData->hdr.otherRef;
++                      offset = otherOffset(pOvlyData);
++                      break;
++              case CREATEPHASE:
++                      nSects = numCreateSects(pOvlyData);
++                      offset = createOffset(pOvlyData);
++                      phaseRef = &pOvlyData->hdr.createRef;
++                      break;
++              case DELETEPHASE:
++                      nSects = numDeleteSects(pOvlyData);
++                      offset = deleteOffset(pOvlyData);
++                      phaseRef = &pOvlyData->hdr.deleteRef;
++                      otherRef = &pOvlyData->hdr.otherRef;
++                      break;
++              case EXECUTEPHASE:
++                      nSects = numExecuteSects(pOvlyData);
++                      offset = executeOffset(pOvlyData);
++                      phaseRef = &pOvlyData->hdr.executeRef;
++                      break;
++              default:
++                      /* ERROR */
++                      DBC_Assert(false);
++                      break;
++              }
++              if (*phaseRef) {
++                      *phaseRef = *phaseRef - 1;
++                      if (*phaseRef == 0) {
++                              /* Unload overlay sections for phase */
++                              freeSects(dbl, pOvlyData, offset, nSects);
++                      }
++                      if (phase == DELETEPHASE) {
++                              DBC_Assert(*otherRef);
++                              *otherRef = *otherRef - 1;
++                              if (*otherRef == 0) {
++                                      /* Unload other overlay sections */
++                                      nSects = numOtherSects(pOvlyData);
++                                      offset = otherOffset(pOvlyData);
++                                      freeSects(dbl, pOvlyData, offset,
++                                               nSects);
++                              }
++                      }
++              }
++      }
++
++      return status;
++}
++
++/*
++ *  ======== freeSects ========
++ *  Purpose:
++ *    Free section
++ */
++static void freeSects(struct DBL_TargetObj *dbl, struct OvlyData *pOvlyData,
++                   s32 offset, s32 nSects)
++{
++      u32 runAddr;
++      u32 size;
++      u32 space;
++      s32 i;
++
++      for (i = 0; i < nSects; i++) {
++              runAddr = pOvlyData->data[offset + i].runAddr;
++              size = pOvlyData->data[offset + i].size;
++              space = pOvlyData->data[offset + i].page;
++              if (!(dbl->dblAttrs.free)
++                  (dbl->dblAttrs.rmmHandle, space, runAddr, size, true)) {
++                      /*
++                       *  Free function will not fail for overlay, unless
++                       *  address passed in is bad.
++                       */
++                      DBC_Assert(false);
++              }
++      }
++}
++
++/*
++ *  ======== loadSect ========
++ *  Purpose:
++ *    Load section to target
++ */
++static DSP_STATUS loadSect(struct DBL_TargetObj *dbl,
++                        struct DBL_LibraryObj *pdblLib)
++{
++      struct DBOF_SectHdr sectHdr;
++      char *pBuf;
++      struct KFILE_FileObj *file;
++      u32 space;
++      u32 addr;
++      u32 total;
++      u32 nWords = 0;
++      u32 nBytes = 0;
++      u16 mauSize;
++      u32 bufSize;
++      DSP_STATUS status = DSP_SOK;
++
++      file = pdblLib->file;
++      mauSize = pdblLib->pTargetInfo->mauSize;
++      bufSize = LOADBUFSIZE / mauSize;
++      pBuf = dbl->pBuf;
++
++      /* Read the section header */
++      if ((*dbl->dblAttrs.fread)(&sectHdr, sizeof(struct DBOF_SectHdr),
++         1, file) != 1) {
++              GT_0trace(DBL_debugMask, GT_6CLASS,
++                       "Failed to read DCD sect header\n");
++              status = DSP_EFREAD;
++      } else {
++              if (pdblLib->byteSwapped) {
++                      sectHdr.size = SWAPLONG(sectHdr.size);
++                      sectHdr.addr = SWAPLONG(sectHdr.addr);
++                      sectHdr.page = SWAPWORD(sectHdr.page);
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              addr = sectHdr.addr;
++              space = sectHdr.page;
++              for (total = sectHdr.size; total > 0; total -= nWords) {
++                      nWords = min(total, bufSize);
++                      nBytes = nWords * mauSize;
++                      /* Read section data */
++                      if ((*dbl->dblAttrs.fread)(pBuf, nBytes, 1,
++                         file) != 1) {
++                              GT_0trace(DBL_debugMask, GT_6CLASS,
++                                       "Failed to read DCD sect header\n");
++                              status = DSP_EFREAD;
++                              break;
++                      }
++                      /* Write section to target */
++                      if (!(*dbl->dblAttrs.write)(dbl->dblAttrs.wHandle,
++                         addr, pBuf, nBytes, space)) {
++                              GT_0trace(DBL_debugMask, GT_6CLASS,
++                                       "Failed to write section data\n");
++                              status = DSP_EFWRITE;
++                              break;
++                      }
++                      addr += nWords;
++              }
++      }
++      return status;
++}
++
++/*
++ *  ======== readDCDSects ========
++ *  Purpose:
++ *    Read DCD sections.
++ */
++static DSP_STATUS readDCDSects(struct DBL_TargetObj *dbl,
++                            struct DBL_LibraryObj *pdblLib)
++{
++      struct DBOF_DCDSectHdr *pSectHdr;
++      struct DCDSect *pSect;
++      struct KFILE_FileObj *file;
++      u16 nSects;
++      u16 i;
++      u16 mauSize;
++      DSP_STATUS status = DSP_SOK;
++
++      file = pdblLib->file;
++      mauSize = pdblLib->pTargetInfo->mauSize;
++      nSects = pdblLib->fileHdr.numDCDSects;
++      for (i = 0; i < nSects; i++) {
++              pSect = &pdblLib->dcdSects[i];
++              pSectHdr = &pdblLib->dcdSects[i].sectHdr;
++              /* Read sect header */
++              if ((*dbl->dblAttrs.fread)(pSectHdr,
++                 sizeof(struct DBOF_DCDSectHdr), 1, file) != 1) {
++                      GT_0trace(DBL_debugMask, GT_6CLASS,
++                               "Failed to read DCD sect header\n");
++                      status = DSP_EFREAD;
++                      break;
++              }
++              if (pdblLib->byteSwapped)
++                      pSectHdr->size = SWAPLONG(pSectHdr->size);
++
++              pSect->pData = (char *)MEM_Calloc(pSectHdr->size *
++                              mauSize, MEM_PAGED);
++              if (pSect->pData == NULL) {
++                      GT_2trace(DBL_debugMask, GT_6CLASS,
++                               "Memory allocation for sect %s "
++                               "data failed: Size: 0x%lx\n", pSectHdr->name,
++                               pSectHdr->size);
++                      status = DSP_EMEMORY;
++                      break;
++              }
++              /* Read DCD sect data */
++              if ((*dbl->dblAttrs.fread)(pSect->pData, mauSize,
++                 pSectHdr->size, file) != pSectHdr->size) {
++                      GT_0trace(DBL_debugMask, GT_6CLASS,
++                                "Failed to read DCD sect data\n");
++                      status = DSP_EFREAD;
++                      break;
++              }
++      }
++
++      return status;
++}
++
++/*
++ *  ======== readHeader ========
++ *  Purpose:
++ *    Read Header.
++ */
++static DSP_STATUS readHeader(struct DBL_TargetObj *dbl,
++                          struct DBL_LibraryObj *pdblLib)
++{
++      struct KFILE_FileObj *file;
++      s32 i;
++      struct DBOF_FileHdr *pHdr;
++      u32 swapMagic;
++      DSP_STATUS status = DSP_SOK;
++
++      pdblLib->byteSwapped = false;
++      file = pdblLib->file;
++      pHdr = &pdblLib->fileHdr;
++      if ((*dbl->dblAttrs.fread)(pHdr, sizeof(struct DBOF_FileHdr), 1,
++         file) != 1) {
++              GT_0trace(DBL_debugMask, GT_6CLASS,
++                       "readHeader: Failed to read file header\n");
++              status = DSP_EFREAD;
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              /* Determine if byte swapped */
++              for (i = 0; i < NUMTARGS; i++) {
++                      swapMagic = SWAPLONG(pHdr->magic);
++                      if (pHdr->magic == magicTab[i] || swapMagic ==
++                         magicTab[i]) {
++                              if (swapMagic == magicTab[i]) {
++                                      pdblLib->byteSwapped = true;
++                                      pHdr->magic = SWAPLONG(pHdr->magic);
++                                      pHdr->entry = SWAPLONG(pHdr->entry);
++                                      pHdr->symOffset = SWAPLONG(pHdr->
++                                                              symOffset);
++                                      pHdr->dcdSectOffset = SWAPLONG(pHdr->
++                                                              dcdSectOffset);
++                                      pHdr->loadSectOffset = SWAPLONG(pHdr->
++                                                              loadSectOffset);
++                                      pHdr->ovlySectOffset = SWAPLONG(pHdr->
++                                                              ovlySectOffset);
++                                      pHdr->numSymbols = SWAPWORD(pHdr->
++                                                              numSymbols);
++                                      pHdr->numDCDSects = SWAPWORD(pHdr->
++                                                              numDCDSects);
++                                      pHdr->numSects = SWAPWORD(pHdr->
++                                                              numSects);
++                                      pHdr->numOvlySects = SWAPWORD(pHdr->
++                                                              numOvlySects);
++                              }
++                              break;
++                      }
++              }
++              if (i == NUMTARGS) {
++                      GT_0trace(DBL_debugMask, GT_6CLASS,
++                               "readHeader: Failed to determine"
++                               " target type\n");
++                      status = DSP_ECORRUPTFILE;
++              } else {
++                      pdblLib->pTargetInfo = &targetTab[i];
++                      GT_1trace(DBL_debugMask, GT_ENTER,
++                               "COF type: 0x%lx\n", pHdr->magic);
++                      GT_1trace(DBL_debugMask, GT_ENTER,
++                               "Entry point:0x%lx\n", pHdr->entry);
++              }
++      }
++      return status;
++}
++
++/*
++ *  ======== readOvlySects ========
++ *  Purpose:
++ *    Read Overlay Sections
++ */
++static DSP_STATUS readOvlySects(struct DBL_TargetObj *dbl,
++                              struct DBL_LibraryObj *pdblLib)
++{
++      struct DBOF_OvlySectHdr hdr;
++      struct DBOF_OvlySectData *pData;
++      struct OvlyData *pOvlyData;
++      char *pName;
++      struct KFILE_FileObj *file;
++      u16 i, j;
++      u16 nSects;
++      u16 n;
++      DSP_STATUS status = DSP_SOK;
++
++      pdblLib->nOvlySects = nSects = pdblLib->fileHdr.numOvlySects;
++      file = pdblLib->file;
++      if (nSects > 0) {
++              pdblLib->ppOvlyData = MEM_Calloc(nSects * sizeof(OvlyData *),
++                                               MEM_PAGED);
++              if (pdblLib->ppOvlyData == NULL) {
++                      GT_0trace(DBL_debugMask, GT_7CLASS,
++                               "Failed to allocatate overlay "
++                               "data memory\n");
++                      status = DSP_EMEMORY;
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Read overlay data for each node */
++              for (i = 0; i < nSects; i++) {
++                      /* Read overlay section header */
++                      if ((*dbl->dblAttrs.fread)(&hdr,
++                         sizeof(struct DBOF_OvlySectHdr), 1, file) != 1) {
++                              GT_0trace(DBL_debugMask, GT_6CLASS,
++                                       "Failed to read overlay sect"
++                                       " header\n");
++                              status = DSP_EFREAD;
++                              break;
++                      }
++                      if (pdblLib->byteSwapped) {
++                              hdr.nameLen = SWAPWORD(hdr.nameLen);
++                              hdr.numCreateSects =
++                                              SWAPWORD(hdr.numCreateSects);
++                              hdr.numDeleteSects =
++                                              SWAPWORD(hdr.numDeleteSects);
++                              hdr.numExecuteSects =
++                                              SWAPWORD(hdr.numExecuteSects);
++                              hdr.numOtherSects =
++                                              SWAPWORD(hdr.numOtherSects);
++                              hdr.resvd = SWAPWORD(hdr.resvd);
++                      }
++                      n = hdr.numCreateSects + hdr.numDeleteSects +
++                          hdr.numExecuteSects + hdr.numOtherSects;
++
++                      /* Allocate memory for node's overlay data */
++                      pOvlyData = (struct OvlyData *)MEM_Calloc
++                                  (sizeof(struct OvlyHdr) +
++                                  n * sizeof(struct DBOF_OvlySectData),
++                                  MEM_PAGED);
++                      if (pOvlyData == NULL) {
++                              GT_0trace(DBL_debugMask, GT_7CLASS,
++                                       "Failed to allocatate ovlyay"
++                                       " data memory\n");
++                              status = DSP_EMEMORY;
++                              break;
++                      }
++                      pOvlyData->hdr.dbofHdr = hdr;
++                      pdblLib->ppOvlyData[i] = pOvlyData;
++                      /* Allocate memory for section name */
++                      pName = (char *)MEM_Calloc(hdr.nameLen + 1, MEM_PAGED);
++                      if (pName == NULL) {
++                              GT_0trace(DBL_debugMask, GT_7CLASS,
++                                       "Failed to allocatate ovlyay"
++                                       " section name\n");
++                              status = DSP_EMEMORY;
++                              break;
++                      }
++                      pOvlyData->hdr.pName = pName;
++                      /* Read the overlay section name */
++                      if ((*dbl->dblAttrs.fread)(pName, sizeof(char),
++                         hdr.nameLen, file) != hdr.nameLen) {
++                              GT_0trace(DBL_debugMask, GT_7CLASS,
++                                       "readOvlySects: Unable to "
++                                       "read overlay name.\n");
++                              status = DSP_EFREAD;
++                              break;
++                      }
++                      /* Read the overlay section data */
++                      pData = pOvlyData->data;
++                      if ((*dbl->dblAttrs.fread)(pData,
++                         sizeof(struct DBOF_OvlySectData), n, file) != n) {
++                              GT_0trace(DBL_debugMask, GT_7CLASS,
++                                       "readOvlySects: Unable to "
++                                       "read overlay data.\n");
++                              status = DSP_EFREAD;
++                              break;
++                      }
++                      /* Swap overlay data, if necessary */
++                      if (pdblLib->byteSwapped) {
++                              for (j = 0; j < n; j++) {
++                                      pData[j].loadAddr =
++                                               SWAPLONG(pData[j].loadAddr);
++                                      pData[j].runAddr =
++                                               SWAPLONG(pData[j].runAddr);
++                                      pData[j].size =
++                                               SWAPLONG(pData[j].size);
++                                      pData[j].page =
++                                               SWAPWORD(pData[j].page);
++                              }
++                      }
++              }
++      }
++      return status;
++}
++
++/*
++ *  ======== readSymbols ========
++ *  Purpose:
++ *    Read Symbols
++ */
++static DSP_STATUS readSymbols(struct DBL_TargetObj *dbl,
++                           struct DBL_LibraryObj *pdblLib)
++{
++      struct DBOF_SymbolHdr symHdr;
++      struct KFILE_FileObj *file;
++      u16 i;
++      u16 nSymbols;
++      u16 len;
++      char *pName = NULL;
++      DSP_STATUS status = DSP_SOK;
++
++      file = pdblLib->file;
++
++      nSymbols = pdblLib->fileHdr.numSymbols;
++
++      for (i = 0; i < nSymbols; i++) {
++              /* Read symbol value */
++              if ((*dbl->dblAttrs.fread)(&symHdr,
++                 sizeof(struct DBOF_SymbolHdr), 1, file) != 1) {
++                      GT_0trace(DBL_debugMask, GT_6CLASS,
++                               "Failed to read symbol value\n");
++                      status = DSP_EFREAD;
++                      break;
++              }
++              if (pdblLib->byteSwapped) {
++                      symHdr.nameLen = SWAPWORD(symHdr.nameLen);
++                      symHdr.value = SWAPLONG(symHdr.value);
++              }
++              /* Allocate buffer for symbol name */
++              len = symHdr.nameLen;
++              pName = (char *)MEM_Calloc(len + 1, MEM_PAGED);
++              if (pName == NULL) {
++                      GT_0trace(DBL_debugMask, GT_6CLASS,
++                               "Memory allocation failed\n");
++                      status = DSP_EMEMORY;
++                      break;
++              }
++              pdblLib->symbols[i].pSymName = pName;
++              pdblLib->symbols[i].sym.value = symHdr.value;
++              /* Read symbol name */
++              if ((*dbl->dblAttrs.fread) (pName, sizeof(char), len, file) !=
++                 len) {
++                      GT_0trace(DBL_debugMask, GT_6CLASS,
++                               "Failed to read symbol value\n");
++                      status = DSP_EFREAD;
++                      break;
++              } else {
++                      pName[len] = '\0';
++                      GT_2trace(DBL_debugMask, GT_ENTER,
++                               "Symbol: %s  Value: 0x%lx\n",
++                               pName, symHdr.value);
++              }
++      }
++      return status;
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dbll.c b/drivers/dsp/bridge/pmgr/dbll.c
+new file mode 100644
+index 0000000..82430a3
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dbll.c
+@@ -0,0 +1,1564 @@
++/*
++ * dbll.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software;  you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== dbll.c ========
++ *
++ *! Revision History
++ *! ================
++ *! 25-Apr-2030 map:    Fixed symbol redefinition bug + unload and return error
++ *! 08-Apr-2003 map:  Consolidated DBL with DBLL loader name
++ *! 24-Mar-2003 map:    Updated findSymbol to support dllview update
++ *! 23-Jan-2003 map:    Updated rmmAlloc to support memory granularity
++ *! 21-Nov-2002 map:    Combine fopen and DLOAD_module_open to increase
++ *!         performance on start.
++ *! 04-Oct-2002 map:    Integrated new TIP dynamic loader w/ DOF api.
++ *! 27-Sep-2002 map:    Changed handle passed to RemoteFree, instead of
++ *!         RMM_free;  added GT_trace to rmmDealloc
++ *! 20-Sep-2002 map:    Updated from Code Review
++ *! 08-Aug-2002 jeh:    Updated to support overlays.
++ *! 25-Jun-2002 jeh:    Pass RMM_Addr object to alloc function in rmmAlloc().
++ *! 20-Mar-2002 jeh:    Created.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++#include <dspbridge/dbc.h>
++#include <dspbridge/gh.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* Dynamic loader library interface */
++#include <dspbridge/dynamic_loader.h>
++#include <dspbridge/getsection.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/dbll.h>
++#include <dspbridge/rmm.h>
++
++#define DBLL_TARGSIGNATURE      0x544c4c44    /* "TLLD" */
++#define DBLL_LIBSIGNATURE       0x4c4c4c44    /* "LLLD" */
++
++/* Number of buckets for symbol hash table */
++#define MAXBUCKETS 211
++
++/* Max buffer length */
++#define MAXEXPR 128
++
++#ifndef UINT32_C
++#define UINT32_C(zzz) ((uint32_t)zzz)
++#endif
++#define DOFF_ALIGN(x) (((x) + 3) & ~UINT32_C(3))
++
++/*
++ *  ======== struct DBLL_TarObj* ========
++ *  A target may have one or more libraries of symbols/code/data loaded
++ *  onto it, where a library is simply the symbols/code/data contained
++ *  in a DOFF file.
++ */
++/*
++ *  ======== DBLL_TarObj ========
++ */
++struct DBLL_TarObj {
++      u32 dwSignature;        /* For object validation */
++      struct DBLL_Attrs attrs;
++      struct DBLL_LibraryObj *head;   /* List of all opened libraries */
++} ;
++
++/*
++ *  The following 4 typedefs are "super classes" of the dynamic loader
++ *  library types used in dynamic loader functions (dynamic_loader.h).
++ */
++/*
++ *  ======== DBLLStream ========
++ *  Contains Dynamic_Loader_Stream
++ */
++struct DBLLStream {
++      struct Dynamic_Loader_Stream dlStream;
++      struct DBLL_LibraryObj *lib;
++} ;
++
++/*
++ *  ======== DBLLSymbol ========
++ */
++struct DBLLSymbol {
++      struct Dynamic_Loader_Sym dlSymbol;
++      struct DBLL_LibraryObj *lib;
++} ;
++
++/*
++ *  ======== DBLLAlloc ========
++ */
++ struct DBLLAlloc {
++      struct Dynamic_Loader_Allocate dlAlloc;
++      struct DBLL_LibraryObj *lib;
++} ;
++
++/*
++ *  ======== DBLLInit ========
++ */
++struct DBLLInit {
++      struct Dynamic_Loader_Initialize dlInit;
++      struct DBLL_LibraryObj *lib;
++};
++
++/*
++ *  ======== DBLL_Library ========
++ *  A library handle is returned by DBLL_Open() and is passed to DBLL_load()
++ *  to load symbols/code/data, and to DBLL_unload(), to remove the
++ *  symbols/code/data loaded by DBLL_load().
++ */
++
++/*
++ *  ======== DBLL_LibraryObj ========
++ */
++ struct DBLL_LibraryObj {
++      u32 dwSignature;        /* For object validation */
++      struct DBLL_LibraryObj *next;   /* Next library in target's list */
++      struct DBLL_LibraryObj *prev;   /* Previous in the list */
++      struct DBLL_TarObj *pTarget;    /* target for this library */
++
++      /* Objects needed by dynamic loader */
++      struct DBLLStream stream;
++      struct DBLLSymbol symbol;
++      struct DBLLAlloc allocate;
++      struct DBLLInit init;
++      DLOAD_mhandle mHandle;
++
++      char *fileName;         /* COFF file name */
++      void *fp;               /* Opaque file handle */
++      u32 entry;              /* Entry point */
++      DLOAD_mhandle desc;     /* desc of DOFF file loaded */
++      u32 openRef;            /* Number of times opened */
++      u32 loadRef;            /* Number of times loaded */
++      struct GH_THashTab *symTab;     /* Hash table of symbols */
++      u32 ulPos;
++} ;
++
++/*
++ *  ======== Symbol ========
++ */
++struct Symbol {
++      struct DBLL_Symbol value;
++      char *name;
++} ;
++extern bool bSymbolsReloaded;
++
++static void dofClose(struct DBLL_LibraryObj *zlLib);
++static DSP_STATUS dofOpen(struct DBLL_LibraryObj *zlLib);
++static s32 NoOp(struct Dynamic_Loader_Initialize *thisptr, void *bufr,
++              LDR_ADDR locn, struct LDR_SECTION_INFO *info, unsigned bytsiz);
++
++/*
++ *  Functions called by dynamic loader
++ *
++ */
++/* Dynamic_Loader_Stream */
++static int readBuffer(struct Dynamic_Loader_Stream *this, void *buffer,
++                   unsigned bufsize);
++static int setFilePosn(struct Dynamic_Loader_Stream *this, unsigned int pos);
++/* Dynamic_Loader_Sym */
++static struct dynload_symbol *findSymbol(struct Dynamic_Loader_Sym *this,
++                                      const char *name);
++static struct dynload_symbol *addToSymbolTable(struct Dynamic_Loader_Sym *this,
++                                            const char *name,
++                                            unsigned moduleId);
++static struct dynload_symbol *findInSymbolTable(struct Dynamic_Loader_Sym *this,
++                                              const char *name,
++                                              unsigned moduleid);
++static void purgeSymbolTable(struct Dynamic_Loader_Sym *this,
++                          unsigned moduleId);
++static void *allocate(struct Dynamic_Loader_Sym *this, unsigned memsize);
++static void deallocate(struct Dynamic_Loader_Sym *this, void *memPtr);
++static void errorReport(struct Dynamic_Loader_Sym *this, const char *errstr,
++                      va_list args);
++/* Dynamic_Loader_Allocate */
++static int rmmAlloc(struct Dynamic_Loader_Allocate *this,
++                 struct LDR_SECTION_INFO *info, unsigned align);
++static void rmmDealloc(struct Dynamic_Loader_Allocate *this,
++                    struct LDR_SECTION_INFO *info);
++
++/* Dynamic_Loader_Initialize */
++static int connect(struct Dynamic_Loader_Initialize *this);
++static int readMem(struct Dynamic_Loader_Initialize *this, void *buf,
++                LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++                unsigned nbytes);
++static int writeMem(struct Dynamic_Loader_Initialize *this, void *buf,
++                 LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++                 unsigned nbytes);
++static int fillMem(struct Dynamic_Loader_Initialize *this, LDR_ADDR addr,
++                 struct LDR_SECTION_INFO *info, unsigned nbytes,
++                 unsigned val);
++static int execute(struct Dynamic_Loader_Initialize *this, LDR_ADDR start);
++static void release(struct Dynamic_Loader_Initialize *this);
++
++/* symbol table hash functions */
++static u16 nameHash(void *name, u16 maxBucket);
++static bool nameMatch(void *name, void *sp);
++static void symDelete(void *sp);
++
++#if GT_TRACE
++static struct GT_Mask DBLL_debugMask = { NULL, NULL };  /* GT trace variable */
++#endif
++
++static u32 cRefs;             /* module reference count */
++
++/* Symbol Redefinition */
++static int bRedefinedSymbol;
++static int bGblSearch = 1;
++
++/*
++ *  ======== DBLL_close ========
++ */
++void DBLL_close(struct DBLL_LibraryObj *zlLib)
++{
++      struct DBLL_TarObj *zlTarget;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++      DBC_Require(zlLib->openRef > 0);
++      zlTarget = zlLib->pTarget;
++      GT_1trace(DBLL_debugMask, GT_ENTER, "DBLL_close: lib: 0x%x\n", zlLib);
++      zlLib->openRef--;
++      if (zlLib->openRef == 0) {
++              /* Remove library from list */
++              if (zlTarget->head == zlLib)
++                      zlTarget->head = zlLib->next;
++
++              if (zlLib->prev)
++                      (zlLib->prev)->next = zlLib->next;
++
++              if (zlLib->next)
++                      (zlLib->next)->prev = zlLib->prev;
++
++              /* Free DOF resources */
++              dofClose(zlLib);
++              if (zlLib->fileName)
++                      MEM_Free(zlLib->fileName);
++
++              /* remove symbols from symbol table */
++              if (zlLib->symTab)
++                      GH_delete(zlLib->symTab);
++
++              /* remove the library object itself */
++              MEM_FreeObject(zlLib);
++              zlLib = NULL;
++      }
++}
++
++/*
++ *  ======== DBLL_create ========
++ */
++DSP_STATUS DBLL_create(struct DBLL_TarObj **pTarget, struct DBLL_Attrs *pAttrs)
++{
++      struct DBLL_TarObj *pzlTarget;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pAttrs != NULL);
++      DBC_Require(pTarget != NULL);
++
++      GT_2trace(DBLL_debugMask, GT_ENTER,
++                "DBLL_create: pTarget: 0x%x pAttrs: "
++                "0x%x\n", pTarget, pAttrs);
++      /* Allocate DBL target object */
++      MEM_AllocObject(pzlTarget, struct DBLL_TarObj, DBLL_TARGSIGNATURE);
++      if (pTarget != NULL) {
++              if (pzlTarget == NULL) {
++                      GT_0trace(DBLL_debugMask, GT_6CLASS,
++                               "DBLL_create: Memory allocation"
++                               " failed\n");
++                      *pTarget = NULL;
++                      status = DSP_EMEMORY;
++              } else {
++                      pzlTarget->attrs = *pAttrs;
++                      *pTarget = (struct DBLL_TarObj *)pzlTarget;
++              }
++              DBC_Ensure((DSP_SUCCEEDED(status) &&
++                        MEM_IsValidHandle(((struct DBLL_TarObj *)(*pTarget)),
++                        DBLL_TARGSIGNATURE)) || (DSP_FAILED(status) &&
++                        *pTarget == NULL));
++      }
++
++      return status;
++}
++
++/*
++ *  ======== DBLL_delete ========
++ */
++void DBLL_delete(struct DBLL_TarObj *target)
++{
++      struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++
++      GT_1trace(DBLL_debugMask, GT_ENTER, "DBLL_delete: target: 0x%x\n",
++               target);
++
++      if (zlTarget != NULL)
++              MEM_FreeObject(zlTarget);
++
++}
++
++/*
++ *  ======== DBLL_exit ========
++ *  Discontinue usage of DBL module.
++ */
++void DBLL_exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      cRefs--;
++
++      GT_1trace(DBLL_debugMask, GT_5CLASS, "DBLL_exit() ref count: 0x%x\n",
++                cRefs);
++
++      if (cRefs == 0) {
++              MEM_Exit();
++              CSL_Exit();
++              GH_exit();
++#if GT_TRACE
++              DBLL_debugMask.flags = NULL;
++#endif
++      }
++
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== DBLL_getAddr ========
++ *  Get address of name in the specified library.
++ */
++bool DBLL_getAddr(struct DBLL_LibraryObj *zlLib, char *name,
++                struct DBLL_Symbol **ppSym)
++{
++      struct Symbol *sym;
++      bool status = false;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++      DBC_Require(name != NULL);
++      DBC_Require(ppSym != NULL);
++      DBC_Require(zlLib->symTab != NULL);
++
++      GT_3trace(DBLL_debugMask, GT_ENTER,
++               "DBLL_getAddr: lib: 0x%x name: %s pAddr:"
++               " 0x%x\n", zlLib, name, ppSym);
++      sym = (struct Symbol *)GH_find(zlLib->symTab, name);
++      if (sym != NULL) {
++              *ppSym = &sym->value;
++              status = true;
++      }
++      return status;
++}
++
++/*
++ *  ======== DBLL_getAttrs ========
++ *  Retrieve the attributes of the target.
++ */
++void DBLL_getAttrs(struct DBLL_TarObj *target, struct DBLL_Attrs *pAttrs)
++{
++      struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++      DBC_Require(pAttrs != NULL);
++
++      if ((pAttrs != NULL) && (zlTarget != NULL))
++              *pAttrs = zlTarget->attrs;
++
++}
++
++/*
++ *  ======== DBLL_getCAddr ========
++ *  Get address of a "C" name in the specified library.
++ */
++bool DBLL_getCAddr(struct DBLL_LibraryObj *zlLib, char *name,
++                 struct DBLL_Symbol **ppSym)
++{
++      struct Symbol *sym;
++      char cname[MAXEXPR + 1];
++      bool status = false;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++      DBC_Require(ppSym != NULL);
++      DBC_Require(zlLib->symTab != NULL);
++      DBC_Require(name != NULL);
++
++      cname[0] = '_';
++
++       strncpy(cname + 1, name, sizeof(cname) - 2);
++      cname[MAXEXPR] = '\0';  /* insure '\0' string termination */
++
++      /* Check for C name, if not found */
++      sym = (struct Symbol *)GH_find(zlLib->symTab, cname);
++
++      if (sym != NULL) {
++              *ppSym = &sym->value;
++              status = true;
++      }
++
++      return status;
++}
++
++/*
++ *  ======== DBLL_getSect ========
++ *  Get the base address and size (in bytes) of a COFF section.
++ */
++DSP_STATUS DBLL_getSect(struct DBLL_LibraryObj *lib, char *name, u32 *pAddr,
++                      u32 *pSize)
++{
++      u32 uByteSize;
++      bool fOpenedDoff = false;
++      const struct LDR_SECTION_INFO *sect = NULL;
++      struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(name != NULL);
++      DBC_Require(pAddr != NULL);
++      DBC_Require(pSize != NULL);
++      DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++
++      GT_4trace(DBLL_debugMask, GT_ENTER,
++               "DBLL_getSect: lib: 0x%x name: %s pAddr:"
++               " 0x%x pSize: 0x%x\n", lib, name, pAddr, pSize);
++      /* If DOFF file is not open, we open it. */
++      if (zlLib != NULL) {
++              if (zlLib->fp == NULL) {
++                      status = dofOpen(zlLib);
++                      if (DSP_SUCCEEDED(status))
++                              fOpenedDoff = true;
++
++              } else {
++                      (*(zlLib->pTarget->attrs.fseek))(zlLib->fp,
++                       zlLib->ulPos, SEEK_SET);
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              uByteSize = 1;
++              if (DLOAD_GetSectionInfo(zlLib->desc, name, &sect)) {
++                      *pAddr = sect->load_addr;
++                      *pSize = sect->size * uByteSize;
++                      /* Make sure size is even for good swap */
++                      if (*pSize % 2)
++                              (*pSize)++;
++
++                      /* Align size */
++                      *pSize = DOFF_ALIGN(*pSize);
++              } else {
++                      status = DSP_ENOSECT;
++              }
++      }
++      if (fOpenedDoff) {
++              dofClose(zlLib);
++              fOpenedDoff = false;
++      }
++
++      return status;
++}
++
++/*
++ *  ======== DBLL_init ========
++ */
++bool DBLL_init(void)
++{
++      bool retVal = true;
++
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++              DBC_Assert(!DBLL_debugMask.flags);
++              GT_create(&DBLL_debugMask, "DL");       /* "DL" for dbDL */
++              GH_init();
++              CSL_Init();
++              retVal = MEM_Init();
++              if (!retVal)
++                      MEM_Exit();
++
++      }
++
++      if (retVal)
++              cRefs++;
++
++
++      GT_1trace(DBLL_debugMask, GT_5CLASS, "DBLL_init(), ref count:  0x%x\n",
++               cRefs);
++
++      DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
++
++      return retVal;
++}
++
++/*
++ *  ======== DBLL_load ========
++ */
++DSP_STATUS DBLL_load(struct DBLL_LibraryObj *lib, DBLL_Flags flags,
++                   struct DBLL_Attrs *attrs, u32 *pEntry)
++{
++      struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++      struct DBLL_TarObj *dbzl;
++      bool gotSymbols = true;
++      s32 err;
++      DSP_STATUS status = DSP_SOK;
++      bool fOpenedDoff = false;
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++      DBC_Require(pEntry != NULL);
++      DBC_Require(attrs != NULL);
++
++      GT_4trace(DBLL_debugMask, GT_ENTER,
++               "DBLL_load: lib: 0x%x flags: 0x%x pEntry:"
++               " 0x%x\n", lib, flags, attrs, pEntry);
++      /*
++       *  Load if not already loaded.
++       */
++      if (zlLib->loadRef == 0 || !(flags & DBLL_DYNAMIC)) {
++              dbzl = zlLib->pTarget;
++              dbzl->attrs = *attrs;
++              /* Create a hash table for symbols if not already created */
++              if (zlLib->symTab == NULL) {
++                      gotSymbols = false;
++                      zlLib->symTab = GH_create(MAXBUCKETS,
++                                               sizeof(struct Symbol),
++                                               nameHash,
++                                               nameMatch, symDelete);
++                      if (zlLib->symTab == NULL)
++                              status = DSP_EMEMORY;
++
++              }
++              /*
++               *  Set up objects needed by the dynamic loader
++               */
++              /* Stream */
++              zlLib->stream.dlStream.read_buffer = readBuffer;
++              zlLib->stream.dlStream.set_file_posn = setFilePosn;
++              zlLib->stream.lib = zlLib;
++              /* Symbol */
++              zlLib->symbol.dlSymbol.Find_Matching_Symbol = findSymbol;
++              if (gotSymbols) {
++                      zlLib->symbol.dlSymbol.Add_To_Symbol_Table =
++                                                      findInSymbolTable;
++              } else {
++                      zlLib->symbol.dlSymbol.Add_To_Symbol_Table =
++                                                      addToSymbolTable;
++              }
++              zlLib->symbol.dlSymbol.Purge_Symbol_Table = purgeSymbolTable;
++              zlLib->symbol.dlSymbol.Allocate = allocate;
++              zlLib->symbol.dlSymbol.Deallocate = deallocate;
++              zlLib->symbol.dlSymbol.Error_Report = errorReport;
++              zlLib->symbol.lib = zlLib;
++              /* Allocate */
++              zlLib->allocate.dlAlloc.Allocate = rmmAlloc;
++              zlLib->allocate.dlAlloc.Deallocate = rmmDealloc;
++              zlLib->allocate.lib = zlLib;
++              /* Init */
++              zlLib->init.dlInit.connect = connect;
++              zlLib->init.dlInit.readmem = readMem;
++              zlLib->init.dlInit.writemem = writeMem;
++              zlLib->init.dlInit.fillmem = fillMem;
++              zlLib->init.dlInit.execute = execute;
++              zlLib->init.dlInit.release = release;
++              zlLib->init.lib = zlLib;
++              /* If COFF file is not open, we open it. */
++              if (zlLib->fp == NULL) {
++                      status = dofOpen(zlLib);
++                      if (DSP_SUCCEEDED(status))
++                              fOpenedDoff = true;
++
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      zlLib->ulPos = (*(zlLib->pTarget->attrs.ftell))
++                                      (zlLib->fp);
++                      /* Reset file cursor */
++                      (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long)0,
++                               SEEK_SET);
++                      bSymbolsReloaded = true;
++                      /* The 5th argument, DLOAD_INITBSS, tells the DLL
++                       * module to zero-init all BSS sections.  In general,
++                       * this is not necessary and also increases load time.
++                       * We may want to make this configurable by the user */
++                      err = Dynamic_Load_Module(&zlLib->stream.dlStream,
++                            &zlLib->symbol.dlSymbol, &zlLib->allocate.dlAlloc,
++                            &zlLib->init.dlInit, DLOAD_INITBSS,
++                            &zlLib->mHandle);
++
++                      if (err != 0) {
++                              GT_1trace(DBLL_debugMask, GT_6CLASS,
++                                       "DBLL_load: "
++                                       "Dynamic_Load_Module failed: 0x%lx\n",
++                                       err);
++                              status = DSP_EDYNLOAD;
++                      } else if (bRedefinedSymbol) {
++                              zlLib->loadRef++;
++                              DBLL_unload(zlLib, (struct DBLL_Attrs *) attrs);
++                              bRedefinedSymbol = false;
++                              status = DSP_EDYNLOAD;
++                      } else {
++                              *pEntry = zlLib->entry;
++                      }
++              }
++      }
++      if (DSP_SUCCEEDED(status))
++              zlLib->loadRef++;
++
++      /* Clean up DOFF resources */
++      if (fOpenedDoff)
++              dofClose(zlLib);
++
++      DBC_Ensure(DSP_FAILED(status) || zlLib->loadRef > 0);
++      return status;
++}
++
++/*
++ *  ======== DBLL_loadSect ========
++ *  Not supported for COFF.
++ */
++DSP_STATUS DBLL_loadSect(struct DBLL_LibraryObj *zlLib, char *sectName,
++                      struct DBLL_Attrs *attrs)
++{
++      DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++
++      return DSP_ENOTIMPL;
++}
++
++/*
++ *  ======== DBLL_open ========
++ */
++DSP_STATUS DBLL_open(struct DBLL_TarObj *target, char *file, DBLL_Flags flags,
++                  struct DBLL_LibraryObj **pLib)
++{
++      struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++      struct DBLL_LibraryObj *zlLib = NULL;
++      s32 err;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++      DBC_Require(zlTarget->attrs.fopen != NULL);
++      DBC_Require(file != NULL);
++      DBC_Require(pLib != NULL);
++
++      GT_3trace(DBLL_debugMask, GT_ENTER,
++               "DBLL_open: target: 0x%x file: %s pLib:"
++               " 0x%x\n", target, file, pLib);
++      zlLib = zlTarget->head;
++      while (zlLib != NULL) {
++               if (strcmp(zlLib->fileName, file) == 0) {
++                      /* Library is already opened */
++                      zlLib->openRef++;
++                      break;
++              }
++              zlLib = zlLib->next;
++      }
++      if (zlLib == NULL) {
++              /* Allocate DBL library object */
++              MEM_AllocObject(zlLib, struct DBLL_LibraryObj,
++                              DBLL_LIBSIGNATURE);
++              if (zlLib == NULL) {
++                      GT_0trace(DBLL_debugMask, GT_6CLASS,
++                               "DBLL_open: Memory allocation failed\n");
++                      status = DSP_EMEMORY;
++              } else {
++                      zlLib->ulPos = 0;
++                      /* Increment ref count to allow close on failure
++                       * later on */
++                      zlLib->openRef++;
++                      zlLib->pTarget = zlTarget;
++                      /* Keep a copy of the file name */
++                       zlLib->fileName = MEM_Calloc(strlen(file) + 1,
++                                                      MEM_PAGED);
++                      if (zlLib->fileName == NULL) {
++                              GT_0trace(DBLL_debugMask, GT_6CLASS,
++                                       "DBLL_open: Memory "
++                                       "allocation failed\n");
++                              status = DSP_EMEMORY;
++                      } else {
++                               strncpy(zlLib->fileName, file,
++                                          strlen(file) + 1);
++                      }
++                      zlLib->symTab = NULL;
++              }
++      }
++      /*
++       *  Set up objects needed by the dynamic loader
++       */
++      if (DSP_FAILED(status))
++              goto func_cont;
++
++      /* Stream */
++      zlLib->stream.dlStream.read_buffer = readBuffer;
++      zlLib->stream.dlStream.set_file_posn = setFilePosn;
++      zlLib->stream.lib = zlLib;
++      /* Symbol */
++      zlLib->symbol.dlSymbol.Add_To_Symbol_Table = addToSymbolTable;
++      zlLib->symbol.dlSymbol.Find_Matching_Symbol = findSymbol;
++      zlLib->symbol.dlSymbol.Purge_Symbol_Table = purgeSymbolTable;
++      zlLib->symbol.dlSymbol.Allocate = allocate;
++      zlLib->symbol.dlSymbol.Deallocate = deallocate;
++      zlLib->symbol.dlSymbol.Error_Report = errorReport;
++      zlLib->symbol.lib = zlLib;
++      /* Allocate */
++      zlLib->allocate.dlAlloc.Allocate = rmmAlloc;
++      zlLib->allocate.dlAlloc.Deallocate = rmmDealloc;
++      zlLib->allocate.lib = zlLib;
++      /* Init */
++      zlLib->init.dlInit.connect = connect;
++      zlLib->init.dlInit.readmem = readMem;
++      zlLib->init.dlInit.writemem = writeMem;
++      zlLib->init.dlInit.fillmem = fillMem;
++      zlLib->init.dlInit.execute = execute;
++      zlLib->init.dlInit.release = release;
++      zlLib->init.lib = zlLib;
++      if (DSP_SUCCEEDED(status) && zlLib->fp == NULL)
++              status = dofOpen(zlLib);
++
++      zlLib->ulPos = (*(zlLib->pTarget->attrs.ftell)) (zlLib->fp);
++      (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long) 0, SEEK_SET);
++      /* Create a hash table for symbols if flag is set */
++      if (zlLib->symTab != NULL || !(flags & DBLL_SYMB))
++              goto func_cont;
++
++      zlLib->symTab = GH_create(MAXBUCKETS, sizeof(struct Symbol), nameHash,
++                               nameMatch, symDelete);
++      if (zlLib->symTab == NULL) {
++              status = DSP_EMEMORY;
++      } else {
++              /* Do a fake load to get symbols - set write function to NoOp */
++              zlLib->init.dlInit.writemem = NoOp;
++              err = Dynamic_Open_Module(&zlLib->stream.dlStream,
++                                      &zlLib->symbol.dlSymbol,
++                                      &zlLib->allocate.dlAlloc,
++                                      &zlLib->init.dlInit, 0,
++                                      &zlLib->mHandle);
++              if (err != 0) {
++                      GT_1trace(DBLL_debugMask, GT_6CLASS, "DBLL_open: "
++                               "Dynamic_Load_Module failed: 0x%lx\n", err);
++                      status = DSP_EDYNLOAD;
++              } else {
++                      /* Now that we have the symbol table, we can unload */
++                      err = Dynamic_Unload_Module(zlLib->mHandle,
++                                                 &zlLib->symbol.dlSymbol,
++                                                 &zlLib->allocate.dlAlloc,
++                                                 &zlLib->init.dlInit);
++                      if (err != 0) {
++                              GT_1trace(DBLL_debugMask, GT_6CLASS,
++                                      "DBLL_open: "
++                                      "Dynamic_Unload_Module failed: 0x%lx\n",
++                                      err);
++                              status = DSP_EDYNLOAD;
++                      }
++                      zlLib->mHandle = NULL;
++              }
++      }
++func_cont:
++      if (DSP_SUCCEEDED(status)) {
++              if (zlLib->openRef == 1) {
++                      /* First time opened - insert in list */
++                      if (zlTarget->head)
++                              (zlTarget->head)->prev = zlLib;
++
++                      zlLib->prev = NULL;
++                      zlLib->next = zlTarget->head;
++                      zlTarget->head = zlLib;
++              }
++              *pLib = (struct DBLL_LibraryObj *)zlLib;
++      } else {
++              *pLib = NULL;
++              if (zlLib != NULL)
++                      DBLL_close((struct DBLL_LibraryObj *)zlLib);
++
++      }
++      DBC_Ensure((DSP_SUCCEEDED(status) && (zlLib->openRef > 0) &&
++                MEM_IsValidHandle(((struct DBLL_LibraryObj *)(*pLib)),
++                DBLL_LIBSIGNATURE)) || (DSP_FAILED(status) && *pLib == NULL));
++      return status;
++}
++
++/*
++ *  ======== DBLL_readSect ========
++ *  Get the content of a COFF section.
++ */
++DSP_STATUS DBLL_readSect(struct DBLL_LibraryObj *lib, char *name,
++                       char *pContent, u32 size)
++{
++      struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++      bool fOpenedDoff = false;
++      u32 uByteSize;          /* size of bytes */
++      u32 ulSectSize;                 /* size of section */
++      const struct LDR_SECTION_INFO *sect = NULL;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++      DBC_Require(name != NULL);
++      DBC_Require(pContent != NULL);
++      DBC_Require(size != 0);
++
++      GT_4trace(DBLL_debugMask, GT_ENTER,
++               "DBLL_readSect: lib: 0x%x name: %s "
++               "pContent: 0x%x size: 0x%x\n", lib, name, pContent, size);
++      /* If DOFF file is not open, we open it. */
++      if (zlLib != NULL) {
++              if (zlLib->fp == NULL) {
++                      status = dofOpen(zlLib);
++                      if (DSP_SUCCEEDED(status))
++                              fOpenedDoff = true;
++
++              } else {
++                      (*(zlLib->pTarget->attrs.fseek))(zlLib->fp,
++                              zlLib->ulPos, SEEK_SET);
++              }
++      }
++
++      if (DSP_FAILED(status))
++              goto func_cont;
++
++      uByteSize = 1;
++      if (!DLOAD_GetSectionInfo(zlLib->desc, name, &sect)) {
++              status = DSP_ENOSECT;
++              goto func_cont;
++      }
++      /*
++       * Ensure the supplied buffer size is sufficient to store
++       * the section content to be read.
++       */
++      ulSectSize = sect->size * uByteSize;
++      /* Make sure size is even for good swap */
++      if (ulSectSize % 2)
++              ulSectSize++;
++
++      /* Align size */
++      ulSectSize = DOFF_ALIGN(ulSectSize);
++      if (ulSectSize > size) {
++              status = DSP_EFAIL;
++      } else {
++              if (!DLOAD_GetSection(zlLib->desc, sect, pContent))
++                      status = DSP_EFREAD;
++
++      }
++func_cont:
++      if (fOpenedDoff) {
++              dofClose(zlLib);
++              fOpenedDoff = false;
++      }
++      return status;
++}
++
++/*
++ *  ======== DBLL_setAttrs ========
++ *  Set the attributes of the target.
++ */
++void DBLL_setAttrs(struct DBLL_TarObj *target, struct DBLL_Attrs *pAttrs)
++{
++      struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++      DBC_Require(pAttrs != NULL);
++      GT_2trace(DBLL_debugMask, GT_ENTER,
++               "DBLL_setAttrs: target: 0x%x pAttrs: "
++               "0x%x\n", target, pAttrs);
++      if ((pAttrs != NULL) && (zlTarget != NULL))
++              zlTarget->attrs = *pAttrs;
++
++}
++
++/*
++ *  ======== DBLL_unload ========
++ */
++void DBLL_unload(struct DBLL_LibraryObj *lib, struct DBLL_Attrs *attrs)
++{
++      struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++      s32 err = 0;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++      DBC_Require(zlLib->loadRef > 0);
++      GT_1trace(DBLL_debugMask, GT_ENTER, "DBLL_unload: lib: 0x%x\n", lib);
++      zlLib->loadRef--;
++      /* Unload only if reference count is 0 */
++      if (zlLib->loadRef != 0)
++              goto func_end;
++
++      zlLib->pTarget->attrs = *attrs;
++      if (zlLib != NULL) {
++              if (zlLib->mHandle) {
++                      err = Dynamic_Unload_Module(zlLib->mHandle,
++                              &zlLib->symbol.dlSymbol,
++                              &zlLib->allocate.dlAlloc, &zlLib->init.dlInit);
++                      if (err != 0) {
++                              GT_1trace(DBLL_debugMask, GT_5CLASS,
++                                       "Dynamic_Unload_Module "
++                                       "failed: 0x%x\n", err);
++                      }
++              }
++              /* remove symbols from symbol table */
++              if (zlLib->symTab != NULL) {
++                      GH_delete(zlLib->symTab);
++                      zlLib->symTab = NULL;
++              }
++              /* delete DOFF desc since it holds *lots* of host OS
++               * resources */
++              dofClose(zlLib);
++      }
++func_end:
++      DBC_Ensure(zlLib->loadRef >= 0);
++}
++
++/*
++ *  ======== DBLL_unloadSect ========
++ *  Not supported for COFF.
++ */
++DSP_STATUS DBLL_unloadSect(struct DBLL_LibraryObj *lib, char *sectName,
++                        struct DBLL_Attrs *attrs)
++{
++      DBC_Require(cRefs > 0);
++      DBC_Require(sectName != NULL);
++      GT_2trace(DBLL_debugMask, GT_ENTER,
++               "DBLL_unloadSect: lib: 0x%x sectName: "
++               "%s\n", lib, sectName);
++      return DSP_ENOTIMPL;
++}
++
++/*
++ *  ======== dofClose ========
++ */
++static void dofClose(struct DBLL_LibraryObj *zlLib)
++{
++      if (zlLib->desc) {
++              DLOAD_module_close(zlLib->desc);
++              zlLib->desc = NULL;
++      }
++      /* close file */
++      if (zlLib->fp) {
++              (zlLib->pTarget->attrs.fclose) (zlLib->fp);
++              zlLib->fp = NULL;
++      }
++}
++
++/*
++ *  ======== dofOpen ========
++ */
++static DSP_STATUS dofOpen(struct DBLL_LibraryObj *zlLib)
++{
++      void *open = *(zlLib->pTarget->attrs.fopen);
++      DSP_STATUS status = DSP_SOK;
++
++      /* First open the file for the dynamic loader, then open COF */
++      zlLib->fp = (void *)((DBLL_FOpenFxn)(open))(zlLib->fileName, "rb");
++
++      /* Open DOFF module */
++      if (zlLib->fp && zlLib->desc == NULL) {
++              (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long)0, SEEK_SET);
++              zlLib->desc = DLOAD_module_open(&zlLib->stream.dlStream,
++                                              &zlLib->symbol.dlSymbol);
++              if (zlLib->desc == NULL) {
++                      (zlLib->pTarget->attrs.fclose)(zlLib->fp);
++                      zlLib->fp = NULL;
++                      status = DSP_EFOPEN;
++              }
++      } else {
++              status = DSP_EFOPEN;
++      }
++
++      return status;
++}
++
++/*
++ *  ======== nameHash ========
++ */
++static u16 nameHash(void *key, u16 maxBucket)
++{
++      u16 ret;
++      u16 hash;
++      char *name = (char *)key;
++
++      DBC_Require(name != NULL);
++
++      hash = 0;
++
++      while (*name) {
++              hash <<= 1;
++              hash ^= *name++;
++      }
++
++      ret = hash % maxBucket;
++
++      return ret;
++}
++
++/*
++ *  ======== nameMatch ========
++ */
++static bool nameMatch(void *key, void *value)
++{
++      DBC_Require(key != NULL);
++      DBC_Require(value != NULL);
++
++      if ((key != NULL) && (value != NULL)) {
++               if (strcmp((char *)key, ((struct Symbol *)value)->name) == 0)
++                      return true;
++      }
++      return false;
++}
++
++/*
++ *  ======== NoOp ========
++ */
++static int NoOp(struct Dynamic_Loader_Initialize *thisptr, void *bufr,
++              LDR_ADDR locn, struct LDR_SECTION_INFO *info, unsigned bytsize)
++{
++      return 1;
++}
++
++/*
++ *  ======== symDelete ========
++ */
++static void symDelete(void *value)
++{
++      struct Symbol *sp = (struct Symbol *)value;
++
++      MEM_Free(sp->name);
++}
++
++/*
++ *  Dynamic Loader Functions
++ */
++
++/* Dynamic_Loader_Stream */
++/*
++ *  ======== readBuffer ========
++ */
++static int readBuffer(struct Dynamic_Loader_Stream *this, void *buffer,
++                   unsigned bufsize)
++{
++      struct DBLLStream *pStream = (struct DBLLStream *)this;
++      struct DBLL_LibraryObj *lib;
++      int bytesRead = 0;
++
++      DBC_Require(this != NULL);
++      lib = pStream->lib;
++      DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++      if (lib != NULL) {
++              bytesRead = (*(lib->pTarget->attrs.fread))(buffer, 1, bufsize,
++                          lib->fp);
++      }
++      return bytesRead;
++}
++
++/*
++ *  ======== setFilePosn ========
++ */
++static int setFilePosn(struct Dynamic_Loader_Stream *this, unsigned int pos)
++{
++      struct DBLLStream *pStream = (struct DBLLStream *)this;
++      struct DBLL_LibraryObj *lib;
++      int status = 0;                 /* Success */
++
++      DBC_Require(this != NULL);
++      lib = pStream->lib;
++      DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++      if (lib != NULL) {
++              status = (*(lib->pTarget->attrs.fseek))(lib->fp, (long)pos,
++                       SEEK_SET);
++      }
++
++      return status;
++}
++
++/* Dynamic_Loader_Sym */
++
++/*
++ *  ======== findSymbol ========
++ */
++static struct dynload_symbol *findSymbol(struct Dynamic_Loader_Sym *this,
++                                      const char *name)
++{
++      struct dynload_symbol *retSym;
++      struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++      struct DBLL_LibraryObj *lib;
++      struct DBLL_Symbol *pSym = NULL;
++      bool status = false;    /* Symbol not found yet */
++
++      DBC_Require(this != NULL);
++      lib = pSymbol->lib;
++      DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++      if (lib != NULL) {
++              if (lib->pTarget->attrs.symLookup) {
++                      /* Check current lib + base lib + dep lib +
++                       * persistent lib */
++                      status = (*(lib->pTarget->attrs.symLookup))
++                               (lib->pTarget->attrs.symHandle,
++                               lib->pTarget->attrs.symArg,
++                               lib->pTarget->attrs.rmmHandle, name, &pSym);
++              } else {
++                      /* Just check current lib for symbol */
++                      status = DBLL_getAddr((struct DBLL_LibraryObj *)lib,
++                               (char *)name, &pSym);
++                      if (!status) {
++                              status =
++                                 DBLL_getCAddr((struct DBLL_LibraryObj *)lib,
++                                 (char *)name, &pSym);
++                      }
++              }
++      }
++
++      if (!status && bGblSearch) {
++              GT_1trace(DBLL_debugMask, GT_6CLASS,
++                       "findSymbol: Symbol not found: %s\n", name);
++      }
++
++      DBC_Assert((status && (pSym != NULL)) || (!status && (pSym == NULL)));
++
++      retSym = (struct dynload_symbol *)pSym;
++      return retSym;
++}
++
++/*
++ *  ======== findInSymbolTable ========
++ */
++static struct dynload_symbol *findInSymbolTable(struct Dynamic_Loader_Sym *this,
++                                              const char *name,
++                                              unsigned moduleid)
++{
++      struct dynload_symbol *retSym;
++      struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++      struct DBLL_LibraryObj *lib;
++      struct Symbol *sym;
++
++      DBC_Require(this != NULL);
++      lib = pSymbol->lib;
++      DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++      DBC_Require(lib->symTab != NULL);
++
++      sym = (struct Symbol *)GH_find(lib->symTab, (char *) name);
++
++      retSym = (struct dynload_symbol *)&sym->value;
++      return retSym;
++}
++
++/*
++ *  ======== addToSymbolTable ========
++ */
++static struct dynload_symbol *addToSymbolTable(struct Dynamic_Loader_Sym *this,
++                                            const char *name,
++                                            unsigned moduleId)
++{
++      struct Symbol *symPtr = NULL;
++      struct Symbol symbol;
++      struct dynload_symbol *pSym = NULL;
++      struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++      struct DBLL_LibraryObj *lib;
++      struct dynload_symbol *retVal;
++
++      DBC_Require(this != NULL);
++       DBC_Require(name);
++      lib = pSymbol->lib;
++      DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++      /* Check to see if symbol is already defined in symbol table */
++      if (!(lib->pTarget->attrs.baseImage)) {
++              bGblSearch = false;
++              pSym = findSymbol(this, name);
++              bGblSearch = true;
++              if (pSym) {
++                      bRedefinedSymbol = true;
++                      GT_1trace(DBLL_debugMask, GT_6CLASS,
++                               "Symbol already defined in "
++                               "symbol table: %s\n", name);
++                      return NULL;
++              }
++      }
++      /* Allocate string to copy symbol name */
++       symbol.name = (char *)MEM_Calloc(strlen((char *const)name) + 1,
++                                                      MEM_PAGED);
++      if (symbol.name == NULL)
++              return NULL;
++
++      if (symbol.name != NULL) {
++              /* Just copy name (value will be filled in by dynamic loader) */
++               strncpy(symbol.name, (char *const)name,
++                          strlen((char *const)name) + 1);
++
++              /* Add symbol to symbol table */
++              symPtr = (struct Symbol *)GH_insert(lib->symTab, (void *)name,
++                       (void *)&symbol);
++              if (symPtr == NULL)
++                      MEM_Free(symbol.name);
++
++      }
++      if (symPtr != NULL)
++              retVal = (struct dynload_symbol *)&symPtr->value;
++      else
++              retVal = NULL;
++
++      return retVal;
++}
++
++/*
++ *  ======== purgeSymbolTable ========
++ */
++static void purgeSymbolTable(struct Dynamic_Loader_Sym *this, unsigned moduleId)
++{
++      struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++      struct DBLL_LibraryObj *lib;
++
++      DBC_Require(this != NULL);
++      lib = pSymbol->lib;
++      DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++      /* May not need to do anything */
++}
++
++/*
++ *  ======== allocate ========
++ */
++static void *allocate(struct Dynamic_Loader_Sym *this, unsigned memsize)
++{
++      struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++      struct DBLL_LibraryObj *lib;
++      void *buf;
++
++      DBC_Require(this != NULL);
++      lib = pSymbol->lib;
++      DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++      buf = MEM_Calloc(memsize, MEM_PAGED);
++
++      return buf;
++}
++
++/*
++ *  ======== deallocate ========
++ */
++static void deallocate(struct Dynamic_Loader_Sym *this, void *memPtr)
++{
++      struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++      struct DBLL_LibraryObj *lib;
++
++      DBC_Require(this != NULL);
++      lib = pSymbol->lib;
++      DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++      MEM_Free(memPtr);
++}
++
++/*
++ *  ======== errorReport ========
++ */
++static void errorReport(struct Dynamic_Loader_Sym *this, const char *errstr,
++                      va_list args)
++{
++      struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++      struct DBLL_LibraryObj *lib;
++      char tempBuf[MAXEXPR];
++
++      DBC_Require(this != NULL);
++      lib = pSymbol->lib;
++      DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++      vsnprintf((char *)tempBuf, MAXEXPR, (char *)errstr, args);
++      GT_1trace(DBLL_debugMask, GT_5CLASS, "%s\n", tempBuf);
++}
++
++/* Dynamic_Loader_Allocate */
++
++/*
++ *  ======== rmmAlloc ========
++ */
++static int rmmAlloc(struct Dynamic_Loader_Allocate *this,
++                 struct LDR_SECTION_INFO *info, unsigned align)
++{
++      struct DBLLAlloc *pAlloc = (struct DBLLAlloc *)this;
++      struct DBLL_LibraryObj *lib;
++      DSP_STATUS status = DSP_SOK;
++      u32 memType;
++      struct RMM_Addr rmmAddr;
++      s32 retVal = TRUE;
++      unsigned stype = DLOAD_SECTION_TYPE(info->type);
++      char *pToken = NULL;
++      char *szSecLastToken = NULL;
++      char *szLastToken = NULL;
++      char *szSectName = NULL;
++      char *pszCur;
++      s32 tokenLen = 0;
++      s32 segId = -1;
++      s32 req = -1;
++      s32 count = 0;
++      u32 allocSize = 0;
++
++      DBC_Require(this != NULL);
++      lib = pAlloc->lib;
++      DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++      memType = (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == DLOAD_BSS) ?
++                 DBLL_BSS : DBLL_DATA;
++
++      /* Attempt to extract the segment ID and requirement information from
++       the name of the section */
++       DBC_Require(info->name);
++       tokenLen = strlen((char *)(info->name)) + 1;
++
++      szSectName = MEM_Calloc(tokenLen, MEM_PAGED);
++      szLastToken = MEM_Calloc(tokenLen, MEM_PAGED);
++      szSecLastToken = MEM_Calloc(tokenLen, MEM_PAGED);
++
++      if (szSectName == NULL || szSecLastToken == NULL ||
++         szLastToken == NULL) {
++              status = DSP_EMEMORY;
++              goto func_cont;
++      }
++       strncpy(szSectName, (char *)(info->name), tokenLen);
++      pszCur = szSectName;
++      while ((pToken = strsep(&pszCur, ":")) && *pToken != '\0') {
++               strncpy(szSecLastToken, szLastToken, strlen(szLastToken) + 1);
++               strncpy(szLastToken, pToken, strlen(pToken) + 1);
++              pToken = strsep(&pszCur, ":");
++              count++;        /* optimizes processing*/
++      }
++      /* If pToken is 0 or 1, and szSecLastToken is DYN_DARAM or DYN_SARAM,
++       or DYN_EXTERNAL, then mem granularity information is present
++       within the section name - only process if there are at least three
++       tokens within the section name (just a minor optimization)*/
++      if (count >= 3)
++               strict_strtol(szLastToken, 10, (long *)&req);
++
++      if ((req == 0) || (req == 1)) {
++               if (strcmp(szSecLastToken, "DYN_DARAM") == 0) {
++                      segId = 0;
++              } else {
++                       if (strcmp(szSecLastToken, "DYN_SARAM") == 0) {
++                              segId = 1;
++                      } else {
++                               if (strcmp(szSecLastToken,
++                                 "DYN_EXTERNAL") == 0) {
++                                      segId = 2;
++                              }
++                      }
++              }
++              if (segId != -1) {
++                      GT_2trace(DBLL_debugMask, GT_5CLASS,
++                               "Extracted values for memory"
++                               " granularity req [%d] segId [%d]\n",
++                               req, segId);
++              }
++      }
++      MEM_Free(szSectName);
++      szSectName = NULL;
++      MEM_Free(szLastToken);
++      szLastToken = NULL;
++      MEM_Free(szSecLastToken);
++      szSecLastToken = NULL;
++func_cont:
++      if (memType == DBLL_CODE)
++              allocSize = info->size + GEM_L1P_PREFETCH_SIZE;
++      else
++              allocSize = info->size;
++      /* TODO - ideally, we can pass the alignment requirement also
++       * from here */
++      if (lib != NULL) {
++              status = (lib->pTarget->attrs.alloc)(lib->pTarget->
++                       attrs.rmmHandle, memType, allocSize, align,
++                       (u32 *)&rmmAddr, segId, req, FALSE);
++      }
++      if (DSP_FAILED(status)) {
++              retVal = false;
++      } else {
++              /* RMM gives word address. Need to convert to byte address */
++              info->load_addr = rmmAddr.addr * DSPWORDSIZE;
++              info->run_addr = info->load_addr;
++              info->context = (u32)rmmAddr.segid;
++              GT_3trace(DBLL_debugMask, GT_5CLASS,
++                       "Remote alloc: %s  base = 0x%lx len"
++                       "= 0x%lx\n", info->name, info->load_addr / DSPWORDSIZE,
++                       info->size / DSPWORDSIZE);
++      }
++      return retVal;
++}
++
++/*
++ *  ======== rmmDealloc ========
++ */
++static void rmmDealloc(struct Dynamic_Loader_Allocate *this,
++                     struct LDR_SECTION_INFO *info)
++{
++      struct DBLLAlloc *pAlloc = (struct DBLLAlloc *)this;
++      struct DBLL_LibraryObj *lib;
++      u32 segid;
++      DSP_STATUS status = DSP_SOK;
++      unsigned stype = DLOAD_SECTION_TYPE(info->type);
++      u32 memType;
++      u32 freeSize = 0;
++
++      memType = (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == DLOAD_BSS) ?
++                DBLL_BSS : DBLL_DATA;
++      DBC_Require(this != NULL);
++      lib = pAlloc->lib;
++      DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++      /* segid was set by alloc function */
++      segid = (u32)info->context;
++      if (memType == DBLL_CODE)
++              freeSize = info->size + GEM_L1P_PREFETCH_SIZE;
++      else
++              freeSize = info->size;
++      if (lib != NULL) {
++              status = (lib->pTarget->attrs.free)(lib->pTarget->
++                       attrs.symHandle, segid, info->load_addr / DSPWORDSIZE,
++                       freeSize, false);
++      }
++      if (DSP_SUCCEEDED(status)) {
++              GT_2trace(DBLL_debugMask, GT_5CLASS,
++                       "Remote dealloc: base = 0x%lx len ="
++                       "0x%lx\n", info->load_addr / DSPWORDSIZE,
++                       freeSize / DSPWORDSIZE);
++      }
++}
++
++/* Dynamic_Loader_Initialize */
++/*
++ *  ======== connect ========
++ */
++static int connect(struct Dynamic_Loader_Initialize *this)
++{
++      return true;
++}
++
++/*
++ *  ======== readMem ========
++ *  This function does not need to be implemented.
++ */
++static int readMem(struct Dynamic_Loader_Initialize *this, void *buf,
++                LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++                unsigned nbytes)
++{
++      struct DBLLInit *pInit = (struct DBLLInit *)this;
++      struct DBLL_LibraryObj *lib;
++      int bytesRead = 0;
++
++      DBC_Require(this != NULL);
++      lib = pInit->lib;
++      DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++      /* Need WMD_BRD_Read function */
++      return bytesRead;
++}
++
++/*
++ *  ======== writeMem ========
++ */
++static int writeMem(struct Dynamic_Loader_Initialize *this, void *buf,
++                 LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++                 unsigned nBytes)
++{
++      struct DBLLInit *pInit = (struct DBLLInit *)this;
++      struct DBLL_LibraryObj *lib;
++      struct DBLL_SectInfo sectInfo;
++      u32 memType;
++      bool retVal = true;
++
++      DBC_Require(this != NULL);
++      lib = pInit->lib;
++      DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++      memType = (DLOAD_SECTION_TYPE(info->type) == DLOAD_TEXT) ? DBLL_CODE :
++                DBLL_DATA;
++      if (lib != NULL) {
++              retVal = (*lib->pTarget->attrs.write)(lib->pTarget->
++                      attrs.wHandle, addr, buf, nBytes, memType);
++      }
++      if (lib->pTarget->attrs.logWrite) {
++              sectInfo.name = info->name;
++              sectInfo.runAddr = info->run_addr;
++              sectInfo.loadAddr = info->load_addr;
++              sectInfo.size = info->size;
++              sectInfo.type = memType;
++              /* Pass the information about what we've written to
++               * another module */
++              (*lib->pTarget->attrs.logWrite)(lib->pTarget->
++                      attrs.logWriteHandle, &sectInfo, addr, nBytes);
++      }
++      return retVal;
++}
++
++/*
++ *  ======== fillMem ========
++ *  Fill nBytes of memory at a given address with a given value by
++ *  writing from a buffer containing the given value.  Write in
++ *  sets of MAXEXPR (128) bytes to avoid large stack buffer issues.
++ */
++static int fillMem(struct Dynamic_Loader_Initialize *this, LDR_ADDR addr,
++                 struct LDR_SECTION_INFO *info, unsigned nBytes,
++                 unsigned val)
++{
++      bool retVal = true;
++      char *pBuf;
++      struct DBLL_LibraryObj *lib;
++      struct DBLLInit *pInit = (struct DBLLInit *)this;
++
++      DBC_Require(this != NULL);
++      lib = pInit->lib;
++      pBuf = NULL;
++      /* Pass the NULL pointer to writeMem to get the start address of Shared
++          memory. This is a trick to just get the start address, there is no
++          writing taking place with this Writemem
++      */
++      if ((lib->pTarget->attrs.write) != (DBLL_WriteFxn)NoOp)
++              writeMem(this, &pBuf, addr, info, 0);
++      if (pBuf)
++              memset(pBuf, val, nBytes);
++
++      return retVal;
++}
++
++/*
++ *  ======== execute ========
++ */
++static int execute(struct Dynamic_Loader_Initialize *this, LDR_ADDR start)
++{
++      struct DBLLInit *pInit = (struct DBLLInit *)this;
++      struct DBLL_LibraryObj *lib;
++      bool retVal = true;
++
++      DBC_Require(this != NULL);
++      lib = pInit->lib;
++      DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++      /* Save entry point */
++      if (lib != NULL)
++              lib->entry = (u32)start;
++
++      return retVal;
++}
++
++/*
++ *  ======== release ========
++ */
++static void release(struct Dynamic_Loader_Initialize *this)
++{
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dev.c b/drivers/dsp/bridge/pmgr/dev.c
+new file mode 100644
+index 0000000..1c2f7d5
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dev.c
+@@ -0,0 +1,1476 @@
++/*
++ * dev.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dev.c ========
++ *  Description:
++ *      Implementation of 'Bridge Mini-driver device operations.
++ *
++ *  Public Functions:
++ *      DEV_BrdWriteFxn
++ *      DEV_CreateDevice
++ *      DEV_Create2
++ *      DEV_Destroy2
++ *      DEV_DestroyDevice
++ *      DEV_GetChnlMgr
++ *      DEV_GetCmmMgr
++ *      DEV_GetCodMgr
++ *      DEV_GetDehMgr
++ *      DEV_GetDevNode
++ *      DEV_GetDSPWordSize
++ *      DEV_GetFirst
++ *      DEV_GetIntfFxns
++ *      DEV_GetIOMgr
++ *      DEV_GetNext
++ *      DEV_GetNodeManager
++ *      DEV_GetSymbol
++ *      DEV_GetWMDContext
++ *      DEV_Exit
++ *      DEV_Init
++ *      DEV_InsertProcObject
++ *      DEV_IsLocked
++ *      DEV_NotifyClient
++ *      DEV_RegisterNotify
++ *      DEV_ReleaseCodMgr
++ *      DEV_RemoveDevice
++ *      DEV_RemoveProcObject
++ *      DEV_SetChnlMgr
++ *      DEV_SetMsgMgr
++ *      DEV_SetLockOwner
++ *      DEV_StartDevice
++ *
++ *  Private Functions:
++ *      FxnNotImplemented
++ *      InitCodMgr
++ *      InsertDevObject
++ *      IsValidHandle
++ *      RemoveDevObject
++ *      StoreInterfaceFxns
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Jan-2005 hn  Support for IVA DEH
++ *! 08-Mar-2004 sb  Added the Dynamic Memory Mapping feature
++ *! 09-Feb-2004 vp    Updated to support IVA.
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 29-Nov-2001 jeh Check for DSP_ENOTIMPL status of DEH create function.
++ *! 05-Nov-2001 kc  Added support for DEH module.
++ *! 05-Aug-2001 ag  Shared memory registration moved to WMD_IO_OnLoaded().
++ *! 11-Jul-2001 jeh Moved MGR_Create() from DSP_Init() to DEV_StartDevice().
++ *! 11-Apr-2001 rr: Removed CMM_RegisterGPPSMSeg.
++ *! 02-Apr-2001 rr: CHNL_Create failure is printed out.
++ *! 15-Jan-2001 jeh Removed call to IO_OnLoaded() from DEV_Create2().
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name update.
++ *! 15-Dec-2000 rr: Dev_Create2 returns error if NODE_CreateMgr fails.
++ *! 05-Dec-2000 jeh Moved IO_OnLoaded() to PROC_Load. Added DEV_SetMsgMgr.
++ *! 05-Dev-2000 ag  SM Heap for messaging registered via CMM_RegisterGPPSMSeg().
++ *!                 SM heap base and size currently taken from registry.
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 17-Nov-2000 jeh Added calls to get IO manager (IO_Create), IO_OnLoaded().
++ *! 06-Oct-2000 rr: DEV_Destroy2 and DEV_Create2 added.
++ *! 02-Oct-2000 rr: DEV_GetNodeManager added.
++ *! 11-Aug-2000 ag: Added DEV_GetCmmMgr(), CMM_Init() & CMM_Exit().
++ *!                 Removed <dspbridge/std.h> & <stdwin.h>, added <dspbridge/dbtype.h>
++ *! 10-Aug-2000 rr: DEV_InsertProcObject/RemoveProcObject added.
++ *!                 DEV_Cleanup calls PROC_Detach if it is a matching process.
++ *! 27-Jul-2000 rr: DEV is in new directoy DEV and produces devlib.lib
++ *! 17-Jul-2000 rr: DRV Object holds the list of Dev Objects. DEV gets
++ *!                 the List and Next devices through DRV.
++ *!                 DEV object has a back pointer to DRV Object.
++ *! 06-Jun-2000 jeh Added DEV_GetSymbol().
++ *! 09-May-2000 rr: dwMemBase has index for multiple windows need.
++ *! 28-Feb-2000 rr: New GT Usage implemented.
++ *! 03-Feb-2000 rr: GT and Module init/exit Changes.(Done up front from
++ *!               SERVICES)
++ *! 31-Jan-2000 rr: Comments changed after code review.
++ *! 21-Jan-2000 rr: windows.h, tchar.h, HMODULE removed. FreeLibrary replaced
++ *!                 with LDR_FreeModule
++ *! 17-Jan-2000 rr: CFG_Get/SetPrivateDword renamed to CFG_Get/SetDevObject.
++ *!                 StoreInterfaceFxns stores the new fxn WMD_BRD_SETSTATE.
++ *! 20-Nov-1999 ag: Actual uSMLength =  total - monitor offset.
++ *! 12-Nov-1999 rr: bIRQ and IRQAttrib taken from the struct CFG_HOSTRES.
++ *!               dMemBase is added with offset for monitor taken from
++ *!               registry.
++ *! 31-Oct-1999 ag: Added CHNL support.
++ *! 10-Sep-1999 rr: GT Enabled. DEV_Create will Load the Mini Driver and will
++ *!                 find its fxn table. Right now lot of things are hardcoded
++ *!                 as the REG is not ready.
++ *! 10-Jun-1996 rr: Created from WSX
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/ldr.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/dmm.h>
++
++/*  ----------------------------------- Resource Manager */
++#include <dspbridge/mgr.h>
++#include <dspbridge/node.h>
++
++/*  ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++#include <dspbridge/wcd.h>            /* WCD version info. */
++
++#include <dspbridge/chnl.h>
++#include <dspbridge/io.h>
++#include <dspbridge/msg.h>
++#include <dspbridge/cmm.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/dev.h>
++
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++
++#define SIGNATURE           0x5f564544        /* "DEV_" (in reverse) */
++#define MAKEVERSION(major, minor)   (major * 10 + minor)
++#define WCDVERSION          MAKEVERSION(WCD_MAJOR_VERSION, WCD_MINOR_VERSION)
++
++/* The WMD device object: */
++struct DEV_OBJECT {
++      /* LST requires "link" to be first field!                        */
++      struct LST_ELEM link;           /* Link to next DEV_OBJECT.      */
++      u32 devType;            /* Device Type */
++      u32 dwSignature;        /* Used for object validation.   */
++      struct CFG_DEVNODE *hDevNode;   /* Platform specific device id   */
++      struct WMD_DEV_CONTEXT *hWmdContext;    /* WMD Context Handle        */
++      struct WMD_DRV_INTERFACE intfFxns;      /* Function interface to WMD. */
++      struct BRD_OBJECT *lockOwner;   /* Client with exclusive access. */
++      struct COD_MANAGER *hCodMgr;    /* Code manager handle.          */
++      struct CHNL_MGR *hChnlMgr;      /* Channel manager.              */
++      struct DEH_MGR *hDehMgr;        /* DEH manager.                  */
++      struct MSG_MGR *hMsgMgr;        /* Message manager.              */
++      struct IO_MGR *hIOMgr;          /* IO manager (CHNL, MSG)        */
++      struct CMM_OBJECT *hCmmMgr;     /* SM memory manager.            */
++      struct DMM_OBJECT *hDmmMgr;     /* Dynamic memory manager.       */
++      struct LDR_MODULE *hModule;     /* WMD Module handle.            */
++      u32 uWordSize;  /* DSP word size: quick access.  */
++      struct DRV_OBJECT *hDrvObject;  /* Driver Object                 */
++      struct LST_LIST *procList;      /* List of Proceeosr attached to
++                               * this device  */
++      struct NODE_MGR *hNodeMgr;
++} ;
++
++/*  ----------------------------------- Globals */
++static u32 cRefs;             /* Module reference count */
++#if GT_TRACE
++static struct GT_Mask debugMask = { NULL, NULL };     /* For debugging */
++#endif
++
++/*  ----------------------------------- Function Prototypes */
++static DSP_STATUS FxnNotImplemented(int arg, ...);
++static DSP_STATUS InitCodMgr(struct DEV_OBJECT *pDevObject);
++static bool IsValidHandle(struct DEV_OBJECT *hObj);
++static void StoreInterfaceFxns(struct WMD_DRV_INTERFACE *pDrvFxns,
++                             OUT struct WMD_DRV_INTERFACE *pIntfFxns);
++/*
++ *  ======== DEV_BrdWriteFxn ========
++ *  Purpose:
++ *      Exported function to be used as the COD write function.  This function
++ *      is passed a handle to a DEV_hObject, then calls the
++ *      device's WMD_BRD_Write() function.
++ */
++u32 DEV_BrdWriteFxn(void *pArb, u32 ulDspAddr, void *pHostBuf,
++                    u32 ulNumBytes, u32 nMemSpace)
++{
++      struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)pArb;
++      u32 ulWritten = 0;
++      DSP_STATUS status;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pHostBuf != NULL);  /* Required of BrdWrite(). */
++      GT_5trace(debugMask, GT_ENTER,
++              "Entered DEV_BrdWriteFxn, pArb: 0x%x\n\t\t"
++              "ulDspAddr: 0x%x\n\t\tpHostBuf: 0x%x\n \t\tulNumBytes:  0x%x\n"
++              "\t\tnMemSpace:  0x%x\n", pArb, ulDspAddr, pHostBuf,
++              ulNumBytes, nMemSpace);
++      if (IsValidHandle(pDevObject)) {
++              /* Require of BrdWrite() */
++              DBC_Assert(pDevObject->hWmdContext != NULL);
++              status = (*pDevObject->intfFxns.pfnBrdWrite)(pDevObject->
++                       hWmdContext, pHostBuf, ulDspAddr, ulNumBytes,
++                       nMemSpace);
++               /* Special case of getting the address only */
++              if (ulNumBytes == 0)
++                      ulNumBytes = 1;
++              if (DSP_SUCCEEDED(status))
++                      ulWritten = ulNumBytes;
++
++      }
++      GT_1trace(debugMask, GT_ENTER, "Exit DEV_BrdWriteFxn ulWritten: 0x%x\n",
++                ulWritten);
++      return ulWritten;
++}
++
++/*
++ *  ======== DEV_CreateDevice ========
++ *  Purpose:
++ *      Called by the operating system to load the PM Mini Driver for a
++ *      PM board (device).
++ */
++DSP_STATUS DEV_CreateDevice(OUT struct DEV_OBJECT **phDevObject,
++                          IN CONST char *pstrWMDFileName,
++                          IN CONST struct CFG_HOSTRES *pHostConfig,
++                          IN CONST struct CFG_DSPRES *pDspConfig,
++                          struct CFG_DEVNODE *hDevNode)
++{
++      struct LDR_MODULE *hModule = NULL;
++      struct WMD_DRV_INTERFACE *pDrvFxns = NULL;
++      struct DEV_OBJECT *pDevObject = NULL;
++      struct CHNL_MGRATTRS mgrAttrs;
++      struct IO_ATTRS ioMgrAttrs;
++      u32 uNumWindows;
++      struct DRV_OBJECT *hDrvObject = NULL;
++      DSP_STATUS status = DSP_SOK;
++      DBC_Require(cRefs > 0);
++      DBC_Require(phDevObject != NULL);
++      DBC_Require(pstrWMDFileName != NULL);
++      DBC_Require(pHostConfig != NULL);
++      DBC_Require(pDspConfig != NULL);
++
++      GT_5trace(debugMask, GT_ENTER,
++                "Entered DEV_CreateDevice, phDevObject: 0x%x\n"
++                "\t\tpstrWMDFileName:  0x%x\n\t\tpHostConfig:0x%x\n\t\t"
++                "pDspConfig:  0x%x\n\t\tnhDevNode:  0x%x\n", phDevObject,
++                pstrWMDFileName, pHostConfig, pDspConfig, hDevNode);
++      /*  Get the WMD interface functions*/
++      WMD_DRV_Entry(&pDrvFxns, pstrWMDFileName);
++      if (DSP_FAILED(CFG_GetObject((u32 *) &hDrvObject, REG_DRV_OBJECT))) {
++              /* don't propogate CFG errors from this PROC function */
++              GT_0trace(debugMask, GT_7CLASS,
++                        "Failed to get the DRV Object \n");
++              status = DSP_EFAIL;
++      }
++      /* Create the device object, and pass a handle to the WMD for
++       * storage. */
++      if (DSP_SUCCEEDED(status)) {
++              DBC_Assert(pDrvFxns);
++              MEM_AllocObject(pDevObject, struct DEV_OBJECT, SIGNATURE);
++              if (pDevObject) {
++                      /* Fill out the rest of the Dev Object structure: */
++                      pDevObject->hDevNode = hDevNode;
++                      pDevObject->hModule = hModule;
++                      pDevObject->hCodMgr = NULL;
++                      pDevObject->hChnlMgr = NULL;
++                      pDevObject->hDehMgr = NULL;
++                      pDevObject->lockOwner = NULL;
++                      pDevObject->uWordSize = pDspConfig->uWordSize;
++                      pDevObject->hDrvObject = hDrvObject;
++                      pDevObject->devType = DSP_UNIT;
++                      /* Store this WMD's interface functions, based on its
++                       * version. */
++                      StoreInterfaceFxns(pDrvFxns, &pDevObject->intfFxns);
++                      /* Call WMD_DEV_CREATE() to get the WMD's device
++                       * context handle. */
++                      status = (pDevObject->intfFxns.pfnDevCreate)
++                               (&pDevObject->hWmdContext, pDevObject,
++                               pHostConfig, pDspConfig);
++                      /* Assert WMD_DEV_Create()'s ensure clause: */
++                      DBC_Assert(DSP_FAILED(status) || (pDevObject->
++                                 hWmdContext != NULL));
++              } else {
++                      GT_0trace(debugMask, GT_7CLASS,
++                                "DEV_Create: Out Of Memory");
++                      status = DSP_EMEMORY;
++              }
++      }
++      /* Attempt to create the COD manager for this device: */
++      if (DSP_SUCCEEDED(status))
++              status = InitCodMgr(pDevObject);
++
++      /* Attempt to create the channel manager for this device: */
++      if (DSP_SUCCEEDED(status)) {
++              mgrAttrs.cChannels = CHNL_MAXCHANNELS;
++              ioMgrAttrs.bIRQ = pHostConfig->bIRQRegisters;
++              ioMgrAttrs.fShared = (pHostConfig->bIRQAttrib & CFG_IRQSHARED);
++              ioMgrAttrs.uWordSize = pDspConfig->uWordSize;
++              mgrAttrs.uWordSize = pDspConfig->uWordSize;
++              uNumWindows = pHostConfig->wNumMemWindows;
++              if (uNumWindows) {
++                      /* Assume last memory window is for CHNL */
++                      ioMgrAttrs.dwSMBase = pHostConfig->dwMemBase[1] +
++                                            pHostConfig->dwOffsetForMonitor;
++                      ioMgrAttrs.uSMLength = pHostConfig->dwMemLength[1] -
++                                             pHostConfig->dwOffsetForMonitor;
++              } else {
++                      ioMgrAttrs.dwSMBase = 0;
++                      ioMgrAttrs.uSMLength = 0;
++                      GT_0trace(debugMask, GT_7CLASS,
++                                "**There is no memory reserved for "
++                                "shared structures**\n");
++              }
++              status = CHNL_Create(&pDevObject->hChnlMgr, pDevObject,
++                                  &mgrAttrs);
++              if (status == DSP_ENOTIMPL) {
++                      /* It's OK for a device not to have a channel
++                       * manager: */
++                      status = DSP_SOK;
++              }
++              /* Create CMM mgr even if Msg Mgr not impl.  */
++              status = CMM_Create(&pDevObject->hCmmMgr,
++                                 (struct DEV_OBJECT *)pDevObject, NULL);
++              if (DSP_FAILED(status)) {
++                      GT_0trace(debugMask, GT_7CLASS,
++                                "DEV_Create: Failed to Create SM "
++                                "Manager\n");
++              }
++              /* Only create IO manager if we have a channel manager */
++              if (DSP_SUCCEEDED(status) && pDevObject->hChnlMgr) {
++                      status = IO_Create(&pDevObject->hIOMgr, pDevObject,
++                                         &ioMgrAttrs);
++              }
++              /* Only create DEH manager if we have an IO manager */
++              if (DSP_SUCCEEDED(status)) {
++                      /* Instantiate the DEH module */
++                      status = (*pDevObject->intfFxns.pfnDehCreate)
++                               (&pDevObject->hDehMgr,         pDevObject);
++              }
++              /* Create DMM mgr .  */
++              status = DMM_Create(&pDevObject->hDmmMgr,
++                                 (struct DEV_OBJECT *)pDevObject, NULL);
++              if (DSP_FAILED(status)) {
++                      GT_0trace(debugMask, GT_7CLASS,
++                                "DEV_Create: Failed to Create DMM "
++                                "Manager\n");
++              }
++      }
++      /* Add the new DEV_Object to the global list: */
++      if (DSP_SUCCEEDED(status)) {
++              LST_InitElem(&pDevObject->link);
++              status = DRV_InsertDevObject(hDrvObject, pDevObject);
++      }
++      /* Create the Processor List */
++      if (DSP_SUCCEEDED(status)) {
++              pDevObject->procList = LST_Create();
++              if (!(pDevObject->procList)) {
++                      status = DSP_EFAIL;
++                      GT_0trace(debugMask, GT_7CLASS, "DEV_Create: "
++                               "Failed to Create Proc List");
++              }
++      }
++       /*  If all went well, return a handle to the dev object;
++       *  else, cleanup and return NULL in the OUT parameter.  */
++      if (DSP_SUCCEEDED(status)) {
++              *phDevObject = pDevObject;
++              GT_1trace(debugMask, GT_1CLASS,
++                       "DEV_CreateDevice Succeeded \nDevObject "
++                       "0x%x\n", pDevObject);
++      } else {
++              if (pDevObject && pDevObject->procList)
++                      LST_Delete(pDevObject->procList);
++
++              if (pDevObject && pDevObject->hCodMgr)
++                      COD_Delete(pDevObject->hCodMgr);
++
++              if (pDevObject && pDevObject->hDmmMgr)
++                      DMM_Destroy(pDevObject->hDmmMgr);
++
++              if (pDevObject)
++                      MEM_FreeObject(pDevObject);
++
++              *phDevObject = NULL;
++              GT_0trace(debugMask, GT_7CLASS, "DEV_CreateDevice Failed\n");
++      }
++      GT_1trace(debugMask, GT_1CLASS, "Exiting DEV_Create: DevObject 0x%x\n",
++               *phDevObject);
++      DBC_Ensure((DSP_SUCCEEDED(status) && IsValidHandle(*phDevObject)) ||
++                (DSP_FAILED(status) && !*phDevObject));
++      return status;
++}
++
++/*
++ *  ======== DEV_Create2 ========
++ *  Purpose:
++ *      After successful loading of the image from WCD_InitComplete2
++ *      (PROC Auto_Start) or PROC_Load this fxn is called. This creates
++ *      the Node Manager and updates the DEV Object.
++ */
++DSP_STATUS DEV_Create2(struct DEV_OBJECT *hDevObject)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *pDevObject = hDevObject;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(IsValidHandle(hDevObject));
++
++      GT_1trace(debugMask, GT_ENTER,
++               "Entered DEV_Create2, hDevObject: 0x%x\n", hDevObject);
++      /* There can be only one Node Manager per DEV object */
++      DBC_Assert(!pDevObject->hNodeMgr);
++      status = NODE_CreateMgr(&pDevObject->hNodeMgr, hDevObject);
++      if (DSP_FAILED(status)) {
++              GT_1trace(debugMask, GT_7CLASS,
++                       "DEV_Create2: NODE_CreateMgr failed, "
++                       "0x%x!\n", status);
++              pDevObject->hNodeMgr = NULL;
++              GT_0trace(debugMask, GT_7CLASS, "DEV_Create2: Failed!!\n");
++      }
++      DBC_Ensure((DSP_SUCCEEDED(status) && pDevObject->hNodeMgr != NULL)
++                 || (DSP_FAILED(status) && pDevObject->hNodeMgr == NULL));
++      GT_2trace(debugMask, GT_ENTER,
++                "Exiting DEV_Create2, hNodeMgr:  0x%x, status:"
++                " 0x%x\n", pDevObject->hNodeMgr, status);
++      return status;
++}
++
++/*
++ *  ======== DEV_Destroy2 ========
++ *  Purpose:
++ *      Destroys the Node manager for this device.
++ */
++DSP_STATUS DEV_Destroy2(struct DEV_OBJECT *hDevObject)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *pDevObject = hDevObject;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(IsValidHandle(hDevObject));
++
++      GT_1trace(debugMask, GT_ENTER,
++               "Entered DEV_Destroy2, hDevObject: 0x%x\n",
++               hDevObject);
++      if (pDevObject->hNodeMgr) {
++              if (DSP_FAILED(NODE_DeleteMgr(pDevObject->hNodeMgr)))
++                      status = DSP_EFAIL;
++              else
++                      pDevObject->hNodeMgr = NULL;
++
++      }
++      if (DSP_FAILED(status))
++              GT_0trace(debugMask, GT_7CLASS, "DEV_Destroy2 failed!!\n");
++
++      DBC_Ensure((DSP_SUCCEEDED(status) && pDevObject->hNodeMgr == NULL) ||
++                DSP_FAILED(status));
++      GT_2trace(debugMask, GT_ENTER,
++               "Exiting DEV_Destroy2, hNodeMgr: 0x%x, status"
++               " = 0x%x\n", pDevObject->hNodeMgr, status);
++      return status;
++}
++
++/*
++ *  ======== DEV_DestroyDevice ========
++ *  Purpose:
++ *      Destroys the channel manager for this device, if any, calls
++ *      WMD_DEV_Destroy(), and then attempts to unload the WMD module.
++ */
++DSP_STATUS DEV_DestroyDevice(struct DEV_OBJECT *hDevObject)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *pDevObject = hDevObject;
++
++      DBC_Require(cRefs > 0);
++
++      GT_1trace(debugMask, GT_ENTER, "Entered DEV_DestroyDevice, hDevObject: "
++               "0x%x\n", hDevObject);
++      if (IsValidHandle(hDevObject)) {
++              if (pDevObject->hCodMgr)
++                      COD_Delete(pDevObject->hCodMgr);
++
++              if (pDevObject->hNodeMgr)
++                      NODE_DeleteMgr(pDevObject->hNodeMgr);
++
++              /* Free the io, channel, and message managers for this board: */
++              if (pDevObject->hIOMgr) {
++                      IO_Destroy(pDevObject->hIOMgr);
++                      pDevObject->hIOMgr = NULL;
++              }
++              if (pDevObject->hChnlMgr) {
++                      CHNL_Destroy(pDevObject->hChnlMgr);
++                      pDevObject->hChnlMgr = NULL;
++              }
++              if (pDevObject->hMsgMgr)
++                      MSG_Delete(pDevObject->hMsgMgr);
++
++              if (pDevObject->hDehMgr) {
++                      /* Uninitialize DEH module. */
++                      (*pDevObject->intfFxns.pfnDehDestroy)
++                      (pDevObject->hDehMgr);
++              }
++              if (pDevObject->hCmmMgr)
++                      CMM_Destroy(pDevObject->hCmmMgr, true);
++
++              if (pDevObject->hDmmMgr)
++                      DMM_Destroy(pDevObject->hDmmMgr);
++
++              /* Call the driver's WMD_DEV_Destroy() function: */
++              /* Require of DevDestroy */
++              DBC_Assert(pDevObject->hWmdContext != NULL);
++              status = (*pDevObject->intfFxns.pfnDevDestroy)
++                       (pDevObject->hWmdContext);
++              if (DSP_SUCCEEDED(status)) {
++                      if (pDevObject->procList)
++                              LST_Delete(pDevObject->procList);
++
++                      /* Remove this DEV_Object from the global list: */
++                      DRV_RemoveDevObject(pDevObject->hDrvObject, pDevObject);
++                      /* Free The library * LDR_FreeModule
++                       * (pDevObject->hModule);*/
++                      /* Free this dev object: */
++                      MEM_FreeObject(pDevObject);
++              }
++      } else {
++              GT_0trace(debugMask, GT_7CLASS, "DEV_Destroy: Invlaid handle");
++              status = DSP_EHANDLE;
++      }
++      GT_1trace(debugMask, GT_ENTER, "Exit DEV_destroy: status 0x%x\n",
++               status);
++      return status;
++}
++
++/*
++ *  ======== DEV_GetChnlMgr ========
++ *  Purpose:
++ *      Retrieve the handle to the channel manager handle created for this
++ *      device.
++ */
++DSP_STATUS DEV_GetChnlMgr(struct DEV_OBJECT *hDevObject,
++                       OUT struct CHNL_MGR **phMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *pDevObject = hDevObject;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phMgr != NULL);
++
++      GT_2trace(debugMask, GT_ENTER,
++               "Entered DEV_GetChnlMgr, hDevObject: 0x%x\n\t"
++               "\tphMgr: 0x%x\n", hDevObject, phMgr);
++      if (IsValidHandle(hDevObject)) {
++              *phMgr = pDevObject->hChnlMgr;
++      } else {
++              *phMgr = NULL;
++              status = DSP_EHANDLE;
++              GT_0trace(debugMask, GT_7CLASS,
++                       "DEV_GetChnlMgr: Invalid handle");
++      }
++      GT_2trace(debugMask, GT_ENTER,
++               "Exit DEV_GetChnlMgr: status 0x%x\t\n hMgr: "
++               "0x%x\n", status, *phMgr);
++      DBC_Ensure(DSP_SUCCEEDED(status) || ((phMgr != NULL) &&
++                (*phMgr == NULL)));
++      return status;
++}
++
++/*
++ *  ======== DEV_GetCmmMgr ========
++ *  Purpose:
++ *      Retrieve the handle to the shared memory manager created for this
++ *      device.
++ */
++DSP_STATUS DEV_GetCmmMgr(struct DEV_OBJECT *hDevObject,
++                      OUT struct CMM_OBJECT **phMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *pDevObject = hDevObject;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phMgr != NULL);
++      GT_2trace(debugMask, GT_ENTER,
++               "Entered DEV_GetCmmMgr, hDevObject:  0x%x\n\t"
++               "\tphMgr:  0x%x\n", hDevObject, phMgr);
++      if (IsValidHandle(hDevObject)) {
++              *phMgr = pDevObject->hCmmMgr;
++      } else {
++              *phMgr = NULL;
++              status = DSP_EHANDLE;
++              GT_0trace(debugMask, GT_7CLASS,
++                       "DEV_GetCmmMgr: Invalid handle");
++      }
++      GT_2trace(debugMask, GT_ENTER,
++               "Exit DEV_GetCmmMgr: status 0x%x\t\nhMgr: "
++               "0x%x\n", status, *phMgr);
++      DBC_Ensure(DSP_SUCCEEDED(status) || ((phMgr != NULL) &&
++                (*phMgr == NULL)));
++      return status;
++}
++
++/*
++ *  ======== DEV_GetDmmMgr ========
++ *  Purpose:
++ *      Retrieve the handle to the dynamic memory manager created for this
++ *      device.
++ */
++DSP_STATUS DEV_GetDmmMgr(struct DEV_OBJECT *hDevObject,
++                      OUT struct DMM_OBJECT **phMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *pDevObject = hDevObject;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phMgr != NULL);
++
++      GT_2trace(debugMask, GT_ENTER, "Entered DEV_GetDmmMgr, hDevObject: "
++               "0x%x\n\t\tphMgr: 0x%x\n", hDevObject, phMgr);
++      if (IsValidHandle(hDevObject)) {
++              *phMgr = pDevObject->hDmmMgr;
++      } else {
++              *phMgr = NULL;
++              status = DSP_EHANDLE;
++              GT_0trace(debugMask, GT_7CLASS,
++                       "DEV_GetDmmMgr: Invalid handle");
++      }
++      GT_2trace(debugMask, GT_ENTER,
++               "Exit DEV_GetDmmMgr: status 0x%x\t\n hMgr: "
++               "0x%x\n", status, *phMgr);
++      DBC_Ensure(DSP_SUCCEEDED(status) || ((phMgr != NULL) &&
++                (*phMgr == NULL)));
++      return status;
++}
++
++/*
++ *  ======== DEV_GetCodMgr ========
++ *  Purpose:
++ *      Retrieve the COD manager create for this device.
++ */
++DSP_STATUS DEV_GetCodMgr(struct DEV_OBJECT *hDevObject,
++                      OUT struct COD_MANAGER **phCodMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *pDevObject = hDevObject;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phCodMgr != NULL);
++
++      GT_2trace(debugMask, GT_ENTER,
++               "Entered DEV_GetCodMgr, hDevObject: 0x%x\n\t\t"
++               "phCodMgr: 0x%x\n", hDevObject, phCodMgr);
++      if (IsValidHandle(hDevObject)) {
++              *phCodMgr = pDevObject->hCodMgr;
++      } else {
++              *phCodMgr = NULL;
++              status = DSP_EHANDLE;
++              GT_1trace(debugMask, GT_7CLASS,
++                       "DEV_GetCodMgr, invalid handle:  0x%x\n",
++                       hDevObject);
++      }
++      GT_2trace(debugMask, GT_ENTER,
++               "Exit DEV_GetCodMgr: status 0x%x\t\n hCodMgr:"
++               " 0x%x\n", status, *phCodMgr);
++      DBC_Ensure(DSP_SUCCEEDED(status) || ((phCodMgr != NULL) &&
++                (*phCodMgr == NULL)));
++      return status;
++}
++
++/*
++ *  ========= DEV_GetDehMgr ========
++ */
++DSP_STATUS DEV_GetDehMgr(struct DEV_OBJECT *hDevObject,
++                      OUT struct DEH_MGR **phDehMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phDehMgr != NULL);
++      DBC_Require(MEM_IsValidHandle(hDevObject, SIGNATURE));
++      if (IsValidHandle(hDevObject)) {
++              *phDehMgr = hDevObject->hDehMgr;
++      } else {
++              *phDehMgr = NULL;
++              status = DSP_EHANDLE;
++              GT_0trace(debugMask, GT_7CLASS,
++                       "DEV_GetDehMgr: Invalid handle");
++      }
++      return status;
++}
++
++/*
++ *  ======== DEV_GetDevNode ========
++ *  Purpose:
++ *      Retrieve the platform specific device ID for this device.
++ */
++DSP_STATUS DEV_GetDevNode(struct DEV_OBJECT *hDevObject,
++                       OUT struct CFG_DEVNODE **phDevNode)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *pDevObject = hDevObject;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phDevNode != NULL);
++
++      GT_2trace(debugMask, GT_ENTER,
++               "Entered DEV_GetDevNode, hDevObject: 0x%x\n\t"
++               "\tphDevNode: 0x%x\n", hDevObject, phDevNode);
++      if (IsValidHandle(hDevObject)) {
++              *phDevNode = pDevObject->hDevNode;
++      } else {
++              *phDevNode = NULL;
++              status = DSP_EHANDLE;
++              GT_0trace(debugMask, GT_7CLASS,
++                       "DEV_GetDevNode: Invalid handle");
++      }
++      GT_2trace(debugMask, GT_ENTER,
++               "Exit DEV_GetDevNode: status 0x%x\t\nhDevNode:"
++               "0x%x\n", status, *phDevNode);
++      DBC_Ensure(DSP_SUCCEEDED(status) || ((phDevNode != NULL) &&
++                (*phDevNode == NULL)));
++      return status;
++}
++
++/*
++ *  ======== DEV_GetFirst ========
++ *  Purpose:
++ *      Retrieve the first Device Object handle from an internal linked list
++ *      DEV_OBJECTs maintained by DEV.
++ */
++struct DEV_OBJECT *DEV_GetFirst(void)
++{
++      struct DEV_OBJECT *pDevObject = NULL;
++
++      pDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++
++      DBC_Ensure((pDevObject == NULL) || IsValidHandle(pDevObject));
++
++      return pDevObject;
++}
++
++/*
++ *  ======== DEV_GetIntfFxns ========
++ *  Purpose:
++ *      Retrieve the WMD interface function structure for the loaded WMD.
++ *      ppIntfFxns != NULL.
++ */
++DSP_STATUS DEV_GetIntfFxns(struct DEV_OBJECT *hDevObject,
++                        OUT struct WMD_DRV_INTERFACE **ppIntfFxns)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *pDevObject = hDevObject;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(ppIntfFxns != NULL);
++
++      GT_2trace(debugMask, GT_ENTER,
++               "Entered DEV_GetIntfFxns, hDevObject: 0x%x\n\t"
++               "\tppIntfFxns: 0x%x\n", hDevObject, ppIntfFxns);
++      if (IsValidHandle(hDevObject)) {
++              *ppIntfFxns = &pDevObject->intfFxns;
++      } else {
++              *ppIntfFxns = NULL;
++              status = DSP_EHANDLE;
++              GT_0trace(debugMask, GT_7CLASS,
++                        "DEV_GetIntDxns: Invalid handle");
++      }
++      GT_2trace(debugMask, GT_ENTER, "Exit DEV_GetIntFxns: status 0x%x\t\n"
++               "ppIntFxns: 0x%x\n", status, *ppIntfFxns);
++      DBC_Ensure(DSP_SUCCEEDED(status) || ((ppIntfFxns != NULL) &&
++                (*ppIntfFxns == NULL)));
++      return status;
++}
++
++/*
++ *  ========= DEV_GetIOMgr ========
++ */
++DSP_STATUS DEV_GetIOMgr(struct DEV_OBJECT *hDevObject,
++                      OUT struct IO_MGR **phIOMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phIOMgr != NULL);
++      DBC_Require(MEM_IsValidHandle(hDevObject, SIGNATURE));
++
++      if (IsValidHandle(hDevObject)) {
++              *phIOMgr = hDevObject->hIOMgr;
++      } else {
++              *phIOMgr = NULL;
++              status = DSP_EHANDLE;
++              GT_0trace(debugMask, GT_7CLASS, "DEV_GetIOMgr: Invalid handle");
++      }
++
++      return status;
++}
++
++/*
++ *  ======== DEV_GetNext ========
++ *  Purpose:
++ *      Retrieve the next Device Object handle from an internal linked list
++ *      of DEV_OBJECTs maintained by DEV, after having previously called
++ *      DEV_GetFirst() and zero or more DEV_GetNext
++ */
++struct DEV_OBJECT *DEV_GetNext(struct DEV_OBJECT *hDevObject)
++{
++      struct DEV_OBJECT *pNextDevObject = NULL;
++
++      if (IsValidHandle(hDevObject)) {
++              pNextDevObject = (struct DEV_OBJECT *)
++                               DRV_GetNextDevObject((u32)hDevObject);
++      }
++      DBC_Ensure((pNextDevObject == NULL) || IsValidHandle(pNextDevObject));
++      return pNextDevObject;
++}
++
++/*
++ *  ========= DEV_GetMsgMgr ========
++ */
++void DEV_GetMsgMgr(struct DEV_OBJECT *hDevObject,
++                      OUT struct MSG_MGR **phMsgMgr)
++{
++      DBC_Require(cRefs > 0);
++      DBC_Require(phMsgMgr != NULL);
++      DBC_Require(MEM_IsValidHandle(hDevObject, SIGNATURE));
++
++      *phMsgMgr = hDevObject->hMsgMgr;
++}
++
++/*
++ *  ======== DEV_GetNodeManager ========
++ *  Purpose:
++ *      Retrieve the Node Manager Handle
++ */
++DSP_STATUS DEV_GetNodeManager(struct DEV_OBJECT *hDevObject,
++                                 OUT struct NODE_MGR **phNodeMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *pDevObject = hDevObject;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phNodeMgr != NULL);
++
++      GT_2trace(debugMask, GT_ENTER,
++               "Entered DEV_GetNodeManager, hDevObject: 0x%x"
++               "\n\t\tphNodeMgr: 0x%x\n", hDevObject, phNodeMgr);
++      if (IsValidHandle(hDevObject)) {
++              *phNodeMgr = pDevObject->hNodeMgr;
++      } else {
++              *phNodeMgr = NULL;
++              status = DSP_EHANDLE;
++              GT_1trace(debugMask, GT_7CLASS,
++                       "DEV_GetNodeManager, invalid handle: 0x"
++                       "%x\n", hDevObject);
++      }
++      GT_2trace(debugMask, GT_ENTER,
++               "Exit DEV_GetNodeManager: status 0x%x\t\nhMgr:"
++               " 0x%x\n", status, *phNodeMgr);
++      DBC_Ensure(DSP_SUCCEEDED(status) || ((phNodeMgr != NULL) &&
++                (*phNodeMgr == NULL)));
++      return status;
++}
++
++/*
++ *  ======== DEV_GetSymbol ========
++ */
++DSP_STATUS DEV_GetSymbol(struct DEV_OBJECT *hDevObject,
++                            IN CONST char *pstrSym, OUT u32 *pulValue)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct COD_MANAGER *hCodMgr;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pstrSym != NULL && pulValue != NULL);
++
++      GT_3trace(debugMask, GT_ENTER,
++               "Entered DEV_GetSymbol, hDevObject: 0x%x\n\t\t"
++               "pstrSym: 0x%x\n\t\tpulValue: 0x%x\n", hDevObject, pstrSym,
++               pulValue);
++      if (IsValidHandle(hDevObject)) {
++              status = DEV_GetCodMgr(hDevObject, &hCodMgr);
++              if (DSP_SUCCEEDED(status)) {
++                      DBC_Assert(hCodMgr != NULL);
++                      status = COD_GetSymValue(hCodMgr, (char *)pstrSym,
++                               pulValue);
++              }
++      } else {
++              status = DSP_EHANDLE;
++              GT_0trace(debugMask, GT_7CLASS,
++                       "DEV_GetSymbol: Invalid handle");
++      }
++      GT_2trace(debugMask, GT_ENTER, "Exit DEV_GetSymbol: status 0x%x\t\n"
++               "hWmdContext: 0x%x\n", status, *pulValue);
++      return status;
++}
++
++/*
++ *  ======== DEV_GetWMDContext ========
++ *  Purpose:
++ *      Retrieve the WMD Context handle, as returned by the WMD_Create fxn.
++ */
++DSP_STATUS DEV_GetWMDContext(struct DEV_OBJECT *hDevObject,
++                          OUT struct WMD_DEV_CONTEXT **phWmdContext)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *pDevObject = hDevObject;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phWmdContext != NULL);
++      GT_2trace(debugMask, GT_ENTER,
++                "Entered DEV_GetWMDContext, hDevObject: 0x%x\n"
++                "\t\tphWmdContext: 0x%x\n", hDevObject, phWmdContext);
++      if (IsValidHandle(hDevObject)) {
++              *phWmdContext = pDevObject->hWmdContext;
++      } else {
++              *phWmdContext = NULL;
++              status = DSP_EHANDLE;
++              GT_0trace(debugMask, GT_7CLASS,
++                       "DEV_GetWMDContext: Invalid handle");
++      }
++
++      GT_2trace(debugMask, GT_ENTER,
++               "Exit DEV_GetWMDContext: status 0x%x\t\n"
++               "hWmdContext: 0x%x\n", status, *phWmdContext);
++      DBC_Ensure(DSP_SUCCEEDED(status) || ((phWmdContext != NULL) &&
++                (*phWmdContext == NULL)));
++      return status;
++}
++
++/*
++ *  ======== DEV_Exit ========
++ *  Purpose:
++ *      Decrement reference count, and free resources when reference count is
++ *      0.
++ */
++void DEV_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      cRefs--;
++
++      if (cRefs == 0) {
++              CMM_Exit();
++              DMM_Exit();
++      }
++
++      GT_1trace(debugMask, GT_5CLASS, "Entered DEV_Exit, ref count: 0x%x\n",
++               cRefs);
++
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== DEV_Init ========
++ *  Purpose:
++ *      Initialize DEV's private state, keeping a reference count on each call.
++ */
++bool DEV_Init(void)
++{
++      bool fCmm, fDmm, fRetval = true;
++
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++              /* Set the Trace mask */
++              DBC_Assert(!debugMask.flags);
++              GT_create(&debugMask, "DV");    /* "DV" for DeVice */
++              fCmm = CMM_Init();
++              fDmm = DMM_Init();
++
++              fRetval = fCmm && fDmm;
++
++              if (!fRetval) {
++                      if (fCmm)
++                              CMM_Exit();
++
++
++                      if (fDmm)
++                              DMM_Exit();
++
++              }
++      }
++
++      if (fRetval)
++              cRefs++;
++
++
++      GT_1trace(debugMask, GT_5CLASS, "Entered DEV_Init, ref count: 0x%x\n",
++               cRefs);
++
++      DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++      return fRetval;
++}
++
++/*
++ *  ======== DEV_NotifyClients ========
++ *  Purpose:
++ *      Notify all clients of this device of a change in device status.
++ */
++DSP_STATUS DEV_NotifyClients(struct DEV_OBJECT *hDevObject, u32 ulStatus)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      struct DEV_OBJECT *pDevObject = hDevObject;
++      DSP_HPROCESSOR hProcObject;
++
++      GT_2trace(debugMask, GT_ENTER,
++               "Entered DEV_NotifyClients, hDevObject: 0x%x\n"
++               "\t\tulStatus: 0x%x\n", hDevObject, ulStatus);
++      for (hProcObject = (DSP_HPROCESSOR)LST_First(pDevObject->procList);
++              hProcObject != NULL;
++              hProcObject = (DSP_HPROCESSOR)LST_Next(pDevObject->procList,
++                                              (struct LST_ELEM *)hProcObject))
++              PROC_NotifyClients(hProcObject, (u32) ulStatus);
++
++      return status;
++}
++
++/*
++ *  ======== DEV_RemoveDevice ========
++ */
++DSP_STATUS DEV_RemoveDevice(struct CFG_DEVNODE *hDevNode)
++{
++      struct DEV_OBJECT *hDevObject;  /* handle to device object */
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *pDevObject;
++
++      GT_1trace(debugMask, GT_ENTER,
++               "Entered DEV_RemoveDevice, hDevNode:  0x%x\n", hDevNode);
++      /* Retrieve the device object handle originaly stored with
++       * the DevNode: */
++      status = CFG_GetDevObject(hDevNode, (u32 *)&hDevObject);
++      if (DSP_SUCCEEDED(status)) {
++              /* Remove the Processor List */
++              pDevObject = (struct DEV_OBJECT *)hDevObject;
++              /* Destroy the device object. */
++              status = DEV_DestroyDevice(hDevObject);
++              if (DSP_SUCCEEDED(status)) {
++                      /* Null out the handle stored with the DevNode. */
++                      GT_0trace(debugMask, GT_1CLASS,
++                               "DEV_RemoveDevice, success");
++              }
++      }
++      GT_1trace(debugMask, GT_ENTER, "Exit DEV_RemoveDevice, status: 0x%x\n",
++                status);
++      return status;
++}
++
++/*
++ *  ======== DEV_SetChnlMgr ========
++ *  Purpose:
++ *      Set the channel manager for this device.
++ */
++DSP_STATUS DEV_SetChnlMgr(struct DEV_OBJECT *hDevObject, struct CHNL_MGR *hMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *pDevObject = hDevObject;
++
++      DBC_Require(cRefs > 0);
++
++      GT_2trace(debugMask, GT_ENTER,
++               "Entered DEV_SetChnlMgr, hDevObject: 0x%x\n\t"
++               "\thMgr:0x%x\n", hDevObject, hMgr);
++      if (IsValidHandle(hDevObject)) {
++              pDevObject->hChnlMgr = hMgr;
++      } else {
++              status = DSP_EHANDLE;
++              GT_0trace(debugMask, GT_7CLASS,
++                       "DEV_SetChnlMgr, Invalid handle\n");
++      }
++      DBC_Ensure(DSP_FAILED(status) || (pDevObject->hChnlMgr == hMgr));
++      return status;
++}
++
++/*
++ *  ======== DEV_SetMsgMgr ========
++ *  Purpose:
++ *      Set the message manager for this device.
++ */
++void DEV_SetMsgMgr(struct DEV_OBJECT *hDevObject, struct MSG_MGR *hMgr)
++{
++      DBC_Require(cRefs > 0);
++      DBC_Require(IsValidHandle(hDevObject));
++      GT_2trace(debugMask, GT_ENTER,
++               "Entered DEV_SetMsgMgr, hDevObject: 0x%x\n\t\t"
++               "hMgr: 0x%x\n", hDevObject, hMgr);
++      hDevObject->hMsgMgr = hMgr;
++}
++
++/*
++ *  ======== DEV_StartDevice ========
++ *  Purpose:
++ *      Initializes the new device with the BRIDGE environment.
++ */
++DSP_STATUS DEV_StartDevice(struct CFG_DEVNODE *hDevNode)
++{
++      struct DEV_OBJECT *hDevObject = NULL;   /* handle to 'Bridge Device */
++      struct CFG_HOSTRES hostRes;     /* resources struct. */
++      struct CFG_DSPRES dspRes;       /* DSP resources struct */
++      char szWMDFileName[CFG_MAXSEARCHPATHLEN] = "UMA"; /* wmd filename */
++      DSP_STATUS status;
++      struct MGR_OBJECT *hMgrObject = NULL;
++
++      DBC_Require(cRefs > 0);
++
++      GT_1trace(debugMask, GT_ENTER,
++               "Entered DEV_StartDevice, hDevObject: 0x%x\n", hDevNode);
++              status = CFG_GetHostResources(hDevNode, &hostRes);
++              if (DSP_SUCCEEDED(status)) {
++                      /* Get DSP resources of device from Registry: */
++                      status = CFG_GetDSPResources(hDevNode, &dspRes);
++                      if (DSP_FAILED(status)) {
++                              GT_1trace(debugMask, GT_7CLASS,
++                                       "Failed to get WMD DSP resources"
++                                       " from registry: 0x%x ", status);
++                      }
++              } else {
++                      GT_1trace(debugMask, GT_7CLASS,
++                               "Failed to get WMD Host resources "
++                               "from registry: 0x%x ", status);
++              }
++      if (DSP_SUCCEEDED(status)) {
++              /* Given all resources, create a device object. */
++              status = DEV_CreateDevice(&hDevObject, szWMDFileName, &hostRes,
++                                       &dspRes, hDevNode);
++              if (DSP_SUCCEEDED(status)) {
++                      /* Store away the hDevObject with the DEVNODE */
++                      status = CFG_SetDevObject(hDevNode, (u32)hDevObject);
++                      if (DSP_FAILED(status)) {
++                              /* Clean up */
++                              GT_1trace(debugMask, GT_7CLASS,
++                                       "Failed to set DevObject in the "
++                                       "Registry: 0x%x", status);
++                              DEV_DestroyDevice(hDevObject);
++                              hDevObject = NULL;
++                      }
++              } else {
++                      GT_1trace(debugMask, GT_7CLASS,
++                               "Failed to Create Device: 0x%x",
++                               status);
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Create the Manager Object */
++              status = MGR_Create(&hMgrObject, hDevNode);
++      }
++      if (DSP_FAILED(status)) {
++              GT_1trace(debugMask, GT_7CLASS, "Failed to MGR object: 0x%x",
++                       status);
++              status = DSP_EFAIL;
++      }
++      if (DSP_FAILED(status)) {
++              if (hDevObject)
++                      DEV_DestroyDevice(hDevObject);
++
++              /* Ensure the device extension is NULL */
++              CFG_SetDevObject(hDevNode, 0L);
++      }
++      GT_1trace(debugMask, GT_ENTER, "Exiting DEV_StartDevice status 0x%x\n",
++               status);
++      return status;
++}
++
++/*
++ *  ======== FxnNotImplemented ========
++ *  Purpose:
++ *      Takes the place of a WMD Null Function.
++ *  Parameters:
++ *      Multiple, optional.
++ *  Returns:
++ *      DSP_ENOTIMPL:   Always.
++ */
++static DSP_STATUS FxnNotImplemented(int arg, ...)
++{
++      DBG_Trace(DBG_LEVEL1,
++               "WARNING: Calling a non-implemented WMD function.\n");
++
++      return DSP_ENOTIMPL;
++}
++
++/*
++ *  ======== IsValidHandle ========
++ *  Purpose:
++ *      Validate the device object handle.
++ *  Parameters:
++ *      hDevObject:     Handle to device object created with
++ *                      DEV_CreateDevice().
++ *  Returns:
++ *      true if handle is valid; false otherwise.
++ *  Requires:
++ *  Ensures:
++ */
++static bool IsValidHandle(struct DEV_OBJECT *hObj)
++{
++      bool retVal;
++
++      retVal = (hObj != NULL) && (hObj->dwSignature == SIGNATURE);
++
++      return retVal;
++}
++
++/*
++ *  ======== InitCodMgr ========
++ *  Purpose:
++ *      Create a COD manager for this device.
++ *  Parameters:
++ *      pDevObject:             Pointer to device object created with
++ *                              DEV_CreateDevice()
++ *  Returns:
++ *      DSP_SOK:                Success.
++ *      DSP_EHANDLE:            Invalid hDevObject.
++ *  Requires:
++ *      Should only be called once by DEV_CreateDevice() for a given DevObject.
++ *  Ensures:
++ */
++static DSP_STATUS InitCodMgr(struct DEV_OBJECT *pDevObject)
++{
++      DSP_STATUS status = DSP_SOK;
++      char *szDummyFile = "dummy";
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(!IsValidHandle(pDevObject) ||
++                 (pDevObject->hCodMgr == NULL));
++      GT_1trace(debugMask, GT_ENTER, "Entering InitCodMgr pDevObject: 0x%x",
++               pDevObject);
++      status = COD_Create(&pDevObject->hCodMgr, szDummyFile, NULL);
++      GT_1trace(debugMask, GT_ENTER, "Exiting InitCodMgr status 0x%x\n ",
++               status);
++      return status;
++}
++
++/*
++ *  ======== DEV_InsertProcObject ========
++ *  Purpose:
++ *      Insert a ProcObject into the list maintained by DEV.
++ *  Parameters:
++ *      pProcObject:        Ptr to ProcObject to insert.
++ *      pDevObject:         Ptr to Dev Object where the list is.
++  *     pbAlreadyAttached:  Ptr to return the bool
++ *  Returns:
++ *      DSP_SOK:           If successful.
++ *  Requires:
++ *      List Exists
++ *      hDevObject is Valid handle
++ *      DEV Initialized
++ *      pbAlreadyAttached != NULL
++ *      hProcObject != 0
++ *  Ensures:
++ *      DSP_SOK and List is not Empty.
++ */
++DSP_STATUS DEV_InsertProcObject(struct DEV_OBJECT *hDevObject,
++                                   u32 hProcObject,
++                                   OUT bool *pbAlreadyAttached)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)hDevObject;
++
++      GT_2trace(debugMask, GT_ENTER,
++               "Entering DEV_InsetProcObject pProcObject 0x%x"
++               "pDevObject 0x%x\n", hProcObject, hDevObject);
++      DBC_Require(cRefs > 0);
++      DBC_Require(IsValidHandle(pDevObject));
++      DBC_Require(hProcObject != 0);
++      DBC_Require(pDevObject->procList != NULL);
++      DBC_Require(pbAlreadyAttached != NULL);
++      if (!LST_IsEmpty(pDevObject->procList))
++              *pbAlreadyAttached = true;
++
++      /* Add DevObject to tail. */
++      LST_PutTail(pDevObject->procList, (struct LST_ELEM *)hProcObject);
++
++      GT_1trace(debugMask, GT_ENTER,
++               "Exiting DEV_InsetProcObject status 0x%x\n", status);
++      DBC_Ensure(DSP_SUCCEEDED(status) && !LST_IsEmpty(pDevObject->procList));
++
++      return status;
++}
++
++/*
++ *  ======== DEV_RemoveProcObject ========
++ *  Purpose:
++ *      Search for and remove a Proc object from the given list maintained
++ *      by the DEV
++ *  Parameters:
++ *      pProcObject:        Ptr to ProcObject to insert.
++ *      pDevObject          Ptr to Dev Object where the list is.
++ *  Returns:
++ *      DSP_SOK:            If successful.
++ *  Requires:
++ *      List exists and is not empty
++ *      hProcObject != 0
++ *      hDevObject is a valid Dev handle.
++ *  Ensures:
++ *  Details:
++ *      List will be deleted when the DEV is destroyed.
++ */
++DSP_STATUS DEV_RemoveProcObject(struct DEV_OBJECT *hDevObject,
++                                   u32 hProcObject)
++{
++      DSP_STATUS status = DSP_EFAIL;
++      struct LST_ELEM *pCurElem;
++      struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)hDevObject;
++
++      DBC_Require(IsValidHandle(pDevObject));
++      DBC_Require(hProcObject != 0);
++      DBC_Require(pDevObject->procList != NULL);
++      DBC_Require(!LST_IsEmpty(pDevObject->procList));
++
++      GT_1trace(debugMask, GT_ENTER,
++               "Entering DEV_RemoveProcObject hDevObject "
++               "0x%x\n", hDevObject);
++      /* Search list for pDevObject: */
++      for (pCurElem = LST_First(pDevObject->procList); pCurElem != NULL;
++          pCurElem = LST_Next(pDevObject->procList, pCurElem)) {
++              /* If found, remove it. */
++              if ((u32)pCurElem == hProcObject) {
++                      LST_RemoveElem(pDevObject->procList, pCurElem);
++                      status = DSP_SOK;
++                      break;
++              }
++      }
++      GT_1trace(debugMask, GT_ENTER, "DEV_RemoveProcObject returning 0x%x\n",
++               status);
++      return status;
++}
++
++DSP_STATUS DEV_GetDevType(struct DEV_OBJECT *hdevObject, u32 *devType)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)hdevObject;
++
++      *devType = pDevObject->devType;
++
++      return status;
++}
++
++/*
++ *  ======== StoreInterfaceFxns ========
++ *  Purpose:
++ *      Copy the WMD's interface functions into the device object,
++ *      ensuring that FxnNotImplemented() is set for:
++ *
++ *      1. All WMD function pointers which are NULL; and
++ *      2. All function slots in the struct DEV_OBJECT structure which have no
++ *         corresponding slots in the the WMD's interface, because the WMD
++ *         is of an *older* version.
++ *  Parameters:
++ *      pIntfFxns:      Interface Fxn Structure of the WCD's Dev Object.
++ *      pDrvFxns:       Interface Fxns offered by the WMD during DEV_Create().
++ *  Returns:
++ *  Requires:
++ *      Input pointers are valid.
++ *      WMD is *not* written for a newer WCD.
++ *  Ensures:
++ *      All function pointers in the dev object's Fxn interface are not NULL.
++ */
++static void StoreInterfaceFxns(struct WMD_DRV_INTERFACE *pDrvFxns,
++                            OUT struct WMD_DRV_INTERFACE *pIntfFxns)
++{
++      u32 dwWMDVersion;
++
++      /* Local helper macro: */
++#define  StoreFxn(cast, pfn) \
++    (pIntfFxns->pfn = ((pDrvFxns->pfn != NULL) ? pDrvFxns->pfn : \
++    (cast)FxnNotImplemented))
++
++      DBC_Require(pIntfFxns != NULL);
++      DBC_Require(pDrvFxns != NULL);
++      DBC_Require(MAKEVERSION(pDrvFxns->dwWCDMajorVersion,
++                 pDrvFxns->dwWCDMinorVersion) <= WCDVERSION);
++      dwWMDVersion = MAKEVERSION(pDrvFxns->dwWCDMajorVersion,
++                                pDrvFxns->dwWCDMinorVersion);
++      pIntfFxns->dwWCDMajorVersion = pDrvFxns->dwWCDMajorVersion;
++      pIntfFxns->dwWCDMinorVersion = pDrvFxns->dwWCDMinorVersion;
++      /* Install functions up to WCD version .80 (first alpha): */
++      if (dwWMDVersion > 0) {
++              StoreFxn(WMD_DEV_CREATE, pfnDevCreate);
++              StoreFxn(WMD_DEV_DESTROY, pfnDevDestroy);
++              StoreFxn(WMD_DEV_CTRL, pfnDevCntrl);
++              StoreFxn(WMD_BRD_MONITOR, pfnBrdMonitor);
++              StoreFxn(WMD_BRD_START, pfnBrdStart);
++              StoreFxn(WMD_BRD_STOP, pfnBrdStop);
++              StoreFxn(WMD_BRD_STATUS, pfnBrdStatus);
++              StoreFxn(WMD_BRD_READ, pfnBrdRead);
++              StoreFxn(WMD_BRD_WRITE, pfnBrdWrite);
++              StoreFxn(WMD_BRD_SETSTATE, pfnBrdSetState);
++              StoreFxn(WMD_BRD_MEMCOPY, pfnBrdMemCopy);
++              StoreFxn(WMD_BRD_MEMWRITE, pfnBrdMemWrite);
++              StoreFxn(WMD_BRD_MEMMAP, pfnBrdMemMap);
++              StoreFxn(WMD_BRD_MEMUNMAP, pfnBrdMemUnMap);
++              StoreFxn(WMD_CHNL_CREATE, pfnChnlCreate);
++              StoreFxn(WMD_CHNL_DESTROY, pfnChnlDestroy);
++              StoreFxn(WMD_CHNL_OPEN, pfnChnlOpen);
++              StoreFxn(WMD_CHNL_CLOSE, pfnChnlClose);
++              StoreFxn(WMD_CHNL_ADDIOREQ, pfnChnlAddIOReq);
++              StoreFxn(WMD_CHNL_GETIOC, pfnChnlGetIOC);
++              StoreFxn(WMD_CHNL_CANCELIO, pfnChnlCancelIO);
++              StoreFxn(WMD_CHNL_FLUSHIO, pfnChnlFlushIO);
++              StoreFxn(WMD_CHNL_GETINFO, pfnChnlGetInfo);
++              StoreFxn(WMD_CHNL_GETMGRINFO, pfnChnlGetMgrInfo);
++              StoreFxn(WMD_CHNL_IDLE, pfnChnlIdle);
++              StoreFxn(WMD_CHNL_REGISTERNOTIFY, pfnChnlRegisterNotify);
++              StoreFxn(WMD_DEH_CREATE, pfnDehCreate);
++              StoreFxn(WMD_DEH_DESTROY, pfnDehDestroy);
++              StoreFxn(WMD_DEH_NOTIFY, pfnDehNotify);
++              StoreFxn(WMD_DEH_REGISTERNOTIFY, pfnDehRegisterNotify);
++              StoreFxn(WMD_DEH_GETINFO, pfnDehGetInfo);
++              StoreFxn(WMD_IO_CREATE, pfnIOCreate);
++              StoreFxn(WMD_IO_DESTROY, pfnIODestroy);
++              StoreFxn(WMD_IO_ONLOADED, pfnIOOnLoaded);
++              StoreFxn(WMD_IO_GETPROCLOAD, pfnIOGetProcLoad);
++              StoreFxn(WMD_MSG_CREATE, pfnMsgCreate);
++              StoreFxn(WMD_MSG_CREATEQUEUE, pfnMsgCreateQueue);
++              StoreFxn(WMD_MSG_DELETE, pfnMsgDelete);
++              StoreFxn(WMD_MSG_DELETEQUEUE, pfnMsgDeleteQueue);
++              StoreFxn(WMD_MSG_GET, pfnMsgGet);
++              StoreFxn(WMD_MSG_PUT, pfnMsgPut);
++              StoreFxn(WMD_MSG_REGISTERNOTIFY, pfnMsgRegisterNotify);
++              StoreFxn(WMD_MSG_SETQUEUEID, pfnMsgSetQueueId);
++      }
++      /* Add code for any additional functions in newer WMD versions here: */
++      /* Ensure postcondition: */
++      DBC_Ensure(pIntfFxns->pfnDevCreate != NULL);
++      DBC_Ensure(pIntfFxns->pfnDevDestroy != NULL);
++      DBC_Ensure(pIntfFxns->pfnDevCntrl != NULL);
++      DBC_Ensure(pIntfFxns->pfnBrdMonitor != NULL);
++      DBC_Ensure(pIntfFxns->pfnBrdStart != NULL);
++      DBC_Ensure(pIntfFxns->pfnBrdStop != NULL);
++      DBC_Ensure(pIntfFxns->pfnBrdStatus != NULL);
++      DBC_Ensure(pIntfFxns->pfnBrdRead != NULL);
++      DBC_Ensure(pIntfFxns->pfnBrdWrite != NULL);
++      DBC_Ensure(pIntfFxns->pfnChnlCreate != NULL);
++      DBC_Ensure(pIntfFxns->pfnChnlDestroy != NULL);
++      DBC_Ensure(pIntfFxns->pfnChnlOpen != NULL);
++      DBC_Ensure(pIntfFxns->pfnChnlClose != NULL);
++      DBC_Ensure(pIntfFxns->pfnChnlAddIOReq != NULL);
++      DBC_Ensure(pIntfFxns->pfnChnlGetIOC != NULL);
++      DBC_Ensure(pIntfFxns->pfnChnlCancelIO != NULL);
++      DBC_Ensure(pIntfFxns->pfnChnlFlushIO != NULL);
++      DBC_Ensure(pIntfFxns->pfnChnlGetInfo != NULL);
++      DBC_Ensure(pIntfFxns->pfnChnlGetMgrInfo != NULL);
++      DBC_Ensure(pIntfFxns->pfnChnlIdle != NULL);
++      DBC_Ensure(pIntfFxns->pfnChnlRegisterNotify != NULL);
++      DBC_Ensure(pIntfFxns->pfnDehCreate != NULL);
++      DBC_Ensure(pIntfFxns->pfnDehDestroy != NULL);
++      DBC_Ensure(pIntfFxns->pfnDehNotify != NULL);
++      DBC_Ensure(pIntfFxns->pfnDehRegisterNotify != NULL);
++      DBC_Ensure(pIntfFxns->pfnDehGetInfo != NULL);
++      DBC_Ensure(pIntfFxns->pfnIOCreate != NULL);
++      DBC_Ensure(pIntfFxns->pfnIODestroy != NULL);
++      DBC_Ensure(pIntfFxns->pfnIOOnLoaded != NULL);
++      DBC_Ensure(pIntfFxns->pfnIOGetProcLoad != NULL);
++      DBC_Ensure(pIntfFxns->pfnMsgSetQueueId != NULL);
++
++#undef  StoreFxn
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dmm.c b/drivers/dsp/bridge/pmgr/dmm.c
+new file mode 100644
+index 0000000..803de93
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dmm.c
+@@ -0,0 +1,692 @@
++/*
++ * dmm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== dmm.c ========
++ *  Purpose:
++ *      The Dynamic Memory Manager (DMM) module manages the DSP Virtual address
++ *      space that can be directly mapped to any MPU buffer or memory region
++ *
++ *  Public Functions:
++ *      DMM_CreateTables
++ *      DMM_Create
++ *      DMM_Destroy
++ *      DMM_Exit
++ *      DMM_Init
++ *      DMM_MapMemory
++ *      DMM_Reset
++ *      DMM_ReserveMemory
++ *      DMM_UnMapMemory
++ *      DMM_UnReserveMemory
++ *
++ *  Private Functions:
++ *      AddRegion
++ *      CreateRegion
++ *      GetRegion
++ *    GetFreeRegion
++ *    GetMappedRegion
++ *
++ *  Notes:
++ *      Region: Generic memory entitiy having a start address and a size
++ *      Chunk:  Reserved region
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 04-Jun-2008 Hari K : Optimized DMM implementation. Removed linked list
++ *!                                and instead used Table approach.
++ *! 19-Apr-2004 sb: Integrated Alan's code review updates.
++ *! 17-Mar-2004 ap: Fixed GetRegion for size=0 using tighter bound.
++ *! 20-Feb-2004 sb: Created.
++ *!
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/proc.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/dmm.h>
++
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++/* Object signatures */
++#define DMMSIGNATURE       0x004d4d44 /* "DMM"   (in reverse) */
++
++#define DMM_ADDR_VIRTUAL(a) \
++      (((struct MapPage *)(a) - pVirtualMappingTable) * PG_SIZE_4K +\
++      dynMemMapBeg)
++#define DMM_ADDR_TO_INDEX(a) (((a) - dynMemMapBeg) / PG_SIZE_4K)
++
++/* DMM Mgr */
++struct DMM_OBJECT {
++      u32 dwSignature;        /* Used for object validation */
++      /* Dmm Lock is used to serialize access mem manager for
++       * multi-threads. */
++      struct SYNC_CSOBJECT *hDmmLock; /* Lock to access dmm mgr */
++};
++
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask DMM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs;             /* module reference count */
++struct MapPage {
++      u32   RegionSize:15;
++      u32   MappedSize:15;
++      u32   bReserved:1;
++      u32   bMapped:1;
++};
++
++/*  Create the free list */
++static struct MapPage *pVirtualMappingTable;
++static u32  iFreeRegion;      /* The index of free region */
++static u32  iFreeSize;
++static u32  *pPhysicalAddrTable;      /* Physical address of MPU buffer */
++static u32  dynMemMapBeg;     /* The Beginning of dynamic memory mapping */
++static u32  TableSize;/* The size of virtual and physical pages tables */
++
++/*  ----------------------------------- Function Prototypes */
++static struct MapPage *GetRegion(u32 addr);
++static struct MapPage *GetFreeRegion(u32 aSize);
++static struct MapPage *GetMappedRegion(u32 aAddr);
++#ifdef DSP_DMM_DEBUG
++u32 DMM_MemMapDump(struct DMM_OBJECT *hDmmMgr);
++#endif
++
++/*  ======== DMM_CreateTables ========
++ *  Purpose:
++ *      Create table to hold the information of physical address
++ *      the buffer pages that is passed by the user, and the table
++ *      to hold the information of the virtual memory that is reserved
++ *      for DSP.
++ */
++DSP_STATUS DMM_CreateTables(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 size)
++{
++      struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++      DSP_STATUS status = DSP_SOK;
++
++      GT_3trace(DMM_debugMask, GT_ENTER,
++               "Entered DMM_CreateTables () hDmmMgr %x, addr"
++               " %x, size %x\n", hDmmMgr, addr, size);
++      status = DMM_DeleteTables(pDmmObj);
++      if (DSP_SUCCEEDED(status)) {
++              SYNC_EnterCS(pDmmObj->hDmmLock);
++              dynMemMapBeg = addr;
++              TableSize = (size/PG_SIZE_4K) + 1;
++              /*  Create the free list */
++              pVirtualMappingTable = (struct MapPage *) MEM_Calloc
++              (TableSize*sizeof(struct MapPage), MEM_NONPAGED);
++              if (pVirtualMappingTable == NULL)
++                      status = DSP_EMEMORY;
++              else {
++                      /* This table will be used
++                      * to store the virtual to physical
++                      * address translations
++                      */
++                      pPhysicalAddrTable = (u32 *)MEM_Calloc
++                              (TableSize*sizeof(u32), MEM_NONPAGED);
++                      GT_1trace(DMM_debugMask, GT_4CLASS,
++                      "DMM_CreateTables: Allocate"
++                      "memory for pPhysicalAddrTable=%d entries\n",
++                      TableSize);
++                      if (pPhysicalAddrTable == NULL) {
++                              status = DSP_EMEMORY;
++                              GT_0trace(DMM_debugMask, GT_7CLASS,
++                                  "DMM_CreateTables: Memory allocation for "
++                                  "pPhysicalAddrTable failed\n");
++                      } else {
++                      /* On successful allocation,
++                      * all entries are zero ('free') */
++                      iFreeRegion = 0;
++                      iFreeSize = TableSize*PG_SIZE_4K;
++                      pVirtualMappingTable[0].RegionSize = TableSize;
++                      }
++              }
++              SYNC_LeaveCS(pDmmObj->hDmmLock);
++      } else
++              GT_0trace(DMM_debugMask, GT_7CLASS,
++                       "DMM_CreateTables: DMM_DeleteTables"
++                       "Failure\n");
++
++      GT_1trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_CreateTables status"
++                                                      "0x%x\n", status);
++      return status;
++}
++
++/*
++ *  ======== DMM_Create ========
++ *  Purpose:
++ *      Create a dynamic memory manager object.
++ */
++DSP_STATUS DMM_Create(OUT struct DMM_OBJECT **phDmmMgr,
++                   struct DEV_OBJECT *hDevObject,
++                   IN CONST struct DMM_MGRATTRS *pMgrAttrs)
++{
++      struct DMM_OBJECT *pDmmObject = NULL;
++      DSP_STATUS status = DSP_SOK;
++      DBC_Require(cRefs > 0);
++      DBC_Require(phDmmMgr != NULL);
++
++      GT_3trace(DMM_debugMask, GT_ENTER,
++               "DMM_Create: phDmmMgr: 0x%x hDevObject: "
++               "0x%x pMgrAttrs: 0x%x\n", phDmmMgr, hDevObject, pMgrAttrs);
++      *phDmmMgr = NULL;
++      /* create, zero, and tag a cmm mgr object */
++      MEM_AllocObject(pDmmObject, struct DMM_OBJECT, DMMSIGNATURE);
++      if (pDmmObject != NULL) {
++              status = SYNC_InitializeCS(&pDmmObject->hDmmLock);
++              if (DSP_SUCCEEDED(status))
++                      *phDmmMgr = pDmmObject;
++              else
++                      DMM_Destroy(pDmmObject);
++      } else {
++              GT_0trace(DMM_debugMask, GT_7CLASS,
++                       "DMM_Create: Object Allocation "
++                       "Failure(DMM Object)\n");
++              status = DSP_EMEMORY;
++      }
++      GT_2trace(DMM_debugMask, GT_4CLASS,
++                      "Leaving DMM_Create status %x pDmmObject %x\n",
++                      status, pDmmObject);
++
++      return status;
++}
++
++/*
++ *  ======== DMM_Destroy ========
++ *  Purpose:
++ *      Release the communication memory manager resources.
++ */
++DSP_STATUS DMM_Destroy(struct DMM_OBJECT *hDmmMgr)
++{
++      struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++      DSP_STATUS status = DSP_SOK;
++
++      GT_1trace(DMM_debugMask, GT_ENTER,
++              "Entered DMM_Destroy () hDmmMgr %x\n", hDmmMgr);
++      DBC_Require(cRefs > 0);
++      if (MEM_IsValidHandle(hDmmMgr, DMMSIGNATURE)) {
++              status = DMM_DeleteTables(pDmmObj);
++              if (DSP_SUCCEEDED(status)) {
++                      /* Delete CS & dmm mgr object */
++                      SYNC_DeleteCS(pDmmObj->hDmmLock);
++                      MEM_FreeObject(pDmmObj);
++              } else
++                      GT_0trace(DMM_debugMask, GT_7CLASS,
++                       "DMM_Destroy: DMM_DeleteTables "
++                       "Failure\n");
++      } else
++              status = DSP_EHANDLE;
++      GT_1trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_Destroy status %x\n",
++                                                              status);
++      return status;
++}
++
++
++/*
++ *  ======== DMM_DeleteTables ========
++ *  Purpose:
++ *      Delete DMM Tables.
++ */
++DSP_STATUS DMM_DeleteTables(struct DMM_OBJECT *hDmmMgr)
++{
++      struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++      DSP_STATUS status = DSP_SOK;
++
++      GT_1trace(DMM_debugMask, GT_ENTER,
++              "Entered DMM_DeleteTables () hDmmMgr %x\n", hDmmMgr);
++      DBC_Require(cRefs > 0);
++      if (MEM_IsValidHandle(hDmmMgr, DMMSIGNATURE)) {
++              /* Delete all DMM tables */
++              SYNC_EnterCS(pDmmObj->hDmmLock);
++
++              if (pVirtualMappingTable != NULL)
++                      MEM_Free(pVirtualMappingTable);
++
++              if (pPhysicalAddrTable != NULL)
++                      MEM_Free(pPhysicalAddrTable);
++
++              SYNC_LeaveCS(pDmmObj->hDmmLock);
++      } else
++              status = DSP_EHANDLE;
++      GT_1trace(DMM_debugMask, GT_4CLASS,
++              "Leaving DMM_DeleteTables status %x\n", status);
++      return status;
++}
++
++
++
++
++/*
++ *  ======== DMM_Exit ========
++ *  Purpose:
++ *      Discontinue usage of module; free resources when reference count
++ *      reaches 0.
++ */
++void DMM_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      cRefs--;
++
++      GT_1trace(DMM_debugMask, GT_ENTER,
++               "exiting DMM_Exit, ref count:0x%x\n", cRefs);
++}
++
++/*
++ *  ======== DMM_GetHandle ========
++ *  Purpose:
++ *      Return the dynamic memory manager object for this device.
++ *      This is typically called from the client process.
++ */
++DSP_STATUS DMM_GetHandle(DSP_HPROCESSOR hProcessor,
++                      OUT struct DMM_OBJECT **phDmmMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *hDevObject;
++
++      GT_2trace(DMM_debugMask, GT_ENTER,
++               "DMM_GetHandle: hProcessor %x, phDmmMgr"
++               "%x\n", hProcessor, phDmmMgr);
++      DBC_Require(cRefs > 0);
++      DBC_Require(phDmmMgr != NULL);
++      if (hProcessor != NULL)
++              status = PROC_GetDevObject(hProcessor, &hDevObject);
++      else
++              hDevObject = DEV_GetFirst();    /* default */
++
++      if (DSP_SUCCEEDED(status))
++              status = DEV_GetDmmMgr(hDevObject, phDmmMgr);
++
++      GT_2trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_GetHandle status %x, "
++               "*phDmmMgr %x\n", status, phDmmMgr ? *phDmmMgr : NULL);
++      return status;
++}
++
++/*
++ *  ======== DMM_Init ========
++ *  Purpose:
++ *      Initializes private state of DMM module.
++ */
++bool DMM_Init(void)
++{
++      bool fRetval = true;
++
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++              /* Set the Trace mask */
++              /*"DM" for Dymanic Memory Manager */
++              GT_create(&DMM_debugMask, "DM");
++      }
++
++      if (fRetval)
++              cRefs++;
++
++      GT_1trace(DMM_debugMask, GT_ENTER,
++               "Entered DMM_Init, ref count:0x%x\n", cRefs);
++
++      DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++      pVirtualMappingTable = NULL ;
++      pPhysicalAddrTable = NULL ;
++      TableSize = 0;
++
++      return fRetval;
++}
++
++/*
++ *  ======== DMM_MapMemory ========
++ *  Purpose:
++ *      Add a mapping block to the reserved chunk. DMM assumes that this block
++ *  will be mapped in the DSP/IVA's address space. DMM returns an error if a
++ *  mapping overlaps another one. This function stores the info that will be
++ *  required later while unmapping the block.
++ */
++DSP_STATUS DMM_MapMemory(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 size)
++{
++      struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++      struct MapPage *chunk;
++      DSP_STATUS status = DSP_SOK;
++
++      GT_3trace(DMM_debugMask, GT_ENTER,
++               "Entered DMM_MapMemory () hDmmMgr %x, "
++               "addr %x, size %x\n", hDmmMgr, addr, size);
++      SYNC_EnterCS(pDmmObj->hDmmLock);
++      /* Find the Reserved memory chunk containing the DSP block to
++       * be mapped */
++      chunk = (struct MapPage *)GetRegion(addr);
++      if (chunk != NULL) {
++              /* Mark the region 'mapped', leave the 'reserved' info as-is */
++              chunk->bMapped = true;
++              chunk->MappedSize = (size/PG_SIZE_4K);
++      } else
++              status = DSP_ENOTFOUND;
++      SYNC_LeaveCS(pDmmObj->hDmmLock);
++      GT_2trace(DMM_debugMask, GT_4CLASS,
++               "Leaving DMM_MapMemory status %x, chunk %x\n",
++              status, chunk);
++      return status;
++}
++
++/*
++ *  ======== DMM_ReserveMemory ========
++ *  Purpose:
++ *      Reserve a chunk of virtually contiguous DSP/IVA address space.
++ */
++DSP_STATUS DMM_ReserveMemory(struct DMM_OBJECT *hDmmMgr, u32 size,
++                                                      u32 *pRsvAddr)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++      struct MapPage *node;
++      u32 rsvAddr = 0;
++      u32 rsvSize = 0;
++
++      GT_3trace(DMM_debugMask, GT_ENTER,
++               "Entered DMM_ReserveMemory () hDmmMgr %x, "
++               "size %x, pRsvAddr %x\n", hDmmMgr, size, pRsvAddr);
++      SYNC_EnterCS(pDmmObj->hDmmLock);
++
++      /* Try to get a DSP chunk from the free list */
++      node = GetFreeRegion(size);
++      if (node != NULL) {
++              /*  DSP chunk of given size is available. */
++              rsvAddr = DMM_ADDR_VIRTUAL(node);
++              /* Calculate the number entries to use */
++              rsvSize = size/PG_SIZE_4K;
++              if (rsvSize < node->RegionSize) {
++                      /* Mark remainder of free region */
++                      node[rsvSize].bMapped = false;
++                      node[rsvSize].bReserved = false;
++                      node[rsvSize].RegionSize = node->RegionSize - rsvSize;
++                      node[rsvSize].MappedSize = 0;
++              }
++              /*  GetRegion will return first fit chunk. But we only use what
++                      is requested. */
++              node->bMapped = false;
++              node->bReserved = true;
++              node->RegionSize = rsvSize;
++              node->MappedSize = 0;
++              /* Return the chunk's starting address */
++              *pRsvAddr = rsvAddr;
++      } else
++              /*dSP chunk of given size is not available */
++              status = DSP_EMEMORY;
++
++      SYNC_LeaveCS(pDmmObj->hDmmLock);
++      GT_3trace(DMM_debugMask, GT_4CLASS,
++               "Leaving ReserveMemory status %x, rsvAddr"
++               " %x, rsvSize %x\n", status, rsvAddr, rsvSize);
++      return status;
++}
++
++
++/*
++ *  ======== DMM_UnMapMemory ========
++ *  Purpose:
++ *      Remove the mapped block from the reserved chunk.
++ */
++DSP_STATUS DMM_UnMapMemory(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 *pSize)
++{
++      struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++      struct MapPage *chunk;
++      DSP_STATUS status = DSP_SOK;
++
++      GT_3trace(DMM_debugMask, GT_ENTER,
++               "Entered DMM_UnMapMemory () hDmmMgr %x, "
++               "addr %x, pSize %x\n", hDmmMgr, addr, pSize);
++      SYNC_EnterCS(pDmmObj->hDmmLock);
++      chunk = GetMappedRegion(addr) ;
++      if (chunk == NULL)
++              status = DSP_ENOTFOUND ;
++
++      if (DSP_SUCCEEDED(status)) {
++              /* Unmap the region */
++              *pSize = chunk->MappedSize * PG_SIZE_4K;
++              chunk->bMapped = false;
++              chunk->MappedSize = 0;
++      }
++      SYNC_LeaveCS(pDmmObj->hDmmLock);
++      GT_3trace(DMM_debugMask, GT_ENTER,
++               "Leaving DMM_UnMapMemory status %x, chunk"
++               " %x,  *pSize %x\n", status, chunk, *pSize);
++
++      return status;
++}
++
++/*
++ *  ======== DMM_UnReserveMemory ========
++ *  Purpose:
++ *      Free a chunk of reserved DSP/IVA address space.
++ */
++DSP_STATUS DMM_UnReserveMemory(struct DMM_OBJECT *hDmmMgr, u32 rsvAddr)
++{
++      struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++      struct MapPage *chunk;
++      u32 i;
++      DSP_STATUS status = DSP_SOK;
++      u32 chunkSize;
++
++      GT_2trace(DMM_debugMask, GT_ENTER,
++               "Entered DMM_UnReserveMemory () hDmmMgr "
++               "%x, rsvAddr %x\n", hDmmMgr, rsvAddr);
++
++      SYNC_EnterCS(pDmmObj->hDmmLock);
++
++      /* Find the chunk containing the reserved address */
++      chunk = GetMappedRegion(rsvAddr);
++      if (chunk == NULL)
++              status = DSP_ENOTFOUND;
++
++      if (DSP_SUCCEEDED(status)) {
++              /* Free all the mapped pages for this reserved region */
++              i = 0;
++              while (i < chunk->RegionSize) {
++                      if (chunk[i].bMapped) {
++                              /* Remove mapping from the page tables. */
++                              chunkSize = chunk[i].MappedSize;
++                              /* Clear the mapping flags */
++                              chunk[i].bMapped = false;
++                              chunk[i].MappedSize = 0;
++                              i += chunkSize;
++                      } else
++                              i++;
++              }
++              /* Clear the flags (mark the region 'free') */
++              chunk->bReserved = false;
++              /* NOTE: We do NOT coalesce free regions here.
++               * Free regions are coalesced in GetRegion(), as it traverses
++               *the whole mapping table
++               */
++      }
++      SYNC_LeaveCS(pDmmObj->hDmmLock);
++      GT_2trace(DMM_debugMask, GT_ENTER,
++               "Leaving DMM_UnReserveMemory status %x"
++               " chunk %x\n", status, chunk);
++      return status;
++}
++
++
++/*
++ *  ======== GetRegion ========
++ *  Purpose:
++ *      Returns a region containing the specified memory region
++ */
++static struct MapPage *GetRegion(u32 aAddr)
++{
++      struct MapPage *currRegion = NULL;
++      u32   i = 0;
++
++      GT_1trace(DMM_debugMask, GT_ENTER, "Entered GetRegion () "
++              " aAddr %x\n", aAddr);
++
++      if (pVirtualMappingTable != NULL) {
++              /* find page mapped by this address */
++              i = DMM_ADDR_TO_INDEX(aAddr);
++              if (i < TableSize)
++                      currRegion = pVirtualMappingTable + i;
++      }
++      GT_3trace(DMM_debugMask, GT_4CLASS,
++             "Leaving GetRegion currRegion %x, iFreeRegion %d\n,"
++             "iFreeSize %d\n", currRegion, iFreeRegion, iFreeSize) ;
++      return currRegion;
++}
++
++/*
++ *  ======== GetFreeRegion ========
++ *  Purpose:
++ *  Returns the requested free region
++ */
++static struct MapPage *GetFreeRegion(u32 aSize)
++{
++      struct MapPage *currRegion = NULL;
++      u32   i = 0;
++      u32   RegionSize = 0;
++      u32   nextI = 0;
++      GT_1trace(DMM_debugMask, GT_ENTER, "Entered GetFreeRegion () "
++              "aSize 0x%x\n", aSize);
++
++      if (pVirtualMappingTable == NULL)
++              return currRegion;
++      if (aSize > iFreeSize) {
++              /* Find the largest free region
++              * (coalesce during the traversal) */
++              while (i < TableSize) {
++                      RegionSize = pVirtualMappingTable[i].RegionSize;
++                      nextI = i+RegionSize;
++                      if (pVirtualMappingTable[i].bReserved == false) {
++                              /* Coalesce, if possible */
++                              if (nextI < TableSize &&
++                              pVirtualMappingTable[nextI].bReserved
++                                                      == false) {
++                                      pVirtualMappingTable[i].RegionSize +=
++                                      pVirtualMappingTable[nextI].RegionSize;
++                                      continue;
++                              }
++                              RegionSize *= PG_SIZE_4K;
++                              if (RegionSize > iFreeSize)     {
++                                      iFreeRegion = i;
++                                      iFreeSize = RegionSize;
++                              }
++                      }
++                      i = nextI;
++              }
++      }
++      if (aSize <= iFreeSize) {
++              currRegion = pVirtualMappingTable + iFreeRegion;
++              iFreeRegion += (aSize / PG_SIZE_4K);
++              iFreeSize -= aSize;
++      }
++      return currRegion;
++}
++
++/*
++ *  ======== GetMappedRegion ========
++ *  Purpose:
++ *  Returns the requestedmapped region
++ */
++static struct MapPage *GetMappedRegion(u32 aAddr)
++{
++      u32   i = 0;
++      struct MapPage *currRegion = NULL;
++      GT_1trace(DMM_debugMask, GT_ENTER, "Entered GetMappedRegion () "
++                                              "aAddr 0x%x\n", aAddr);
++
++      if (pVirtualMappingTable == NULL)
++              return currRegion;
++
++      i = DMM_ADDR_TO_INDEX(aAddr);
++      if (i < TableSize && (pVirtualMappingTable[i].bMapped ||
++                      pVirtualMappingTable[i].bReserved))
++              currRegion = pVirtualMappingTable + i;
++      return currRegion;
++}
++
++/*
++ *  ======== DMM_GetPhysicalAddrTable ========
++ *  Purpose:
++ *  Returns the physical table address
++ */
++u32 *DMM_GetPhysicalAddrTable(void)
++{
++      GT_1trace(DMM_debugMask, GT_ENTER, "Entered "
++                      "DMM_GetPhysicalAddrTable()- pPhysicalAddrTable 0x%x\n",
++                      pPhysicalAddrTable);
++      return pPhysicalAddrTable;
++}
++
++#ifdef DSP_DMM_DEBUG
++u32 DMM_MemMapDump(struct DMM_OBJECT *hDmmMgr)
++{
++      struct MapPage *curNode = NULL;
++      u32 i;
++      u32 freemem = 0;
++      u32 bigsize = 0;
++
++      SYNC_EnterCS(hDmmMgr->hDmmLock);
++
++      if (pVirtualMappingTable != NULL) {
++              for (i = 0; i < TableSize; i +=
++                              pVirtualMappingTable[i].RegionSize) {
++                      curNode = pVirtualMappingTable + i;
++                      if (curNode->bReserved == TRUE) {
++                              /*printk("RESERVED size = 0x%x, "
++                                      "Map size = 0x%x\n",
++                                      (curNode->RegionSize * PG_SIZE_4K),
++                                      (curNode->bMapped == false) ? 0 :
++                                      (curNode->MappedSize * PG_SIZE_4K));
++*/
++                      } else {
++/*                            printk("UNRESERVED size = 0x%x\n",
++                                      (curNode->RegionSize * PG_SIZE_4K));
++*/
++                              freemem += (curNode->RegionSize * PG_SIZE_4K);
++                              if (curNode->RegionSize > bigsize)
++                                      bigsize = curNode->RegionSize;
++                      }
++              }
++      }
++      printk(KERN_INFO "Total DSP VA FREE memory = %d Mbytes\n",
++                      freemem/(1024*1024));
++      printk(KERN_INFO "Total DSP VA USED memory= %d Mbytes \n",
++                      (((TableSize * PG_SIZE_4K)-freemem))/(1024*1024));
++      printk(KERN_INFO "DSP VA - Biggest FREE block = %d Mbytes \n\n",
++                      (bigsize*PG_SIZE_4K/(1024*1024)));
++      SYNC_LeaveCS(hDmmMgr->hDmmLock);
++
++      return 0;
++}
++#endif
+diff --git a/drivers/dsp/bridge/pmgr/io.c b/drivers/dsp/bridge/pmgr/io.c
+new file mode 100644
+index 0000000..cdfe0dc
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/io.c
+@@ -0,0 +1,205 @@
++/*
++ * io.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== io.c ========
++ *  Description:
++ *      IO manager interface: Manages IO between CHNL and MSG.
++ *
++ *  Public Functions:
++ *      IO_Create
++ *      IO_Destroy
++ *      IO_Exit
++ *      IO_Init
++ *      IO_OnLoaded
++ *
++ *  Notes:
++ *      This interface is basically a pass through to the WMD IO functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa   PMGR Code review comments incorporated.
++ *! 04-Apr-2001 rr      WSX_STATUS initialized in IO_Create.
++ *! 07-Nov-2000 jeh     Created.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/mem.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/*  ----------------------------------- This */
++#include <ioobj.h>
++#include <dspbridge/iodefs.h>
++#include <dspbridge/io.h>
++
++/*  ----------------------------------- Globals */
++static u32 cRefs;
++
++#if GT_TRACE
++static struct GT_Mask IO_DebugMask = { NULL, NULL };  /* WCD IO Mask */
++#endif
++
++/*
++ *  ======== IO_Create ========
++ *  Purpose:
++ *      Create an IO manager object, responsible for managing IO between
++ *      CHNL and MSG
++ */
++DSP_STATUS IO_Create(OUT struct IO_MGR **phIOMgr, struct DEV_OBJECT *hDevObject,
++                  IN CONST struct IO_ATTRS *pMgrAttrs)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      struct IO_MGR *hIOMgr = NULL;
++      struct IO_MGR_ *pIOMgr = NULL;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phIOMgr != NULL);
++      DBC_Require(pMgrAttrs != NULL);
++
++      GT_3trace(IO_DebugMask, GT_ENTER, "Entered IO_Create: phIOMgr: 0x%x\t "
++               "hDevObject: 0x%x\tpMgrAttrs: 0x%x\n",
++               phIOMgr, hDevObject, pMgrAttrs);
++
++      *phIOMgr = NULL;
++
++      /* A memory base of 0 implies no memory base:  */
++      if ((pMgrAttrs->dwSMBase != 0) && (pMgrAttrs->uSMLength == 0)) {
++              status = CHNL_E_INVALIDMEMBASE;
++              GT_0trace(IO_DebugMask, GT_7CLASS,
++                       "IO_Create:Invalid Mem Base\n");
++      }
++
++      if (pMgrAttrs->uWordSize == 0) {
++              status = CHNL_E_INVALIDWORDSIZE;
++              GT_0trace(IO_DebugMask, GT_7CLASS,
++                       "IO_Create:Invalid Word size\n");
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++
++              /* Let WMD channel module finish the create: */
++              status = (*pIntfFxns->pfnIOCreate)(&hIOMgr, hDevObject,
++                       pMgrAttrs);
++
++              if (DSP_SUCCEEDED(status)) {
++                      pIOMgr = (struct IO_MGR_ *) hIOMgr;
++                      pIOMgr->pIntfFxns = pIntfFxns;
++                      pIOMgr->hDevObject = hDevObject;
++
++                      /* Return the new channel manager handle: */
++                      *phIOMgr = hIOMgr;
++                      GT_1trace(IO_DebugMask, GT_1CLASS,
++                               "IO_Create: Success hIOMgr: 0x%x\n",
++                               hIOMgr);
++              }
++      }
++
++      GT_2trace(IO_DebugMask, GT_ENTER,
++               "Exiting IO_Create: hIOMgr: 0x%x, status:"
++               " 0x%x\n", hIOMgr, status);
++
++      return status;
++}
++
++/*
++ *  ======== IO_Destroy ========
++ *  Purpose:
++ *      Delete IO manager.
++ */
++DSP_STATUS IO_Destroy(struct IO_MGR *hIOMgr)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      struct IO_MGR_ *pIOMgr = (struct IO_MGR_ *)hIOMgr;
++      DSP_STATUS status;
++
++      DBC_Require(cRefs > 0);
++
++      GT_1trace(IO_DebugMask, GT_ENTER, "Entered IO_Destroy: hIOMgr: 0x%x\n",
++                hIOMgr);
++
++      pIntfFxns = pIOMgr->pIntfFxns;
++
++      /* Let WMD channel module destroy the IO_MGR: */
++      status = (*pIntfFxns->pfnIODestroy) (hIOMgr);
++
++      GT_2trace(IO_DebugMask, GT_ENTER,
++               "Exiting IO_Destroy: pIOMgr: 0x%x, status:"
++               " 0x%x\n", pIOMgr, status);
++      return status;
++}
++
++/*
++ *  ======== IO_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the IO module.
++ */
++void IO_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      cRefs--;
++
++      GT_1trace(IO_DebugMask, GT_5CLASS,
++               "Entered IO_Exit, ref count: 0x%x\n", cRefs);
++
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== IO_Init ========
++ *  Purpose:
++ *      Initialize the IO module's private state.
++ */
++bool IO_Init(void)
++{
++      bool fRetval = true;
++
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++              DBC_Assert(!IO_DebugMask.flags);
++              GT_create(&IO_DebugMask, "IO"); /* "IO" for IO */
++      }
++
++      if (fRetval)
++              cRefs++;
++
++
++      GT_1trace(IO_DebugMask, GT_5CLASS,
++               "Entered IO_Init, ref count: 0x%x\n", cRefs);
++
++      DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++      return fRetval;
++}
+diff --git a/drivers/dsp/bridge/pmgr/ioobj.h b/drivers/dsp/bridge/pmgr/ioobj.h
+new file mode 100644
+index 0000000..f473a63
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/ioobj.h
+@@ -0,0 +1,52 @@
++/*
++ * ioobj.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== ioobj.h ========
++ *  Description:
++ *      Structure subcomponents of channel class library IO objects which
++ *      are exposed to class driver from mini-driver.
++ *
++ *  Public Functions:
++ *      None.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 01/16/97 gp: Created from chnlpriv.h
++ */
++
++#ifndef IOOBJ_
++#define IOOBJ_
++
++#include <dspbridge/devdefs.h>
++#include <dspbridge/wmd.h>
++
++/*
++ *  This struct is the first field in a IO_MGR struct, as implemented in
++ *  a WMD channel class library.  Other, implementation specific fields
++ *  follow this structure in memory.
++ */
++struct IO_MGR_ {
++      /* These must be the first fields in a IO_MGR struct: */
++      u32 dwSignature;        /* Used for object validation.   */
++      struct WMD_DEV_CONTEXT *hWmdContext;    /* WMD device context.  */
++      struct WMD_DRV_INTERFACE *pIntfFxns;    /* Function interface to WMD. */
++      struct DEV_OBJECT *hDevObject;  /* Device this board represents. */
++} ;
++
++#endif                                /* IOOBJ_ */
+diff --git a/drivers/dsp/bridge/pmgr/msg.c b/drivers/dsp/bridge/pmgr/msg.c
+new file mode 100644
+index 0000000..bbf5174
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/msg.c
+@@ -0,0 +1,173 @@
++/*
++ * msg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== msg.c ========
++ *  Description:
++ *      DSP/BIOS Bridge MSG Module.
++ *
++ *  Public Functions:
++ *      MSG_Create
++ *      MSG_Delete
++ *      MSG_Exit
++ *      MSG_Init
++ *
++ *! Revision History:
++ *! =================
++ *! 24-Feb-2003 swa   PMGR Code review comments incorporated.
++ *! 15-May-2001 ag      Changed SUCCEEDED to DSP_SUCCEEDED.
++ *! 16-Feb-2001 jeh     Fixed some comments.
++ *! 15-Dec-2000 rr      MSG_Create returns DSP_EFAIL if pfnMsgCreate fails.
++ *! 12-Sep-2000 jeh     Created.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++
++/*  ----------------------------------- Mini Driver */
++#include <dspbridge/wmd.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/*  ----------------------------------- This */
++#include <msgobj.h>
++#include <dspbridge/msg.h>
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask MSG_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++static u32 cRefs;             /* module reference count */
++
++/*
++ *  ======== MSG_Create ========
++ *  Purpose:
++ *      Create an object to manage message queues. Only one of these objects
++ *      can exist per device object.
++ */
++DSP_STATUS MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++                    struct DEV_OBJECT *hDevObject, MSG_ONEXIT msgCallback)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      struct MSG_MGR_ *pMsgMgr;
++      struct MSG_MGR *hMsgMgr;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phMsgMgr != NULL);
++      DBC_Require(msgCallback != NULL);
++      DBC_Require(hDevObject != NULL);
++
++      GT_3trace(MSG_debugMask, GT_ENTER, "MSG_Create: phMsgMgr: 0x%x\t"
++               "hDevObject: 0x%x\tmsgCallback: 0x%x\n",
++               phMsgMgr, hDevObject, msgCallback);
++
++      *phMsgMgr = NULL;
++
++      DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++
++      /* Let WMD message module finish the create: */
++      status = (*pIntfFxns->pfnMsgCreate)(&hMsgMgr, hDevObject, msgCallback);
++
++      if (DSP_SUCCEEDED(status)) {
++              /* Fill in WCD message module's fields of the MSG_MGR
++               * structure */
++              pMsgMgr = (struct MSG_MGR_ *)hMsgMgr;
++              pMsgMgr->pIntfFxns = pIntfFxns;
++
++              /* Finally, return the new message manager handle: */
++              *phMsgMgr = hMsgMgr;
++              GT_1trace(MSG_debugMask, GT_1CLASS,
++                       "MSG_Create: Success pMsgMgr: 0x%x\n", pMsgMgr);
++      } else {
++              status = DSP_EFAIL;
++      }
++      return status;
++}
++
++/*
++ *  ======== MSG_Delete ========
++ *  Purpose:
++ *      Delete a MSG manager allocated in MSG_Create().
++ */
++void MSG_Delete(struct MSG_MGR *hMsgMgr)
++{
++      struct MSG_MGR_ *pMsgMgr = (struct MSG_MGR_ *)hMsgMgr;
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
++
++      GT_1trace(MSG_debugMask, GT_ENTER, "MSG_Delete: hMsgMgr: 0x%x\n",
++               hMsgMgr);
++
++      pIntfFxns = pMsgMgr->pIntfFxns;
++
++      /* Let WMD message module destroy the MSG_MGR: */
++      (*pIntfFxns->pfnMsgDelete)(hMsgMgr);
++
++      DBC_Ensure(!MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
++}
++
++/*
++ *  ======== MSG_Exit ========
++ */
++void MSG_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++      cRefs--;
++      GT_1trace(MSG_debugMask, GT_5CLASS,
++               "Entered MSG_Exit, ref count: 0x%x\n", cRefs);
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== MSG_Init ========
++ */
++bool MSG_Init(void)
++{
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++              DBC_Assert(!MSG_debugMask.flags);
++              GT_create(&MSG_debugMask, "MG");        /* "MG" for MsG */
++      }
++
++      cRefs++;
++
++      GT_1trace(MSG_debugMask, GT_5CLASS, "MSG_Init(), ref count:  0x%x\n",
++               cRefs);
++
++      DBC_Ensure(cRefs >= 0);
++
++      return true;
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/msgobj.h b/drivers/dsp/bridge/pmgr/msgobj.h
+new file mode 100644
+index 0000000..63d025b
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/msgobj.h
+@@ -0,0 +1,52 @@
++/*
++ * msgobj.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== msgobj.h ========
++ *  Description:
++ *      Structure subcomponents of channel class library MSG objects which
++ *      are exposed to class driver from mini-driver.
++ *
++ *  Public Functions:
++ *      None.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa   PMGR Code review comments incorporated.
++ *! 17-Nov-2000 jeh     Created.
++ */
++
++#ifndef MSGOBJ_
++#define MSGOBJ_
++
++#include <dspbridge/wmd.h>
++
++#include <dspbridge/msgdefs.h>
++
++/*
++ *  This struct is the first field in a MSG_MGR struct, as implemented in
++ *  a WMD channel class library.  Other, implementation specific fields
++ *  follow this structure in memory.
++ */
++struct MSG_MGR_ {
++      /* The first two fields must match those in msgobj.h */
++      u32 dwSignature;
++      struct WMD_DRV_INTERFACE *pIntfFxns;    /* Function interface to WMD. */
++};
++
++#endif                                /* MSGOBJ_ */
++
+diff --git a/drivers/dsp/bridge/pmgr/wcd.c b/drivers/dsp/bridge/pmgr/wcd.c
+new file mode 100644
+index 0000000..859043d
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/wcd.c
+@@ -0,0 +1,1647 @@
++/*
++ * wcd.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== wcd.c ========
++ *  Description:
++ *      Common WCD functions, also includes the wrapper
++ *      functions called directly by the DeviceIOControl interface.
++ *
++ *  Public Functions:
++ *      WCD_CallDevIOCtl
++ *      WCD_Init
++ *      WCD_InitComplete2
++ *      WCD_Exit
++ *      <MOD>WRAP_*
++ *
++ *! Revision History:
++ *! ================
++ *! 29-Apr-2004 hp  Call PROC_AutoStart only for DSP device
++ *! 19-Apr-2004 sb  Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb  Added the Dynamic Memory Mapping APIs
++ *! 03-Apr-2003 sb  Process environment pointer in PROCWRAP_Load
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 30-Jan-2002 ag  CMMWRAP_AllocBuf name changed to CMMWRAP_CallocBuf
++ *! 15-Jan-2002 ag  Added actual bufSize param to STRMWRAP_Reclaim[issue].
++ *! 14-Dec-2001 rr  ARGS_NODE_CONNECT maps the pAttr.
++ *! 03-Oct-2001 rr  ARGS_NODE_ALLOCMSGBUF/FREEMSGBUF maps the pAttr.
++ *! 10-Sep-2001 ag  Added CMD_CMM_GETHANDLE.
++ *! 23-Apr-2001 jeh Pass pStatus to NODE_Terminate.
++ *! 11-Apr-2001 jeh STRMWRAP_Reclaim embedded pointer is mapped and unmapped.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 06-Dec-2000 jeh WRAP_MAP2CALLER pointers in RegisterNotify calls.
++ *! 05-Dec-2000 ag: Removed MAP2CALLER in NODEWRAP_FreeMsgBuf().
++ *! 22-Nov-2000 kc: Added MGRWRAP_GetPerf_Data().
++ *! 20-Nov-2000 jeh Added MSG_Init()/MSG_Exit(), IO_Init()/IO_Exit().
++ *!            WRAP pointers to handles for PROC_Attach, NODE_Allocate.
++ *! 27-Oct-2000 jeh Added NODEWRAP_AllocMsgBuf, NODEWRAP_FreeMsgBuf. Removed
++ *!            NODEWRAP_GetMessageStream.
++ *! 12-Oct-2000 ag: Added user CMM wrappers.
++ *! 05-Oct-2000 rr: WcdInitComplete2 will fail even if one BRD or PROC
++ *!            AutoStart fails.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 13-Sep-2000 jeh Pass ARGS_NODE_CONNECT.pAttrs to NODE_Connect().
++ *! 11-Aug-2000 rr: Part of node enabled.
++ *! 31-Jul-2000 rr: UTIL_Wrap and MEM_Wrap added to RM.
++ *! 27-Jul-2000 rr: PROCWRAP, NODEWRAP and STRMWRAP implemented.
++ *!            STRM and some NODE Wrappers are not implemented.
++ *! 27-Jun-2000 rr: MGRWRAP fxns added.IFDEF to build for PM or DSP/BIOS Bridge
++ *! 08-Feb-2000 rr  File name changed to wcd.c
++ *! 03-Feb-2000 rr: Module initialization are done by SERVICES init. GT Class
++ *!            changes for module init/exit fxns.
++ *! 24-Jan-2000 rr: Merged with Scott's code.
++ *! 21-Jan-1999 sg: Changed ARGS_CHNL_GETMODE field name from pdwMode to pMode.
++ *! 17-Jan-2000 rr: BRD_GetStatus does WRAP_MAP2CALLER for state.
++ *! 14-Dec-1999 ag: Removed _MAP2CALLER in CHNL_GetMgr().
++ *! 13-Dec-1999 rr: BRDWRAP_GetSymbol, BRDWRAP_GetTrace uses WRAP_MAP2CALLER
++ *!            macros.BRDWRAP_Load maps and unmaps embedded pointers.
++ *! 10-Dec-1999 ag: User CHNL bufs mapped in _AddIOReq & _GetIOCompletion.
++ *! 09-Dec-1999 rr: BRDWRAP_Open and CHNLWRAP_GetMgr does not map
++ *!            pointer as there was a change in config.c
++ *! 06-Dec-1999 rr: BRD_Read and Write Maps the buf pointers.
++ *! 03-Dec-1999 rr: CHNLWRAP_GetMgr and BRDWRAP_Open maps  hDevNode pointer.
++ *!            WCD_InitComplete2 Included for BRD_AutoStart.
++ *! 16-Nov-1999 ag: Map buf to process in CHNLWRAP_AllocBuffer().
++ *!            CHNL_GetMgr() Mapping Fix.
++ *! 10-Nov-1999 ag: Removed unnecessary calls to WRAP_MAP2CALLER.
++ *! 08-Nov-1999 kc: Added MEMRY & enabled BRD_IOCtl for tests.
++ *! 29-Oct-1999 ag: Added CHNL.
++ *! 29-Oct-1999 kc: Added trace statements; added ptr mapping; updated
++ *!            use of UTIL module API.
++ *! 29-Oct-1999 rr: Wrapper functions does the Mapping of the Pointers.
++ *!            in WinCE all the explicit pointers will be converted
++ *!            by the OS during interprocess but not the embedded pointers.
++ *! 16-Oct-1999 kc: Code review cleanup.
++ *! 07-Oct-1999 kc: Added UTILWRAP_TestDll() to run PM test harness. See
++ *!            /src/doc/pmtest.doc for more detail.
++ *! 09-Sep-1999 rr: After exactly two years(!). Adopted for WinCE. GT Enabled.
++ *! 09-Sep-1997 gp: Created.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/services.h>
++#include <dspbridge/util.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/chnl.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/drv.h>
++
++#include <dspbridge/proc.h>
++#include <dspbridge/strm.h>
++
++/*  ----------------------------------- Resource Manager */
++#include <dspbridge/disp.h>
++#include <dspbridge/mgr.h>
++#include <dspbridge/node.h>
++#include <dspbridge/rmm.h>
++
++
++/*  ----------------------------------- Others */
++#include <dspbridge/msg.h>
++#include <dspbridge/cmm.h>
++#include <dspbridge/io.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/_dcd.h>
++#include <dspbridge/dbdcd.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++#define MAX_TRACEBUFLEN 255
++#define MAX_LOADARGS    16
++#define MAX_NODES       64
++#define MAX_STREAMS     16
++#define MAX_BUFS      64
++
++/* Following two macros should ideally have do{}while(0) */
++
++#define cp_fm_usr(dest, src, status, elements)    \
++    if (DSP_SUCCEEDED(status)) {\
++          if (unlikely(src == NULL) ||                                \
++              unlikely(copy_from_user(dest, src, elements * sizeof(*(dest))))) { \
++              GT_1trace(WCD_debugMask, GT_7CLASS, \
++              "copy_from_user failed, src=0x%x\n", src);  \
++              status = DSP_EPOINTER ; \
++      } \
++    }
++
++#define cp_to_usr(dest, src, status, elements)    \
++    if (DSP_SUCCEEDED(status)) {\
++          if (unlikely(dest == NULL) ||                               \
++              unlikely(copy_to_user(dest, src, elements * sizeof(*(src))))) { \
++              GT_1trace(WCD_debugMask, GT_7CLASS, \
++              "copy_to_user failed, dest=0x%x\n", dest); \
++              status = DSP_EPOINTER ;\
++      } \
++    }
++
++/* Device IOCtl function pointer */
++struct WCD_Cmd {
++      u32(*fxn)(union Trapped_Args *args);
++      u32 dwIndex;
++} ;
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask WCD_debugMask = { NULL, NULL }; /* Core VxD Mask */
++#endif
++static u32 WCD_cRefs;
++
++/*
++ *  Function table.
++ *  The order of these functions MUST be the same as the order of the command
++ *  numbers defined in wcdioctl.h  This is how an IOCTL number in user mode
++ *  turns into a function call in kernel mode.
++ */
++static struct WCD_Cmd WCD_cmdTable[] = {
++      /* MGR module */
++      {MGRWRAP_EnumNode_Info, CMD_MGR_ENUMNODE_INFO_OFFSET},
++      {MGRWRAP_EnumProc_Info, CMD_MGR_ENUMPROC_INFO_OFFSET},
++      {MGRWRAP_RegisterObject, CMD_MGR_REGISTEROBJECT_OFFSET},
++      {MGRWRAP_UnregisterObject, CMD_MGR_UNREGISTEROBJECT_OFFSET},
++      {MGRWRAP_WaitForBridgeEvents, CMD_MGR_WAIT_OFFSET},
++#ifndef RES_CLEANUP_DISABLE
++      {MGRWRAP_GetProcessResourcesInfo, CMD_MGR_RESOUCES_OFFSET},
++#endif
++      /* PROC Module */
++      {PROCWRAP_Attach, CMD_PROC_ATTACH_OFFSET},
++      {PROCWRAP_Ctrl, CMD_PROC_CTRL_OFFSET},
++      {PROCWRAP_Detach, CMD_PROC_DETACH_OFFSET},
++      {PROCWRAP_EnumNode_Info, CMD_PROC_ENUMNODE_OFFSET},
++      {PROCWRAP_EnumResources, CMD_PROC_ENUMRESOURCES_OFFSET},
++      {PROCWRAP_GetState, CMD_PROC_GETSTATE_OFFSET},
++      {PROCWRAP_GetTrace, CMD_PROC_GETTRACE_OFFSET},
++      {PROCWRAP_Load, CMD_PROC_LOAD_OFFSET},
++      {PROCWRAP_RegisterNotify, CMD_PROC_REGISTERNOTIFY_OFFSET},
++      {PROCWRAP_Start, CMD_PROC_START_OFFSET},
++      {PROCWRAP_ReserveMemory, CMD_PROC_RSVMEM_OFFSET},
++      {PROCWRAP_UnReserveMemory, CMD_PROC_UNRSVMEM_OFFSET},
++      {PROCWRAP_Map, CMD_PROC_MAPMEM_OFFSET},
++      {PROCWRAP_UnMap, CMD_PROC_UNMAPMEM_OFFSET},
++      {PROCWRAP_FlushMemory, CMD_PROC_FLUSHMEMORY_OFFSET},
++      {PROCWRAP_Stop, CMD_PROC_STOP_OFFSET},
++      {PROCWRAP_InvalidateMemory, CMD_PROC_INVALIDATEMEMORY_OFFSET},
++      /* NODE Module */
++      {NODEWRAP_Allocate, CMD_NODE_ALLOCATE_OFFSET},
++      {NODEWRAP_AllocMsgBuf, CMD_NODE_ALLOCMSGBUF_OFFSET},
++      {NODEWRAP_ChangePriority, CMD_NODE_CHANGEPRIORITY_OFFSET},
++      {NODEWRAP_Connect, CMD_NODE_CONNECT_OFFSET},
++      {NODEWRAP_Create, CMD_NODE_CREATE_OFFSET},
++      {NODEWRAP_Delete, CMD_NODE_DELETE_OFFSET},
++      {NODEWRAP_FreeMsgBuf, CMD_NODE_FREEMSGBUF_OFFSET},
++      {NODEWRAP_GetAttr, CMD_NODE_GETATTR_OFFSET},
++      {NODEWRAP_GetMessage, CMD_NODE_GETMESSAGE_OFFSET},
++      {NODEWRAP_Pause, CMD_NODE_PAUSE_OFFSET},
++      {NODEWRAP_PutMessage, CMD_NODE_PUTMESSAGE_OFFSET},
++      {NODEWRAP_RegisterNotify, CMD_NODE_REGISTERNOTIFY_OFFSET},
++      {NODEWRAP_Run, CMD_NODE_RUN_OFFSET},
++      {NODEWRAP_Terminate, CMD_NODE_TERMINATE_OFFSET},
++      {NODEWRAP_GetUUIDProps, CMD_NODE_GETUUIDPROPS_OFFSET},
++      /* STRM wrapper functions */
++      {STRMWRAP_AllocateBuffer, CMD_STRM_ALLOCATEBUFFER_OFFSET},
++      {STRMWRAP_Close, CMD_STRM_CLOSE_OFFSET},
++      {STRMWRAP_FreeBuffer, CMD_STRM_FREEBUFFER_OFFSET},
++      {STRMWRAP_GetEventHandle, CMD_STRM_GETEVENTHANDLE_OFFSET},
++      {STRMWRAP_GetInfo, CMD_STRM_GETINFO_OFFSET},
++      {STRMWRAP_Idle, CMD_STRM_IDLE_OFFSET},
++      {STRMWRAP_Issue, CMD_STRM_ISSUE_OFFSET},
++      {STRMWRAP_Open, CMD_STRM_OPEN_OFFSET},
++      {STRMWRAP_Reclaim, CMD_STRM_RECLAIM_OFFSET},
++      {STRMWRAP_RegisterNotify, CMD_STRM_REGISTERNOTIFY_OFFSET},
++      {STRMWRAP_Select, CMD_STRM_SELECT_OFFSET},
++      /* CMM module */
++      {CMMWRAP_CallocBuf, CMD_CMM_ALLOCBUF_OFFSET},
++      {CMMWRAP_FreeBuf, CMD_CMM_FREEBUF_OFFSET},
++      {CMMWRAP_GetHandle, CMD_CMM_GETHANDLE_OFFSET},
++      {CMMWRAP_GetInfo, CMD_CMM_GETINFO_OFFSET}
++};
++
++/*
++ *  ======== WCD_CallDevIOCtl ========
++ *  Purpose:
++ *      Call the (wrapper) function for the corresponding WCD IOCTL.
++ */
++inline DSP_STATUS WCD_CallDevIOCtl(u32 cmd, union Trapped_Args *args,
++                                  u32 *pResult)
++{
++      if ((cmd < (sizeof(WCD_cmdTable) / sizeof(struct WCD_Cmd)))) {
++              /* make the fxn call via the cmd table */
++              *pResult = (*WCD_cmdTable[cmd].fxn) (args);
++              return DSP_SOK;
++      } else {
++              return DSP_EINVALIDARG;
++      }
++}
++
++/*
++ *  ======== WCD_Exit ========
++ */
++void WCD_Exit(void)
++{
++      DBC_Require(WCD_cRefs > 0);
++      WCD_cRefs--;
++      GT_1trace(WCD_debugMask, GT_5CLASS,
++               "Entered WCD_Exit, ref count:  0x%x\n", WCD_cRefs);
++      if (WCD_cRefs == 0) {
++              /* Release all WCD modules initialized in WCD_Init(). */
++              COD_Exit();
++              DEV_Exit();
++              CHNL_Exit();
++              MSG_Exit();
++              IO_Exit();
++              STRM_Exit();
++              NTFY_Exit();
++              DISP_Exit();
++              NODE_Exit();
++              PROC_Exit();
++              MGR_Exit();
++              RMM_exit();
++              DRV_Exit();
++              SERVICES_Exit();
++      }
++      DBC_Ensure(WCD_cRefs >= 0);
++}
++
++/*
++ *  ======== WCD_Init ========
++ *  Purpose:
++ *      Module initialization is done by SERVICES Init.
++ */
++bool WCD_Init(void)
++{
++      bool fInit = true;
++      bool fDRV, fDEV, fCOD, fSERVICES, fCHNL, fMSG, fIO;
++      bool fMGR, fPROC, fNODE, fDISP, fNTFY, fSTRM, fRMM;
++#ifdef DEBUG
++      /* runtime check of Device IOCtl array. */
++      u32 i;
++      for (i = 1; i < (sizeof(WCD_cmdTable) / sizeof(struct WCD_Cmd)); i++)
++              DBC_Assert(WCD_cmdTable[i - 1].dwIndex == i);
++
++#endif
++      if (WCD_cRefs == 0) {
++              /* initialize all SERVICES modules */
++              fSERVICES = SERVICES_Init();
++              /* initialize debugging module */
++              DBC_Assert(!WCD_debugMask.flags);
++              GT_create(&WCD_debugMask, "CD");    /* CD for class driver */
++              /* initialize class driver and other modules */
++              fDRV = DRV_Init();
++              fMGR = MGR_Init();
++              fPROC = PROC_Init();
++              fNODE = NODE_Init();
++              fDISP = DISP_Init();
++              fNTFY = NTFY_Init();
++              fSTRM = STRM_Init();
++              fRMM = RMM_init();
++              fCHNL = CHNL_Init();
++              fMSG = MSG_Init();
++              fIO = IO_Init();
++              fDEV = DEV_Init();
++              fCOD = COD_Init();
++              fInit = fSERVICES && fDRV && fDEV && fCHNL && fCOD &&
++                      fMSG && fIO;
++              fInit = fInit && fMGR && fPROC && fRMM;
++              if (!fInit) {
++                      if (fSERVICES)
++                              SERVICES_Exit();
++
++                      if (fDRV)
++                              DRV_Exit();
++
++                      if (fMGR)
++                              MGR_Exit();
++
++                      if (fSTRM)
++                              STRM_Exit();
++
++                      if (fPROC)
++                              PROC_Exit();
++
++                      if (fNODE)
++                              NODE_Exit();
++
++                      if (fDISP)
++                              DISP_Exit();
++
++                      if (fNTFY)
++                              NTFY_Exit();
++
++                      if (fCHNL)
++                              CHNL_Exit();
++
++                      if (fMSG)
++                              MSG_Exit();
++
++                      if (fIO)
++                              IO_Exit();
++
++                      if (fDEV)
++                              DEV_Exit();
++
++                      if (fCOD)
++                              COD_Exit();
++
++                      if (fRMM)
++                              RMM_exit();
++
++              }
++      }
++      if (fInit)
++              WCD_cRefs++;
++
++      GT_1trace(WCD_debugMask, GT_5CLASS,
++               "Entered WCD_Init, ref count: 0x%x\n", WCD_cRefs);
++      return fInit;
++}
++
++/*
++ *  ======== WCD_InitComplete2 ========
++ *  Purpose:
++ *      Perform any required WCD, and WMD initialization which
++ *      cannot not be performed in WCD_Init() or DEV_StartDevice() due
++ *      to the fact that some services are not yet
++ *      completely initialized.
++ *  Parameters:
++ *  Returns:
++ *      DSP_SOK:      Allow this device to load
++ *      DSP_EFAIL:      Failure.
++ *  Requires:
++ *      WCD initialized.
++ *  Ensures:
++ */
++DSP_STATUS WCD_InitComplete2(void)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct CFG_DEVNODE *DevNode;
++      struct DEV_OBJECT *hDevObject;
++      u32 devType;
++
++      DBC_Require(WCD_cRefs > 0);
++      GT_0trace(WCD_debugMask, GT_ENTER, "Entered WCD_InitComplete\n");
++       /*  Walk the list of DevObjects, get each devnode, and attempting to
++       *  autostart the board. Note that this requires COF loading, which
++       *  requires KFILE.  */
++      for (hDevObject = DEV_GetFirst(); hDevObject != NULL;
++           hDevObject = DEV_GetNext(hDevObject)) {
++              if (DSP_FAILED(DEV_GetDevNode(hDevObject, &DevNode)))
++                      continue;
++
++              if (DSP_FAILED(DEV_GetDevType(hDevObject, &devType)))
++                      continue;
++
++              if ((devType == DSP_UNIT) || (devType == IVA_UNIT)) {
++                      if (DSP_FAILED(PROC_AutoStart(DevNode, hDevObject))) {
++                              GT_0trace(WCD_debugMask, GT_1CLASS,
++                                       "WCD_InitComplete2 Failed\n");
++                              status = DSP_EFAIL;
++                              /* break; */
++                      }
++              } else
++                      GT_1trace(WCD_debugMask, GT_ENTER,
++                               "Ignoring PROC_AutoStart "
++                               "for Device Type = 0x%x \n", devType);
++      }                       /* End For Loop */
++      GT_1trace(WCD_debugMask, GT_ENTER,
++               "Exiting WCD_InitComplete status 0x%x\n", status);
++      return status;
++}
++
++/*
++ * ======== MGRWRAP_EnumNode_Info ========
++ */
++u32 MGRWRAP_EnumNode_Info(union Trapped_Args *args)
++{
++      u8 *pNDBProps;
++      u32 uNumNodes;
++      DSP_STATUS status = DSP_SOK;
++      u32 size = args->ARGS_MGR_ENUMNODE_INFO.uNDBPropsSize;
++
++      GT_4trace(WCD_debugMask, GT_ENTER,
++               "MGR_EnumNodeInfo: entered args:\n0x%x"
++               " uNode: 0x%x\tpNDBProps: 0x%x\tuNDBPropsSize: "
++               "0x%x\tpuNumNodes\n", args->ARGS_MGR_ENUMNODE_INFO.uNode,
++               args->ARGS_MGR_ENUMNODE_INFO.pNDBProps,
++               args->ARGS_MGR_ENUMNODE_INFO.uNDBPropsSize,
++               args->ARGS_MGR_ENUMNODE_INFO.puNumNodes);
++      pNDBProps = MEM_Alloc(size, MEM_NONPAGED);
++      if (pNDBProps == NULL)
++              status = DSP_EMEMORY;
++
++      if (DSP_SUCCEEDED(status)) {
++              status = MGR_EnumNodeInfo(args->ARGS_MGR_ENUMNODE_INFO.uNode,
++                                       (struct DSP_NDBPROPS *)pNDBProps,
++                                       size, &uNumNodes);
++      }
++      cp_to_usr(args->ARGS_MGR_ENUMNODE_INFO.pNDBProps, pNDBProps, status,
++               size);
++      cp_to_usr(args->ARGS_MGR_ENUMNODE_INFO.puNumNodes, &uNumNodes, status,
++               1);
++      if (pNDBProps)
++              MEM_Free(pNDBProps);
++
++      return status;
++}
++
++/*
++ * ======== MGRWRAP_EnumProc_Info ========
++ */
++u32 MGRWRAP_EnumProc_Info(union Trapped_Args *args)
++{
++      u8 *pProcessorInfo;
++      u32 uNumProcs;
++      DSP_STATUS status = DSP_SOK;
++      u32 size = args->ARGS_MGR_ENUMPROC_INFO.uProcessorInfoSize;
++
++      GT_4trace(WCD_debugMask, GT_ENTER,
++               "MGRWRAP_EnumProc_Info: entered args:\n"
++               "0x%x uProcessor: 0x%x\tpProcessorInfo: 0x%x\t"
++               "uProcessorInfoSize: 0x%x\tpuNumProcs \n",
++               args->ARGS_MGR_ENUMPROC_INFO.uProcessor,
++               args->ARGS_MGR_ENUMPROC_INFO.pProcessorInfo,
++               args->ARGS_MGR_ENUMPROC_INFO.uProcessorInfoSize,
++               args->ARGS_MGR_ENUMPROC_INFO.puNumProcs);
++      pProcessorInfo = MEM_Alloc(size, MEM_NONPAGED);
++      if (pProcessorInfo == NULL)
++              status = DSP_EMEMORY;
++
++      if (DSP_SUCCEEDED(status)) {
++              status = MGR_EnumProcessorInfo(args->
++                              ARGS_MGR_ENUMPROC_INFO.uProcessor,
++                              (struct DSP_PROCESSORINFO *)pProcessorInfo,
++                              size, &uNumProcs);
++      }
++      cp_to_usr(args->ARGS_MGR_ENUMPROC_INFO.pProcessorInfo, pProcessorInfo,
++               status, size);
++      cp_to_usr(args->ARGS_MGR_ENUMPROC_INFO.puNumProcs, &uNumProcs,
++               status, 1);
++      if (pProcessorInfo)
++              MEM_Free(pProcessorInfo);
++
++      return status;
++}
++
++#define WRAP_MAP2CALLER(x) x
++/*
++ * ======== MGRWRAP_RegisterObject ========
++ */
++u32 MGRWRAP_RegisterObject(union Trapped_Args *args)
++{
++      u32 retVal;
++
++      GT_1trace(WCD_debugMask, GT_ENTER,
++               "MGRWRAP_RegisterObject: entered pg2hMsg "
++               "0x%x\n", args->ARGS_MGR_REGISTEROBJECT.pUuid);
++      retVal = DCD_RegisterObject(WRAP_MAP2CALLER
++                  (args->ARGS_MGR_REGISTEROBJECT.pUuid),
++                  args->ARGS_MGR_REGISTEROBJECT.objType,
++                  WRAP_MAP2CALLER(args->ARGS_MGR_REGISTEROBJECT.pszPathName));
++      return retVal;
++}
++
++/*
++ * ======== MGRWRAP_UnregisterObject ========
++ */
++u32 MGRWRAP_UnregisterObject(union Trapped_Args *args)
++{
++      u32 retVal;
++
++      GT_1trace(WCD_debugMask, GT_ENTER,
++               "MGRWRAP_UnregisterObject: entered pg2hMsg"
++               " 0x%x\n", args->ARGS_MGR_UNREGISTEROBJECT.pUuid);
++      retVal = DCD_UnregisterObject(WRAP_MAP2CALLER
++                      (args->ARGS_MGR_UNREGISTEROBJECT.pUuid),
++                      args->ARGS_MGR_UNREGISTEROBJECT.objType);
++
++      return retVal;
++}
++
++/*
++ * ======== MGRWRAP_WaitForBridgeEvents ========
++ */
++u32 MGRWRAP_WaitForBridgeEvents(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DSP_NOTIFICATION *aNotifications[MAX_EVENTS];
++      struct DSP_NOTIFICATION notifications[MAX_EVENTS];
++      u32 uIndex, i;
++      u32 uCount = args->ARGS_MGR_WAIT.uCount;
++
++      GT_0trace(WCD_debugMask, GT_ENTER,
++               "MGRWRAP_WaitForBridgeEvents: entered\n");
++
++      if (uCount > MAX_EVENTS)
++              status = DSP_EINVALIDARG;
++
++      /* get the array of pointers to user structures */
++      cp_fm_usr(aNotifications, args->ARGS_MGR_WAIT.aNotifications,
++       status, uCount);
++      /* get the events */
++      for (i = 0; i < uCount; i++) {
++              cp_fm_usr(&notifications[i], aNotifications[i], status, 1);
++              if (DSP_SUCCEEDED(status)) {
++                      /* set the array of pointers to kernel structures*/
++                      aNotifications[i] = &notifications[i];
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              status = MGR_WaitForBridgeEvents(aNotifications, uCount,
++                       &uIndex, args->ARGS_MGR_WAIT.uTimeout);
++      }
++      cp_to_usr(args->ARGS_MGR_WAIT.puIndex, &uIndex, status, 1);
++      return status;
++}
++
++
++#ifndef RES_CLEANUP_DISABLE
++/*
++ * ======== MGRWRAP_GetProcessResourceInfo ========
++ */
++u32 MGRWRAP_GetProcessResourcesInfo(union Trapped_Args *args)
++{
++    DSP_STATUS status = DSP_SOK;
++    u32 uSize = 0;
++    u8 *pBuf = MEM_Alloc(8092, MEM_NONPAGED);
++    status = DRV_ProcDisplayResInfo(pBuf, &uSize);
++    GT_1trace(WCD_debugMask, GT_ENTER,
++           "MGRWRAP_GetProcessResourcesInfo:uSize=%d :\n", uSize);
++    cp_to_usr(args->ARGS_PROC_GETTRACE.pBuf, pBuf, status, uSize);
++    GT_0trace(WCD_debugMask, GT_ENTER, "\n***********"
++           "123MGRWRAP_GetProcessResourcesInfo:**************\n");
++    GT_0trace(WCD_debugMask, GT_ENTER, "\n***********"
++           "456MGRWRAP_GetProcessResourcesInfo:**************\n");
++    cp_to_usr(args->ARGS_PROC_GETTRACE.pSize, &uSize, status, 1);
++    MEM_Free(pBuf);
++    return status;
++}
++#endif
++
++
++/*
++ * ======== PROCWRAP_Attach ========
++ */
++u32 PROCWRAP_Attach(union Trapped_Args *args)
++{
++      DSP_HPROCESSOR processor;
++      DSP_STATUS status = DSP_SOK;
++      struct DSP_PROCESSORATTRIN attrIn, *pAttrIn = NULL;
++
++      GT_3trace(WCD_debugMask, GT_ENTER,
++               "PROCWRAP_Attach: entered args:\n" "0x%x"
++               " uProcessor: 0x%x\tpAttrIn: 0x%x\tphProcessor \n",
++               args->ARGS_PROC_ATTACH.uProcessor,
++               args->ARGS_PROC_ATTACH.pAttrIn,
++               args->ARGS_PROC_ATTACH.phProcessor);
++      /* Optional argument */
++      if (args->ARGS_PROC_ATTACH.pAttrIn) {
++              cp_fm_usr(&attrIn, args->ARGS_PROC_ATTACH.pAttrIn, status, 1);
++              if (DSP_SUCCEEDED(status))
++                      pAttrIn = &attrIn;
++
++      }
++      status = PROC_Attach(args->ARGS_PROC_ATTACH.uProcessor, pAttrIn,
++                          &processor);
++      cp_to_usr(args->ARGS_PROC_ATTACH.phProcessor, &processor, status, 1);
++      return status;
++}
++
++/*
++ * ======== PROCWRAP_Ctrl ========
++ */
++u32 PROCWRAP_Ctrl(union Trapped_Args *args)
++{
++      u32 cbDataSize, __user *pSize = (u32 __user *)
++                      args->ARGS_PROC_CTRL.pArgs;
++      u8 *pArgs = NULL;
++      DSP_STATUS status = DSP_SOK;
++
++      GT_3trace(WCD_debugMask, GT_ENTER,
++               "PROCWRAP_Ctrl: entered args:\n 0x%x"
++               " uProcessor: 0x%x\tdwCmd: 0x%x\tpArgs \n",
++               args->ARGS_PROC_CTRL.hProcessor,
++               args->ARGS_PROC_CTRL.dwCmd,
++               args->ARGS_PROC_CTRL.pArgs);
++      if (pSize) {
++              if (get_user(cbDataSize, pSize))
++                      status = DSP_EFAIL;
++
++              cbDataSize += sizeof(u32);
++              if (DSP_SUCCEEDED(status)) {
++                      pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED);
++                      if (pArgs == NULL)
++                              status = DSP_EMEMORY;
++
++              }
++              cp_fm_usr(pArgs, args->ARGS_PROC_CTRL.pArgs, status,
++                       cbDataSize);
++      }
++      if (DSP_SUCCEEDED(status)) {
++              status = PROC_Ctrl(args->ARGS_PROC_CTRL.hProcessor,
++                                args->ARGS_PROC_CTRL.dwCmd,
++                                (struct DSP_CBDATA *)pArgs);
++      }
++
++      /* cp_to_usr(args->ARGS_PROC_CTRL.pArgs, pArgs, status, 1);*/
++      if (pArgs)
++              MEM_Free(pArgs);
++
++      return status;
++}
++
++/*
++ * ======== PROCWRAP_Detach ========
++ */
++u32 PROCWRAP_Detach(union Trapped_Args *args)
++{
++      u32 retVal;
++
++      GT_1trace(WCD_debugMask, GT_ENTER,
++               "PROCWRAP_Detach: entered args\n0x%x "
++               "hProceesor \n", args->ARGS_PROC_DETACH.hProcessor);
++      retVal = PROC_Detach(args->ARGS_PROC_DETACH.hProcessor);
++
++      return retVal;
++}
++
++/*
++ * ======== PROCWRAP_EnumNode_Info ========
++ */
++u32 PROCWRAP_EnumNode_Info(union Trapped_Args *args)
++{
++      DSP_STATUS status;
++      DSP_HNODE aNodeTab[MAX_NODES];
++      u32 uNumNodes;
++      u32 uAllocated;
++
++      GT_5trace(WCD_debugMask, GT_ENTER,
++               "PROCWRAP_EnumNode_Info:entered args:\n0x"
++               "%xhProcessor:0x%x\taNodeTab:0x%x\tuNodeTabSize:"
++               "%0x%x\tpuNumNodes%\n0x%x puAllocated: \n",
++               args->ARGS_PROC_ENUMNODE_INFO.hProcessor,
++               args->ARGS_PROC_ENUMNODE_INFO.aNodeTab,
++               args->ARGS_PROC_ENUMNODE_INFO.uNodeTabSize,
++               args->ARGS_PROC_ENUMNODE_INFO.puNumNodes,
++               args->ARGS_PROC_ENUMNODE_INFO.puAllocated);
++      DBC_Require(args->ARGS_PROC_ENUMNODE_INFO.uNodeTabSize <= MAX_NODES);
++      status = PROC_EnumNodes(args->ARGS_PROC_ENUMNODE_INFO.hProcessor,
++                              aNodeTab,
++                              args->ARGS_PROC_ENUMNODE_INFO.uNodeTabSize,
++                              &uNumNodes, &uAllocated);
++      cp_to_usr(args->ARGS_PROC_ENUMNODE_INFO.aNodeTab, aNodeTab, status,
++               uNumNodes);
++      cp_to_usr(args->ARGS_PROC_ENUMNODE_INFO.puNumNodes, &uNumNodes,
++               status, 1);
++      cp_to_usr(args->ARGS_PROC_ENUMNODE_INFO.puAllocated, &uAllocated,
++               status, 1);
++      return status;
++}
++
++/*
++ * ======== PROCWRAP_FlushMemory ========
++ */
++u32 PROCWRAP_FlushMemory(union Trapped_Args *args)
++{
++      DSP_STATUS status;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_FlushMemory: entered\n");
++
++      status = PROC_FlushMemory(args->ARGS_PROC_FLUSHMEMORY.hProcessor,
++                               args->ARGS_PROC_FLUSHMEMORY.pMpuAddr,
++                               args->ARGS_PROC_FLUSHMEMORY.ulSize,
++                               args->ARGS_PROC_FLUSHMEMORY.ulFlags);
++      return status;
++}
++
++
++/*
++ * ======== PROCWRAP_InvalidateMemory ========
++ */
++u32 PROCWRAP_InvalidateMemory(union Trapped_Args *args)
++{
++      DSP_STATUS status;
++
++      GT_0trace(WCD_debugMask, GT_ENTER,
++               "PROCWRAP_InvalidateMemory:entered\n");
++
++      status = PROC_InvalidateMemory(
++                                args->ARGS_PROC_INVALIDATEMEMORY.hProcessor,
++                                args->ARGS_PROC_INVALIDATEMEMORY.pMpuAddr,
++                                args->ARGS_PROC_INVALIDATEMEMORY.ulSize);
++      return status;
++}
++
++
++/*
++ * ======== PROCWRAP_EnumResources ========
++ */
++u32 PROCWRAP_EnumResources(union Trapped_Args *args)
++{
++      u32 retVal;
++
++      GT_4trace(WCD_debugMask, GT_ENTER,
++               "PROCWRAP_EnumResources: entered args:\n"
++               "0x%x hProcessor: 0x%x\tuResourceMask: 0x%x\tpResourceInfo"
++               " 0x%x\tuResourceInfoSixe \n",
++               args->ARGS_PROC_ENUMRESOURCES.hProcessor,
++               args->ARGS_PROC_ENUMRESOURCES.uResourceType,
++               args->ARGS_PROC_ENUMRESOURCES.pResourceInfo,
++               args->ARGS_PROC_ENUMRESOURCES.uResourceInfoSize);
++      retVal = PROC_GetResourceInfo(args->ARGS_PROC_ENUMRESOURCES.hProcessor,
++                      args->ARGS_PROC_ENUMRESOURCES.uResourceType,
++                      WRAP_MAP2CALLER(args->ARGS_PROC_ENUMRESOURCES.
++                      pResourceInfo), args->ARGS_PROC_ENUMRESOURCES.
++                      uResourceInfoSize);
++
++      return retVal;
++}
++
++/*
++ * ======== PROCWRAP_GetState ========
++ */
++u32 PROCWRAP_GetState(union Trapped_Args *args)
++{
++      DSP_STATUS status;
++      struct DSP_PROCESSORSTATE procStatus;
++      GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_GetState: entered\n");
++      status = PROC_GetState(args->ARGS_PROC_GETSTATE.hProcessor, &procStatus,
++                            args->ARGS_PROC_GETSTATE.uStateInfoSize);
++      cp_to_usr(args->ARGS_PROC_GETSTATE.pProcStatus, &procStatus, status, 1);
++      return status;
++
++}
++
++/*
++ * ======== PROCWRAP_GetTrace ========
++ */
++u32 PROCWRAP_GetTrace(union Trapped_Args *args)
++{
++      DSP_STATUS status;
++      u8 *pBuf;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_GetTrace: entered\n");
++
++      DBC_Require(args->ARGS_PROC_GETTRACE.uMaxSize <= MAX_TRACEBUFLEN);
++
++      pBuf = MEM_Calloc(args->ARGS_PROC_GETTRACE.uMaxSize, MEM_NONPAGED);
++      if (pBuf != NULL) {
++              status = PROC_GetTrace(args->ARGS_PROC_GETTRACE.hProcessor,
++                                    pBuf, args->ARGS_PROC_GETTRACE.uMaxSize);
++      } else {
++              status = DSP_EMEMORY;
++      }
++      cp_to_usr(args->ARGS_PROC_GETTRACE.pBuf, pBuf, status,
++               args->ARGS_PROC_GETTRACE.uMaxSize);
++      if (pBuf)
++              MEM_Free(pBuf);
++
++      return status;
++}
++
++/*
++ * ======== PROCWRAP_Load ========
++ */
++u32 PROCWRAP_Load(union Trapped_Args *args)
++{
++      s32 i, len;
++      DSP_STATUS status = DSP_SOK;
++       char *temp;
++      s32 argc = args->ARGS_PROC_LOAD.iArgc;
++      u8 **argv, **envp = NULL;
++
++
++      DBC_Require(argc > 0);
++      DBC_Require(argc <= MAX_LOADARGS);
++
++      argv = MEM_Alloc(argc * sizeof(u8 *), MEM_NONPAGED);
++      if (argv == NULL)
++              status = DSP_EMEMORY;
++
++      cp_fm_usr(argv, args->ARGS_PROC_LOAD.aArgv, status, argc);
++      for (i = 0; DSP_SUCCEEDED(status) && (i < argc); i++) {
++              if (argv[i] != NULL) {
++                        /* User space pointer to argument */
++                       temp = (char *) argv[i];
++                       len = strlen_user((char *)temp);
++                      /* Kernel space pointer to argument */
++                      argv[i] = MEM_Alloc(len, MEM_NONPAGED);
++                      if (argv[i] == NULL) {
++                              status = DSP_EMEMORY;
++                              break;
++                      }
++                      cp_fm_usr(argv[i], temp, status, len);
++              }
++      }
++      /* TODO: validate this */
++      if (args->ARGS_PROC_LOAD.aEnvp != NULL) {
++              /* number of elements in the envp array including NULL */
++              len = 0;
++              do {
++                      len++;
++                       get_user(temp, args->ARGS_PROC_LOAD.aEnvp);
++               } while (temp);
++              envp = MEM_Alloc(len * sizeof(u8 *), MEM_NONPAGED);
++              if (envp == NULL)
++                      status = DSP_EMEMORY;
++
++              cp_fm_usr(envp, args->ARGS_PROC_LOAD.aEnvp, status, len);
++              for (i = 0; DSP_SUCCEEDED(status) && (envp[i] != NULL); i++) {
++                        /* User space pointer to argument */
++                       temp = (char *)envp[i];
++                       len = strlen_user((char *)temp);
++                      /* Kernel space pointer to argument */
++                      envp[i] = MEM_Alloc(len, MEM_NONPAGED);
++                      if (envp[i] == NULL) {
++                              status = DSP_EMEMORY;
++                              break;
++                      }
++                      cp_fm_usr(envp[i], temp, status, len);
++              }
++      }
++      GT_5trace(WCD_debugMask, GT_ENTER,
++               "PROCWRAP_Load, hProcessor: 0x%x\n\tiArgc:"
++               "0x%x\n\taArgv: 0x%x\n\taArgv[0]: %s\n\taEnvp: 0x%0x\n",
++               args->ARGS_PROC_LOAD.hProcessor,
++               args->ARGS_PROC_LOAD.iArgc, args->ARGS_PROC_LOAD.aArgv,
++               argv[0], args->ARGS_PROC_LOAD.aEnvp);
++      if (DSP_SUCCEEDED(status)) {
++              status = PROC_Load(args->ARGS_PROC_LOAD.hProcessor,
++                                args->ARGS_PROC_LOAD.iArgc,
++                                (CONST char **)argv, (CONST char **)envp);
++      }
++      if (envp != NULL) {
++              i = 0;
++              while (envp[i] != NULL)
++                      MEM_Free(envp[i++]);
++
++              MEM_Free(envp);
++      }
++      if (argv != NULL) {
++              for (i = 0; i < argc; i++) {
++                      if (argv[i] != NULL)
++                              MEM_Free(argv[i]);
++
++              }
++              MEM_Free(argv);
++      }
++      return status;
++}
++
++/*
++ * ======== PROCWRAP_Map ========
++ */
++u32 PROCWRAP_Map(union Trapped_Args *args)
++{
++      DSP_STATUS status;
++      void *pMapAddr;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_Map: entered\n");
++      status = PROC_Map(args->ARGS_PROC_MAPMEM.hProcessor,
++                       args->ARGS_PROC_MAPMEM.pMpuAddr,
++                       args->ARGS_PROC_MAPMEM.ulSize,
++                       args->ARGS_PROC_MAPMEM.pReqAddr, &pMapAddr,
++                       args->ARGS_PROC_MAPMEM.ulMapAttr);
++      if (DSP_SUCCEEDED(status)) {
++              if (put_user(pMapAddr, args->ARGS_PROC_MAPMEM.ppMapAddr))
++                      status = DSP_EINVALIDARG;
++
++      }
++      return status;
++}
++
++/*
++ * ======== PROCWRAP_RegisterNotify ========
++ */
++u32 PROCWRAP_RegisterNotify(union Trapped_Args *args)
++{
++      DSP_STATUS status;
++      struct DSP_NOTIFICATION notification;
++
++      GT_0trace(WCD_debugMask, GT_ENTER,
++               "PROCWRAP_RegisterNotify: entered\n");
++
++      /* Initialize the notification data structure  */
++      notification.psName = NULL;
++      notification.handle = NULL;
++
++      status = PROC_RegisterNotify(args->ARGS_PROC_REGISTER_NOTIFY.hProcessor,
++                                  args->ARGS_PROC_REGISTER_NOTIFY.uEventMask,
++                                  args->ARGS_PROC_REGISTER_NOTIFY.uNotifyType,
++                                  &notification);
++      cp_to_usr(args->ARGS_PROC_REGISTER_NOTIFY.hNotification, &notification,
++               status, 1);
++      return status;
++}
++
++/*
++ * ======== PROCWRAP_ReserveMemory ========
++ */
++u32 PROCWRAP_ReserveMemory(union Trapped_Args *args)
++{
++      DSP_STATUS status;
++      void *pRsvAddr;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_ReserveMemory: entered\n");
++      status = PROC_ReserveMemory(args->ARGS_PROC_RSVMEM.hProcessor,
++                                 args->ARGS_PROC_RSVMEM.ulSize, &pRsvAddr);
++      if (put_user(pRsvAddr, args->ARGS_PROC_RSVMEM.ppRsvAddr))
++              status = DSP_EINVALIDARG;
++
++      return status;
++}
++
++/*
++ * ======== PROCWRAP_Start ========
++ */
++u32 PROCWRAP_Start(union Trapped_Args *args)
++{
++      u32 retVal;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_Start: entered\n");
++      retVal = PROC_Start(args->ARGS_PROC_START.hProcessor);
++      return retVal;
++}
++
++/*
++ * ======== PROCWRAP_UnMap ========
++ */
++u32 PROCWRAP_UnMap(union Trapped_Args *args)
++{
++      DSP_STATUS status;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_UnMap: entered\n");
++      status = PROC_UnMap(args->ARGS_PROC_UNMAPMEM.hProcessor,
++                         args->ARGS_PROC_UNMAPMEM.pMapAddr);
++      return status;
++}
++
++/*
++ * ======== PROCWRAP_UnReserveMemory ========
++ */
++u32 PROCWRAP_UnReserveMemory(union Trapped_Args *args)
++{
++      DSP_STATUS status;
++
++      GT_0trace(WCD_debugMask, GT_ENTER,
++               "PROCWRAP_UnReserveMemory: entered\n");
++      status = PROC_UnReserveMemory(args->ARGS_PROC_UNRSVMEM.hProcessor,
++                                   args->ARGS_PROC_UNRSVMEM.pRsvAddr);
++      return status;
++}
++
++/*
++ * ======== PROCWRAP_Stop ========
++ */
++u32 PROCWRAP_Stop(union Trapped_Args *args)
++{
++      u32 retVal;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_Stop: entered\n");
++      retVal = PROC_Stop(args->ARGS_PROC_STOP.hProcessor);
++
++      return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Allocate ========
++ */
++u32 NODEWRAP_Allocate(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DSP_UUID nodeId;
++      u32 cbDataSize;
++      u32 __user *pSize = (u32 __user *)args->ARGS_NODE_ALLOCATE.pArgs;
++      u8 *pArgs = NULL;
++      struct DSP_NODEATTRIN attrIn, *pAttrIn = NULL;
++      struct NODE_OBJECT *hNode;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Allocate: entered\n");
++
++      /* Optional argument */
++      if (pSize) {
++              if (get_user(cbDataSize, pSize))
++                      status = DSP_EFAIL;
++
++              cbDataSize += sizeof(u32);
++              if (DSP_SUCCEEDED(status)) {
++                      pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED);
++                      if (pArgs == NULL)
++                              status = DSP_EMEMORY;
++
++              }
++              cp_fm_usr(pArgs, args->ARGS_NODE_ALLOCATE.pArgs, status,
++                       cbDataSize);
++      }
++      cp_fm_usr(&nodeId, args->ARGS_NODE_ALLOCATE.pNodeID, status, 1);
++      /* Optional argument */
++      if (args->ARGS_NODE_ALLOCATE.pAttrIn) {
++              cp_fm_usr(&attrIn, args->ARGS_NODE_ALLOCATE.pAttrIn, status, 1);
++              if (DSP_SUCCEEDED(status))
++                      pAttrIn = &attrIn;
++
++      }
++      if (DSP_SUCCEEDED(status)) {
++              status = NODE_Allocate(args->ARGS_NODE_ALLOCATE.hProcessor,
++                                    &nodeId, (struct DSP_CBDATA *)pArgs,
++                                    pAttrIn, &hNode);
++      }
++      cp_to_usr(args->ARGS_NODE_ALLOCATE.phNode, &hNode, status, 1);
++      if (pArgs)
++              MEM_Free(pArgs);
++
++      return status;
++}
++
++/*
++ *  ======== NODEWRAP_AllocMsgBuf ========
++ */
++u32 NODEWRAP_AllocMsgBuf(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DSP_BUFFERATTR *pAttr = NULL;
++      struct DSP_BUFFERATTR attr;
++      u8 *pBuffer = NULL;
++
++      if (args->ARGS_NODE_ALLOCMSGBUF.pAttr) {        /* Optional argument */
++              cp_fm_usr(&attr, args->ARGS_NODE_ALLOCMSGBUF.pAttr, status, 1);
++              if (DSP_SUCCEEDED(status))
++                      pAttr = &attr;
++
++      }
++      /* IN OUT argument */
++      cp_fm_usr(&pBuffer, args->ARGS_NODE_ALLOCMSGBUF.pBuffer, status, 1);
++      if (DSP_SUCCEEDED(status)) {
++              status = NODE_AllocMsgBuf(args->ARGS_NODE_ALLOCMSGBUF.hNode,
++                                       args->ARGS_NODE_ALLOCMSGBUF.uSize,
++                                       pAttr, &pBuffer);
++      }
++      cp_to_usr(args->ARGS_NODE_ALLOCMSGBUF.pBuffer, &pBuffer, status, 1)
++      return status;
++}
++
++/*
++ * ======== NODEWRAP_ChangePriority ========
++ */
++u32 NODEWRAP_ChangePriority(union Trapped_Args *args)
++{
++      u32 retVal;
++
++      GT_0trace(WCD_debugMask, GT_ENTER,
++               "NODEWRAP_ChangePriority: entered\n");
++      retVal = NODE_ChangePriority(args->ARGS_NODE_CHANGEPRIORITY.hNode,
++                      args->ARGS_NODE_CHANGEPRIORITY.iPriority);
++
++      return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Connect ========
++ */
++u32 NODEWRAP_Connect(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DSP_STRMATTR attrs;
++      struct DSP_STRMATTR *pAttrs = NULL;
++      u32 cbDataSize;
++      u32 __user *pSize = (u32 __user *)args->ARGS_NODE_CONNECT.pConnParam;
++      u8 *pArgs = NULL;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Connect: entered\n");
++
++      /* Optional argument */
++      if (pSize) {
++              if (get_user(cbDataSize, pSize))
++                      status = DSP_EFAIL;
++
++              cbDataSize += sizeof(u32);
++              if (DSP_SUCCEEDED(status)) {
++                      pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED);
++                      if (pArgs == NULL)
++                              status = DSP_EMEMORY;
++
++              }
++              cp_fm_usr(pArgs, args->ARGS_NODE_CONNECT.pConnParam, status,
++                       cbDataSize);
++      }
++      if (args->ARGS_NODE_CONNECT.pAttrs) {   /* Optional argument */
++              cp_fm_usr(&attrs, args->ARGS_NODE_CONNECT.pAttrs, status, 1);
++              if (DSP_SUCCEEDED(status))
++                      pAttrs = &attrs;
++
++      }
++      if (DSP_SUCCEEDED(status)) {
++              status = NODE_Connect(args->ARGS_NODE_CONNECT.hNode,
++                                   args->ARGS_NODE_CONNECT.uStream,
++                                   args->ARGS_NODE_CONNECT.hOtherNode,
++                                   args->ARGS_NODE_CONNECT.uOtherStream,
++                                   pAttrs, (struct DSP_CBDATA *)pArgs);
++      }
++      if (pArgs)
++              MEM_Free(pArgs);
++
++      return status;
++}
++
++/*
++ * ======== NODEWRAP_Create ========
++ */
++u32 NODEWRAP_Create(union Trapped_Args *args)
++{
++      u32 retVal;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Create: entered\n");
++      retVal = NODE_Create(args->ARGS_NODE_CREATE.hNode);
++
++      return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Delete ========
++ */
++u32 NODEWRAP_Delete(union Trapped_Args *args)
++{
++      u32 retVal;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Delete: entered\n");
++      retVal = NODE_Delete(args->ARGS_NODE_DELETE.hNode);
++
++      return retVal;
++}
++
++/*
++ *  ======== NODEWRAP_FreeMsgBuf ========
++ */
++u32 NODEWRAP_FreeMsgBuf(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DSP_BUFFERATTR *pAttr = NULL;
++      struct DSP_BUFFERATTR attr;
++      if (args->ARGS_NODE_FREEMSGBUF.pAttr) { /* Optional argument */
++              cp_fm_usr(&attr, args->ARGS_NODE_FREEMSGBUF.pAttr, status, 1);
++              if (DSP_SUCCEEDED(status))
++                      pAttr = &attr;
++
++      }
++      if (DSP_SUCCEEDED(status)) {
++              status = NODE_FreeMsgBuf(args->ARGS_NODE_FREEMSGBUF.hNode,
++                                      args->ARGS_NODE_FREEMSGBUF.pBuffer,
++                                      pAttr);
++      }
++
++      return status;
++}
++
++/*
++ * ======== NODEWRAP_GetAttr ========
++ */
++u32 NODEWRAP_GetAttr(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DSP_NODEATTR attr;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_GetAttr: entered\n");
++
++      status = NODE_GetAttr(args->ARGS_NODE_GETATTR.hNode, &attr,
++                           args->ARGS_NODE_GETATTR.uAttrSize);
++      cp_to_usr(args->ARGS_NODE_GETATTR.pAttr, &attr, status, 1);
++
++      return status;
++}
++
++/*
++ * ======== NODEWRAP_GetMessage ========
++ */
++u32 NODEWRAP_GetMessage(union Trapped_Args *args)
++{
++      DSP_STATUS status;
++      struct DSP_MSG msg;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_GetMessage: entered\n");
++
++      status = NODE_GetMessage(args->ARGS_NODE_GETMESSAGE.hNode, &msg,
++                              args->ARGS_NODE_GETMESSAGE.uTimeout);
++
++      cp_to_usr(args->ARGS_NODE_GETMESSAGE.pMessage, &msg, status, 1);
++
++      return status;
++}
++
++/*
++ * ======== NODEWRAP_Pause ========
++ */
++u32 NODEWRAP_Pause(union Trapped_Args *args)
++{
++      u32 retVal;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Pause: entered\n");
++      retVal = NODE_Pause(args->ARGS_NODE_PAUSE.hNode);
++
++      return retVal;
++}
++
++/*
++ * ======== NODEWRAP_PutMessage ========
++ */
++u32 NODEWRAP_PutMessage(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DSP_MSG msg;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_PutMessage: entered\n");
++
++      cp_fm_usr(&msg, args->ARGS_NODE_PUTMESSAGE.pMessage, status, 1);
++
++      if (DSP_SUCCEEDED(status)) {
++              status = NODE_PutMessage(args->ARGS_NODE_PUTMESSAGE.hNode, &msg,
++                                      args->ARGS_NODE_PUTMESSAGE.uTimeout);
++      }
++
++      return status;
++}
++
++/*
++ * ======== NODEWRAP_RegisterNotify ========
++ */
++u32 NODEWRAP_RegisterNotify(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DSP_NOTIFICATION notification;
++
++      GT_0trace(WCD_debugMask, GT_ENTER,
++               "NODEWRAP_RegisterNotify: entered\n");
++
++      /* Initialize the notification data structure  */
++      notification.psName = NULL;
++      notification.handle = NULL;
++
++      status = NODE_RegisterNotify(args->ARGS_NODE_REGISTERNOTIFY.hNode,
++                                  args->ARGS_NODE_REGISTERNOTIFY.uEventMask,
++                                  args->ARGS_NODE_REGISTERNOTIFY.uNotifyType,
++                                  &notification);
++      cp_to_usr(args->ARGS_NODE_REGISTERNOTIFY.hNotification, &notification,
++               status, 1);
++      return status;
++}
++
++/*
++ * ======== NODEWRAP_Run ========
++ */
++u32 NODEWRAP_Run(union Trapped_Args *args)
++{
++      u32 retVal;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Run: entered\n");
++      retVal = NODE_Run(args->ARGS_NODE_RUN.hNode);
++
++      return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Terminate ========
++ */
++u32 NODEWRAP_Terminate(union Trapped_Args *args)
++{
++      DSP_STATUS status;
++      DSP_STATUS tempstatus;
++
++      GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Terminate: entered\n");
++
++      status = NODE_Terminate(args->ARGS_NODE_TERMINATE.hNode, &tempstatus);
++
++      cp_to_usr(args->ARGS_NODE_TERMINATE.pStatus, &tempstatus, status, 1);
++
++      return status;
++}
++
++
++/*
++ * ======== NODEWRAP_GetUUIDProps ========
++ */
++u32 NODEWRAP_GetUUIDProps(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DSP_UUID nodeId;
++      struct DSP_NDBPROPS    *pnodeProps = NULL;
++
++      GT_0trace(WCD_debugMask, GT_ENTER,
++               "NODEWRAP_GetUUIDPropste: entered\n");
++
++
++      cp_fm_usr(&nodeId, args->ARGS_NODE_GETUUIDPROPS.pNodeID, status, 1);
++      pnodeProps = MEM_Alloc(sizeof(struct DSP_NDBPROPS), MEM_NONPAGED);
++      if (pnodeProps != NULL) {
++              status = NODE_GetUUIDProps(args->
++                                        ARGS_NODE_GETUUIDPROPS.hProcessor,
++                                        &nodeId, pnodeProps);
++              cp_to_usr(args->ARGS_NODE_GETUUIDPROPS.pNodeProps, pnodeProps,
++                       status, 1);
++      }       else
++              status = DSP_EMEMORY;
++      if (pnodeProps)
++              MEM_Free(pnodeProps);
++      return status;
++}
++
++/*
++ * ======== STRMWRAP_AllocateBuffer ========
++ */
++u32 STRMWRAP_AllocateBuffer(union Trapped_Args *args)
++{
++      DSP_STATUS status;
++      u8 **apBuffer = NULL;
++      u32 uNumBufs = args->ARGS_STRM_ALLOCATEBUFFER.uNumBufs;
++
++      DBC_Require(uNumBufs <= MAX_BUFS);
++
++      apBuffer = MEM_Alloc((uNumBufs * sizeof(u8 *)), MEM_NONPAGED);
++
++      status = STRM_AllocateBuffer(args->ARGS_STRM_ALLOCATEBUFFER.hStream,
++                                   args->ARGS_STRM_ALLOCATEBUFFER.uSize,
++                                   apBuffer, uNumBufs);
++      cp_to_usr(args->ARGS_STRM_ALLOCATEBUFFER.apBuffer, apBuffer, status,
++               uNumBufs);
++      if (apBuffer)
++              MEM_Free(apBuffer);
++
++      return status;
++}
++
++/*
++ * ======== STRMWRAP_Close ========
++ */
++u32 STRMWRAP_Close(union Trapped_Args *args)
++{
++      u32 retVal;
++
++      retVal = STRM_Close(args->ARGS_STRM_CLOSE.hStream);
++
++      return retVal;
++}
++
++/*
++ * ======== STRMWRAP_FreeBuffer ========
++ */
++u32 STRMWRAP_FreeBuffer(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      u8 **apBuffer = NULL;
++      u32 uNumBufs = args->ARGS_STRM_FREEBUFFER.uNumBufs;
++
++      DBC_Require(uNumBufs <= MAX_BUFS);
++
++      apBuffer = MEM_Alloc((uNumBufs * sizeof(u8 *)), MEM_NONPAGED);
++
++      cp_fm_usr(apBuffer, args->ARGS_STRM_FREEBUFFER.apBuffer, status,
++               uNumBufs);
++
++      if (DSP_SUCCEEDED(status)) {
++              status = STRM_FreeBuffer(args->ARGS_STRM_FREEBUFFER.hStream,
++                                       apBuffer, uNumBufs);
++      }
++      cp_to_usr(args->ARGS_STRM_FREEBUFFER.apBuffer, apBuffer, status,
++               uNumBufs);
++      if (apBuffer)
++              MEM_Free(apBuffer);
++
++      return status;
++}
++
++/*
++ * ======== STRMWRAP_GetEventHandle ========
++ */
++u32 STRMWRAP_GetEventHandle(union Trapped_Args *args)
++{
++      return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== STRMWRAP_GetInfo ========
++ */
++u32 STRMWRAP_GetInfo(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct STRM_INFO strmInfo;
++      struct DSP_STREAMINFO user;
++      struct DSP_STREAMINFO *temp;
++
++      cp_fm_usr(&strmInfo, args->ARGS_STRM_GETINFO.pStreamInfo, status, 1);
++      temp = strmInfo.pUser;
++
++      strmInfo.pUser = &user;
++
++      if (DSP_SUCCEEDED(status)) {
++              status = STRM_GetInfo(args->ARGS_STRM_GETINFO.hStream,
++                       &strmInfo, args->ARGS_STRM_GETINFO.uStreamInfoSize);
++      }
++      cp_to_usr(temp, strmInfo.pUser, status, 1);
++      strmInfo.pUser = temp;
++      cp_to_usr(args->ARGS_STRM_GETINFO.pStreamInfo, &strmInfo, status, 1);
++      return status;
++}
++
++/*
++ * ======== STRMWRAP_Idle ========
++ */
++u32 STRMWRAP_Idle(union Trapped_Args *args)
++{
++      u32 retVal;
++
++      retVal = STRM_Idle(args->ARGS_STRM_IDLE.hStream,
++                      args->ARGS_STRM_IDLE.bFlush);
++
++      return retVal;
++}
++
++/*
++ * ======== STRMWRAP_Issue ========
++ */
++u32 STRMWRAP_Issue(union Trapped_Args *args)
++{
++      u32 retVal;
++
++      retVal = STRM_Issue(args->ARGS_STRM_ISSUE.hStream,
++                      args->ARGS_STRM_ISSUE.pBuffer,
++                      args->ARGS_STRM_ISSUE.dwBytes,
++                      args->ARGS_STRM_ISSUE.dwBufSize,
++                      args->ARGS_STRM_ISSUE.dwArg);
++
++      /* This is a user space pointer */
++      return retVal;
++}
++
++/*
++ * ======== STRMWRAP_Open ========
++ */
++u32 STRMWRAP_Open(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct STRM_ATTR attr;
++      struct STRM_OBJECT *pStrm;
++      struct DSP_STREAMATTRIN strmAttrIn;
++
++      cp_fm_usr(&attr, args->ARGS_STRM_OPEN.pAttrIn, status, 1);
++
++      if (attr.pStreamAttrIn != NULL) {       /* Optional argument */
++              cp_fm_usr(&strmAttrIn, attr.pStreamAttrIn, status, 1);
++              if (DSP_SUCCEEDED(status))
++                      attr.pStreamAttrIn = &strmAttrIn;
++
++      }
++      status = STRM_Open(args->ARGS_STRM_OPEN.hNode,
++                        args->ARGS_STRM_OPEN.uDirection,
++                        args->ARGS_STRM_OPEN.uIndex, &attr, &pStrm);
++      cp_to_usr(args->ARGS_STRM_OPEN.phStream, &pStrm, status, 1);
++      return status;
++}
++
++/*
++ * ======== STRMWRAP_Reclaim ========
++ */
++u32 STRMWRAP_Reclaim(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      u8 *pBufPtr;
++      u32 ulBytes;
++      u32 dwArg;
++      u32 ulBufSize;
++
++      status = STRM_Reclaim(args->ARGS_STRM_RECLAIM.hStream, &pBufPtr,
++                           &ulBytes, &ulBufSize, &dwArg);
++      cp_to_usr(args->ARGS_STRM_RECLAIM.pBufPtr, &pBufPtr, status, 1);
++      cp_to_usr(args->ARGS_STRM_RECLAIM.pBytes, &ulBytes, status, 1);
++      cp_to_usr(args->ARGS_STRM_RECLAIM.pdwArg, &dwArg, status, 1);
++
++      if (args->ARGS_STRM_RECLAIM.pBufSize != NULL) {
++              cp_to_usr(args->ARGS_STRM_RECLAIM.pBufSize, &ulBufSize,
++                       status, 1);
++      }
++
++      return status;
++}
++
++/*
++ * ======== STRMWRAP_RegisterNotify ========
++ */
++u32 STRMWRAP_RegisterNotify(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DSP_NOTIFICATION notification;
++
++      GT_0trace(WCD_debugMask, GT_ENTER,
++               "NODEWRAP_RegisterNotify: entered\n");
++
++      /* Initialize the notification data structure  */
++      notification.psName = NULL;
++      notification.handle = NULL;
++
++      status = STRM_RegisterNotify(args->ARGS_STRM_REGISTERNOTIFY.hStream,
++                                  args->ARGS_STRM_REGISTERNOTIFY.uEventMask,
++                                  args->ARGS_STRM_REGISTERNOTIFY.uNotifyType,
++                                  &notification);
++      cp_to_usr(args->ARGS_STRM_REGISTERNOTIFY.hNotification, &notification,
++               status, 1);
++
++      return status;
++}
++
++/*
++ * ======== STRMWRAP_Select ========
++ */
++u32 STRMWRAP_Select(union Trapped_Args *args)
++{
++      u32 mask;
++      struct STRM_OBJECT *aStrmTab[MAX_STREAMS];
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(args->ARGS_STRM_SELECT.nStreams <= MAX_STREAMS);
++
++      cp_fm_usr(aStrmTab, args->ARGS_STRM_SELECT.aStreamTab, status,
++               args->ARGS_STRM_SELECT.nStreams);
++      if (DSP_SUCCEEDED(status)) {
++              status = STRM_Select(aStrmTab, args->ARGS_STRM_SELECT.nStreams,
++                                  &mask, args->ARGS_STRM_SELECT.uTimeout);
++      }
++      cp_to_usr(args->ARGS_STRM_SELECT.pMask, &mask, status, 1);
++      return status;
++}
++
++/* CMM */
++
++/*
++ * ======== CMMWRAP_CallocBuf ========
++ */
++u32 CMMWRAP_CallocBuf(union Trapped_Args *args)
++{
++      /* This operation is done in kernel */
++      return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== CMMWRAP_FreeBuf ========
++ */
++u32 CMMWRAP_FreeBuf(union Trapped_Args *args)
++{
++      /* This operation is done in kernel */
++      return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== CMMWRAP_GetHandle ========
++ */
++u32 CMMWRAP_GetHandle(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct CMM_OBJECT *hCmmMgr;
++
++      status = CMM_GetHandle(args->ARGS_CMM_GETHANDLE.hProcessor, &hCmmMgr);
++
++      cp_to_usr(args->ARGS_CMM_GETHANDLE.phCmmMgr, &hCmmMgr, status, 1);
++
++      return status;
++}
++
++/*
++ * ======== CMMWRAP_GetInfo ========
++ */
++u32 CMMWRAP_GetInfo(union Trapped_Args *args)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct CMM_INFO cmmInfo;
++
++      status = CMM_GetInfo(args->ARGS_CMM_GETINFO.hCmmMgr, &cmmInfo);
++
++      cp_to_usr(args->ARGS_CMM_GETINFO.pCmmInfo, &cmmInfo, status, 1);
++
++      return status;
++}
+diff --git a/drivers/dsp/bridge/rmgr/dbdcd.c b/drivers/dsp/bridge/rmgr/dbdcd.c
+new file mode 100644
+index 0000000..c5ec8f9
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/dbdcd.c
+@@ -0,0 +1,1573 @@
++/*
++ * dbdcd.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dbdcd.c ========
++ *  Description:
++ *      This file contains the implementation of the DSP/BIOS Bridge
++ *      Configuration Database (DCD).
++ *
++ *  Notes:
++ *      The fxn DCD_GetObjects can apply a callback fxn to each DCD object
++ *      that is located in a specified COFF file.  At the moment,
++ *      DCD_AutoRegister, DCD_AutoUnregister, and NLDR module all use
++ *      DCD_GetObjects.
++ *
++ *! Revision History
++ *! ================
++ *! 03-Dec-2003 map Changed DCD_OBJTYPE to DSP_DCDOBJTYPE
++ *! 17-Dec-2002 map Modified DCD_GetDepLibs, DCD_GetNumDepLibs, GetDepLibInfo
++ *!                 to include phase information
++ *! 02-Dec-2002 map Modified DCD_GetLibraryName for phases in different
++ *!                 libraries
++ *! 26-Feb-2003 kc  Updated DCD_AutoUnregister and DCD_GetObjects to simplify
++ *!                 DCD implementation.
++ *! 17-Jul-2002 jeh Call COD_Open() instead of COD_OpenBase(), call COD_Close()
++ *! 11-Jul-2002 jeh Added DCD_GetDepLibs(), DCD_GetNumDepLibs().
++ *! 18-Feb-2003 vp  Code review updates
++ *! 18-Oct-2002 vp  Ported to Linux platform
++ *! 15-Mar-2002 jeh Read dynamic loading memory requirements into node object
++ *!                 data. Added DCD_GetLibraryName().
++ *! 13-Feb-2002 jeh Get system stack size in GetAttrsFromBuf().
++ *! 01-Aug-2001 ag: Added check for PROC "extended" attributes used for
++ *!                    DSP-MMU setup. These are private attributes.
++ *! 18-Apr-2001 jeh Use COD_OpenBase instead of COD_LoadBase.
++ *! 03-Apr-2001 sg: Changed error names to DSP_EDCD* format.
++ *! 11-Jan-2001 jeh Changes to DCD_GetObjectDef to match node.cdb, proc.cdb.
++ *! 12-Dec-2000 kc: Added DCD_AutoUnregister. MSGNODE, DAISNODE added in
++ *!                 GetAttrsFromBuf
++ *! 22-Nov-2000 kc: Replaced sprintf() calls with strncat.
++ *! 09-Nov-2000 kc: Optimized DCD module.
++ *! 30-Oct-2000 kc: Added DCD_AutoRegister function; changed local var. names.
++ *! 29-Sep-2000 kc: Added code review changes (src/reviews/dcd_reviews.txt).
++ *! 06-Sep-2000 jeh Get message segid, message notification type. Added Atoi()
++ *!                 to replace atoi(), until cdb generation can output in
++ *!                 decimal format.
++ *! 26-Jul-2000 kc: Created.
++ *!
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/reg.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++
++/*  ----------------------------------- Others */
++#include <dspbridge/uuidutil.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/dbdcd.h>
++
++/*  ----------------------------------- Global defines. */
++#define SIGNATURE       0x5f444344    /* "DCD_" (in reverse). */
++
++#define IsValidHandle(h)    (((h) != NULL) && (h->dwSignature == SIGNATURE))
++
++#define MAX_INT2CHAR_LENGTH     16   /* Maximum int2char len of 32 bit int. */
++
++/* Name of section containing dependent libraries */
++#define DEPLIBSECT              ".dspbridge_deplibs"
++
++/* DCD specific structures. */
++struct DCD_MANAGER {
++      u32 dwSignature;        /* Used for object validation.   */
++      struct COD_MANAGER *hCodMgr;    /* Handle to COD manager object. */
++};
++
++/* Global reference variables. */
++static u32 cRefs;
++static u32 cEnumRefs;
++
++extern struct GT_Mask curTrace;
++
++/* helper function prototypes. */
++static s32 Atoi(char *pszBuf);
++
++static DSP_STATUS GetAttrsFromBuf(char *pszBuf, u32 ulBufSize,
++                                enum DSP_DCDOBJTYPE objType,
++                                struct DCD_GENERICOBJ *pGenObj);
++
++static void CompressBuf(char *pszBuf, u32 ulBufSize, s32 cCharSize);
++
++static char DspChar2GppChar(char *pWord, s32 cDspCharSize);
++
++static DSP_STATUS GetDepLibInfo(IN struct DCD_MANAGER *hDcdMgr,
++                              IN struct DSP_UUID *pUuid,
++                              IN OUT u16 *pNumLibs,
++                              OPTIONAL OUT u16 *pNumPersLibs,
++                              OPTIONAL OUT struct DSP_UUID *pDepLibUuids,
++                              OPTIONAL OUT bool *pPersistentDepLibs,
++                              IN enum NLDR_PHASE phase);
++
++/*
++ *  ======== DCD_AutoRegister ========
++ *  Purpose:
++ *      Parses the supplied image and resigsters with DCD.
++ */
++
++DSP_STATUS DCD_AutoRegister(IN struct DCD_MANAGER *hDcdMgr,
++                          IN char *pszCoffPath)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++
++      GT_1trace(curTrace, GT_ENTER, "DCD_AutoRegister: hDcdMgr 0x%x\n",
++               hDcdMgr);
++
++      if (IsValidHandle(hDcdMgr)) {
++              status = DCD_GetObjects(hDcdMgr, pszCoffPath,
++                                      (DCD_REGISTERFXN)DCD_RegisterObject,
++                                      (void *)pszCoffPath);
++      } else {
++              status = DSP_EHANDLE;
++              GT_0trace(curTrace, GT_6CLASS,
++                       "DCD_AutoRegister: invalid DCD manager handle.\n");
++      }
++
++      return status;
++}
++
++/*
++ *  ======== DCD_AutoUnregister ========
++ *  Purpose:
++ *      Parses the supplied DSP image and unresiters from DCD.
++ */
++DSP_STATUS DCD_AutoUnregister(IN struct DCD_MANAGER *hDcdMgr,
++                           IN char *pszCoffPath)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++
++      GT_1trace(curTrace, GT_ENTER, "DCD_AutoUnregister: hDcdMgr 0x%x\n",
++               hDcdMgr);
++
++      if (IsValidHandle(hDcdMgr)) {
++              status = DCD_GetObjects(hDcdMgr, pszCoffPath,
++                                     (DCD_REGISTERFXN)DCD_RegisterObject,
++                                     NULL);
++      } else {
++              status = DSP_EHANDLE;
++              GT_0trace(curTrace, GT_6CLASS,
++                       "DCD_AutoUnregister: invalid DCD manager"
++                       " handle.\n");
++      }
++
++      return status;
++}
++
++/*
++ *  ======== DCD_CreateManager ========
++ *  Purpose:
++ *      Creates DCD manager.
++ */
++DSP_STATUS DCD_CreateManager(IN char *pszZlDllName,
++                          OUT struct DCD_MANAGER **phDcdMgr)
++{
++      struct COD_MANAGER *hCodMgr;    /* COD manager handle */
++      struct DCD_MANAGER *pDcdMgr = NULL;     /* DCD Manager pointer */
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs >= 0);
++      DBC_Require(phDcdMgr);
++
++      GT_1trace(curTrace, GT_ENTER, "DCD_CreateManager: phDcdMgr 0x%x\n",
++               phDcdMgr);
++
++      status = COD_Create(&hCodMgr, pszZlDllName, NULL);
++      if (DSP_SUCCEEDED(status)) {
++
++              /* Create a DCD object. */
++              MEM_AllocObject(pDcdMgr, struct DCD_MANAGER, SIGNATURE);
++              if (pDcdMgr != NULL) {
++
++                      /* Fill out the object. */
++                      pDcdMgr->hCodMgr = hCodMgr;
++
++                      /* Return handle to this DCD interface. */
++                      *phDcdMgr = pDcdMgr;
++
++                      GT_2trace(curTrace, GT_5CLASS,
++                               "DCD_CreateManager: pDcdMgr 0x%x, "
++                               " hCodMgr 0x%x", pDcdMgr, hCodMgr);
++              } else {
++                      status = DSP_EMEMORY;
++
++                      /*
++                       * If allocation of DcdManager object failed, delete the
++                       * COD manager.
++                       */
++                      COD_Delete(hCodMgr);
++
++                      GT_0trace(curTrace, GT_6CLASS,
++                               "DCD_CreateManager: MEM_AllocObject failed\n");
++              }
++      } else {
++              status = DSP_EFAIL;
++              GT_0trace(curTrace, GT_6CLASS,
++                       "DCD_CreateManager: COD_Create failed\n");
++      }
++
++      DBC_Ensure((DSP_SUCCEEDED(status)) || ((hCodMgr == NULL) &&
++                (status == DSP_EFAIL)) || ((pDcdMgr == NULL) &&
++                (status == DSP_EMEMORY)));
++
++      return status;
++}
++
++/*
++ *  ======== DCD_DestroyManager ========
++ *  Purpose:
++ *      Frees DCD Manager object.
++ */
++DSP_STATUS DCD_DestroyManager(IN struct DCD_MANAGER *hDcdMgr)
++{
++      struct DCD_MANAGER *pDcdMgr = hDcdMgr;
++      DSP_STATUS status = DSP_EHANDLE;
++
++      DBC_Require(cRefs >= 0);
++
++      GT_1trace(curTrace, GT_ENTER, "DCD_DestroyManager: hDcdMgr 0x%x\n",
++               hDcdMgr);
++
++      if (IsValidHandle(hDcdMgr)) {
++
++              /* Delete the COD manager. */
++              COD_Delete(pDcdMgr->hCodMgr);
++
++              /* Deallocate a DCD manager object. */
++              MEM_FreeObject(pDcdMgr);
++
++              status = DSP_SOK;
++      } else {
++              GT_0trace(curTrace, GT_6CLASS,
++                       "DCD_DestroyManager: invalid DCD manager handle.\n");
++      }
++
++      return status;
++}
++
++/*
++ *  ======== DCD_EnumerateObject ========
++ *  Purpose:
++ *      Enumerates objects in the DCD.
++ */
++DSP_STATUS DCD_EnumerateObject(IN s32 cIndex, IN enum DSP_DCDOBJTYPE objType,
++                             OUT struct DSP_UUID *pUuid)
++{
++      DSP_STATUS status = DSP_SOK;
++      char szRegKey[REG_MAXREGPATHLENGTH];
++      char szValue[REG_MAXREGPATHLENGTH];
++      char szData[REG_MAXREGPATHLENGTH];
++      u32 dwValueSize;
++      u32 dwDataSize;
++      struct DSP_UUID dspUuid;
++      char szObjType[MAX_INT2CHAR_LENGTH];    /* str. rep. of objType. */
++      u32 dwKeyLen = 0;
++
++      DBC_Require(cRefs >= 0);
++      DBC_Require(cIndex >= 0);
++      DBC_Require(pUuid != NULL);
++
++      GT_3trace(curTrace, GT_ENTER,
++               "DCD_EnumerateObject: cIndex %d, objType %d, "
++               " pUuid 0x%x\n", cIndex, objType, pUuid);
++
++      if ((cIndex != 0) && (cEnumRefs == 0)) {
++              /*
++               * If an enumeration is being performed on an index greater
++               * than zero, then the current cEnumRefs must have been
++               * incremented to greater than zero.
++               */
++              status = DSP_ECHANGEDURINGENUM;
++      } else {
++              /* Enumerate a specific key in the registry by index. */
++              dwValueSize = REG_MAXREGPATHLENGTH;
++              dwDataSize = REG_MAXREGPATHLENGTH;
++
++              /*
++               * Pre-determine final key length. It's length of DCD_REGKEY +
++               *  "_\0" + length of szObjType string + terminating NULL.
++               */
++               dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++              DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++
++              /* Create proper REG key; concatenate DCD_REGKEY with
++               * objType. */
++               strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++               if ((strlen(szRegKey) + strlen("_\0")) <
++                 REG_MAXREGPATHLENGTH) {
++                       strncat(szRegKey, "_\0", 2);
++              } else {
++                      status = DSP_EFAIL;
++              }
++
++              /* This snprintf is guaranteed not to exceed max size of an
++               * integer. */
++              status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d",
++                               objType);
++
++              if (status == -1) {
++                      status = DSP_EFAIL;
++              } else {
++                      status = DSP_SOK;
++                       if ((strlen(szRegKey) + strlen(szObjType)) <
++                         REG_MAXREGPATHLENGTH) {
++                               strncat(szRegKey, szObjType,
++                                          strlen(szObjType) + 1);
++                      } else {
++                              status = DSP_EFAIL;
++                      }
++              }
++
++              if (DSP_SUCCEEDED(status)) {
++                      status = REG_EnumValue(NULL, cIndex, szRegKey, szValue,
++                                            &dwValueSize, szData,
++                                            &dwDataSize);
++              }
++
++              if (DSP_SUCCEEDED(status)) {
++                      /* Create UUID value using string retrieved from
++                       * registry. */
++                      UUID_UuidFromString(szValue, &dspUuid);
++
++                      *pUuid = dspUuid;
++
++                      /* Increment cEnumRefs to update reference count. */
++                      cEnumRefs++;
++
++                      status = DSP_SOK;
++              } else if (status == REG_E_NOMOREITEMS) {
++                      /* At the end of enumeration. Reset cEnumRefs. */
++                      cEnumRefs = 0;
++
++                      status = DSP_SENUMCOMPLETE;
++              } else {
++                      status = DSP_EFAIL;
++                      GT_1trace(curTrace, GT_6CLASS,
++                               "DCD_EnumerateObject: REG_EnumValue"
++                               " failed, status = 0x%x\n", status);
++              }
++      }
++
++      DBC_Ensure(pUuid || (status == DSP_EFAIL));
++
++      return status;
++}
++
++/*
++ *  ======== DCD_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the DCD module.
++ */
++void DCD_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      GT_1trace(curTrace, GT_5CLASS, "DCD_Exit: cRefs 0x%x\n", cRefs);
++
++      cRefs--;
++      if (cRefs == 0) {
++              REG_Exit();
++              COD_Exit();
++              MEM_Exit();
++      }
++
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== DCD_GetDepLibs ========
++ */
++DSP_STATUS DCD_GetDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++                       IN struct DSP_UUID *pUuid,
++                       u16 numLibs, OUT struct DSP_UUID *pDepLibUuids,
++                       OUT bool *pPersistentDepLibs, IN enum NLDR_PHASE phase)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(IsValidHandle(hDcdMgr));
++      DBC_Require(pUuid != NULL);
++      DBC_Require(pDepLibUuids != NULL);
++      DBC_Require(pPersistentDepLibs != NULL);
++
++      GT_1trace(curTrace, GT_ENTER, "DCD_GetDepLibs: hDcdMgr 0x%x\n",
++               hDcdMgr);
++
++      status = GetDepLibInfo(hDcdMgr, pUuid, &numLibs, NULL, pDepLibUuids,
++                            pPersistentDepLibs, phase);
++
++      return status;
++}
++
++/*
++ *  ======== DCD_GetNumDepLibs ========
++ */
++DSP_STATUS DCD_GetNumDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++                          IN struct DSP_UUID *pUuid, OUT u16 *pNumLibs,
++                          OUT u16 *pNumPersLibs, IN enum NLDR_PHASE phase)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(IsValidHandle(hDcdMgr));
++      DBC_Require(pNumLibs != NULL);
++      DBC_Require(pNumPersLibs != NULL);
++      DBC_Require(pUuid != NULL);
++
++      GT_1trace(curTrace, GT_ENTER, "DCD_GetNumDepLibs: hDcdMgr 0x%x\n",
++               hDcdMgr);
++
++      status = GetDepLibInfo(hDcdMgr, pUuid, pNumLibs, pNumPersLibs,
++                            NULL, NULL, phase);
++
++      return status;
++}
++
++/*
++ *  ======== DCD_GetObjectDef ========
++ *  Purpose:
++ *      Retrieves the properties of a node or processor based on the UUID and
++ *      object type.
++ */
++DSP_STATUS DCD_GetObjectDef(IN struct DCD_MANAGER *hDcdMgr,
++                         IN struct DSP_UUID *pObjUuid,
++                         IN enum DSP_DCDOBJTYPE objType,
++                         OUT struct DCD_GENERICOBJ *pObjDef)
++{
++      struct DCD_MANAGER *pDcdMgr = hDcdMgr;  /* pointer to DCD manager */
++      struct COD_LIBRARYOBJ *lib = NULL;
++      DSP_STATUS status = DSP_SOK;
++      u32 ulAddr = 0; /* Used by COD_GetSection */
++      u32 ulLen = 0;  /* Used by COD_GetSection */
++      u32 dwBufSize;  /* Used by REG functions */
++      char szRegKey[REG_MAXREGPATHLENGTH];
++      char *szUuid;           /*[MAXUUIDLEN];*/
++      char szRegData[REG_MAXREGPATHLENGTH];
++      char szSectName[MAXUUIDLEN + 2];        /* ".[UUID]\0" */
++      char *pszCoffBuf;
++      u32 dwKeyLen;           /* Len of REG key. */
++      char szObjType[MAX_INT2CHAR_LENGTH];    /* str. rep. of objType. */
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pObjDef != NULL);
++      DBC_Require(pObjUuid != NULL);
++
++      GT_4trace(curTrace, GT_ENTER,
++               "DCD_GetObjectDef: hDcdMgr 0x%x, " "objUuid"
++               " 0x%x, objType 0x%x, pObjDef 0x%x\n", hDcdMgr, pObjUuid,
++               objType, pObjDef);
++      szUuid = (char *)MEM_Calloc(MAXUUIDLEN, MEM_PAGED);
++      if (!szUuid)
++              return status = DSP_EMEMORY;
++
++      if (!IsValidHandle(hDcdMgr)) {
++              status = DSP_EHANDLE;
++              GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: invalid "
++                       "DCD manager handle.\n");
++              goto func_end;
++      }
++       /* Pre-determine final key length. It's length of DCD_REGKEY +
++       *  "_\0" + length of szObjType string + terminating NULL */
++       dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++      DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++      /* Create proper REG key; concatenate DCD_REGKEY with objType. */
++       strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++
++       if ((strlen(szRegKey) + strlen("_\0")) < REG_MAXREGPATHLENGTH)
++               strncat(szRegKey, "_\0", 2);
++      else
++              status = DSP_EFAIL;
++
++      status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d", objType);
++      if (status == -1) {
++              status = DSP_EFAIL;
++      } else {
++              status = DSP_SOK;
++
++               if ((strlen(szRegKey) + strlen(szObjType)) <
++                 REG_MAXREGPATHLENGTH) {
++                       strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++              } else {
++                      status = DSP_EFAIL;
++              }
++              /* Create UUID value to set in registry. */
++              UUID_UuidToString(pObjUuid, szUuid, MAXUUIDLEN);
++
++               if ((strlen(szRegKey) + MAXUUIDLEN) < REG_MAXREGPATHLENGTH)
++                       strncat(szRegKey, szUuid, MAXUUIDLEN);
++               else
++                      status = DSP_EFAIL;
++
++              /* Retrieve paths from the registry based on struct DSP_UUID */
++              dwBufSize = REG_MAXREGPATHLENGTH;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              status = REG_GetValue(NULL, szRegKey, szRegKey, (u8 *)szRegData,
++                                   &dwBufSize);
++      }
++      if (DSP_FAILED(status)) {
++              status = DSP_EUUID;
++              GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++                       "REG_GetValue() failed\n");
++              goto func_end;
++      }
++      /* Open COFF file. */
++      status = COD_Open(pDcdMgr->hCodMgr, szRegData, COD_NOLOAD, &lib);
++      if (DSP_FAILED(status)) {
++              status = DSP_EDCDLOADBASE;
++              GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++                       "COD_OpenBase() failed\n");
++              goto func_end;
++      }
++      /* Ensure szUuid + 1 is not greater than sizeof szSectName. */
++       DBC_Assert((strlen(szUuid) + 1) < sizeof(szSectName));
++      /* Create section name based on node UUID. A period is
++       * pre-pended to the UUID string to form the section name.
++       * I.e. ".24BC8D90_BB45_11d4_B756_006008BDB66F" */
++       strncpy(szSectName, ".", 2);
++       strncat(szSectName, szUuid, strlen(szUuid));
++      /* Get section information. */
++      status = COD_GetSection(lib, szSectName, &ulAddr, &ulLen);
++      if (DSP_FAILED(status)) {
++              status = DSP_EDCDGETSECT;
++              GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef:"
++                       " COD_GetSection() failed\n");
++              goto func_end;
++      }
++      /* Allocate zeroed buffer. */
++      pszCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
++#ifdef _DB_TIOMAP
++       if (strstr(szRegData, "iva") == NULL) {
++              /* Locate section by objectID and read its content. */
++              status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
++      } else {
++              status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
++              GT_0trace(curTrace, GT_4CLASS,
++                       "Skipped Byte swap for IVA !!\n");
++      }
++#else
++      status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
++#endif
++      if (DSP_SUCCEEDED(status)) {
++              /* Compres DSP buffer to conform to PC format. */
++               if (strstr(szRegData, "iva") == NULL) {
++                      CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
++              } else {
++                      CompressBuf(pszCoffBuf, ulLen, 1);
++                      GT_0trace(curTrace, GT_4CLASS, "Compressing IVA "
++                               "COFF buffer by 1 for IVA !!\n");
++              }
++              /* Parse the content of the COFF buffer. */
++              status = GetAttrsFromBuf(pszCoffBuf, ulLen, objType, pObjDef);
++              if (DSP_FAILED(status)) {
++                      status = DSP_EDCDPARSESECT;
++                      GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++                               "GetAttrsFromBuf() failed\n");
++              }
++      } else {
++              status = DSP_EDCDREADSECT;
++              GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++                       "COD_ReadSection() failed\n");
++      }
++      /* Free the previously allocated dynamic buffer. */
++      MEM_Free(pszCoffBuf);
++func_end:
++      if (lib)
++              COD_Close(lib);
++
++      if (szUuid)
++              MEM_Free(szUuid);
++      return status;
++}
++
++/*
++ *  ======== DCD_GetObjects ========
++ */
++DSP_STATUS DCD_GetObjects(IN struct DCD_MANAGER *hDcdMgr, IN char *pszCoffPath,
++                       DCD_REGISTERFXN registerFxn, void *handle)
++{
++      struct DCD_MANAGER *pDcdMgr = hDcdMgr;  /* pointer to DCD manager */
++      DSP_STATUS status = DSP_SOK;
++      char *pszCoffBuf;
++      char *pszCur;
++      struct COD_LIBRARYOBJ *lib = NULL;
++      u32 ulAddr = 0; /* Used by COD_GetSection */
++      u32 ulLen = 0;  /* Used by COD_GetSection */
++      char seps[] = ":, ";
++      char *pToken = NULL;
++      struct DSP_UUID dspUuid;
++      s32 cObjectType;
++
++      DBC_Require(cRefs > 0);
++      GT_1trace(curTrace, GT_ENTER,
++               "DCD_GetObjects: hDcdMgr 0x%x\n", hDcdMgr);
++      if (!IsValidHandle(hDcdMgr)) {
++              status = DSP_EHANDLE;
++              GT_0trace(curTrace, GT_6CLASS,
++                       "DCD_GetObjects: invalid DCD manager handle.\n");
++              goto func_end;
++      }
++      /* Open DSP coff file, don't load symbols. */
++      status = COD_Open(pDcdMgr->hCodMgr, pszCoffPath, COD_NOLOAD, &lib);
++      if (DSP_FAILED(status)) {
++              status = DSP_EDCDLOADBASE;
++              GT_0trace(curTrace, GT_6CLASS,
++                       "DCD_AutoRegister: COD_Open() failed\n");
++              goto func_cont;
++      }
++      /* Get DCD_RESIGER_SECTION section information. */
++      status = COD_GetSection(lib, DCD_REGISTER_SECTION, &ulAddr, &ulLen);
++      if (DSP_FAILED(status) ||  !(ulLen > 0)) {
++              status = DSP_EDCDNOAUTOREGISTER;
++              GT_0trace(curTrace, GT_6CLASS,
++                       "DCD_GetObjects: COD_GetSection() "
++                       "- no auto register section\n");
++              goto func_cont;
++      }
++      /* Allocate zeroed buffer. */
++      pszCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
++#ifdef _DB_TIOMAP
++      if (strstr(pszCoffPath, "iva") == NULL) {
++              /* Locate section by objectID and read its content. */
++              status = COD_ReadSection(lib, DCD_REGISTER_SECTION,
++                                      pszCoffBuf, ulLen);
++      } else {
++              GT_0trace(curTrace, GT_4CLASS, "Skipped Byte swap for IVA!!\n");
++              status = COD_ReadSection(lib, DCD_REGISTER_SECTION,
++                                      pszCoffBuf, ulLen);
++      }
++#else
++      status = COD_ReadSection(lib, DCD_REGISTER_SECTION, pszCoffBuf, ulLen);
++#endif
++      if (DSP_SUCCEEDED(status)) {
++              /* Compress DSP buffer to conform to PC format. */
++              GT_0trace(curTrace, GT_4CLASS,
++                       "Successfully read section !!\n");
++              if (strstr(pszCoffPath, "iva") == NULL) {
++                      CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
++              } else {
++                      CompressBuf(pszCoffBuf, ulLen, 1);
++                      GT_0trace(curTrace, GT_4CLASS, "Compress COFF buffer "
++                               "with 1 word for IVA !!\n");
++              }
++              /* Read from buffer and register object in buffer. */
++              pszCur = pszCoffBuf;
++              while ((pToken = strsep(&pszCur, seps)) && *pToken != '\0') {
++                      /*  Retrieve UUID string. */
++                      UUID_UuidFromString(pToken, &dspUuid);
++                      /*  Retrieve object type */
++                      pToken = strsep(&pszCur, seps);
++                      /*  Retrieve object type */
++                      cObjectType = Atoi(pToken);
++                      /*
++                       *  Apply registerFxn to the found DCD object.
++                       *  Possible actions include:
++                       *
++                       *  1) Register found DCD object.
++                       *  2) Unregister found DCD object (when handle == NULL)
++                       *  3) Add overlay node.
++                       */
++                      GT_1trace(curTrace, GT_4CLASS, "Registering objtype "
++                               "%d \n", cObjectType);
++                      status = registerFxn(&dspUuid, cObjectType, handle);
++                      if (DSP_SUCCEEDED(status)) {
++                              GT_1trace(curTrace, GT_5CLASS,
++                                       "DCD_GetObjects: status 0x%x\n",
++                                       status);
++                      } else {
++                              GT_0trace(curTrace, GT_6CLASS,
++                                       "DCD_GetObjects: "
++                                       "registration() failed\n");
++                              /* if error occurs, break from while loop. */
++                              break;
++                      }
++              }
++      } else {
++              status = DSP_EDCDREADSECT;
++              GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjects: "
++                       "COD_ReadSection() failed\n");
++      }
++      /* Free the previously allocated dynamic buffer. */
++      MEM_Free(pszCoffBuf);
++func_cont:
++      if (lib)
++              COD_Close(lib);
++
++func_end:
++      return status;
++}
++
++/*
++ *  ======== DCD_GetLibraryName ========
++ *  Purpose:
++ *      Retrieves the library name for the given UUID.
++ *
++ */
++DSP_STATUS DCD_GetLibraryName(IN struct DCD_MANAGER *hDcdMgr,
++                           IN struct DSP_UUID *pUuid,
++                           IN OUT char *pstrLibName, IN OUT u32 *pdwSize,
++                           enum NLDR_PHASE phase, OUT bool *fPhaseSplit)
++{
++      char szRegKey[REG_MAXREGPATHLENGTH];
++      char szUuid[MAXUUIDLEN];
++      u32 dwKeyLen;           /* Len of REG key. */
++      char szObjType[MAX_INT2CHAR_LENGTH];    /* str. rep. of objType. */
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(pUuid != NULL);
++      DBC_Require(pstrLibName != NULL);
++      DBC_Require(pdwSize != NULL);
++      DBC_Require(IsValidHandle(hDcdMgr));
++
++      GT_4trace(curTrace, GT_ENTER,
++               "DCD_GetLibraryName: hDcdMgr 0x%x, pUuid 0x%x, "
++               " pstrLibName 0x%x, pdwSize 0x%x\n", hDcdMgr, pUuid,
++               pstrLibName, pdwSize);
++      /*
++       *  Pre-determine final key length. It's length of DCD_REGKEY +
++       *  "_\0" + length of szObjType string + terminating NULL.
++       */
++       dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++      DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++      /* Create proper REG key; concatenate DCD_REGKEY with objType. */
++       strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++       if ((strlen(szRegKey) + strlen("_\0")) < REG_MAXREGPATHLENGTH)
++               strncat(szRegKey, "_\0", 2);
++      else
++              status = DSP_EFAIL;
++
++      switch (phase) {
++      case NLDR_CREATE:
++              /* create phase type */
++              sprintf(szObjType, "%d", DSP_DCDCREATELIBTYPE);
++              break;
++      case NLDR_EXECUTE:
++              /* execute phase type */
++              sprintf(szObjType, "%d", DSP_DCDEXECUTELIBTYPE);
++              break;
++      case NLDR_DELETE:
++              /* delete phase type */
++              sprintf(szObjType, "%d", DSP_DCDDELETELIBTYPE);
++              break;
++      case NLDR_NOPHASE:
++              /* known to be a dependent library */
++              sprintf(szObjType, "%d", DSP_DCDLIBRARYTYPE);
++              break;
++      default:
++              status = -1;
++              DBC_Assert(false);
++      }
++      if (status == -1) {
++              status = DSP_EFAIL;
++      } else {
++              status = DSP_SOK;
++               if ((strlen(szRegKey) + strlen(szObjType))
++                 < REG_MAXREGPATHLENGTH) {
++                       strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++              } else {
++                      status = DSP_EFAIL;
++              }
++              /* Create UUID value to find match in registry. */
++              UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
++               if ((strlen(szRegKey) + MAXUUIDLEN) <
++                 REG_MAXREGPATHLENGTH) {
++                       strncat(szRegKey, szUuid, MAXUUIDLEN);
++              } else {
++                      status = DSP_EFAIL;
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Retrieve path from the registry based on DSP_UUID */
++              status = REG_GetValue(NULL, szRegKey, szRegKey,
++                                      (u8 *)pstrLibName, pdwSize);
++      }
++      /* If can't find, phases might be registered as generic LIBRARYTYPE */
++      if (DSP_FAILED(status) && phase != NLDR_NOPHASE) {
++              if (fPhaseSplit)
++                      *fPhaseSplit = false;
++
++               strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++               if ((strlen(szRegKey) + strlen("_\0")) <
++                 REG_MAXREGPATHLENGTH) {
++                       strncat(szRegKey, "_\0", 2);
++              } else {
++                      status = DSP_EFAIL;
++              }
++              sprintf(szObjType, "%d", DSP_DCDLIBRARYTYPE);
++               if ((strlen(szRegKey) + strlen(szObjType))
++                 < REG_MAXREGPATHLENGTH) {
++                       strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++              } else {
++                      status = DSP_EFAIL;
++              }
++              UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
++               if ((strlen(szRegKey) + MAXUUIDLEN) < REG_MAXREGPATHLENGTH)
++                       strncat(szRegKey, szUuid, MAXUUIDLEN);
++               else
++                      status = DSP_EFAIL;
++
++              status = REG_GetValue(NULL, szRegKey, szRegKey,
++                                      (u8 *)pstrLibName, pdwSize);
++      }
++
++      return status;
++}
++
++/*
++ *  ======== DCD_Init ========
++ *  Purpose:
++ *      Initialize the DCD module.
++ */
++bool DCD_Init(void)
++{
++      bool fInitMEM;
++      bool fInitREG;
++      bool fInitCOD;
++      bool fInit = true;
++
++      DBC_Require(cRefs >= 0);
++
++      GT_1trace(curTrace, GT_ENTER, "DCD_Init: (on enter) cRefs = 0x%x\n",
++               cRefs);
++
++      if (cRefs == 0) {
++
++              /* Initialize required modules. */
++              fInitMEM = MEM_Init();
++              fInitCOD = COD_Init();
++              fInitREG = REG_Init();
++              if (!fInitMEM || !fInitCOD || !fInitREG) {
++                      fInit = false;
++                      GT_0trace(curTrace, GT_6CLASS, "DCD_Init failed\n");
++                      /* Exit initialized modules. */
++                      if (fInitMEM)
++                              MEM_Exit();
++
++                      if (fInitCOD)
++                              COD_Exit();
++
++                      if (fInitREG)
++                              REG_Exit();
++
++              }
++      }
++
++      if (fInit)
++              cRefs++;
++
++
++      GT_1trace(curTrace, GT_5CLASS, "DCD_Init: (on exit) cRefs = 0x%x\n",
++               cRefs);
++
++      DBC_Ensure((fInit && (cRefs > 0)) || (!fInit && (cRefs == 0)));
++
++      return fInit;
++}
++
++/*
++ *  ======== DCD_RegisterObject ========
++ *  Purpose:
++ *      Registers a node or a processor with the DCD.
++ *      If pszPathName == NULL, unregister the specified DCD object.
++ */
++DSP_STATUS DCD_RegisterObject(IN struct DSP_UUID *pUuid,
++                           IN enum DSP_DCDOBJTYPE objType,
++                           IN char *pszPathName)
++{
++      DSP_STATUS status = DSP_SOK;
++      char szRegKey[REG_MAXREGPATHLENGTH];
++      char szUuid[MAXUUIDLEN + 1];
++      u32 dwPathSize = 0;
++      u32 dwKeyLen;           /* Len of REG key. */
++      char szObjType[MAX_INT2CHAR_LENGTH];    /* str. rep. of objType. */
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pUuid != NULL);
++      DBC_Require((objType == DSP_DCDNODETYPE) ||
++                 (objType == DSP_DCDPROCESSORTYPE) ||
++                 (objType == DSP_DCDLIBRARYTYPE) ||
++                 (objType == DSP_DCDCREATELIBTYPE) ||
++                 (objType == DSP_DCDEXECUTELIBTYPE) ||
++                 (objType == DSP_DCDDELETELIBTYPE));
++
++      GT_3trace(curTrace, GT_ENTER, "DCD_RegisterObject: object UUID 0x%x, "
++               "objType %d, szPathName %s\n", pUuid, objType, pszPathName);
++      /*
++       * Pre-determine final key length. It's length of DCD_REGKEY +
++       *  "_\0" + length of szObjType string + terminating NULL.
++       */
++       dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++      DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++      /* Create proper REG key; concatenate DCD_REGKEY with objType. */
++       strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++       if ((strlen(szRegKey) + strlen("_\0")) < REG_MAXREGPATHLENGTH)
++               strncat(szRegKey, "_\0", 2);
++      else
++              status = DSP_EFAIL;
++
++      status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d", objType);
++      if (status == -1) {
++              status = DSP_EFAIL;
++      } else {
++              status = DSP_SOK;
++               if ((strlen(szRegKey) + strlen(szObjType)) <
++                 REG_MAXREGPATHLENGTH) {
++                       strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++              } else {
++                      status = DSP_EFAIL;
++              }
++              /* Create UUID value to set in registry. */
++              UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
++               if ((strlen(szRegKey) + MAXUUIDLEN) < REG_MAXREGPATHLENGTH)
++                       strncat(szRegKey, szUuid, MAXUUIDLEN);
++               else
++                      status = DSP_EFAIL;
++
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              /*
++               * If pszPathName != NULL, perform registration, otherwise,
++               * perform unregistration.
++               */
++              if (pszPathName) {
++                      /* Add new reg value (UUID+objType) with COFF path
++                       * info. */
++                       dwPathSize = strlen(pszPathName) + 1;
++                      status = REG_SetValue(NULL, szRegKey, szRegKey, REG_SZ,
++                                           (u8 *)pszPathName, dwPathSize);
++                      GT_3trace(curTrace, GT_6CLASS,
++                               "REG_SetValue  REG_SZ=%d, "
++                               "(u8 *)pszPathName=%s, dwPathSize=%d\n",
++                               REG_SZ, pszPathName, dwPathSize);
++                      if (DSP_FAILED(status)) {
++                              status = DSP_EFAIL;
++                              GT_0trace(curTrace, GT_6CLASS,
++                                "DCD_RegisterObject: REG_SetValue failed!\n");
++                      }
++              } else {
++                      /* Deregister an existing object. */
++                      status = REG_DeleteValue(NULL, szRegKey, szRegKey);
++                      if (DSP_FAILED(status)) {
++                              status = DSP_EFAIL;
++                              GT_0trace(curTrace, GT_6CLASS,
++                                      "DCD_UnregisterObject: "
++                                      "REG_DeleteValue failed!\n");
++                      }
++              }
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              /*
++               *  Because the node database has been updated through a
++               *  successful object registration/de-registration operation,
++               *  we need to reset the object enumeration counter to allow
++               *  current enumerations to reflect this update in the node
++               *  database.
++               */
++
++              cEnumRefs = 0;
++      }
++
++      return status;
++}
++
++/*
++ *  ======== DCD_UnregisterObject ========
++ *  Call DCD_Register object with pszPathName set to NULL to
++ *  perform actual object de-registration.
++ */
++DSP_STATUS DCD_UnregisterObject(IN struct DSP_UUID *pUuid,
++                              IN enum DSP_DCDOBJTYPE objType)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pUuid != NULL);
++      DBC_Require((objType == DSP_DCDNODETYPE) ||
++                 (objType == DSP_DCDPROCESSORTYPE) ||
++                 (objType == DSP_DCDLIBRARYTYPE) ||
++                 (objType == DSP_DCDCREATELIBTYPE) ||
++                 (objType == DSP_DCDEXECUTELIBTYPE) ||
++                 (objType == DSP_DCDDELETELIBTYPE));
++
++      GT_2trace(curTrace, GT_ENTER,
++               "DCD_UnregisterObject: object UUID 0x%x, "
++               "objType %d\n", pUuid, objType);
++
++      /*
++       *  When DCD_RegisterObject is called with NULL as pathname,
++       *  it indicates an unregister object operation.
++       */
++      status = DCD_RegisterObject(pUuid, objType, NULL);
++
++      return status;
++}
++
++/*
++ **********************************************************************
++ * DCD Helper Functions
++ **********************************************************************
++ */
++
++/*
++ *  ======== Atoi ========
++ *  Purpose:
++ *      This function converts strings in decimal or hex format to integers.
++ */
++static s32 Atoi(char *pszBuf)
++{
++      s32 result = 0;
++      char *pch = pszBuf;
++      char c;
++      char first;
++      s32 base = 10;
++      s32 len;
++
++      while (isspace(*pch))
++              pch++;
++
++      first = *pch;
++      if (first == '-' || first == '+') {
++              pch++;
++      } else {
++              /* Determine if base 10 or base 16 */
++              len = strlen(pch);
++              if (len  > 1) {
++                      c = pch[1];
++                      if ((*pch == '0' && (c == 'x' || c == 'X'))) {
++                              base = 16;
++                              pch += 2;
++                      }
++                      c = pch[len - 1];
++                      if (c == 'h' || c == 'H')
++                              base = 16;
++
++              }
++      }
++
++      while (isdigit(c = *pch) || ((base == 16) && isxdigit(c))) {
++              result *= base;
++              if ('A' <= c && c <= 'F') {
++                      c = c - 'A' + 10;
++              } else {
++                      if ('a' <= c && c <= 'f')
++                              c = c - 'a' + 10;
++                      else
++                              c -= '0';
++
++              }
++              result += c;
++              ++pch;
++      }
++
++      return result;
++}
++
++/*
++ *  ======== GetAttrsFromBuf ========
++ *  Purpose:
++ *      Parse the content of a buffer filled with DSP-side data and
++ *      retrieve an object's attributes from it. IMPORTANT: Assume the
++ *      buffer has been converted from DSP format to GPP format.
++ */
++static DSP_STATUS GetAttrsFromBuf(char *pszBuf, u32 ulBufSize,
++                               enum DSP_DCDOBJTYPE objType,
++                               struct DCD_GENERICOBJ *pGenObj)
++{
++      DSP_STATUS status = DSP_SOK;
++      char seps[] = ", ";
++      char *pszCur;
++      char *token;
++      s32 cLen = 0;
++      u32 i = 0;
++#ifdef _DB_TIOMAP
++      s32 iEntry;
++#endif
++
++      DBC_Require(pszBuf != NULL);
++      DBC_Require(ulBufSize != 0);
++      DBC_Require((objType == DSP_DCDNODETYPE)
++                  || (objType == DSP_DCDPROCESSORTYPE));
++      DBC_Require(pGenObj != NULL);
++
++
++      switch (objType) {
++      case DSP_DCDNODETYPE:
++              /*
++               * Parse COFF sect buffer to retrieve individual tokens used
++               * to fill in object attrs.
++               */
++              pszCur = pszBuf;
++              token = strsep(&pszCur, seps);
++
++              /* u32 cbStruct */
++              pGenObj->objData.nodeObj.ndbProps.cbStruct =
++                              (u32) Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              /* DSP_UUID uiNodeID */
++              UUID_UuidFromString(token,
++                                &pGenObj->objData.nodeObj.ndbProps.uiNodeID);
++              token = strsep(&pszCur, seps);
++
++              /* acName */
++               DBC_Require(token);
++              cLen = strlen(token);
++              if (cLen > DSP_MAXNAMELEN - 1)
++                      cLen = DSP_MAXNAMELEN - 1;
++
++               strncpy(pGenObj->objData.nodeObj.ndbProps.acName,
++                         token, cLen);
++              pGenObj->objData.nodeObj.ndbProps.acName[cLen] = '\0';
++              token = strsep(&pszCur, seps);
++              /* u32 uNodeType */
++              pGenObj->objData.nodeObj.ndbProps.uNodeType = Atoi(token);
++              token = strsep(&pszCur, seps);
++              /* u32 bCacheOnGPP */
++              pGenObj->objData.nodeObj.ndbProps.bCacheOnGPP = Atoi(token);
++              token = strsep(&pszCur, seps);
++              /* DSP_RESOURCEREQMTS dspResourceReqmts */
++              pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.cbStruct =
++                              (u32) Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++                      uStaticDataSize = Atoi(token);
++              token = strsep(&pszCur, seps);
++              pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++                      uGlobalDataSize = Atoi(token);
++              token = strsep(&pszCur, seps);
++              pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++                      uProgramMemSize = Atoi(token);
++              token = strsep(&pszCur, seps);
++              pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++                      uWCExecutionTime = Atoi(token);
++              token = strsep(&pszCur, seps);
++              pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++                      uWCPeriod = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++                      uWCDeadline = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++                      uAvgExectionTime = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++                      uMinimumPeriod = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              /* s32 iPriority */
++              pGenObj->objData.nodeObj.ndbProps.iPriority = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              /* u32 uStackSize */
++              pGenObj->objData.nodeObj.ndbProps.uStackSize = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              /* u32 uSysStackSize */
++              pGenObj->objData.nodeObj.ndbProps.uSysStackSize = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              /* u32 uStackSeg */
++              pGenObj->objData.nodeObj.ndbProps.uStackSeg = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              /* u32 uMessageDepth */
++              pGenObj->objData.nodeObj.ndbProps.uMessageDepth = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              /* u32 uNumInputStreams */
++              pGenObj->objData.nodeObj.ndbProps.uNumInputStreams =
++                      Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              /* u32 uNumOutputStreams */
++              pGenObj->objData.nodeObj.ndbProps.uNumOutputStreams =
++                      Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              /* u32 uTimeout */
++              pGenObj->objData.nodeObj.ndbProps.uTimeout =
++                      Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              /* char * pstrCreatePhaseFxn */
++               DBC_Require(token);
++              cLen = strlen(token);
++              pGenObj->objData.nodeObj.pstrCreatePhaseFxn =
++                      MEM_Calloc(cLen + 1, MEM_PAGED);
++              strncpy(pGenObj->objData.nodeObj.pstrCreatePhaseFxn,
++                      token, cLen);
++              pGenObj->objData.nodeObj.pstrCreatePhaseFxn[cLen] = '\0';
++              token = strsep(&pszCur, seps);
++
++              /* char * pstrExecutePhaseFxn */
++               DBC_Require(token);
++              cLen = strlen(token);
++              pGenObj->objData.nodeObj.pstrExecutePhaseFxn =
++                       MEM_Calloc(cLen + 1, MEM_PAGED);
++              strncpy(pGenObj->objData.nodeObj.pstrExecutePhaseFxn,
++                      token, cLen);
++              pGenObj->objData.nodeObj.pstrExecutePhaseFxn[cLen] = '\0';
++              token = strsep(&pszCur, seps);
++
++              /* char * pstrDeletePhaseFxn */
++               DBC_Require(token);
++              cLen = strlen(token);
++              pGenObj->objData.nodeObj.pstrDeletePhaseFxn =
++                      MEM_Calloc(cLen + 1, MEM_PAGED);
++              strncpy(pGenObj->objData.nodeObj.pstrDeletePhaseFxn,
++                      token, cLen);
++              pGenObj->objData.nodeObj.pstrDeletePhaseFxn[cLen] = '\0';
++              token = strsep(&pszCur, seps);
++
++              /* Segment id for message buffers */
++              pGenObj->objData.nodeObj.uMsgSegid = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              /* Message notification type */
++              pGenObj->objData.nodeObj.uMsgNotifyType = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              /* char * pstrIAlgName */
++              if (token) {
++                      cLen = strlen(token);
++                      pGenObj->objData.nodeObj.pstrIAlgName =
++                              MEM_Calloc(cLen + 1, MEM_PAGED);
++                      strncpy(pGenObj->objData.nodeObj.pstrIAlgName,
++                              token, cLen);
++                      pGenObj->objData.nodeObj.pstrIAlgName[cLen] = '\0';
++                      token = strsep(&pszCur, seps);
++              }
++
++              /* Load type (static, dynamic, or overlay) */
++              if (token) {
++                      pGenObj->objData.nodeObj.usLoadType = Atoi(token);
++                      token = strsep(&pszCur, seps);
++              }
++
++              /* Dynamic load data requirements */
++              if (token) {
++                      pGenObj->objData.nodeObj.ulDataMemSegMask = Atoi(token);
++                      token = strsep(&pszCur, seps);
++              }
++
++              /* Dynamic load code requirements */
++              if (token) {
++                      pGenObj->objData.nodeObj.ulCodeMemSegMask = Atoi(token);
++                      token = strsep(&pszCur, seps);
++              }
++
++              /* Extract node profiles into node properties */
++              if (token) {
++
++                      pGenObj->objData.nodeObj.ndbProps.uCountProfiles =
++                              Atoi(token);
++                      for (i = 0; i < pGenObj->objData.nodeObj.ndbProps.
++                          uCountProfiles; i++) {
++                              token = strsep(&pszCur, seps);
++                              if (token) {
++                                      /* Heap Size for the node */
++                                      pGenObj->objData.nodeObj.ndbProps.
++                                              aProfiles[i].ulHeapSize =
++                                              Atoi(token);
++                              }
++                      }
++              }
++              token = strsep(&pszCur, seps);
++              if (token) {
++                      pGenObj->objData.nodeObj.ndbProps.uStackSegName =
++                              (u32)(token);
++              }
++
++              break;
++
++      case DSP_DCDPROCESSORTYPE:
++              /*
++               * Parse COFF sect buffer to retrieve individual tokens used
++               * to fill in object attrs.
++               */
++              pszCur = pszBuf;
++              token = strsep(&pszCur, seps);
++
++              pGenObj->objData.procObj.cbStruct = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              pGenObj->objData.procObj.uProcessorFamily = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              pGenObj->objData.procObj.uProcessorType = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              pGenObj->objData.procObj.uClockRate = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              pGenObj->objData.procObj.ulInternalMemSize = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              pGenObj->objData.procObj.ulExternalMemSize = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              pGenObj->objData.procObj.uProcessorID = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              pGenObj->objData.procObj.tyRunningRTOS = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              pGenObj->objData.procObj.nNodeMinPriority = Atoi(token);
++              token = strsep(&pszCur, seps);
++
++              pGenObj->objData.procObj.nNodeMaxPriority = Atoi(token);
++
++#ifdef _DB_TIOMAP
++              /* Proc object may contain additional(extended) attributes. */
++              /* attr must match proc.hxx */
++              for (iEntry = 0; iEntry < 7; iEntry++) {
++                      token = strsep(&pszCur, seps);
++                      pGenObj->objData.extProcObj.tyTlb[iEntry].ulGppPhys =
++                              Atoi(token);
++
++                      token = strsep(&pszCur, seps);
++                      pGenObj->objData.extProcObj.tyTlb[iEntry].ulDspVirt =
++                              Atoi(token);
++              }
++#endif
++
++              break;
++
++      default:
++              status = DSP_EFAIL;
++              break;
++      }
++
++      return status;
++}
++
++/*
++ *  ======== CompressBuffer ========
++ *  Purpose:
++ *      Compress the DSP buffer, if necessary, to conform to PC format.
++ */
++static void CompressBuf(char *pszBuf, u32 ulBufSize, s32 cCharSize)
++{
++      char *p;
++      char ch;
++      char *q;
++
++      p = pszBuf;
++      if (p == NULL)
++              return;
++
++      for (q = pszBuf; q < (pszBuf + ulBufSize);) {
++
++              ch = DspChar2GppChar(q, cCharSize);
++              if (ch == '\\') {
++                      q += cCharSize;
++                      ch = DspChar2GppChar(q, cCharSize);
++                      switch (ch) {
++                      case 't':
++                              *p = '\t';
++                              break;
++
++                      case 'n':
++                              *p = '\n';
++                              break;
++
++                      case 'r':
++                              *p = '\r';
++                              break;
++
++                      case '0':
++                              *p = '\0';
++                              break;
++
++                      default:
++                              *p = ch;
++                              break;
++                      }
++              } else {
++                      *p = ch;
++              }
++              p++;
++              q += cCharSize;
++      }
++
++      /* NULL out remainder of buffer. */
++      while (p < q)
++              *p++ = '\0';
++
++}
++
++/*
++ *  ======== DspChar2GppChar ========
++ *  Purpose:
++ *      Convert DSP char to host GPP char in a portable manner
++ */
++static char DspChar2GppChar(char *pWord, s32 cDspCharSize)
++{
++      char ch = '\0';
++      char *chSrc;
++      s32 i;
++
++      for (chSrc = pWord, i = cDspCharSize; i > 0; i--)
++              ch |= *chSrc++;
++
++      return ch;
++}
++
++/*
++ *  ======== GetDepLibInfo ========
++ */
++static DSP_STATUS GetDepLibInfo(IN struct DCD_MANAGER *hDcdMgr,
++                              IN struct DSP_UUID *pUuid,
++                              IN OUT u16 *pNumLibs,
++                              OPTIONAL OUT u16 *pNumPersLibs,
++                              OPTIONAL OUT struct DSP_UUID *pDepLibUuids,
++                              OPTIONAL OUT bool *pPersistentDepLibs,
++                              enum NLDR_PHASE phase)
++{
++      struct DCD_MANAGER *pDcdMgr = hDcdMgr;  /* pointer to DCD manager */
++      char *pszCoffBuf = NULL;
++      char *pszCur;
++      char *pszFileName = NULL;
++      struct COD_LIBRARYOBJ *lib = NULL;
++      u32 ulAddr = 0; /* Used by COD_GetSection */
++      u32 ulLen = 0;  /* Used by COD_GetSection */
++      u32 dwDataSize = COD_MAXPATHLENGTH;
++      char seps[] = ", ";
++      char *pToken = NULL;
++      bool fGetUuids = (pDepLibUuids != NULL);
++      u16 nDepLibs = 0;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++
++      DBC_Require(IsValidHandle(hDcdMgr));
++      DBC_Require(pNumLibs != NULL);
++      DBC_Require(pUuid != NULL);
++
++      GT_1trace(curTrace, GT_ENTER, "DCD_GetNumDepLibs: hDcdMgr 0x%x\n",
++               hDcdMgr);
++
++      /*  Initialize to 0 dependent libraries, if only counting number of
++       *  dependent libraries */
++      if (!fGetUuids) {
++              *pNumLibs = 0;
++              *pNumPersLibs = 0;
++      }
++
++      /* Allocate a buffer for file name */
++      pszFileName = MEM_Calloc(dwDataSize, MEM_PAGED);
++      if (pszFileName == NULL) {
++              status = DSP_EMEMORY;
++      } else {
++              /* Get the name of the library */
++              status = DCD_GetLibraryName(hDcdMgr, pUuid, pszFileName,
++                       &dwDataSize, phase, NULL);
++      }
++      /* Open the library */
++      if (DSP_SUCCEEDED(status)) {
++              status = COD_Open(pDcdMgr->hCodMgr, pszFileName,
++                               COD_NOLOAD, &lib);
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Get dependent library section information. */
++              status = COD_GetSection(lib, DEPLIBSECT, &ulAddr, &ulLen);
++
++              if (DSP_FAILED(status)) {
++                      /* Ok, no dependent libraries */
++                      ulLen = 0;
++                      status = DSP_SNODEPENDENTLIBS;
++              }
++      }
++
++      if (DSP_FAILED(status) || !(ulLen > 0))
++              goto func_cont;
++
++      /* Allocate zeroed buffer. */
++      pszCoffBuf = MEM_Calloc(ulLen, MEM_PAGED);
++      if (pszCoffBuf == NULL)
++              status = DSP_EMEMORY;
++
++      /* Read section contents. */
++      status = COD_ReadSection(lib, DEPLIBSECT, pszCoffBuf, ulLen);
++      if (DSP_FAILED(status))
++              goto func_cont;
++
++      /* Compress and format DSP buffer to conform to PC format. */
++      CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
++      /* Read from buffer */
++      pszCur = pszCoffBuf;
++      while ((pToken = strsep(&pszCur, seps)) && *pToken != '\0') {
++              if (fGetUuids) {
++                      if (nDepLibs >= *pNumLibs) {
++                              /* Gone beyond the limit */
++                              break;
++                      } else {
++                              /* Retrieve UUID string. */
++                              UUID_UuidFromString(pToken,
++                                               &(pDepLibUuids[nDepLibs]));
++                              /* Is this library persistent? */
++                              pToken = strsep(&pszCur, seps);
++                              pPersistentDepLibs[nDepLibs] = Atoi(pToken);
++                              nDepLibs++;
++                      }
++              } else {
++                      /* Advanc to next token */
++                      pToken = strsep(&pszCur, seps);
++                      if (Atoi(pToken))
++                              (*pNumPersLibs)++;
++
++                      /* Just counting number of dependent libraries */
++                      (*pNumLibs)++;
++              }
++      }
++func_cont:
++      if (lib)
++              COD_Close(lib);
++
++      /* Free previously allocated dynamic buffers. */
++      if (pszFileName)
++              MEM_Free(pszFileName);
++
++      if (pszCoffBuf)
++              MEM_Free(pszCoffBuf);
++
++      return status;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/disp.c b/drivers/dsp/bridge/rmgr/disp.c
+new file mode 100644
+index 0000000..3fbbf01
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/disp.c
+@@ -0,0 +1,916 @@
++/*
++ * disp.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software;  you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== disp.c ========
++ *
++ *  Description:
++ *      Node Dispatcher interface. Communicates with Resource Manager Server
++ *      (RMS) on DSP. Access to RMS is synchronized in NODE.
++ *
++ *  Public Functions:
++ *      DISP_Create
++ *      DISP_Delete
++ *      DISP_Exit
++ *      DISP_Init
++ *      DISP_NodeChangePriority
++ *      DISP_NodeCreate
++ *      DISP_NodeDelete
++ *      DISP_NodePause
++ *      DISP_NodeRun
++ *
++ *! Revision History:
++ *! =================
++ *! 18-Feb-2003 vp      Code review updates
++ *! 18-Oct-2002 vp      Ported to Linux platform
++ *! 16-May-2002 jeh     Added DISP_DoCinit().
++ *! 24-Apr-2002 jeh     Added DISP_MemWrite().
++ *! 13-Feb-2002 jeh     Pass system stack size to RMS.
++ *! 16-Jan-2002  ag     Added bufsize param to _ChnlAddIOReq() fxn
++ *! 10-May-2001 jeh     Code Review cleanup.
++ *! 26-Sep-2000 jeh     Fixed status values in SendMessage().
++ *! 19-Jun-2000 jeh     Created.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++#include <dspbridge/dbc.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/dev.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/csl.h>
++
++/*  ----------------------------------- Link Driver */
++#include <dspbridge/wmd.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/chnldefs.h>
++
++/*  ----------------------------------- Resource Manager */
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/rms_sh.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/disp.h>
++
++#define DISP_SIGNATURE       0x50534944       /* "PSID" */
++
++/* Size of a reply from RMS */
++#define REPLYSIZE (3 * sizeof(RMS_WORD))
++
++/* Reserved channel offsets for communication with RMS */
++#define CHNLTORMSOFFSET       0
++#define CHNLFROMRMSOFFSET     1
++
++#define CHNLIOREQS      1
++
++#define SwapWord(x)     (((u32)(x) >> 16) | ((u32)(x) << 16))
++
++/*
++ *  ======== DISP_OBJECT ========
++ */
++struct DISP_OBJECT {
++      u32 dwSignature;        /* Used for object validation */
++      struct DEV_OBJECT *hDevObject;  /* Device for this processor */
++      struct WMD_DRV_INTERFACE *pIntfFxns;    /* Function interface to WMD */
++      struct CHNL_MGR *hChnlMgr;      /* Channel manager */
++      struct CHNL_OBJECT *hChnlToDsp;   /* Channel for commands to RMS */
++      struct CHNL_OBJECT *hChnlFromDsp;   /* Channel for replies from RMS */
++      u8 *pBuf;               /* Buffer for commands, replies */
++      u32 ulBufsize;  /* pBuf size in bytes */
++      u32 ulBufsizeRMS;       /* pBuf size in RMS words */
++      u32 uCharSize;          /* Size of DSP character */
++      u32 uWordSize;          /* Size of DSP word */
++      u32 uDataMauSize;       /* Size of DSP Data MAU */
++};
++
++static u32 cRefs;
++
++/* Debug msgs: */
++#if GT_TRACE
++static struct GT_Mask DISP_DebugMask = { NULL, NULL };
++#endif
++
++static void DeleteDisp(struct DISP_OBJECT *hDisp);
++static DSP_STATUS FillStreamDef(RMS_WORD *pdwBuf, u32 *ptotal, u32 offset,
++                              struct NODE_STRMDEF strmDef, u32 max,
++                              u32 uCharsInRMSWord);
++static DSP_STATUS SendMessage(struct DISP_OBJECT *hDisp, u32 dwTimeout,
++                           u32 ulBytes, OUT u32 *pdwArg);
++
++/*
++ *  ======== DISP_Create ========
++ *  Create a NODE Dispatcher object.
++ */
++DSP_STATUS DISP_Create(OUT struct DISP_OBJECT **phDispObject,
++                    struct DEV_OBJECT *hDevObject,
++                    IN CONST struct DISP_ATTRS *pDispAttrs)
++{
++      struct DISP_OBJECT *pDisp;
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      u32 ulChnlId;
++      struct CHNL_ATTRS chnlAttrs;
++      DSP_STATUS status = DSP_SOK;
++      u32 devType;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phDispObject != NULL);
++      DBC_Require(pDispAttrs != NULL);
++      DBC_Require(hDevObject != NULL);
++
++      GT_3trace(DISP_DebugMask, GT_ENTER, "DISP_Create: phDispObject: 0x%x\t"
++               "hDevObject: 0x%x\tpDispAttrs: 0x%x\n", phDispObject,
++               hDevObject, pDispAttrs);
++
++      *phDispObject = NULL;
++
++      /* Allocate Node Dispatcher object */
++      MEM_AllocObject(pDisp, struct DISP_OBJECT, DISP_SIGNATURE);
++      if (pDisp == NULL) {
++              status = DSP_EMEMORY;
++              GT_0trace(DISP_DebugMask, GT_6CLASS,
++                       "DISP_Create: MEM_AllocObject() failed!\n");
++      } else {
++              pDisp->hDevObject = hDevObject;
++      }
++
++      /* Get Channel manager and WMD function interface */
++      if (DSP_SUCCEEDED(status)) {
++              status = DEV_GetChnlMgr(hDevObject, &(pDisp->hChnlMgr));
++              if (DSP_SUCCEEDED(status)) {
++                      (void) DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++                      pDisp->pIntfFxns = pIntfFxns;
++              } else {
++                      GT_1trace(DISP_DebugMask, GT_6CLASS,
++                               "DISP_Create: Failed to get "
++                               "channel manager! status = 0x%x\n", status);
++              }
++      }
++
++      /* check device type and decide if streams or messag'ing is used for
++       * RMS/EDS */
++      if (DSP_FAILED(status))
++              goto func_cont;
++
++      status = DEV_GetDevType(hDevObject, &devType);
++      GT_1trace(DISP_DebugMask, GT_6CLASS, "DISP_Create: Creating DISP for "
++               "device = 0x%x\n", devType);
++      if (DSP_FAILED(status))
++              goto func_cont;
++
++      if (devType != DSP_UNIT) {
++              GT_0trace(DISP_DebugMask, GT_6CLASS,
++                       "DISP_Create: Unkown device "
++                       "type in Device object !! \n");
++              status = DSP_EFAIL;
++              goto func_cont;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              pDisp->uCharSize = DSPWORDSIZE;
++              pDisp->uWordSize = DSPWORDSIZE;
++              pDisp->uDataMauSize = DSPWORDSIZE;
++              /* Open channels for communicating with the RMS */
++              chnlAttrs.uIOReqs = CHNLIOREQS;
++              chnlAttrs.hEvent = NULL;
++              ulChnlId = pDispAttrs->ulChnlOffset + CHNLTORMSOFFSET;
++              status = (*pIntfFxns->pfnChnlOpen)(&(pDisp->hChnlToDsp),
++                       pDisp->hChnlMgr, CHNL_MODETODSP, ulChnlId, &chnlAttrs);
++              if (DSP_FAILED(status)) {
++                      GT_2trace(DISP_DebugMask, GT_6CLASS,
++                               "DISP_Create:  Channel to RMS "
++                               "open failed, chnl id = %d, status = 0x%x\n",
++                               ulChnlId, status);
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              ulChnlId = pDispAttrs->ulChnlOffset + CHNLFROMRMSOFFSET;
++              status = (*pIntfFxns->pfnChnlOpen)(&(pDisp->hChnlFromDsp),
++                       pDisp->hChnlMgr, CHNL_MODEFROMDSP, ulChnlId,
++                       &chnlAttrs);
++              if (DSP_FAILED(status)) {
++                      GT_2trace(DISP_DebugMask, GT_6CLASS,
++                               "DISP_Create: Channel from RMS "
++                               "open failed, chnl id = %d, status = 0x%x\n",
++                               ulChnlId, status);
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Allocate buffer for commands, replies */
++              pDisp->ulBufsize = pDispAttrs->ulChnlBufSize;
++              pDisp->ulBufsizeRMS = RMS_COMMANDBUFSIZE;
++              pDisp->pBuf = MEM_Calloc(pDisp->ulBufsize, MEM_PAGED);
++              if (pDisp->pBuf == NULL) {
++                      status = DSP_EMEMORY;
++                      GT_0trace(DISP_DebugMask, GT_6CLASS,
++                               "DISP_Create: Failed "
++                               "to allocate channel buffer!\n");
++              }
++      }
++func_cont:
++      if (DSP_SUCCEEDED(status))
++              *phDispObject = pDisp;
++      else
++              DeleteDisp(pDisp);
++
++      DBC_Ensure(((DSP_FAILED(status)) && ((*phDispObject == NULL))) ||
++                ((DSP_SUCCEEDED(status)) &&
++                (MEM_IsValidHandle((*phDispObject), DISP_SIGNATURE))));
++      return status;
++}
++
++/*
++ *  ======== DISP_Delete ========
++ *  Delete the NODE Dispatcher.
++ */
++void DISP_Delete(struct DISP_OBJECT *hDisp)
++{
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++
++      GT_1trace(DISP_DebugMask, GT_ENTER,
++               "DISP_Delete: hDisp: 0x%x\n", hDisp);
++
++      DeleteDisp(hDisp);
++
++      DBC_Ensure(!MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++}
++
++/*
++ *  ======== DISP_Exit ========
++ *  Discontinue usage of DISP module.
++ */
++void DISP_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      cRefs--;
++
++      GT_1trace(DISP_DebugMask, GT_5CLASS,
++               "Entered DISP_Exit, ref count:  0x%x\n", cRefs);
++
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== DISP_Init ========
++ *  Initialize the DISP module.
++ */
++bool DISP_Init(void)
++{
++      bool fRetVal = true;
++
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++              DBC_Assert(!DISP_DebugMask.flags);
++              GT_create(&DISP_DebugMask, "DI");  /* "DI" for DIspatcher */
++      }
++
++      if (fRetVal)
++              cRefs++;
++
++      GT_1trace(DISP_DebugMask, GT_5CLASS,
++               "DISP_Init(), ref count:  0x%x\n", cRefs);
++
++      DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
++      return fRetVal;
++}
++
++/*
++ *  ======== DISP_NodeChangePriority ========
++ *  Change the priority of a node currently running on the target.
++ */
++DSP_STATUS DISP_NodeChangePriority(struct DISP_OBJECT *hDisp,
++                                struct NODE_OBJECT *hNode,
++                                u32 ulRMSFxn, NODE_ENV nodeEnv,
++                                s32 nPriority)
++{
++      u32 dwArg;
++      struct RMS_Command *pCommand;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++      DBC_Require(hNode != NULL);
++
++      GT_5trace(DISP_DebugMask, GT_ENTER, "DISP_NodeChangePriority: hDisp: "
++              "0x%x\thNode: 0x%x\tulRMSFxn: 0x%x\tnodeEnv: 0x%x\tnPriority\n",
++              hDisp, hNode, ulRMSFxn, nodeEnv, nPriority);
++
++      /* Send message to RMS to change priority */
++      pCommand = (struct RMS_Command *)(hDisp->pBuf);
++      pCommand->fxn = (RMS_WORD)(ulRMSFxn);
++      pCommand->arg1 = (RMS_WORD)nodeEnv;
++      pCommand->arg2 = nPriority;
++      status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++               sizeof(struct RMS_Command), &dwArg);
++      if (DSP_FAILED(status)) {
++              GT_1trace(DISP_DebugMask, GT_6CLASS,
++                       "DISP_NodeChangePriority failed! "
++                       "status = 0x%x\n", status);
++      }
++      return status;
++}
++
++/*
++ *  ======== DISP_NodeCreate ========
++ *  Create a node on the DSP by remotely calling the node's create function.
++ */
++DSP_STATUS DISP_NodeCreate(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
++                        u32 ulRMSFxn, u32 ulCreateFxn,
++                        IN CONST struct NODE_CREATEARGS *pArgs,
++                        OUT NODE_ENV *pNodeEnv)
++{
++      struct NODE_MSGARGS msgArgs;
++      struct NODE_TASKARGS taskArgs;
++      struct RMS_Command *pCommand;
++      struct RMS_MsgArgs *pMsgArgs;
++      struct RMS_MoreTaskArgs *pMoreTaskArgs;
++      enum NODE_TYPE nodeType;
++      u32 dwLength;
++      RMS_WORD *pdwBuf = NULL;
++      u32 ulBytes;
++      u32 i;
++      u32 total;
++      u32 uCharsInRMSWord;
++      s32 taskArgsOffset;
++      s32 sioInDefOffset;
++      s32 sioOutDefOffset;
++      s32 sioDefsOffset;
++      s32 argsOffset = -1;
++      s32 offset;
++      struct NODE_STRMDEF strmDef;
++      u32 max;
++      DSP_STATUS status = DSP_SOK;
++      struct DSP_NODEINFO nodeInfo;
++      u32 devType;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++      DBC_Require(hNode != NULL);
++      DBC_Require(NODE_GetType(hNode) != NODE_DEVICE);
++      DBC_Require(pNodeEnv != NULL);
++
++      GT_6trace(DISP_DebugMask, GT_ENTER,
++           "DISP_NodeCreate: hDisp: 0x%x\thNode:"
++           " 0x%x\tulRMSFxn: 0x%x\tulCreateFxn: 0x%x\tpArgs: 0x%x\tpNodeEnv:"
++           " 0x%x\n", hDisp, hNode, ulRMSFxn, ulCreateFxn, pArgs, pNodeEnv);
++
++      status = DEV_GetDevType(hDisp->hDevObject, &devType);
++
++      GT_1trace(DISP_DebugMask, GT_6CLASS, "DISP_Create: Creating DISP "
++               "for device = 0x%x\n", devType);
++
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      if (devType != DSP_UNIT) {
++              GT_1trace(DISP_DebugMask, GT_7CLASS,
++                       "DISP_NodeCreate unknown device "
++                       "type = 0x%x\n", devType);
++              goto func_end;
++      }
++      DBC_Require(pArgs != NULL);
++      nodeType = NODE_GetType(hNode);
++      msgArgs = pArgs->asa.msgArgs;
++      max = hDisp->ulBufsizeRMS;    /*Max # of RMS words that can be sent */
++      DBC_Assert(max == RMS_COMMANDBUFSIZE);
++      uCharsInRMSWord = sizeof(RMS_WORD) / hDisp->uCharSize;
++      /* Number of RMS words needed to hold arg data */
++      dwLength = (msgArgs.uArgLength + uCharsInRMSWord - 1) / uCharsInRMSWord;
++      /* Make sure msg args and command fit in buffer */
++      total = sizeof(struct RMS_Command) / sizeof(RMS_WORD) +
++              sizeof(struct RMS_MsgArgs)
++              / sizeof(RMS_WORD)  - 1 + dwLength;
++      if (total >= max) {
++              status = DSP_EFAIL;
++              GT_2trace(DISP_DebugMask, GT_6CLASS,
++                      "DISP_NodeCreate: Message args too"
++                      " large for buffer! Message args size = %d, max = %d\n",
++                      total, max);
++      }
++      /*
++       *  Fill in buffer to send to RMS.
++       *  The buffer will have the following  format:
++       *
++       *  RMS command:
++       *      Address of RMS_CreateNode()
++       *      Address of node's create function
++       *      dummy argument
++       *      node type
++       *
++       *  Message Args:
++       *      max number of messages
++       *      segid for message buffer allocation
++       *      notification type to use when message is received
++       *      length of message arg data
++       *      message args data
++       *
++       *  Task Args (if task or socket node):
++       *      priority
++       *      stack size
++       *      system stack size
++       *      stack segment
++       *      misc
++       *      number of input streams
++       *      pSTRMInDef[] - offsets of STRM definitions for input streams
++       *      number of output streams
++       *      pSTRMOutDef[] - offsets of STRM definitions for output
++       *      streams
++       *      STRMInDef[] - array of STRM definitions for input streams
++       *      STRMOutDef[] - array of STRM definitions for output streams
++       *
++       *  Socket Args (if DAIS socket node):
++       *
++       */
++      if (DSP_SUCCEEDED(status)) {
++              total = 0;      /* Total number of words in buffer so far */
++              pdwBuf = (RMS_WORD *)hDisp->pBuf;
++              pCommand = (struct RMS_Command *)pdwBuf;
++              pCommand->fxn = (RMS_WORD)(ulRMSFxn);
++              pCommand->arg1 = (RMS_WORD)(ulCreateFxn);
++              if (NODE_GetLoadType(hNode) == NLDR_DYNAMICLOAD) {
++                      /* Flush ICACHE on Load */
++                      pCommand->arg2 = 1;     /* dummy argument */
++              } else {
++                      /* Do not flush ICACHE */
++                      pCommand->arg2 = 0;     /* dummy argument */
++              }
++              pCommand->data = NODE_GetType(hNode);
++              /*
++               *  argsOffset is the offset of the data field in struct
++               *  RMS_Command structure. We need this to calculate stream
++               *  definition offsets.
++               */
++              argsOffset = 3;
++              total += sizeof(struct RMS_Command) / sizeof(RMS_WORD);
++              /* Message args */
++              pMsgArgs = (struct RMS_MsgArgs *) (pdwBuf + total);
++              pMsgArgs->maxMessages = msgArgs.uMaxMessages;
++              pMsgArgs->segid = msgArgs.uSegid;
++              pMsgArgs->notifyType = msgArgs.uNotifyType;
++              pMsgArgs->argLength = msgArgs.uArgLength;
++              total += sizeof(struct RMS_MsgArgs) / sizeof(RMS_WORD) - 1;
++              memcpy(pdwBuf + total, msgArgs.pData, msgArgs.uArgLength);
++              total += dwLength;
++      }
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      /* If node is a task node, copy task create arguments into  buffer */
++      if (nodeType == NODE_TASK || nodeType == NODE_DAISSOCKET) {
++              taskArgs = pArgs->asa.taskArgs;
++              taskArgsOffset = total;
++              total += sizeof(struct RMS_MoreTaskArgs) / sizeof(RMS_WORD) +
++                      1 + taskArgs.uNumInputs + taskArgs.uNumOutputs;
++              /* Copy task arguments */
++              if (total < max) {
++                      total = taskArgsOffset;
++                      pMoreTaskArgs = (struct RMS_MoreTaskArgs *)(pdwBuf +
++                                      total);
++                      /*
++                       * Get some important info about the node. Note that we
++                       * don't just reach into the hNode struct because
++                       * that would break the node object's abstraction.
++                       */
++                      GetNodeInfo(hNode, &nodeInfo);
++                      GT_2trace(DISP_DebugMask, GT_ENTER,
++                               "uExecutionPriority %x, nPriority %x\n",
++                               nodeInfo.uExecutionPriority,
++                               taskArgs.nPriority);
++                      pMoreTaskArgs->priority = nodeInfo.uExecutionPriority;
++                      pMoreTaskArgs->stackSize = taskArgs.uStackSize;
++                      pMoreTaskArgs->sysstackSize = taskArgs.uSysStackSize;
++                      pMoreTaskArgs->stackSeg = taskArgs.uStackSeg;
++                      pMoreTaskArgs->heapAddr = taskArgs.uDSPHeapAddr;
++                      pMoreTaskArgs->heapSize = taskArgs.uHeapSize;
++                      pMoreTaskArgs->misc = taskArgs.ulDaisArg;
++                      pMoreTaskArgs->numInputStreams = taskArgs.uNumInputs;
++                      total +=
++                          sizeof(struct RMS_MoreTaskArgs) / sizeof(RMS_WORD);
++                      GT_2trace(DISP_DebugMask, GT_7CLASS,
++                               "DISP::::uDSPHeapAddr %x, "
++                               "uHeapSize %x\n", taskArgs.uDSPHeapAddr,
++                               taskArgs.uHeapSize);
++                      /* Keep track of pSIOInDef[] and pSIOOutDef[]
++                       * positions in the buffer, since this needs to be
++                       * filled in later.  */
++                      sioInDefOffset = total;
++                      total += taskArgs.uNumInputs;
++                      pdwBuf[total++] = taskArgs.uNumOutputs;
++                      sioOutDefOffset = total;
++                      total += taskArgs.uNumOutputs;
++                      sioDefsOffset = total;
++                      /* Fill SIO defs and offsets */
++                      offset = sioDefsOffset;
++                      for (i = 0; i < taskArgs.uNumInputs; i++) {
++                              if (DSP_FAILED(status))
++                                      break;
++
++                              pdwBuf[sioInDefOffset + i] =
++                                      (offset - argsOffset)
++                                      * (sizeof(RMS_WORD) / DSPWORDSIZE);
++                              strmDef = taskArgs.strmInDef[i];
++                              status = FillStreamDef(pdwBuf, &total, offset,
++                                       strmDef, max, uCharsInRMSWord);
++                              offset = total;
++                      }
++                      for (i = 0;  (i < taskArgs.uNumOutputs) &&
++                          (DSP_SUCCEEDED(status)); i++) {
++                              pdwBuf[sioOutDefOffset + i] =
++                                      (offset - argsOffset)
++                                      * (sizeof(RMS_WORD) / DSPWORDSIZE);
++                              strmDef = taskArgs.strmOutDef[i];
++                              status = FillStreamDef(pdwBuf, &total, offset,
++                                       strmDef, max, uCharsInRMSWord);
++                              offset = total;
++                      }
++                      if (DSP_FAILED(status)) {
++                              GT_2trace(DISP_DebugMask, GT_6CLASS,
++                                    "DISP_NodeCreate: Message"
++                                    " args to large for buffer! Message args"
++                                    " size = %d, max = %d\n", total, max);
++                      }
++              } else {
++                      /* Args won't fit */
++                      status = DSP_EFAIL;
++                      GT_2trace(DISP_DebugMask, GT_6CLASS,
++                               "DISP_NodeCreate: Message args "
++                               " too large for buffer! Message args size = %d"
++                               ", max = %d\n", total, max);
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              ulBytes = total * sizeof(RMS_WORD);
++              DBC_Assert(ulBytes < (RMS_COMMANDBUFSIZE * sizeof(RMS_WORD)));
++              status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++                       ulBytes, pNodeEnv);
++              if (DSP_FAILED(status)) {
++                      GT_1trace(DISP_DebugMask, GT_6CLASS,
++                                "DISP_NodeCreate  failed! "
++                                "status = 0x%x\n", status);
++              } else {
++                      /*
++                       * Message successfully received from RMS.
++                       * Return the status of the Node's create function
++                       * on the DSP-side
++                       */
++                      status = (((RMS_WORD *)(hDisp->pBuf))[0]);
++                      if (DSP_FAILED(status)) {
++                              GT_1trace(DISP_DebugMask, GT_6CLASS,
++                                       "DISP_NodeCreate, "
++                                       "DSP-side Node Create failed: 0x%x\n",
++                                       status);
++                      }
++
++              }
++      }
++func_end:
++      return status;
++}
++
++/*
++ *  ======== DISP_NodeDelete ========
++ *  purpose:
++ *      Delete a node on the DSP by remotely calling the node's delete function.
++ *
++ */
++DSP_STATUS DISP_NodeDelete(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
++                        u32 ulRMSFxn, u32 ulDeleteFxn, NODE_ENV nodeEnv)
++{
++      u32 dwArg;
++      struct RMS_Command *pCommand;
++      DSP_STATUS status = DSP_SOK;
++      u32 devType;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++      DBC_Require(hNode != NULL);
++
++      GT_5trace(DISP_DebugMask, GT_ENTER,
++               "DISP_NodeDelete: hDisp: 0x%xthNode: "
++               "0x%x\tulRMSFxn: 0x%x\tulDeleteFxn: 0x%x\tnodeEnv: 0x%x\n",
++               hDisp, hNode, ulRMSFxn, ulDeleteFxn, nodeEnv);
++
++      status = DEV_GetDevType(hDisp->hDevObject, &devType);
++
++      if (DSP_SUCCEEDED(status)) {
++
++              if (devType == DSP_UNIT) {
++
++                      /*
++                       *  Fill in buffer to send to RMS
++                       */
++                      pCommand = (struct RMS_Command *)hDisp->pBuf;
++                      pCommand->fxn = (RMS_WORD)(ulRMSFxn);
++                      pCommand->arg1 = (RMS_WORD)nodeEnv;
++                      pCommand->arg2 = (RMS_WORD)(ulDeleteFxn);
++                      pCommand->data = NODE_GetType(hNode);
++
++                      status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++                                          sizeof(struct RMS_Command), &dwArg);
++                      if (DSP_FAILED(status)) {
++                              GT_1trace(DISP_DebugMask, GT_6CLASS,
++                                       "DISP_NodeDelete failed!"
++                                       "status = 0x%x\n", status);
++                      } else {
++                              /*
++                               * Message successfully received from RMS.
++                               * Return the status of the Node's delete
++                               * function on the DSP-side
++                               */
++                              status = (((RMS_WORD *)(hDisp->pBuf))[0]);
++                              if (DSP_FAILED(status)) {
++                                      GT_1trace(DISP_DebugMask, GT_6CLASS,
++                                       "DISP_NodeDelete, "
++                                       "DSP-side Node Delete failed: 0x%x\n",
++                                       status);
++                              }
++                      }
++
++
++              }
++      }
++      return status;
++}
++
++/*
++ *  ======== DISP_NodeRun ========
++ *  purpose:
++ *      Start execution of a node's execute phase, or resume execution of a node
++ *      that has been suspended (via DISP_NodePause()) on the DSP.
++ */
++DSP_STATUS DISP_NodeRun(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
++                      u32 ulRMSFxn, u32 ulExecuteFxn, NODE_ENV nodeEnv)
++{
++      u32 dwArg;
++      struct RMS_Command *pCommand;
++      DSP_STATUS status = DSP_SOK;
++      u32 devType;
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++      DBC_Require(hNode != NULL);
++
++      GT_5trace(DISP_DebugMask, GT_ENTER, "DISP_NodeRun: hDisp: 0x%xthNode: \
++               0x%x\tulRMSFxn: 0x%x\tulExecuteFxn: 0x%x\tnodeEnv: 0x%x\n", \
++               hDisp, hNode, ulRMSFxn, ulExecuteFxn, nodeEnv);
++
++      status = DEV_GetDevType(hDisp->hDevObject, &devType);
++
++      if (DSP_SUCCEEDED(status)) {
++
++              if (devType == DSP_UNIT) {
++
++                      /*
++                       *  Fill in buffer to send to RMS.
++                       */
++                      pCommand = (struct RMS_Command *) hDisp->pBuf;
++                      pCommand->fxn = (RMS_WORD) (ulRMSFxn);
++                      pCommand->arg1 = (RMS_WORD) nodeEnv;
++                      pCommand->arg2 = (RMS_WORD) (ulExecuteFxn);
++                      pCommand->data = NODE_GetType(hNode);
++
++                      status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++                               sizeof(struct RMS_Command), &dwArg);
++                      if (DSP_FAILED(status)) {
++                              GT_1trace(DISP_DebugMask, GT_6CLASS,
++                                       "DISP_NodeRun failed!"
++                                       "status = 0x%x\n", status);
++                      } else {
++                              /*
++                               * Message successfully received from RMS.
++                               * Return the status of the Node's execute
++                               * function on the DSP-side
++                               */
++                              status = (((RMS_WORD *)(hDisp->pBuf))[0]);
++                              if (DSP_FAILED(status)) {
++                                      GT_1trace(DISP_DebugMask, GT_6CLASS,
++                                              "DISP_NodeRun, DSP-side Node "
++                                              "Execute failed: 0x%x\n",
++                                              status);
++              }
++              }
++
++      }
++      }
++
++      return status;
++}
++
++/*
++ *  ======== DeleteDisp ========
++ *  purpose:
++ *      Frees the resources allocated for the dispatcher.
++ */
++static void DeleteDisp(struct DISP_OBJECT *hDisp)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++
++      if (MEM_IsValidHandle(hDisp, DISP_SIGNATURE)) {
++              pIntfFxns = hDisp->pIntfFxns;
++
++              /* Free Node Dispatcher resources */
++              if (hDisp->hChnlFromDsp) {
++                      /* Channel close can fail only if the channel handle
++                       * is invalid. */
++                      status = (*pIntfFxns->pfnChnlClose)
++                               (hDisp->hChnlFromDsp);
++                      if (DSP_FAILED(status)) {
++                              GT_1trace(DISP_DebugMask, GT_6CLASS,
++                                       "DISP_Delete: Failed to "
++                                       "close channel from RMS: 0x%x\n",
++                                       status);
++                      }
++              }
++              if (hDisp->hChnlToDsp) {
++                      status = (*pIntfFxns->pfnChnlClose)(hDisp->hChnlToDsp);
++                      if (DSP_FAILED(status)) {
++                              GT_1trace(DISP_DebugMask, GT_6CLASS,
++                                       "DISP_Delete: Failed to "
++                                       "close channel to RMS: 0x%x\n",
++                                       status);
++                      }
++              }
++              if (hDisp->pBuf)
++                      MEM_Free(hDisp->pBuf);
++
++              MEM_FreeObject(hDisp);
++      }
++}
++
++/*
++ *  ======== FillStreamDef ========
++ *  purpose:
++ *      Fills stream definitions.
++ */
++static DSP_STATUS FillStreamDef(RMS_WORD *pdwBuf, u32 *ptotal, u32 offset,
++                              struct NODE_STRMDEF strmDef, u32 max,
++                              u32 uCharsInRMSWord)
++{
++      struct RMS_StrmDef *pStrmDef;
++      u32 total = *ptotal;
++      u32 uNameLen;
++      u32 dwLength;
++      DSP_STATUS status = DSP_SOK;
++
++      if (total + sizeof(struct RMS_StrmDef) / sizeof(RMS_WORD) >= max) {
++              status = DSP_EFAIL;
++      } else {
++              pStrmDef = (struct RMS_StrmDef *)(pdwBuf + total);
++              pStrmDef->bufsize = strmDef.uBufsize;
++              pStrmDef->nbufs = strmDef.uNumBufs;
++              pStrmDef->segid = strmDef.uSegid;
++              pStrmDef->align = strmDef.uAlignment;
++              pStrmDef->timeout = strmDef.uTimeout;
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              /*
++               *  Since we haven't added the device name yet, subtract
++               *  1 from total.
++               */
++              total += sizeof(struct RMS_StrmDef) / sizeof(RMS_WORD) - 1;
++               DBC_Require(strmDef.szDevice);
++               dwLength = strlen(strmDef.szDevice) + 1;
++
++              /* Number of RMS_WORDS needed to hold device name */
++              uNameLen = (dwLength + uCharsInRMSWord - 1) / uCharsInRMSWord;
++
++              if (total + uNameLen >= max) {
++                      status = DSP_EFAIL;
++              } else {
++                      /*
++                       *  Zero out last word, since the device name may not
++                       *  extend to completely fill this word.
++                       */
++                      pdwBuf[total + uNameLen - 1] = 0;
++                      /** TODO USE SERVICES **/
++                      memcpy(pdwBuf + total, strmDef.szDevice, dwLength);
++                      total += uNameLen;
++                      *ptotal = total;
++              }
++      }
++
++      return status;
++}
++
++/*
++ *  ======== SendMessage ======
++ *  Send command message to RMS, get reply from RMS.
++ */
++static DSP_STATUS SendMessage(struct DISP_OBJECT *hDisp, u32 dwTimeout,
++                           u32 ulBytes, u32 *pdwArg)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      struct CHNL_OBJECT *hChnl;
++      u32 dwArg = 0;
++      u8 *pBuf;
++      struct CHNL_IOC chnlIOC;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(pdwArg != NULL);
++
++      *pdwArg = (u32) NULL;
++      pIntfFxns = hDisp->pIntfFxns;
++      hChnl = hDisp->hChnlToDsp;
++      pBuf = hDisp->pBuf;
++
++      /* Send the command */
++      status = (*pIntfFxns->pfnChnlAddIOReq) (hChnl, pBuf, ulBytes, 0,
++               0L, dwArg);
++
++      if (DSP_FAILED(status)) {
++              GT_1trace(DISP_DebugMask, GT_6CLASS,
++                       "SendMessage: Channel AddIOReq to"
++                       " RMS failed! Status = 0x%x\n", status);
++              goto func_cont;
++      }
++      status = (*pIntfFxns->pfnChnlGetIOC) (hChnl, dwTimeout, &chnlIOC);
++      if (DSP_SUCCEEDED(status)) {
++              if (!CHNL_IsIOComplete(chnlIOC)) {
++                      if (CHNL_IsTimedOut(chnlIOC)) {
++                              status = DSP_ETIMEOUT;
++                      } else {
++                              GT_1trace(DISP_DebugMask, GT_6CLASS,
++                                       "SendMessage failed! "
++                                       "Channel IOC status = 0x%x\n",
++                                       chnlIOC.status);
++                              status = DSP_EFAIL;
++                      }
++              }
++      } else {
++              GT_1trace(DISP_DebugMask, GT_6CLASS,
++                       "SendMessage: Channel GetIOC to"
++                       " RMS failed! Status = 0x%x\n", status);
++      }
++func_cont:
++      /* Get the reply */
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      hChnl = hDisp->hChnlFromDsp;
++      ulBytes = REPLYSIZE;
++      status = (*pIntfFxns->pfnChnlAddIOReq)(hChnl, pBuf, ulBytes,
++               0, 0L, dwArg);
++      if (DSP_FAILED(status)) {
++              GT_1trace(DISP_DebugMask, GT_6CLASS,
++                       "SendMessage: Channel AddIOReq "
++                       "from RMS failed! Status = 0x%x\n", status);
++              goto func_end;
++      }
++      status = (*pIntfFxns->pfnChnlGetIOC) (hChnl, dwTimeout, &chnlIOC);
++      if (DSP_SUCCEEDED(status)) {
++              if (CHNL_IsTimedOut(chnlIOC)) {
++                      status = DSP_ETIMEOUT;
++              } else if (chnlIOC.cBytes < ulBytes) {
++                      /* Did not get all of the reply from the RMS */
++                      GT_1trace(DISP_DebugMask, GT_6CLASS,
++                               "SendMessage: Did not get all"
++                               "of reply from RMS! Bytes received: %d\n",
++                               chnlIOC.cBytes);
++                      status = DSP_EFAIL;
++              } else {
++                      if (CHNL_IsIOComplete(chnlIOC)) {
++                              DBC_Assert(chnlIOC.pBuf == pBuf);
++                              status = (*((RMS_WORD *)chnlIOC.pBuf));
++                              *pdwArg = (((RMS_WORD *)(chnlIOC.pBuf))[1]);
++                      } else {
++                              status = DSP_EFAIL;
++                      }
++              }
++      } else {
++              /* GetIOC failed */
++              GT_1trace(DISP_DebugMask, GT_6CLASS,
++                       "SendMessage: Failed to get "
++                       "reply from RMS! Status = 0x%x\n", status);
++      }
++func_end:
++      return status;
++}
+diff --git a/drivers/dsp/bridge/rmgr/drv.c b/drivers/dsp/bridge/rmgr/drv.c
+new file mode 100644
+index 0000000..256ce12
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/drv.c
+@@ -0,0 +1,1893 @@
++/*
++ * drv.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== drv.c ========
++ *  Description:
++ *      DSP/BIOS Bridge resource allocation module.
++ *
++ *  Public Functions:
++ *      DRV_Create
++ *      DRV_Destroy
++ *      DRV_Exit
++ *      DRV_GetDevObject
++ *      DRV_GetDevExtension
++ *      DRV_GetFirstDevObject
++ *      DRV_GetNextDevObject
++ *      DRV_GetNextDevExtension
++ *      DRV_Init
++ *      DRV_InsertDevObject
++ *      DRV_RemoveDevObject
++ *      DRV_RequestResources
++ *      DRV_ReleaseResources
++ *
++ *! Revision History
++ *! ======== ========
++ *! 19-Apr-2004 sb: Replaced OS specific APIs with MEM_AllocPhysMem and
++                  MEM_FreePhysMem. Fixed warnings. Cosmetic updates.
++ *! 12-Apr-2004 hp: IVA clean up during bridge-uninstall
++ *! 05-Jan-2004 vp: Updated for 24xx platform
++ *! 21-Mar-2003 sb: Get SHM size from registry
++ *! 10-Feb-2003 vp: Code review updates
++ *! 18-Oct-2002 vp: Ported to Linux platform
++ *! 30-Oct-2000 kc: Modified usage of REG_SetValue.
++ *! 06-Sep-2000 jeh Read channel info into struct CFG_HOSTRES in
++ *!                                   RequestISAResources()
++ *! 21-Sep-2000 rr: numwindows is calculated instead of default value in
++ *!            RequestISAResources.
++ *! 07-Aug-2000 rr: static list of dev objects removed.
++ *! 27-Jul-2000 rr: RequestResources split into two(Request and Release)
++ *!            Device extension created to hold the DevNodeString.
++ *! 17-Jul-2000 rr: Driver Object holds the list of Device Objects.
++ *!            Added DRV_Create, DRV_Destroy, DRV_GetDevObject,
++ *!            DRV_GetFirst/NextDevObject, DRV_Insert/RemoveDevObject.
++ *! 09-May-2000 rr: PCI Support is not L301 specific.Use of MEM_Calloc
++ *!            instead of MEM_Alloc.
++ *! 28-Mar-2000 rr: PCI Support added. L301 Specific. TBD.
++ *! 03-Feb-2000 rr: GT and Module Init/exit Changes. Merged with kc.
++ *! 19-Jan-2000 rr: DBC_Ensure in RequestPCMCIA moved within PCCARD ifdef
++ *! 29-Dec-1999 rr: PCCard support for any slot.Bus type stored in the
++ *!            struct CFG_HOSTRES Structure.
++ *! 17-Dec-1999 rr: if PCCARD_Init fails we return DSP_EFAIL.
++ *!            DBC_Ensure checks for sucess and pDevice != NULL
++ *! 11-Dec-1999 ag: #define "Isa" renamed to "IsaBus".
++ *! 09-Dec-1999 rr: windows.h included to remove warnings.
++ *! 02-Dec-1999 rr: struct GT_Mask is with in if DEBUG. Request resources checks
++ *!            status while making call to Reg functions.
++ *! 23-Nov-1999 rr: windows.h included
++ *! 19-Nov-1999 rr: DRV_RELEASE bug while setting the registry to zero.
++ *!            fixed.
++ *! 12-Nov-1999 rr: RequestResources() reads values from the registry.
++ *!            Hardcoded bIRQRegister define removed.
++ *! 05-Nov-1999 rr: Added hardcoded device interrupt.
++ *! 25-Oct-1999 rr: Resource structure removed. Now it uses the Host
++ *!            Resource structure directly.
++ *! 15-Oct-1999 rr: Resource Structure modified. See drv.h
++ *!            dwBusType taken from the registry.Hard coded
++ *!            registry entries removed.
++ *! 05-Oct-1999 rr: Calling DEV_StartDevice moved to wcdce.c. DRV_Register
++ *!            MiniDriver has been renamed to DRV_RequestResources.
++ *!            DRV_UnRegisterMiniDriver fxn removed.
++ *! 24-Sep-1999 rr: Significant changes to the RegisterMiniDriver fxns.
++ *!            Now it is simpler. IT stores the dev node in the
++ *!            registry, assign resources and calls the DEV_Start.
++ *! 10-Sep-1999 rr: Register Minidriver modified.
++ *!            - Resource structure follows the NT model
++ *! 08-Aug-1999 rr: Adopted for WinCE. Exports Fxns removed. Hull Created.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/reg.h>
++
++/*  ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/node.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/strm.h>
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/wmdchnl.h>
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE   0x5f52474d        /* "DRV_" (in reverse) */
++
++struct DRV_OBJECT {
++      u32 dwSignature;
++      struct LST_LIST *devList;
++      struct LST_LIST *devNodeString;
++#ifndef RES_CLEANUP_DISABLE
++      struct PROCESS_CONTEXT  *procCtxtList;
++#endif
++};
++
++/*
++ *  This is the Device Extension. Named with the Prefix
++ *  DRV_ since it is living in this module
++ */
++struct DRV_EXT {
++      struct LST_ELEM link;
++      char szString[MAXREGPATHLENGTH];
++};
++
++/*  ----------------------------------- Globals */
++static s32 cRefs;
++
++#if GT_TRACE
++extern struct GT_Mask curTrace;
++#endif
++
++/*  ----------------------------------- Function Prototypes */
++static DSP_STATUS RequestBridgeResources(u32 dwContext, s32 fRequest);
++static DSP_STATUS RequestBridgeResourcesDSP(u32 dwContext, s32 fRequest);
++
++#ifndef RES_CLEANUP_DISABLE
++/* GPP PROCESS CLEANUP CODE */
++
++static DSP_STATUS PrintProcessInformation(void);
++static DSP_STATUS DRV_ProcFreeNodeRes(HANDLE hPCtxt);
++static DSP_STATUS  DRV_ProcFreeSTRMRes(HANDLE hPCtxt);
++extern enum NODE_STATE NODE_GetState(HANDLE hNode);
++
++/* Get the process context list from driver object */
++
++/* Set the Process ID */
++DSP_STATUS DRV_ProcSetPID(HANDLE hPCtxt, s32 hProcess)
++{
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Assert(hPCtxt != NULL);
++
++      pCtxt->pid = hProcess;
++      return status;
++}
++
++
++/* Getting the head of the process context list */
++DSP_STATUS DRV_GetProcCtxtList(struct PROCESS_CONTEXT **pPctxt,
++                              struct DRV_OBJECT *hDrvObject)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
++
++      DBC_Assert(hDrvObject != NULL);
++      GT_2trace(curTrace, GT_ENTER,
++              "DRV_GetProcCtxtList: 2 *pPctxt:%x, pDrvObject"
++              ":%x", *pPctxt, pDrvObject);
++      *pPctxt = pDrvObject->procCtxtList;
++      GT_2trace(curTrace, GT_ENTER,
++              "DRV_GetProcCtxtList: 3 *pPctxt:%x, pDrvObject"
++              ":%x", *pPctxt, pDrvObject);
++      return status;
++}
++
++
++
++/* Get a particular process context based on process handle (phProcess) */
++DSP_STATUS DRV_GetProcContext(u32 phProcess,
++                              struct DRV_OBJECT *hDrvObject,
++                              HANDLE hPCtxt, DSP_HNODE hNode,
++                              u32 pMapAddr)
++{
++      struct PROCESS_CONTEXT **pCtxt = (struct PROCESS_CONTEXT **)hPCtxt;
++      DSP_STATUS status = DSP_SOK;
++      struct PROCESS_CONTEXT *pCtxtList = NULL;
++      struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
++      struct NODE_RES_OBJECT *pTempNode2 = NULL;
++      struct NODE_RES_OBJECT *pTempNode = NULL;
++      struct DMM_RES_OBJECT *pTempDMM2 = NULL;
++      struct DMM_RES_OBJECT *pTempDMM = NULL;
++      s32 pCtxtFound = 0;
++
++      DBC_Assert(pDrvObject != NULL);
++      pCtxtList = pDrvObject->procCtxtList;
++      GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 2");
++      while ((pCtxtList != NULL) && (pCtxtList->pid != phProcess)) {
++              pCtxtList = pCtxtList->next;
++              GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 3");
++      }
++      if (pCtxtList == NULL) {
++              if (hNode != NULL) {
++                      pCtxtList = pDrvObject->procCtxtList;
++                      while ((pCtxtList != NULL) && (pCtxtFound == 0)) {
++                              pTempNode = pCtxtList->pNodeList;
++                              while ((pTempNode != NULL) &&
++                                    (pTempNode->hNode != hNode)) {
++                                      pTempNode2 = pTempNode;
++                                      pTempNode = pTempNode->next;
++                              }
++                              if (pTempNode != NULL) {
++                                      pCtxtFound = 1;
++                                      status = DSP_SOK;
++                              } else {
++                                      pCtxtList = pCtxtList->next;
++                              }
++                      }
++              } else if ((pMapAddr != 0) && (pCtxtFound == 0)) {
++                      pCtxtList = pDrvObject->procCtxtList;
++                      while ((pCtxtList != NULL) && (pCtxtFound == 0)) {
++                              pTempDMM = pCtxtList->pDMMList;
++                              while ((pTempDMM != NULL) &&
++                                   (pTempDMM->ulDSPAddr != pMapAddr)) {
++                                      pTempDMM2 = pTempDMM;
++                                      pTempDMM = pTempDMM->next;
++                              }
++                              if (pTempDMM != NULL) {
++                                      pCtxtFound = 1;
++                                      status = DSP_SOK;
++                              } else {
++                                      pCtxtList = pCtxtList->next;
++                              }
++                      }
++                      if (pCtxtList == NULL)
++                              status = DSP_ENOTFOUND;
++
++              }
++      } else{
++              status = DSP_SOK;
++      }
++      GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 4");
++      *pCtxt = pCtxtList;
++      return status;
++}
++
++
++/* Add a new process context to process context list */
++DSP_STATUS DRV_InsertProcContext(struct DRV_OBJECT *hDrVObject, HANDLE hPCtxt)
++{
++      struct PROCESS_CONTEXT **pCtxt = (struct PROCESS_CONTEXT **)hPCtxt;
++      DSP_STATUS status = DSP_SOK;
++      struct PROCESS_CONTEXT *pCtxtList = NULL;
++      struct DRV_OBJECT            *hDRVObject;
++
++      GT_0trace(curTrace, GT_ENTER, "\n In DRV_InsertProcContext\n");
++      status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++      DBC_Assert(hDRVObject != NULL);
++      *pCtxt = MEM_Calloc(1 * sizeof(struct PROCESS_CONTEXT), MEM_PAGED);
++      GT_0trace(curTrace, GT_ENTER,
++               "\n In DRV_InsertProcContext Calling "
++               "DRV_GetProcCtxtList\n");
++      DRV_GetProcCtxtList(&pCtxtList, hDRVObject);
++      GT_0trace(curTrace, GT_ENTER,
++               "\n In DRV_InsertProcContext After Calling "
++               "DRV_GetProcCtxtList\n");
++      if (pCtxtList != NULL) {
++              GT_0trace(curTrace, GT_ENTER,
++                       "\n In DRV_InsertProcContext and pCtxt is "
++                       "not Null\n");
++              while (pCtxtList->next != NULL)
++                      pCtxtList = pCtxtList->next;
++
++              pCtxtList->next = *pCtxt;
++      } else {
++              GT_0trace(curTrace, GT_ENTER,
++                       "\n In DRV_InsertProcContext and "
++                       "pCtxt is Null\n");
++              hDRVObject->procCtxtList = *pCtxt;
++      }
++      return status;
++}
++
++/* Delete a process context from process resource context list */
++DSP_STATUS DRV_RemoveProcContext(struct DRV_OBJECT *hDRVObject,
++                                   HANDLE hPCtxt, HANDLE hProcess)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct PROCESS_CONTEXT    *pCtxt2 = NULL;
++      struct PROCESS_CONTEXT    *pTmp = NULL;
++      struct PROCESS_CONTEXT    *pCtxtList = NULL;
++
++      DBC_Assert(hDRVObject != NULL);
++      DRV_GetProcContext((u32)hProcess, hDRVObject, &pCtxt2, NULL, 0);
++
++      GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 12");
++      DRV_GetProcCtxtList(&pCtxtList, hDRVObject);
++      GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 13");
++      pTmp = pCtxtList;
++      while ((pCtxtList != NULL) && (pCtxtList != pCtxt2)) {
++              pTmp = pCtxtList;
++              pCtxtList = pCtxtList->next;
++              GT_0trace(curTrace, GT_ENTER,
++                       "DRV_RemoveProcContext: 2");
++      }
++      GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 3");
++      if (hDRVObject->procCtxtList == pCtxt2)
++              hDRVObject->procCtxtList = pCtxt2->next;
++
++      if (pCtxtList == NULL)
++              return DSP_ENOTFOUND;
++      else if (pTmp->next != NULL)
++              pTmp->next = pTmp->next->next;
++
++      MEM_Free(pCtxt2);
++      GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 7");
++
++      return status;
++}
++
++/* Update the state of process context */
++DSP_STATUS DRV_ProcUpdatestate(HANDLE hPCtxt, enum GPP_PROC_RES_STATE status)
++{
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      DSP_STATUS status1 = DSP_SOK;
++      if (pCtxt != NULL) {
++              pCtxt->resState = status;
++      } else {
++              GT_0trace(curTrace, GT_ENTER,
++                       "DRV_ProcUpdatestate: Failed to update "
++                       "process state");
++      }
++      return status1;
++}
++
++/* Allocate and add a node resource element
++* This function is called from .Node_Allocate.  */
++DSP_STATUS DRV_InsertNodeResElement(HANDLE hNode, HANDLE hNodeRes,
++                                      HANDLE hPCtxt)
++{
++      struct NODE_RES_OBJECT **pNodeRes = (struct NODE_RES_OBJECT **)hNodeRes;
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      DSP_STATUS status = DSP_SOK;
++      struct NODE_RES_OBJECT   *pTempNodeRes = NULL;
++      GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 1");
++      *pNodeRes = (struct NODE_RES_OBJECT *)MEM_Calloc
++                  (1 * sizeof(struct NODE_RES_OBJECT), MEM_PAGED);
++      DBC_Assert(hPCtxt != NULL);
++      if ((*pNodeRes == NULL) || (hPCtxt == NULL)) {
++              GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 12");
++              status = DSP_EHANDLE;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              (*pNodeRes)->hNode = hNode;
++              if (pCtxt->pNodeList != NULL) {
++                      pTempNodeRes = pCtxt->pNodeList;
++                      while (pTempNodeRes->next != NULL)
++                              pTempNodeRes = pTempNodeRes->next;
++
++                      pTempNodeRes->next = *pNodeRes;
++                      GT_0trace(curTrace, GT_ENTER,
++                               "DRV_InsertNodeResElement: 2");
++              } else {
++                      pCtxt->pNodeList = *pNodeRes;
++                      GT_0trace(curTrace, GT_ENTER,
++                               "DRV_InsertNodeResElement: 3");
++              }
++      }
++      GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 4");
++      return status;
++}
++
++/* Release all Node resources and its context
++* This is called from .Node_Delete.  */
++DSP_STATUS DRV_RemoveNodeResElement(HANDLE hNodeRes, HANDLE hPCtxt)
++{
++      struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      DSP_STATUS      status = DSP_SOK;
++      struct NODE_RES_OBJECT *pTempNode2 = pCtxt->pNodeList;
++      struct NODE_RES_OBJECT *pTempNode = pCtxt->pNodeList;
++
++      DBC_Assert(hPCtxt != NULL);
++      GT_0trace(curTrace, GT_ENTER, "\nDRV_RemoveNodeResElement: 1\n");
++      while ((pTempNode != NULL) && (pTempNode != pNodeRes)) {
++              pTempNode2 = pTempNode;
++              pTempNode = pTempNode->next;
++      }
++      if (pCtxt->pNodeList == pNodeRes)
++              pCtxt->pNodeList = pNodeRes->next;
++
++      if (pTempNode == NULL)
++              return DSP_ENOTFOUND;
++      else if (pTempNode2->next != NULL)
++              pTempNode2->next = pTempNode2->next->next;
++
++      MEM_Free(pTempNode);
++      return status;
++}
++
++/* Actual Node De-Allocation */
++static DSP_STATUS DRV_ProcFreeNodeRes(HANDLE hPCtxt)
++{
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      DSP_STATUS status = DSP_SOK;
++      struct NODE_RES_OBJECT *pNodeList = NULL;
++      struct NODE_RES_OBJECT *pNodeRes = NULL;
++      u32  nState;
++
++      DBC_Assert(hPCtxt != NULL);
++      pNodeList = pCtxt->pNodeList;
++      while (pNodeList != NULL) {
++              GT_0trace(curTrace, GT_ENTER, "DRV_ProcFreeNodeRes: 1");
++              pNodeRes = pNodeList;
++              pNodeList = pNodeList->next;
++              if (pNodeRes->nodeAllocated) {
++                      nState = NODE_GetState(pNodeRes->hNode) ;
++                      GT_1trace(curTrace, GT_5CLASS,
++                              "DRV_ProcFreeNodeRes: Node state %x\n", nState);
++                      if (nState <= NODE_DELETING) {
++                              if ((nState == NODE_RUNNING) ||
++                                      (nState == NODE_PAUSED) ||
++                                      (nState == NODE_TERMINATING)) {
++                                      GT_1trace(curTrace, GT_5CLASS,
++                                      "Calling Node_Terminate for Node:"
++                                      " 0x%x\n", pNodeRes->hNode);
++                                      status = NODE_Terminate
++                                              (pNodeRes->hNode, &status);
++                                      GT_1trace(curTrace, GT_5CLASS,
++                                               "Calling Node_Delete for Node:"
++                                               " 0x%x\n", pNodeRes->hNode);
++                                      status = NODE_Delete(pNodeRes->hNode);
++                                      GT_1trace(curTrace, GT_5CLASS,
++                                      "the status after the NodeDelete %x\n",
++                                      status);
++                              } else if ((nState == NODE_ALLOCATED)
++                                      || (nState == NODE_CREATED))
++                                      status = NODE_Delete(pNodeRes->hNode);
++                      }
++              }
++              pNodeRes->nodeAllocated = 0;
++      }
++      return status;
++}
++
++/* Allocate the DMM resource element
++* This is called from Proc_Map. after the actual resource is allocated */
++DSP_STATUS DRV_InsertDMMResElement(HANDLE hDMMRes, HANDLE hPCtxt)
++{
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      struct DMM_RES_OBJECT **pDMMRes = (struct DMM_RES_OBJECT **)hDMMRes;
++      DSP_STATUS      status = DSP_SOK;
++      struct DMM_RES_OBJECT *pTempDMMRes = NULL;
++
++      *pDMMRes = (struct DMM_RES_OBJECT *)
++                  MEM_Calloc(1 * sizeof(struct DMM_RES_OBJECT), MEM_PAGED);
++      DBC_Assert(hPCtxt != NULL);
++      GT_0trace(curTrace, GT_ENTER, "DRV_InsertDMMResElement: 1");
++      if ((*pDMMRes == NULL) || (hPCtxt == NULL)) {
++              GT_0trace(curTrace, GT_5CLASS, "DRV_InsertDMMResElement: 2");
++              status = DSP_EHANDLE;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              if (pCtxt->pDMMList != NULL) {
++                      GT_0trace(curTrace, GT_5CLASS,
++                               "DRV_InsertDMMResElement: 3");
++                      pTempDMMRes = pCtxt->pDMMList;
++                      while (pTempDMMRes->next != NULL)
++                              pTempDMMRes = pTempDMMRes->next;
++
++                      pTempDMMRes->next = *pDMMRes;
++              } else {
++                      pCtxt->pDMMList = *pDMMRes;
++                      GT_0trace(curTrace, GT_5CLASS,
++                               "DRV_InsertDMMResElement: 4");
++              }
++      }
++      GT_0trace(curTrace, GT_ENTER, "DRV_InsertDMMResElement: 5");
++      return status;
++}
++
++
++
++/* Release DMM resource element context
++* This is called from Proc_UnMap. after the actual resource is freed */
++DSP_STATUS    DRV_RemoveDMMResElement(HANDLE hDMMRes, HANDLE hPCtxt)
++{
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      struct DMM_RES_OBJECT *pDMMRes = (struct DMM_RES_OBJECT *)hDMMRes;
++      DSP_STATUS status = DSP_SOK;
++      struct DMM_RES_OBJECT *pTempDMMRes2 = NULL;
++      struct DMM_RES_OBJECT *pTempDMMRes = NULL;
++
++      DBC_Assert(hPCtxt != NULL);
++      pTempDMMRes2 = pCtxt->pDMMList;
++      pTempDMMRes = pCtxt->pDMMList;
++      GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 1");
++      while ((pTempDMMRes != NULL) && (pTempDMMRes != pDMMRes)) {
++              GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 2");
++              pTempDMMRes2 = pTempDMMRes;
++              pTempDMMRes = pTempDMMRes->next;
++      }
++      GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 3");
++      if (pCtxt->pDMMList == pTempDMMRes)
++              pCtxt->pDMMList = pTempDMMRes->next;
++
++      if (pTempDMMRes == NULL)
++              return DSP_ENOTFOUND;
++      else if (pTempDMMRes2->next != NULL)
++              pTempDMMRes2->next = pTempDMMRes2->next->next;
++
++      MEM_Free(pDMMRes);
++      GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 4");
++      return status;
++}
++
++/* Update DMM resource status */
++DSP_STATUS DRV_UpdateDMMResElement(HANDLE hDMMRes, u32 pMpuAddr, u32 ulSize,
++                                u32 pReqAddr, u32 pMapAddr,
++                                HANDLE hProcessor)
++{
++      struct DMM_RES_OBJECT *pDMMRes = (struct DMM_RES_OBJECT *)hDMMRes;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Assert(hDMMRes != NULL);
++      pDMMRes->ulMpuAddr = pMpuAddr;
++      pDMMRes->ulDSPAddr = pMapAddr;
++      pDMMRes->ulDSPResAddr = pReqAddr;
++      pDMMRes->dmmSize = ulSize;
++      pDMMRes->hProcessor = hProcessor;
++      pDMMRes->dmmAllocated = 1;
++
++      return status;
++}
++
++/* Actual DMM De-Allocation */
++DSP_STATUS  DRV_ProcFreeDMMRes(HANDLE hPCtxt)
++{
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      DSP_STATUS status = DSP_SOK;
++      struct DMM_RES_OBJECT *pDMMList = pCtxt->pDMMList;
++      struct DMM_RES_OBJECT *pDMMRes = NULL;
++
++      DBC_Assert(hPCtxt != NULL);
++      GT_0trace(curTrace, GT_ENTER, "\nDRV_ProcFreeDMMRes: 1\n");
++      while (pDMMList != NULL) {
++              pDMMRes = pDMMList;
++              pDMMList = pDMMList->next;
++              if (pDMMRes->dmmAllocated) {
++                      status = PROC_UnMap(pDMMRes->hProcessor,
++                               (void *)pDMMRes->ulDSPResAddr);
++                      status = PROC_UnReserveMemory(pDMMRes->hProcessor,
++                               (void *)pDMMRes->ulDSPResAddr);
++                      pDMMRes->dmmAllocated = 0;
++              }
++      }
++      return status;
++}
++
++
++/* Release all DMM resources and its context
++* This is called from .bridge_release. */
++DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE hPCtxt)
++{
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      DSP_STATUS status = DSP_SOK;
++      struct DMM_RES_OBJECT *pTempDMMRes2 = NULL;
++      struct DMM_RES_OBJECT *pTempDMMRes = NULL;
++
++      DBC_Assert(pCtxt != NULL);
++      DRV_ProcFreeDMMRes(pCtxt);
++      pTempDMMRes = pCtxt->pDMMList;
++      while (pTempDMMRes != NULL) {
++              pTempDMMRes2 = pTempDMMRes;
++              pTempDMMRes = pTempDMMRes->next;
++              MEM_Free(pTempDMMRes2);
++      }
++      pCtxt->pDMMList = NULL;
++      return status;
++}
++
++DSP_STATUS DRV_GetDMMResElement(u32 pMapAddr, HANDLE hDMMRes, HANDLE hPCtxt)
++{
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      struct DMM_RES_OBJECT **pDMMRes = (struct DMM_RES_OBJECT **)hDMMRes;
++      DSP_STATUS status = DSP_SOK;
++      struct DMM_RES_OBJECT *pTempDMM2 = NULL;
++      struct DMM_RES_OBJECT *pTempDMM = NULL;
++
++      DBC_Assert(hPCtxt != NULL);
++      pTempDMM = pCtxt->pDMMList;
++      while ((pTempDMM != NULL) && (pTempDMM->ulDSPAddr != pMapAddr)) {
++              GT_3trace(curTrace, GT_ENTER,
++                       "DRV_GetDMMResElement: 2 pTempDMM:%x "
++                       "pTempDMM->ulDSPAddr:%x pMapAddr:%x\n", pTempDMM,
++                       pTempDMM->ulDSPAddr, pMapAddr);
++              pTempDMM2 = pTempDMM;
++              pTempDMM = pTempDMM->next;
++      }
++      if (pTempDMM != NULL) {
++              GT_0trace(curTrace, GT_ENTER, "DRV_GetDMMResElement: 3");
++              *pDMMRes = pTempDMM;
++      } else {
++              status = DSP_ENOTFOUND;
++      } GT_0trace(curTrace, GT_ENTER, "DRV_GetDMMResElement: 4");
++      return status;
++}
++
++/* Update Node allocation status */
++void DRV_ProcNodeUpdateStatus(HANDLE hNodeRes, s32 status)
++{
++      struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
++      DBC_Assert(hNodeRes != NULL);
++      pNodeRes->nodeAllocated = status;
++}
++
++/* Update Node Heap status */
++void DRV_ProcNodeUpdateHeapStatus(HANDLE hNodeRes, s32 status)
++{
++      struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
++      DBC_Assert(hNodeRes != NULL);
++      pNodeRes->heapAllocated = status;
++}
++
++/* Release all Node resources and its context
++* This is called from .bridge_release.
++*/
++DSP_STATUS    DRV_RemoveAllNodeResElements(HANDLE hPCtxt)
++{
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      DSP_STATUS status = DSP_SOK;
++      struct NODE_RES_OBJECT *pTempNode2 = NULL;
++      struct NODE_RES_OBJECT *pTempNode = NULL;
++
++      DBC_Assert(hPCtxt != NULL);
++      DRV_ProcFreeNodeRes(pCtxt);
++      pTempNode = pCtxt->pNodeList;
++      while (pTempNode != NULL) {
++              pTempNode2 = pTempNode;
++              pTempNode = pTempNode->next;
++              MEM_Free(pTempNode2);
++      }
++      pCtxt->pNodeList = NULL;
++      return status;
++}
++
++/* Getting the node resource element */
++
++DSP_STATUS DRV_GetNodeResElement(HANDLE hNode, HANDLE hNodeRes, HANDLE hPCtxt)
++{
++      struct NODE_RES_OBJECT **nodeRes = (struct NODE_RES_OBJECT **)hNodeRes;
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      DSP_STATUS status = DSP_SOK;
++      struct NODE_RES_OBJECT *pTempNode2 = NULL;
++      struct NODE_RES_OBJECT *pTempNode = NULL;
++
++      DBC_Assert(hPCtxt != NULL);
++      pTempNode = pCtxt->pNodeList;
++      GT_0trace(curTrace, GT_ENTER, "DRV_GetNodeResElement: 1");
++      while ((pTempNode != NULL) && (pTempNode->hNode != hNode)) {
++              pTempNode2 = pTempNode;
++              pTempNode = pTempNode->next;
++      }
++      if (pTempNode != NULL)
++              *nodeRes = pTempNode;
++      else
++              status = DSP_ENOTFOUND;
++
++      return status;
++}
++
++
++
++/* Allocate the STRM resource element
++* This is called after the actual resource is allocated
++*/
++DSP_STATUS DRV_ProcInsertSTRMResElement(HANDLE hStreamHandle, HANDLE hSTRMRes,
++                                      HANDLE hPCtxt)
++{
++      struct STRM_RES_OBJECT **pSTRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      DSP_STATUS status = DSP_SOK;
++      struct STRM_RES_OBJECT *pTempSTRMRes = NULL;
++      DBC_Assert(hPCtxt != NULL);
++
++      *pSTRMRes = (struct STRM_RES_OBJECT *)
++                  MEM_Calloc(1 * sizeof(struct STRM_RES_OBJECT), MEM_PAGED);
++      if ((*pSTRMRes == NULL) || (hPCtxt == NULL)) {
++              GT_0trace(curTrace, GT_ENTER, "DRV_InsertSTRMResElement: 2");
++              status = DSP_EHANDLE;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              (*pSTRMRes)->hStream = hStreamHandle;
++              if (pCtxt->pSTRMList != NULL) {
++                      GT_0trace(curTrace, GT_ENTER,
++                               "DRV_InsertiSTRMResElement: 3");
++                      pTempSTRMRes = pCtxt->pSTRMList;
++                      while (pTempSTRMRes->next != NULL)
++                              pTempSTRMRes = pTempSTRMRes->next;
++
++                      pTempSTRMRes->next = *pSTRMRes;
++              } else {
++                      pCtxt->pSTRMList = *pSTRMRes;
++                      GT_0trace(curTrace, GT_ENTER,
++                               "DRV_InsertSTRMResElement: 4");
++              }
++      }
++      return status;
++}
++
++
++
++/* Release Stream resource element context
++* This function called after the actual resource is freed
++*/
++DSP_STATUS    DRV_ProcRemoveSTRMResElement(HANDLE hSTRMRes, HANDLE hPCtxt)
++{
++      struct STRM_RES_OBJECT *pSTRMRes = (struct STRM_RES_OBJECT *)hSTRMRes;
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      DSP_STATUS status = DSP_SOK;
++      struct STRM_RES_OBJECT *pTempSTRMRes2 = pCtxt->pSTRMList;
++      struct STRM_RES_OBJECT *pTempSTRMRes = pCtxt->pSTRMList;
++
++      DBC_Assert(hPCtxt != NULL);
++      while ((pTempSTRMRes != NULL) && (pTempSTRMRes != pSTRMRes)) {
++              pTempSTRMRes2 = pTempSTRMRes;
++              pTempSTRMRes = pTempSTRMRes->next;
++      }
++      if (pCtxt->pSTRMList == pTempSTRMRes)
++              pCtxt->pSTRMList = pTempSTRMRes->next;
++
++      if (pTempSTRMRes == NULL)
++              status = DSP_ENOTFOUND;
++      else if (pTempSTRMRes2->next != NULL)
++              pTempSTRMRes2->next = pTempSTRMRes2->next->next;
++
++      MEM_Free(pSTRMRes);
++      return status;
++}
++
++
++/* Actual Stream De-Allocation */
++static DSP_STATUS  DRV_ProcFreeSTRMRes(HANDLE hPCtxt)
++{
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      DSP_STATUS status = DSP_SOK;
++      DSP_STATUS status1 = DSP_SOK;
++      u8 **apBuffer = NULL;
++      struct STRM_RES_OBJECT *pSTRMList = NULL;
++      struct STRM_RES_OBJECT *pSTRMRes = NULL;
++      u8 *pBufPtr;
++      u32 ulBytes;
++      u32 dwArg;
++      s32 ulBufSize;
++
++
++      DBC_Assert(hPCtxt != NULL);
++      pSTRMList = pCtxt->pSTRMList;
++      while (pSTRMList != NULL) {
++              pSTRMRes = pSTRMList;
++              pSTRMList = pSTRMList->next;
++              if (pSTRMRes->uNumBufs != 0) {
++                      apBuffer = MEM_Alloc((pSTRMRes->uNumBufs *
++                                          sizeof(u8 *)), MEM_NONPAGED);
++                      status = STRM_FreeBuffer(pSTRMRes->hStream, apBuffer,
++                                              pSTRMRes->uNumBufs);
++                      MEM_Free(apBuffer);
++              }
++              status = STRM_Close(pSTRMRes->hStream);
++              if (DSP_FAILED(status)) {
++                      if (status == DSP_EPENDING) {
++                              status = STRM_Reclaim(pSTRMRes->hStream,
++                                                   &pBufPtr, &ulBytes,
++                                                   (u32 *)&ulBufSize, &dwArg);
++                              if (DSP_SUCCEEDED(status))
++                                      status = STRM_Close(pSTRMRes->hStream);
++
++                      }
++              }
++      }
++      return status1;
++}
++
++/* Release all Stream resources and its context
++* This is called from .bridge_release.
++*/
++DSP_STATUS    DRV_RemoveAllSTRMResElements(HANDLE hPCtxt)
++{
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      DSP_STATUS status = DSP_SOK;
++      struct STRM_RES_OBJECT *pTempSTRMRes2 = NULL;
++      struct STRM_RES_OBJECT *pTempSTRMRes = NULL;
++
++      DBC_Assert(hPCtxt != NULL);
++      DRV_ProcFreeSTRMRes(pCtxt);
++      pTempSTRMRes = pCtxt->pSTRMList;
++      while (pTempSTRMRes != NULL) {
++              pTempSTRMRes2 = pTempSTRMRes;
++              pTempSTRMRes = pTempSTRMRes->next;
++              MEM_Free(pTempSTRMRes2);
++      }
++      pCtxt->pSTRMList = NULL;
++      return status;
++}
++
++
++/* Getting the stream resource element */
++DSP_STATUS DRV_GetSTRMResElement(HANDLE hStrm, HANDLE hSTRMRes, HANDLE hPCtxt)
++{
++      struct STRM_RES_OBJECT **STRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      DSP_STATUS status = DSP_SOK;
++      struct STRM_RES_OBJECT *pTempSTRM2 = NULL;
++      struct STRM_RES_OBJECT *pTempSTRM = pCtxt->pSTRMList;
++
++      DBC_Assert(hPCtxt != NULL);
++      while ((pTempSTRM != NULL) && (pTempSTRM->hStream != hStrm)) {
++              GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 2");
++              pTempSTRM2 = pTempSTRM;
++              pTempSTRM = pTempSTRM->next;
++      }
++      if (pTempSTRM != NULL) {
++              GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 3");
++              *STRMRes = pTempSTRM;
++      } else {
++              GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 4");
++              status = DSP_ENOTFOUND;
++      }
++      GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 5");
++      return status;
++}
++
++/* Updating the stream resource element */
++DSP_STATUS DRV_ProcUpdateSTRMRes(u32 uNumBufs, HANDLE hSTRMRes, HANDLE hPCtxt)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct STRM_RES_OBJECT **STRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
++
++      DBC_Assert(hPCtxt != NULL);
++      (*STRMRes)->uNumBufs = uNumBufs;
++      return status;
++}
++
++/* Displaying the resources allocated by a process */
++DSP_STATUS DRV_ProcDisplayResInfo(u8 *pBuf1, u32 *pSize)
++{
++      struct PROCESS_CONTEXT *pCtxt = NULL;
++      struct NODE_RES_OBJECT *pNodeRes = NULL;
++      struct DMM_RES_OBJECT *pDMMRes = NULL;
++      struct STRM_RES_OBJECT *pSTRMRes = NULL;
++      struct DSPHEAP_RES_OBJECT *pDSPHEAPRes = NULL;
++      u32 tempCount = 1;
++      HANDLE hDrvObject = NULL;
++      void *pBuf = pBuf1;
++      u8 pTempBuf[250];
++      u32 tempStrLen = 0, tempStrLen2 = 0;
++      DSP_STATUS status = DSP_SOK;
++
++      CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++      DRV_GetProcCtxtList(&pCtxt, (struct DRV_OBJECT *)hDrvObject);
++      GT_0trace(curTrace, GT_ENTER, "*********************"
++               "DRV_ProcDisplayResourceInfo:*\n");
++      while (pCtxt != NULL) {
++              tempStrLen2 = sprintf((char *)pTempBuf,
++                                   "-------------------------------------"
++                                   "-----------------------------------\n");
++              tempStrLen2 += 2;
++              memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++              tempStrLen += tempStrLen2;
++              if (pCtxt->resState == PROC_RES_ALLOCATED) {
++                      tempStrLen2 = sprintf((char *)pTempBuf,
++                                      "GPP Process Resource State: "
++                                      "pCtxt->resState = PROC_RES_ALLOCATED, "
++                                      " Process ID: %d\n", pCtxt->pid);
++                      tempStrLen2 += 2;
++                      memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++                      tempStrLen += tempStrLen2;
++              } else {
++                      tempStrLen2 = sprintf((char *)pTempBuf,
++                              "GPP Resource State: pCtxt->resState"
++                              " = PROC_RES_DEALLOCATED, Process ID:%d\n",
++                              pCtxt->pid);
++                      tempStrLen2 += 2;
++                      memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++                      tempStrLen += tempStrLen2;
++              }
++              pNodeRes = pCtxt->pNodeList;
++              tempCount = 1;
++              while (pNodeRes != NULL) {
++                      GT_2trace(curTrace, GT_ENTER,
++                               "DRV_ProcDisplayResourceInfo: #:%d "
++                               "pCtxt->pNodeList->hNode:%x\n",
++                               tempCount, pNodeRes->hNode);
++                      tempStrLen2 = sprintf((char *)pTempBuf,
++                                      "Node Resource Information: Node #"
++                                      " %d Node Handle hNode:0X%x\n",
++                                      tempCount, (u32)pNodeRes->hNode);
++                      pNodeRes = pNodeRes->next;
++                      tempStrLen2 += 2;
++                      memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++                      tempStrLen += tempStrLen2;
++                      tempCount++;
++              }
++              tempCount = 1;
++              pDSPHEAPRes = pCtxt->pDSPHEAPList;
++              while (pDSPHEAPRes != NULL) {
++                      GT_2trace(curTrace, GT_ENTER,
++                               "DRV_ProcDisplayResourceInfo: #:%d "
++                               "pCtxt->pDSPHEAPRList->ulMpuAddr:%x\n",
++                               tempCount, pDSPHEAPRes->ulMpuAddr);
++                      tempStrLen2 = sprintf((char *)pTempBuf,
++                               "DSP Heap Resource Info: HEAP # %d"
++                               " Mapped GPP Address: 0x%x, size: 0x%x\n",
++                               tempCount, (u32)pDSPHEAPRes->ulMpuAddr,
++                               (u32)pDSPHEAPRes->heapSize);
++                      pDSPHEAPRes = pDSPHEAPRes->next;
++                      tempStrLen2 += 2;
++                      memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++                      tempStrLen += tempStrLen2;
++                      tempCount++;
++              }
++              tempCount = 1;
++              pDMMRes = pCtxt->pDMMList;
++              while (pDMMRes != NULL) {
++                      GT_2trace(curTrace, GT_ENTER,
++                                      "DRV_ProcDisplayResourceInfo: #:%d "
++                                      " pCtxt->pDMMList->ulMpuAddr:%x\n",
++                                      tempCount,
++                                      pDMMRes->ulMpuAddr);
++                      tempStrLen2 = sprintf((char *)pTempBuf,
++                                       "DMM Resource Info: DMM # %d Mapped"
++                                       " GPP Address: 0x%x, size: 0x%x\n",
++                                       tempCount, (u32)pDMMRes->ulMpuAddr,
++                                       (u32)pDMMRes->dmmSize);
++                      pDMMRes = pDMMRes->next;
++                      tempStrLen2 += 2;
++                      memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++                      tempStrLen += tempStrLen2;
++                      tempCount++;
++              }
++              tempCount = 1;
++              pSTRMRes = pCtxt->pSTRMList;
++              while (pSTRMRes != NULL) {
++                      GT_2trace(curTrace, GT_ENTER,
++                               "DRV_ProcDisplayResourceInfo: #:%d "
++                               "pCtxt->pSTRMList->hStream:%x\n", tempCount,
++                               pSTRMRes->hStream);
++                      tempStrLen2 = sprintf((char *)pTempBuf,
++                                           "Stream Resource info: STRM # %d "
++                                           "Stream Handle: 0x%x \n",
++                                           tempCount, (u32)pSTRMRes->hStream);
++                      pSTRMRes = pSTRMRes->next;
++                      tempStrLen2 += 2;
++                      memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++                      tempStrLen += tempStrLen2;
++                      tempCount++;
++              }
++              pCtxt = pCtxt->next;
++      }
++      *pSize = tempStrLen;
++      status = PrintProcessInformation();
++      GT_0trace(curTrace, GT_ENTER, "*********************"
++              "DRV_ProcDisplayResourceInfo:**\n");
++      return status;
++}
++
++/*
++ *  ======== PrintProcessInformation ========
++ *  Purpose:
++ *      This function prints the Process's information stored in
++ *      the process context list. Some of the information that
++ *      it displays is Process's state, Node, Stream, DMM, and
++ *      Heap information.
++ */
++static DSP_STATUS PrintProcessInformation(void)
++{
++      struct DRV_OBJECT *hDrvObject = NULL;
++      struct PROCESS_CONTEXT *pCtxtList = NULL;
++      struct NODE_RES_OBJECT *pNodeRes = NULL;
++      struct DMM_RES_OBJECT *pDMMRes = NULL;
++      struct STRM_RES_OBJECT *pSTRMRes = NULL;
++      struct DSPHEAP_RES_OBJECT *pDSPHEAPRes = NULL;
++      DSP_STATUS status = DSP_SOK;
++      u32 tempCount;
++      u32  procID;
++
++      /* Get the Process context list */
++      CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++      DRV_GetProcCtxtList(&pCtxtList, hDrvObject);
++      GT_0trace(curTrace, GT_4CLASS, "\n### Debug information"
++                      " for DSP bridge ##\n");
++      GT_0trace(curTrace, GT_4CLASS, " \n ###The  processes"
++                      " information is as follows ### \n") ;
++      GT_0trace(curTrace, GT_4CLASS, "  ====================="
++                      "============ \n");
++      /* Go through the entries in the Process context list */
++      while (pCtxtList  != NULL) {
++              GT_1trace(curTrace, GT_4CLASS, "\nThe process"
++                              " id is %d\n", pCtxtList->pid);
++              GT_0trace(curTrace, GT_4CLASS, " -------------------"
++                              "---------\n");
++              if (pCtxtList->resState == PROC_RES_ALLOCATED) {
++                      GT_0trace(curTrace, GT_4CLASS, " \nThe Process"
++                                      " is in Allocated state\n");
++              } else {
++                      GT_0trace(curTrace, GT_4CLASS, "\nThe Process"
++                                      " is in DeAllocated state\n");
++              }
++              GT_1trace(curTrace, GT_4CLASS, "\nThe  hProcessor"
++                              " handle is: 0X%x\n",
++                              (u32)pCtxtList->hProcessor);
++              if (pCtxtList->hProcessor != NULL) {
++                      PROC_GetProcessorId(pCtxtList->hProcessor, &procID);
++                      if (procID == DSP_UNIT) {
++                              GT_0trace(curTrace, GT_4CLASS,
++                                      "\nProcess connected to"
++                                      " DSP Processor\n");
++                      } else if (procID == IVA_UNIT) {
++                              GT_0trace(curTrace, GT_4CLASS,
++                                      "\nProcess connected to"
++                                      " IVA Processor\n");
++                      } else {
++                              GT_0trace(curTrace, GT_7CLASS,
++                                      "\n***ERROR:Invalid Processor Id***\n");
++                      }
++              }
++              pNodeRes = pCtxtList->pNodeList;
++              tempCount = 1;
++              while (pNodeRes != NULL) {
++                      if (tempCount == 1)
++                              GT_0trace(curTrace, GT_4CLASS,
++                                      "\n***The Nodes allocated by"
++                                      " this Process are***\n");
++                      GT_2trace(curTrace, GT_4CLASS,
++                                      "Node # %d Node Handle hNode:0x%x\n",
++                                      tempCount, (u32)pNodeRes->hNode);
++                      pNodeRes = pNodeRes->next;
++                      tempCount++;
++              }
++              if (tempCount == 1)
++                      GT_0trace(curTrace, GT_4CLASS,
++                                      "\n ***There are no Nodes"
++                                      " allocated by this Process***\n");
++              tempCount = 1;
++              pDSPHEAPRes = pCtxtList->pDSPHEAPList;
++              while (pDSPHEAPRes != NULL) {
++                      if (tempCount == 1)
++                              GT_0trace(curTrace, GT_4CLASS,
++                                              "\n***The Heaps allocated by"
++                                              " this Process are***\n");
++                      GT_3trace(curTrace, GT_4CLASS,
++                              "DSP Heap Resource Info: HEAP # %d "
++                              "Mapped GPP Address:0x%x, Size: 0x%lx\n",
++                              tempCount, (u32)pDSPHEAPRes->ulMpuAddr,
++                              pDSPHEAPRes->heapSize);
++                      pDSPHEAPRes = pDSPHEAPRes->next;
++                      tempCount++;
++              }
++              if (tempCount == 1)
++                      GT_0trace(curTrace, GT_4CLASS,
++                              "\n ***There are no Heaps allocated"
++                              " by this Process***\n");
++              tempCount = 1;
++              pDMMRes = pCtxtList->pDMMList;
++              while (pDMMRes != NULL) {
++                      if (tempCount == 1)
++                              GT_0trace(curTrace, GT_4CLASS,
++                                      "\n ***The DMM resources allocated by"
++                                      " this Process are***\n");
++                      GT_3trace(curTrace, GT_4CLASS,
++                              "DMM Resource Info: DMM # %d "
++                              "Mapped GPP Address:0X%lx, Size: 0X%lx\n",
++                              tempCount, pDMMRes->ulMpuAddr,
++                              pDMMRes->dmmSize);
++                      pDMMRes = pDMMRes->next;
++                      tempCount++;
++              }
++              if (tempCount == 1)
++                      GT_0trace(curTrace, GT_4CLASS,
++                              "\n ***There are no DMM resources"
++                              " allocated by this Process***\n");
++              tempCount = 1;
++              pSTRMRes = pCtxtList->pSTRMList;
++              while (pSTRMRes != NULL) {
++                      if (tempCount == 1)
++                              GT_0trace(curTrace, GT_4CLASS,
++                                      "\n***The Stream resources allocated by"
++                                      " this Process are***\n");
++                      GT_2trace(curTrace, GT_4CLASS,
++                              "Stream Resource info: STRM # %d"
++                              "Stream Handle:0X%x\n", tempCount,
++                              (u32)pSTRMRes->hStream);
++                      pSTRMRes = pSTRMRes->next;
++                      tempCount++;
++              }
++              if (tempCount == 1)
++                      GT_0trace(curTrace, GT_4CLASS,
++                              "\n ***There are no Stream resources"
++                              "allocated by this Process***\n");
++              pCtxtList = pCtxtList->next;
++      }
++      return status;
++}
++
++/* GPP PROCESS CLEANUP CODE END */
++#endif
++
++/*
++ *  ======== = DRV_Create ======== =
++ *  Purpose:
++ *      DRV Object gets created only once during Driver Loading.
++ */
++DSP_STATUS DRV_Create(OUT struct DRV_OBJECT **phDRVObject)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DRV_OBJECT *pDRVObject = NULL;
++
++      DBC_Require(phDRVObject != NULL);
++      DBC_Require(cRefs > 0);
++      GT_1trace(curTrace, GT_ENTER, "Entering DRV_Create"
++                      " phDRVObject 0x%x\n", phDRVObject);
++      MEM_AllocObject(pDRVObject, struct DRV_OBJECT, SIGNATURE);
++      if (pDRVObject) {
++              /* Create and Initialize List of device objects */
++              pDRVObject->devList = LST_Create();
++              if (pDRVObject->devList) {
++                      /* Create and Initialize List of device Extension */
++                      pDRVObject->devNodeString = LST_Create();
++                      if (!(pDRVObject->devNodeString)) {
++                              status = DSP_EFAIL;
++                              GT_0trace(curTrace, GT_7CLASS,
++                                       "Failed to Create DRV_EXT list ");
++                              MEM_FreeObject(pDRVObject);
++                      }
++              } else {
++                      status = DSP_EFAIL;
++                      GT_0trace(curTrace, GT_7CLASS,
++                               "Failed to Create Dev List ");
++                      MEM_FreeObject(pDRVObject);
++              }
++      } else {
++              status = DSP_EFAIL;
++              GT_0trace(curTrace, GT_7CLASS,
++                       "Failed to Allocate Memory for DRV Obj");
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Store the DRV Object in the Registry */
++              if (DSP_SUCCEEDED
++                  (CFG_SetObject((u32) pDRVObject, REG_DRV_OBJECT))) {
++                      GT_1trace(curTrace, GT_1CLASS,
++                               "DRV Obj Created pDrvObject 0x%x\n ",
++                               pDRVObject);
++                      *phDRVObject = pDRVObject;
++              } else {
++                      /* Free the DRV Object */
++                      status = DSP_EFAIL;
++                      MEM_Free(pDRVObject);
++                      GT_0trace(curTrace, GT_7CLASS,
++                               "Failed to update the Registry with "
++                               "DRV Object ");
++              }
++      }
++      GT_2trace(curTrace, GT_ENTER,
++               "Exiting DRV_Create: phDRVObject: 0x%x\tstatus:"
++               "0x%x\n", phDRVObject, status);
++      DBC_Ensure(DSP_FAILED(status) ||
++                MEM_IsValidHandle(pDRVObject, SIGNATURE));
++      return status;
++}
++
++/*
++ *  ======== DRV_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the DRV module.
++ */
++void DRV_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      GT_0trace(curTrace, GT_5CLASS, "Entering DRV_Exit \n");
++
++      cRefs--;
++
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== = DRV_Destroy ======== =
++ *  purpose:
++ *      Invoked during bridge de-initialization
++ */
++DSP_STATUS DRV_Destroy(struct DRV_OBJECT *hDRVObject)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
++
++      GT_1trace(curTrace, GT_ENTER, "Entering DRV_Destroy"
++                      " hDRVObject 0x%x\n", hDRVObject);
++      /*
++       *  Delete the List if it exists.Should not come here
++       *  as the DRV_RemoveDevObject and the Last DRV_RequestResources
++       *  removes the list if the lists are empty.
++       */
++      if (pDRVObject->devList) {
++              /* Could assert if the list is not empty  */
++              LST_Delete(pDRVObject->devList);
++      }
++      if (pDRVObject->devNodeString) {
++              /* Could assert if the list is not empty */
++              LST_Delete(pDRVObject->devNodeString);
++      }
++      MEM_FreeObject(pDRVObject);
++      /* Update the DRV Object in Registry to be 0 */
++      (void)CFG_SetObject(0, REG_DRV_OBJECT);
++      GT_2trace(curTrace, GT_ENTER,
++               "Exiting DRV_Destroy: hDRVObject: 0x%x\tstatus:"
++               "0x%x\n", hDRVObject, status);
++      DBC_Ensure(!MEM_IsValidHandle(pDRVObject, SIGNATURE));
++      return status;
++}
++
++/*
++ *  ======== DRV_GetDevObject ========
++ *  Purpose:
++ *      Given a index, returns a handle to DevObject from the list.
++ */
++DSP_STATUS DRV_GetDevObject(u32 uIndex, struct DRV_OBJECT *hDrvObject,
++                         struct DEV_OBJECT **phDevObject)
++{
++      DSP_STATUS status = DSP_SOK;
++#if GT_TRACE  /* pDrvObject is used only for Assertions and debug messages.*/
++      struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
++#endif
++      struct DEV_OBJECT *pDevObject;
++      u32 i;
++      DBC_Require(MEM_IsValidHandle(pDrvObject, SIGNATURE));
++      DBC_Require(phDevObject != NULL);
++      DBC_Require(uIndex >= 0);
++      DBC_Require(cRefs > 0);
++      DBC_Assert(!(LST_IsEmpty(pDrvObject->devList)));
++      GT_3trace(curTrace, GT_ENTER,
++               "Entered DRV_GetDevObject, args:\n\tuIndex: "
++               "0x%x\n\thDrvObject:  0x%x\n\tphDevObject:  0x%x\n",
++               uIndex, hDrvObject, phDevObject);
++      pDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++      for (i = 0; i < uIndex; i++) {
++              pDevObject =
++                 (struct DEV_OBJECT *)DRV_GetNextDevObject((u32)pDevObject);
++      }
++      if (pDevObject) {
++              *phDevObject = (struct DEV_OBJECT *) pDevObject;
++              status = DSP_SOK;
++      } else {
++              *phDevObject = NULL;
++              status = DSP_EFAIL;
++              GT_0trace(curTrace, GT_7CLASS,
++                       "DRV: Could not get the DevObject\n");
++      }
++      GT_2trace(curTrace, GT_ENTER,
++               "Exiting Drv_GetDevObject\n\tstatus: 0x%x\n\t"
++               "hDevObject: 0x%x\n", status, *phDevObject);
++      return status;
++}
++
++/*
++ *  ======== DRV_GetFirstDevObject ========
++ *  Purpose:
++ *      Retrieve the first Device Object handle from an internal linked list of
++ *      of DEV_OBJECTs maintained by DRV.
++ */
++u32 DRV_GetFirstDevObject(void)
++{
++      u32 dwDevObject = 0;
++      struct DRV_OBJECT *pDrvObject;
++
++      if (DSP_SUCCEEDED
++          (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
++              if ((pDrvObject->devList != NULL) &&
++                 !LST_IsEmpty(pDrvObject->devList))
++                      dwDevObject = (u32) LST_First(pDrvObject->devList);
++      }
++
++      return dwDevObject;
++}
++
++/*
++ *  ======== DRV_GetFirstDevNodeString ========
++ *  Purpose:
++ *      Retrieve the first Device Extension from an internal linked list of
++ *      of Pointer to DevNode Strings maintained by DRV.
++ */
++u32 DRV_GetFirstDevExtension(void)
++{
++      u32 dwDevExtension = 0;
++      struct DRV_OBJECT *pDrvObject;
++
++      if (DSP_SUCCEEDED
++          (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
++
++              if ((pDrvObject->devNodeString != NULL) &&
++                 !LST_IsEmpty(pDrvObject->devNodeString)) {
++                      dwDevExtension = (u32)LST_First(pDrvObject->
++                                                      devNodeString);
++              }
++      }
++
++      return dwDevExtension;
++}
++
++/*
++ *  ======== DRV_GetNextDevObject ========
++ *  Purpose:
++ *      Retrieve the next Device Object handle from an internal linked list of
++ *      of DEV_OBJECTs maintained by DRV, after having previously called
++ *      DRV_GetFirstDevObject() and zero or more DRV_GetNext.
++ */
++u32 DRV_GetNextDevObject(u32 hDevObject)
++{
++      u32 dwNextDevObject = 0;
++      struct DRV_OBJECT *pDrvObject;
++
++      DBC_Require(hDevObject != 0);
++
++      if (DSP_SUCCEEDED
++          (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
++
++              if ((pDrvObject->devList != NULL) &&
++                 !LST_IsEmpty(pDrvObject->devList)) {
++                      dwNextDevObject = (u32)LST_Next(pDrvObject->devList,
++                                        (struct LST_ELEM *)hDevObject);
++              }
++      }
++      return dwNextDevObject;
++}
++
++/*
++ *  ======== DRV_GetNextDevExtension ========
++ *  Purpose:
++ *      Retrieve the next Device Extension from an internal linked list of
++ *      of pointer to DevNodeString maintained by DRV, after having previously
++ *      called DRV_GetFirstDevExtension() and zero or more
++ *      DRV_GetNextDevExtension().
++ */
++u32 DRV_GetNextDevExtension(u32 hDevExtension)
++{
++      u32 dwDevExtension = 0;
++      struct DRV_OBJECT *pDrvObject;
++
++      DBC_Require(hDevExtension != 0);
++
++      if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&pDrvObject,
++         REG_DRV_OBJECT))) {
++              if ((pDrvObject->devNodeString != NULL) &&
++                 !LST_IsEmpty(pDrvObject->devNodeString)) {
++                      dwDevExtension = (u32)LST_Next(pDrvObject->
++                              devNodeString,
++                              (struct LST_ELEM *)hDevExtension);
++              }
++      }
++
++      return dwDevExtension;
++}
++
++/*
++ *  ======== DRV_Init ========
++ *  Purpose:
++ *      Initialize DRV module private state.
++ */
++DSP_STATUS DRV_Init(void)
++{
++      s32 fRetval = 1;        /* function return value */
++
++      DBC_Require(cRefs >= 0);
++
++      if (fRetval)
++              cRefs++;
++
++      GT_1trace(curTrace, GT_5CLASS, "Entering DRV_Entry  crefs 0x%x \n",
++               cRefs);
++
++      DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++      return fRetval;
++}
++
++/*
++ *  ======== DRV_InsertDevObject ========
++ *  Purpose:
++ *      Insert a DevObject into the list of Manager object.
++ */
++DSP_STATUS DRV_InsertDevObject(struct DRV_OBJECT *hDRVObject,
++                             struct DEV_OBJECT *hDevObject)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(hDevObject != NULL);
++      DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
++      DBC_Assert(pDRVObject->devList);
++
++      GT_2trace(curTrace, GT_ENTER,
++               "Entering DRV_InsertProcObject hDRVObject "
++               "0x%x\n, hDevObject 0x%x\n", hDRVObject, hDevObject);
++
++      LST_PutTail(pDRVObject->devList, (struct LST_ELEM *)hDevObject);
++
++      GT_1trace(curTrace, GT_ENTER,
++               "Exiting InsertDevObject status 0x%x\n", status);
++
++      DBC_Ensure(DSP_SUCCEEDED(status) && !LST_IsEmpty(pDRVObject->devList));
++
++      return status;
++}
++
++/*
++ *  ======== DRV_RemoveDevObject ========
++ *  Purpose:
++ *      Search for and remove a DeviceObject from the given list of DRV
++ *      objects.
++ */
++DSP_STATUS DRV_RemoveDevObject(struct DRV_OBJECT *hDRVObject,
++                             struct DEV_OBJECT *hDevObject)
++{
++      DSP_STATUS status = DSP_EFAIL;
++      struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
++      struct LST_ELEM *pCurElem;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
++      DBC_Require(hDevObject != NULL);
++
++      DBC_Require(pDRVObject->devList != NULL);
++      DBC_Require(!LST_IsEmpty(pDRVObject->devList));
++
++      GT_2trace(curTrace, GT_ENTER,
++               "Entering DRV_RemoveDevObject hDevObject "
++               "0x%x\n, hDRVObject 0x%x\n", hDevObject, hDRVObject);
++      /* Search list for pProcObject: */
++      for (pCurElem = LST_First(pDRVObject->devList); pCurElem != NULL;
++          pCurElem = LST_Next(pDRVObject->devList, pCurElem)) {
++              /* If found, remove it. */
++              if ((struct DEV_OBJECT *) pCurElem == hDevObject) {
++                      LST_RemoveElem(pDRVObject->devList, pCurElem);
++                      status = DSP_SOK;
++                      break;
++              }
++      }
++      /* Remove list if empty. */
++      if (LST_IsEmpty(pDRVObject->devList)) {
++              LST_Delete(pDRVObject->devList);
++              pDRVObject->devList = NULL;
++      }
++      DBC_Ensure((pDRVObject->devList == NULL) ||
++                !LST_IsEmpty(pDRVObject->devList));
++      GT_1trace(curTrace, GT_ENTER,
++               "DRV_RemoveDevObject returning 0x%x\n", status);
++      return status;
++}
++
++/*
++ *  ======== DRV_RequestResources ========
++ *  Purpose:
++ *      Requests  resources from the OS.
++ */
++DSP_STATUS DRV_RequestResources(u32 dwContext, u32 *pDevNodeString)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DRV_OBJECT *pDRVObject;
++      struct DRV_EXT *pszdevNode;
++
++      DBC_Require(dwContext != 0);
++      DBC_Require(pDevNodeString != NULL);
++      GT_0trace(curTrace, GT_ENTER, "Entering DRV_RequestResources\n");
++      /*
++       *  Allocate memory to hold the string. This will live untill
++       *  it is freed in the Release resources. Update the driver object
++       *  list.
++       */
++      if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&pDRVObject,
++         REG_DRV_OBJECT))) {
++              pszdevNode = MEM_Calloc(sizeof(struct DRV_EXT), MEM_NONPAGED);
++              if (pszdevNode) {
++                      LST_InitElem(&pszdevNode->link);
++                       strncpy((char *) pszdevNode->szString,
++                               (char *)dwContext, MAXREGPATHLENGTH);
++                      /* Update the Driver Object List */
++                      *pDevNodeString = (u32)pszdevNode->szString;
++                      LST_PutTail(pDRVObject->devNodeString,
++                              (struct LST_ELEM *)pszdevNode);
++              } else {
++                      GT_0trace(curTrace, GT_7CLASS,
++                              "Failed to Allocate Memory devNodeString ");
++                      status = DSP_EFAIL;
++                      *pDevNodeString = 0;
++              }
++      } else {
++              status = DSP_EFAIL;
++              GT_0trace(curTrace, GT_7CLASS,
++                       "Failed to get Driver Object from Registry");
++              *pDevNodeString = 0;
++      }
++
++       if (!(strcmp((char *) dwContext, "TIOMAP1510"))) {
++              GT_0trace(curTrace, GT_1CLASS,
++                        " Allocating resources for UMA \n");
++              status = RequestBridgeResourcesDSP(dwContext, DRV_ASSIGN);
++      } else {
++              status = DSP_EFAIL;
++              GT_0trace(curTrace, GT_7CLASS, "Unknown Device ");
++      }
++
++      if (DSP_FAILED(status)) {
++              GT_0trace(curTrace, GT_7CLASS,
++                       "Failed to reserve bridge resources ");
++      }
++      DBC_Ensure((DSP_SUCCEEDED(status) && pDevNodeString != NULL &&
++                !LST_IsEmpty(pDRVObject->devNodeString)) ||
++                (DSP_FAILED(status) && *pDevNodeString == 0));
++
++      return status;
++}
++
++/*
++ *  ======== DRV_ReleaseResources ========
++ *  Purpose:
++ *      Releases  resources from the OS.
++ */
++DSP_STATUS DRV_ReleaseResources(u32 dwContext, struct DRV_OBJECT *hDrvObject)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDrvObject;
++      struct DRV_EXT *pszdevNode;
++
++      GT_0trace(curTrace, GT_ENTER, "Entering DRV_Release Resources\n");
++
++       if (!(strcmp((char *)((struct DRV_EXT *)dwContext)->szString,
++         "TIOMAP1510"))) {
++              GT_0trace(curTrace, GT_1CLASS,
++                       " Releasing DSP-Bridge resources \n");
++              status = RequestBridgeResources(dwContext, DRV_RELEASE);
++      } else {
++              GT_0trace(curTrace, GT_1CLASS, " Unknown device\n");
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              GT_0trace(curTrace, GT_1CLASS,
++                       "Failed to relese bridge resources\n");
++      }
++
++      /*
++       *  Irrespective of the status go ahead and clean it
++       *  The following will over write the status.
++       */
++      for (pszdevNode = (struct DRV_EXT *)DRV_GetFirstDevExtension();
++          pszdevNode != NULL; pszdevNode = (struct DRV_EXT *)
++          DRV_GetNextDevExtension((u32)pszdevNode)) {
++              if ((u32)pszdevNode == dwContext) {
++                      /* Found it */
++                      /* Delete from the Driver object list */
++                      LST_RemoveElem(pDRVObject->devNodeString,
++                                    (struct LST_ELEM *)pszdevNode);
++                      MEM_Free((void *) pszdevNode);
++                      break;
++              }
++              /* Delete the List if it is empty */
++              if (LST_IsEmpty(pDRVObject->devNodeString)) {
++                      LST_Delete(pDRVObject->devNodeString);
++                      pDRVObject->devNodeString = NULL;
++              }
++      }
++      return status;
++}
++
++/*
++ *  ======== RequestBridgeResources ========
++ *  Purpose:
++ *      Reserves shared memory for bridge.
++ */
++static DSP_STATUS RequestBridgeResources(u32 dwContext, s32 bRequest)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct CFG_HOSTRES *pResources;
++      u32 dwBuffSize;
++
++      struct DRV_EXT *driverExt;
++      u32 shm_size;
++
++      DBC_Require(dwContext != 0);
++
++      GT_0trace(curTrace, GT_ENTER, "->RequestBridgeResources \n");
++
++      if (!bRequest) {
++              driverExt = (struct DRV_EXT *)dwContext;
++              /* Releasing resources by deleting the registry key  */
++              dwBuffSize = sizeof(struct CFG_HOSTRES);
++              pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
++              if (DSP_FAILED(REG_GetValue(NULL, (char *)driverExt->szString,
++                 CURRENTCONFIG, (u8 *)pResources, &dwBuffSize))) {
++                      status = CFG_E_RESOURCENOTAVAIL;
++                      GT_0trace(curTrace, GT_1CLASS,
++                               "REG_GetValue Failed \n");
++              } else {
++                      GT_0trace(curTrace, GT_1CLASS,
++                               "REG_GetValue Succeeded \n");
++              }
++
++              if (pResources != NULL) {
++                      dwBuffSize = sizeof(shm_size);
++                      status = REG_GetValue(NULL, CURRENTCONFIG, SHMSIZE,
++                              (u8 *)&shm_size, &dwBuffSize);
++                      if (DSP_SUCCEEDED(status)) {
++                              if ((pResources->dwMemBase[1]) &&
++                                 (pResources->dwMemPhys[1])) {
++                                      MEM_FreePhysMem((void *)pResources->
++                                      dwMemBase[1], pResources->dwMemPhys[1],
++                                      shm_size);
++                              }
++                      } else {
++                              GT_1trace(curTrace, GT_7CLASS,
++                                      "Error getting SHM size from registry: "
++                                      "%x. Not calling MEM_FreePhysMem\n",
++                                      status);
++                      }
++                      pResources->dwMemBase[1] = 0;
++                      pResources->dwMemPhys[1] = 0;
++
++                      if (pResources->dwPrmBase)
++                              iounmap((void *)pResources->dwPrmBase);
++                      if (pResources->dwCmBase)
++                              iounmap((void *)pResources->dwCmBase);
++                      if (pResources->dwMboxBase)
++                              iounmap((void *)pResources->dwMboxBase);
++                      if (pResources->dwMemBase[0])
++                              iounmap((void *)pResources->dwMemBase[0]);
++                      if (pResources->dwMemBase[2])
++                              iounmap((void *)pResources->dwMemBase[2]);
++                      if (pResources->dwMemBase[3])
++                              iounmap((void *)pResources->dwMemBase[3]);
++                      if (pResources->dwMemBase[4])
++                              iounmap((void *)pResources->dwMemBase[4]);
++                      if (pResources->dwWdTimerDspBase)
++                              iounmap((void *)pResources->dwWdTimerDspBase);
++                      if (pResources->dwDmmuBase)
++                              iounmap((void *)pResources->dwDmmuBase);
++                      if (pResources->dwPerBase)
++                              iounmap((void *)pResources->dwPerBase);
++                       if (pResources->dwPerPmBase)
++                               iounmap((void *)pResources->dwPerPmBase);
++                       if (pResources->dwCorePmBase)
++                               iounmap((void *)pResources->dwCorePmBase);
++                      if (pResources->dwSysCtrlBase) {
++                              iounmap((void *)pResources->dwSysCtrlBase);
++                              /* don't set pResources->dwSysCtrlBase to null
++                               * as it is used in BOARD_Stop */
++                      }
++                      pResources->dwPrmBase = (u32) NULL;
++                      pResources->dwCmBase = (u32) NULL;
++                      pResources->dwMboxBase = (u32) NULL;
++                      pResources->dwMemBase[0] = (u32) NULL;
++                      pResources->dwMemBase[2] = (u32) NULL;
++                      pResources->dwMemBase[3] = (u32) NULL;
++                      pResources->dwMemBase[4] = (u32) NULL;
++                      pResources->dwWdTimerDspBase = (u32) NULL;
++                      pResources->dwDmmuBase = (u32) NULL;
++
++                      dwBuffSize = sizeof(struct CFG_HOSTRES);
++                      status = REG_SetValue(NULL, (char *)driverExt->szString,
++                               CURRENTCONFIG, REG_BINARY, (u8 *)pResources,
++                               (u32)dwBuffSize);
++                      /*  Set all the other entries to NULL */
++                      MEM_Free(pResources);
++              }
++              GT_0trace(curTrace, GT_ENTER, " <- RequestBridgeResources \n");
++              return status;
++      }
++      dwBuffSize = sizeof(struct CFG_HOSTRES);
++      pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
++      if (pResources != NULL) {
++              /* wNumMemWindows must not be more than CFG_MAXMEMREGISTERS */
++              pResources->wNumMemWindows = 2;
++              /* First window is for DSP internal memory */
++
++              pResources->dwPrmBase = (u32)ioremap(OMAP_IVA2_PRM_BASE,
++                                                      OMAP_IVA2_PRM_SIZE);
++              pResources->dwCmBase = (u32)ioremap(OMAP_IVA2_CM_BASE,
++                                                      OMAP_IVA2_CM_SIZE);
++              pResources->dwMboxBase = (u32)ioremap(OMAP_MBOX_BASE,
++                                                      OMAP_MBOX_SIZE);
++              pResources->dwSysCtrlBase = (u32)ioremap(OMAP_SYSC_BASE,
++                                                      OMAP_SYSC_SIZE);
++              GT_1trace(curTrace, GT_2CLASS, "dwMemBase[0] 0x%x\n",
++                       pResources->dwMemBase[0]);
++              GT_1trace(curTrace, GT_2CLASS, "dwMemBase[3] 0x%x\n",
++                       pResources->dwMemBase[3]);
++              GT_1trace(curTrace, GT_2CLASS, "dwPrmBase 0x%x\n",
++                                                      pResources->dwPrmBase);
++              GT_1trace(curTrace, GT_2CLASS, "dwCmBase 0x%x\n",
++                                                      pResources->dwCmBase);
++              GT_1trace(curTrace, GT_2CLASS, "dwWdTimerDspBase 0x%x\n",
++                                              pResources->dwWdTimerDspBase);
++              GT_1trace(curTrace, GT_2CLASS, "dwMboxBase 0x%x\n",
++                                              pResources->dwMboxBase);
++              GT_1trace(curTrace, GT_2CLASS, "dwDmmuBase 0x%x\n",
++                                              pResources->dwDmmuBase);
++
++              /* for 24xx base port is not mapping the mamory for DSP
++               * internal memory TODO Do a ioremap here */
++              /* Second window is for DSP external memory shared with MPU */
++              if (DSP_SUCCEEDED(status)) {
++                      /* for Linux, these are hard-coded values */
++                      pResources->dwBusType = 0;
++                      pResources->bIRQRegisters = 0;
++                      pResources->bIRQAttrib = 0;
++                      pResources->dwOffsetForMonitor = 0;
++                      pResources->dwChnlOffset = 0;
++                      /* CHNL_MAXCHANNELS */
++                      pResources->dwNumChnls = CHNL_MAXCHANNELS;
++                      pResources->dwChnlBufSize = 0x400;
++                      dwBuffSize = sizeof(struct CFG_HOSTRES);
++                      status = REG_SetValue(NULL, (char *) dwContext,
++                                           CURRENTCONFIG, REG_BINARY,
++                                           (u8 *)pResources,
++                                           sizeof(struct CFG_HOSTRES));
++                      if (DSP_SUCCEEDED(status)) {
++                              GT_0trace(curTrace, GT_1CLASS,
++                                       " Successfully set the registry "
++                                       "value for CURRENTCONFIG\n");
++                      } else {
++                              GT_0trace(curTrace, GT_7CLASS,
++                                       " Failed to set the registry "
++                                       "value for CURRENTCONFIG\n");
++                      }
++              }
++              MEM_Free(pResources);
++      }
++      /* End Mem alloc */
++      return status;
++}
++
++/*
++ *  ======== RequestBridgeResourcesDSP ========
++ *  Purpose:
++ *      Reserves shared memory for bridge.
++ */
++static DSP_STATUS RequestBridgeResourcesDSP(u32 dwContext, s32 bRequest)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct CFG_HOSTRES *pResources;
++      u32 dwBuffSize;
++      u32 dmaAddr;
++      u32 shm_size;
++
++      DBC_Require(dwContext != 0);
++
++      GT_0trace(curTrace, GT_ENTER, "->RequestBridgeResourcesDSP \n");
++
++      dwBuffSize = sizeof(struct CFG_HOSTRES);
++
++      pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
++
++      if (pResources != NULL) {
++              if (DSP_FAILED(CFG_GetHostResources((struct CFG_DEVNODE *)
++                 dwContext, pResources))) {
++                      /* Call CFG_GetHostResources to get reserve resouces */
++                      status = RequestBridgeResources(dwContext, bRequest);
++                      if (DSP_SUCCEEDED(status)) {
++                              status = CFG_GetHostResources
++                                      ((struct CFG_DEVNODE *) dwContext,
++                                      pResources);
++                      }
++              }
++              /* wNumMemWindows must not be more than CFG_MAXMEMREGISTERS */
++              pResources->wNumMemWindows = 4;
++
++              pResources->dwMemBase[0] = 0;
++              pResources->dwMemBase[2] = (u32)ioremap(OMAP_DSP_MEM1_BASE,
++                                                      OMAP_DSP_MEM1_SIZE);
++              pResources->dwMemBase[3] = (u32)ioremap(OMAP_DSP_MEM2_BASE,
++                                                      OMAP_DSP_MEM2_SIZE);
++              pResources->dwMemBase[4] = (u32)ioremap(OMAP_DSP_MEM3_BASE,
++                                                      OMAP_DSP_MEM3_SIZE);
++              pResources->dwPerBase = (u32)ioremap(OMAP_PER_CM_BASE,
++                                                      OMAP_PER_CM_SIZE);
++               pResources->dwPerPmBase = (u32)ioremap(OMAP_PER_PRM_BASE,
++                                                       OMAP_PER_PRM_SIZE);
++               pResources->dwCorePmBase = (u32)ioremap(OMAP_CORE_PRM_BASE,
++                                                       OMAP_CORE_PRM_SIZE);
++              pResources->dwDmmuBase = (u32)ioremap(OMAP_DMMU_BASE,
++                                                      OMAP_DMMU_SIZE);
++              pResources->dwWdTimerDspBase = 0;
++
++              GT_1trace(curTrace, GT_2CLASS, "dwMemBase[0] 0x%x\n",
++                                              pResources->dwMemBase[0]);
++              GT_1trace(curTrace, GT_2CLASS, "dwMemBase[1] 0x%x\n",
++                                              pResources->dwMemBase[1]);
++              GT_1trace(curTrace, GT_2CLASS, "dwMemBase[2] 0x%x\n",
++                                              pResources->dwMemBase[2]);
++              GT_1trace(curTrace, GT_2CLASS, "dwMemBase[3] 0x%x\n",
++                                              pResources->dwMemBase[3]);
++              GT_1trace(curTrace, GT_2CLASS, "dwMemBase[4] 0x%x\n",
++                                              pResources->dwMemBase[4]);
++              GT_1trace(curTrace, GT_2CLASS, "dwPrmBase 0x%x\n",
++                                              pResources->dwPrmBase);
++              GT_1trace(curTrace, GT_2CLASS, "dwCmBase 0x%x\n",
++                                              pResources->dwCmBase);
++              GT_1trace(curTrace, GT_2CLASS, "dwWdTimerDspBase 0x%x\n",
++                                              pResources->dwWdTimerDspBase);
++              GT_1trace(curTrace, GT_2CLASS, "dwMboxBase 0x%x\n",
++                                              pResources->dwMboxBase);
++              GT_1trace(curTrace, GT_2CLASS, "dwDmmuBase 0x%x\n",
++                                              pResources->dwDmmuBase);
++              dwBuffSize = sizeof(shm_size);
++              status = REG_GetValue(NULL, CURRENTCONFIG, SHMSIZE,
++                                   (u8 *)&shm_size, &dwBuffSize);
++              if (DSP_SUCCEEDED(status)) {
++                      /* Allocate Physically contiguous,
++                       * non-cacheable  memory */
++                      pResources->dwMemBase[1] =
++                              (u32)MEM_AllocPhysMem(shm_size, 0x100000,
++                                                      &dmaAddr);
++                      if (pResources->dwMemBase[1] == 0) {
++                              status = DSP_EMEMORY;
++                              GT_0trace(curTrace, GT_7CLASS,
++                                       "SHM reservation Failed\n");
++                      } else {
++                              pResources->dwMemLength[1] = shm_size;
++                              pResources->dwMemPhys[1] = dmaAddr;
++
++                              GT_3trace(curTrace, GT_1CLASS,
++                                       "Bridge SHM address 0x%x dmaAddr"
++                                       " %x size %x\n",
++                                       pResources->dwMemBase[1],
++                                       dmaAddr, shm_size);
++                      }
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      /* for Linux, these are hard-coded values */
++                      pResources->dwBusType = 0;
++                      pResources->bIRQRegisters = 0;
++                      pResources->bIRQAttrib = 0;
++                      pResources->dwOffsetForMonitor = 0;
++                      pResources->dwChnlOffset = 0;
++                      /* CHNL_MAXCHANNELS */
++                      pResources->dwNumChnls = CHNL_MAXCHANNELS;
++                      pResources->dwChnlBufSize = 0x400;
++                      dwBuffSize = sizeof(struct CFG_HOSTRES);
++                      status = REG_SetValue(NULL, (char *)dwContext,
++                                           CURRENTCONFIG, REG_BINARY,
++                                           (u8 *)pResources,
++                                           sizeof(struct CFG_HOSTRES));
++                      if (DSP_SUCCEEDED(status)) {
++                              GT_0trace(curTrace, GT_1CLASS,
++                                       " Successfully set the registry"
++                                       " value for CURRENTCONFIG\n");
++                      } else {
++                              GT_0trace(curTrace, GT_7CLASS,
++                                       " Failed to set the registry value"
++                                       " for CURRENTCONFIG\n");
++                      }
++              }
++              MEM_Free(pResources);
++      }
++      /* End Mem alloc */
++      return status;
++}
+diff --git a/drivers/dsp/bridge/rmgr/drv_interface.c b/drivers/dsp/bridge/rmgr/drv_interface.c
+new file mode 100644
+index 0000000..4aa7de6
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/drv_interface.c
+@@ -0,0 +1,777 @@
++/*
++ * drv_interface.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== linux_driver.c ========
++ *  Description:
++ *      DSP/BIOS Bridge driver interface.
++ *
++ *  Public Functions:
++ *      driver_init
++ *      driver_exit
++ *      driver_open
++ *      driver_release
++ *      driver_ioctl
++ *      driver_mmap
++ *
++ *! Revision History
++ *! ================
++ *! 21-Apr-2004 map   Deprecated use of MODULE_PARM for kernel versions
++ *!              greater than 2.5, use module_param.
++ *! 08-Mar-2004 sb    Added the dsp_debug argument, which keeps the DSP in self
++ *!              loop after image load and waits in a loop for DSP to start
++ *! 16-Feb-2004 vp    Deprecated the usage of MOD_INC_USE_COUNT and
++ *!                                           MOD_DEC_USE_COUNT
++ *!              for kernel versions greater than 2.5
++ *! 20-May-2003 vp    Added unregister functions for the DPM.
++ *! 24-Mar-2003 sb    Pass pid instead of driverContext to DSP_Close
++ *! 24-Mar-2003 vp    Added Power Management support.
++ *! 21-Mar-2003 sb    Configure SHM size using insmod argument shm_size
++ *! 10-Feb-2003 vp    Updated based on code review comments
++ *! 18-Oct-2002 sb    Created initial version
++ */
++
++/*  ----------------------------------- Host OS */
++
++#include <dspbridge/host_os.h>
++#include <linux/platform_device.h>
++#include <linux/pm.h>
++
++#ifdef MODULE
++#include <linux/module.h>
++#endif
++
++#include <linux/device.h>
++#include <linux/init.h>
++#include <linux/moduleparam.h>
++#include <linux/cdev.h>
++
++#include <mach/board-3430sdp.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++#include <dspbridge/dbc.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/services.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/reg.h>
++#include <dspbridge/csl.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/wcdioctl.h>
++#include <dspbridge/_dcd.h>
++#include <dspbridge/dspdrv.h>
++#include <dspbridge/dbreg.h>
++
++/*  ----------------------------------- Resource Manager */
++#include <dspbridge/pwr.h>
++
++/*  ----------------------------------- This */
++#include <drv_interface.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/cfg.h>
++#include <dspbridge/resourcecleanup.h>
++#include <dspbridge/chnl.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/drvdefs.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/dbreg.h>
++#endif
++
++#ifdef CONFIG_BRIDGE_DVFS
++#include <mach/omap-pm.h>
++#include <mach-omap2/omap3-opp.h>
++#endif
++
++#define BRIDGE_NAME "C6410"
++/*  ----------------------------------- Globals */
++#define DRIVER_NAME  "DspBridge"
++#define DRIVER_MAJOR 0                /* Linux assigns our Major device number */
++#define DRIVER_MINOR 0                /* Linux assigns our Major device number */
++s32 dsp_debug;
++
++struct platform_device *omap_dspbridge_dev;
++
++struct bridge_dev {
++      struct cdev cdev;
++};
++
++static struct bridge_dev *bridge_device;
++
++static struct class *bridge_class;
++
++static u32 driverContext;
++#ifdef CONFIG_BRIDGE_DEBUG
++static char *GT_str;
++#endif /* CONFIG_BRIDGE_DEBUG */
++static s32 driver_major = DRIVER_MAJOR;
++static s32 driver_minor = DRIVER_MINOR;
++static char *base_img;
++char *iva_img;
++static char *num_procs = "C55=1";
++static s32 shm_size = 0x400000;       /* 4 MB */
++static u32 phys_mempool_base;
++static u32 phys_mempool_size;
++static int tc_wordswapon;     /* Default value is always false */
++
++#ifdef CONFIG_PM
++struct omap34xx_bridge_suspend_data {
++      int suspended;
++      wait_queue_head_t suspend_wq;
++};
++
++static struct omap34xx_bridge_suspend_data bridge_suspend_data;
++
++static int omap34xxbridge_suspend_lockout(
++              struct omap34xx_bridge_suspend_data *s, struct file *f)
++{
++      if ((s)->suspended) {
++              if ((f)->f_flags & O_NONBLOCK)
++                      return DSP_EDPMSUSPEND;
++              wait_event_interruptible((s)->suspend_wq, (s)->suspended == 0);
++      }
++      return 0;
++}
++
++#endif
++
++#ifdef DEBUG
++module_param(GT_str, charp, 0);
++MODULE_PARM_DESC(GT_str, "GT string, default = NULL");
++
++module_param(dsp_debug, int, 0);
++MODULE_PARM_DESC(dsp_debug, "Wait after loading DSP image. default = false");
++#endif
++
++module_param(driver_major, int, 0);   /* Driver's major number */
++MODULE_PARM_DESC(driver_major, "Major device number, default = 0 (auto)");
++
++module_param(driver_minor, int, 0);   /* Driver's major number */
++MODULE_PARM_DESC(driver_minor, "Minor device number, default = 0 (auto)");
++
++module_param(base_img, charp, 0);
++MODULE_PARM_DESC(base_img, "DSP base image, default = NULL");
++
++module_param(shm_size, int, 0);
++MODULE_PARM_DESC(shm_size, "SHM size, default = 4 MB, minimum = 64 KB");
++
++module_param(phys_mempool_base, uint, 0);
++MODULE_PARM_DESC(phys_mempool_base,
++              "Physical memory pool base passed to driver");
++
++module_param(phys_mempool_size, uint, 0);
++MODULE_PARM_DESC(phys_mempool_size,
++              "Physical memory pool size passed to driver");
++module_param(tc_wordswapon, int, 0);
++MODULE_PARM_DESC(tc_wordswapon, "TC Word Swap Option. default = 0");
++
++MODULE_AUTHOR("Texas Instruments");
++MODULE_LICENSE("GPL");
++
++static char *driver_name = DRIVER_NAME;
++
++#ifdef CONFIG_BRIDGE_DEBUG
++static struct GT_Mask driverTrace;
++#endif /* CONFIG_BRIDGE_DEBUG */
++
++static struct file_operations bridge_fops = {
++      .open           = bridge_open,
++      .release        = bridge_release,
++      .ioctl          = bridge_ioctl,
++      .mmap           = bridge_mmap,
++};
++
++#ifdef CONFIG_PM
++static u32 timeOut = 1000;
++#ifdef CONFIG_BRIDGE_DVFS
++static struct clk *clk_handle;
++s32 dsp_max_opps = VDD1_OPP3;
++#endif
++
++/* Maximum Opps that can be requested by IVA*/
++/*vdd1 rate table*/
++#ifdef CONFIG_BRIDGE_DVFS
++const struct omap_opp  vdd1_rate_table_bridge[] = {
++      {0, 0, 0},
++      /*OPP1*/
++      {S125M, VDD1_OPP1, 0},
++      /*OPP2*/
++      {S250M, VDD1_OPP2, 0},
++      /*OPP3*/
++      {S500M, VDD1_OPP3, 0},
++      /*OPP4*/
++      {S550M, VDD1_OPP4, 0},
++      /*OPP5*/
++      {S600M, VDD1_OPP5, 0},
++};
++#endif
++#endif
++
++struct dspbridge_platform_data *omap_dspbridge_pdata;
++
++u32 vdd1_dsp_freq[6][4] = {
++      {0, 0, 0, 0},
++      /*OPP1*/
++      {0, 90000, 0, 86000},
++      /*OPP2*/
++      {0, 180000, 80000, 170000},
++      /*OPP3*/
++      {0, 360000, 160000, 340000},
++      /*OPP4*/
++      {0, 396000, 325000, 376000},
++      /*OPP5*/
++      {0, 430000, 355000, 430000},
++};
++
++#ifdef CONFIG_BRIDGE_DVFS
++static int dspbridge_post_scale(struct notifier_block *op, unsigned long level,
++                              void *ptr)
++{
++      PWR_PM_PostScale(PRCM_VDD1, level);
++      return 0;
++}
++
++static struct notifier_block iva_clk_notifier = {
++      .notifier_call = dspbridge_post_scale,
++      NULL,
++};
++#endif
++
++static int __devinit omap34xx_bridge_probe(struct platform_device *pdev)
++{
++      int status;
++      u32 initStatus;
++      u32 temp;
++      dev_t   dev = 0 ;
++      int     result;
++#ifdef CONFIG_BRIDGE_DVFS
++      int i = 0;
++#endif
++      struct dspbridge_platform_data *pdata = pdev->dev.platform_data;
++
++      omap_dspbridge_dev = pdev;
++
++      /* use 2.6 device model */
++      if (driver_major) {
++              dev = MKDEV(driver_major, driver_minor);
++              result = register_chrdev_region(dev, 1, driver_name);
++      } else {
++              result = alloc_chrdev_region(&dev, driver_minor, 1,
++                                          driver_name);
++              driver_major = MAJOR(dev);
++      }
++
++      if (result < 0) {
++              GT_1trace(driverTrace, GT_7CLASS, "bridge_init: "
++                              "Can't get Major %d \n", driver_major);
++              return result;
++      }
++
++      bridge_device = kmalloc(sizeof(struct bridge_dev), GFP_KERNEL);
++      if (!bridge_device) {
++              result = -ENOMEM;
++              unregister_chrdev_region(dev, 1);
++              return result;
++      }
++      memset(bridge_device, 0, sizeof(struct bridge_dev));
++      cdev_init(&bridge_device->cdev, &bridge_fops);
++      bridge_device->cdev.owner = THIS_MODULE;
++      bridge_device->cdev.ops = &bridge_fops;
++
++      status = cdev_add(&bridge_device->cdev, dev, 1);
++
++      if (status) {
++              GT_0trace(driverTrace, GT_7CLASS,
++                              "Failed to add the bridge device \n");
++              return status;
++      }
++
++      /* udev support */
++      bridge_class = class_create(THIS_MODULE, "ti_bridge");
++
++      if (IS_ERR(bridge_class))
++              GT_0trace(driverTrace, GT_7CLASS,
++                              "Error creating bridge class \n");
++
++      device_create(bridge_class, NULL, MKDEV(driver_major, driver_minor),
++                      NULL, "DspBridge");
++
++      GT_init();
++      GT_create(&driverTrace, "LD");
++
++#ifdef DEBUG
++      if (GT_str)
++              GT_set(GT_str);
++#elif defined(DDSP_DEBUG_PRODUCT) && GT_TRACE
++      GT_set("**=67");
++#endif
++
++      GT_0trace(driverTrace, GT_ENTER, "-> driver_init\n");
++
++#ifdef CONFIG_PM
++      /* Initialize the wait queue */
++      if (!status) {
++              bridge_suspend_data.suspended = 0;
++              init_waitqueue_head(&bridge_suspend_data.suspend_wq);
++      }
++#endif
++
++      SERVICES_Init();
++
++      /*  Autostart flag.  This should be set to true if the DSP image should
++       *  be loaded and run during bridge module initialization  */
++
++      if (base_img) {
++              temp = true;
++              REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
++                          sizeof(temp));
++              REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *)base_img,
++                                              strlen(base_img) + 1);
++      } else {
++              temp = false;
++              REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
++                          sizeof(temp));
++              REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *) "\0", (u32)2);
++      }
++      REG_SetValue(NULL, NULL, NUMPROCS, REG_SZ, (u8 *) num_procs,
++                                              strlen(num_procs) + 1);
++
++      if (shm_size >= 0x10000) {      /* 64 KB */
++              initStatus = REG_SetValue(NULL, NULL, SHMSIZE, REG_DWORD,
++                                        (u8 *)&shm_size, sizeof(shm_size));
++      } else {
++              initStatus = DSP_EINVALIDARG;
++              status = -1;
++              GT_0trace(driverTrace, GT_7CLASS,
++                        "SHM size must be at least 64 KB\n");
++      }
++      GT_1trace(driverTrace, GT_7CLASS,
++               "requested shm_size = 0x%x\n", shm_size);
++
++      if (pdata->phys_mempool_base && pdata->phys_mempool_size) {
++              phys_mempool_base = pdata->phys_mempool_base;
++              phys_mempool_size = pdata->phys_mempool_size;
++      }
++
++      if (phys_mempool_base > 0x0) {
++              initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLBASE,
++                                       REG_DWORD, (u8 *)&phys_mempool_base,
++                                       sizeof(phys_mempool_base));
++      }
++      GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_base = 0x%x \n",
++               phys_mempool_base);
++
++      if (phys_mempool_size > 0x0) {
++              initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLSIZE,
++                                       REG_DWORD, (u8 *)&phys_mempool_size,
++                                       sizeof(phys_mempool_size));
++      }
++      GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_size = 0x%x\n",
++               phys_mempool_base);
++      if ((phys_mempool_base > 0x0) && (phys_mempool_size > 0x0))
++              MEM_ExtPhysPoolInit(phys_mempool_base, phys_mempool_size);
++      if (tc_wordswapon) {
++              GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is enabled\n");
++              REG_SetValue(NULL, NULL, TCWORDSWAP, REG_DWORD,
++                          (u8 *)&tc_wordswapon, sizeof(tc_wordswapon));
++      } else {
++              GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is disabled\n");
++              REG_SetValue(NULL, NULL, TCWORDSWAP,
++                          REG_DWORD, (u8 *)&tc_wordswapon,
++                          sizeof(tc_wordswapon));
++      }
++      if (DSP_SUCCEEDED(initStatus)) {
++#ifdef CONFIG_BRIDGE_DVFS
++              for (i = 0; i < 6; i++)
++                      pdata->mpu_speed[i] = vdd1_rate_table_bridge[i].rate;
++
++              clk_handle = clk_get(NULL, "iva2_ck");
++              if (!clk_handle) {
++                      GT_0trace(driverTrace, GT_7CLASS,
++                      "clk_get failed to get iva2_ck \n");
++              } else {
++                      GT_0trace(driverTrace, GT_7CLASS,
++                      "clk_get PASS to get iva2_ck \n");
++              }
++              if (!clk_notifier_register(clk_handle, &iva_clk_notifier)) {
++                      GT_0trace(driverTrace, GT_7CLASS,
++                      "clk_notifier_register PASS for iva2_ck \n");
++              } else {
++                      GT_0trace(driverTrace, GT_7CLASS,
++                      "clk_notifier_register FAIL for iva2_ck \n");
++              }
++#endif
++              driverContext = DSP_Init(&initStatus);
++              if (DSP_FAILED(initStatus)) {
++                      status = -1;
++                      GT_0trace(driverTrace, GT_7CLASS,
++                               "DSP/BIOS Bridge initialization Failed\n");
++              } else {
++                      GT_0trace(driverTrace, GT_5CLASS,
++                                      "DSP/BIOS Bridge driver loaded\n");
++              }
++      }
++
++      DBC_Assert(status == 0);
++      DBC_Assert(DSP_SUCCEEDED(initStatus));
++      GT_0trace(driverTrace, GT_ENTER, " <- driver_init\n");
++      return status;
++}
++
++static int __devexit omap34xx_bridge_remove(struct platform_device *pdev)
++{
++      dev_t devno;
++      bool ret;
++      DSP_STATUS dsp_status = DSP_SOK;
++      HANDLE       hDrvObject = NULL;
++      struct PROCESS_CONTEXT  *pTmp = NULL;
++      struct PROCESS_CONTEXT    *pCtxtclosed = NULL;
++      struct PROCESS_CONTEXT    *pCtxttraverse = NULL;
++
++      GT_0trace(driverTrace, GT_ENTER, "-> driver_exit\n");
++
++      dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++      DRV_GetProcCtxtList(&pCtxtclosed, (struct DRV_OBJECT *)hDrvObject);
++      while (pCtxtclosed != NULL) {
++              DRV_RemoveAllResources(pCtxtclosed);
++              if (pCtxtclosed->hProcessor != NULL) {
++                      DRV_GetProcCtxtList(&pCtxttraverse,
++                                          (struct DRV_OBJECT *)hDrvObject);
++                      if (pCtxttraverse->next == NULL) {
++                              PROC_Detach(pCtxtclosed->hProcessor);
++                              goto func_cont;
++                      }
++                      if ((pCtxtclosed->pid == pCtxttraverse->pid) &&
++                         (pCtxttraverse->next != NULL)) {
++                              pCtxttraverse = pCtxttraverse->next;
++                      }
++                      while ((pCtxttraverse != NULL) &&
++                            (pCtxtclosed->hProcessor
++                            != pCtxttraverse->hProcessor)) {
++                              pCtxttraverse = pCtxttraverse->next;
++                              if ((pCtxttraverse != NULL) &&
++                                 (pCtxtclosed->pid == pCtxttraverse->pid)) {
++                                      pCtxttraverse = pCtxttraverse->next;
++                              }
++                      }
++                      if (pCtxttraverse == NULL)
++                              PROC_Detach(pCtxtclosed->hProcessor);
++              }
++func_cont:
++              pTmp = pCtxtclosed->next;
++              DRV_RemoveProcContext((struct DRV_OBJECT *)hDrvObject,
++                                   pCtxtclosed, (void *)pCtxtclosed->pid);
++              pCtxtclosed = pTmp;
++      }
++
++      /* unregister the clock notifier */
++#ifdef CONFIG_BRIDGE_DVFS
++      if (!clk_notifier_unregister(clk_handle, &iva_clk_notifier)) {
++              GT_0trace(driverTrace, GT_7CLASS,
++              "clk_notifier_unregister PASS for iva2_ck \n");
++      } else {
++              GT_0trace(driverTrace, GT_7CLASS,
++              "clk_notifier_unregister PASS for iva2_ck \n");
++      }
++
++      clk_put(clk_handle);
++      clk_handle = NULL;
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++
++      if (driverContext) {
++              ret = DSP_Deinit(driverContext);
++              driverContext = 0;
++
++              DBC_Assert(ret == true);
++      }
++      SERVICES_Exit();
++      GT_exit();
++
++      devno = MKDEV(driver_major, driver_minor);
++      if (bridge_device) {
++              cdev_del(&bridge_device->cdev);
++              kfree(bridge_device);
++      }
++      unregister_chrdev_region(devno, 1);
++      if (bridge_class) {
++              /* remove the device from sysfs */
++              device_destroy(bridge_class, MKDEV(driver_major, driver_minor));
++              class_destroy(bridge_class);
++
++      }
++      return 0;
++}
++
++
++#ifdef CONFIG_PM
++static int bridge_suspend(struct platform_device *pdev, pm_message_t state)
++{
++      u32 status;
++      u32 command = PWR_EMERGENCYDEEPSLEEP;
++
++      status = PWR_SleepDSP(command, timeOut);
++      if (DSP_FAILED(status))
++              return -1;
++
++      bridge_suspend_data.suspended = 1;
++      return 0;
++}
++
++static int bridge_resume(struct platform_device *pdev)
++{
++      u32 status;
++
++      status = PWR_WakeDSP(timeOut);
++      if (DSP_FAILED(status))
++              return -1;
++
++      bridge_suspend_data.suspended = 0;
++      wake_up(&bridge_suspend_data.suspend_wq);
++      return 0;
++}
++#else
++#define bridge_suspend NULL
++#define bridge_resume NULL
++#endif
++
++static struct platform_driver bridge_driver = {
++      .driver = {
++              .name = BRIDGE_NAME,
++      },
++      .probe   = omap34xx_bridge_probe,
++      .remove  = __devexit_p(omap34xx_bridge_remove),
++      .suspend = bridge_suspend,
++      .resume  = bridge_resume,
++};
++
++static int __init bridge_init(void)
++{
++      return platform_driver_register(&bridge_driver);
++}
++
++static void __exit bridge_exit(void)
++{
++      platform_driver_unregister(&bridge_driver);
++}
++
++/* This function is called when an application opens handle to the
++ * bridge driver. */
++
++static int bridge_open(struct inode *ip, struct file *filp)
++{
++      int status = 0;
++#ifndef RES_CLEANUP_DISABLE
++       u32     hProcess;
++      DSP_STATUS dsp_status = DSP_SOK;
++      HANDLE       hDrvObject = NULL;
++      struct PROCESS_CONTEXT    *pPctxt = NULL;
++      struct PROCESS_CONTEXT  *next_node = NULL;
++      struct PROCESS_CONTEXT    *pCtxtclosed = NULL;
++      struct PROCESS_CONTEXT    *pCtxttraverse = NULL;
++      struct task_struct *tsk = NULL;
++      GT_0trace(driverTrace, GT_ENTER, "-> driver_open\n");
++      dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++
++      /* Checking weather task structure for all process existing
++       * in the process context list If not removing those processes*/
++      if (DSP_FAILED(dsp_status))
++              goto func_cont;
++
++      DRV_GetProcCtxtList(&pCtxtclosed, (struct DRV_OBJECT *)hDrvObject);
++      while (pCtxtclosed != NULL) {
++              tsk = find_task_by_vpid(pCtxtclosed->pid);
++              next_node = pCtxtclosed->next;
++
++              if ((tsk == NULL) || (tsk->exit_state == EXIT_ZOMBIE)) {
++
++                      GT_1trace(driverTrace, GT_5CLASS,
++                               "***Task structure not existing for "
++                               "process***%d\n", pCtxtclosed->pid);
++                      DRV_RemoveAllResources(pCtxtclosed);
++                      if (pCtxtclosed->hProcessor != NULL) {
++                              DRV_GetProcCtxtList(&pCtxttraverse,
++                                          (struct DRV_OBJECT *)hDrvObject);
++                              if (pCtxttraverse->next == NULL) {
++                                      PROC_Detach(pCtxtclosed->hProcessor);
++                              } else {
++                                      if ((pCtxtclosed->pid ==
++                                        pCtxttraverse->pid) &&
++                                        (pCtxttraverse->next != NULL)) {
++                                              pCtxttraverse =
++                                                      pCtxttraverse->next;
++                                      }
++                                      while ((pCtxttraverse != NULL) &&
++                                           (pCtxtclosed->hProcessor
++                                           != pCtxttraverse->hProcessor)) {
++                                              pCtxttraverse =
++                                                      pCtxttraverse->next;
++                                              if ((pCtxttraverse != NULL) &&
++                                                (pCtxtclosed->pid ==
++                                                pCtxttraverse->pid)) {
++                                                      pCtxttraverse =
++                                                         pCtxttraverse->next;
++                                              }
++                                      }
++                                      if (pCtxttraverse == NULL) {
++                                              PROC_Detach
++                                                   (pCtxtclosed->hProcessor);
++                                      }
++                              }
++                      }
++                      DRV_RemoveProcContext((struct DRV_OBJECT *)hDrvObject,
++                                           pCtxtclosed,
++                                           (void *)pCtxtclosed->pid);
++              }
++              pCtxtclosed = next_node;
++      }
++func_cont:
++      dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++      if (DSP_SUCCEEDED(dsp_status))
++              dsp_status = DRV_InsertProcContext(
++                              (struct DRV_OBJECT *)hDrvObject, &pPctxt);
++
++      if (pPctxt != NULL) {
++                      /* Return PID instead of process handle */
++                      hProcess = current->pid;
++
++              DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
++                      DRV_ProcSetPID(pPctxt, hProcess);
++      }
++#endif
++
++      GT_0trace(driverTrace, GT_ENTER, " <- driver_open\n");
++      return status;
++}
++
++/* This function is called when an application closes handle to the bridge
++ * driver. */
++static int bridge_release(struct inode *ip, struct file *filp)
++{
++      int status;
++       u32 pid;
++
++      GT_0trace(driverTrace, GT_ENTER, "-> driver_release\n");
++
++       /* Return PID instead of process handle */
++       pid = current->pid;
++
++       status = DSP_Close(pid);
++
++
++      (status == true) ? (status = 0) : (status = -1);
++
++      GT_0trace(driverTrace, GT_ENTER, " <- driver_release\n");
++
++      return status;
++}
++
++/* This function provides IO interface to the bridge driver. */
++static int bridge_ioctl(struct inode *ip, struct file *filp, unsigned int code,
++              unsigned long args)
++{
++      int status;
++      u32 retval = DSP_SOK;
++      union Trapped_Args pBufIn;
++
++      DBC_Require(filp != NULL);
++#ifdef CONFIG_PM
++      status = omap34xxbridge_suspend_lockout(&bridge_suspend_data, filp);
++      if (status != 0)
++              return status;
++#endif
++
++      GT_0trace(driverTrace, GT_ENTER, " -> driver_ioctl\n");
++
++      /* Deduct one for the CMD_BASE. */
++      code = (code - 1);
++
++      status = copy_from_user(&pBufIn, (union Trapped_Args *)args,
++                              sizeof(union Trapped_Args));
++
++      if (status >= 0) {
++              status = WCD_CallDevIOCtl(code, &pBufIn, &retval);
++
++              if (DSP_SUCCEEDED(status)) {
++                      status = retval;
++              } else {
++                      GT_1trace(driverTrace, GT_7CLASS,
++                               "IOCTL Failed, code : 0x%x\n", code);
++                      status = -1;
++              }
++
++      }
++
++      GT_0trace(driverTrace, GT_ENTER, " <- driver_ioctl\n");
++
++      return status;
++}
++
++/* This function maps kernel space memory to user space memory. */
++static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
++{
++#if GT_TRACE
++      u32 offset = vma->vm_pgoff << PAGE_SHIFT;
++#endif
++      u32 status;
++
++      DBC_Assert(vma->vm_start < vma->vm_end);
++
++      vma->vm_flags |= VM_RESERVED | VM_IO;
++      vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
++
++      GT_6trace(driverTrace, GT_3CLASS,
++               "vm filp %p offset %lx start %lx end %lx"
++               " page_prot %lx flags %lx\n", filp, offset, vma->vm_start,
++               vma->vm_end, vma->vm_page_prot, vma->vm_flags);
++
++      status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
++                              vma->vm_end - vma->vm_start, vma->vm_page_prot);
++      if (status != 0)
++              status = -EAGAIN;
++
++      return status;
++}
++
++#ifndef RES_CLEANUP_DISABLE
++/* To remove all process resources before removing the process from the
++ * process context list*/
++DSP_STATUS DRV_RemoveAllResources(HANDLE hPCtxt)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++      if (pCtxt != NULL) {
++              DRV_RemoveAllSTRMResElements(pCtxt);
++              DRV_RemoveAllNodeResElements(pCtxt);
++              DRV_RemoveAllDMMResElements(pCtxt);
++              DRV_ProcUpdatestate(pCtxt, PROC_RES_FREED);
++      }
++      return status;
++}
++#endif
++
++/* Bridge driver initialization and de-initialization functions */
++module_init(bridge_init);
++module_exit(bridge_exit);
++
+diff --git a/drivers/dsp/bridge/rmgr/drv_interface.h b/drivers/dsp/bridge/rmgr/drv_interface.h
+new file mode 100644
+index 0000000..f5b068e
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/drv_interface.h
+@@ -0,0 +1,40 @@
++/*
++ * drv_interface.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== drv_interface.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 24-Mar-2003 vp  Added hooks for Power Management Test
++ *! 18-Feb-2003 vp  Code review updates
++ *! 18-Oct-2002 sb  Created initial version
++
++ */
++
++#ifndef       _DRV_INTERFACE_H_
++#define _DRV_INTERFACE_H_
++
++/* Prototypes for all functions in this bridge */
++static int __init bridge_init(void);  /* Initialize bridge */
++static void __exit bridge_exit(void); /* Opposite of initialize */
++static int bridge_open(struct inode *, struct file *);        /* Open */
++static int bridge_release(struct inode *, struct file *);     /* Release */
++static int bridge_ioctl(struct inode *, struct file *, unsigned int,
++                      unsigned long);
++static int bridge_mmap(struct file *filp, struct vm_area_struct *vma);
++#endif                                /* ifndef _DRV_INTERFACE_H_ */
+diff --git a/drivers/dsp/bridge/rmgr/dspdrv.c b/drivers/dsp/bridge/rmgr/dspdrv.c
+new file mode 100644
+index 0000000..a7a74fc
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/dspdrv.c
+@@ -0,0 +1,276 @@
++/*
++ * dspdrv.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dspdrv.c ========
++ *  Description:
++ *      Interface to allocate and free bridge resources.
++ *
++ *! Revision History
++ *! ================
++ *! 12-Apr-2004 hp: Compile IVA only for 24xx.
++ *! 09-Feb-2004 vp: Updated to support IVA.
++ *! 10-Feb-2003 vp: Code review updates.
++ *! 18-oct-2002 vp: Ported to the Linux platform.
++ *! 03-Mar-2002 rr: DSP_Deinit bug fixed (gets the Mgrhandle from registry
++ *!                       before calling MGR_Destroy.
++ *! 11-Jul-2001 jeh Moved MGR_Create() from DSP_Init() to DEV_StartDevice().
++ *! 02-Apr-2001 rr: WCD_InitComplete2 return value is not checked thus
++ *!                 sllowing the class driver to load irrespective of
++ *!                 the image load.
++ *! 30-Oct-2000 kc: Made changes w.r.t. usage of REG_SetValue.
++ *! 05-Oct-2000 rr: WCD_InitComplete2 return value checked for RM.
++ *!                 Failure in WCD_InitComplete2 will cause the
++ *!                 DSP_Init to fail.
++ *! 12-Aug-2000 kc: Changed REG_EnumValue to REG_EnumKey.
++ *! 07-Aug-2000 rr: MGR_Create does the job of loading the DCD Dll.
++ *! 26-Jul-2000 rr: Driver Object holds the DevNodeStrings for each
++ *!                 DevObjects. Static variables removed. Returns
++ *!                 the Driver Object in DSP_Init.
++ *! 17-Jul-2000 rr: Driver Object is created in DSP_Init and that holds
++ *!                 the list of Device objects.
++ *! 07-Jul-2000 rr: RM implementaion started.
++ *! 24-May-2000 ag: Cleaned up debug msgs.
++ *! 02-May-2000 rr: DSP_Open returns GetCallerProcess as dwOpenContext.
++ *! 03-Feb-2000 rr: GT Changes.
++ *! 28-Jan-2000 rr: Code Cleaned up.Type void changed to void.
++ *!                 DSP_Deinit checks return values.dwCode in
++ *!                 DSP_IO_CONTROL is decoded(not hard coded)
++ *! 27-Jan-2000 rr: REG_EnumValue Used .EnumerateKey fxn removed.
++ *! 13-Jan-2000 rr: CFG_GetPrivateDword renamed to CFG_GetDevObject.
++ *! 29-Dec-1999 rr: Code Cleaned up
++ *! 09-Dec-1999 rr: EnumerateKey changed for retail build.
++ *! 06-Dec-1999 rr: ArrayofInstalledNode, index and  ArrayofInstalledDev
++ *!                 is Global.DevObject stores this pointer as hDevNode.
++ *! 02-Dec-1999 rr: DBG_SetGT and RetailMSG conditionally included.
++ *!                 Comments changed.Deinit handled.Code cleaned up.
++ *!                 DSP_IOControl, Close, Deinit returns bool values.
++ *!                 Calls WCD_InitComplete2 for Board AutoStart.
++ *! 29-Nov-1999 rr: DSP_IOControl returns the result through pBufOut.
++ *!                 Global Arrays keeps track of installed devices.
++ *! 19-Nov-1999 rr: DSP_Init handles multiple drivers.
++ *! 12-Nov-1999 rr: GetDriverKey and EnumerateKey functions added.
++ *!                 for multiple mini driver support.PCCARD flag
++ *!                 checking to include PCMCIA related stuff.
++ *! 25-Oct-1999 rr: GT_Init is called within the Process Attach.
++ *!                 return value initalized to S_OK upfront in the
++ *!                 Process Attach.
++ *! 15-Oct-1999 rr: DSP_DeInit handles the return values
++ *! 05-Oct-1999 rr: All the PCMCIA related functions are now in PCCARD.c
++ *!                 DRV_Request Resources is used instead of the
++ *!                 RegisterMiniDriver as it sounds close to what we are doing.
++ *! 24-Sep-1999 rr: DRV_RegisterMiniDriver is being called from here. Only
++ *!                 neccessaryPCMCIA fxns are here. Soon they will move out
++ *!                  either to a seperate file for bus specific inits.
++ *! 10-Sep-1999 rr: GT Enabled. Considerably changed the  driver structure as
++ *!                 - This is the Class driver. After successfully initialized
++ *!                   the Class driver will attempt to load the Mini driver.
++ *!                 - Need to seperate the PCMCIA stuff based on bus type.
++ *!                 - Changed the name of the file to wcdce.c
++ *!                 - Made the Media Handle as Global again
++ *!
++ *! 19-Aug-1999 rr: Removed the Global hbhMediaHandle. Included the MemTest.
++ *!                 Modified the DSP_Init, now three windows are opened.
++ *!                 Split the driver into PDD so that hardware dependent
++ *!                 functions will reside in PDD.
++ *! 16-Jul-1999 ag  Adapted from rkw's CAC Bullet card driver.
++ *!
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/reg.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/_dcd.h>
++
++/*  ----------------------------------- Resource Manager */
++#include <dspbridge/mgr.h>
++
++/*  ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/dspdrv.h>
++
++/*  ----------------------------------- Globals */
++struct GT_Mask curTrace;
++
++/*
++ *  ======== DSP_Init ========
++ *    Allocates bridge resources. Loads a base image onto DSP, if specified.
++ */
++u32 DSP_Init(OUT u32 *initStatus)
++{
++      char devNode[MAXREGPATHLENGTH] = "TIOMAP1510";
++      DSP_STATUS status = DSP_EFAIL;
++      struct DRV_OBJECT *drvObject = NULL;
++      u32 index = 0;
++      u32 deviceNode;
++      u32 deviceNodeString;
++
++      GT_create(&curTrace, "DD");
++
++      GT_0trace(curTrace, GT_ENTER, "Entering DSP_Init \r\n");
++
++      if (DSP_FAILED(WCD_Init())) {
++              GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed \n");
++              goto func_cont;
++      }                       /* End WCD_Exit */
++      if (DSP_FAILED(DRV_Create(&drvObject))) {
++              GT_0trace(curTrace, GT_7CLASS, "DSP_Init:DRV_Create Failed \n");
++              WCD_Exit();
++              goto func_cont;
++      }               /* End DRV_Create */
++      GT_0trace(curTrace, GT_5CLASS, "DSP_Init:DRV Created \r\n");
++
++      /* Request Resources */
++      if (DSP_SUCCEEDED(DRV_RequestResources((u32)&devNode,
++         &deviceNodeString))) {
++              /* Attempt to Start the Device */
++              if (DSP_SUCCEEDED(DEV_StartDevice(
++                 (struct CFG_DEVNODE *)deviceNodeString))) {
++                      /* Retreive the DevObject from the Registry */
++                      GT_2trace(curTrace, GT_1CLASS,
++                               "DSP_Init Succeeded for Device1:"
++                               "%d: value: %x\n", index, deviceNodeString);
++                      status = DSP_SOK;
++              } else {
++                      GT_0trace(curTrace, GT_7CLASS,
++                               "DSP_Init:DEV_StartDevice Failed\n");
++                      (void)DRV_ReleaseResources
++                              ((u32) deviceNodeString, drvObject);
++                      status = DSP_EFAIL;
++              }
++      } else {
++              GT_0trace(curTrace, GT_7CLASS,
++                       "DSP_Init:DRV_RequestResources Failed \r\n");
++              status = DSP_EFAIL;
++      }       /* DRV_RequestResources */
++      index++;
++
++      /* Unwind whatever was loaded */
++      if (DSP_FAILED(status)) {
++              /* irrespective of the status of DEV_RemoveDevice we conitinue
++               * unloading. Get the Driver Object iterate through and remove.
++               * Reset the status to E_FAIL to avoid going through
++               * WCD_InitComplete2. */
++              status = DSP_EFAIL;
++              for (deviceNode = DRV_GetFirstDevExtension(); deviceNode != 0;
++                  deviceNode = DRV_GetNextDevExtension(deviceNode)) {
++                      (void)DEV_RemoveDevice
++                              ((struct CFG_DEVNODE *)deviceNode);
++                      (void)DRV_ReleaseResources((u32)deviceNode,
++                              drvObject);
++              }
++              /* Remove the Driver Object */
++              (void)DRV_Destroy(drvObject);
++              drvObject = NULL;
++              WCD_Exit();
++              GT_0trace(curTrace, GT_7CLASS,
++                       "DSP_Init:Logical device Failed to Load\n");
++      }       /* Unwinding the loaded drivers */
++func_cont:
++      /* Attempt to Start the Board */
++      if (DSP_SUCCEEDED(status)) {
++              /* BRD_AutoStart could fail if the dsp execuetable is not the
++               * correct one. We should not propagate that error
++               * into the device loader. */
++              (void)WCD_InitComplete2();
++              GT_0trace(curTrace, GT_1CLASS, "DSP_Init Succeeded\n");
++      } else {
++              GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed\n");
++      }                       /* End WCD_InitComplete2 */
++      DBC_Ensure((DSP_SUCCEEDED(status) && drvObject != NULL) ||
++                (DSP_FAILED(status) && drvObject == NULL));
++      *initStatus = status;
++      /* Return the Driver Object */
++      return (u32)drvObject;
++}
++
++/*
++ *  ======== DSP_Deinit ========
++ *    Frees the resources allocated for bridge.
++ */
++bool DSP_Deinit(u32 deviceContext)
++{
++      bool retVal = true;
++      u32 deviceNode;
++      struct MGR_OBJECT *mgrObject = NULL;
++
++      GT_0trace(curTrace, GT_ENTER, "Entering DSP_Deinit \r\n");
++
++      while ((deviceNode = DRV_GetFirstDevExtension()) != 0) {
++              (void)DEV_RemoveDevice((struct CFG_DEVNODE *)deviceNode);
++
++              (void)DRV_ReleaseResources((u32)deviceNode,
++                       (struct DRV_OBJECT *)deviceContext);
++      }
++
++      (void) DRV_Destroy((struct DRV_OBJECT *) deviceContext);
++
++      /* Get the Manager Object from Registry
++       * MGR Destroy will unload the DCD dll */
++      if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&mgrObject, REG_MGR_OBJECT)))
++              (void)MGR_Destroy(mgrObject);
++
++      WCD_Exit();
++
++      return retVal;
++}
++
++/*
++ *  ======== DSP_Close ========
++ *    The Calling Process handle is passed to DEV_CleanupProcesState
++ *      for cleaning up of any resources used by the application
++ */
++bool DSP_Close(u32 dwOpenContext)
++{
++      bool retVal = false;
++
++      DBC_Require(dwOpenContext != 0);
++
++      GT_0trace(curTrace, GT_ENTER, "Entering DSP_Close\n");
++
++#ifdef RES_CLEANUP_DISABLE
++
++      if (DSP_SUCCEEDED(DEV_CleanupProcessState((HANDLE) dwOpenContext))) {
++              GT_0trace(curTrace, GT_1CLASS, "DSP_Close Succeeded \r\n");
++              retVal = true;
++      } else {
++              GT_0trace(curTrace, GT_7CLASS, "DSP_Close failed \r\n");
++      }
++#endif
++
++      return retVal;
++}
+diff --git a/drivers/dsp/bridge/rmgr/mgr.c b/drivers/dsp/bridge/rmgr/mgr.c
+new file mode 100644
+index 0000000..943cf93
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/mgr.c
+@@ -0,0 +1,491 @@
++/*
++ * mgr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== mgr.c ========
++ *  Description:
++ *      Implementation of Manager interface to the device object at the
++ *      driver level. This queries the NDB data base and retrieves the
++ *      data about Node and Processor.
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 12-Feb-2003 vp: Code review updates.
++ *! 18-Oct-2002 vp: Ported to Linux platform
++ *! 01-Aug-2001 ag: Added extended info for DSP-MMU setup support.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 22-Nov-2000 kc: Added MGR_GetPerfData.
++ *! 03-Nov-2000 rr: Updated after code review.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 10-Aug-2000 rr: dwSignature is not specifically inserted in MGR Obj
++ *!                 as it is taken care by MEM_AllocObject. stdwin.h added
++ *!                 for retail build to succeed.
++ *! 07-Aug-2000 rr: MGR_Create does the job of Loading DCD Dll.
++ *! 26-Jul-2000 rr: MGR_Destroy releases the hNDBDll.
++ *! 20-Jun-2000 rr: Created.
++ */
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/*  ----------------------------------- Others */
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/mgr.h>
++
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++#define ZLDLLNAME               ""
++#define SIGNATURE               0x5f52474d    /* "MGR_" (in reverse) */
++
++struct MGR_OBJECT {
++      u32 dwSignature;
++      struct DCD_MANAGER *hDcdMgr;    /* Proc/Node data manager */
++};
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask MGR_DebugMask = { NULL, NULL };
++#endif
++
++static u32 cRefs;
++
++/*
++ *  ========= MGR_Create =========
++ *  Purpose:
++ *      MGR Object gets created only once during driver Loading.
++ */
++DSP_STATUS MGR_Create(OUT struct MGR_OBJECT **phMgrObject,
++                   struct CFG_DEVNODE *hDevNode)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct MGR_OBJECT *pMgrObject = NULL;
++
++      DBC_Require(phMgrObject != NULL);
++      DBC_Require(cRefs > 0);
++      GT_1trace(MGR_DebugMask, GT_ENTER,
++               "Entering MGR_Create phMgrObject 0x%x\n ",
++               phMgrObject);
++      MEM_AllocObject(pMgrObject, struct MGR_OBJECT, SIGNATURE);
++      if (pMgrObject) {
++              if (DSP_SUCCEEDED(DCD_CreateManager(ZLDLLNAME,
++                 &pMgrObject->hDcdMgr))) {
++                      /* If succeeded store the handle in the MGR Object */
++                      if (DSP_SUCCEEDED(CFG_SetObject((u32)pMgrObject,
++                         REG_MGR_OBJECT))) {
++                              *phMgrObject = pMgrObject;
++                              GT_0trace(MGR_DebugMask, GT_1CLASS,
++                                       "MGR_Create:MGR Created\r\n");
++                      } else {
++                              status = DSP_EFAIL;
++                              GT_0trace(MGR_DebugMask, GT_7CLASS,
++                                       "MGR_Create:CFG_SetObject "
++                                       "Failed\r\n");
++                              DCD_DestroyManager(pMgrObject->hDcdMgr);
++                              MEM_FreeObject(pMgrObject);
++                      }
++              } else {
++                      /* failed to Create DCD Manager */
++                      status = DSP_EFAIL;
++                      GT_0trace(MGR_DebugMask, GT_7CLASS,
++                               "MGR_Create:DCD_ManagerCreate Failed\r\n");
++                      MEM_FreeObject(pMgrObject);
++              }
++      } else {
++              status = DSP_EMEMORY;
++              GT_0trace(MGR_DebugMask, GT_7CLASS,
++                       "MGR_Create DSP_FAILED to allocate memory \n");
++      }
++      GT_2trace(MGR_DebugMask, GT_ENTER,
++               "Exiting MGR_Create: phMgrObject: 0x%x\t"
++               "status: 0x%x\n", phMgrObject, status);
++      DBC_Ensure(DSP_FAILED(status) ||
++                MEM_IsValidHandle(pMgrObject, SIGNATURE));
++      return status;
++}
++
++/*
++ *  ========= MGR_Destroy =========
++ *     This function is invoked during bridge driver unloading.Frees MGR object.
++ */
++DSP_STATUS MGR_Destroy(struct MGR_OBJECT *hMgrObject)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct MGR_OBJECT *pMgrObject = (struct MGR_OBJECT *)hMgrObject;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hMgrObject, SIGNATURE));
++
++      GT_1trace(MGR_DebugMask, GT_ENTER,
++               "Entering MGR_Destroy hMgrObject 0x%x\n", hMgrObject);
++      /* Free resources */
++      if (hMgrObject->hDcdMgr)
++              DCD_DestroyManager(hMgrObject->hDcdMgr);
++
++      MEM_FreeObject(pMgrObject);
++      /* Update the Registry with NULL for MGR Object */
++      (void)CFG_SetObject(0, REG_MGR_OBJECT);
++
++      GT_2trace(MGR_DebugMask, GT_ENTER,
++               "Exiting MGR_Destroy: hMgrObject: 0x%x\t"
++               "status: 0x%x\n", hMgrObject, status);
++
++      DBC_Ensure(DSP_FAILED(status) ||
++               !MEM_IsValidHandle(hMgrObject, SIGNATURE));
++
++      return status;
++}
++
++/*
++ *  ======== MGR_EnumNodeInfo ========
++ *      Enumerate and get configuration information about nodes configured
++ *      in the node database.
++ */
++DSP_STATUS MGR_EnumNodeInfo(u32 uNode, OUT struct DSP_NDBPROPS *pNDBProps,
++                         u32 uNDBPropsSize, OUT u32 *puNumNodes)
++{
++      DSP_STATUS status = DSP_SOK;
++      DSP_STATUS status1 = DSP_SOK;
++      struct DSP_UUID Uuid, uTempUuid;
++      u32 uTempIndex = 0;
++      u32 uNodeIndex = 0;
++      struct DCD_GENERICOBJ GenObj;
++      struct MGR_OBJECT *pMgrObject = NULL;
++
++      DBC_Require(pNDBProps != NULL);
++      DBC_Require(puNumNodes != NULL);
++      DBC_Require(uNDBPropsSize >= sizeof(struct DSP_NDBPROPS));
++      DBC_Require(cRefs > 0);
++
++      GT_4trace(MGR_DebugMask, GT_ENTER, "Entered Manager_EnumNodeInfo, "
++               "args:\n\t uNode: 0x%x\n\tpNDBProps:  0x%x\n\tuNDBPropsSize:"
++               "0x%x\tpuNumNodes: 0x%x\n", uNode, pNDBProps,
++               uNDBPropsSize, puNumNodes);
++      *puNumNodes = 0;
++      /* Get The Manager Object from the Registry */
++      if (DSP_FAILED(CFG_GetObject((u32 *)&pMgrObject,
++         REG_MGR_OBJECT))) {
++              GT_0trace(MGR_DebugMask, GT_7CLASS,
++                       "Manager_EnumNodeInfo:Failed To Get"
++                       " MGR Object from Registry\r\n");
++              goto func_cont;
++      }
++      DBC_Assert(MEM_IsValidHandle(pMgrObject, SIGNATURE));
++      /* Forever loop till we hit failed or no more items in the
++       * Enumeration. We will exit the loop other than DSP_SOK; */
++      while (status == DSP_SOK) {
++              status = DCD_EnumerateObject(uTempIndex++, DSP_DCDNODETYPE,
++                                          &uTempUuid);
++              if (status == DSP_SOK) {
++                      uNodeIndex++;
++                      if (uNode == (uNodeIndex - 1))
++                              Uuid = uTempUuid;
++
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              if (uNode > (uNodeIndex - 1)) {
++                      status = DSP_EINVALIDARG;
++                      GT_0trace(MGR_DebugMask, GT_7CLASS,
++                               "Manager_EnumNodeInfo: uNode"
++                               " is Invalid \r\n");
++              } else {
++                      status1 = DCD_GetObjectDef(pMgrObject->hDcdMgr,
++                                              (struct DSP_UUID *)&Uuid,
++                                              DSP_DCDNODETYPE, &GenObj);
++                      if (DSP_SUCCEEDED(status1)) {
++                              /* Get the Obj def */
++                              *pNDBProps = GenObj.objData.nodeObj.ndbProps;
++                              *puNumNodes = uNodeIndex;
++                              status = DSP_SOK;
++                      } else {
++                              GT_0trace(MGR_DebugMask, GT_7CLASS,
++                                       "Manager_EnumNodeInfo: "
++                                       "Failed to Get Node Info \r\n");
++                              status = DSP_EFAIL;
++                      }
++              }
++      } else {
++              /* This could be changed during enum, EFAIL ... */
++              GT_0trace(MGR_DebugMask, GT_7CLASS, "Manager_EnumNodeInfo: "
++                       "Enumeration failure\r\n");
++              status = DSP_EFAIL;
++      }
++func_cont:
++      GT_4trace(MGR_DebugMask, GT_ENTER,
++               "Exiting Manager_EnumNodeInfo, args:\n\t"
++               "uNode: 0x%x\n\tpNDBProps:  0x%x\n\tuNDBPropsSize:"
++               " 0x%x\tuNumNodes: 0x%x\n", uNode, pNDBProps,
++              uNDBPropsSize, *puNumNodes);
++      DBC_Ensure((DSP_SUCCEEDED(status) && *puNumNodes > 0) ||
++                (DSP_FAILED(status) && *puNumNodes == 0));
++
++      return status;
++}
++
++/*
++ *  ======== MGR_EnumProcessorInfo ========
++ *      Enumerate and get configuration information about available
++ *      DSP processors.
++ */
++DSP_STATUS MGR_EnumProcessorInfo(u32 uProcessor,
++                              OUT struct DSP_PROCESSORINFO *pProcessorInfo,
++                              u32 uProcessorInfoSize, OUT u32 *puNumProcs)
++{
++      DSP_STATUS status = DSP_SOK;
++      DSP_STATUS status1 = DSP_SOK;
++      DSP_STATUS status2 = DSP_SOK;
++      struct DSP_UUID uTempUuid;
++      u32 uTempIndex = 0;
++      u32 uProcIndex = 0;
++      struct DCD_GENERICOBJ GenObj;
++      struct MGR_OBJECT *pMgrObject = NULL;
++      struct MGR_PROCESSOREXTINFO *pExtInfo;
++      struct DEV_OBJECT *hDevObject;
++      struct DRV_OBJECT *hDrvObject;
++      s32 devType;
++      struct CFG_DEVNODE *devNode;
++      struct CFG_DSPRES chipResources;
++      bool procDetect = false;
++
++      DBC_Require(pProcessorInfo != NULL);
++      DBC_Require(puNumProcs != NULL);
++      DBC_Require(uProcessorInfoSize >= sizeof(struct DSP_PROCESSORINFO));
++      DBC_Require(cRefs > 0);
++
++      GT_4trace(MGR_DebugMask, GT_ENTER,
++               "Entered Manager_EnumProcessorInfo, "
++               "args:\n\tuProcessor:  0x%x\n\tpProcessorInfo: 0x%x\n\t"
++               "uProcessorInfoSize: 0x%x\tpuNumProcs: 0x%x\n", uProcessor,
++               pProcessorInfo, uProcessorInfoSize, puNumProcs);
++      *puNumProcs = 0;
++      status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++      if (DSP_SUCCEEDED(status)) {
++              status = DRV_GetDevObject(uProcessor, hDrvObject, &hDevObject);
++              if (DSP_SUCCEEDED(status)) {
++                      status = DEV_GetDevType(hDevObject, (u32 *) &devType);
++                      status = DEV_GetDevNode(hDevObject, &devNode);
++                      if (devType == DSP_UNIT) {
++                              status = CFG_GetDSPResources(devNode,
++                                                       &chipResources);
++                      } else {
++                              status = DSP_EFAIL;
++                              GT_1trace(MGR_DebugMask, GT_7CLASS,
++                                       "Unsupported dev type gotten"
++                                       "from device object %d\n", devType);
++                      }
++                      if (DSP_SUCCEEDED(status)) {
++                              pProcessorInfo->uProcessorType =
++                                              chipResources.uChipType;
++                      }
++              }
++      }
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      /* Get The Manager Object from the Registry */
++      if (DSP_FAILED(CFG_GetObject((u32 *)&pMgrObject,
++         REG_MGR_OBJECT))) {
++              GT_0trace(MGR_DebugMask, GT_7CLASS,
++                       "Manager_EnumProcessorInfo: "
++                       "Failed To Get MGR Object from Registry\r\n");
++              goto func_end;
++      }
++      DBC_Assert(MEM_IsValidHandle(pMgrObject, SIGNATURE));
++      /* Forever loop till we hit no more items in the
++       * Enumeration. We will exit the loop other than DSP_SOK; */
++      while (status1 == DSP_SOK) {
++              status1 = DCD_EnumerateObject(uTempIndex++,
++                                           DSP_DCDPROCESSORTYPE,
++                                           &uTempUuid);
++              if (status1 != DSP_SOK)
++                      break;
++
++              uProcIndex++;
++              /* Get the Object properties to find the Device/Processor
++               * Type */
++              if (procDetect != false)
++                      continue;
++
++              status2 = DCD_GetObjectDef(pMgrObject->hDcdMgr,
++                                      (struct DSP_UUID *)&uTempUuid,
++                                      DSP_DCDPROCESSORTYPE,
++                                      &GenObj);
++              if (DSP_SUCCEEDED(status2)) {
++                      /* Get the Obj def */
++                      if (uProcessorInfoSize <
++                                      sizeof(struct MGR_PROCESSOREXTINFO)) {
++                              *pProcessorInfo = GenObj.objData.procObj;
++                      } else {
++                              /* extended info */
++                              pExtInfo = (struct MGR_PROCESSOREXTINFO *)
++                                              pProcessorInfo;
++                              *pExtInfo = GenObj.objData.extProcObj;
++                      }
++                      GT_1trace(MGR_DebugMask, GT_7CLASS,
++                               "Manager_EnumProcessorInfo: Got"
++                               " Proctype  from DCD %x \r\n",
++                               pProcessorInfo->uProcessorType);
++                      /* See if we got the needed processor */
++                      if (devType == DSP_UNIT) {
++                              if (pProcessorInfo->uProcessorType ==
++                                 DSPPROCTYPE_C64)
++                                      procDetect = true;
++                      } else if (devType == IVA_UNIT) {
++                              if (pProcessorInfo->uProcessorType ==
++                                 IVAPROCTYPE_ARM7)
++                                      procDetect = true;
++                      }
++                      /* User applciatiuons aonly check for chip type, so
++                       * this clumsy overwrite */
++                      pProcessorInfo->uProcessorType =
++                                       chipResources.uChipType;
++              } else {
++                      GT_1trace(MGR_DebugMask, GT_7CLASS,
++                               "Manager_EnumProcessorInfo: "
++                               "Failed to Get DCD Processor Info %x \r\n",
++                               status2);
++                      status = DSP_EFAIL;
++              }
++      }
++      *puNumProcs = uProcIndex;
++      if (procDetect == false) {
++              GT_0trace(MGR_DebugMask, GT_7CLASS,
++                       "Manager_EnumProcessorInfo: Failed"
++                       " to get Proc info from DCD , so use CFG registry\n");
++              pProcessorInfo->uProcessorType = chipResources.uChipType;
++      }
++func_end:
++      return status;
++}
++
++/*
++ *  ======== MGR_Exit ========
++ *      Decrement reference count, and free resources when reference count is
++ *      0.
++ */
++void MGR_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++      cRefs--;
++      if (cRefs == 0)
++              DCD_Exit();
++
++      GT_1trace(MGR_DebugMask, GT_5CLASS,
++               "Entered MGR_Exit, ref count: 0x%x\n", cRefs);
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== MGR_GetDCDHandle ========
++ *      Retrieves the MGR handle. Accessor Function.
++ */
++DSP_STATUS MGR_GetDCDHandle(struct MGR_OBJECT *hMGRHandle,
++                         OUT u32 *phDCDHandle)
++{
++      DSP_STATUS status = DSP_EFAIL;
++      struct MGR_OBJECT *pMgrObject = (struct MGR_OBJECT *)hMGRHandle;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phDCDHandle != NULL);
++
++      *phDCDHandle = (u32)NULL;
++      if (MEM_IsValidHandle(pMgrObject, SIGNATURE)) {
++              *phDCDHandle = (u32) pMgrObject->hDcdMgr;
++              status = DSP_SOK;
++      }
++      DBC_Ensure((DSP_SUCCEEDED(status) && *phDCDHandle != (u32)NULL) ||
++                (DSP_FAILED(status) && *phDCDHandle == (u32)NULL));
++
++      return status;
++}
++
++/*
++ *  ======== MGR_Init ========
++ *      Initialize MGR's private state, keeping a reference count on each call.
++ */
++bool MGR_Init(void)
++{
++      bool fRetval = true;
++      bool fInitDCD = false;
++
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++
++              /* Set the Trace mask */
++              DBC_Assert(!MGR_DebugMask.flags);
++
++              GT_create(&MGR_DebugMask, "MG");        /* "MG" for Manager */
++              fInitDCD = DCD_Init();  /*  DCD Module */
++
++              if (!fInitDCD) {
++                      fRetval = false;
++                      GT_0trace(MGR_DebugMask, GT_6CLASS,
++                               "MGR_Init failed\n");
++              }
++      }
++
++      if (fRetval)
++              cRefs++;
++
++
++      GT_1trace(MGR_DebugMask, GT_5CLASS,
++               "Entered MGR_Init, ref count:  0x%x\n", cRefs);
++      DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++      return fRetval;
++}
++
++/*
++ *  ======== MGR_WaitForBridgeEvents ========
++ *      Block on any Bridge event(s)
++ */
++DSP_STATUS MGR_WaitForBridgeEvents(struct DSP_NOTIFICATION **aNotifications,
++                                u32 uCount, OUT u32 *puIndex, u32 uTimeout)
++{
++      DSP_STATUS status;
++      struct SYNC_OBJECT *hSyncEvents[MAX_EVENTS];
++      u32 i;
++
++      DBC_Require(uCount < MAX_EVENTS);
++
++      for (i = 0; i < uCount; i++)
++              hSyncEvents[i] = aNotifications[i]->handle;
++
++      status = SYNC_WaitOnMultipleEvents(hSyncEvents, uCount, uTimeout,
++                                       puIndex);
++
++      return status;
++
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/nldr.c b/drivers/dsp/bridge/rmgr/nldr.c
+new file mode 100644
+index 0000000..f3c429c
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/nldr.c
+@@ -0,0 +1,1967 @@
++/*
++ * nldr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== nldr.c ========
++ *  Description:
++ *      DSP/BIOS Bridge dynamic + overlay Node loader.
++ *
++ *  Public Functions:
++ *      NLDR_Allocate
++ *      NLDR_Create
++ *      NLDR_Delete
++ *      NLDR_Exit
++ *      NLDR_Free
++ *      NLDR_GetFxnAddr
++ *      NLDR_Init
++ *      NLDR_Load
++ *      NLDR_Unload
++ *
++ *  Notes:
++ *
++ *! Revision History
++ *! ================
++ *! 07-Apr-2003 map Removed references to dead DLDR module
++ *! 23-Jan-2003 map Updated RemoteAlloc to support memory granularity
++ *! 20-Jan-2003 map Updated to maintain persistent dependent libraries
++ *! 15-Jan-2003 map Adapted for use with multiple dynamic phase libraries
++ *! 19-Dec-2002 map Fixed overlay bug in AddOvlySect for overlay
++ *!            sections > 1024 bytes.
++ *! 13-Dec-2002 map Fixed NLDR_GetFxnAddr bug by searching dependent
++ *!            libs for symbols
++ *! 27-Sep-2002 map Added RemoteFree to convert size to words for
++ *!            correct deallocation
++ *! 16-Sep-2002 map Code Review Cleanup(from dldr.c)
++ *! 29-Aug-2002 map Adjusted for ARM-side overlay copy
++ *! 05-Aug-2002 jeh Created.
++ */
++
++#include <dspbridge/host_os.h>
++
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++#ifdef DEBUG
++#include <dspbridge/dbg.h>
++#endif
++
++/* OS adaptation layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* Platform manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++
++/* Resource manager */
++#include <dspbridge/dbll.h>
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/rmm.h>
++#include <dspbridge/uuidutil.h>
++
++#include <dspbridge/nldr.h>
++
++#define NLDR_SIGNATURE      0x52444c4e        /* "RDLN" */
++#define NLDR_NODESIGNATURE  0x4e444c4e        /* "NDLN" */
++
++/* Name of section containing dynamic load mem */
++#define DYNMEMSECT  ".dspbridge_mem"
++
++/* Name of section containing dependent library information */
++#define DEPLIBSECT  ".dspbridge_deplibs"
++
++/* Max depth of recursion for loading node's dependent libraries */
++#define MAXDEPTH          5
++
++/* Max number of persistent libraries kept by a node */
++#define MAXLIBS        5
++
++/*
++ *  Defines for extracting packed dynamic load memory requirements from two
++ *  masks.
++ *  These defines must match node.cdb and dynm.cdb
++ *  Format of data/code mask is:
++ *   uuuuuuuu|fueeeeee|fudddddd|fucccccc|
++ *  where
++ *      u = unused
++ *      cccccc = prefered/required dynamic mem segid for create phase data/code
++ *      dddddd = prefered/required dynamic mem segid for delete phase data/code
++ *      eeeeee = prefered/req. dynamic mem segid for execute phase data/code
++ *      f = flag indicating if memory is preferred or required:
++ *      f = 1 if required, f = 0 if preferred.
++ *
++ *  The 6 bits of the segid are interpreted as follows:
++ *
++ *  If the 6th bit (bit 5) is not set, then this specifies a memory segment
++ *  between 0 and 31 (a maximum of 32 dynamic loading memory segments).
++ *  If the 6th bit (bit 5) is set, segid has the following interpretation:
++ *      segid = 32 - Any internal memory segment can be used.
++ *      segid = 33 - Any external memory segment can be used.
++ *      segid = 63 - Any memory segment can be used (in this case the
++ *               required/preferred flag is irrelevant).
++ *
++ */
++/* Maximum allowed dynamic loading memory segments */
++#define MAXMEMSEGS      32
++
++#define MAXSEGID      3       /* Largest possible (real) segid */
++#define MEMINTERNALID   32    /* Segid meaning use internal mem */
++#define MEMEXTERNALID   33    /* Segid meaning use external mem */
++#define NULLID          63    /* Segid meaning no memory req/pref */
++#define FLAGBIT        7      /* 7th bit is pref./req. flag */
++#define SEGMASK        0x3f   /* Bits 0 - 5 */
++
++#define CREATEBIT       0     /* Create segid starts at bit 0 */
++#define DELETEBIT       8     /* Delete segid starts at bit 8 */
++#define EXECUTEBIT      16    /* Execute segid starts at bit 16 */
++
++/*
++ *  Masks that define memory type.  Must match defines in dynm.cdb.
++ */
++#define DYNM_CODE       0x2
++#define DYNM_DATA       0x4
++#define DYNM_CODEDATA   (DYNM_CODE | DYNM_DATA)
++#define DYNM_INTERNAL   0x8
++#define DYNM_EXTERNAL   0x10
++
++/*
++ *  Defines for packing memory requirement/preference flags for code and
++ *  data of each of the node's phases into one mask.
++ *  The bit is set if the segid is required for loading code/data of the
++ *  given phase. The bit is not set, if the segid is preferred only.
++ *
++ *  These defines are also used as indeces into a segid array for the node.
++ *  eg node's segid[CREATEDATAFLAGBIT] is the memory segment id that the
++ *  create phase data is required or preferred to be loaded into.
++ */
++#define CREATEDATAFLAGBIT   0
++#define CREATECODEFLAGBIT   1
++#define EXECUTEDATAFLAGBIT  2
++#define EXECUTECODEFLAGBIT  3
++#define DELETEDATAFLAGBIT   4
++#define DELETECODEFLAGBIT   5
++#define MAXFLAGS          6
++
++#define IsInternal(hNldr, segid) (((segid) <= MAXSEGID && \
++          hNldr->segTable[(segid)] & DYNM_INTERNAL) || \
++          (segid) == MEMINTERNALID)
++
++#define IsExternal(hNldr, segid) (((segid) <= MAXSEGID && \
++          hNldr->segTable[(segid)] & DYNM_EXTERNAL) || \
++          (segid) == MEMEXTERNALID)
++
++#define SWAPLONG(x) ((((x) << 24) & 0xFF000000) | (((x) << 8) & 0xFF0000L) | \
++      (((x) >> 8) & 0xFF00L) | (((x) >> 24) & 0xFF))
++
++#define SWAPWORD(x) ((((x) << 8) & 0xFF00) | (((x) >> 8) & 0xFF))
++
++    /*
++     *  These names may be embedded in overlay sections to identify which
++     *  node phase the section should be overlayed.
++     */
++#define PCREATE        "create"
++#define PDELETE        "delete"
++#define PEXECUTE      "execute"
++
++#define IsEqualUUID(uuid1, uuid2) (\
++      ((uuid1).ulData1 == (uuid2).ulData1) && \
++      ((uuid1).usData2 == (uuid2).usData2) && \
++      ((uuid1).usData3 == (uuid2).usData3) && \
++      ((uuid1).ucData4 == (uuid2).ucData4) && \
++      ((uuid1).ucData5 == (uuid2).ucData5) && \
++       (strncmp((void *)(uuid1).ucData6, (void *)(uuid2).ucData6, 6)) == 0)
++
++    /*
++     *  ======== MemInfo ========
++     *  Format of dynamic loading memory segment info in coff file.
++     *  Must match dynm.h55.
++     */
++struct MemInfo {
++      u32 segid;              /* Dynamic loading memory segment number */
++      u32 base;
++      u32 len;
++      u32 type;               /* Mask of DYNM_CODE, DYNM_INTERNAL, etc. */
++};
++
++/*
++ *  ======== LibNode ========
++ *  For maintaining a tree of library dependencies.
++ */
++struct LibNode {
++      struct DBLL_LibraryObj *lib;    /* The library */
++      u16 nDepLibs;   /* Number of dependent libraries */
++      struct LibNode *pDepLibs;       /* Dependent libraries of lib */
++};
++
++/*
++ *  ======== OvlySect ========
++ *  Information needed to overlay a section.
++ */
++struct OvlySect {
++      struct OvlySect *pNextSect;
++      u32 loadAddr;           /* Load address of section */
++      u32 runAddr;            /* Run address of section */
++      u32 size;               /* Size of section */
++      u16 page;               /* DBL_CODE, DBL_DATA */
++};
++
++/*
++ *  ======== OvlyNode ========
++ *  For maintaining a list of overlay nodes, with sections that need to be
++ *  overlayed for each of the nodes phases.
++ */
++struct OvlyNode {
++      struct DSP_UUID uuid;
++      char *pNodeName;
++      struct OvlySect *pCreateSects;
++      struct OvlySect *pDeleteSects;
++      struct OvlySect *pExecuteSects;
++      struct OvlySect *pOtherSects;
++      u16 nCreateSects;
++      u16 nDeleteSects;
++      u16 nExecuteSects;
++      u16 nOtherSects;
++      u16 createRef;
++      u16 deleteRef;
++      u16 executeRef;
++      u16 otherRef;
++};
++
++/*
++ *  ======== NLDR_OBJECT ========
++ *  Overlay loader object.
++ */
++struct NLDR_OBJECT {
++      u32 dwSignature;        /* For object validation */
++      struct DEV_OBJECT *hDevObject;  /* Device object */
++      struct DCD_MANAGER *hDcdMgr;    /* Proc/Node data manager */
++      struct DBLL_TarObj *dbll;       /* The DBL loader */
++      struct DBLL_LibraryObj *baseLib;        /* Base image library */
++      struct RMM_TargetObj *rmm;      /* Remote memory manager for DSP */
++      struct DBLL_Fxns dbllFxns;      /* Loader function table */
++      struct DBLL_Attrs dbllAttrs;    /* attrs to pass to loader functions */
++      NLDR_OVLYFXN ovlyFxn;   /* "write" for overlay nodes */
++      NLDR_WRITEFXN writeFxn; /* "write" for dynamic nodes */
++      struct OvlyNode *ovlyTable;     /* Table of overlay nodes */
++      u16 nOvlyNodes; /* Number of overlay nodes in base */
++      u16 nNode;              /* Index for tracking overlay nodes */
++      u16 nSegs;              /* Number of dynamic load mem segs */
++      u32 *segTable;  /* memtypes of dynamic memory segs
++                               * indexed by segid
++                               */
++      u16 usDSPMauSize;       /* Size of DSP MAU */
++      u16 usDSPWordSize;      /* Size of DSP word */
++};
++
++/*
++ *  ======== NLDR_NODEOBJECT ========
++ *  Dynamic node object. This object is created when a node is allocated.
++ */
++struct NLDR_NODEOBJECT {
++      u32 dwSignature;        /* For object validation */
++      struct NLDR_OBJECT *pNldr;      /* Dynamic loader handle */
++      void *pPrivRef;         /* Handle to pass to DBL_WriteFxn */
++      struct DSP_UUID uuid;           /* Node's UUID */
++      bool fDynamic;          /* Dynamically loaded node? */
++      bool fOverlay;          /* Overlay node? */
++      bool *pfPhaseSplit;     /* Multiple phase libraries? */
++      struct LibNode root;            /* Library containing node phase */
++      struct LibNode createLib;    /* Library containing create phase lib */
++      struct LibNode executeLib;   /* Library containing execute phase lib */
++      struct LibNode deleteLib;    /* Library containing delete phase lib */
++      struct LibNode persLib[MAXLIBS];  /* libs remain loaded until Delete */
++      s32 nPersLib;           /* Number of persistent libraries */
++      /* Path in lib dependency tree */
++      struct DBLL_LibraryObj *libPath[MAXDEPTH + 1];
++      enum NLDR_PHASE phase;  /* Node phase currently being loaded */
++
++      /*
++       *  Dynamic loading memory segments for data and code of each phase.
++       */
++      u16 segId[MAXFLAGS];
++
++      /*
++       *  Mask indicating whether each mem segment specified in segId[]
++       *  is preferred or required.
++       *  For example if (codeDataFlagMask & (1 << EXECUTEDATAFLAGBIT)) != 0,
++       *  then it is required to load execute phase data into the memory
++       *  specified by segId[EXECUTEDATAFLAGBIT].
++       */
++      u32 codeDataFlagMask;
++};
++
++/* Dynamic loader function table */
++static struct DBLL_Fxns dbllFxns = {
++      (DBLL_CloseFxn) DBLL_close,
++      (DBLL_CreateFxn) DBLL_create,
++      (DBLL_DeleteFxn) DBLL_delete,
++      (DBLL_ExitFxn) DBLL_exit,
++      (DBLL_GetAttrsFxn) DBLL_getAttrs,
++      (DBLL_GetAddrFxn) DBLL_getAddr,
++      (DBLL_GetCAddrFxn) DBLL_getCAddr,
++      (DBLL_GetSectFxn) DBLL_getSect,
++      (DBLL_InitFxn) DBLL_init,
++      (DBLL_LoadFxn) DBLL_load,
++      (DBLL_LoadSectFxn) DBLL_loadSect,
++      (DBLL_OpenFxn) DBLL_open,
++      (DBLL_ReadSectFxn) DBLL_readSect,
++      (DBLL_SetAttrsFxn) DBLL_setAttrs,
++      (DBLL_UnloadFxn) DBLL_unload,
++      (DBLL_UnloadSectFxn) DBLL_unloadSect,
++};
++
++static struct GT_Mask NLDR_debugMask = { NULL, NULL };        /* GT trace variable */
++static u32 cRefs;             /* module reference count */
++
++static DSP_STATUS AddOvlyInfo(void *handle, struct DBLL_SectInfo *sectInfo,
++                           u32 addr, u32 nBytes);
++static DSP_STATUS AddOvlyNode(struct DSP_UUID *pUuid,
++                           enum DSP_DCDOBJTYPE objType,
++                           IN void *handle);
++static DSP_STATUS AddOvlySect(struct NLDR_OBJECT *hNldr,
++                            struct OvlySect **pList,
++                            struct DBLL_SectInfo *pSectInfo, bool *pExists,
++                            u32 addr, u32 nBytes);
++static s32 fakeOvlyWrite(void *handle, u32 dspAddr, void *buf, u32 nBytes,
++                      s32 mtype);
++static void FreeSects(struct NLDR_OBJECT *hNldr, struct OvlySect *pPhaseSects,
++                   u16 nAlloc);
++static bool GetSymbolValue(void *handle, void *pArg, void *rmmHandle,
++                        char *symName, struct DBLL_Symbol **sym);
++static DSP_STATUS LoadLib(struct NLDR_NODEOBJECT *hNldrNode,
++                       struct LibNode *root, struct DSP_UUID uuid,
++                       bool rootPersistent, struct DBLL_LibraryObj **libPath,
++                       enum NLDR_PHASE phase, u16 depth);
++static DSP_STATUS LoadOvly(struct NLDR_NODEOBJECT *hNldrNode,
++                        enum NLDR_PHASE phase);
++static DSP_STATUS RemoteAlloc(void **pRef, u16 memType, u32 size,
++                           u32 align, u32 *dspAddr,
++                           OPTIONAL s32 segmentId, OPTIONAL s32 req,
++                           bool reserve);
++static DSP_STATUS RemoteFree(void **pRef, u16 space, u32 dspAddr,
++                          u32 size, bool reserve);
++
++static void UnloadLib(struct NLDR_NODEOBJECT *hNldrNode, struct LibNode *root);
++static void UnloadOvly(struct NLDR_NODEOBJECT *hNldrNode,
++                    enum NLDR_PHASE phase);
++static bool findInPersistentLibArray(struct NLDR_NODEOBJECT *hNldrNode,
++                                  struct DBLL_LibraryObj *lib);
++static u32 findLcm(u32 a, u32 b);
++static u32 findGcf(u32 a, u32 b);
++
++/*
++ *  ======== NLDR_Allocate ========
++ */
++DSP_STATUS NLDR_Allocate(struct NLDR_OBJECT *hNldr, void *pPrivRef,
++                       IN CONST struct DCD_NODEPROPS *pNodeProps,
++                       OUT struct NLDR_NODEOBJECT **phNldrNode,
++                       IN bool *pfPhaseSplit)
++{
++      struct NLDR_NODEOBJECT *pNldrNode = NULL;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pNodeProps != NULL);
++      DBC_Require(phNldrNode != NULL);
++      DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++
++      GT_5trace(NLDR_debugMask, GT_ENTER, "NLDR_Allocate(0x%x, 0x%x, 0x%x, "
++               "0x%x, 0x%x)\n", hNldr, pPrivRef, pNodeProps, phNldrNode,
++               pfPhaseSplit);
++
++      /* Initialize handle in case of failure */
++      *phNldrNode = NULL;
++      /* Allocate node object */
++      MEM_AllocObject(pNldrNode, struct NLDR_NODEOBJECT, NLDR_NODESIGNATURE);
++
++      if (pNldrNode == NULL) {
++              GT_0trace(NLDR_debugMask, GT_6CLASS, "NLDR_Allocate: "
++                       "Memory allocation failed\n");
++              status = DSP_EMEMORY;
++      } else {
++              pNldrNode->pfPhaseSplit = pfPhaseSplit;
++              pNldrNode->nPersLib = 0;
++              pNldrNode->pNldr = hNldr;
++              pNldrNode->pPrivRef = pPrivRef;
++              /* Save node's UUID. */
++              pNldrNode->uuid = pNodeProps->ndbProps.uiNodeID;
++              /*
++               *  Determine if node is a dynamically loaded node from
++               *  ndbProps.
++               */
++              if (pNodeProps->usLoadType == NLDR_DYNAMICLOAD) {
++                      /* Dynamic node */
++                      pNldrNode->fDynamic = true;
++                      /*
++                       *  Extract memory requirements from ndbProps masks
++                       */
++                      /* Create phase */
++                      pNldrNode->segId[CREATEDATAFLAGBIT] = (u16)
++                              (pNodeProps->ulDataMemSegMask >> CREATEBIT) &
++                              SEGMASK;
++                      pNldrNode->codeDataFlagMask |=
++                              ((pNodeProps->ulDataMemSegMask >>
++                              (CREATEBIT + FLAGBIT)) & 1) <<
++                              CREATEDATAFLAGBIT;
++                      pNldrNode->segId[CREATECODEFLAGBIT] = (u16)
++                              (pNodeProps->ulCodeMemSegMask >>
++                              CREATEBIT) & SEGMASK;
++                      pNldrNode->codeDataFlagMask |=
++                              ((pNodeProps->ulCodeMemSegMask >>
++                              (CREATEBIT + FLAGBIT)) & 1) <<
++                              CREATECODEFLAGBIT;
++                      /* Execute phase */
++                      pNldrNode->segId[EXECUTEDATAFLAGBIT] = (u16)
++                              (pNodeProps->ulDataMemSegMask >>
++                              EXECUTEBIT) & SEGMASK;
++                      pNldrNode->codeDataFlagMask |=
++                              ((pNodeProps->ulDataMemSegMask >>
++                              (EXECUTEBIT + FLAGBIT)) & 1) <<
++                              EXECUTEDATAFLAGBIT;
++                      pNldrNode->segId[EXECUTECODEFLAGBIT] = (u16)
++                              (pNodeProps->ulCodeMemSegMask >>
++                              EXECUTEBIT) & SEGMASK;
++                      pNldrNode->codeDataFlagMask |=
++                              ((pNodeProps->ulCodeMemSegMask >>
++                              (EXECUTEBIT + FLAGBIT)) & 1) <<
++                              EXECUTECODEFLAGBIT;
++                      /* Delete phase */
++                      pNldrNode->segId[DELETEDATAFLAGBIT] = (u16)
++                          (pNodeProps->ulDataMemSegMask >> DELETEBIT) &
++                          SEGMASK;
++                      pNldrNode->codeDataFlagMask |=
++                              ((pNodeProps->ulDataMemSegMask >>
++                              (DELETEBIT + FLAGBIT)) & 1) <<
++                              DELETEDATAFLAGBIT;
++                      pNldrNode->segId[DELETECODEFLAGBIT] = (u16)
++                              (pNodeProps->ulCodeMemSegMask >>
++                              DELETEBIT) & SEGMASK;
++                      pNldrNode->codeDataFlagMask |=
++                              ((pNodeProps->ulCodeMemSegMask >>
++                              (DELETEBIT + FLAGBIT)) & 1) <<
++                              DELETECODEFLAGBIT;
++              } else {
++                      /* Non-dynamically loaded nodes are part of the
++                       * base image */
++                      pNldrNode->root.lib = hNldr->baseLib;
++                      /* Check for overlay node */
++                      if (pNodeProps->usLoadType == NLDR_OVLYLOAD)
++                              pNldrNode->fOverlay = true;
++
++              }
++              *phNldrNode = (struct NLDR_NODEOBJECT *) pNldrNode;
++      }
++      /* Cleanup on failure */
++      if (DSP_FAILED(status) && pNldrNode)
++              NLDR_Free((struct NLDR_NODEOBJECT *) pNldrNode);
++
++      DBC_Ensure((DSP_SUCCEEDED(status) &&
++                MEM_IsValidHandle(((struct NLDR_NODEOBJECT *)(*phNldrNode)),
++                NLDR_NODESIGNATURE)) || (DSP_FAILED(status) &&
++                *phNldrNode == NULL));
++      return status;
++}
++
++/*
++ *  ======== NLDR_Create ========
++ */
++DSP_STATUS NLDR_Create(OUT struct NLDR_OBJECT **phNldr,
++                    struct DEV_OBJECT *hDevObject,
++                    IN CONST struct NLDR_ATTRS *pAttrs)
++{
++      struct COD_MANAGER *hCodMgr;    /* COD manager */
++      char *pszCoffBuf = NULL;
++      char szZLFile[COD_MAXPATHLENGTH];
++      struct NLDR_OBJECT *pNldr = NULL;
++      struct DBLL_Attrs saveAttrs;
++      struct DBLL_Attrs newAttrs;
++      DBLL_Flags flags;
++      u32 ulEntry;
++      u16 nSegs = 0;
++      struct MemInfo *pMemInfo;
++      u32 ulLen = 0;
++      u32 ulAddr;
++      struct RMM_Segment *rmmSegs = NULL;
++      u16 i;
++      DSP_STATUS status = DSP_SOK;
++      DBC_Require(cRefs > 0);
++      DBC_Require(phNldr != NULL);
++      DBC_Require(hDevObject != NULL);
++      DBC_Require(pAttrs != NULL);
++      DBC_Require(pAttrs->pfnOvly != NULL);
++      DBC_Require(pAttrs->pfnWrite != NULL);
++      GT_3trace(NLDR_debugMask, GT_ENTER, "NLDR_Create(0x%x, 0x%x, 0x%x)\n",
++               phNldr, hDevObject, pAttrs);
++      /* Allocate dynamic loader object */
++      MEM_AllocObject(pNldr, struct NLDR_OBJECT, NLDR_SIGNATURE);
++      if (pNldr) {
++              pNldr->hDevObject = hDevObject;
++              /* warning, lazy status checking alert! */
++              status = DEV_GetCodMgr(hDevObject, &hCodMgr);
++              DBC_Assert(DSP_SUCCEEDED(status));
++              status = COD_GetLoader(hCodMgr, &pNldr->dbll);
++              DBC_Assert(DSP_SUCCEEDED(status));
++              status = COD_GetBaseLib(hCodMgr, &pNldr->baseLib);
++              DBC_Assert(DSP_SUCCEEDED(status));
++              status = COD_GetBaseName(hCodMgr, szZLFile, COD_MAXPATHLENGTH);
++              DBC_Assert(DSP_SUCCEEDED(status));
++              status = DSP_SOK;
++              /* end lazy status checking */
++              pNldr->usDSPMauSize = pAttrs->usDSPMauSize;
++              pNldr->usDSPWordSize = pAttrs->usDSPWordSize;
++              pNldr->dbllFxns = dbllFxns;
++              if (!(pNldr->dbllFxns.initFxn()))
++                      status = DSP_EMEMORY;
++
++      } else {
++              GT_0trace(NLDR_debugMask, GT_6CLASS, "NLDR_Create: "
++                       "Memory allocation failed\n");
++              status = DSP_EMEMORY;
++      }
++      /* Create the DCD Manager */
++      if (DSP_SUCCEEDED(status))
++              status = DCD_CreateManager(NULL, &pNldr->hDcdMgr);
++
++      /* Get dynamic loading memory sections from base lib */
++      if (DSP_SUCCEEDED(status)) {
++              status = pNldr->dbllFxns.getSectFxn(pNldr->baseLib, DYNMEMSECT,
++                       &ulAddr, &ulLen);
++              if (DSP_SUCCEEDED(status)) {
++                      pszCoffBuf = MEM_Calloc(ulLen * pNldr->usDSPMauSize,
++                                              MEM_PAGED);
++                      if (!pszCoffBuf) {
++                              GT_0trace(NLDR_debugMask, GT_6CLASS,
++                                       "NLDR_Create: Memory "
++                                       "allocation failed\n");
++                              status = DSP_EMEMORY;
++                      }
++              } else {
++                      /* Ok to not have dynamic loading memory */
++                      status = DSP_SOK;
++                      ulLen = 0;
++                      GT_1trace(NLDR_debugMask, GT_6CLASS,
++                               "NLDR_Create: DBLL_getSect "
++                               "failed (no dynamic loading mem segments): "
++                               "0x%lx\n", status);
++              }
++      }
++      if (DSP_SUCCEEDED(status) && ulLen > 0) {
++              /* Read section containing dynamic load mem segments */
++              status = pNldr->dbllFxns.readSectFxn(pNldr->baseLib, DYNMEMSECT,
++                                                  pszCoffBuf, ulLen);
++              if (DSP_FAILED(status)) {
++                      GT_1trace(NLDR_debugMask, GT_6CLASS,
++                               "NLDR_Create: DBLL_read Section"
++                               "failed: 0x%lx\n", status);
++              }
++      }
++      if (DSP_SUCCEEDED(status) && ulLen > 0) {
++              /* Parse memory segment data */
++              nSegs = (u16)(*((u32 *)pszCoffBuf));
++              if (nSegs > MAXMEMSEGS) {
++                      GT_1trace(NLDR_debugMask, GT_6CLASS,
++                               "NLDR_Create: Invalid number of "
++                               "dynamic load mem segments: 0x%lx\n", nSegs);
++                      status = DSP_ECORRUPTFILE;
++              }
++      }
++      /* Parse dynamic load memory segments */
++      if (DSP_SUCCEEDED(status) && nSegs > 0) {
++              rmmSegs = MEM_Calloc(sizeof(struct RMM_Segment) * nSegs,
++                                  MEM_PAGED);
++              pNldr->segTable = MEM_Calloc(sizeof(u32) * nSegs, MEM_PAGED);
++              if (rmmSegs == NULL || pNldr->segTable == NULL) {
++                      status = DSP_EMEMORY;
++              } else {
++                      pNldr->nSegs = nSegs;
++                      pMemInfo = (struct MemInfo *)(pszCoffBuf +
++                                 sizeof(u32));
++                      for (i = 0; i < nSegs; i++) {
++                              rmmSegs[i].base = (pMemInfo + i)->base;
++                              rmmSegs[i].length = (pMemInfo + i)->len;
++                              rmmSegs[i].space = 0;
++                              pNldr->segTable[i] = (pMemInfo + i)->type;
++#ifdef DEBUG
++                              DBG_Trace(DBG_LEVEL7,
++                                  "** (proc) DLL MEMSEGMENT: %d, Base: 0x%x, "
++                                  "Length: 0x%x\n", i, rmmSegs[i].base,
++                                  rmmSegs[i].length);
++#endif
++                      }
++              }
++      }
++      /* Create Remote memory manager */
++      if (DSP_SUCCEEDED(status))
++              status = RMM_create(&pNldr->rmm, rmmSegs, nSegs);
++
++      if (DSP_SUCCEEDED(status)) {
++              /* set the alloc, free, write functions for loader */
++              pNldr->dbllFxns.getAttrsFxn(pNldr->dbll, &saveAttrs);
++              newAttrs = saveAttrs;
++              newAttrs.alloc = (DBLL_AllocFxn) RemoteAlloc;
++              newAttrs.free = (DBLL_FreeFxn) RemoteFree;
++              newAttrs.symLookup = (DBLL_SymLookup) GetSymbolValue;
++              newAttrs.symHandle = pNldr;
++              newAttrs.write = (DBLL_WriteFxn) pAttrs->pfnWrite;
++              pNldr->ovlyFxn = pAttrs->pfnOvly;
++              pNldr->writeFxn = pAttrs->pfnWrite;
++              pNldr->dbllAttrs = newAttrs;
++      }
++      if (rmmSegs)
++              MEM_Free(rmmSegs);
++
++      if (pszCoffBuf)
++              MEM_Free(pszCoffBuf);
++
++      /* Get overlay nodes */
++      if (DSP_SUCCEEDED(status)) {
++              status = COD_GetBaseName(hCodMgr, szZLFile, COD_MAXPATHLENGTH);
++              /* lazy check */
++              DBC_Assert(DSP_SUCCEEDED(status));
++              /* First count number of overlay nodes */
++              status = DCD_GetObjects(pNldr->hDcdMgr, szZLFile, AddOvlyNode,
++                                      (void *) pNldr);
++              /* Now build table of overlay nodes */
++              if (DSP_SUCCEEDED(status) && pNldr->nOvlyNodes > 0) {
++                      /* Allocate table for overlay nodes */
++                      pNldr->ovlyTable =
++                      MEM_Calloc(sizeof(struct OvlyNode) * pNldr->nOvlyNodes,
++                                MEM_PAGED);
++                      /* Put overlay nodes in the table */
++                      pNldr->nNode = 0;
++                      status = DCD_GetObjects(pNldr->hDcdMgr, szZLFile,
++                                              AddOvlyNode,
++                                              (void *) pNldr);
++              }
++      }
++      /* Do a fake reload of the base image to get overlay section info */
++      if (DSP_SUCCEEDED(status) && pNldr->nOvlyNodes > 0) {
++              saveAttrs.write = fakeOvlyWrite;
++              saveAttrs.logWrite = AddOvlyInfo;
++              saveAttrs.logWriteHandle = pNldr;
++              flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
++              status = pNldr->dbllFxns.loadFxn(pNldr->baseLib, flags,
++                                              &saveAttrs, &ulEntry);
++      }
++      if (DSP_SUCCEEDED(status)) {
++              *phNldr = (struct NLDR_OBJECT *) pNldr;
++      } else {
++              if (pNldr)
++                      NLDR_Delete((struct NLDR_OBJECT *) pNldr);
++
++              *phNldr = NULL;
++      }
++      /* FIXME:Temp. Fix. Must be removed */
++      DBC_Ensure((DSP_SUCCEEDED(status) &&
++                       MEM_IsValidHandle(((struct NLDR_OBJECT *)*phNldr),
++                                        NLDR_SIGNATURE))
++                      || (DSP_FAILED(status) && (*phNldr == NULL)));
++      return status;
++}
++
++/*
++ *  ======== NLDR_Delete ========
++ */
++void NLDR_Delete(struct NLDR_OBJECT *hNldr)
++{
++      struct OvlySect *pSect;
++      struct OvlySect *pNext;
++      u16 i;
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++      GT_1trace(NLDR_debugMask, GT_ENTER, "NLDR_Delete(0x%x)\n", hNldr);
++      hNldr->dbllFxns.exitFxn();
++      if (hNldr->rmm)
++              RMM_delete(hNldr->rmm);
++
++      if (hNldr->segTable)
++              MEM_Free(hNldr->segTable);
++
++      if (hNldr->hDcdMgr)
++              DCD_DestroyManager(hNldr->hDcdMgr);
++
++      /* Free overlay node information */
++      if (hNldr->ovlyTable) {
++              for (i = 0; i < hNldr->nOvlyNodes; i++) {
++                      pSect = hNldr->ovlyTable[i].pCreateSects;
++                      while (pSect) {
++                              pNext = pSect->pNextSect;
++                              MEM_Free(pSect);
++                              pSect = pNext;
++                      }
++                      pSect = hNldr->ovlyTable[i].pDeleteSects;
++                      while (pSect) {
++                              pNext = pSect->pNextSect;
++                              MEM_Free(pSect);
++                              pSect = pNext;
++                      }
++                      pSect = hNldr->ovlyTable[i].pExecuteSects;
++                      while (pSect) {
++                              pNext = pSect->pNextSect;
++                              MEM_Free(pSect);
++                              pSect = pNext;
++                      }
++                      pSect = hNldr->ovlyTable[i].pOtherSects;
++                      while (pSect) {
++                              pNext = pSect->pNextSect;
++                              MEM_Free(pSect);
++                              pSect = pNext;
++                      }
++              }
++              MEM_Free(hNldr->ovlyTable);
++      }
++      MEM_FreeObject(hNldr);
++      DBC_Ensure(!MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++}
++
++/*
++ *  ======== NLDR_Exit ========
++ *  Discontinue usage of NLDR module.
++ */
++void NLDR_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      cRefs--;
++
++      GT_1trace(NLDR_debugMask, GT_5CLASS,
++               "Entered NLDR_Exit, ref count:  0x%x\n", cRefs);
++
++      if (cRefs == 0) {
++              RMM_exit();
++              NLDR_debugMask.flags = NULL;
++      }
++
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== NLDR_Free ========
++ */
++void NLDR_Free(struct NLDR_NODEOBJECT *hNldrNode)
++{
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++
++      GT_1trace(NLDR_debugMask, GT_ENTER, "NLDR_Free(0x%x)\n", hNldrNode);
++
++      MEM_FreeObject(hNldrNode);
++}
++
++/*
++ *  ======== NLDR_GetFxnAddr ========
++ */
++DSP_STATUS NLDR_GetFxnAddr(struct NLDR_NODEOBJECT *hNldrNode, char *pstrFxn,
++                        u32 *pulAddr)
++{
++      struct DBLL_Symbol *pSym;
++      struct NLDR_OBJECT *hNldr;
++      DSP_STATUS status = DSP_SOK;
++      bool status1 = false;
++      s32 i = 0;
++      struct LibNode root = { NULL, 0, NULL };
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++      DBC_Require(pulAddr != NULL);
++      DBC_Require(pstrFxn != NULL);
++      GT_3trace(NLDR_debugMask, GT_ENTER, "NLDR_GetFxnAddr(0x%x, %s, 0x%x)\n",
++               hNldrNode, pstrFxn, pulAddr);
++
++      hNldr = hNldrNode->pNldr;
++      /* Called from NODE_Create(), NODE_Delete(), or NODE_Run(). */
++      if (hNldrNode->fDynamic && *hNldrNode->pfPhaseSplit) {
++              switch (hNldrNode->phase) {
++              case NLDR_CREATE:
++                      root = hNldrNode->createLib;
++                      break;
++              case NLDR_EXECUTE:
++                      root = hNldrNode->executeLib;
++                      break;
++              case NLDR_DELETE:
++                      root = hNldrNode->deleteLib;
++                      break;
++              default:
++                      DBC_Assert(false);
++                      break;
++              }
++      } else {
++              /* for Overlay nodes or non-split Dynamic nodes */
++              root = hNldrNode->root;
++      }
++      status1 = hNldr->dbllFxns.getCAddrFxn(root.lib, pstrFxn, &pSym);
++      if (!status1)
++              status1 = hNldr->dbllFxns.getAddrFxn(root.lib, pstrFxn, &pSym);
++
++      /* If symbol not found, check dependent libraries */
++      if (!status1) {
++              for (i = 0; i < root.nDepLibs; i++) {
++                      status1 = hNldr->dbllFxns.getAddrFxn(root.pDepLibs[i].
++                                      lib, pstrFxn, &pSym);
++                      if (!status1) {
++                              status1 = hNldr->dbllFxns.getCAddrFxn(root.
++                                      pDepLibs[i].lib, pstrFxn, &pSym);
++                      }
++                      if (status1) {
++                              /* Symbol found */
++                              break;
++                      }
++              }
++      }
++      /* Check persistent libraries */
++      if (!status1) {
++              for (i = 0; i < hNldrNode->nPersLib; i++) {
++                      status1 = hNldr->dbllFxns.getAddrFxn(hNldrNode->
++                                      persLib[i].lib, pstrFxn, &pSym);
++                      if (!status1) {
++                              status1 =
++                                  hNldr->dbllFxns.getCAddrFxn(hNldrNode->
++                                      persLib[i].lib, pstrFxn, &pSym);
++                      }
++                      if (status1) {
++                              /* Symbol found */
++                              break;
++                      }
++              }
++      }
++
++      if (status1) {
++              *pulAddr = pSym->value;
++      } else {
++              GT_1trace(NLDR_debugMask, GT_6CLASS,
++                       "NLDR_GetFxnAddr: Symbol not found: "
++                       "%s\n", pstrFxn);
++              status = DSP_ESYMBOL;
++      }
++
++      return status;
++}
++
++/*
++ *  ======== NLDR_GetRmmManager ========
++ *  Given a NLDR object, retrieve RMM Manager Handle
++ */
++DSP_STATUS NLDR_GetRmmManager(struct NLDR_OBJECT *hNldrObject,
++                           OUT struct RMM_TargetObj **phRmmMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct NLDR_OBJECT *pNldrObject = hNldrObject;
++      DBC_Require(phRmmMgr != NULL);
++      GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_GetRmmManager(0x%x, 0x%x)\n",
++               hNldrObject, phRmmMgr);
++      if (MEM_IsValidHandle(hNldrObject, NLDR_SIGNATURE)) {
++              *phRmmMgr = pNldrObject->rmm;
++      } else {
++              *phRmmMgr = NULL;
++              status = DSP_EHANDLE;
++              GT_0trace(NLDR_debugMask, GT_7CLASS,
++                       "NLDR_GetRmmManager:Invalid handle");
++      }
++
++      GT_2trace(NLDR_debugMask, GT_ENTER, "Exit NLDR_GetRmmManager: status "
++               "0x%x\n\tphRmmMgr:  0x%x\n", status, *phRmmMgr);
++
++      DBC_Ensure(DSP_SUCCEEDED(status) || ((phRmmMgr != NULL) &&
++                (*phRmmMgr == NULL)));
++
++      return status;
++}
++
++/*
++ *  ======== NLDR_Init ========
++ *  Initialize the NLDR module.
++ */
++bool NLDR_Init(void)
++{
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++              DBC_Assert(!NLDR_debugMask.flags);
++              GT_create(&NLDR_debugMask, "DL");       /* "DL" for DLdr */
++
++              RMM_init();
++      }
++
++      cRefs++;
++
++      GT_1trace(NLDR_debugMask, GT_5CLASS, "NLDR_Init(), ref count: 0x%x\n",
++               cRefs);
++
++      DBC_Ensure(cRefs > 0);
++      return true;
++}
++
++/*
++ *  ======== NLDR_Load ========
++ */
++DSP_STATUS NLDR_Load(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
++{
++      struct NLDR_OBJECT *hNldr;
++      struct DSP_UUID libUUID;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++
++      hNldr = hNldrNode->pNldr;
++
++      GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_Load(0x%x, 0x%x)\n",
++               hNldrNode, phase);
++
++      if (hNldrNode->fDynamic) {
++              hNldrNode->phase = phase;
++
++              libUUID = hNldrNode->uuid;
++
++              /* At this point, we may not know if node is split into
++               * different libraries. So we'll go ahead and load the
++               * library, and then save the pointer to the appropriate
++               * location after we know. */
++
++              status = LoadLib(hNldrNode, &hNldrNode->root, libUUID, false,
++                              hNldrNode->libPath, phase, 0);
++
++              if (DSP_SUCCEEDED(status)) {
++                      if (*hNldrNode->pfPhaseSplit) {
++                              switch (phase) {
++                              case NLDR_CREATE:
++                                      hNldrNode->createLib = hNldrNode->root;
++                                      break;
++
++                              case NLDR_EXECUTE:
++                                      hNldrNode->executeLib = hNldrNode->root;
++                                      break;
++
++                              case NLDR_DELETE:
++                                      hNldrNode->deleteLib = hNldrNode->root;
++                                      break;
++
++                              default:
++                                      DBC_Assert(false);
++                                      break;
++                              }
++                      }
++              }
++      } else {
++              if (hNldrNode->fOverlay)
++                      status = LoadOvly(hNldrNode, phase);
++
++      }
++
++      return status;
++}
++
++/*
++ *  ======== NLDR_Unload ========
++ */
++DSP_STATUS NLDR_Unload(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct LibNode *pRootLib = NULL;
++      s32 i = 0;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++      GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_Unload(0x%x, 0x%x)\n",
++               hNldrNode, phase);
++      if (hNldrNode != NULL) {
++              if (hNldrNode->fDynamic) {
++                      if (*hNldrNode->pfPhaseSplit) {
++                              switch (phase) {
++                              case NLDR_CREATE:
++                                      pRootLib = &hNldrNode->createLib;
++                                      break;
++                              case NLDR_EXECUTE:
++                                      pRootLib = &hNldrNode->executeLib;
++                                      break;
++                              case NLDR_DELETE:
++                                      pRootLib = &hNldrNode->deleteLib;
++                                      /* Unload persistent libraries */
++                                      for (i = 0; i < hNldrNode->nPersLib;
++                                          i++) {
++                                              UnloadLib(hNldrNode,
++                                                      &hNldrNode->persLib[i]);
++                                      }
++                                      hNldrNode->nPersLib = 0;
++                                      break;
++                              default:
++                                      DBC_Assert(false);
++                                      break;
++                              }
++                      } else {
++                              /* Unload main library */
++                              pRootLib = &hNldrNode->root;
++                      }
++                      UnloadLib(hNldrNode, pRootLib);
++              } else {
++                      if (hNldrNode->fOverlay)
++                              UnloadOvly(hNldrNode, phase);
++
++              }
++      }
++      return status;
++}
++
++/*
++ *  ======== AddOvlyInfo ========
++ */
++static DSP_STATUS AddOvlyInfo(void *handle, struct DBLL_SectInfo *sectInfo,
++                           u32 addr, u32 nBytes)
++{
++      char *pNodeName;
++      char *pSectName = (char *)sectInfo->name;
++      bool fExists = false;
++      char seps = ':';
++      char *pch;
++      u16 i;
++      struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
++      DSP_STATUS status = DSP_SOK;
++
++      /* Is this an overlay section (load address != run address)? */
++      if (sectInfo->loadAddr == sectInfo->runAddr)
++              goto func_end;
++
++      /* Find the node it belongs to */
++      for (i = 0; i < hNldr->nOvlyNodes; i++) {
++              pNodeName = hNldr->ovlyTable[i].pNodeName;
++               DBC_Require(pNodeName);
++               if (strncmp(pNodeName, pSectName + 1,
++                               strlen(pNodeName)) == 0) {
++                              /* Found the node */
++                              break;
++              }
++      }
++      if (!(i < hNldr->nOvlyNodes))
++              goto func_end;
++
++      /* Determine which phase this section belongs to */
++      for (pch = pSectName + 1; *pch && *pch != seps; pch++)
++              ;;
++
++      if (*pch) {
++              pch++;  /* Skip over the ':' */
++               if (strncmp(pch, PCREATE, strlen(PCREATE)) == 0) {
++                      status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++                              pCreateSects, sectInfo, &fExists, addr, nBytes);
++                      if (DSP_SUCCEEDED(status) && !fExists)
++                              hNldr->ovlyTable[i].nCreateSects++;
++
++              } else
++               if (strncmp(pch, PDELETE, strlen(PDELETE)) == 0) {
++                      status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++                                          pDeleteSects, sectInfo, &fExists,
++                                          addr, nBytes);
++                      if (DSP_SUCCEEDED(status) && !fExists)
++                              hNldr->ovlyTable[i].nDeleteSects++;
++
++              } else
++               if (strncmp(pch, PEXECUTE, strlen(PEXECUTE)) == 0) {
++                      status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++                                          pExecuteSects, sectInfo, &fExists,
++                                          addr, nBytes);
++                      if (DSP_SUCCEEDED(status) && !fExists)
++                              hNldr->ovlyTable[i].nExecuteSects++;
++
++              } else {
++                      /* Put in "other" sectins */
++                      status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++                                          pOtherSects, sectInfo, &fExists,
++                                          addr, nBytes);
++                      if (DSP_SUCCEEDED(status) && !fExists)
++                              hNldr->ovlyTable[i].nOtherSects++;
++
++              }
++      }
++func_end:
++      return status;
++}
++
++/*
++ *  ======== AddOvlyNode =========
++ *  Callback function passed to DCD_GetObjects.
++ */
++static DSP_STATUS AddOvlyNode(struct DSP_UUID *pUuid,
++                           enum DSP_DCDOBJTYPE objType,
++                           IN void *handle)
++{
++      struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
++      char *pNodeName = NULL;
++      char *pBuf = NULL;
++      u32 uLen;
++      struct DCD_GENERICOBJ objDef;
++      DSP_STATUS status = DSP_SOK;
++
++      if (objType != DSP_DCDNODETYPE)
++              goto func_end;
++
++      status = DCD_GetObjectDef(hNldr->hDcdMgr, pUuid, objType, &objDef);
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      /* If overlay node, add to the list */
++      if (objDef.objData.nodeObj.usLoadType == NLDR_OVLYLOAD) {
++              if (hNldr->ovlyTable == NULL) {
++                      hNldr->nOvlyNodes++;
++              } else {
++                      /* Add node to table */
++                      hNldr->ovlyTable[hNldr->nNode].uuid = *pUuid;
++                       DBC_Require(objDef.objData.nodeObj.ndbProps.acName);
++                       uLen = strlen(objDef.objData.nodeObj.ndbProps.acName);
++                      pNodeName = objDef.objData.nodeObj.ndbProps.acName;
++                      pBuf = MEM_Calloc(uLen + 1, MEM_PAGED);
++                      if (pBuf == NULL) {
++                              status = DSP_EMEMORY;
++                      } else {
++                               strncpy(pBuf, pNodeName, uLen);
++                              hNldr->ovlyTable[hNldr->nNode].pNodeName = pBuf;
++                              hNldr->nNode++;
++                      }
++              }
++      }
++      /* These were allocated in DCD_GetObjectDef */
++      if (objDef.objData.nodeObj.pstrCreatePhaseFxn)
++              MEM_Free(objDef.objData.nodeObj.pstrCreatePhaseFxn);
++
++      if (objDef.objData.nodeObj.pstrExecutePhaseFxn)
++              MEM_Free(objDef.objData.nodeObj.pstrExecutePhaseFxn);
++
++      if (objDef.objData.nodeObj.pstrDeletePhaseFxn)
++              MEM_Free(objDef.objData.nodeObj.pstrDeletePhaseFxn);
++
++      if (objDef.objData.nodeObj.pstrIAlgName)
++              MEM_Free(objDef.objData.nodeObj.pstrIAlgName);
++
++func_end:
++      return status;
++}
++
++/*
++ *  ======== AddOvlySect ========
++ */
++static DSP_STATUS AddOvlySect(struct NLDR_OBJECT *hNldr,
++                            struct OvlySect **pList,
++                            struct DBLL_SectInfo *pSectInfo, bool *pExists,
++                            u32 addr, u32 nBytes)
++{
++      struct OvlySect *pNewSect = NULL;
++      struct OvlySect *pLastSect;
++      struct OvlySect *pSect;
++      DSP_STATUS status = DSP_SOK;
++
++      pSect = pLastSect = *pList;
++      *pExists = false;
++      while (pSect) {
++              /*
++               *  Make sure section has not already been added. Multiple
++               *  'write' calls may be made to load the section.
++               */
++              if (pSect->loadAddr == addr) {
++                      /* Already added */
++                      *pExists = true;
++                      break;
++              }
++              pLastSect = pSect;
++              pSect = pSect->pNextSect;
++      }
++
++      if (!pSect) {
++              /* New section */
++              pNewSect = MEM_Calloc(sizeof(struct OvlySect), MEM_PAGED);
++              if (pNewSect == NULL) {
++                      status = DSP_EMEMORY;
++              } else {
++                      pNewSect->loadAddr = addr;
++                      pNewSect->runAddr = pSectInfo->runAddr +
++                                          (addr - pSectInfo->loadAddr);
++                      pNewSect->size = nBytes;
++                      pNewSect->page = pSectInfo->type;
++              }
++
++              /* Add to the list */
++              if (DSP_SUCCEEDED(status)) {
++                      if (*pList == NULL) {
++                              /* First in the list */
++                              *pList = pNewSect;
++                      } else {
++                              pLastSect->pNextSect = pNewSect;
++                      }
++              }
++      }
++
++      return status;
++}
++
++/*
++ *  ======== fakeOvlyWrite ========
++ */
++static s32 fakeOvlyWrite(void *handle, u32 dspAddr, void *buf, u32 nBytes,
++                      s32 mtype)
++{
++      return (s32)nBytes;
++}
++
++/*
++ *  ======== FreeSects ========
++ */
++static void FreeSects(struct NLDR_OBJECT *hNldr, struct OvlySect *pPhaseSects,
++                   u16 nAlloc)
++{
++      struct OvlySect *pSect = pPhaseSects;
++      u16 i = 0;
++      bool fRet;
++
++      while (pSect && i < nAlloc) {
++              /* 'Deallocate' */
++              /* segid - page not supported yet */
++              /* Reserved memory */
++              fRet = RMM_free(hNldr->rmm, 0, pSect->runAddr, pSect->size,
++                              true);
++              DBC_Assert(fRet);
++              pSect = pSect->pNextSect;
++              i++;
++      }
++}
++
++/*
++ *  ======== GetSymbolValue ========
++ *  Find symbol in library's base image.  If not there, check dependent
++ *  libraries.
++ */
++static bool GetSymbolValue(void *handle, void *pArg, void *rmmHandle,
++                        char *name, struct DBLL_Symbol **sym)
++{
++      struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
++      struct NLDR_NODEOBJECT *hNldrNode = (struct NLDR_NODEOBJECT *)rmmHandle;
++      struct LibNode *root = (struct LibNode *)pArg;
++      u16 i;
++      bool status = false;
++
++      /* check the base image */
++      status = hNldr->dbllFxns.getAddrFxn(hNldr->baseLib, name, sym);
++      if (!status)
++              status = hNldr->dbllFxns.getCAddrFxn(hNldr->baseLib, name, sym);
++
++      /*
++       *  Check in root lib itself. If the library consists of
++       *  multiple object files linked together, some symbols in the
++       *  library may need to be resolved.
++       */
++      if (!status) {
++              status = hNldr->dbllFxns.getAddrFxn(root->lib, name, sym);
++              if (!status) {
++                      status =
++                          hNldr->dbllFxns.getCAddrFxn(root->lib, name, sym);
++              }
++      }
++
++      /*
++       *  Check in root lib's dependent libraries, but not dependent
++       *  libraries' dependents.
++       */
++      if (!status) {
++              for (i = 0; i < root->nDepLibs; i++) {
++                      status = hNldr->dbllFxns.getAddrFxn(root->pDepLibs[i].
++                                                         lib, name, sym);
++                      if (!status) {
++                              status = hNldr->dbllFxns.getCAddrFxn(root->
++                                       pDepLibs[i].lib, name, sym);
++                      }
++                      if (status) {
++                              /* Symbol found */
++                              break;
++                      }
++              }
++      }
++      /*
++       * Check in persistent libraries
++       */
++      if (!status) {
++              for (i = 0; i < hNldrNode->nPersLib; i++) {
++                      status = hNldr->dbllFxns.getAddrFxn(hNldrNode->
++                               persLib[i].lib, name, sym);
++                      if (!status) {
++                              status = hNldr->dbllFxns.getCAddrFxn
++                                      (hNldrNode->persLib[i].lib, name, sym);
++                      }
++                      if (status) {
++                              /* Symbol found */
++                              break;
++                      }
++              }
++      }
++
++      return status;
++}
++
++/*
++ *  ======== LoadLib ========
++ *  Recursively load library and all its dependent libraries. The library
++ *  we're loading is specified by a uuid.
++ */
++static DSP_STATUS LoadLib(struct NLDR_NODEOBJECT *hNldrNode,
++                       struct LibNode *root, struct DSP_UUID uuid,
++                       bool rootPersistent, struct DBLL_LibraryObj **libPath,
++                       enum NLDR_PHASE phase, u16 depth)
++{
++      struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++      u16 nLibs = 0;  /* Number of dependent libraries */
++      u16 nPLibs = 0; /* Number of persistent libraries */
++      u16 nLoaded = 0;        /* Number of dep. libraries loaded */
++      u16 i;
++      u32 entry;
++      u32 dwBufSize = NLDR_MAXPATHLENGTH;
++      DBLL_Flags flags = DBLL_SYMB | DBLL_CODE | DBLL_DATA | DBLL_DYNAMIC;
++      struct DBLL_Attrs newAttrs;
++      char *pszFileName = NULL;
++      struct DSP_UUID *depLibUUIDs = NULL;
++      bool *persistentDepLibs = NULL;
++      DSP_STATUS status = DSP_SOK;
++      bool fStatus = false;
++      struct LibNode *pDepLib;
++
++      if (depth > MAXDEPTH) {
++              /* Error */
++              DBC_Assert(false);
++      }
++      root->lib = NULL;
++      /* Allocate a buffer for library file name of size DBL_MAXPATHLENGTH */
++      pszFileName = MEM_Calloc(DBLL_MAXPATHLENGTH, MEM_PAGED);
++      if (pszFileName == NULL)
++              status = DSP_EMEMORY;
++
++      if (DSP_SUCCEEDED(status)) {
++              /* Get the name of the library */
++              if (depth == 0) {
++                      status = DCD_GetLibraryName(hNldrNode->pNldr->hDcdMgr,
++                              &uuid, pszFileName, &dwBufSize, phase,
++                              hNldrNode->pfPhaseSplit);
++              } else {
++                      /* Dependent libraries are registered with a phase */
++                      status = DCD_GetLibraryName(hNldrNode->pNldr->hDcdMgr,
++                              &uuid, pszFileName, &dwBufSize, NLDR_NOPHASE,
++                              NULL);
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Open the library, don't load symbols */
++              status = hNldr->dbllFxns.openFxn(hNldr->dbll, pszFileName,
++                       DBLL_NOLOAD, &root->lib);
++      }
++      /* Done with file name */
++      if (pszFileName)
++              MEM_Free(pszFileName);
++
++      /* Check to see if library not already loaded */
++      if (DSP_SUCCEEDED(status) && rootPersistent) {
++              fStatus = findInPersistentLibArray(hNldrNode, root->lib);
++              /* Close library */
++              if (fStatus) {
++                      hNldr->dbllFxns.closeFxn(root->lib);
++                      return DSP_SALREADYLOADED;
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Check for circular dependencies. */
++              for (i = 0; i < depth; i++) {
++                      if (root->lib == libPath[i]) {
++                              /* This condition could be checked by a
++                               * tool at build time. */
++                              status = DSP_EDYNLOAD;
++                      }
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Add library to current path in dependency tree */
++              libPath[depth] = root->lib;
++              depth++;
++              /* Get number of dependent libraries */
++              status = DCD_GetNumDepLibs(hNldrNode->pNldr->hDcdMgr, &uuid,
++                                        &nLibs, &nPLibs, phase);
++      }
++      DBC_Assert(nLibs >= nPLibs);
++      if (DSP_SUCCEEDED(status)) {
++              if (!(*hNldrNode->pfPhaseSplit))
++                      nPLibs = 0;
++
++              /* nLibs = #of dependent libraries */
++              root->nDepLibs = nLibs - nPLibs;
++              if (nLibs > 0) {
++                      depLibUUIDs = MEM_Calloc(sizeof(struct DSP_UUID) *
++                                    nLibs, MEM_PAGED);
++                      persistentDepLibs =
++                              MEM_Calloc(sizeof(bool) * nLibs, MEM_PAGED);
++                      if (!depLibUUIDs || !persistentDepLibs)
++                              status = DSP_EMEMORY;
++
++                      if (root->nDepLibs > 0) {
++                              /* Allocate arrays for dependent lib UUIDs,
++                               * lib nodes */
++                              root->pDepLibs = MEM_Calloc
++                                      (sizeof(struct LibNode) *
++                                      (root->nDepLibs), MEM_PAGED);
++                              if (!(root->pDepLibs))
++                                      status = DSP_EMEMORY;
++
++                      }
++
++                      if (DSP_SUCCEEDED(status)) {
++                              /* Get the dependent library UUIDs */
++                              status = DCD_GetDepLibs(hNldrNode->pNldr->
++                                      hDcdMgr, &uuid, nLibs, depLibUUIDs,
++                                      persistentDepLibs, phase);
++                      }
++              }
++      }
++
++      /*
++       *  Recursively load dependent libraries.
++       */
++      if (DSP_SUCCEEDED(status) && persistentDepLibs) {
++              for (i = 0; i < nLibs; i++) {
++                      /* If root library is NOT persistent, and dep library
++                       * is, then record it.  If root library IS persistent,
++                       * the deplib is already included */
++                      if (!rootPersistent && persistentDepLibs[i] &&
++                         *hNldrNode->pfPhaseSplit) {
++                              if ((hNldrNode->nPersLib) > MAXLIBS) {
++                                      status = DSP_EDYNLOAD;
++                                      break;
++                              }
++
++                              /* Allocate library outside of phase */
++                              pDepLib = &hNldrNode->persLib[hNldrNode->
++                                        nPersLib];
++                      } else {
++                              if (rootPersistent)
++                                      persistentDepLibs[i] = true;
++
++
++                              /* Allocate library within phase */
++                              pDepLib = &root->pDepLibs[nLoaded];
++                      }
++
++                      if (depLibUUIDs) {
++                              status = LoadLib(hNldrNode, pDepLib,
++                                              depLibUUIDs[i],
++                                              persistentDepLibs[i], libPath,
++                                              phase,
++                                              depth);
++                      } else {
++                              status = DSP_EMEMORY;
++                      }
++
++                      if (DSP_SUCCEEDED(status)) {
++                              if ((status != DSP_SALREADYLOADED) &&
++                                 !rootPersistent && persistentDepLibs[i] &&
++                                 *hNldrNode->pfPhaseSplit) {
++                                      (hNldrNode->nPersLib)++;
++                              } else {
++                                      if (!persistentDepLibs[i] ||
++                                         !(*hNldrNode->pfPhaseSplit)) {
++                                              nLoaded++;
++                                      }
++                              }
++                      } else {
++                              break;
++                      }
++              }
++      }
++
++      /* Now we can load the root library */
++      if (DSP_SUCCEEDED(status)) {
++              newAttrs = hNldr->dbllAttrs;
++              newAttrs.symArg = root;
++              newAttrs.rmmHandle = hNldrNode;
++              newAttrs.wHandle = hNldrNode->pPrivRef;
++              newAttrs.baseImage = false;
++
++              status = hNldr->dbllFxns.loadFxn(root->lib, flags, &newAttrs,
++                       &entry);
++      }
++
++      /*
++       *  In case of failure, unload any dependent libraries that
++       *  were loaded, and close the root library.
++       *  (Persistent libraries are unloaded from the very top)
++       */
++      if (DSP_FAILED(status)) {
++              if (phase != NLDR_EXECUTE) {
++                      for (i = 0; i < hNldrNode->nPersLib; i++)
++                              UnloadLib(hNldrNode, &hNldrNode->persLib[i]);
++
++                      hNldrNode->nPersLib = 0;
++              }
++              for (i = 0; i < nLoaded; i++)
++                      UnloadLib(hNldrNode, &root->pDepLibs[i]);
++
++              if (root->lib)
++                      hNldr->dbllFxns.closeFxn(root->lib);
++
++      }
++
++      /* Going up one node in the dependency tree */
++      depth--;
++
++      if (depLibUUIDs) {
++              MEM_Free(depLibUUIDs);
++              depLibUUIDs = NULL;
++      }
++
++      if (persistentDepLibs) {
++              MEM_Free(persistentDepLibs);
++              persistentDepLibs = NULL;
++      }
++
++      return status;
++}
++
++/*
++ *  ======== LoadOvly ========
++ */
++static DSP_STATUS LoadOvly(struct NLDR_NODEOBJECT *hNldrNode,
++                        enum NLDR_PHASE phase)
++{
++      struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++      struct OvlyNode *pONode = NULL;
++      struct OvlySect *pPhaseSects = NULL;
++      struct OvlySect *pOtherSects = NULL;
++      u16 i;
++      u16 nAlloc = 0;
++      u16 nOtherAlloc = 0;
++      u16 *pRefCount = NULL;
++      u16 *pOtherRef = NULL;
++      u32 nBytes;
++      struct OvlySect *pSect;
++      DSP_STATUS status = DSP_SOK;
++
++      /* Find the node in the table */
++      for (i = 0; i < hNldr->nOvlyNodes; i++) {
++              if (IsEqualUUID(hNldrNode->uuid, hNldr->ovlyTable[i].uuid)) {
++                      /* Found it */
++                      pONode = &(hNldr->ovlyTable[i]);
++                      break;
++              }
++      }
++
++      DBC_Assert(i < hNldr->nOvlyNodes);
++      switch (phase) {
++      case NLDR_CREATE:
++              pRefCount = &(pONode->createRef);
++              pOtherRef = &(pONode->otherRef);
++              pPhaseSects = pONode->pCreateSects;
++              pOtherSects = pONode->pOtherSects;
++              break;
++
++      case NLDR_EXECUTE:
++              pRefCount = &(pONode->executeRef);
++              pPhaseSects = pONode->pExecuteSects;
++              break;
++
++      case NLDR_DELETE:
++              pRefCount = &(pONode->deleteRef);
++              pPhaseSects = pONode->pDeleteSects;
++              break;
++
++      default:
++              DBC_Assert(false);
++              break;
++      }
++
++      DBC_Assert(pRefCount != NULL);
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      if (pRefCount == NULL)
++              goto func_end;
++
++      if (*pRefCount != 0)
++              goto func_end;
++
++      /* 'Allocate' memory for overlay sections of this phase */
++      pSect = pPhaseSects;
++      while (pSect) {
++              /* allocate */ /* page not supported yet */
++                /* reserve */ /* align */
++              status = RMM_alloc(hNldr->rmm, 0, pSect->size, 0,
++                       &(pSect->runAddr), true);
++              if (DSP_SUCCEEDED(status)) {
++                      pSect = pSect->pNextSect;
++                      nAlloc++;
++              } else {
++                      break;
++              }
++      }
++      if (pOtherRef && *pOtherRef == 0) {
++              /* 'Allocate' memory for other overlay sections
++               * (create phase) */
++              if (DSP_SUCCEEDED(status)) {
++                      pSect = pOtherSects;
++                      while (pSect) {
++                              /* page not supported */ /* align */
++                              /* reserve */
++                              status = RMM_alloc(hNldr->rmm, 0, pSect->size,
++                                       0, &(pSect->runAddr), true);
++                              if (DSP_SUCCEEDED(status)) {
++                                      pSect = pSect->pNextSect;
++                                      nOtherAlloc++;
++                              } else {
++                                      break;
++                              }
++                      }
++              }
++      }
++      if (*pRefCount == 0) {
++              if (DSP_SUCCEEDED(status)) {
++                      /* Load sections for this phase */
++                      pSect = pPhaseSects;
++                      while (pSect && DSP_SUCCEEDED(status)) {
++                              nBytes = (*hNldr->ovlyFxn)(hNldrNode->pPrivRef,
++                                       pSect->runAddr, pSect->loadAddr,
++                                       pSect->size, pSect->page);
++                              if (nBytes != pSect->size)
++                                      status = DSP_EFAIL;
++
++                              pSect = pSect->pNextSect;
++                      }
++              }
++      }
++      if (pOtherRef && *pOtherRef == 0) {
++              if (DSP_SUCCEEDED(status)) {
++                      /* Load other sections (create phase) */
++                      pSect = pOtherSects;
++                      while (pSect && DSP_SUCCEEDED(status)) {
++                              nBytes = (*hNldr->ovlyFxn)(hNldrNode->pPrivRef,
++                                       pSect->runAddr, pSect->loadAddr,
++                                       pSect->size, pSect->page);
++                              if (nBytes != pSect->size)
++                                      status = DSP_EFAIL;
++
++                              pSect = pSect->pNextSect;
++                      }
++              }
++      }
++      if (DSP_FAILED(status)) {
++              /* 'Deallocate' memory */
++              FreeSects(hNldr, pPhaseSects, nAlloc);
++              FreeSects(hNldr, pOtherSects, nOtherAlloc);
++      }
++func_end:
++      if (DSP_SUCCEEDED(status) && (pRefCount != NULL)) {
++              *pRefCount += 1;
++              if (pOtherRef)
++                      *pOtherRef += 1;
++
++      }
++
++      return status;
++}
++
++/*
++ *  ======== RemoteAlloc ========
++ */
++static DSP_STATUS RemoteAlloc(void **pRef, u16 space, u32 size,
++                           u32 align, u32 *dspAddr,
++                           OPTIONAL s32 segmentId, OPTIONAL s32 req,
++                           bool reserve)
++{
++      struct NLDR_NODEOBJECT *hNode = (struct NLDR_NODEOBJECT *)pRef;
++      struct NLDR_OBJECT *hNldr;
++      struct RMM_TargetObj *rmm;
++      u16 memPhaseBit = MAXFLAGS;
++      u16 segid = 0;
++      u16 i;
++      u16 memType;
++      u32 nWords;
++      struct RMM_Addr *pRmmAddr = (struct RMM_Addr *)dspAddr;
++      bool fReq = false;
++      DSP_STATUS status = DSP_EMEMORY;        /* Set to fail */
++      DBC_Require(MEM_IsValidHandle(hNode, NLDR_NODESIGNATURE));
++      DBC_Require(space == DBLL_CODE || space == DBLL_DATA ||
++                 space == DBLL_BSS);
++      hNldr = hNode->pNldr;
++      rmm = hNldr->rmm;
++      /* Convert size to DSP words */
++      nWords = (size + hNldr->usDSPWordSize - 1) / hNldr->usDSPWordSize;
++      /* Modify memory 'align' to account for DSP cache line size */
++      align = findLcm(GEM_CACHE_LINE_SIZE, align);
++      GT_1trace(NLDR_debugMask, GT_7CLASS,
++               "RemoteAlloc: memory align to 0x%x \n", align);
++      if (segmentId != -1) {
++              pRmmAddr->segid = segmentId;
++              segid = segmentId;
++              fReq = req;
++      } else {
++              switch (hNode->phase) {
++              case NLDR_CREATE:
++                      memPhaseBit = CREATEDATAFLAGBIT;
++                      break;
++              case NLDR_DELETE:
++                      memPhaseBit = DELETEDATAFLAGBIT;
++                      break;
++              case NLDR_EXECUTE:
++                      memPhaseBit = EXECUTEDATAFLAGBIT;
++                      break;
++              default:
++                      DBC_Assert(false);
++                      break;
++              }
++              if (space == DBLL_CODE)
++                      memPhaseBit++;
++
++              if (memPhaseBit < MAXFLAGS)
++                      segid = hNode->segId[memPhaseBit];
++
++              /* Determine if there is a memory loading requirement */
++              if ((hNode->codeDataFlagMask >> memPhaseBit) & 0x1)
++                      fReq = true;
++
++      }
++      memType = (space == DBLL_CODE) ? DYNM_CODE : DYNM_DATA;
++
++      /* Find an appropriate segment based on space */
++      if (segid == NULLID) {
++              /* No memory requirements of preferences */
++              DBC_Assert(!fReq);
++              goto func_cont;
++      }
++      if (segid <= MAXSEGID) {
++              DBC_Assert(segid < hNldr->nSegs);
++              /* Attempt to allocate from segid first. */
++              pRmmAddr->segid = segid;
++              status = RMM_alloc(rmm, segid, nWords, align, dspAddr, false);
++              if (DSP_FAILED(status)) {
++                      GT_1trace(NLDR_debugMask, GT_6CLASS,
++                               "RemoteAlloc:Unable allocate "
++                               "from segment %d.\n", segid);
++              }
++      } else {
++              /* segid > MAXSEGID ==> Internal or external memory */
++              DBC_Assert(segid == MEMINTERNALID || segid == MEMEXTERNALID);
++               /*  Check for any internal or external memory segment,
++                *  depending on segid.*/
++              memType |= segid == MEMINTERNALID ?
++                               DYNM_INTERNAL : DYNM_EXTERNAL;
++              for (i = 0; i < hNldr->nSegs; i++) {
++                      if ((hNldr->segTable[i] & memType) != memType)
++                              continue;
++
++                      status = RMM_alloc(rmm, i, nWords, align, dspAddr,
++                                         false);
++                      if (DSP_SUCCEEDED(status)) {
++                              /* Save segid for freeing later */
++                              pRmmAddr->segid = i;
++                              break;
++                      }
++              }
++      }
++func_cont:
++      /* Haven't found memory yet, attempt to find any segment that works */
++      if (status == DSP_EMEMORY && !fReq) {
++              GT_0trace(NLDR_debugMask, GT_6CLASS,
++                       "RemoteAlloc: Preferred segment "
++                       "unavailable, trying another segment.\n");
++              for (i = 0; i < hNldr->nSegs; i++) {
++                      /* All bits of memType must be set */
++                      if ((hNldr->segTable[i] & memType) != memType)
++                              continue;
++
++                      status = RMM_alloc(rmm, i, nWords, align, dspAddr,
++                                        false);
++                      if (DSP_SUCCEEDED(status)) {
++                              /* Save segid */
++                              pRmmAddr->segid = i;
++                              break;
++                      }
++              }
++      }
++
++      return status;
++}
++
++static DSP_STATUS RemoteFree(void **pRef, u16 space, u32 dspAddr,
++                              u32 size, bool reserve)
++{
++      struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)pRef;
++      struct RMM_TargetObj *rmm;
++      u32 nWords;
++      DSP_STATUS status = DSP_EMEMORY;        /* Set to fail */
++
++      DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++
++      rmm = hNldr->rmm;
++
++      /* Convert size to DSP words */
++      nWords = (size + hNldr->usDSPWordSize - 1) / hNldr->usDSPWordSize;
++
++      if (RMM_free(rmm, space, dspAddr, nWords, reserve))
++              status = DSP_SOK;
++
++      return status;
++}
++
++/*
++ *  ======== UnloadLib ========
++ */
++static void UnloadLib(struct NLDR_NODEOBJECT *hNldrNode, struct LibNode *root)
++{
++      struct DBLL_Attrs newAttrs;
++      struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++      u16 i;
++
++      DBC_Assert(root != NULL);
++
++      /* Unload dependent libraries */
++      for (i = 0; i < root->nDepLibs; i++)
++              UnloadLib(hNldrNode, &root->pDepLibs[i]);
++
++      root->nDepLibs = 0;
++
++      newAttrs = hNldr->dbllAttrs;
++      newAttrs.rmmHandle = hNldr->rmm;
++      newAttrs.wHandle = hNldrNode->pPrivRef;
++      newAttrs.baseImage = false;
++      newAttrs.symArg = root;
++
++      if (root->lib) {
++              /* Unload the root library */
++              hNldr->dbllFxns.unloadFxn(root->lib, &newAttrs);
++              hNldr->dbllFxns.closeFxn(root->lib);
++      }
++
++      /* Free dependent library list */
++      if (root->pDepLibs) {
++              MEM_Free(root->pDepLibs);
++              root->pDepLibs = NULL;
++      }
++}
++
++/*
++ *  ======== UnloadOvly ========
++ */
++static void UnloadOvly(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
++{
++      struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++      struct OvlyNode *pONode = NULL;
++      struct OvlySect *pPhaseSects = NULL;
++      struct OvlySect *pOtherSects = NULL;
++      u16 i;
++      u16 nAlloc = 0;
++      u16 nOtherAlloc = 0;
++      u16 *pRefCount = NULL;
++      u16 *pOtherRef = NULL;
++      DSP_STATUS status = DSP_SOK;
++
++      /* Find the node in the table */
++      for (i = 0; i < hNldr->nOvlyNodes; i++) {
++              if (IsEqualUUID(hNldrNode->uuid, hNldr->ovlyTable[i].uuid)) {
++                      /* Found it */
++                      pONode = &(hNldr->ovlyTable[i]);
++                      break;
++              }
++      }
++
++      DBC_Assert(i < hNldr->nOvlyNodes);
++      switch (phase) {
++      case NLDR_CREATE:
++              pRefCount = &(pONode->createRef);
++              pPhaseSects = pONode->pCreateSects;
++              nAlloc = pONode->nCreateSects;
++              break;
++      case NLDR_EXECUTE:
++              pRefCount = &(pONode->executeRef);
++              pPhaseSects = pONode->pExecuteSects;
++              nAlloc = pONode->nExecuteSects;
++              break;
++      case NLDR_DELETE:
++              pRefCount = &(pONode->deleteRef);
++              pOtherRef = &(pONode->otherRef);
++              pPhaseSects = pONode->pDeleteSects;
++              /* 'Other' overlay sections are unloaded in the delete phase */
++              pOtherSects = pONode->pOtherSects;
++              nAlloc = pONode->nDeleteSects;
++              nOtherAlloc = pONode->nOtherSects;
++              break;
++      default:
++              DBC_Assert(false);
++              break;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              DBC_Assert(pRefCount && (*pRefCount > 0));
++               if (pRefCount && (*pRefCount > 0)) {
++                      *pRefCount -= 1;
++                      if (pOtherRef) {
++                              DBC_Assert(*pOtherRef > 0);
++                              *pOtherRef -= 1;
++                      }
++              }
++      }
++      if (pRefCount && (*pRefCount == 0)) {
++              /* 'Deallocate' memory */
++              FreeSects(hNldr, pPhaseSects, nAlloc);
++      }
++      if (pOtherRef && *pOtherRef == 0)
++              FreeSects(hNldr, pOtherSects, nOtherAlloc);
++
++}
++
++/*
++ *  ======== findInPersistentLibArray ========
++ */
++static bool findInPersistentLibArray(struct NLDR_NODEOBJECT *hNldrNode,
++                                  struct DBLL_LibraryObj *lib)
++{
++      s32 i = 0;
++
++      for (i = 0; i < hNldrNode->nPersLib; i++) {
++              if (lib == hNldrNode->persLib[i].lib)
++                      return true;
++
++      }
++
++      return false;
++}
++
++/*
++ * ================ Find LCM (Least Common Multiplier ===
++ */
++static u32 findLcm(u32 a, u32 b)
++{
++      u32 retVal;
++
++      retVal = a * b / findGcf(a, b);
++
++      return retVal;
++}
++
++/*
++ * ================ Find GCF (Greatest Common Factor ) ===
++ */
++static u32 findGcf(u32 a, u32 b)
++{
++      u32 c;
++
++      /* Get the GCF (Greatest common factor between the numbers,
++       * using Euclidian Algo */
++      while ((c = (a % b))) {
++              a = b;
++              b = c;
++      }
++      return b;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/node.c b/drivers/dsp/bridge/rmgr/node.c
+new file mode 100644
+index 0000000..178b802
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/node.c
+@@ -0,0 +1,3544 @@
++/*
++ * node.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== node.c ========
++ *
++ *  Description:
++ *      DSP/BIOS Bridge Node Manager.
++ *
++ *  Public Functions:
++ *      NODE_Allocate
++ *      NODE_AllocMsgBuf
++ *      NODE_ChangePriority
++ *      NODE_Connect
++ *      NODE_Create
++ *      NODE_CreateMgr
++ *      NODE_Delete
++ *      NODE_DeleteMgr
++ *      NODE_EnumNodes
++ *      NODE_Exit
++ *      NODE_FreeMsgBuf
++ *      NODE_GetAttr
++ *      NODE_GetChannelId
++ *      NODE_GetMessage
++ *      NODE_GetStrmMgr
++ *      NODE_Init
++ *      NODE_OnExit
++ *      NODE_Pause
++ *      NODE_PutMessage
++ *      NODE_RegisterNotify
++ *      NODE_Run
++ *      NODE_Terminate
++ *
++ *! Revision History:
++ *! =================
++ *! 12-Apr-2004 hp  Compile IVA only for 24xx
++ *! 09-Feb-2004 vp  Updated to support IVA.
++ *! 07-Apr-2003 map       Eliminated references to old DLDR
++ *! 26-Mar-2003 vp  Commented the call to DSP deep sleep in Node_Delete
++ *!               function.
++ *! 18-Feb-2003 vp  Code review updates.
++ *! 06-Feb-2003 kc      Fixed FreeStream to release streams correctly.
++ *! 23-Jan-2003 map     Removed call to DISP_DoCinit within Write()
++ *! 03-Jan-2003 map     Only unload code after phase has executed if
++ *!                overlay or split dynload phases
++ *! 18-Oct-2002 vp  Ported to Linux platform.
++ *! 06-Nov-2002 map     Fixed NODE_Run on NODE_PAUSED bug
++ *! 12-Oct-2002 map     Fixed DeleteNode bug in NODE_Create
++ *! 11-Sep-2002 rr      DeleteNode frees the memory for strmConnect and dcd obj
++ *! 29-Aug-2002 map     Modified Ovly and Write to use ARM-side copy
++ *! 22-May-2002 sg      Changed use of cbData for PWR calls.
++ *! 17-May-2002 jeh     Removed LoadLoaderFxns(). Get address of RMS_cinit()
++ *!                function. Call DISP_DoCinit() from Write(), if .cinit.
++ *! 13-May-2002 sg      Added timeout to wake/sleep calls.
++ *! 02-May-2002 sg      Added wake/sleep of DSP to support "nap" mode.
++ *! 18-Apr-2002 jeh     Use dynamic loader if compile flag is set.
++ *! 13-Feb-2002 jeh     Get uSysStackSize from DSP_NDBPROPS.
++ *! 07-Jan-2002 ag      STRMMODE_ZEROCOPY(shared memory buffer swap) enabled.
++ *! 17-Dec-2001 ag      STRMMODE_RDMA(DDMA) enabled.
++ *! 12-Dec-2001 ag      Check for valid stream mode in NODE_Connect().
++ *! 04-Dec-2001 jeh     Check for node sufficiently connected in NODE_Create().
++ *! 15-Nov-2001 jeh     Removed DBC_Require(pNode->hXlator != NULL) from
++ *!                NODE_AllocMsgBuf(), and check node type != NODE_DEVICE.
++ *! 11-Sep-2001 ag      Zero-copy messaging support.
++ *! 28-Aug-2001 jeh     Overlay/dynamic loader infrastructure added. Removed
++ *!                NODE_GetDispatcher, excess node states.
++ *! 07-Aug-2001 jeh     Removed critical section for dispatcher.
++ *! 26-Jul-2001 jeh     Get ZL dll name through CFG.
++ *! 05-Jun-2001 jeh     Assume DSP_STRMATTRS.uBufsize in GPP bytes.
++ *! 11-May-2001 jeh     Some code review cleanup.
++ *! 13-Feb-2001 kc:     DSP/BIOS Bridge name updates.
++ *! 15-Dec-2000 sg      Convert IALG_Fxn address from byte addr to word addr.
++ *! 04-Dec-2000 jeh     Call MSG Get and Put functions.
++ *! 04-Dec-2000 ag      Added SM support for node messaging.
++ *! 10-Nov-2000 rr:     NODE_MIN/MAX Priority is defined in dspdefs.h.
++ *! 27-Oct-2000 jeh     Added NODE_AllocMsgBuf(), NODE_FreeMsgBuf().
++ *! 11-Oct-2000 jeh     Changed NODE_EnumNodeInfo to NODE_EnumNodes. Added
++ *!                NODE_CloseOrphans(). Remove NODE_RegisterNotifyAllNodes
++ *! 19-Jun-2000 jeh     Created.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/strm.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/ntfy.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/cmm.h>
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/msg.h>
++
++/*  ----------------------------------- Resource Manager */
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/disp.h>
++#include <dspbridge/rms_sh.h>
++
++/*  ----------------------------------- Link Driver */
++#include <dspbridge/wmd.h>
++#include <dspbridge/wmdioctl.h>
++
++/*  ----------------------------------- Others */
++#include <dspbridge/gb.h>
++#ifdef DEBUG
++#include <dspbridge/uuidutil.h>
++#include <dspbridge/dbg.h>
++#endif
++
++/*  ----------------------------------- This */
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/node.h>
++
++/* Static/Dynamic Loader includes */
++#include <dspbridge/dbll.h>
++#include <dspbridge/nldr.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/drv.h>
++#include <dspbridge/drvdefs.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++
++#define NODE_SIGNATURE      0x45444f4e        /* "EDON" */
++#define NODEMGR_SIGNATURE   0x52474d4e        /* "RGMN" */
++
++#define HOSTPREFIX      "/host"
++#define PIPEPREFIX      "/dbpipe"
++
++#define MaxInputs(h)  ((h)->dcdProps.objData.nodeObj.ndbProps.uNumInputStreams)
++#define MaxOutputs(h) ((h)->dcdProps.objData.nodeObj.ndbProps.uNumOutputStreams)
++
++#define NODE_GetPriority(h) ((h)->nPriority)
++#define NODE_SetPriority(hNode, nPriority) ((hNode)->nPriority = nPriority)
++#define NODE_SetState(hNode, state) ((hNode)->nState = state)
++
++#define MAXPIPES      100     /* Max # of /pipe connections (CSL limit) */
++#define MAXDEVSUFFIXLEN 2     /* Max(Log base 10 of MAXPIPES, MAXSTREAMS) */
++
++#define PIPENAMELEN     (sizeof(PIPEPREFIX) + MAXDEVSUFFIXLEN)
++#define HOSTNAMELEN     (sizeof(HOSTPREFIX) + MAXDEVSUFFIXLEN)
++
++#define MAXDEVNAMELEN 32      /* DSP_NDBPROPS.acName size */
++#define CREATEPHASE   1
++#define EXECUTEPHASE  2
++#define DELETEPHASE   3
++
++/* Define default STRM parameters */
++/*
++ *  TBD: Put in header file, make global DSP_STRMATTRS with defaults,
++ *  or make defaults configurable.
++ */
++#define DEFAULTBUFSIZE                32
++#define DEFAULTNBUFS          2
++#define DEFAULTSEGID          0
++#define DEFAULTALIGNMENT      0
++#define DEFAULTTIMEOUT                10000
++
++#define RMSQUERYSERVER                0
++#define RMSCONFIGURESERVER    1
++#define RMSCREATENODE         2
++#define RMSEXECUTENODE                3
++#define RMSDELETENODE         4
++#define RMSCHANGENODEPRIORITY 5
++#define RMSREADMEMORY         6
++#define RMSWRITEMEMORY                7
++#define RMSCOPY                       8
++#define MAXTIMEOUT            2000
++
++#define NUMRMSFXNS            9
++
++#define PWR_TIMEOUT           500     /* default PWR timeout in msec */
++
++#define STACKSEGLABEL "L1DSRAM_HEAP"  /* Label for DSP Stack Segment Address */
++
++/*
++ *  ======== NODE_MGR ========
++ */
++struct NODE_MGR {
++      u32 dwSignature;        /* For object validation */
++      struct DEV_OBJECT *hDevObject;  /* Device object */
++      struct WMD_DRV_INTERFACE *pIntfFxns;    /* Function interface to WMD */
++      struct DCD_MANAGER *hDcdMgr;    /* Proc/Node data manager */
++      struct DISP_OBJECT *hDisp;      /* Node dispatcher */
++      struct LST_LIST *nodeList;      /* List of all allocated nodes */
++      u32 uNumNodes;          /* Number of nodes in nodeList */
++      u32 uNumCreated;        /* Number of nodes *created* on DSP */
++      struct GB_TMap *pipeMap;                /* Pipe connection bit map */
++      struct GB_TMap *pipeDoneMap;    /* Pipes that are half free */
++      struct GB_TMap *chnlMap;                /* Channel allocation bit map */
++      struct GB_TMap *dmaChnlMap;     /* DMA Channel allocation bit map */
++      struct GB_TMap *zChnlMap;       /* Zero-Copy Channel alloc bit map */
++      struct NTFY_OBJECT *hNtfy;      /* Manages registered notifications */
++      struct SYNC_CSOBJECT *hSync;    /* For critical sections */
++      u32 ulFxnAddrs[NUMRMSFXNS];     /* RMS function addresses */
++      struct MSG_MGR *hMsg;
++
++      /* Processor properties needed by Node Dispatcher */
++      u32 ulNumChnls; /* Total number of channels */
++      u32 ulChnlOffset;       /* Offset of chnl ids rsvd for RMS */
++      u32 ulChnlBufSize;      /* Buffer size for data to RMS */
++      DSP_PROCFAMILY procFamily;      /* eg, 5000 */
++      DSP_PROCTYPE procType;  /* eg, 5510 */
++      u32 uDSPWordSize;       /* Size of DSP word on host bytes */
++      u32 uDSPDataMauSize;    /* Size of DSP data MAU */
++      u32 uDSPMauSize;        /* Size of MAU */
++      s32 nMinPri;            /* Minimum runtime priority for node */
++      s32 nMaxPri;            /* Maximum runtime priority for node */
++
++      struct STRM_MGR *hStrmMgr;      /* STRM manager */
++
++      /* Loader properties */
++      struct NLDR_OBJECT *hNldr;      /* Handle to loader */
++      struct NLDR_FXNS nldrFxns;      /* Handle to loader functions */
++      bool fLoaderInit;       /* Loader Init function succeeded? */
++};
++
++/*
++ *  ======== CONNECTTYPE ========
++ */
++enum CONNECTTYPE {
++      NOTCONNECTED = 0,
++      NODECONNECT,
++      HOSTCONNECT,
++      DEVICECONNECT,
++} ;
++
++/*
++ *  ======== STREAM ========
++ */
++struct STREAM {
++      enum CONNECTTYPE type;  /* Type of stream connection */
++      u32 devId;              /* pipe or channel id */
++};
++
++/*
++ *  ======== NODE_OBJECT ========
++ */
++struct NODE_OBJECT {
++      struct LST_ELEM listElem;
++      u32 dwSignature;        /* For object validation */
++      struct NODE_MGR *hNodeMgr;      /* The manager of this node */
++      struct PROC_OBJECT *hProcessor; /* Back pointer to processor */
++      struct DSP_UUID nodeId; /* Node's ID */
++      s32 nPriority;          /* Node's current priority */
++      u32 uTimeout;           /* Timeout for blocking NODE calls */
++      u32 uHeapSize;          /* Heap Size */
++      u32 uDSPHeapVirtAddr;   /* Heap Size */
++      u32 uGPPHeapVirtAddr;   /* Heap Size */
++      enum NODE_TYPE nType;   /* Type of node: message, task, etc */
++      enum NODE_STATE nState; /* NODE_ALLOCATED, NODE_CREATED, ... */
++      u32 uNumInputs; /* Current number of inputs */
++      u32 uNumOutputs;        /* Current number of outputs */
++      u32 uMaxInputIndex;     /* Current max input stream index */
++      u32 uMaxOutputIndex;    /* Current max output stream index */
++      struct STREAM *inputs;          /* Node's input streams */
++      struct STREAM *outputs; /* Node's output streams */
++      struct NODE_CREATEARGS createArgs;  /* Args for node create function */
++      NODE_ENV nodeEnv;       /* Environment returned by RMS */
++      struct DCD_GENERICOBJ dcdProps; /* Node properties from DCD */
++      struct DSP_CBDATA *pArgs;       /* Optional args to pass to node */
++      struct NTFY_OBJECT *hNtfy;      /* Manages registered notifications */
++      char *pstrDevName;      /* device name, if device node */
++      struct SYNC_OBJECT *hSyncDone;  /* Synchronize NODE_Terminate */
++      s32 nExitStatus;        /* execute function return status */
++
++      /* Information needed for NODE_GetAttr() */
++      DSP_HNODE hDeviceOwner; /* If dev node, task that owns it */
++      u32 uNumGPPInputs;      /* Current # of from GPP streams */
++      u32 uNumGPPOutputs;     /* Current # of to GPP streams */
++      /* Current stream connections */
++      struct DSP_STREAMCONNECT *streamConnect;
++
++      /* Message queue */
++      struct MSG_QUEUE *hMsgQueue;
++
++      /* These fields used for SM messaging */
++      struct CMM_XLATOROBJECT *hXlator;   /* Node's SM address translator */
++
++      /* Handle to pass to dynamic loader */
++      struct NLDR_NODEOBJECT *hNldrNode;
++      bool fLoaded;           /* Code is (dynamically) loaded */
++      bool fPhaseSplit;       /* Phases split in many libs or ovly */
++
++} ;
++
++/* Default buffer attributes */
++static struct DSP_BUFFERATTR NODE_DFLTBUFATTRS = {
++      0,                      /* cbStruct */
++      1,                      /* uSegment */
++      0,                      /* uAlignment */
++};
++
++static void DeleteNode(struct NODE_OBJECT *hNode);
++static void DeleteNodeMgr(struct NODE_MGR *hNodeMgr);
++static void FillStreamConnect(struct NODE_OBJECT *hNode1,
++                           struct NODE_OBJECT *hNode2, u32 uStream1,
++                           u32 uStream2);
++static void FillStreamDef(struct NODE_OBJECT *hNode,
++                      struct NODE_STRMDEF *pstrmDef,
++                      struct DSP_STRMATTR *pAttrs);
++static void FreeStream(struct NODE_MGR *hNodeMgr, struct STREAM stream);
++static DSP_STATUS GetFxnAddress(struct NODE_OBJECT *hNode, u32 *pulFxnAddr,
++                              u32 uPhase);
++static DSP_STATUS GetNodeProps(struct DCD_MANAGER *hDcdMgr,
++                             struct NODE_OBJECT *hNode,
++                             CONST struct DSP_UUID *pNodeId,
++                             struct DCD_GENERICOBJ *pdcdProps);
++static DSP_STATUS GetProcProps(struct NODE_MGR *hNodeMgr,
++                            struct DEV_OBJECT *hDevObject);
++static DSP_STATUS GetRMSFxns(struct NODE_MGR *hNodeMgr);
++static u32 Ovly(void *pPrivRef, u32 ulDspRunAddr, u32 ulDspLoadAddr,
++                      u32 ulNumBytes, u32 nMemSpace);
++static u32 Write(void *pPrivRef, u32 ulDspAddr, void *pBuf,
++                      u32 ulNumBytes, u32 nMemSpace);
++
++#if GT_TRACE
++static struct GT_Mask NODE_debugMask = { NULL, NULL };  /* GT trace variable */
++#endif
++
++#ifdef DSP_DMM_DEBUG
++extern u32 DMM_MemMapDump(struct DMM_OBJECT *hDmmMgr);
++#endif
++
++static u32 cRefs;             /* module reference count */
++
++/* Dynamic loader functions. */
++static struct NLDR_FXNS nldrFxns = {
++      NLDR_Allocate,
++      NLDR_Create,
++      NLDR_Delete,
++      NLDR_Exit,
++      NLDR_Free,
++      NLDR_GetFxnAddr,
++      NLDR_Init,
++      NLDR_Load,
++      NLDR_Unload,
++};
++
++enum NODE_STATE NODE_GetState(HANDLE hNode)
++{
++       struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++       if (!MEM_IsValidHandle(pNode, NODE_SIGNATURE)) {
++               GT_1trace(NODE_debugMask, GT_5CLASS,
++                "NODE_GetState:hNode 0x%x\n", pNode);
++               return  -1;
++       } else
++               return pNode->nState;
++
++}
++
++/*
++ *  ======== NODE_Allocate ========
++ *  Purpose:
++ *      Allocate GPP resources to manage a node on the DSP.
++ */
++DSP_STATUS NODE_Allocate(struct PROC_OBJECT *hProcessor,
++                      IN CONST struct DSP_UUID *pNodeId,
++                      OPTIONAL IN CONST struct DSP_CBDATA *pArgs,
++                      OPTIONAL IN CONST struct DSP_NODEATTRIN *pAttrIn,
++                      OUT struct NODE_OBJECT **phNode)
++{
++      struct NODE_MGR *hNodeMgr;
++      struct DEV_OBJECT *hDevObject;
++      struct NODE_OBJECT *pNode = NULL;
++      enum NODE_TYPE nodeType = NODE_TASK;
++      struct NODE_MSGARGS *pmsgArgs;
++      struct NODE_TASKARGS *ptaskArgs;
++      u32 uNumStreams;
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      DSP_STATUS status = DSP_SOK;
++      struct CMM_OBJECT *hCmmMgr = NULL; /* Shared memory manager hndl */
++      u32 procId;
++      char *label;
++      u32 pulValue;
++      u32 dynextBase;
++      u32 offSet = 0;
++      u32 ulStackSegAddr, ulStackSegVal;
++      u32 ulGppMemBase;
++      struct CFG_HOSTRES hostRes;
++      u32 pMappedAddr = 0;
++      u32 mapAttrs = 0x0;
++      struct DSP_PROCESSORSTATE procStatus;
++#ifdef DSP_DMM_DEBUG
++      struct DMM_OBJECT *hDmmMgr;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++#endif
++
++#ifndef RES_CLEANUP_DISABLE
++      HANDLE       hDrvObject;
++      HANDLE       nodeRes;
++       u32                  hProcess;
++      struct PROCESS_CONTEXT   *pPctxt = NULL;
++      DSP_STATUS res_status = DSP_SOK;
++#endif
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(hProcessor != NULL);
++      DBC_Require(phNode != NULL);
++      DBC_Require(pNodeId != NULL);
++
++      GT_5trace(NODE_debugMask, GT_ENTER, "NODE_Allocate: \thProcessor: "
++              "0x%x\tpNodeId: 0x%x\tpArgs: 0x%x\tpAttrIn: "
++              "0x%x\tphNode: 0x%x\n", hProcessor, pNodeId, pArgs, pAttrIn,
++              phNode);
++
++      *phNode = NULL;
++
++      status = PROC_GetProcessorId(hProcessor, &procId);
++
++      status = PROC_GetDevObject(hProcessor, &hDevObject);
++      if (DSP_SUCCEEDED(status)) {
++              status = DEV_GetNodeManager(hDevObject, &hNodeMgr);
++              if (hNodeMgr == NULL)
++                      status = DSP_EFAIL;
++
++      }
++      if (procId != DSP_UNIT)
++              goto func_cont;
++
++      if (DSP_FAILED(status))
++              goto func_cont;
++
++      status = PROC_GetState(hProcessor, &procStatus,
++                      sizeof(struct DSP_PROCESSORSTATE));
++      if (DSP_FAILED(status))
++              goto func_end;
++      /* If processor is in error state then don't attempt
++          to send the message */
++      if (procStatus.iState == PROC_ERROR) {
++              GT_1trace(NODE_debugMask, GT_5CLASS,
++                      "NODE_Allocate: proc Status 0x%x\n",
++                      procStatus.iState);
++              status = DSP_EFAIL;
++              goto func_end;
++      }
++
++      /* Assuming that 0 is not a valid function address */
++      if (hNodeMgr->ulFxnAddrs[0] == 0) {
++              /* No RMS on target - we currently can't handle this */
++              GT_0trace(NODE_debugMask, GT_5CLASS, "No RMS functions in base "
++                       "image. Node allocation fails.\n");
++              status = DSP_EFAIL;
++      } else {
++              /* Validate pAttrIn fields, if non-NULL */
++              if (pAttrIn) {
++                      /* Check if pAttrIn->iPriority is within range */
++                      if (pAttrIn->iPriority < hNodeMgr->nMinPri ||
++                         pAttrIn->iPriority > hNodeMgr->nMaxPri)
++                              status = DSP_ERANGE;
++              }
++      }
++func_cont:
++      /* Allocate node object and fill in */
++      if (DSP_FAILED(status))
++              goto func_cont2;
++
++      MEM_AllocObject(pNode, struct NODE_OBJECT, NODE_SIGNATURE);
++      if (pNode == NULL) {
++              status = DSP_EMEMORY;
++              goto func_cont1;
++      }
++      pNode->hNodeMgr = hNodeMgr;
++      /* This critical section protects GetNodeProps */
++      status = SYNC_EnterCS(hNodeMgr->hSync);
++      if (procId != DSP_UNIT)
++              goto func_cont3;
++
++      /* Get DSP_NDBPROPS from node database */
++      status = GetNodeProps(hNodeMgr->hDcdMgr, pNode, pNodeId,
++                           &(pNode->dcdProps));
++      if (DSP_FAILED(status))
++              goto func_cont3;
++
++      pNode->nodeId = *pNodeId;
++      pNode->hProcessor = hProcessor;
++      pNode->nType = pNode->dcdProps.objData.nodeObj.ndbProps.uNodeType;
++      pNode->uTimeout = pNode->dcdProps.objData.nodeObj.ndbProps.uTimeout;
++      pNode->nPriority = pNode->dcdProps.objData.nodeObj.ndbProps.iPriority;
++
++      /* Currently only C64 DSP builds support Node Dynamic * heaps */
++      /* Allocate memory for node heap */
++      pNode->createArgs.asa.taskArgs.uHeapSize = 0;
++      pNode->createArgs.asa.taskArgs.uDSPHeapAddr = 0;
++      pNode->createArgs.asa.taskArgs.uDSPHeapResAddr = 0;
++      pNode->createArgs.asa.taskArgs.uGPPHeapAddr = 0;
++      if (!pAttrIn)
++              goto func_cont3;
++
++      /* Check if we have a user allocated node heap */
++      if (!(pAttrIn->pGPPVirtAddr))
++              goto func_cont3;
++
++      /* check for page aligned Heap size */
++      if (((pAttrIn->uHeapSize) & (PG_SIZE_4K - 1))) {
++              GT_1trace(NODE_debugMask, GT_7CLASS,
++                       "NODE_Allocate: node heap page size"
++                       " not aligned to 4K page, size=0x%x \n",
++                       pAttrIn->uHeapSize);
++              status = DSP_EINVALIDARG;
++      } else {
++              pNode->createArgs.asa.taskArgs.uHeapSize = pAttrIn->uHeapSize;
++              pNode->createArgs.asa.taskArgs.uGPPHeapAddr =
++                                               (u32)pAttrIn->pGPPVirtAddr;
++      }
++      if (DSP_FAILED(status))
++              goto func_cont3;
++
++      status = PROC_ReserveMemory(hProcessor,
++                      pNode->createArgs.asa.taskArgs.uHeapSize + PAGE_SIZE,
++                      (void **)&(pNode->createArgs.asa.taskArgs.
++                              uDSPHeapResAddr));
++      if (DSP_FAILED(status)) {
++              GT_1trace(NODE_debugMask, GT_5CLASS,
++                       "NODE_Allocate:Failed to reserve "
++                       "memory for Heap: 0x%x\n", status);
++      } else {
++              GT_1trace(NODE_debugMask, GT_5CLASS,
++                       "NODE_Allocate: DSPProcessor_Reserve"
++                       " Memory successful: 0x%x\n", status);
++      }
++#ifdef DSP_DMM_DEBUG
++      status = DMM_GetHandle(pProcObject, &hDmmMgr);
++      if (DSP_SUCCEEDED(status))
++              DMM_MemMapDump(hDmmMgr);
++#endif
++      if (DSP_FAILED(status))
++              goto func_cont3;
++
++      mapAttrs |= DSP_MAPLITTLEENDIAN;
++      mapAttrs |= DSP_MAPELEMSIZE32;
++      mapAttrs |= DSP_MAPVIRTUALADDR;
++      status = PROC_Map(hProcessor, (void *)pAttrIn->pGPPVirtAddr,
++                      pNode->createArgs.asa.taskArgs.uHeapSize,
++                      (void *)pNode->createArgs.asa.taskArgs.uDSPHeapResAddr,
++                      (void **)&pMappedAddr, mapAttrs);
++      if (DSP_FAILED(status)) {
++              GT_1trace(NODE_debugMask, GT_5CLASS,
++                       "NODE_Allocate: Failed to map memory"
++                       " for Heap: 0x%x\n", status);
++      } else {
++              pNode->createArgs.asa.taskArgs.uDSPHeapAddr =
++                      (u32) pMappedAddr;
++              GT_1trace(NODE_debugMask, GT_5CLASS,
++                       "NODE_Allocate:DSPProcessor_Map"
++                       " successful: 0x%x\n", status);
++      }
++
++func_cont3:
++      (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_cont1:
++      if (pAttrIn != NULL) {
++              /* Overrides of NBD properties */
++              pNode->uTimeout = pAttrIn->uTimeout;
++              pNode->nPriority = pAttrIn->iPriority;
++      }
++func_cont2:
++      /* Create object to manage notifications */
++      if (DSP_SUCCEEDED(status))
++              status = NTFY_Create(&pNode->hNtfy);
++
++      if (DSP_SUCCEEDED(status)) {
++              nodeType = NODE_GetType(pNode);
++               /*  Allocate DSP_STREAMCONNECT array for device, task, and
++               *  dais socket nodes.  */
++              if (nodeType != NODE_MESSAGE) {
++                      uNumStreams = MaxInputs(pNode) + MaxOutputs(pNode);
++                      pNode->streamConnect = MEM_Calloc(uNumStreams *
++                                             sizeof(struct DSP_STREAMCONNECT),
++                                             MEM_PAGED);
++                      if (uNumStreams > 0 && pNode->streamConnect == NULL)
++                              status = DSP_EMEMORY;
++
++              }
++              if (DSP_SUCCEEDED(status) && (nodeType == NODE_TASK ||
++                 nodeType == NODE_DAISSOCKET)) {
++                      /* Allocate arrays for maintainig stream connections */
++                      pNode->inputs =
++                              MEM_Calloc(MaxInputs(pNode) *
++                                      sizeof(struct STREAM), MEM_PAGED);
++                      pNode->outputs =
++                              MEM_Calloc(MaxOutputs(pNode) *
++                                      sizeof(struct STREAM), MEM_PAGED);
++                      ptaskArgs = &(pNode->createArgs.asa.taskArgs);
++                      ptaskArgs->strmInDef =
++                              MEM_Calloc(MaxInputs(pNode) *
++                                      sizeof(struct NODE_STRMDEF),
++                                      MEM_PAGED);
++                      ptaskArgs->strmOutDef =
++                                      MEM_Calloc(MaxOutputs(pNode) *
++                                              sizeof(struct NODE_STRMDEF),
++                                              MEM_PAGED);
++                      if ((MaxInputs(pNode) > 0 && (pNode->inputs == NULL ||
++                         ptaskArgs->strmInDef == NULL)) ||
++                         (MaxOutputs(pNode) > 0 && (pNode->outputs == NULL ||
++                         ptaskArgs->strmOutDef == NULL)))
++                              status = DSP_EMEMORY;
++              }
++      }
++      if (DSP_SUCCEEDED(status) && (nodeType != NODE_DEVICE)) {
++              /* Create an event that will be posted when RMS_EXIT is
++               * received. */
++              status = SYNC_OpenEvent(&pNode->hSyncDone, NULL);
++              if (DSP_SUCCEEDED(status)) {
++                      /*Get the shared mem mgr for this nodes dev object */
++                      status = CMM_GetHandle(hProcessor, &hCmmMgr);
++                      if (DSP_FAILED(status)) {
++                              GT_1trace(NODE_debugMask, GT_5CLASS,
++                                       "NODE_Allocate: Failed to"
++                                       " get CMM Mgr handle: 0x%x\n", status);
++                      } else {
++                              /* Allocate a SM addr translator for this node
++                               * w/ deflt attr */
++                              status = CMM_XlatorCreate(&pNode->hXlator,
++                                       hCmmMgr, NULL);
++                              if (DSP_FAILED(status)) {
++                                      GT_1trace(NODE_debugMask, GT_5CLASS,
++                                          "NODE_Allocate: Failed"
++                                          " to create SM translator: 0x%x\n",
++                                          status);
++                              }
++                      }
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      /* Fill in message args */
++                      if ((pArgs != NULL) && (pArgs->cbData > 0)) {
++                              pmsgArgs = &(pNode->createArgs.asa.msgArgs);
++                              pmsgArgs->pData = MEM_Calloc(pArgs->cbData,
++                                                          MEM_PAGED);
++                              if (pmsgArgs->pData == NULL) {
++                                      status = DSP_EMEMORY;
++                              } else {
++                                      pmsgArgs->uArgLength = pArgs->cbData;
++                                      memcpy(pmsgArgs->pData, pArgs->cData,
++                                            pArgs->cbData);
++                              }
++                      }
++              }
++      }
++
++      if (DSP_SUCCEEDED(status) && nodeType != NODE_DEVICE) {
++              /* Create a message queue for this node */
++              pIntfFxns = hNodeMgr->pIntfFxns;
++              status = (*pIntfFxns->pfnMsgCreateQueue)(hNodeMgr->hMsg,
++                              &pNode->hMsgQueue, 0,
++                                  pNode->createArgs.asa.msgArgs.uMaxMessages,
++                                  pNode);
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              /* Create object for dynamic loading */
++
++              status = hNodeMgr->nldrFxns.pfnAllocate(hNodeMgr->hNldr,
++                                           (void *) pNode,
++                                           &pNode->dcdProps.objData.nodeObj,
++                                           &pNode->hNldrNode,
++                                           &pNode->fPhaseSplit);
++              if (DSP_FAILED(status)) {
++                      GT_1trace(NODE_debugMask, GT_5CLASS,
++                               "NODE_Allocate: Failed to "
++                               "allocate NLDR node: 0x%x\n", status);
++              }
++      }
++
++      /* Comapare value read from Node Properties and check if it is same as
++       * STACKSEGLABEL, if yes read the Address of STACKSEGLABEL, calculate
++       * GPP Address, Read the value in that address and override the
++       * uStackSeg value in task args */
++      if (DSP_SUCCEEDED(status) &&
++         (char *)pNode->dcdProps.objData.nodeObj.ndbProps.uStackSegName !=
++         NULL) {
++              label = MEM_Calloc(sizeof(STACKSEGLABEL)+1, MEM_PAGED);
++               strncpy(label, STACKSEGLABEL, sizeof(STACKSEGLABEL)+1);
++
++               if (strcmp((char *)pNode->dcdProps.objData.nodeObj.
++                                   ndbProps.uStackSegName, label) == 0) {
++                      status = hNodeMgr->nldrFxns.pfnGetFxnAddr(pNode->
++                               hNldrNode, "DYNEXT_BEG", &dynextBase);
++                      if (DSP_FAILED(status)) {
++                              GT_1trace(NODE_debugMask, GT_5CLASS,
++                              "NODE_Allocate: Failed to get Address for "
++                              "DYNEXT_BEG: 0x%x\n", status);
++                      }
++
++                      status = hNodeMgr->nldrFxns.pfnGetFxnAddr(pNode->
++                               hNldrNode, "L1DSRAM_HEAP", &pulValue);
++
++                      if (DSP_FAILED(status)) {
++                              GT_1trace(NODE_debugMask, GT_5CLASS,
++                              "NODE_Allocate: Failed to get Address for "
++                              "L1DSRAM_HEAP: 0x%x\n", status);
++                      }
++
++                      status = CFG_GetHostResources((struct CFG_DEVNODE *)
++                               DRV_GetFirstDevExtension(), &hostRes);
++
++                      if (DSP_FAILED(status)) {
++                              GT_1trace(NODE_debugMask, GT_5CLASS,
++                              "NODE_Allocate: Failed to get host resource "
++                              "0x%x\n", status);
++                      }
++
++                      ulGppMemBase = hostRes.dwMemBase[1];
++                      offSet = pulValue - dynextBase;
++                      ulStackSegAddr = ulGppMemBase + offSet;
++                      ulStackSegVal = (u32)*((REG_UWORD32 *)
++                                      ((u32)(ulStackSegAddr)));
++
++                      GT_1trace(NODE_debugMask, GT_5CLASS,
++                               "StackSegVal =0x%x\n", ulStackSegVal);
++                      GT_1trace(NODE_debugMask, GT_5CLASS,
++                               "ulStackSegAddr = 0x%x\n", ulStackSegAddr);
++
++                      pNode->createArgs.asa.taskArgs.uStackSeg =
++                              ulStackSegVal;
++
++              }
++
++              if (label)
++                      MEM_Free(label);
++
++      }
++
++
++      if (DSP_SUCCEEDED(status)) {
++              /* Add the node to the node manager's list of allocated
++               * nodes. */
++              LST_InitElem((struct LST_ELEM *)pNode);
++              NODE_SetState(pNode, NODE_ALLOCATED);
++
++              status = SYNC_EnterCS(hNodeMgr->hSync);
++
++              if (DSP_SUCCEEDED(status)) {
++                      LST_PutTail(hNodeMgr->nodeList,
++                      (struct LST_ELEM *) pNode);
++                      ++(hNodeMgr->uNumNodes);
++              }
++
++              /* Exit critical section */
++              (void) SYNC_LeaveCS(hNodeMgr->hSync);
++
++              /* Preset this to assume phases are split
++               * (for overlay and dll) */
++              pNode->fPhaseSplit = true;
++
++              if (DSP_SUCCEEDED(status))
++                      *phNode = pNode;
++
++
++              /* Notify all clients registered for DSP_NODESTATECHANGE. */
++              PROC_NotifyAllClients(hProcessor, DSP_NODESTATECHANGE);
++      } else {
++              /* Cleanup */
++              if (pNode)
++                      DeleteNode(pNode);
++
++      }
++
++#ifndef RES_CLEANUP_DISABLE
++      if (DSP_SUCCEEDED(status)) {
++               /* Return PID instead of process handle */
++               hProcess = current->pid;
++
++              res_status = CFG_GetObject((u32 *)&hDrvObject,
++                                        REG_DRV_OBJECT);
++              if (DSP_SUCCEEDED(res_status)) {
++                       DRV_GetProcContext(hProcess,
++                                       (struct DRV_OBJECT *)hDrvObject,
++                                       &pPctxt, *phNode, 0);
++                      if (pPctxt == NULL) {
++                              DRV_InsertProcContext(
++                                      (struct DRV_OBJECT *)hDrvObject,
++                                      &pPctxt);
++                              if (pPctxt != NULL) {
++                                      DRV_ProcUpdatestate(pPctxt,
++                                                      PROC_RES_ALLOCATED);
++                                       DRV_ProcSetPID(pPctxt, hProcess);
++                                      pPctxt->hProcessor =
++                                               (DSP_HPROCESSOR)hProcessor;
++                              }
++                      }
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++               /* Return PID instead of process handle */
++               hProcess = current->pid;
++              res_status = CFG_GetObject((u32 *)&hDrvObject,
++                                      REG_DRV_OBJECT);
++              if (DSP_SUCCEEDED(res_status)) {
++                       DRV_GetProcContext(hProcess,
++                                       (struct DRV_OBJECT *)hDrvObject,
++                                       &pPctxt, *phNode, 0);
++                      if (pPctxt != NULL) {
++                              DRV_InsertNodeResElement(*phNode, &nodeRes,
++                                                       pPctxt);
++                              DRV_ProcNodeUpdateHeapStatus(nodeRes, true);
++                              DRV_ProcNodeUpdateStatus(nodeRes, true);
++                      }
++              }
++      }
++#endif
++      DBC_Ensure((DSP_FAILED(status) && (*phNode == NULL)) ||
++                (DSP_SUCCEEDED(status)
++                  && MEM_IsValidHandle((*phNode), NODE_SIGNATURE)));
++func_end:
++      return status;
++}
++
++/*
++ *  ======== NODE_AllocMsgBuf ========
++ *  Purpose:
++ *      Allocates buffer for zero copy messaging.
++ */
++DBAPI NODE_AllocMsgBuf(struct NODE_OBJECT *hNode, u32 uSize,
++                     OPTIONAL IN OUT struct DSP_BUFFERATTR *pAttr,
++                     OUT u8 **pBuffer)
++{
++      struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++      DSP_STATUS status = DSP_SOK;
++      bool bVirtAddr = false;
++      bool bSetInfo;
++      u32 procId;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pBuffer != NULL);
++
++      DBC_Require(uSize > 0);
++
++      GT_4trace(NODE_debugMask, GT_ENTER,
++               "NODE_AllocMsgBuf: hNode: 0x%x\tuSize:"
++               " 0x%x\tpAttr: 0x%x\tpBuffer: %d\n", pNode, uSize, pAttr,
++               pBuffer);
++
++      if (!MEM_IsValidHandle(pNode, NODE_SIGNATURE))
++              status = DSP_EHANDLE;
++
++      if (NODE_GetType(pNode) == NODE_DEVICE)
++              status = DSP_ENODETYPE;
++
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      if (pAttr == NULL)
++              pAttr = &NODE_DFLTBUFATTRS;     /* set defaults */
++
++      status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++      if (procId != DSP_UNIT) {
++              DBC_Assert(NULL);
++              goto func_end;
++      }
++       /*  If segment ID includes MEM_SETVIRTUALSEGID then pBuffer is a
++       *  virt  address, so set this info in this node's translator
++       *  object for  future ref. If MEM_GETVIRTUALSEGID then retrieve
++       *  virtual address  from node's translator.  */
++      if ((pAttr->uSegment & MEM_SETVIRTUALSEGID) ||
++                          (pAttr->uSegment & MEM_GETVIRTUALSEGID)) {
++              bVirtAddr = true;
++              bSetInfo = (pAttr->uSegment & MEM_SETVIRTUALSEGID) ?
++                         true : false;
++              pAttr->uSegment &= ~MEM_MASKVIRTUALSEGID; /* clear mask bits */
++              /* Set/get this node's translators virtual address base/size */
++              status = CMM_XlatorInfo(pNode->hXlator, pBuffer, uSize,
++                                      pAttr->uSegment, bSetInfo);
++              if (DSP_FAILED(status)) {
++                      GT_1trace(NODE_debugMask, GT_7CLASS,
++                               "NODE_AllocMsgBuf "
++                               "failed: 0x%lx\n", status);
++              }
++      }
++      if (DSP_SUCCEEDED(status) && (!bVirtAddr)) {
++              if (pAttr->uSegment != 1) {
++                      /* Node supports single SM segment only. */
++                      status = DSP_EBADSEGID;
++              }
++               /*  Arbitrary SM buffer alignment not supported for host side
++                *  allocs, but guaranteed for the following alignment
++                *  values.  */
++              switch (pAttr->uAlignment) {
++              case 0:
++              case 1:
++              case 2:
++              case 4:
++                      break;
++              default:
++                      /* alignment value not suportted */
++                      status = DSP_EALIGNMENT;
++                      break;
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      /* allocate physical buffer from segId in node's
++                       * translator */
++                      (void)CMM_XlatorAllocBuf(pNode->hXlator, pBuffer,
++                                               uSize);
++                      if (*pBuffer == NULL) {
++                              GT_0trace(NODE_debugMask, GT_7CLASS,
++                                       "NODE_AllocMsgBuf: "
++                                       "ERROR: Out of shared memory.\n");
++                              status = DSP_EMEMORY;
++                      }
++              }
++      }
++func_end:
++      return status;
++}
++
++/*
++ *  ======== NODE_ChangePriority ========
++ *  Purpose:
++ *      Change the priority of a node in the allocated state, or that is
++ *      currently running or paused on the target.
++ */
++DSP_STATUS NODE_ChangePriority(struct NODE_OBJECT *hNode, s32 nPriority)
++{
++      struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++      struct NODE_MGR *hNodeMgr = NULL;
++      enum NODE_TYPE nodeType;
++      enum NODE_STATE state;
++      DSP_STATUS status = DSP_SOK;
++      u32 procId;
++
++      DBC_Require(cRefs > 0);
++
++      GT_2trace(NODE_debugMask, GT_ENTER, "NODE_ChangePriority: "
++               "hNode: 0x%x\tnPriority: %d\n", hNode, nPriority);
++
++      if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++              GT_1trace(NODE_debugMask, GT_7CLASS,
++                       "Invalid NODE Handle: 0x%x\n", hNode);
++              status = DSP_EHANDLE;
++      } else {
++              hNodeMgr = hNode->hNodeMgr;
++              nodeType = NODE_GetType(hNode);
++              if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET)
++                      status = DSP_ENODETYPE;
++              else if (nPriority < hNodeMgr->nMinPri ||
++                              nPriority > hNodeMgr->nMaxPri)
++                              status = DSP_ERANGE;
++      }
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      /* Enter critical section */
++      status = SYNC_EnterCS(hNodeMgr->hSync);
++      if (DSP_FAILED(status))
++              goto func_cont;
++
++      state = NODE_GetState(hNode);
++      if (state == NODE_ALLOCATED || state == NODE_PAUSED) {
++              NODE_SetPriority(hNode, nPriority);
++      } else {
++              if (state != NODE_RUNNING) {
++                      status = DSP_EWRONGSTATE;
++                      goto func_cont;
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      status = PROC_GetProcessorId(pNode->hProcessor,
++                                                  &procId);
++                      if (procId == DSP_UNIT) {
++                              status = DISP_NodeChangePriority(hNodeMgr->
++                                  hDisp, hNode,
++                                  hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY],
++                                  hNode->nodeEnv, nPriority);
++                      }
++                      if (DSP_SUCCEEDED(status))
++                              NODE_SetPriority(hNode, nPriority);
++
++              }
++      }
++func_cont:
++              /* Leave critical section */
++              (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_end:
++      return status;
++}
++
++/*
++ *  ======== NODE_Connect ========
++ *  Purpose:
++ *      Connect two nodes on the DSP, or a node on the DSP to the GPP.
++ */
++DSP_STATUS NODE_Connect(struct NODE_OBJECT *hNode1, u32 uStream1,
++                      struct NODE_OBJECT *hNode2,
++                      u32 uStream2, OPTIONAL IN struct DSP_STRMATTR *pAttrs,
++                      OPTIONAL IN struct DSP_CBDATA *pConnParam)
++{
++      struct NODE_MGR *hNodeMgr;
++      char *pstrDevName = NULL;
++      enum NODE_TYPE node1Type = NODE_TASK;
++      enum NODE_TYPE node2Type = NODE_TASK;
++      struct NODE_STRMDEF *pstrmDef;
++      struct NODE_STRMDEF *pInput = NULL;
++      struct NODE_STRMDEF *pOutput = NULL;
++      struct NODE_OBJECT *hDevNode;
++      struct NODE_OBJECT *hNode;
++      struct STREAM *pStream;
++      GB_BitNum pipeId = GB_NOBITS;
++      GB_BitNum chnlId = GB_NOBITS;
++      CHNL_MODE uMode;
++      u32 dwLength;
++      DSP_STATUS status = DSP_SOK;
++      DBC_Require(cRefs > 0);
++      GT_5trace(NODE_debugMask, GT_ENTER,
++               "NODE_Connect: hNode1: 0x%x\tuStream1:"
++               " %d\thNode2: 0x%x\tuStream2: %d\tpAttrs: 0x%x\n", hNode1,
++               uStream1, hNode2, uStream2, pAttrs);
++      if (DSP_SUCCEEDED(status)) {
++              if ((hNode1 != (struct NODE_OBJECT *) DSP_HGPPNODE &&
++                 !MEM_IsValidHandle(hNode1, NODE_SIGNATURE)) ||
++                 (hNode2 != (struct NODE_OBJECT *) DSP_HGPPNODE &&
++                 !MEM_IsValidHandle(hNode2, NODE_SIGNATURE)))
++                      status = DSP_EHANDLE;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* The two nodes must be on the same processor */
++              if (hNode1 != (struct NODE_OBJECT *)DSP_HGPPNODE &&
++                 hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE &&
++                 hNode1->hNodeMgr != hNode2->hNodeMgr)
++                      status = DSP_EFAIL;
++              /* Cannot connect a node to itself */
++              if (hNode1 == hNode2)
++                      status = DSP_EFAIL;
++
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* NODE_GetType() will return NODE_GPP if hNode =
++               * DSP_HGPPNODE. */
++              node1Type = NODE_GetType(hNode1);
++              node2Type = NODE_GetType(hNode2);
++      /* Check stream indices ranges */
++              if ((node1Type != NODE_GPP && node1Type != NODE_DEVICE &&
++                 uStream1 >= MaxOutputs(hNode1)) || (node2Type != NODE_GPP &&
++                 node2Type != NODE_DEVICE && uStream2 >= MaxInputs(hNode2)))
++                      status = DSP_EVALUE;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /*
++               *  Only the following types of connections are allowed:
++               *      task/dais socket < == > task/dais socket
++               *      task/dais socket < == > device
++               *      task/dais socket < == > GPP
++               *
++               *  ie, no message nodes, and at least one task or dais
++               *  socket node.
++               */
++              if (node1Type == NODE_MESSAGE || node2Type == NODE_MESSAGE ||
++                  (node1Type != NODE_TASK && node1Type != NODE_DAISSOCKET &&
++                   node2Type != NODE_TASK && node2Type != NODE_DAISSOCKET))
++                      status = DSP_EFAIL;
++      }
++      /*
++       * Check stream mode. Default is STRMMODE_PROCCOPY.
++       */
++      if (DSP_SUCCEEDED(status) && pAttrs) {
++              if (pAttrs->lMode != STRMMODE_PROCCOPY)
++                      status = DSP_ESTRMMODE; /* illegal stream mode */
++
++      }
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      if (node1Type != NODE_GPP) {
++              hNodeMgr = hNode1->hNodeMgr;
++      } else {
++              DBC_Assert(hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE);
++              hNodeMgr = hNode2->hNodeMgr;
++      }
++      /* Enter critical section */
++      status = SYNC_EnterCS(hNodeMgr->hSync);
++      if (DSP_FAILED(status))
++              goto func_cont;
++
++      /* Nodes must be in the allocated state */
++      if (node1Type != NODE_GPP && NODE_GetState(hNode1) != NODE_ALLOCATED)
++              status = DSP_EWRONGSTATE;
++
++      if (node2Type != NODE_GPP && NODE_GetState(hNode2) != NODE_ALLOCATED)
++              status = DSP_EWRONGSTATE;
++
++      if (DSP_SUCCEEDED(status)) {
++              /*  Check that stream indices for task and dais socket nodes
++               *  are not already be used. (Device nodes checked later) */
++              if (node1Type == NODE_TASK || node1Type == NODE_DAISSOCKET) {
++                      pOutput = &(hNode1->createArgs.asa.taskArgs.
++                                strmOutDef[uStream1]);
++                      if (pOutput->szDevice != NULL)
++                              status = DSP_EALREADYCONNECTED;
++
++              }
++              if (node2Type == NODE_TASK || node2Type == NODE_DAISSOCKET) {
++                      pInput = &(hNode2->createArgs.asa.taskArgs.
++                               strmInDef[uStream2]);
++                      if (pInput->szDevice != NULL)
++                              status = DSP_EALREADYCONNECTED;
++
++              }
++      }
++      /* Connecting two task nodes? */
++      if (DSP_SUCCEEDED(status) && ((node1Type == NODE_TASK ||
++         node1Type == NODE_DAISSOCKET) && (node2Type == NODE_TASK ||
++         node2Type == NODE_DAISSOCKET))) {
++              /* Find available pipe */
++              pipeId = GB_findandset(hNodeMgr->pipeMap);
++              if (pipeId == GB_NOBITS) {
++                      status = DSP_ENOMORECONNECTIONS;
++              } else {
++                      hNode1->outputs[uStream1].type = NODECONNECT;
++                      hNode2->inputs[uStream2].type = NODECONNECT;
++                      hNode1->outputs[uStream1].devId = pipeId;
++                      hNode2->inputs[uStream2].devId = pipeId;
++                      pOutput->szDevice = MEM_Calloc(PIPENAMELEN + 1,
++                                                    MEM_PAGED);
++                      pInput->szDevice = MEM_Calloc(PIPENAMELEN + 1,
++                                                   MEM_PAGED);
++                      if (pOutput->szDevice == NULL ||
++                         pInput->szDevice == NULL) {
++                              /* Undo the connection */
++                              if (pOutput->szDevice)
++                                      MEM_Free(pOutput->szDevice);
++
++                              if (pInput->szDevice)
++                                      MEM_Free(pInput->szDevice);
++
++                              pOutput->szDevice = NULL;
++                              pInput->szDevice = NULL;
++                              GB_clear(hNodeMgr->pipeMap, pipeId);
++                              status = DSP_EMEMORY;
++                      } else {
++                              /* Copy "/dbpipe<pipId>" name to device names */
++                              sprintf(pOutput->szDevice, "%s%d",
++                                              PIPEPREFIX, pipeId);
++                              strcpy(pInput->szDevice, pOutput->szDevice);
++                      }
++              }
++      }
++      /* Connecting task node to host? */
++      if (DSP_SUCCEEDED(status) && (node1Type == NODE_GPP ||
++         node2Type == NODE_GPP)) {
++              if (node1Type == NODE_GPP) {
++                      uMode = CHNL_MODETODSP;
++              } else {
++                      DBC_Assert(node2Type == NODE_GPP);
++                      uMode = CHNL_MODEFROMDSP;
++              }
++               /*  Reserve a channel id. We need to put the name "/host<id>"
++               *  in the node's createArgs, but the host
++               *  side channel will not be opened until DSPStream_Open is
++               *  called for this node.  */
++              if (pAttrs) {
++                      if (pAttrs->lMode == STRMMODE_RDMA) {
++                              chnlId = GB_findandset(hNodeMgr->dmaChnlMap);
++                              /* dma chans are 2nd transport chnl set
++                               * ids(e.g. 16-31)*/
++                              (chnlId != GB_NOBITS) ?
++                                 (chnlId = chnlId + hNodeMgr->ulNumChnls) :
++                                 chnlId;
++                      } else if (pAttrs->lMode == STRMMODE_ZEROCOPY) {
++                              chnlId = GB_findandset(hNodeMgr->zChnlMap);
++                              /* zero-copy chans are 3nd transport set
++                               * (e.g. 32-47) */
++                              (chnlId != GB_NOBITS) ?  (chnlId = chnlId +
++                                      (2 * hNodeMgr->ulNumChnls)) : chnlId;
++                      } else {        /* must be PROCCOPY */
++                              DBC_Assert(pAttrs->lMode == STRMMODE_PROCCOPY);
++                              chnlId = GB_findandset(hNodeMgr->chnlMap);
++                              /* e.g. 0-15 */
++                      }
++              } else {
++                      /* default to PROCCOPY */
++                      chnlId = GB_findandset(hNodeMgr->chnlMap);
++              }
++              if (chnlId == GB_NOBITS) {
++                      status = DSP_ENOMORECONNECTIONS;
++                      goto func_cont2;
++              }
++              pstrDevName = MEM_Calloc(HOSTNAMELEN + 1, MEM_PAGED);
++              if (pstrDevName != NULL)
++                      goto func_cont2;
++
++              if (pAttrs) {
++                      if (pAttrs->lMode == STRMMODE_RDMA) {
++                              GB_clear(hNodeMgr->dmaChnlMap, chnlId -
++                                       hNodeMgr->ulNumChnls);
++                      } else if (pAttrs->lMode == STRMMODE_ZEROCOPY) {
++                              GB_clear(hNodeMgr->zChnlMap, chnlId -
++                                      (2*hNodeMgr->ulNumChnls));
++                      } else {
++                              DBC_Assert(pAttrs->lMode == STRMMODE_PROCCOPY);
++                              GB_clear(hNodeMgr->chnlMap, chnlId);
++                      }
++              } else {
++                      GB_clear(hNodeMgr->chnlMap, chnlId);
++              }
++              status = DSP_EMEMORY;
++func_cont2:
++              if (DSP_SUCCEEDED(status)) {
++                      if (hNode1 == (struct NODE_OBJECT *) DSP_HGPPNODE) {
++                              hNode2->inputs[uStream2].type = HOSTCONNECT;
++                              hNode2->inputs[uStream2].devId = chnlId;
++                              pInput->szDevice = pstrDevName;
++                      } else {
++                              hNode1->outputs[uStream1].type = HOSTCONNECT;
++                              hNode1->outputs[uStream1].devId = chnlId;
++                              pOutput->szDevice = pstrDevName;
++                      }
++                      sprintf(pstrDevName, "%s%d", HOSTPREFIX, chnlId);
++              }
++      }
++      /* Connecting task node to device node? */
++      if (DSP_SUCCEEDED(status) && ((node1Type == NODE_DEVICE) ||
++         (node2Type == NODE_DEVICE))) {
++              if (node2Type == NODE_DEVICE) {
++                      /* node1 == > device */
++                      hDevNode = hNode2;
++                      hNode = hNode1;
++                      pStream = &(hNode1->outputs[uStream1]);
++                      pstrmDef = pOutput;
++              } else {
++                      /* device == > node2 */
++                      hDevNode = hNode1;
++                      hNode = hNode2;
++                      pStream = &(hNode2->inputs[uStream2]);
++                      pstrmDef = pInput;
++              }
++              /* Set up create args */
++              pStream->type = DEVICECONNECT;
++               dwLength = strlen(hDevNode->pstrDevName);
++              if (pConnParam != NULL) {
++                      pstrmDef->szDevice = MEM_Calloc(dwLength + 1 +
++                                              (u32) pConnParam->cbData,
++                                              MEM_PAGED);
++              } else {
++                      pstrmDef->szDevice = MEM_Calloc(dwLength + 1,
++                                                      MEM_PAGED);
++              }
++              if (pstrmDef->szDevice == NULL) {
++                      status = DSP_EMEMORY;
++              } else {
++                      /* Copy device name */
++                       strncpy(pstrmDef->szDevice, hDevNode->pstrDevName,
++                                 dwLength);
++                      if (pConnParam != NULL) {
++                               strncat(pstrmDef->szDevice,
++                                       (char *)pConnParam->cData,
++                                       (u32)pConnParam->cbData);
++                      }
++                      hDevNode->hDeviceOwner = hNode;
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Fill in create args */
++              if (node1Type == NODE_TASK || node1Type == NODE_DAISSOCKET) {
++                      hNode1->createArgs.asa.taskArgs.uNumOutputs++;
++                      FillStreamDef(hNode1, pOutput, pAttrs);
++              }
++              if (node2Type == NODE_TASK || node2Type == NODE_DAISSOCKET) {
++                      hNode2->createArgs.asa.taskArgs.uNumInputs++;
++                      FillStreamDef(hNode2, pInput, pAttrs);
++              }
++              /* Update hNode1 and hNode2 streamConnect */
++              if (node1Type != NODE_GPP && node1Type != NODE_DEVICE) {
++                      hNode1->uNumOutputs++;
++                      if (uStream1 > hNode1->uMaxOutputIndex)
++                              hNode1->uMaxOutputIndex = uStream1;
++
++              }
++              if (node2Type != NODE_GPP && node2Type != NODE_DEVICE) {
++                      hNode2->uNumInputs++;
++                      if (uStream2 > hNode2->uMaxInputIndex)
++                              hNode2->uMaxInputIndex = uStream2;
++
++              }
++              FillStreamConnect(hNode1, hNode2, uStream1, uStream2);
++      }
++func_cont:
++      /* end of SYNC_EnterCS */
++      /* Exit critical section */
++      (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_end:
++      return status;
++}
++
++/*
++ *  ======== NODE_Create ========
++ *  Purpose:
++ *      Create a node on the DSP by remotely calling the node's create function.
++ */
++DSP_STATUS NODE_Create(struct NODE_OBJECT *hNode)
++{
++      struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++      struct NODE_MGR *hNodeMgr;
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      u32 ulCreateFxn;
++      enum NODE_TYPE nodeType;
++      DSP_STATUS status = DSP_SOK;
++      DSP_STATUS status1 = DSP_SOK;
++      bool bJustWokeDSP = false;
++      struct DSP_CBDATA cbData;
++      u32 procId = 255;
++      struct DSP_PROCESSORSTATE procStatus;
++      struct PROC_OBJECT *hProcessor;
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++      struct dspbridge_platform_data *pdata =
++                              omap_dspbridge_dev->dev.platform_data;
++#endif
++
++      DBC_Require(cRefs > 0);
++      GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Create: hNode: 0x%x\n",
++               hNode);
++      hProcessor = hNode->hProcessor;
++      status = PROC_GetState(hProcessor, &procStatus,
++                                      sizeof(struct DSP_PROCESSORSTATE));
++      if (DSP_FAILED(status))
++              goto func_end;
++      /* If processor is in error state then don't attempt to create
++          new node */
++      if (procStatus.iState == PROC_ERROR) {
++              GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Create:"
++                      "               proc Status 0x%x\n", procStatus.iState);
++              status = DSP_EFAIL;
++              goto func_end;
++      }
++      /* create struct DSP_CBDATA struct for PWR calls */
++      cbData.cbData = PWR_TIMEOUT;
++      nodeType = NODE_GetType(hNode);
++      hNodeMgr = hNode->hNodeMgr;
++      pIntfFxns = hNodeMgr->pIntfFxns;
++      /* Get access to node dispatcher */
++      status = SYNC_EnterCS(hNodeMgr->hSync);
++      if (DSP_FAILED(status))
++              goto func_cont;
++
++      /* Check node state */
++      if (NODE_GetState(hNode) != NODE_ALLOCATED)
++              status = DSP_EWRONGSTATE;
++
++      if (DSP_SUCCEEDED(status))
++              status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++      if (DSP_FAILED(status))
++              goto func_cont2;
++
++      if (procId != DSP_UNIT)
++              goto func_cont2;
++
++      /* Make sure streams are properly connected */
++      if ((hNode->uNumInputs && hNode->uMaxInputIndex >
++         hNode->uNumInputs - 1) ||
++         (hNode->uNumOutputs && hNode->uMaxOutputIndex >
++         hNode->uNumOutputs - 1))
++              status = DSP_ENOTCONNECTED;
++
++      if (DSP_SUCCEEDED(status)) {
++              /* If node's create function is not loaded, load it */
++              /* Boost the OPP level to max level that DSP can be requested */
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++              if (pdata->cpu_set_freq) {
++                      (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP3]);
++
++                      if (pdata->dsp_get_opp) {
++                              GT_1trace(NODE_debugMask, GT_4CLASS, "opp level"
++                              "after setting to VDD1_OPP3 is %d\n",
++                              (*pdata->dsp_get_opp)());
++                      }
++              }
++#endif
++              status = hNodeMgr->nldrFxns.pfnLoad(hNode->hNldrNode,
++                                                 NLDR_CREATE);
++              /* Get address of node's create function */
++              if (DSP_SUCCEEDED(status)) {
++                      hNode->fLoaded = true;
++                      if (nodeType != NODE_DEVICE) {
++                              status = GetFxnAddress(hNode, &ulCreateFxn,
++                                                      CREATEPHASE);
++                      }
++              } else {
++                      GT_1trace(NODE_debugMask, GT_ENTER,
++                               "NODE_Create: failed to load"
++                               " create code: 0x%x\n", status);
++              }
++              /* Request the lowest OPP level*/
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++              if (pdata->cpu_set_freq) {
++                      (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP1]);
++
++                      if (pdata->dsp_get_opp) {
++                              GT_1trace(NODE_debugMask, GT_4CLASS, "opp level"
++                              "after setting to VDD1_OPP1 is %d\n",
++                              (*pdata->dsp_get_opp)());
++                      }
++              }
++#endif
++              /* Get address of iAlg functions, if socket node */
++              if (DSP_SUCCEEDED(status)) {
++                      if (nodeType == NODE_DAISSOCKET) {
++                              status = hNodeMgr->nldrFxns.pfnGetFxnAddr
++                                      (hNode->hNldrNode, hNode->dcdProps.
++                                      objData.nodeObj.pstrIAlgName,
++                                      &hNode->createArgs.asa.taskArgs.
++                                      ulDaisArg);
++                      }
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              if (nodeType != NODE_DEVICE) {
++                      status = DISP_NodeCreate(hNodeMgr->hDisp, hNode,
++                               hNodeMgr->ulFxnAddrs[RMSCREATENODE],
++                               ulCreateFxn, &(hNode->createArgs),
++                               &(hNode->nodeEnv));
++                      if (DSP_SUCCEEDED(status)) {
++                              /* Set the message queue id to the node env
++                               * pointer */
++                              pIntfFxns = hNodeMgr->pIntfFxns;
++                              (*pIntfFxns->pfnMsgSetQueueId)(hNode->hMsgQueue,
++                              hNode->nodeEnv);
++                      }
++              }
++      }
++      /*  Phase II/Overlays: Create, execute, delete phases  possibly in
++       *  different files/sections. */
++      if (hNode->fLoaded && hNode->fPhaseSplit) {
++              /* If create code was dynamically loaded, we can now unload
++               * it. */
++              status1 = hNodeMgr->nldrFxns.pfnUnload(hNode->hNldrNode,
++                                                    NLDR_CREATE);
++              hNode->fLoaded = false;
++      }
++      if (DSP_FAILED(status1)) {
++              GT_1trace(NODE_debugMask, GT_5CLASS,
++                       "NODE_Create: Failed to unload "
++                       "create code: 0x%x\n", status1);
++      }
++func_cont2:
++      /* Update node state and node manager state */
++      if (DSP_SUCCEEDED(status)) {
++              NODE_SetState(hNode, NODE_CREATED);
++              hNodeMgr->uNumCreated++;
++              goto func_cont;
++      }
++      if (status != DSP_EWRONGSTATE) {
++              /* Put back in NODE_ALLOCATED state if error occurred */
++              NODE_SetState(hNode, NODE_ALLOCATED);
++      }
++      if (procId == DSP_UNIT) {
++              /* If node create failed, see if should sleep DSP now */
++              if (bJustWokeDSP == true) {
++                      /* Check to see if partial create happened on DSP */
++                      if (hNode->nodeEnv == (u32)NULL) {
++                              /* No environment allocated on DSP, re-sleep
++                               * DSP now */
++                              PROC_Ctrl(hNode->hProcessor, WMDIOCTL_DEEPSLEEP,
++                                       &cbData);
++                      } else {
++                              /* Increment count, sleep later when node fully
++                               * deleted */
++                              hNodeMgr->uNumCreated++;
++                      }
++              }
++      }
++func_cont:
++              /* Free access to node dispatcher */
++              (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_end:
++      if (DSP_SUCCEEDED(status)) {
++              PROC_NotifyClients(hNode->hProcessor, DSP_NODESTATECHANGE);
++              NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++      }
++
++      return status;
++}
++
++/*
++ *  ======== NODE_CreateMgr ========
++ *  Purpose:
++ *      Create a NODE Manager object.
++ */
++DSP_STATUS NODE_CreateMgr(OUT struct NODE_MGR **phNodeMgr,
++                       struct DEV_OBJECT *hDevObject)
++{
++      u32 i;
++      struct NODE_MGR *pNodeMgr = NULL;
++      struct DISP_ATTRS dispAttrs;
++      char *szZLFile = "";
++      struct NLDR_ATTRS nldrAttrs;
++      DSP_STATUS status = DSP_SOK;
++      u32 devType;
++      DBC_Require(cRefs > 0);
++      DBC_Require(phNodeMgr != NULL);
++      DBC_Require(hDevObject != NULL);
++      GT_2trace(NODE_debugMask, GT_ENTER, "NODE_CreateMgr: phNodeMgr: 0x%x\t"
++               "hDevObject: 0x%x\n", phNodeMgr, hDevObject);
++      *phNodeMgr = NULL;
++      /* Allocate Node manager object */
++      MEM_AllocObject(pNodeMgr, struct NODE_MGR, NODEMGR_SIGNATURE);
++      if (pNodeMgr) {
++              pNodeMgr->hDevObject = hDevObject;
++              pNodeMgr->nodeList = LST_Create();
++              pNodeMgr->pipeMap = GB_create(MAXPIPES);
++              pNodeMgr->pipeDoneMap = GB_create(MAXPIPES);
++              if (pNodeMgr->nodeList == NULL || pNodeMgr->pipeMap == NULL ||
++                 pNodeMgr->pipeDoneMap == NULL) {
++                      status = DSP_EMEMORY;
++                      GT_0trace(NODE_debugMask, GT_6CLASS,
++                               "NODE_CreateMgr: Memory "
++                               "allocation failed\n");
++              } else {
++                      status = NTFY_Create(&pNodeMgr->hNtfy);
++              }
++              pNodeMgr->uNumCreated = 0;
++      } else {
++              GT_0trace(NODE_debugMask, GT_6CLASS,
++                       "NODE_CreateMgr: Memory allocation failed\n");
++              status = DSP_EMEMORY;
++      }
++      /* get devNodeType */
++      if (DSP_SUCCEEDED(status))
++              status = DEV_GetDevType(hDevObject, &devType);
++
++      /* Create the DCD Manager */
++      if (DSP_SUCCEEDED(status)) {
++              status = DCD_CreateManager(szZLFile, &pNodeMgr->hDcdMgr);
++              if (DSP_SUCCEEDED(status))
++                      status = GetProcProps(pNodeMgr, hDevObject);
++
++      }
++      /* Create NODE Dispatcher */
++      if (DSP_SUCCEEDED(status)) {
++              dispAttrs.ulChnlOffset = pNodeMgr->ulChnlOffset;
++              dispAttrs.ulChnlBufSize = pNodeMgr->ulChnlBufSize;
++              dispAttrs.procFamily = pNodeMgr->procFamily;
++              dispAttrs.procType = pNodeMgr->procType;
++              status = DISP_Create(&pNodeMgr->hDisp, hDevObject, &dispAttrs);
++      }
++      /* Create a STRM Manager */
++      if (DSP_SUCCEEDED(status))
++              status = STRM_Create(&pNodeMgr->hStrmMgr, hDevObject);
++
++      if (DSP_SUCCEEDED(status)) {
++              DEV_GetIntfFxns(hDevObject, &pNodeMgr->pIntfFxns);
++              /* Get MSG queue manager */
++              DEV_GetMsgMgr(hDevObject, &pNodeMgr->hMsg);
++              status = SYNC_InitializeCS(&pNodeMgr->hSync);
++              if (DSP_FAILED(status))
++                      status = DSP_EMEMORY;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              pNodeMgr->chnlMap = GB_create(pNodeMgr->ulNumChnls);
++              /* dma chnl map. ulNumChnls is # per transport */
++              pNodeMgr->dmaChnlMap = GB_create(pNodeMgr->ulNumChnls);
++              pNodeMgr->zChnlMap = GB_create(pNodeMgr->ulNumChnls);
++              if ((pNodeMgr->chnlMap == NULL) ||
++                 (pNodeMgr->dmaChnlMap == NULL) ||
++                 (pNodeMgr->zChnlMap == NULL)) {
++                      status = DSP_EMEMORY;
++              } else {
++                      /* Block out reserved channels */
++                      for (i = 0; i < pNodeMgr->ulChnlOffset; i++)
++                              GB_set(pNodeMgr->chnlMap, i);
++
++                      /* Block out channels reserved for RMS */
++                      GB_set(pNodeMgr->chnlMap, pNodeMgr->ulChnlOffset);
++                      GB_set(pNodeMgr->chnlMap, pNodeMgr->ulChnlOffset + 1);
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* NO RM Server on the IVA */
++              if (devType != IVA_UNIT) {
++                      /* Get addresses of any RMS functions loaded */
++                      status = GetRMSFxns(pNodeMgr);
++                      if (DSP_FAILED(status)) {
++                              GT_1trace(NODE_debugMask, GT_6CLASS,
++                              "NODE_CreateMgr: Failed to"
++                              " get RMS functions: status = 0x%x", status);
++                      }
++              }
++      }
++
++      /* Get loader functions and create loader */
++      if (DSP_SUCCEEDED(status)) {
++              GT_0trace(NODE_debugMask, GT_1CLASS,
++                       "NODE_CreateMgr: using dynamic loader\n");
++              pNodeMgr->nldrFxns = nldrFxns;  /* Dynamic loader functions */
++      }
++      if (DSP_SUCCEEDED(status)) {
++              nldrAttrs.pfnOvly = Ovly;
++              nldrAttrs.pfnWrite = Write;
++              nldrAttrs.usDSPWordSize = pNodeMgr->uDSPWordSize;
++              nldrAttrs.usDSPMauSize = pNodeMgr->uDSPMauSize;
++              pNodeMgr->fLoaderInit = pNodeMgr->nldrFxns.pfnInit();
++              status = pNodeMgr->nldrFxns.pfnCreate(&pNodeMgr->hNldr,
++                                                   hDevObject, &nldrAttrs);
++              if (DSP_FAILED(status)) {
++                      GT_1trace(NODE_debugMask, GT_6CLASS,
++                               "NODE_CreateMgr: Failed to "
++                               "create loader: status = 0x%x\n", status);
++              }
++      }
++      if (DSP_SUCCEEDED(status))
++              *phNodeMgr = pNodeMgr;
++      else
++              DeleteNodeMgr(pNodeMgr);
++
++      DBC_Ensure((DSP_FAILED(status) && (*phNodeMgr == NULL)) ||
++                (DSP_SUCCEEDED(status) &&
++                MEM_IsValidHandle((*phNodeMgr), NODEMGR_SIGNATURE)));
++
++      return status;
++}
++
++/*
++ *  ======== NODE_Delete ========
++ *  Purpose:
++ *      Delete a node on the DSP by remotely calling the node's delete function.
++ *      Loads the node's delete function if necessary. Free GPP side resources
++ *      after node's delete function returns.
++ */
++DSP_STATUS NODE_Delete(struct NODE_OBJECT *hNode)
++{
++      struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++      struct NODE_MGR *hNodeMgr;
++      struct PROC_OBJECT *hProcessor;
++      struct DISP_OBJECT *hDisp;
++      u32 ulDeleteFxn;
++      enum NODE_TYPE nodeType;
++      enum NODE_STATE state;
++      DSP_STATUS status = DSP_SOK;
++      DSP_STATUS status1 = DSP_SOK;
++      struct DSP_CBDATA cbData;
++      u32 procId;
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++
++#ifndef RES_CLEANUP_DISABLE
++       u32                     hProcess;
++      HANDLE          nodeRes;
++      HANDLE          hDrvObject;
++      struct PROCESS_CONTEXT *pCtxt = NULL;
++      DSP_STATUS res_status = DSP_SOK;
++#endif
++      struct DSP_PROCESSORSTATE procStatus;
++      DBC_Require(cRefs > 0);
++      GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Delete: hNode: 0x%x\n",
++                hNode);
++      if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++              status = DSP_EHANDLE;
++              goto func_end;
++      }
++      /* create struct DSP_CBDATA struct for PWR call */
++      cbData.cbData = PWR_TIMEOUT;
++      hNodeMgr = hNode->hNodeMgr;
++      hProcessor = hNode->hProcessor;
++      hDisp = hNodeMgr->hDisp;
++      nodeType = NODE_GetType(hNode);
++      pIntfFxns = hNodeMgr->pIntfFxns;
++      /* Enter critical section */
++      status = SYNC_EnterCS(hNodeMgr->hSync);
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      state = NODE_GetState(hNode);
++       /*  Execute delete phase code for non-device node in all cases
++        *  except when the node was only allocated. Delete phase must be
++        *  executed even if create phase was executed, but failed.
++        *  If the node environment pointer is non-NULL, the delete phase
++        *  code must be  executed.  */
++      if (!(state == NODE_ALLOCATED && hNode->nodeEnv == (u32)NULL) &&
++         nodeType != NODE_DEVICE) {
++              status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++              if (DSP_FAILED(status))
++                      goto func_cont1;
++
++              if (procId == DSP_UNIT || procId == IVA_UNIT) {
++                      /*  If node has terminated, execute phase code will
++                       *  have already been unloaded in NODE_OnExit(). If the
++                       *  node is PAUSED, the execute phase is loaded, and it
++                       *  is now ok to unload it. If the node is running, we
++                       *  will unload the execute phase only after deleting
++                       *  the node.  */
++                      if (state == NODE_PAUSED && hNode->fLoaded &&
++                         hNode->fPhaseSplit) {
++                              /* Ok to unload execute code as long as node
++                               * is not * running */
++                              status1 = hNodeMgr->nldrFxns.pfnUnload(hNode->
++                                        hNldrNode, NLDR_EXECUTE);
++                              hNode->fLoaded = false;
++                              NODE_SetState(hNode, NODE_DONE);
++                      }
++                      /* Load delete phase code if not loaded or if haven't
++                       * * unloaded EXECUTE phase */
++                      if ((!(hNode->fLoaded) || (state == NODE_RUNNING)) &&
++                         hNode->fPhaseSplit) {
++                              status = hNodeMgr->nldrFxns.pfnLoad(hNode->
++                                       hNldrNode, NLDR_DELETE);
++                              if (DSP_SUCCEEDED(status)) {
++                                      hNode->fLoaded = true;
++                              } else {
++                                      GT_1trace(NODE_debugMask, GT_ENTER,
++                                               "NODE_Delete: failed to "
++                                               "load delete code: 0x%x\n",
++                                               status);
++                              }
++                      }
++              }
++func_cont1:
++              if (DSP_SUCCEEDED(status)) {
++                      /* Unblock a thread trying to terminate the node */
++                      (void)SYNC_SetEvent(hNode->hSyncDone);
++                      if (procId == DSP_UNIT) {
++                              /* ulDeleteFxn = address of node's delete
++                               * function */
++                              status = GetFxnAddress(hNode, &ulDeleteFxn,
++                                                    DELETEPHASE);
++                      } else if (procId == IVA_UNIT)
++                              ulDeleteFxn = (u32)hNode->nodeEnv;
++                      if (DSP_SUCCEEDED(status)) {
++                              status = PROC_GetState(hProcessor, &procStatus,
++                                      sizeof(struct DSP_PROCESSORSTATE));
++                              GT_1trace(NODE_debugMask, GT_4CLASS,
++                                               "NODE_Delete: proc Status "
++                                               "0x%x\n", procStatus.iState);
++                              if (procStatus.iState != PROC_ERROR) {
++                                      status = DISP_NodeDelete(hDisp, hNode,
++                                      hNodeMgr->ulFxnAddrs[RMSDELETENODE],
++                                      ulDeleteFxn, hNode->nodeEnv);
++                              } else
++                                      NODE_SetState(hNode, NODE_DONE);
++
++                              /* Unload execute, if not unloaded, and delete
++                               * function */
++                              if (state == NODE_RUNNING &&
++                                 hNode->fPhaseSplit) {
++                                      status1 = hNodeMgr->nldrFxns.pfnUnload(
++                                              hNode->hNldrNode, NLDR_EXECUTE);
++                              }
++                              if (DSP_FAILED(status1)) {
++                                      GT_1trace(NODE_debugMask, GT_ENTER,
++                                                "NODE_Delete: failed to"
++                                                "unload execute code: 0x%x\n",
++                                                status1);
++                              }
++                              status1 = hNodeMgr->nldrFxns.pfnUnload(
++                                        hNode->hNldrNode, NLDR_DELETE);
++                              hNode->fLoaded = false;
++                              if (DSP_FAILED(status1)) {
++                                      GT_1trace(NODE_debugMask, GT_ENTER,
++                                                "NODE_Delete: failed to"
++                                                "unload delete code: 0x%x\n",
++                                                status1);
++                              }
++                      }
++              }
++      }
++      /* Free host side resources even if a failure occurred */
++      /* Remove node from hNodeMgr->nodeList */
++      LST_RemoveElem(hNodeMgr->nodeList, (struct LST_ELEM *) hNode);
++      hNodeMgr->uNumNodes--;
++      /* Decrement count of nodes created on DSP */
++      if ((state != NODE_ALLOCATED) || ((state == NODE_ALLOCATED) &&
++      (hNode->nodeEnv != (u32) NULL)))
++              hNodeMgr->uNumCreated--;
++       /*  Free host-side resources allocated by NODE_Create()
++       *  DeleteNode() fails if SM buffers not freed by client!  */
++#ifndef RES_CLEANUP_DISABLE
++       /* Return PID instead of process handle */
++       hProcess = current->pid;
++      res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++      if (DSP_FAILED(res_status))
++              goto func_cont;
++      DRV_GetProcContext(0, (struct DRV_OBJECT *)hDrvObject,
++                                              &pCtxt, hNode, 0);
++      if (pCtxt == NULL)
++              goto func_cont;
++      if (DRV_GetNodeResElement(hNode, &nodeRes, pCtxt) != DSP_ENOTFOUND) {
++              GT_0trace(NODE_debugMask, GT_5CLASS, "\nNODE_Delete12:\n");
++              DRV_ProcNodeUpdateStatus(nodeRes, false);
++      }
++#endif
++func_cont:
++      GT_0trace(NODE_debugMask, GT_ENTER, "\nNODE_Delete13:\n ");
++      DeleteNode(hNode);
++#ifndef RES_CLEANUP_DISABLE
++      GT_0trace(NODE_debugMask, GT_5CLASS, "\nNODE_Delete2:\n ");
++      if (pCtxt != NULL)
++              DRV_RemoveNodeResElement(nodeRes, (HANDLE)pCtxt);
++#endif
++      GT_0trace(NODE_debugMask, GT_ENTER, "\nNODE_Delete3:\n ");
++      /* Exit critical section */
++      (void)SYNC_LeaveCS(hNodeMgr->hSync);
++      PROC_NotifyClients(hProcessor, DSP_NODESTATECHANGE);
++func_end:
++      return status;
++}
++
++/*
++ *  ======== NODE_DeleteMgr ========
++ *  Purpose:
++ *      Delete the NODE Manager.
++ */
++DSP_STATUS NODE_DeleteMgr(struct NODE_MGR *hNodeMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE));
++
++      GT_1trace(NODE_debugMask, GT_ENTER, "NODE_DeleteMgr: hNodeMgr: 0x%x\n",
++               hNodeMgr);
++      DeleteNodeMgr(hNodeMgr);
++
++      return status;
++}
++
++/*
++ *  ======== NODE_EnumNodes ========
++ *  Purpose:
++ *      Enumerate currently allocated nodes.
++ */
++DSP_STATUS NODE_EnumNodes(struct NODE_MGR *hNodeMgr, IN DSP_HNODE *aNodeTab,
++                       u32 uNodeTabSize, OUT u32 *puNumNodes,
++                       OUT u32 *puAllocated)
++{
++      struct NODE_OBJECT *hNode;
++      u32 i;
++      DSP_STATUS status = DSP_SOK;
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE));
++      DBC_Require(aNodeTab != NULL || uNodeTabSize == 0);
++      DBC_Require(puNumNodes != NULL);
++      DBC_Require(puAllocated != NULL);
++      GT_5trace(NODE_debugMask, GT_ENTER, "NODE_EnumNodes: hNodeMgr: 0x%x\t"
++               "aNodeTab: %d\tuNodeTabSize: 0x%x\tpuNumNodes: 0x%x\t"
++               "puAllocated\n", hNodeMgr, aNodeTab, uNodeTabSize, puNumNodes,
++               puAllocated);
++      /* Enter critical section */
++      status = SYNC_EnterCS(hNodeMgr->hSync);
++      if (DSP_SUCCEEDED(status)) {
++              if (hNodeMgr->uNumNodes > uNodeTabSize) {
++                      *puAllocated = hNodeMgr->uNumNodes;
++                      *puNumNodes = 0;
++                      status = DSP_ESIZE;
++              } else {
++                      hNode = (struct NODE_OBJECT *)LST_First(hNodeMgr->
++                              nodeList);
++                      for (i = 0; i < hNodeMgr->uNumNodes; i++) {
++                              DBC_Assert(MEM_IsValidHandle(hNode,
++                                        NODE_SIGNATURE));
++                              aNodeTab[i] = hNode;
++                              hNode = (struct NODE_OBJECT *)LST_Next
++                                      (hNodeMgr->nodeList,
++                                      (struct LST_ELEM *)hNode);
++                      }
++                      *puAllocated = *puNumNodes = hNodeMgr->uNumNodes;
++              }
++      }
++      /* end of SYNC_EnterCS */
++      /* Exit critical section */
++      (void)SYNC_LeaveCS(hNodeMgr->hSync);
++      return status;
++}
++
++/*
++ *  ======== NODE_Exit ========
++ *  Purpose:
++ *      Discontinue usage of NODE module.
++ */
++void NODE_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      cRefs--;
++
++      GT_1trace(NODE_debugMask, GT_5CLASS,
++               "Entered NODE_Exit, ref count:  0x%x\n", cRefs);
++
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== NODE_FreeMsgBuf ========
++ *  Purpose:
++ *      Frees the message buffer.
++ */
++DSP_STATUS NODE_FreeMsgBuf(struct NODE_OBJECT *hNode, IN u8 *pBuffer,
++                               OPTIONAL struct DSP_BUFFERATTR *pAttr)
++{
++      struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++      DSP_STATUS status = DSP_SOK;
++      u32 procId;
++      DBC_Require(cRefs > 0);
++      DBC_Require(pBuffer != NULL);
++      DBC_Require(pNode != NULL);
++      DBC_Require(pNode->hXlator != NULL);
++      GT_3trace(NODE_debugMask, GT_ENTER, "NODE_FreeMsgBuf: hNode: 0x%x\t"
++               "pBuffer: 0x%x\tpAttr: 0x%x\n", hNode, pBuffer, pAttr);
++      if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++              status = DSP_EHANDLE;
++
++      status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++      if (procId == DSP_UNIT) {
++              if (DSP_SUCCEEDED(status)) {
++                      if (pAttr == NULL) {
++                              /* set defaults */
++                              pAttr = &NODE_DFLTBUFATTRS;
++                      }
++                       /* Node supports single SM segment only */
++                      if (pAttr->uSegment != 1)
++                              status = DSP_EBADSEGID;
++
++                      /* pBuffer is clients Va. */
++                      status = CMM_XlatorFreeBuf(pNode->hXlator, pBuffer);
++                      if (DSP_FAILED(status))
++                              status = DSP_EFAIL;
++                      else
++                              status = DSP_SOK;
++
++              }
++      } else {
++              DBC_Assert(NULL);       /* BUG */
++      }
++      return status;
++}
++
++/*
++ *  ======== NODE_GetAttr ========
++ *  Purpose:
++ *      Copy the current attributes of the specified node into a DSP_NODEATTR
++ *      structure.
++ */
++DSP_STATUS NODE_GetAttr(struct NODE_OBJECT *hNode,
++                      OUT struct DSP_NODEATTR *pAttr, u32 uAttrSize)
++{
++      struct NODE_MGR *hNodeMgr;
++      DSP_STATUS status = DSP_SOK;
++      DBC_Require(cRefs > 0);
++      DBC_Require(pAttr != NULL);
++      DBC_Require(uAttrSize >= sizeof(struct DSP_NODEATTR));
++      GT_3trace(NODE_debugMask, GT_ENTER, "NODE_GetAttr: hNode: "
++               "0x%x\tpAttr: 0x%x \tuAttrSize: 0x%x\n", hNode, pAttr,
++               uAttrSize);
++      if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++              status = DSP_EHANDLE;
++      } else {
++              hNodeMgr = hNode->hNodeMgr;
++               /* Enter hNodeMgr critical section (since we're accessing
++                * data that could be changed by NODE_ChangePriority() and
++                * NODE_Connect().  */
++              status = SYNC_EnterCS(hNodeMgr->hSync);
++              if (DSP_SUCCEEDED(status)) {
++                      pAttr->cbStruct = sizeof(struct DSP_NODEATTR);
++                      /* DSP_NODEATTRIN */
++                      pAttr->inNodeAttrIn.cbStruct =
++                                       sizeof(struct DSP_NODEATTRIN);
++                      pAttr->inNodeAttrIn.iPriority = hNode->nPriority;
++                      pAttr->inNodeAttrIn.uTimeout = hNode->uTimeout;
++                      pAttr->inNodeAttrIn.uHeapSize =
++                              hNode->createArgs.asa.taskArgs.uHeapSize;
++                      pAttr->inNodeAttrIn.pGPPVirtAddr = (void *)
++                              hNode->createArgs.asa.taskArgs.uGPPHeapAddr;
++                      pAttr->uInputs = hNode->uNumGPPInputs;
++                      pAttr->uOutputs = hNode->uNumGPPOutputs;
++                      /* DSP_NODEINFO */
++                      GetNodeInfo(hNode, &(pAttr->iNodeInfo));
++              }
++              /* end of SYNC_EnterCS */
++              /* Exit critical section */
++              (void)SYNC_LeaveCS(hNodeMgr->hSync);
++      }
++      return status;
++}
++
++/*
++ *  ======== NODE_GetChannelId ========
++ *  Purpose:
++ *      Get the channel index reserved for a stream connection between the
++ *      host and a node.
++ */
++DSP_STATUS NODE_GetChannelId(struct NODE_OBJECT *hNode, u32 uDir, u32 uIndex,
++                          OUT u32 *pulId)
++{
++      enum NODE_TYPE nodeType;
++      DSP_STATUS status = DSP_EVALUE;
++      DBC_Require(cRefs > 0);
++      DBC_Require(uDir == DSP_TONODE || uDir == DSP_FROMNODE);
++      DBC_Require(pulId != NULL);
++      GT_4trace(NODE_debugMask, GT_ENTER, "NODE_GetChannelId: hNode: "
++               "0x%x\tuDir: %d\tuIndex: %d\tpulId: 0x%x\n", hNode, uDir,
++               uIndex, pulId);
++      if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++              status = DSP_EHANDLE;
++              return status;
++      }
++      nodeType = NODE_GetType(hNode);
++      if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET) {
++              status = DSP_ENODETYPE;
++              return status;
++      }
++      if (uDir == DSP_TONODE) {
++              if (uIndex < MaxInputs(hNode)) {
++                      if (hNode->inputs[uIndex].type == HOSTCONNECT) {
++                              *pulId = hNode->inputs[uIndex].devId;
++                              status = DSP_SOK;
++                      }
++              }
++      } else {
++              DBC_Assert(uDir == DSP_FROMNODE);
++              if (uIndex < MaxOutputs(hNode)) {
++                      if (hNode->outputs[uIndex].type == HOSTCONNECT) {
++                              *pulId = hNode->outputs[uIndex].devId;
++                              status = DSP_SOK;
++                      }
++              }
++      }
++      return status;
++}
++
++/*
++ *  ======== NODE_GetMessage ========
++ *  Purpose:
++ *      Retrieve a message from a node on the DSP.
++ */
++DSP_STATUS NODE_GetMessage(struct NODE_OBJECT *hNode, OUT struct DSP_MSG *pMsg,
++                        u32 uTimeout)
++{
++      struct NODE_MGR *hNodeMgr;
++      enum NODE_TYPE nodeType;
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      DSP_STATUS status = DSP_SOK;
++      void *pTmpBuf;
++      struct DSP_PROCESSORSTATE procStatus;
++      struct PROC_OBJECT *hProcessor;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pMsg != NULL);
++      GT_3trace(NODE_debugMask, GT_ENTER,
++               "NODE_GetMessage: hNode: 0x%x\tpMsg: "
++               "0x%x\tuTimeout: 0x%x\n", hNode, pMsg, uTimeout);
++      hProcessor = hNode->hProcessor;
++      status = PROC_GetState(hProcessor, &procStatus,
++                                      sizeof(struct DSP_PROCESSORSTATE));
++      if (DSP_FAILED(status))
++              goto func_end;
++      /* If processor is in error state then don't attempt to get the
++          message */
++      if (procStatus.iState == PROC_ERROR) {
++              GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_GetMessage:"
++                      "               proc Status 0x%x\n", procStatus.iState);
++              status = DSP_EFAIL;
++              goto func_end;
++      }
++      if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++              status = DSP_EHANDLE;
++              goto func_end;
++      }
++      hNodeMgr = hNode->hNodeMgr;
++      nodeType = NODE_GetType(hNode);
++      if (nodeType != NODE_MESSAGE && nodeType != NODE_TASK &&
++         nodeType != NODE_DAISSOCKET) {
++              status = DSP_ENODETYPE;
++              goto func_end;
++      }
++       /*  This function will block unless a message is available. Since
++       *  DSPNode_RegisterNotify() allows notification when a message
++       *  is available, the system can be designed so that
++       *  DSPNode_GetMessage() is only called when a message is
++       *  available.  */
++      pIntfFxns = hNodeMgr->pIntfFxns;
++      status = (*pIntfFxns->pfnMsgGet)(hNode->hMsgQueue, pMsg, uTimeout);
++      /* Check if message contains SM descriptor */
++      if (DSP_FAILED(status) ||  !(pMsg->dwCmd & DSP_RMSBUFDESC))
++              goto func_end;
++
++       /* Translate DSP byte addr to GPP Va.  */
++      pTmpBuf = CMM_XlatorTranslate(hNode->hXlator,
++              (void *)(pMsg->dwArg1 * hNode->hNodeMgr->uDSPWordSize),
++              CMM_DSPPA2PA);
++      if (pTmpBuf  != NULL) {
++              /* now convert this GPP Pa to Va */
++              pTmpBuf = CMM_XlatorTranslate(hNode->hXlator, pTmpBuf,
++                                                      CMM_PA2VA);
++              if (pTmpBuf != NULL) {
++                      /* Adjust SM size in msg */
++                      pMsg->dwArg1 = (u32) pTmpBuf;
++                      pMsg->dwArg2 *= hNode->hNodeMgr->uDSPWordSize;
++              } else {
++                      GT_0trace(NODE_debugMask, GT_7CLASS, "NODE_GetMessage: "
++                               "Failed SM translation!\n");
++                      status = DSP_ETRANSLATE;
++              }
++      } else {
++              GT_0trace(NODE_debugMask, GT_7CLASS, "NODE_GetMessage: Failed "
++                       "SM Pa/Pa translation!\n");
++              status = DSP_ETRANSLATE;
++      }
++func_end:
++      return status;
++}
++
++/*
++ *   ======== NODE_GetNldrObj ========
++ */
++DSP_STATUS NODE_GetNldrObj(struct NODE_MGR *hNodeMgr,
++                        struct NLDR_OBJECT **phNldrObj)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct NODE_MGR *pNodeMgr = hNodeMgr;
++      DBC_Require(phNldrObj != NULL);
++      GT_2trace(NODE_debugMask, GT_ENTER,
++               "Entered NODE_GetNldrObj, hNodeMgr: "
++               "0x%x\n\tphNldrObj:  0x%x\n", hNodeMgr, phNldrObj);
++      if (!MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE))
++              status = DSP_EHANDLE;
++      else
++              *phNldrObj = pNodeMgr->hNldr;
++
++      GT_2trace(NODE_debugMask, GT_ENTER,
++               "Exit NODE_GetNldrObj: status 0x%x\n\t"
++               "phNldrObj:  0x%x\n", status, *phNldrObj);
++      DBC_Ensure(DSP_SUCCEEDED(status) || ((phNldrObj != NULL) &&
++                (*phNldrObj == NULL)));
++      return status;
++}
++
++/*
++ *  ======== NODE_GetStrmMgr ========
++ *  Purpose:
++ *      Returns the Stream manager.
++ */
++DSP_STATUS NODE_GetStrmMgr(struct NODE_OBJECT *hNode,
++                        struct STRM_MGR **phStrmMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++
++      if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++              status = DSP_EHANDLE;
++      else
++              *phStrmMgr = hNode->hNodeMgr->hStrmMgr;
++
++      return status;
++}
++
++/*
++ *  ======== NODE_GetLoadType ========
++ */
++enum NLDR_LOADTYPE NODE_GetLoadType(struct NODE_OBJECT *hNode)
++{
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++       if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++               GT_1trace(NODE_debugMask, GT_5CLASS,
++                        "NODE_GetLoadType: Failed. hNode:"
++                         " 0x%x\n", hNode);
++               return -1;
++       } else
++               return hNode->dcdProps.objData.nodeObj.usLoadType;
++}
++
++/*
++ *  ======== NODE_GetTimeout ========
++ *  Purpose:
++ *      Returns the timeout value for this node.
++ */
++u32 NODE_GetTimeout(struct NODE_OBJECT *hNode)
++{
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++       if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++               GT_1trace(NODE_debugMask, GT_5CLASS,
++                        "NODE_GetTimeout: Failed. hNode:"
++                         " 0x%x\n", hNode);
++               return 0;
++       } else
++               return hNode->uTimeout;
++}
++
++/*
++ *  ======== NODE_GetType ========
++ *  Purpose:
++ *      Returns the node type.
++ */
++enum NODE_TYPE NODE_GetType(struct NODE_OBJECT *hNode)
++{
++      enum NODE_TYPE nodeType;
++
++      if (hNode == (struct NODE_OBJECT *) DSP_HGPPNODE)
++              nodeType = NODE_GPP;
++      else {
++                if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++                        nodeType = -1;
++                else
++                        nodeType = hNode->nType;
++      }
++      return nodeType;
++}
++
++/*
++ *  ======== NODE_Init ========
++ *  Purpose:
++ *      Initialize the NODE module.
++ */
++bool NODE_Init(void)
++{
++      bool fRetVal = true;
++
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++              DBC_Assert(!NODE_debugMask.flags);
++              GT_create(&NODE_debugMask, "NO");       /* "NO" for NOde */
++      }
++
++      if (fRetVal)
++              cRefs++;
++
++      GT_1trace(NODE_debugMask, GT_5CLASS, "NODE_Init(), ref count: 0x%x\n",
++               cRefs);
++
++      DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
++      return fRetVal;
++}
++
++/*
++ *  ======== NODE_OnExit ========
++ *  Purpose:
++ *      Gets called when RMS_EXIT is received for a node.
++ */
++void NODE_OnExit(struct NODE_OBJECT *hNode, s32 nStatus)
++{
++      DBC_Assert(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++      /* Set node state to done */
++      NODE_SetState(hNode, NODE_DONE);
++      hNode->nExitStatus = nStatus;
++      if (hNode->fLoaded && hNode->fPhaseSplit) {
++              (void)hNode->hNodeMgr->nldrFxns.pfnUnload(hNode->hNldrNode,
++                                                       NLDR_EXECUTE);
++              hNode->fLoaded = false;
++      }
++      /* Unblock call to NODE_Terminate */
++      (void) SYNC_SetEvent(hNode->hSyncDone);
++      /* Notify clients */
++      PROC_NotifyClients(hNode->hProcessor, DSP_NODESTATECHANGE);
++      NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++}
++
++/*
++ *  ======== NODE_Pause ========
++ *  Purpose:
++ *      Suspend execution of a node currently running on the DSP.
++ */
++DSP_STATUS NODE_Pause(struct NODE_OBJECT *hNode)
++{
++      struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++      enum NODE_TYPE nodeType;
++      enum NODE_STATE state;
++      struct NODE_MGR *hNodeMgr;
++      DSP_STATUS status = DSP_SOK;
++      u32 procId;
++      struct DSP_PROCESSORSTATE procStatus;
++      struct PROC_OBJECT *hProcessor;
++
++      DBC_Require(cRefs > 0);
++
++      GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Pause: hNode: 0x%x\n", hNode);
++
++      if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++              status = DSP_EHANDLE;
++      } else {
++              nodeType = NODE_GetType(hNode);
++              if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET)
++                      status = DSP_ENODETYPE;
++
++      }
++
++      status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++      if (procId == IVA_UNIT)
++              status = DSP_ENOTIMPL;
++
++      if (DSP_SUCCEEDED(status)) {
++              hNodeMgr = hNode->hNodeMgr;
++
++              /* Enter critical section */
++              status = SYNC_EnterCS(hNodeMgr->hSync);
++
++              if (DSP_SUCCEEDED(status)) {
++                      state = NODE_GetState(hNode);
++                      /* Check node state */
++                      if (state != NODE_RUNNING)
++                              status = DSP_EWRONGSTATE;
++
++                      hProcessor = hNode->hProcessor;
++                      status = PROC_GetState(hProcessor, &procStatus,
++                                      sizeof(struct DSP_PROCESSORSTATE));
++                      if (DSP_FAILED(status))
++                              goto func_end;
++                      /* If processor is in error state then don't attempt
++                          to send the message */
++                      if (procStatus.iState == PROC_ERROR) {
++                              GT_1trace(NODE_debugMask, GT_4CLASS,
++                                      "NODE_Pause: proc Status 0x%x\n",
++                                      procStatus.iState);
++                              status = DSP_EFAIL;
++                              goto func_end;
++                      }
++                      if (DSP_SUCCEEDED(status)) {
++                              status = DISP_NodeChangePriority(hNodeMgr->
++                                 hDisp, hNode,
++                                 hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY],
++                                 hNode->nodeEnv, NODE_SUSPENDEDPRI);
++                      }
++
++                      /* Update state */
++                      if (DSP_SUCCEEDED(status)) {
++                              NODE_SetState(hNode, NODE_PAUSED);
++                      } else {
++                              GT_1trace(NODE_debugMask, GT_6CLASS,
++                                       "NODE_Pause: Failed. hNode:"
++                                       " 0x%x\n", hNode);
++                      }
++              }
++              /* End of SYNC_EnterCS */
++              /* Leave critical section */
++              (void)SYNC_LeaveCS(hNodeMgr->hSync);
++              if (DSP_SUCCEEDED(status)) {
++                      PROC_NotifyClients(hNode->hProcessor,
++                                        DSP_NODESTATECHANGE);
++                      NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++              }
++      }
++func_end:
++      return status;
++}
++
++/*
++ *  ======== NODE_PutMessage ========
++ *  Purpose:
++ *      Send a message to a message node, task node, or XDAIS socket node. This
++ *      function will block until the message stream can accommodate the
++ *      message, or a timeout occurs.
++ */
++DSP_STATUS NODE_PutMessage(struct NODE_OBJECT *hNode,
++                        IN CONST struct DSP_MSG *pMsg, u32 uTimeout)
++{
++      struct NODE_MGR *hNodeMgr = NULL;
++      enum NODE_TYPE nodeType;
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      enum NODE_STATE state;
++      DSP_STATUS status = DSP_SOK;
++      void *pTmpBuf;
++      struct DSP_MSG newMsg;
++      struct DSP_PROCESSORSTATE procStatus;
++      struct PROC_OBJECT *hProcessor;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pMsg != NULL);
++      GT_3trace(NODE_debugMask, GT_ENTER,
++               "NODE_PutMessage: hNode: 0x%x\tpMsg: "
++               "0x%x\tuTimeout: 0x%x\n", hNode, pMsg, uTimeout);
++      hProcessor = hNode->hProcessor;
++      status = PROC_GetState(hProcessor, &procStatus,
++                                      sizeof(struct DSP_PROCESSORSTATE));
++      if (DSP_FAILED(status))
++              goto func_end;
++      /* If processor is in bad state then don't attempt sending the
++          message */
++      if (procStatus.iState == PROC_ERROR) {
++              GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_PutMessage:"
++                      "               proc Status 0x%x\n", procStatus.iState);
++              status = DSP_EFAIL;
++              goto func_end;
++      }
++      if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++              status = DSP_EHANDLE;
++      else {
++              hNodeMgr = hNode->hNodeMgr;
++              nodeType = NODE_GetType(hNode);
++              if (nodeType != NODE_MESSAGE && nodeType != NODE_TASK &&
++                  nodeType != NODE_DAISSOCKET)
++                      status = DSP_ENODETYPE;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /*  Check node state. Can't send messages to a node after
++               *  we've sent the RMS_EXIT command. There is still the
++               *  possibility that NODE_Terminate can be called after we've
++               *  checked the state. Could add another SYNC object to
++               *  prevent this (can't use hNodeMgr->hSync, since we don't
++               *  want to block other NODE functions). However, the node may
++               *  still exit on its own, before this message is sent.  */
++              status = SYNC_EnterCS(hNodeMgr->hSync);
++              if (DSP_SUCCEEDED(status)) {
++                      state = NODE_GetState(hNode);
++                      if (state == NODE_TERMINATING || state == NODE_DONE)
++                              status = DSP_EWRONGSTATE;
++
++              }
++              /* end of SYNC_EnterCS */
++              (void)SYNC_LeaveCS(hNodeMgr->hSync);
++      }
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      /* assign pMsg values to new msg  */
++      newMsg = *pMsg;
++      /* Now, check if message contains a SM buffer descriptor */
++      if (pMsg->dwCmd & DSP_RMSBUFDESC) {
++              /* Translate GPP Va to DSP physical buf Ptr. */
++              pTmpBuf = CMM_XlatorTranslate(hNode->hXlator,
++                      (void *)newMsg.dwArg1, CMM_VA2DSPPA);
++              if (pTmpBuf != NULL) {
++                      /* got translation, convert to MAUs in msg */
++                      if (hNode->hNodeMgr->uDSPWordSize != 0) {
++                              newMsg.dwArg1 =
++                                      (u32)pTmpBuf /
++                                      hNode->hNodeMgr->uDSPWordSize;
++                              /* MAUs */
++                              newMsg.dwArg2 /= hNode->hNodeMgr->uDSPWordSize;
++                      } else {
++                              GT_0trace(NODE_debugMask, GT_7CLASS,
++                                       "NODE_PutMessage: "
++                                       "uDSPWordSize is zero!\n");
++                              status = DSP_EFAIL;     /* bad DSPWordSize */
++                      }
++              } else {        /* failed to translate buffer address */
++                      GT_0trace(NODE_debugMask, GT_7CLASS,
++                               "NODE_PutMessage: Failed to"
++                               " translate SM address\n");
++                      status = DSP_ETRANSLATE;
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              pIntfFxns = hNodeMgr->pIntfFxns;
++              status = (*pIntfFxns->pfnMsgPut)(hNode->hMsgQueue,
++                       &newMsg, uTimeout);
++      }
++func_end:
++      return status;
++}
++
++/*
++ *  ======== NODE_RegisterNotify ========
++ *  Purpose:
++ *      Register to be notified on specific events for this node.
++ */
++DSP_STATUS NODE_RegisterNotify(struct NODE_OBJECT *hNode, u32 uEventMask,
++                             u32 uNotifyType,
++                             struct DSP_NOTIFICATION *hNotification)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(hNotification != NULL);
++
++      GT_4trace(NODE_debugMask, GT_ENTER,
++               "NODE_RegisterNotify: hNode: 0x%x\t"
++               "uEventMask: 0x%x\tuNotifyType: 0x%x\thNotification: 0x%x\n",
++               hNode, uEventMask, uNotifyType, hNotification);
++
++      if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++              status = DSP_EHANDLE;
++      } else {
++              /* Check if event mask is a valid node related event */
++              if (uEventMask & ~(DSP_NODESTATECHANGE |
++                 DSP_NODEMESSAGEREADY))
++                      status = DSP_EVALUE;
++
++              /* Check if notify type is valid */
++              if (uNotifyType != DSP_SIGNALEVENT)
++                      status = DSP_EVALUE;
++
++              /* Only one Notification can be registered at a
++               * time - Limitation */
++              if (uEventMask == (DSP_NODESTATECHANGE |
++                 DSP_NODEMESSAGEREADY))
++                      status = DSP_EVALUE;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              if (uEventMask == DSP_NODESTATECHANGE) {
++                      status = NTFY_Register(hNode->hNtfy, hNotification,
++                               uEventMask & DSP_NODESTATECHANGE, uNotifyType);
++              } else {
++                      /* Send Message part of event mask to MSG */
++                      pIntfFxns = hNode->hNodeMgr->pIntfFxns;
++                      status = (*pIntfFxns->pfnMsgRegisterNotify)
++                               (hNode->hMsgQueue,
++                               uEventMask & DSP_NODEMESSAGEREADY, uNotifyType,
++                               hNotification);
++              }
++
++      }
++      return status;
++}
++
++/*
++ *  ======== NODE_Run ========
++ *  Purpose:
++ *      Start execution of a node's execute phase, or resume execution of a node
++ *      that has been suspended (via NODE_NodePause()) on the DSP. Load the
++ *      node's execute function if necessary.
++ */
++DSP_STATUS NODE_Run(struct NODE_OBJECT *hNode)
++{
++      struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++      struct NODE_MGR *hNodeMgr;
++      enum NODE_TYPE nodeType;
++      enum NODE_STATE state;
++      u32 ulExecuteFxn;
++      u32 ulFxnAddr;
++      DSP_STATUS status = DSP_SOK;
++      u32 procId;
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      struct DSP_PROCESSORSTATE procStatus;
++      struct PROC_OBJECT *hProcessor;
++
++      DBC_Require(cRefs > 0);
++      GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Run: hNode: 0x%x\n", hNode);
++      hProcessor = hNode->hProcessor;
++      status = PROC_GetState(hProcessor, &procStatus,
++                                      sizeof(struct DSP_PROCESSORSTATE));
++      if (DSP_FAILED(status))
++              goto func_end;
++      /* If processor is in error state then don't attempt to run the node */
++      if (procStatus.iState == PROC_ERROR) {
++              GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Run:"
++                      "               proc Status 0x%x\n", procStatus.iState);
++              status = DSP_EFAIL;
++              goto func_end;
++      }
++      if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++              status = DSP_EHANDLE;
++      } else {
++              nodeType = NODE_GetType(hNode);
++              if (nodeType == NODE_DEVICE)
++                      status = DSP_ENODETYPE;
++      }
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      hNodeMgr = hNode->hNodeMgr;
++      pIntfFxns = hNodeMgr->pIntfFxns;
++      /* Enter critical section */
++      status = SYNC_EnterCS(hNodeMgr->hSync);
++      if (DSP_FAILED(status))
++              goto func_cont;
++
++      state = NODE_GetState(hNode);
++      if (state != NODE_CREATED && state != NODE_PAUSED)
++              status = DSP_EWRONGSTATE;
++
++      if (DSP_SUCCEEDED(status))
++              status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++      if (DSP_FAILED(status))
++              goto func_cont1;
++
++      if ((procId != DSP_UNIT) && (procId != IVA_UNIT))
++              goto func_cont1;
++
++      if (state == NODE_CREATED) {
++              /* If node's execute function is not loaded, load it */
++              if (!(hNode->fLoaded) && hNode->fPhaseSplit) {
++                      status = hNodeMgr->nldrFxns.pfnLoad(hNode->hNldrNode,
++                              NLDR_EXECUTE);
++                      if (DSP_SUCCEEDED(status)) {
++                              hNode->fLoaded = true;
++                      } else {
++                              GT_1trace(NODE_debugMask, GT_ENTER,
++                                       "NODE_Run: failed to load "
++                                       "execute code:0x%x\n", status);
++                      }
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      /* Get address of node's execute function */
++                      if (procId == IVA_UNIT)
++                              ulExecuteFxn = (u32) hNode->nodeEnv;
++                      else {
++                              status = GetFxnAddress(hNode, &ulExecuteFxn,
++                                       EXECUTEPHASE);
++                      }
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      ulFxnAddr = hNodeMgr->ulFxnAddrs[RMSEXECUTENODE];
++                      status = DISP_NodeRun(hNodeMgr->hDisp, hNode, ulFxnAddr,
++                                           ulExecuteFxn, hNode->nodeEnv);
++              }
++      } else if (state == NODE_PAUSED) {
++              ulFxnAddr = hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY];
++              status = DISP_NodeChangePriority(hNodeMgr->hDisp, hNode,
++                                              ulFxnAddr, hNode->nodeEnv,
++                                              NODE_GetPriority(hNode));
++      } else {
++              /* We should never get here */
++              DBC_Assert(false);
++      }
++func_cont1:
++      /* Update node state. */
++      if (DSP_SUCCEEDED(status))
++              NODE_SetState(hNode, NODE_RUNNING);
++       else /* Set state back to previous value */
++              NODE_SetState(hNode, state);
++      /*End of SYNC_EnterCS */
++      /* Exit critical section */
++func_cont:
++      (void)SYNC_LeaveCS(hNodeMgr->hSync);
++      if (DSP_SUCCEEDED(status)) {
++              PROC_NotifyClients(hNode->hProcessor,
++                        DSP_NODESTATECHANGE);
++              NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++      }
++func_end:
++      return status;
++}
++
++/*
++ *  ======== NODE_Terminate ========
++ *  Purpose:
++ *      Signal a node running on the DSP that it should exit its execute phase
++ *      function.
++ */
++DSP_STATUS NODE_Terminate(struct NODE_OBJECT *hNode, OUT DSP_STATUS *pStatus)
++{
++      struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++      struct NODE_MGR *hNodeMgr = NULL;
++      enum NODE_TYPE nodeType;
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      enum NODE_STATE state;
++      struct DSP_MSG msg, killmsg;
++      DSP_STATUS status = DSP_SOK;
++      u32 procId, killTimeOut;
++      struct DEH_MGR *hDehMgr;
++      struct DSP_PROCESSORSTATE procStatus;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pStatus != NULL);
++
++      GT_1trace(NODE_debugMask, GT_ENTER,
++               "NODE_Terminate: hNode: 0x%x\n", hNode);
++
++      if (pNode->hProcessor == NULL) {
++              GT_1trace(NODE_debugMask, GT_4CLASS,
++              "NODE_Terminate: pNode->hProcessor = 0x%x\n",
++              pNode->hProcessor);
++              goto func_end;
++      }
++      status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++      if (DSP_SUCCEEDED(status)) {
++              hNodeMgr = hNode->hNodeMgr;
++
++              if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++                      status = DSP_EHANDLE;
++              else {
++                      nodeType = NODE_GetType(hNode);
++                      if (nodeType != NODE_TASK && nodeType !=
++                         NODE_DAISSOCKET)
++                              status = DSP_ENODETYPE;
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Check node state */
++              status = SYNC_EnterCS(hNodeMgr->hSync);
++              if (DSP_SUCCEEDED(status)) {
++                      state = NODE_GetState(hNode);
++                      if (state != NODE_RUNNING) {
++                              status = DSP_EWRONGSTATE;
++                              /* Set the exit status if node terminated on
++                               * its own. */
++                              if (state == NODE_DONE)
++                                      *pStatus = hNode->nExitStatus;
++
++                      } else {
++                              NODE_SetState(hNode, NODE_TERMINATING);
++                      }
++              }
++              /* end of SYNC_EnterCS */
++              (void)SYNC_LeaveCS(hNodeMgr->hSync);
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /*
++               *  Send exit message. Do not change state to NODE_DONE
++               *  here. That will be done in callback.
++               */
++              GT_1trace(NODE_debugMask, GT_5CLASS,
++                       "NODE_Terminate: env = 0x%x\n", hNode->nodeEnv);
++
++              status = PROC_GetState(pNode->hProcessor, &procStatus,
++                                      sizeof(struct DSP_PROCESSORSTATE));
++              if (DSP_FAILED(status))
++                      goto func_cont;
++              /* If processor is in error state then don't attempt to send
++               * A kill task command */
++              if (procStatus.iState == PROC_ERROR) {
++                      GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Terminate:"
++                              " proc Status 0x%x\n", procStatus.iState);
++                      status = DSP_EFAIL;
++                      goto func_cont;
++              }
++
++              msg.dwCmd = RMS_EXIT;
++              msg.dwArg1 = hNode->nodeEnv;
++              killmsg.dwCmd = RMS_KILLTASK;
++              killmsg.dwArg1 = hNode->nodeEnv;
++              pIntfFxns = hNodeMgr->pIntfFxns;
++
++              if (hNode->uTimeout > MAXTIMEOUT)
++                      killTimeOut = MAXTIMEOUT;
++              else
++                      killTimeOut = (hNode->uTimeout)*2;
++
++              status = (*pIntfFxns->pfnMsgPut)(hNode->hMsgQueue, &msg,
++                                                      hNode->uTimeout);
++              if (DSP_SUCCEEDED(status)) {
++                      /*  Wait on synchronization object that will be
++                       *  posted in the callback on receiving RMS_EXIT
++                       *  message, or by NODE_Delete. Check for valid hNode,
++                       *  in case posted by NODE_Delete().  */
++                      status = SYNC_WaitOnEvent(hNode->hSyncDone,
++                                                      killTimeOut/2);
++                      if (DSP_FAILED(status)) {
++                              if (status == DSP_ETIMEOUT) {
++                                      status = (*pIntfFxns->pfnMsgPut)
++                                               (hNode->hMsgQueue, &killmsg,
++                                               hNode->uTimeout);
++                                      if (DSP_SUCCEEDED(status)) {
++                                              status = SYNC_WaitOnEvent
++                                                      (hNode->hSyncDone,
++                                                      killTimeOut/2);
++                                              if (DSP_FAILED(status)) {
++                                                      /* Here it goes the part
++                                                      * of the simulation of
++                                                      * the DSP exception */
++                                                  DEV_GetDehMgr(hNodeMgr->
++                                                      hDevObject, &hDehMgr);
++                                                  if (hDehMgr) {
++                                                      (*pIntfFxns->
++                                                      pfnDehNotify)(hDehMgr,
++                                                      DSP_SYSERROR,
++                                                      DSP_EXCEPTIONABORT);
++                                                          status = DSP_EFAIL;
++                                                  }
++                                              } else
++                                                  status = DSP_SOK;
++                                      }
++                              } else
++                                      status = DSP_EFAIL;
++                      } else  /* Convert SYNC status to DSP status */
++                              status = DSP_SOK;
++              }
++      }
++func_cont:
++      if (DSP_SUCCEEDED(status)) {
++              /* Enter CS before getting exit status, in case node was
++               * deleted. */
++              status = SYNC_EnterCS(hNodeMgr->hSync);
++              /* Make sure node wasn't deleted while we blocked */
++              if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++                      status = DSP_EFAIL;
++              } else {
++                      *pStatus = hNode->nExitStatus;
++                      GT_1trace(NODE_debugMask, GT_ENTER,
++                               "NODE_Terminate: env = 0x%x "
++                               "succeeded.\n", hNode->nodeEnv);
++              }
++              (void)SYNC_LeaveCS(hNodeMgr->hSync);
++      }               /*End of SYNC_EnterCS */
++func_end:
++      return status;
++}
++
++/*
++ *  ======== DeleteNode ========
++ *  Purpose:
++ *      Free GPP resources allocated in NODE_Allocate() or NODE_Connect().
++ */
++static void DeleteNode(struct NODE_OBJECT *hNode)
++{
++      struct NODE_MGR *hNodeMgr;
++      struct CMM_XLATOROBJECT *hXlator;
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      u32 i;
++      enum NODE_TYPE nodeType;
++      struct STREAM stream;
++      struct NODE_MSGARGS msgArgs;
++      struct NODE_TASKARGS taskArgs;
++#ifdef DSP_DMM_DEBUG
++      struct DMM_OBJECT *hDmmMgr;
++      struct PROC_OBJECT *pProcObject =
++                      (struct PROC_OBJECT *)hNode->hProcessor;
++#endif
++      DSP_STATUS status;
++      DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++      hNodeMgr = hNode->hNodeMgr;
++       if (!MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE))
++               return;
++      hXlator = hNode->hXlator;
++      nodeType = NODE_GetType(hNode);
++      if (nodeType != NODE_DEVICE) {
++              msgArgs = hNode->createArgs.asa.msgArgs;
++              if (msgArgs.pData)
++                      MEM_Free(msgArgs.pData);
++
++              /* Free MSG queue */
++              if (hNode->hMsgQueue) {
++                      pIntfFxns = hNodeMgr->pIntfFxns;
++                      (*pIntfFxns->pfnMsgDeleteQueue) (hNode->hMsgQueue);
++                       hNode->hMsgQueue = NULL;
++
++              }
++              if (hNode->hSyncDone)
++                      (void) SYNC_CloseEvent(hNode->hSyncDone);
++
++              /* Free all stream info */
++              if (hNode->inputs) {
++                      for (i = 0; i < MaxInputs(hNode); i++) {
++                              stream = hNode->inputs[i];
++                              FreeStream(hNodeMgr, stream);
++                      }
++                      MEM_Free(hNode->inputs);
++                       hNode->inputs = NULL;
++              }
++              if (hNode->outputs) {
++                      for (i = 0; i < MaxOutputs(hNode); i++) {
++                              stream = hNode->outputs[i];
++                              FreeStream(hNodeMgr, stream);
++                      }
++                      MEM_Free(hNode->outputs);
++                       hNode->outputs = NULL;
++              }
++              taskArgs = hNode->createArgs.asa.taskArgs;
++              if (taskArgs.strmInDef) {
++                      for (i = 0; i < MaxInputs(hNode); i++) {
++                              if (taskArgs.strmInDef[i].szDevice) {
++                                      MEM_Free(taskArgs.strmInDef[i].
++                                              szDevice);
++                                       taskArgs.strmInDef[i].szDevice = NULL;
++                              }
++                      }
++                      MEM_Free(taskArgs.strmInDef);
++                      taskArgs.strmInDef = NULL;
++              }
++              if (taskArgs.strmOutDef) {
++                      for (i = 0; i < MaxOutputs(hNode); i++) {
++                              if (taskArgs.strmOutDef[i].szDevice) {
++                                      MEM_Free(taskArgs.strmOutDef[i].
++                                              szDevice);
++                                       taskArgs.strmOutDef[i].szDevice = NULL;
++                              }
++                      }
++                      MEM_Free(taskArgs.strmOutDef);
++                      taskArgs.strmOutDef = NULL;
++              }
++              if (taskArgs.uDSPHeapResAddr) {
++                      status = PROC_UnMap(hNode->hProcessor,
++                                         (void *)taskArgs.uDSPHeapAddr);
++                      if (DSP_SUCCEEDED(status)) {
++                              GT_0trace(NODE_debugMask, GT_5CLASS,
++                                       "DSPProcessor_UnMap succeeded.\n");
++                      } else {
++                              GT_1trace(NODE_debugMask, GT_5CLASS,
++                                       "DSPProcessor_UnMap failed."
++                                       " Status = 0x%x\n", (u32)status);
++                      }
++                      status = PROC_UnReserveMemory(hNode->hProcessor,
++                                      (void *)taskArgs.uDSPHeapResAddr);
++                      if (DSP_SUCCEEDED(status)) {
++                              GT_0trace(NODE_debugMask, GT_5CLASS,
++                                       "DSPProcessor_UnReserveMemory "
++                                       "succeeded.\n");
++                      } else {
++                              GT_1trace(NODE_debugMask, GT_5CLASS,
++                                       "DSPProcessor_UnReserveMemory "
++                                       "failed. Status = 0x%x\n",
++                                       (u32)status);
++                      }
++#ifdef DSP_DMM_DEBUG
++                      status = DMM_GetHandle(pProcObject, &hDmmMgr);
++                      if (DSP_SUCCEEDED(status))
++                              DMM_MemMapDump(hDmmMgr);
++#endif
++              }
++      }
++      if (nodeType != NODE_MESSAGE) {
++               if (hNode->streamConnect) {
++                      MEM_Free(hNode->streamConnect);
++                       hNode->streamConnect = NULL;
++               }
++      }
++       if (hNode->pstrDevName) {
++              MEM_Free(hNode->pstrDevName);
++               hNode->pstrDevName = NULL;
++       }
++
++       if (hNode->hNtfy) {
++              NTFY_Delete(hNode->hNtfy);
++               hNode->hNtfy = NULL;
++       }
++
++      /* These were allocated in DCD_GetObjectDef (via NODE_Allocate) */
++       if (hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn) {
++              MEM_Free(hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn);
++               hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn = NULL;
++       }
++
++       if (hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn) {
++              MEM_Free(hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn);
++               hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn = NULL;
++       }
++
++       if (hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn) {
++              MEM_Free(hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn);
++               hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn = NULL;
++       }
++
++       if (hNode->dcdProps.objData.nodeObj.pstrIAlgName) {
++              MEM_Free(hNode->dcdProps.objData.nodeObj.pstrIAlgName);
++               hNode->dcdProps.objData.nodeObj.pstrIAlgName = NULL;
++       }
++
++      /* Free all SM address translator resources */
++       if (hXlator) {
++              (void) CMM_XlatorDelete(hXlator, TRUE); /* force free */
++               hXlator = NULL;
++       }
++
++       if (hNode->hNldrNode) {
++              hNodeMgr->nldrFxns.pfnFree(hNode->hNldrNode);
++               hNode->hNldrNode = NULL;
++       }
++
++      MEM_FreeObject(hNode);
++       hNode = NULL;
++}
++
++/*
++ *  ======== DeleteNodeMgr ========
++ *  Purpose:
++ *      Frees the node manager.
++ */
++static void DeleteNodeMgr(struct NODE_MGR *hNodeMgr)
++{
++      struct NODE_OBJECT *hNode;
++
++      if (MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE)) {
++              /* Free resources */
++              if (hNodeMgr->hDcdMgr)
++                      DCD_DestroyManager(hNodeMgr->hDcdMgr);
++
++              /* Remove any elements remaining in lists */
++              if (hNodeMgr->nodeList) {
++                      while ((hNode =
++                              (struct NODE_OBJECT *)LST_GetHead(hNodeMgr->
++                              nodeList)))
++                                      DeleteNode(hNode);
++
++                      DBC_Assert(LST_IsEmpty(hNodeMgr->nodeList));
++                      LST_Delete(hNodeMgr->nodeList);
++              }
++              if (hNodeMgr->hNtfy)
++                      NTFY_Delete(hNodeMgr->hNtfy);
++
++              if (hNodeMgr->pipeMap)
++                      GB_delete(hNodeMgr->pipeMap);
++
++              if (hNodeMgr->pipeDoneMap)
++                      GB_delete(hNodeMgr->pipeDoneMap);
++
++              if (hNodeMgr->chnlMap)
++                      GB_delete(hNodeMgr->chnlMap);
++
++              if (hNodeMgr->dmaChnlMap)
++                      GB_delete(hNodeMgr->dmaChnlMap);
++
++              if (hNodeMgr->zChnlMap)
++                      GB_delete(hNodeMgr->zChnlMap);
++
++              if (hNodeMgr->hDisp)
++                      DISP_Delete(hNodeMgr->hDisp);
++
++              if (hNodeMgr->hSync)
++                      SYNC_DeleteCS(hNodeMgr->hSync);
++
++              if (hNodeMgr->hStrmMgr)
++                      STRM_Delete(hNodeMgr->hStrmMgr);
++
++              /* Delete the loader */
++              if (hNodeMgr->hNldr)
++                      hNodeMgr->nldrFxns.pfnDelete(hNodeMgr->hNldr);
++
++              if (hNodeMgr->fLoaderInit)
++                      hNodeMgr->nldrFxns.pfnExit();
++
++              MEM_FreeObject(hNodeMgr);
++      }
++}
++
++/*
++ *  ======== FillStreamConnect ========
++ *  Purpose:
++ *      Fills stream information.
++ */
++static void FillStreamConnect(struct NODE_OBJECT *hNode1,
++                           struct NODE_OBJECT *hNode2,
++                           u32 uStream1, u32 uStream2)
++{
++      u32 uStrmIndex;
++      struct DSP_STREAMCONNECT *pStrm1 = NULL;
++      struct DSP_STREAMCONNECT *pStrm2 = NULL;
++      enum NODE_TYPE node1Type = NODE_TASK;
++      enum NODE_TYPE node2Type = NODE_TASK;
++
++      node1Type = NODE_GetType(hNode1);
++      node2Type = NODE_GetType(hNode2);
++      if (hNode1 != (struct NODE_OBJECT *)DSP_HGPPNODE) {
++
++              if (node1Type != NODE_DEVICE) {
++                      uStrmIndex = hNode1->uNumInputs +
++                                   hNode1->uNumOutputs - 1;
++                      pStrm1 = &(hNode1->streamConnect[uStrmIndex]);
++                      pStrm1->cbStruct = sizeof(struct DSP_STREAMCONNECT);
++                      pStrm1->uThisNodeStreamIndex = uStream1;
++              }
++
++              if (hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE) {
++                              /* NODE == > NODE */
++                      if (node1Type != NODE_DEVICE) {
++                              pStrm1->hConnectedNode = hNode2;
++                              pStrm1->uiConnectedNodeID = hNode2->nodeId;
++                              pStrm1->uConnectedNodeStreamIndex = uStream2;
++                              pStrm1->lType = CONNECTTYPE_NODEOUTPUT;
++                      }
++                      if (node2Type != NODE_DEVICE) {
++                              uStrmIndex = hNode2->uNumInputs +
++                                              hNode2->uNumOutputs - 1;
++                              pStrm2 = &(hNode2->streamConnect[uStrmIndex]);
++                              pStrm2->cbStruct =
++                                      sizeof(struct DSP_STREAMCONNECT);
++                              pStrm2->uThisNodeStreamIndex = uStream2;
++                              pStrm2->hConnectedNode = hNode1;
++                              pStrm2->uiConnectedNodeID = hNode1->nodeId;
++                              pStrm2->uConnectedNodeStreamIndex = uStream1;
++                              pStrm2->lType = CONNECTTYPE_NODEINPUT;
++                      }
++              } else if (node1Type != NODE_DEVICE)
++                              pStrm1->lType = CONNECTTYPE_GPPOUTPUT;
++      } else {
++              /* GPP == > NODE */
++              DBC_Assert(hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE);
++              uStrmIndex = hNode2->uNumInputs + hNode2->uNumOutputs - 1;
++              pStrm2 = &(hNode2->streamConnect[uStrmIndex]);
++              pStrm2->cbStruct = sizeof(struct DSP_STREAMCONNECT);
++              pStrm2->uThisNodeStreamIndex = uStream2;
++              pStrm2->lType = CONNECTTYPE_GPPINPUT;
++      }
++}
++
++/*
++ *  ======== FillStreamDef ========
++ *  Purpose:
++ *      Fills Stream attributes.
++ */
++static void FillStreamDef(struct NODE_OBJECT *hNode,
++                        struct NODE_STRMDEF *pstrmDef,
++                        struct DSP_STRMATTR *pAttrs)
++{
++      struct NODE_MGR *hNodeMgr = hNode->hNodeMgr;
++
++      if (pAttrs != NULL) {
++              pstrmDef->uNumBufs = pAttrs->uNumBufs;
++              pstrmDef->uBufsize = pAttrs->uBufsize / hNodeMgr->
++                                                      uDSPDataMauSize;
++              pstrmDef->uSegid = pAttrs->uSegid;
++              pstrmDef->uAlignment = pAttrs->uAlignment;
++              pstrmDef->uTimeout = pAttrs->uTimeout;
++      } else {
++              pstrmDef->uNumBufs = DEFAULTNBUFS;
++              pstrmDef->uBufsize = DEFAULTBUFSIZE / hNodeMgr->
++                                                    uDSPDataMauSize;
++              pstrmDef->uSegid = DEFAULTSEGID;
++              pstrmDef->uAlignment = DEFAULTALIGNMENT;
++              pstrmDef->uTimeout = DEFAULTTIMEOUT;
++      }
++}
++
++/*
++ *  ======== FreeStream ========
++ *  Purpose:
++ *      Updates the channel mask and frees the pipe id.
++ */
++static void FreeStream(struct NODE_MGR *hNodeMgr, struct STREAM stream)
++{
++      /* Free up the pipe id unless other node has not yet been deleted. */
++      if (stream.type == NODECONNECT) {
++              if (GB_test(hNodeMgr->pipeDoneMap, stream.devId)) {
++                      /* The other node has already been deleted */
++                      GB_clear(hNodeMgr->pipeDoneMap, stream.devId);
++                      GB_clear(hNodeMgr->pipeMap, stream.devId);
++              } else {
++                      /* The other node has not been deleted yet */
++                      GB_set(hNodeMgr->pipeDoneMap, stream.devId);
++              }
++      } else if (stream.type == HOSTCONNECT) {
++              if (stream.devId < hNodeMgr->ulNumChnls) {
++                      GB_clear(hNodeMgr->chnlMap, stream.devId);
++              } else if (stream.devId < (2 * hNodeMgr->ulNumChnls)) {
++                      /* dsp-dma */
++                      GB_clear(hNodeMgr->dmaChnlMap, stream.devId -
++                              (1 * hNodeMgr->ulNumChnls));
++              } else if (stream.devId < (3 * hNodeMgr->ulNumChnls)) {
++                      /* zero-copy */
++                      GB_clear(hNodeMgr->zChnlMap, stream.devId -
++                              (2 * hNodeMgr->ulNumChnls));
++              }
++      }
++}
++
++/*
++ *  ======== GetFxnAddress ========
++ *  Purpose:
++ *      Retrieves the address for create, execute or delete phase for a node.
++ */
++static DSP_STATUS GetFxnAddress(struct NODE_OBJECT *hNode, u32 *pulFxnAddr,
++                              u32 uPhase)
++{
++      char *pstrFxnName = NULL;
++      struct NODE_MGR *hNodeMgr = hNode->hNodeMgr;
++      DSP_STATUS status = DSP_SOK;
++      DBC_Require(NODE_GetType(hNode) == NODE_TASK ||
++                      NODE_GetType(hNode) == NODE_DAISSOCKET ||
++                      NODE_GetType(hNode) == NODE_MESSAGE);
++
++      switch (uPhase) {
++      case CREATEPHASE:
++              pstrFxnName = hNode->dcdProps.objData.nodeObj.
++                            pstrCreatePhaseFxn;
++              break;
++      case EXECUTEPHASE:
++              pstrFxnName = hNode->dcdProps.objData.nodeObj.
++                            pstrExecutePhaseFxn;
++              break;
++      case DELETEPHASE:
++              pstrFxnName = hNode->dcdProps.objData.nodeObj.
++                            pstrDeletePhaseFxn;
++              break;
++      default:
++              /* Should never get here */
++              DBC_Assert(false);
++              break;
++      }
++
++      status = hNodeMgr->nldrFxns.pfnGetFxnAddr(hNode->hNldrNode, pstrFxnName,
++                                              pulFxnAddr);
++
++      return status;
++}
++
++/*
++ *  ======== GetNodeInfo ========
++ *  Purpose:
++ *      Retrieves the node information.
++ */
++void GetNodeInfo(struct NODE_OBJECT *hNode, struct DSP_NODEINFO *pNodeInfo)
++{
++      u32 i;
++
++      DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++      DBC_Require(pNodeInfo != NULL);
++
++      pNodeInfo->cbStruct = sizeof(struct DSP_NODEINFO);
++      pNodeInfo->nbNodeDatabaseProps = hNode->dcdProps.objData.nodeObj.
++                                       ndbProps;
++      pNodeInfo->uExecutionPriority = hNode->nPriority;
++      pNodeInfo->hDeviceOwner = hNode->hDeviceOwner;
++      pNodeInfo->uNumberStreams = hNode->uNumInputs + hNode->uNumOutputs;
++      pNodeInfo->uNodeEnv = hNode->nodeEnv;
++
++      pNodeInfo->nsExecutionState = NODE_GetState(hNode);
++
++      /* Copy stream connect data */
++      for (i = 0; i < hNode->uNumInputs + hNode->uNumOutputs; i++)
++              pNodeInfo->scStreamConnection[i] = hNode->streamConnect[i];
++
++}
++
++/*
++ *  ======== GetNodeProps ========
++ *  Purpose:
++ *      Retrieve node properties.
++ */
++static DSP_STATUS GetNodeProps(struct DCD_MANAGER *hDcdMgr,
++                            struct NODE_OBJECT *hNode,
++                            CONST struct DSP_UUID *pNodeId,
++                            struct DCD_GENERICOBJ *pdcdProps)
++{
++      u32 uLen;
++      struct NODE_MSGARGS *pMsgArgs;
++      struct NODE_TASKARGS *pTaskArgs;
++      enum NODE_TYPE nodeType = NODE_TASK;
++      struct DSP_NDBPROPS *pndbProps = &(pdcdProps->objData.nodeObj.ndbProps);
++      DSP_STATUS status = DSP_SOK;
++#ifdef DEBUG
++      char szUuid[MAXUUIDLEN];
++#endif
++
++      status = DCD_GetObjectDef(hDcdMgr, (struct DSP_UUID *)pNodeId,
++                               DSP_DCDNODETYPE, pdcdProps);
++
++      if (DSP_SUCCEEDED(status)) {
++              hNode->nType = nodeType = pndbProps->uNodeType;
++
++#ifdef DEBUG
++              /* Create UUID value to set in registry. */
++              UUID_UuidToString((struct DSP_UUID *)pNodeId, szUuid,
++                               MAXUUIDLEN);
++              DBG_Trace(DBG_LEVEL7, "\n** (node) UUID: %s\n", szUuid);
++#endif
++
++              /* Fill in message args that come from NDB */
++              if (nodeType != NODE_DEVICE) {
++                      pMsgArgs = &(hNode->createArgs.asa.msgArgs);
++                      pMsgArgs->uSegid = pdcdProps->objData.nodeObj.uMsgSegid;
++                      pMsgArgs->uNotifyType = pdcdProps->objData.nodeObj.
++                                              uMsgNotifyType;
++                      pMsgArgs->uMaxMessages = pndbProps->uMessageDepth;
++#ifdef DEBUG
++                      DBG_Trace(DBG_LEVEL7,
++                               "** (node) Max Number of Messages: 0x%x\n",
++                               pMsgArgs->uMaxMessages);
++#endif
++              } else {
++                      /* Copy device name */
++                       DBC_Require(pndbProps->acName);
++                       uLen = strlen(pndbProps->acName);
++                      DBC_Assert(uLen < MAXDEVNAMELEN);
++                      hNode->pstrDevName = MEM_Calloc(uLen + 1, MEM_PAGED);
++                      if (hNode->pstrDevName == NULL) {
++                              status = DSP_EMEMORY;
++                      } else {
++                               strncpy(hNode->pstrDevName,
++                                         pndbProps->acName, uLen);
++                      }
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Fill in create args that come from NDB */
++              if (nodeType == NODE_TASK || nodeType == NODE_DAISSOCKET) {
++                      pTaskArgs = &(hNode->createArgs.asa.taskArgs);
++                      pTaskArgs->nPriority = pndbProps->iPriority;
++                      pTaskArgs->uStackSize = pndbProps->uStackSize;
++                      pTaskArgs->uSysStackSize = pndbProps->uSysStackSize;
++                      pTaskArgs->uStackSeg = pndbProps->uStackSeg;
++#ifdef DEBUG
++                      DBG_Trace(DBG_LEVEL7,
++                               "** (node) Priority: 0x%x\n" "** (node) Stack"
++                               " Size: 0x%x words\n" "** (node) System Stack"
++                               " Size: 0x%x words\n" "** (node) Stack"
++                               " Segment: 0x%x\n\n",
++                                "** (node) profile count : 0x%x \n \n",
++                                pTaskArgs->nPriority, pTaskArgs->uStackSize,
++                                pTaskArgs->uSysStackSize,
++                                pTaskArgs->uStackSeg,
++                                pndbProps->uCountProfiles);
++#endif
++              }
++      }
++
++      return status;
++}
++
++/*
++ *  ======== GetProcProps ========
++ *  Purpose:
++ *      Retrieve the processor properties.
++ */
++static DSP_STATUS GetProcProps(struct NODE_MGR *hNodeMgr,
++                              struct DEV_OBJECT *hDevObject)
++{
++      struct CFG_DEVNODE *hDevNode;
++      struct CFG_HOSTRES hostRes;
++      DSP_STATUS status = DSP_SOK;
++
++      status = DEV_GetDevNode(hDevObject, &hDevNode);
++      if (DSP_SUCCEEDED(status))
++              status = CFG_GetHostResources(hDevNode, &hostRes);
++
++      if (DSP_SUCCEEDED(status)) {
++              hNodeMgr->ulChnlOffset = hostRes.dwChnlOffset;
++              hNodeMgr->ulChnlBufSize = hostRes.dwChnlBufSize;
++              hNodeMgr->ulNumChnls = hostRes.dwNumChnls;
++
++              /*
++               *  PROC will add an API to get DSP_PROCESSORINFO.
++               *  Fill in default values for now.
++               */
++              /* TODO -- Instead of hard coding, take from registry */
++              hNodeMgr->procFamily = 6000;
++              hNodeMgr->procType = 6410;
++              hNodeMgr->nMinPri = DSP_NODE_MIN_PRIORITY;
++              hNodeMgr->nMaxPri = DSP_NODE_MAX_PRIORITY;
++              hNodeMgr->uDSPWordSize = DSPWORDSIZE;
++              hNodeMgr->uDSPDataMauSize = DSPWORDSIZE;
++              hNodeMgr->uDSPMauSize = 1;
++
++      }
++      return status;
++}
++
++
++
++/*
++ *  ======== NODE_GetUUIDProps ========
++ *  Purpose:
++ *      Fetch Node UUID properties from DCD/DOF file.
++ */
++DSP_STATUS NODE_GetUUIDProps(DSP_HPROCESSOR hProcessor,
++                          IN CONST struct DSP_UUID *pNodeId,
++                          OUT struct DSP_NDBPROPS *pNodeProps)
++{
++      struct NODE_MGR *hNodeMgr = NULL;
++      struct DEV_OBJECT *hDevObject;
++      DSP_STATUS status = DSP_SOK;
++      struct DCD_NODEPROPS   dcdNodeProps;
++      struct DSP_PROCESSORSTATE procStatus;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(hProcessor != NULL);
++      DBC_Require(pNodeId != NULL);
++
++      if (hProcessor == NULL || pNodeId == NULL) {
++              status = DSP_EHANDLE;
++              goto func_end;
++      }
++      status = PROC_GetState(hProcessor, &procStatus,
++                      sizeof(struct DSP_PROCESSORSTATE));
++      if (DSP_FAILED(status))
++              goto func_end;
++      /* If processor is in error state then don't attempt
++          to send the message */
++      if (procStatus.iState == PROC_ERROR) {
++              GT_1trace(NODE_debugMask, GT_5CLASS,
++                      "NODE_GetUUIDProps: proc Status 0x%x\n",
++                      procStatus.iState);
++              status = DSP_EFAIL;
++              goto func_end;
++      }
++
++      GT_3trace(NODE_debugMask, GT_ENTER,
++               "NODE_GetUUIDProps: " "\thProcessor: "
++               "0x%x\tpNodeId: 0x%x" "\tpNodeProps: 0x%x\n", hProcessor,
++               pNodeId, pNodeProps);
++
++      status = PROC_GetDevObject(hProcessor, &hDevObject);
++      if (DSP_SUCCEEDED(status) && hDevObject != NULL) {
++              status = DEV_GetNodeManager(hDevObject, &hNodeMgr);
++              if (hNodeMgr == NULL) {
++                      status = DSP_EHANDLE;
++                      goto func_end;
++              }
++      }
++
++      /*
++       * Enter the critical section. This is needed because
++       * DCD_GetObjectDef will ultimately end up calling DBLL_open/close,
++       * which needs to be protected in order to not corrupt the zlib manager
++       * (COD).
++       */
++      status = SYNC_EnterCS(hNodeMgr->hSync);
++
++      if (DSP_SUCCEEDED(status)) {
++              dcdNodeProps.pstrCreatePhaseFxn = NULL;
++              dcdNodeProps.pstrExecutePhaseFxn = NULL;
++              dcdNodeProps.pstrDeletePhaseFxn = NULL;
++              dcdNodeProps.pstrIAlgName = NULL;
++
++              status = DCD_GetObjectDef(hNodeMgr->hDcdMgr,
++                              (struct DSP_UUID *) pNodeId,
++                              DSP_DCDNODETYPE,
++                              (struct DCD_GENERICOBJ *) &dcdNodeProps);
++              if (DSP_SUCCEEDED(status)) {
++                      *pNodeProps = dcdNodeProps.ndbProps;
++                      if (dcdNodeProps.pstrCreatePhaseFxn)
++                              MEM_Free(dcdNodeProps.pstrCreatePhaseFxn);
++
++                      if (dcdNodeProps.pstrExecutePhaseFxn)
++                              MEM_Free(dcdNodeProps.pstrExecutePhaseFxn);
++
++                      if (dcdNodeProps.pstrDeletePhaseFxn)
++                              MEM_Free(dcdNodeProps.pstrDeletePhaseFxn);
++
++                      if (dcdNodeProps.pstrIAlgName)
++                              MEM_Free(dcdNodeProps.pstrIAlgName);
++              }
++              /*  Leave the critical section, we're done.  */
++              (void)SYNC_LeaveCS(hNodeMgr->hSync);
++      }
++func_end:
++      return status;
++}
++
++/*
++ *  ======== GetRMSFxns ========
++ *  Purpose:
++ *      Retrieve the RMS functions.
++ */
++static DSP_STATUS GetRMSFxns(struct NODE_MGR *hNodeMgr)
++{
++      s32 i;
++      struct DEV_OBJECT *hDev = hNodeMgr->hDevObject;
++      DSP_STATUS status = DSP_SOK;
++
++      static char *pszFxns[NUMRMSFXNS] = {
++              "RMS_queryServer",      /* RMSQUERYSERVER */
++              "RMS_configureServer",  /* RMSCONFIGURESERVER */
++              "RMS_createNode",       /* RMSCREATENODE */
++              "RMS_executeNode",      /* RMSEXECUTENODE */
++              "RMS_deleteNode",       /* RMSDELETENODE */
++              "RMS_changeNodePriority",       /* RMSCHANGENODEPRIORITY */
++              "RMS_readMemory",       /* RMSREADMEMORY */
++              "RMS_writeMemory",      /* RMSWRITEMEMORY */
++              "RMS_copy",     /* RMSCOPY */
++      };
++
++      for (i = 0; i < NUMRMSFXNS; i++) {
++              status = DEV_GetSymbol(hDev, pszFxns[i],
++                       &(hNodeMgr->ulFxnAddrs[i]));
++              if (DSP_FAILED(status)) {
++                      if (status == COD_E_SYMBOLNOTFOUND) {
++                              /*
++                               *  May be loaded dynamically (in the future),
++                               *  but return an error for now.
++                               */
++                              GT_1trace(NODE_debugMask, GT_6CLASS,
++                                       "RMS function: %s "
++                                       "currently not loaded\n", pszFxns[i]);
++                      } else {
++                              GT_2trace(NODE_debugMask, GT_6CLASS,
++                                       "GetRMSFxns: Symbol not "
++                                       "found: %s\tstatus = 0x%x\n",
++                                       pszFxns[i], status);
++                              break;
++                      }
++              }
++      }
++
++      return status;
++}
++
++/*
++ *  ======== Ovly ========
++ *  Purpose:
++ *      Called during overlay.Sends command to RMS to copy a block of data.
++ */
++static u32 Ovly(void *pPrivRef, u32 ulDspRunAddr, u32 ulDspLoadAddr,
++                      u32 ulNumBytes, u32 nMemSpace)
++{
++      struct NODE_OBJECT *hNode = (struct NODE_OBJECT *)pPrivRef;
++      struct NODE_MGR *hNodeMgr;
++      u32 ulBytes = 0;
++      u32 ulSize;
++      u32 ulTimeout;
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *hWmdContext;
++      struct WMD_DRV_INTERFACE *pIntfFxns;    /* Function interface to WMD */
++
++      DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++
++      hNodeMgr = hNode->hNodeMgr;
++
++      ulSize = ulNumBytes / hNodeMgr->uDSPWordSize;
++      ulTimeout = hNode->uTimeout;
++
++      /* Call new MemCopy function */
++      pIntfFxns = hNodeMgr->pIntfFxns;
++      status = DEV_GetWMDContext(hNodeMgr->hDevObject, &hWmdContext);
++      status = (*pIntfFxns->pfnBrdMemCopy)(hWmdContext, ulDspRunAddr,
++               ulDspLoadAddr, ulNumBytes, (u32) nMemSpace);
++
++      if (DSP_SUCCEEDED(status))
++              ulBytes = ulNumBytes;
++
++      return ulBytes;
++}
++
++/*
++ *  ======== Write ========
++ */
++static u32 Write(void *pPrivRef, u32 ulDspAddr, void *pBuf,
++                      u32 ulNumBytes, u32 nMemSpace)
++{
++      struct NODE_OBJECT *hNode = (struct NODE_OBJECT *) pPrivRef;
++      struct NODE_MGR *hNodeMgr;
++      u16 memType;
++      u32 ulTimeout;
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *hWmdContext;
++      struct WMD_DRV_INTERFACE *pIntfFxns;    /* Function interface to WMD */
++
++      DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++      DBC_Require(nMemSpace & DBLL_CODE || nMemSpace & DBLL_DATA);
++
++      hNodeMgr = hNode->hNodeMgr;
++
++      ulTimeout = hNode->uTimeout;
++      memType = (nMemSpace & DBLL_CODE) ? RMS_CODE : RMS_DATA;
++
++      /* Call new MemWrite function */
++      pIntfFxns = hNodeMgr->pIntfFxns;
++      status = DEV_GetWMDContext(hNodeMgr->hDevObject, &hWmdContext);
++      status = (*pIntfFxns->pfnBrdMemWrite) (hWmdContext, pBuf, ulDspAddr,
++               ulNumBytes, memType);
++
++      return ulNumBytes;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/proc.c b/drivers/dsp/bridge/rmgr/proc.c
+new file mode 100644
+index 0000000..332e01a
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/proc.c
+@@ -0,0 +1,1985 @@
++/*
++ * proc.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== proc.c ========
++ *  Description:
++ *      Processor interface at the driver level.
++ *
++ *  Public Functions:
++ *      PROC_Attach
++ *      PROC_Ctrl
++ *      PROC_Detach
++ *      PROC_EnumNodes
++ *      PROC_GetResourceInfo
++ *      PROC_Exit
++ *      PROC_FlushMemory
++ *      PROC_GetState
++ *      PROC_GetProcessorId
++ *      PROC_GetTrace
++ *      PROC_Init
++ *      PROC_Load
++ *      PROC_Map
++ *      PROC_NotifyClients
++ *      PROC_RegisterNotify
++ *      PROC_ReserveMemory
++ *      PROC_Start
++ *      PROC_UnMap
++ *      PROC_UnReserveMemory
++ *      PROC_InvalidateMemory
++
++ *! Revision History
++ *! ======== ========
++ *! 04-Apr-2007 sh  Added PROC_InvalidateMemory API
++ *! 19-Apr-2004 sb  Aligned DMM definitions with Symbian
++ *!            Used MEM_FlushCache instead of OS specific API
++ *!            Integrated Alan's code review updates
++ *! 08-Mar-2004 sb  Added the Dynamic Memory Mapping feature
++ *! 08-Mar-2004 vp  Added g_pszLastCoff member to PROC_OBJECT.
++ *!            This is required for multiprocessor environment.
++ *! 09-Feb-2004 vp  Added PROC_GetProcessorID function
++ *! 22-Apr-2003 vp  Fixed issue with the string that stores coff file name
++ *! 03-Apr-2003 sb  Fix DEH deregistering bug
++ *! 26-Mar-2003 vp  Commented the call to DSP deep sleep in PROC_Start function.
++ *! 18-Feb-2003 vp  Code review updates.
++ *! 18-Oct-2002 vp  Ported to Linux platform.
++ *! 22-May-2002 sg  Do IOCTL-to-PWR translation before calling PWR_SleepDSP.
++ *! 14-May-2002 sg  Use CSL_Atoi() instead of atoi().
++ *! 13-May-2002 sg  Propagate PWR return codes upwards.
++ *! 07-May-2002 sg  Added check for, and call to PWR functions in PROC_Ctrl.
++ *! 02-May-2002 sg  Added "nap" mode: put DSP to sleep once booted.
++ *! 01-Apr-2002 jeh Assume word addresses in PROC_GetTrace().
++ *! 29-Nov-2001 jeh Don't call DEH function if hDehMgr == NULL.
++ *! 05-Nov-2001 kc: Updated PROC_RegisterNotify and PROC_GetState to support
++ *!            DEH module.
++ *! 09-Oct-2001 jeh Fix number of bytes calculated in PROC_GetTrace().
++ *! 11-Sep-2001 jeh Delete MSG manager in PROC_Monitor() to fix memory leak.
++ *! 29-Aug-2001 rr: DCD_AutoRegister and IOOnLoaded moved before COD_LoadBase
++ *!            to facilitate the external loading.
++ *! 14-Aug-2001 ag  DCD_AutoRegister() now called before IOOnLoaded() fxn.
++ *! 21-Jun-2001 rr: MSG_Create is done only the first time.
++ *! 02-May-2001 jeh Return failure in PROC_Load if IOOnLoaded function returns
++ *!            error other than E_NOTIMPL.
++ *! 03-Apr-2001 sg: Changed DSP_DCD_ENOAUTOREGISTER to DSP_EDCDNOAUTOREGISTER.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 05-Jan-2001 rr: PROC_LOAD MSG_Create error is checked.
++ *! 15-Dec-2000 rr: IoOnLoaded is checked for WSX_STATUS. We fail to load
++ *!            if DEV_Create2 fails; ie, no non-RMS targets can be
++ *!            loaded.
++ *! 12-Dec-2000 rr: PROC_Start's DEV_Create2 is checked for WSX_STATUS.
++ *! 28-Nov-2000 jeh Added call to IO OnLoaded function to PROC_Load().
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 03-Nov-2000 rr: Auto_Register happens after PROC_Load.
++ *! 06-Oct-2000 rr: Updated to ver 0.9. PROC_Start calls DEV_Create2 and
++ *!            WMD_BRD_STOP is always followed by DEV_Destroy2.
++ *! 05-Sep-2000 rr: PROC_GetTrace calculates the Trace symbol for 55 in a
++ *!            different way.
++ *! 10-Aug-2000 rr: PROC_NotifyClients, PROC_GetProcessorHandle Added
++ *! 07-Aug-2000 rr: PROC_IDLE/SYNCINIT/UNKNOWN state removed.
++ *!            WMD fxns are checked for WSX_STATUS.
++ *!            PROC_Attach does not alter the state of the BRD.
++ *!            PROC_Run removed.
++ *! 04-Aug-2000 rr: All the functions return DSP_EHANDLE if proc handle is
++ *!            invalid
++ *! 27-Jul-2000 rr: PROC_GetTrace and PROC_Load implemented. Updated to
++ *!            ver 0.8 API.
++ *! 06-Jul-2000 rr: Created.
++ */
++
++/* ------------------------------------ Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/sync.h>
++/*  ----------------------------------- Mini Driver */
++#include <dspbridge/wmd.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/procpriv.h>
++#include <dspbridge/dmm.h>
++
++/*  ----------------------------------- Resource Manager */
++#include <dspbridge/mgr.h>
++#include <dspbridge/node.h>
++#include <dspbridge/nldr.h>
++#include <dspbridge/rmm.h>
++
++/*  ----------------------------------- Others */
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/msg.h>
++#include <dspbridge/wmdioctl.h>
++#include <dspbridge/drv.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/proc.h>
++#include <dspbridge/pwr.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/resourcecleanup.h>
++#endif
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++#define PROC_SIGNATURE           0x434F5250   /* "PROC" (in reverse). */
++#define MAXCMDLINELEN       255
++#define PROC_ENVPROCID      "PROC_ID=%d"
++#define MAXPROCIDLEN  (8 + 5)
++#define PROC_DFLT_TIMEOUT   10000     /* Time out in milliseconds  */
++#define PWR_TIMEOUT    500    /* Sleep/wake timout in msec */
++#define EXTEND              "_EXT_END"        /* Extmem end addr in DSP binary */
++
++extern char *iva_img;
++/* The PROC_OBJECT structure.   */
++struct PROC_OBJECT {
++      struct LST_ELEM link;           /* Link to next PROC_OBJECT */
++      u32 dwSignature;        /* Used for object validation */
++      struct DEV_OBJECT *hDevObject;  /* Device this PROC represents */
++      u32 hProcess;   /* Process owning this Processor */
++      struct MGR_OBJECT *hMgrObject;  /* Manager Object Handle */
++      u32 uAttachCount;       /* Processor attach count */
++      u32 uProcessor; /* Processor number */
++      u32 uTimeout;           /* Time out count */
++      enum DSP_PROCSTATE sState;      /* Processor state */
++      u32 ulUnit;             /* DDSP unit number */
++      bool bIsAlreadyAttached;        /*
++                                       * True if the Device below has
++                                       * GPP Client attached
++                                       */
++      struct NTFY_OBJECT *hNtfy;      /* Manages  notifications */
++      struct WMD_DEV_CONTEXT *hWmdContext;    /* WMD Context Handle */
++      struct WMD_DRV_INTERFACE *pIntfFxns;    /* Function interface to WMD */
++      char *g_pszLastCoff;
++} ;
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask PROC_DebugMask = { NULL, NULL };        /* WCD MGR Mask */
++#endif
++
++static u32 cRefs;
++
++struct SYNC_CSOBJECT *hProcLock;      /* For critical sections */
++
++/*  ----------------------------------- Function Prototypes */
++static DSP_STATUS PROC_Monitor(struct PROC_OBJECT *hProcessor);
++static s32 GetEnvpCount(char **envp);
++static char **PrependEnvp(char **newEnvp, char **envp, s32 cEnvp, s32 cNewEnvp,
++                       char *szVar);
++
++
++/*
++ *  ======== PROC_Attach ========
++ *  Purpose:
++ *      Prepare for communication with a particular DSP processor, and return
++ *      a handle to the processor object.
++ */
++DSP_STATUS
++PROC_Attach(u32 uProcessor, OPTIONAL CONST struct DSP_PROCESSORATTRIN *pAttrIn,
++       OUT DSP_HPROCESSOR *phProcessor)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEV_OBJECT *hDevObject;
++      struct PROC_OBJECT *pProcObject = NULL;
++      struct MGR_OBJECT *hMgrObject = NULL;
++      struct DRV_OBJECT *hDrvObject = NULL;
++      u32 devType;
++
++#ifndef RES_CLEANUP_DISABLE
++      HANDLE       hDRVObject;
++       u32                  hProcess;
++      DSP_STATUS res_status = DSP_SOK;
++      struct PROCESS_CONTEXT   *pPctxt = NULL;
++#endif
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phProcessor != NULL);
++
++      GT_3trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Attach, args:\n\t"
++               "uProcessor:  0x%x\n\tpAttrIn:  0x%x\n\tphProcessor:"
++               "0x%x\n", uProcessor, pAttrIn, phProcessor);
++      /* Get the Driver and Manager Object Handles */
++      status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++      if (DSP_SUCCEEDED(status)) {
++              status = CFG_GetObject((u32 *)&hMgrObject, REG_MGR_OBJECT);
++              if (DSP_FAILED(status)) {
++                      /* don't propogate CFG errors from this PROC function */
++                      GT_1trace(PROC_DebugMask, GT_7CLASS,
++                               "PROC_Attach: DSP_FAILED to get"
++                               "the Manager Object.\n", status);
++              }
++      } else {
++              /* don't propogate CFG errors from this PROC function */
++              GT_1trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Attach: failed to get the"
++                       " DriverObject, 0x%x!\n", status);
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Get the Device Object */
++              status = DRV_GetDevObject(uProcessor, hDrvObject, &hDevObject);
++              if (DSP_FAILED(status)) {
++                      GT_1trace(PROC_DebugMask, GT_7CLASS,
++                               "PROC_Attach: failed to get"
++                               " DevObject, 0x%x!\n", status);
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              status = DEV_GetDevType(hDevObject, &devType);
++              if (DSP_FAILED(status)) {
++                      GT_1trace(PROC_DebugMask, GT_7CLASS,
++                               "PROC_Attach: failed to get"
++                               " DevType, 0x%x!\n", status);
++              }
++      }
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      /* If we made it this far, create the Proceesor object: */
++      MEM_AllocObject(pProcObject, struct PROC_OBJECT, PROC_SIGNATURE);
++      /* Fill out the Processor Object: */
++      if (pProcObject == NULL) {
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Attach:Out of memeory \n");
++              status = DSP_EFAIL;
++              goto func_end;
++      }
++      pProcObject->hDevObject = hDevObject;
++      pProcObject->hMgrObject = hMgrObject;
++      pProcObject->uProcessor = devType;
++      /* Get Caller Process and store it */
++       /* Return PID instead of process handle */
++       pProcObject->hProcess = current->pid;
++
++      if (pAttrIn)
++              pProcObject->uTimeout = pAttrIn->uTimeout;
++      else
++              pProcObject->uTimeout = PROC_DFLT_TIMEOUT;
++
++      status = DEV_GetIntfFxns(hDevObject, &pProcObject->pIntfFxns);
++      if (DSP_SUCCEEDED(status)) {
++              status = DEV_GetWMDContext(hDevObject,
++                                       &pProcObject->hWmdContext);
++              if (DSP_FAILED(status)) {
++                      GT_1trace(PROC_DebugMask, GT_7CLASS,
++                               "PROC_Attach Could not"
++                               " get the WMD Context.\n", status);
++                      MEM_FreeObject(pProcObject);
++              }
++      } else {
++              GT_1trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Attach Could not get"
++                       " the DEV_ Interface fxns.\n", status);
++              MEM_FreeObject(pProcObject);
++      }
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      /* Create the Notification Object */
++      /* This is created with no event mask, no notify mask
++       * and no valid handle to the notification. They all get
++       * filled up when PROC_RegisterNotify is called */
++      status = NTFY_Create(&pProcObject->hNtfy);
++      if (DSP_SUCCEEDED(status)) {
++              /* Insert the Processor Object into the DEV List.
++               * Return handle to this Processor Object:
++               * Find out if the Device is already attached to a
++               * Processor. If so, return AlreadyAttached status */
++              LST_InitElem(&pProcObject->link);
++              status = DEV_InsertProcObject(pProcObject->hDevObject,
++                                           (u32)pProcObject,
++                                           &pProcObject->bIsAlreadyAttached);
++              if (DSP_SUCCEEDED(status)) {
++                      if (pProcObject->bIsAlreadyAttached) {
++                              status = DSP_SALREADYATTACHED;
++                              GT_0trace(PROC_DebugMask, GT_1CLASS,
++                                       "PROC_Attach: Processor "
++                                       "Already Attached!\n");
++                      }
++              } else {
++                      if (pProcObject->hNtfy)
++                              NTFY_Delete(pProcObject->hNtfy);
++
++                      MEM_FreeObject(pProcObject);
++                      GT_1trace(PROC_DebugMask, GT_7CLASS,
++                               "PROC_Attach: failed to insert "
++                               "Proc Object into DEV, 0x%x!\n", status);
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      *phProcessor = (DSP_HPROCESSOR)pProcObject;
++                      (void)PROC_NotifyClients(pProcObject,
++                                               DSP_PROCESSORATTACH);
++                      GT_0trace(PROC_DebugMask, GT_1CLASS,
++                               "PROC_Attach: Processor "
++                               "Attach Success!\n");
++              }
++      } else {
++              /* Don't leak memory if DSP_FAILED */
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Attach: Could not allocate "
++                       "storage for notification \n");
++              MEM_FreeObject(pProcObject);
++      }
++func_end:
++#ifndef RES_CLEANUP_DISABLE
++      if (DSP_FAILED(status))
++              goto func_cont;
++
++       /* Return PID instead of process handle */
++       hProcess = current->pid;
++
++      res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++      if (DSP_FAILED(res_status))
++              goto func_cont;
++
++       DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDRVObject,
++                       &pPctxt, NULL, 0);
++      if (pPctxt == NULL) {
++              DRV_InsertProcContext((struct DRV_OBJECT *)hDRVObject, &pPctxt);
++              if (pPctxt != NULL) {
++                      DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
++                       DRV_ProcSetPID(pPctxt, hProcess);
++              }
++      }
++func_cont:
++       /* Return PID instead of process handle */
++       hProcess = current->pid;
++
++      res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++      if (DSP_SUCCEEDED(res_status)) {
++                       DRV_GetProcContext(hProcess,
++                               (struct DRV_OBJECT *)hDRVObject, &pPctxt,
++                               NULL, 0);
++              if (pPctxt != NULL)
++                      pPctxt->hProcessor = (DSP_HPROCESSOR)*phProcessor;
++
++      }
++#endif
++      DBC_Ensure((status == DSP_EFAIL && *phProcessor == NULL) ||
++                (DSP_SUCCEEDED(status) &&
++                MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) ||
++                (status == DSP_SALREADYATTACHED &&
++                MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)));
++      GT_2trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Attach, results:\n\t"
++               "status: 0x%x\n\thProcessor: 0x%x\n", status, *phProcessor);
++
++      return status;
++}
++
++static DSP_STATUS GetExecFile(struct CFG_DEVNODE *hDevNode,
++                           struct DEV_OBJECT *hDevObject,
++                           u32 size, char *execFile)
++{
++      s32 devType;
++      s32 len;
++
++      DEV_GetDevType(hDevObject, (u32 *) &devType);
++      if (devType == DSP_UNIT) {
++              return CFG_GetExecFile(hDevNode, size, execFile);
++      } else if (devType == IVA_UNIT) {
++              if (iva_img) {
++                       len = strlen(iva_img);
++                       strncpy(execFile, iva_img, len + 1);
++                      return DSP_SOK;
++              }
++      }
++      return DSP_EFILE;
++}
++
++/*
++ *  ======== PROC_AutoStart ======== =
++ *  Purpose:
++ *      A Particular device gets loaded with the default image
++ *      if the AutoStart flag is set.
++ *  Parameters:
++ *      hDevObject:     Handle to the Device
++ *  Returns:
++ *      DSP_SOK:   On Successful Loading
++ *      DSP_EFAIL  General Failure
++ *  Requires:
++ *      hDevObject != NULL
++ *  Ensures:
++ */
++DSP_STATUS PROC_AutoStart(struct CFG_DEVNODE *hDevNode,
++                       struct DEV_OBJECT *hDevObject)
++{
++      DSP_STATUS status = DSP_EFAIL;
++      u32 dwAutoStart = 0;    /* autostart flag */
++      struct PROC_OBJECT *pProcObject;
++      struct PROC_OBJECT *hProcObject;
++      char szExecFile[MAXCMDLINELEN];
++      char *argv[2];
++      struct MGR_OBJECT *hMgrObject = NULL;
++      s32 devType;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(hDevNode != NULL);
++      DBC_Require(hDevObject != NULL);
++
++      GT_2trace(PROC_DebugMask, GT_ENTER,
++               "Entered PROC_AutoStart, args:\n\t"
++               "hDevNode: 0x%x\thDevObject: 0x%x\n", hDevNode, hDevObject);
++      /* Create a Dummy PROC Object */
++      if (DSP_FAILED(CFG_GetObject((u32 *)&hMgrObject,
++         REG_MGR_OBJECT))) {
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_AutoStart: DSP_FAILED to "
++                       "Get MGR Object\n");
++              goto func_end;
++      }
++      MEM_AllocObject(pProcObject, struct PROC_OBJECT, PROC_SIGNATURE);
++      if (pProcObject == NULL) {
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_AutoStart: DSP_FAILED "
++                       "to Create a dummy Processor\n");
++              goto func_end;
++      }
++      GT_0trace(PROC_DebugMask, GT_1CLASS, "NTFY Created \n");
++      pProcObject->hDevObject = hDevObject;
++      pProcObject->hMgrObject = hMgrObject;
++      hProcObject = pProcObject;
++      if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++         &pProcObject->pIntfFxns))) {
++              if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++                               &pProcObject->hWmdContext))) {
++                      status = DSP_SOK;
++              } else {
++                      MEM_FreeObject(hProcObject);
++                      GT_0trace(PROC_DebugMask, GT_7CLASS,
++                               "PROC_AutoStart: Failed "
++                               "to get WMD Context \n");
++              }
++      } else {
++              MEM_FreeObject(hProcObject);
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_AutoStart: Failed to "
++                       "get IntFxns \n");
++      }
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      /* Stop the Device, put it into standby mode */
++      status = PROC_Stop(hProcObject);
++      if (DSP_FAILED(CFG_GetAutoStart(hDevNode, &dwAutoStart)) ||
++                         !dwAutoStart) {
++              status = DSP_EFAIL;
++              /* DSP_FAILED to Get s32 Fxn or Wmd Context */
++              GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_AutoStart: "
++                       "CFG_GetAutoStart DSP_FAILED \n");
++              goto func_cont;
++      }
++      /* Get the default executable for this board... */
++      DEV_GetDevType(hDevObject, (u32 *)&devType);
++      pProcObject->uProcessor = devType;
++      if (DSP_SUCCEEDED(GetExecFile(hDevNode, hDevObject,
++                       sizeof(szExecFile), szExecFile))) {
++              argv[0] = szExecFile;
++              argv[1] = NULL;
++              /* ...and try to load it: */
++              status = PROC_Load(hProcObject, 1, (CONST char **)argv, NULL);
++              if (DSP_SUCCEEDED(status)) {
++                      status = PROC_Start(hProcObject);
++                      if (DSP_SUCCEEDED(status)) {
++                              GT_0trace(PROC_DebugMask, GT_1CLASS,
++                                        "PROC_AutoStart: Processor started "
++                                        "running\n");
++                      } else {
++                              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                                        "PROC_AutoStart: DSP_FAILED To "
++                                        "Start \n");
++                      }
++              } else {
++                      GT_0trace(PROC_DebugMask, GT_7CLASS,
++                                "PROC_AutoStart: DSP_FAILED to Load\n");
++              }
++      } else {
++              status = DSP_EFILE;
++              GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_AutoStart: "
++                       "No Exec file found \n");
++      }
++func_cont:
++      MEM_FreeObject(hProcObject);
++func_end:
++      GT_1trace(PROC_DebugMask, GT_ENTER,
++               "Exiting PROC_AutoStart, status:0x%x\n", status);
++      return status;
++}
++
++/*
++ *  ======== PROC_Ctrl ========
++ *  Purpose:
++ *      Pass control information to the GPP device driver managing the
++ *      DSP processor.
++ *
++ *      This will be an OEM-only function, and not part of the DSP/BIOS Bridge
++ *      application developer's API.
++ *      Call the WMD_ICOTL Fxn with the Argument This is a Synchronous
++ *      Operation. arg can be null.
++ */
++DSP_STATUS PROC_Ctrl(DSP_HPROCESSOR hProcessor, u32 dwCmd,
++                  IN struct DSP_CBDATA *arg)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct PROC_OBJECT *pProcObject = hProcessor;
++      u32 timeout = 0;
++
++      DBC_Require(cRefs > 0);
++      GT_3trace(PROC_DebugMask, GT_ENTER,
++               "Entered PROC_Ctrl, args:\n\thProcessor:"
++               " 0x%x\n\tdwCmd: 0x%x\n\targ: 0x%x\n", hProcessor, dwCmd, arg);
++
++      if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++              /* intercept PWR deep sleep command */
++              if (dwCmd == WMDIOCTL_DEEPSLEEP) {
++                      timeout = arg->cbData;
++                      status = PWR_SleepDSP(PWR_DEEPSLEEP, timeout);
++              }
++              /* intercept PWR emergency sleep command */
++              else if (dwCmd == WMDIOCTL_EMERGENCYSLEEP) {
++                      timeout = arg->cbData;
++                      status = PWR_SleepDSP(PWR_EMERGENCYDEEPSLEEP, timeout);
++              } else if (dwCmd == PWR_DEEPSLEEP) {
++                      /* timeout = arg->cbData; */
++                      status = PWR_SleepDSP(PWR_DEEPSLEEP, timeout);
++              }
++              /* intercept PWR wake commands */
++              else if (dwCmd == WMDIOCTL_WAKEUP) {
++                      timeout = arg->cbData;
++                      status = PWR_WakeDSP(timeout);
++              } else if (dwCmd == PWR_WAKEUP) {
++                      /* timeout = arg->cbData; */
++                      status = PWR_WakeDSP(timeout);
++              } else
++                  if (DSP_SUCCEEDED
++                      ((*pProcObject->pIntfFxns->pfnDevCntrl)
++                              (pProcObject->hWmdContext, dwCmd, arg))) {
++                      status = DSP_SOK;
++              } else {
++                      status = DSP_EFAIL;
++                      GT_0trace(PROC_DebugMask, GT_7CLASS,
++                               "PROC_Ctrl: Failed \n");
++              }
++      } else {
++              status = DSP_EHANDLE;
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Ctrl: InValid Processor Handle \n");
++      }
++      GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Ctrl, 0x%x\n",
++               status);
++      return status;
++}
++
++/*
++ *  ======== PROC_Detach ========
++ *  Purpose:
++ *      Destroys the  Processor Object. Removes the notification from the Dev
++ *      List.
++ */
++DSP_STATUS PROC_Detach(DSP_HPROCESSOR hProcessor)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++#ifndef RES_CLEANUP_DISABLE
++      HANDLE hDRVObject;
++       u32 hProcess;
++      DSP_STATUS res_status = DSP_SOK;
++      struct PROCESS_CONTEXT   *pPctxt = NULL;
++#endif
++      DBC_Require(cRefs > 0);
++      GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Detach, args:\n\t"
++               "hProcessor:  0x%x\n", hProcessor);
++
++      if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++              /* Notify the Client */
++              NTFY_Notify(pProcObject->hNtfy, DSP_PROCESSORDETACH);
++              /* Remove the notification memory */
++              if (pProcObject->hNtfy)
++                      NTFY_Delete(pProcObject->hNtfy);
++
++              if (pProcObject->g_pszLastCoff) {
++                      MEM_Free(pProcObject->g_pszLastCoff);
++                      pProcObject->g_pszLastCoff = NULL;
++              }
++
++#ifndef RES_CLEANUP_DISABLE
++              /* Return PID instead of process handle */
++              hProcess = current->pid;
++
++              res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++              if (DSP_SUCCEEDED(res_status)) {
++                      DRV_GetProcContext(hProcess,
++                              (struct DRV_OBJECT *)hDRVObject, &pPctxt,
++                                       NULL, 0);
++                      if (pPctxt != NULL) {
++                              DRV_ProcFreeDMMRes(pPctxt);
++                              pPctxt->hProcessor = NULL;
++                      }
++              }
++#endif
++
++              /* Remove the Proc from the DEV List */
++              (void)DEV_RemoveProcObject(pProcObject->hDevObject,
++                      (u32)pProcObject);
++              /* Free the Processor Object */
++              MEM_FreeObject(pProcObject);
++      } else {
++              status = DSP_EHANDLE;
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Detach: InValid Processor Handle \n");
++      }
++      GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Detach, 0x%x\n",
++               status);
++      return status;
++}
++
++/*
++ *  ======== PROC_EnumNodes ========
++ *  Purpose:
++ *      Enumerate and get configuration information about nodes allocated
++ *      on a DSP processor.
++ */
++DSP_STATUS PROC_EnumNodes(DSP_HPROCESSOR hProcessor, OUT DSP_HNODE *aNodeTab,
++               IN u32 uNodeTabSize, OUT u32 *puNumNodes,
++               OUT u32 *puAllocated)
++{
++      DSP_STATUS status = DSP_EFAIL;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++      struct NODE_MGR *hNodeMgr = NULL;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(aNodeTab != NULL || uNodeTabSize == 0);
++      DBC_Require(puNumNodes != NULL);
++      DBC_Require(puAllocated != NULL);
++
++      GT_5trace(PROC_DebugMask, GT_ENTER, "Entered PROC_EnumNodes, args:\n\t"
++                      "hProcessor:  0x%x\n\taNodeTab:  0x%x\n\tuNodeTabSize: "
++                      " 0x%x\n\t puNumNodes 0x%x\n\t puAllocated: 0x%x\n",
++                      hProcessor, aNodeTab, uNodeTabSize, puNumNodes,
++                      puAllocated);
++      if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++              if (DSP_SUCCEEDED(DEV_GetNodeManager(pProcObject->hDevObject,
++                               &hNodeMgr))) {
++                      if (hNodeMgr) {
++                              status = NODE_EnumNodes(hNodeMgr, aNodeTab,
++                                                      uNodeTabSize,
++                                                      puNumNodes,
++                                                      puAllocated);
++                      }
++              }
++      } else {
++              status = DSP_EHANDLE;
++              GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_EnumNodes: "
++                       "InValid Processor Handle \n");
++      }
++      GT_6trace(PROC_DebugMask, GT_ENTER, "Exit PROC_EnumNodes, args:\n\t"
++                      "hProcessor:  0x%x\n\taNodeTab:  0x%x\n\tuNodeTabSize: "
++                      " 0x%x\n\t puNumNodes 0x%x\n\t puAllocated: 0x%x\n\t "
++                      "status: 0x%x \n", hProcessor, aNodeTab, uNodeTabSize,
++                      puNumNodes, puAllocated, status);
++
++      return status;
++}
++
++/*
++ *  ======== PROC_FlushMemory ========
++ *  Purpose:
++ *     Flush cache
++ */
++DSP_STATUS PROC_FlushMemory(DSP_HPROCESSOR hProcessor, void *pMpuAddr,
++                         u32 ulSize, u32 ulFlags)
++{
++      /* Keep STATUS here for future additions to this function */
++      DSP_STATUS status = DSP_SOK;
++      enum DSP_FLUSHTYPE FlushMemType = PROC_WRITEBACK_INVALIDATE_MEM;
++      DBC_Require(cRefs > 0);
++
++      GT_4trace(PROC_DebugMask, GT_ENTER,
++               "Entered PROC_FlushMemory, args:\n\t"
++               "hProcessor: 0x%x pMpuAddr: 0x%x ulSize 0x%x, ulFlags 0x%x\n",
++               hProcessor, pMpuAddr, ulSize, ulFlags);
++      /* Critical section */
++      (void)SYNC_EnterCS(hProcLock);
++      MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
++      (void)SYNC_LeaveCS(hProcLock);
++
++      GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_FlushMemory [0x%x]",
++               status);
++      return status;
++}
++
++
++/*
++ *  ======== PROC_InvalidateMemory ========
++ *  Purpose:
++ *     Invalidates the memory specified
++ */
++DSP_STATUS PROC_InvalidateMemory(DSP_HPROCESSOR hProcessor, void *pMpuAddr,
++                              u32 ulSize)
++{
++      /* Keep STATUS here for future additions to this function */
++      DSP_STATUS status = DSP_SOK;
++      enum DSP_FLUSHTYPE FlushMemType = PROC_INVALIDATE_MEM;
++      DBC_Require(cRefs > 0);
++      GT_3trace(PROC_DebugMask, GT_ENTER,
++               "Entered PROC_InvalidateMemory, args:\n\t"
++               "hProcessor: 0x%x pMpuAddr: 0x%x ulSize 0x%x\n", hProcessor,
++               pMpuAddr, ulSize);
++      (void)SYNC_EnterCS(hProcLock);
++      MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
++      (void)SYNC_LeaveCS(hProcLock);
++
++      GT_1trace(PROC_DebugMask, GT_ENTER,
++               "Leaving PROC_InvalidateMemory [0x%x]", status);
++      return status;
++}
++
++/*
++ *  ======== PROC_GetResourceInfo ========
++ *  Purpose:
++ *      Enumerate the resources currently available on a processor.
++ */
++DSP_STATUS PROC_GetResourceInfo(DSP_HPROCESSOR hProcessor, u32 uResourceType,
++                              OUT struct DSP_RESOURCEINFO *pResourceInfo,
++                              u32 uResourceInfoSize)
++{
++      DSP_STATUS status = DSP_EFAIL;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++      struct NODE_MGR *hNodeMgr = NULL;
++      struct NLDR_OBJECT *hNldr = NULL;
++      struct RMM_TargetObj *rmm = NULL;
++      struct IO_MGR *hIOMgr = NULL;           /* IO manager handle */
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pResourceInfo != NULL);
++      DBC_Require(uResourceInfoSize >= sizeof(struct DSP_RESOURCEINFO));
++
++      GT_4trace(PROC_DebugMask, GT_ENTER, "Entered PROC_GetResourceInfo,\n\t"
++               "hProcessor:  0x%x\n\tuResourceType:  0x%x\n\tpResourceInfo:"
++               " 0x%x\n\t uResourceInfoSize 0x%x\n", hProcessor,
++               uResourceType, pResourceInfo, uResourceInfoSize);
++      if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++              status = DSP_EHANDLE;
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_GetResourceInfo: InValid "
++                       "Processor Handle \n");
++              goto func_end;
++      }
++      switch (uResourceType) {
++      case DSP_RESOURCE_DYNDARAM:
++      case DSP_RESOURCE_DYNSARAM:
++      case DSP_RESOURCE_DYNEXTERNAL:
++      case DSP_RESOURCE_DYNSRAM:
++              if (DSP_FAILED(DEV_GetNodeManager(pProcObject->hDevObject,
++                 &hNodeMgr)))
++                      goto func_end;
++
++              if (DSP_SUCCEEDED(NODE_GetNldrObj(hNodeMgr, &hNldr))) {
++                      if (DSP_SUCCEEDED(NLDR_GetRmmManager(hNldr, &rmm))) {
++                              DBC_Assert(rmm != NULL);
++                              status = DSP_EVALUE;
++                              if (RMM_stat(rmm,
++                                 (enum DSP_MEMTYPE)uResourceType,
++                                 (struct DSP_MEMSTAT *)&(pResourceInfo->
++                                 result.memStat)))
++                                      status = DSP_SOK;
++                      }
++              }
++              break;
++      case DSP_RESOURCE_PROCLOAD:
++              status = DEV_GetIOMgr(pProcObject->hDevObject, &hIOMgr);
++              status = pProcObject->pIntfFxns->pfnIOGetProcLoad(hIOMgr,
++                       (struct DSP_PROCLOADSTAT *)&(pResourceInfo->
++                       result.procLoadStat));
++              if (DSP_FAILED(status)) {
++                      GT_1trace(PROC_DebugMask, GT_7CLASS,
++                      "Error in procLoadStat function 0x%x\n", status);
++              }
++              break;
++      default:
++              status = DSP_EFAIL;
++              break;
++      }
++func_end:
++      GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_GetResourceInfo, "
++               "status 0x%x\n", status);
++      return status;
++}
++
++/*
++ *  ======== PROC_Exit ========
++ *  Purpose:
++ *      Decrement reference count, and free resources when reference count is
++ *      0.
++ */
++void PROC_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      if (hProcLock)
++              (void)SYNC_DeleteCS(hProcLock);
++
++      cRefs--;
++
++      GT_1trace(PROC_DebugMask, GT_5CLASS,
++               "Entered PROC_Exit, ref count:0x%x\n", cRefs);
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== PROC_GetDevObject ========
++ *  Purpose:
++ *      Return the Dev Object handle for a given Processor.
++ *
++ */
++DSP_STATUS PROC_GetDevObject(DSP_HPROCESSOR hProcessor,
++                           struct DEV_OBJECT **phDevObject)
++{
++      DSP_STATUS status = DSP_EFAIL;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phDevObject != NULL);
++
++      if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++              *phDevObject = pProcObject->hDevObject;
++              status = DSP_SOK;
++      } else {
++              *phDevObject = NULL;
++      }
++
++      DBC_Ensure((DSP_SUCCEEDED(status) && *phDevObject != NULL) ||
++                 (DSP_FAILED(status) && *phDevObject == NULL));
++
++      return status;
++}
++
++/*
++ *  ======== PROC_GetState ========
++ *  Purpose:
++ *      Report the state of the specified DSP processor.
++ */
++DSP_STATUS PROC_GetState(DSP_HPROCESSOR hProcessor,
++                      OUT struct DSP_PROCESSORSTATE *pProcStatus,
++                      u32 uStateInfoSize)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++      BRD_STATUS brdStatus;
++      struct DEH_MGR *hDehMgr;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pProcStatus != NULL);
++      DBC_Require(uStateInfoSize >= sizeof(struct DSP_PROCESSORSTATE));
++
++      GT_3trace(PROC_DebugMask, GT_ENTER, "Entering PROC_GetState, args:\n\t"
++               "pProcStatus: 0x%x\n\thProcessor: 0x%x\n\t uStateInfoSize"
++               " 0x%x\n", pProcStatus, hProcessor, uStateInfoSize);
++      if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++              /* First, retrieve BRD state information */
++              if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++                 (pProcObject->hWmdContext, &brdStatus))) {
++                      switch (brdStatus) {
++                      case BRD_STOPPED:
++                              pProcStatus->iState = PROC_STOPPED;
++                              break;
++                      case BRD_DSP_HIBERNATION:
++                              /* Fall through */
++                      case BRD_RUNNING:
++                              pProcStatus->iState = PROC_RUNNING;
++                              break;
++                      case BRD_LOADED:
++                              pProcStatus->iState = PROC_LOADED;
++                              break;
++                      case BRD_ERROR:
++                              pProcStatus->iState = PROC_ERROR;
++                              break;
++                      default:
++                              pProcStatus->iState = 0xFF;
++                              status = DSP_EFAIL;
++                              break;
++                      }
++              } else {
++                      status = DSP_EFAIL;
++                      GT_0trace(PROC_DebugMask, GT_7CLASS,
++                               "PROC_GetState: General Failure"
++                               " to read the PROC Status \n");
++              }
++              /* Next, retrieve error information, if any */
++              status = DEV_GetDehMgr(pProcObject->hDevObject, &hDehMgr);
++              if (DSP_SUCCEEDED(status) && hDehMgr) {
++                      status = (*pProcObject->pIntfFxns->pfnDehGetInfo)
++                               (hDehMgr, &(pProcStatus->errInfo));
++                      if (DSP_FAILED(status)) {
++                              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                                       "PROC_GetState: Failed "
++                                       "retrieve exception info.\n");
++                      }
++              } else {
++                      status = DSP_EFAIL;
++                      GT_0trace(PROC_DebugMask, GT_7CLASS,
++                               "PROC_GetState: Failed to "
++                               "retrieve DEH handle.\n");
++              }
++      } else {
++              status = DSP_EHANDLE;
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_GetState:InValid Processor Handle \n");
++      }
++      GT_2trace(PROC_DebugMask, GT_ENTER,
++               "Exiting PROC_GetState, results:\n\t"
++               "status:  0x%x\n\tpProcStatus: 0x%x\n", status,
++               pProcStatus->iState);
++      return status;
++}
++
++/*
++ *  ======== PROC_GetTrace ========
++ *  Purpose:
++ *      Retrieve the current contents of the trace buffer, located on the
++ *      Processor.  Predefined symbols for the trace buffer must have been
++ *      configured into the DSP executable.
++ *  Details:
++ *      We support using the symbols SYS_PUTCBEG and SYS_PUTCEND to define a
++ *      trace buffer, only.  Treat it as an undocumented feature.
++ *      This call is destructive, meaning the processor is placed in the monitor
++ *      state as a result of this function.
++ */
++DSP_STATUS PROC_GetTrace(DSP_HPROCESSOR hProcessor, u8 *pBuf, u32 uMaxSize)
++{
++      DSP_STATUS status;
++      status = DSP_ENOTIMPL;
++      return status;
++}
++
++/*
++ *  ======== PROC_Init ========
++ *  Purpose:
++ *      Initialize PROC's private state, keeping a reference count on each call
++ */
++bool PROC_Init(void)
++{
++      bool fRetval = true;
++
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++              /* Set the Trace mask */
++              DBC_Assert(!PROC_DebugMask.flags);
++              GT_create(&PROC_DebugMask, "PR");  /* "PR" for Processor */
++
++              (void)SYNC_InitializeCS(&hProcLock);
++      }
++
++      if (fRetval)
++              cRefs++;
++
++      GT_1trace(PROC_DebugMask, GT_5CLASS,
++               "Entered PROC_Init, ref count:0x%x\n", cRefs);
++      DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++      return fRetval;
++}
++
++/*
++ *  ======== PROC_Load ========
++ *  Purpose:
++ *      Reset a processor and load a new base program image.
++ *      This will be an OEM-only function, and not part of the DSP/BIOS Bridge
++ *      application developer's API.
++ */
++DSP_STATUS PROC_Load(DSP_HPROCESSOR hProcessor, IN CONST s32 iArgc,
++                  IN CONST char **aArgv, IN CONST char **aEnvp)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++      struct IO_MGR *hIOMgr;          /* IO manager handle */
++      struct MSG_MGR *hMsgMgr;
++      struct COD_MANAGER *hCodMgr;    /* Code manager handle */
++      char *pargv0;           /* temp argv[0] ptr */
++      char **newEnvp;         /* Updated envp[] array. */
++      char szProcID[MAXPROCIDLEN];    /* Size of "PROC_ID=<n>" */
++      s32 cEnvp;              /* Num elements in envp[]. */
++      s32 cNewEnvp;           /* "  " in newEnvp[]     */
++      s32 nProcID = 0;        /* Anticipate MP version. */
++      struct DCD_MANAGER *hDCDHandle;
++      struct DMM_OBJECT *hDmmMgr;
++      u32 dwExtEnd;
++      u32 uProcId;
++#ifdef DEBUG
++      BRD_STATUS uBrdState;
++#endif
++#ifdef OPT_LOAD_TIME_INSTRUMENTATION
++      struct timeval tv1;
++      struct timeval tv2;
++#endif
++      DBC_Require(cRefs > 0);
++      DBC_Require(iArgc > 0);
++      DBC_Require(aArgv != NULL);
++#ifdef OPT_LOAD_TIME_INSTRUMENTATION
++      do_gettimeofday(&tv1);
++#endif
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++      struct dspbridge_platform_data *pdata =
++                              omap_dspbridge_dev->dev.platform_data;
++#endif
++      GT_2trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Load, args:\n\t"
++               "hProcessor:  0x%x\taArgv: 0x%x\n", hProcessor, aArgv[0]);
++      /* Call the WMD_BRD_Load Fxn */
++      if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++              status = DSP_EHANDLE;
++              GT_0trace(PROC_DebugMask, GT_1CLASS,
++                       "PROC_Load: Invalid Processor Handle..\n");
++              goto func_end;
++      }
++      if (pProcObject->bIsAlreadyAttached) {
++              status = DSP_EATTACHED;
++              GT_1trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Load  Abort becuase a GPP "
++                       "Client is already attached status 0x%x \n", status);
++              goto func_end;
++      }
++      if (DSP_FAILED(DEV_GetCodMgr(pProcObject->hDevObject, &hCodMgr))) {
++              status = DSP_EFAIL;
++              GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_Load: DSP_FAILED in "
++                       "DEV_GetCodMgr status 0x%x \n", status);
++              goto func_end;
++      }
++      status = PROC_Stop(hProcessor);
++      if (DSP_FAILED(status)) {
++              GT_1trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Load: DSP_FAILED to Place the"
++                       " Processor in Stop Mode(PROC_STOP) status 0x%x \n",
++                       status);
++              goto func_end;
++      }
++      /* Place the board in the monitor state. */
++      status = PROC_Monitor(hProcessor);
++      if (DSP_FAILED(status)) {
++              GT_1trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Load: DSP_FAILED to Place the"
++                       " Processor in Monitor Mode(PROC_IDLE) status 0x%x\n",
++                       status);
++              goto func_end;
++      }
++      /* Save ptr to  original argv[0]. */
++      pargv0 = (char *)aArgv[0];
++      /*Prepend "PROC_ID=<nProcID>"to envp array for target.*/
++      cEnvp = GetEnvpCount((char **)aEnvp);
++      cNewEnvp = (cEnvp ? (cEnvp + 1) : (cEnvp + 2));
++      newEnvp = MEM_Calloc(cNewEnvp * sizeof(char **), MEM_PAGED);
++      if (newEnvp) {
++              status = snprintf(szProcID, MAXPROCIDLEN, PROC_ENVPROCID,
++                                  nProcID);
++              if (status == -1) {
++                      GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Load: "
++                               "Proc ID string overflow \n");
++                      status = DSP_EFAIL;
++              } else {
++                      newEnvp = PrependEnvp(newEnvp, (char **)aEnvp, cEnvp,
++                                           cNewEnvp, szProcID);
++                      /* Get the DCD Handle */
++                      status = MGR_GetDCDHandle(pProcObject->hMgrObject,
++                                               (u32 *)&hDCDHandle);
++                      if (DSP_SUCCEEDED(status)) {
++                              /*  Before proceeding with new load,
++                               *  check if a previously registered COFF
++                               *  exists.
++                               *  If yes, unregister nodes in previously
++                               *  registered COFF.  If any error occurred,
++                               *  set previously registered COFF to NULL.  */
++                              if (pProcObject->g_pszLastCoff != NULL) {
++                                      status = DCD_AutoUnregister(hDCDHandle,
++                                               pProcObject->g_pszLastCoff);
++                                      /* Regardless of auto unregister status,
++                                       *  free previously allocated
++                                       *  memory.  */
++                                      MEM_Free(pProcObject->g_pszLastCoff);
++                                      pProcObject->g_pszLastCoff = NULL;
++                              }
++                      }
++                      /* On success, do COD_OpenBase() */
++                      status = COD_OpenBase(hCodMgr, (char *)aArgv[0],
++                                           COD_SYMB);
++                      if (DSP_FAILED(status)) {
++                              GT_1trace(PROC_DebugMask, GT_7CLASS,
++                                       "PROC_Load: COD_OpenBase "
++                                       "failed (0x%x)\n", status);
++                      }
++              }
++      } else {
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       " PROC_Load:Out of Memory \n");
++              status = DSP_EMEMORY;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Auto-register data base */
++              /* Get the DCD Handle */
++              status = MGR_GetDCDHandle(pProcObject->hMgrObject,
++                                       (u32 *)&hDCDHandle);
++              if (DSP_SUCCEEDED(status)) {
++                      /*  Auto register nodes in specified COFF
++                       *  file.  If registration did not fail,
++                       *  (status = DSP_SOK or DSP_EDCDNOAUTOREGISTER)
++                       *  save the name of the COFF file for
++                       *  de-registration in the future.  */
++                      status = DCD_AutoRegister(hDCDHandle, (char *)aArgv[0]);
++                      if (status == DSP_EDCDNOAUTOREGISTER) {
++                              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                                        "PROC_Load: No Auto "
++                                        "Register section.  Proceeding..\n");
++                              status = DSP_SOK;
++                      }
++                      if (DSP_FAILED(status)) {
++                              status = DSP_EFAIL;
++                              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                                        "PROC_Load: Failed to "
++                                        "Auto Register..\n");
++                      } else {
++                              DBC_Assert(pProcObject->g_pszLastCoff == NULL);
++                              /* Allocate memory for pszLastCoff */
++                              pProcObject->g_pszLastCoff = MEM_Calloc(
++                                       (strlen((char *)aArgv[0]) + 1),
++                                      MEM_PAGED);
++                              /* If memory allocated, save COFF file name*/
++                              if (pProcObject->g_pszLastCoff) {
++                                       strncpy(pProcObject->g_pszLastCoff,
++                                              (char *)aArgv[0],
++                                       (strlen((char *)aArgv[0]) + 1));
++                              }
++                      }
++              }
++      }
++      /* Update shared memory address and size */
++      if (DSP_SUCCEEDED(status)) {
++              /*  Create the message manager. This must be done
++               *  before calling the IOOnLoaded function.  */
++              DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
++              if (!hMsgMgr) {
++                      status = MSG_Create(&hMsgMgr, pProcObject->hDevObject,
++                                         (MSG_ONEXIT)NODE_OnExit);
++                      DBC_Assert(DSP_SUCCEEDED(status));
++                      DEV_SetMsgMgr(pProcObject->hDevObject, hMsgMgr);
++              }
++              if (status == DSP_ENOTIMPL) {
++                      /* It's OK not to have a message manager */
++                      status = DSP_SOK;
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Set the Device object's message manager */
++              status = DEV_GetIOMgr(pProcObject->hDevObject, &hIOMgr);
++              DBC_Assert(DSP_SUCCEEDED(status));
++              status = (*pProcObject->pIntfFxns->pfnIOOnLoaded)(hIOMgr);
++              if (status == DSP_ENOTIMPL) {
++                      /* Ok not to implement this function */
++                      status = DSP_SOK;
++              } else {
++                      if (DSP_FAILED(status)) {
++                              GT_1trace(PROC_DebugMask, GT_7CLASS,
++                                        "PROC_Load: Failed to get shared "
++                                        "memory or message buffer address "
++                                        "from COFF status 0x%x\n", status);
++                              status = DSP_EFAIL;
++                      }
++              }
++      } else {
++              status = DSP_EFAIL;
++              GT_1trace(PROC_DebugMask, GT_7CLASS,
++                        "PROC_Load: DSP_FAILED in "
++                        "MSG_Create status 0x%x\n", status);
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Now, attempt to load an exec: */
++
++      /* Boost the OPP level to Maximum level supported by baseport*/
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++      if (pdata->cpu_set_freq)
++              (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP5]);
++#endif
++              status = COD_LoadBase(hCodMgr, iArgc, (char **)aArgv,
++                                   DEV_BrdWriteFxn,
++                                   pProcObject->hDevObject, NULL);
++              if (DSP_FAILED(status)) {
++                      if (status == COD_E_OPENFAILED) {
++                              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                                      "PROC_Load:Failure to Load the EXE\n");
++                      }
++                      if (status == COD_E_SYMBOLNOTFOUND) {
++                              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                                      "PROC_Load:Could not parse the file\n");
++                      } else {
++                              GT_1trace(PROC_DebugMask, GT_7CLASS,
++                                       "PROC_Load: DSP_FAILED in "
++                                       "COD_Load  status 0x%x \n", status);
++                      }
++              }
++      /* Requesting the lowest opp supported*/
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++      if (pdata->cpu_set_freq)
++              (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP1]);
++#endif
++
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Update the Processor status to loaded */
++              status = (*pProcObject->pIntfFxns->pfnBrdSetState)
++                       (pProcObject->hWmdContext, BRD_LOADED);
++              if (DSP_SUCCEEDED(status)) {
++                      pProcObject->sState = PROC_LOADED;
++                      if (pProcObject->hNtfy) {
++                              PROC_NotifyClients(pProcObject,
++                                               DSP_PROCESSORSTATECHANGE);
++                      }
++              } else {
++                      GT_1trace(PROC_DebugMask, GT_7CLASS,
++                               "PROC_Load, pfnBrdSetState "
++                               "failed: 0x%x\n", status);
++                      status = DSP_EFAIL;
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              status = PROC_GetProcessorId(hProcessor, &uProcId);
++              if (uProcId == DSP_UNIT) {
++                      /* Use all available DSP address space after EXTMEM
++                       * for DMM */
++                      if (DSP_SUCCEEDED(status)) {
++                              status = COD_GetSymValue(hCodMgr, EXTEND,
++                                                              &dwExtEnd);
++                              if (DSP_FAILED(status)) {
++                                      GT_1trace(PROC_DebugMask, GT_7CLASS,
++                                               "PROC_Load: Failed on "
++                                               "COD_GetSymValue %s.\n",
++                                               EXTEND);
++                              }
++                      }
++                      /* Reset DMM structs and add an initial free chunk*/
++                      if (DSP_SUCCEEDED(status)) {
++                              status = DEV_GetDmmMgr(pProcObject->hDevObject,
++                                                    &hDmmMgr);
++                              if (DSP_SUCCEEDED(status)) {
++                                      /* Set dwExtEnd to DMM START u8
++                                        * address */
++                                      dwExtEnd = (dwExtEnd + 1) * DSPWORDSIZE;
++                                       /* DMM memory is from EXT_END */
++                                      status = DMM_CreateTables(hDmmMgr,
++                                              dwExtEnd, DMMPOOLSIZE);
++                              }
++                      }
++              }
++      }
++      /* Restore the original argv[0] */
++      MEM_Free(newEnvp);
++      aArgv[0] = pargv0;
++#ifdef DEBUG
++      if (DSP_SUCCEEDED(status)) {
++              if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++                 (pProcObject->hWmdContext, &uBrdState))) {
++                      GT_0trace(PROC_DebugMask, GT_1CLASS,
++                               "PROC_Load: Processor Loaded\n");
++                      DBC_Assert(uBrdState == BRD_LOADED);
++              }
++      }
++#endif
++func_end:
++#ifdef DEBUG
++      if (DSP_FAILED(status)) {
++              GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_Load: "
++                       "Processor Load Failed.\n");
++
++      }
++#endif
++      GT_1trace(PROC_DebugMask, GT_ENTER,
++               "Exiting PROC_Load, status:  0x%x\n", status);
++      DBC_Ensure((DSP_SUCCEEDED(status) && pProcObject->sState == PROC_LOADED)
++                 || DSP_FAILED(status));
++#ifdef OPT_LOAD_TIME_INSTRUMENTATION
++      do_gettimeofday(&tv2);
++      if (tv2.tv_usec < tv1.tv_usec) {
++              tv2.tv_usec += 1000000;
++              tv2.tv_sec--;
++      }
++      GT_2trace(PROC_DebugMask, GT_1CLASS,
++                      "Proc_Load: time to load %d sec and %d usec \n",
++                  tv2.tv_sec - tv1.tv_sec, tv2.tv_usec - tv1.tv_usec);
++#endif
++      return status;
++}
++
++/*
++ *  ======== PROC_Map ========
++ *  Purpose:
++ *      Maps a MPU buffer to DSP address space.
++ */
++DSP_STATUS PROC_Map(DSP_HPROCESSOR hProcessor, void *pMpuAddr, u32 ulSize,
++                 void *pReqAddr, void **ppMapAddr, u32 ulMapAttr)
++{
++      u32 vaAlign;
++      u32 paAlign;
++      struct DMM_OBJECT *hDmmMgr;
++      u32 sizeAlign;
++      DSP_STATUS status = DSP_SOK;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++#ifndef RES_CLEANUP_DISABLE
++       u32               hProcess;
++       HANDLE        pCtxt = NULL;
++       HANDLE        hDrvObject;
++       HANDLE        dmmRes;
++       DSP_STATUS res_status = DSP_SOK;
++#endif
++
++      GT_6trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Map, args:\n\t"
++               "hProcessor %x, pMpuAddr %x, ulSize %x, pReqAddr %x, "
++               "ulMapAttr %x, ppMapAddr %x\n", hProcessor, pMpuAddr, ulSize,
++               pReqAddr, ulMapAttr, ppMapAddr);
++      /* Calculate the page-aligned PA, VA and size */
++      vaAlign = PG_ALIGN_LOW((u32) pReqAddr, PG_SIZE_4K);
++      paAlign = PG_ALIGN_LOW((u32) pMpuAddr, PG_SIZE_4K);
++      sizeAlign = PG_ALIGN_HIGH(ulSize + (u32)pMpuAddr - paAlign,
++                               PG_SIZE_4K);
++
++      GT_3trace(PROC_DebugMask, GT_ENTER, "PROC_Map: vaAlign %x, paAlign %x, "
++               "sizeAlign %x\n", vaAlign, paAlign, sizeAlign);
++
++      /* Critical section */
++      (void)SYNC_EnterCS(hProcLock);
++      status = DMM_GetHandle(pProcObject, &hDmmMgr);
++      if (DSP_FAILED(status)) {
++              GT_1trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Map: Failed to get DMM Mgr "
++                       "handle: 0x%x\n", status);
++      } else {
++              status = DMM_MapMemory(hDmmMgr, vaAlign, sizeAlign);
++      }
++      /* Add mapping to the page tables. */
++      if (DSP_SUCCEEDED(status)) {
++
++              status = (*pProcObject->pIntfFxns->pfnBrdMemMap)
++                      (pProcObject->hWmdContext, paAlign, vaAlign, sizeAlign,
++                      ulMapAttr);
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Mapped address = MSB of VA | LSB of PA */
++              *ppMapAddr = (void *) (vaAlign | ((u32) pMpuAddr &
++                           (PG_SIZE_4K - 1)));
++      } else {
++              DMM_UnMapMemory(hDmmMgr, vaAlign, &sizeAlign);
++      }
++      (void)SYNC_LeaveCS(hProcLock);
++
++#ifndef RES_CLEANUP_DISABLE
++      if (DSP_SUCCEEDED(status)) {
++              /* Update the node and stream resource status */
++               /* Return PID instead of process handle */
++               hProcess = current->pid;
++
++              res_status = CFG_GetObject((u32 *)&hDrvObject,
++                                        REG_DRV_OBJECT);
++              if (DSP_SUCCEEDED(res_status)) {
++                       if (DRV_GetProcContext(hProcess,
++                               (struct DRV_OBJECT *)hDrvObject, &pCtxt, NULL,
++                                       (u32)pMpuAddr) != DSP_ENOTFOUND) {
++                              DRV_InsertDMMResElement(&dmmRes, pCtxt);
++                              DRV_UpdateDMMResElement(dmmRes, (u32)pMpuAddr,
++                                              ulSize, (u32)pReqAddr,
++                                              (u32)*ppMapAddr, hProcessor);
++                      }
++              }
++      }
++#endif
++      GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_Map [0x%x]", status);
++      return status;
++}
++
++/*
++ *  ======== PROC_RegisterNotify ========
++ *  Purpose:
++ *      Register to be notified of specific processor events.
++ */
++DSP_STATUS PROC_RegisterNotify(DSP_HPROCESSOR hProcessor, u32 uEventMask,
++                            u32 uNotifyType, struct DSP_NOTIFICATION
++                            *hNotification)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++      struct DEH_MGR *hDehMgr;
++
++      DBC_Require(hNotification != NULL);
++      DBC_Require(cRefs > 0);
++
++      GT_4trace(PROC_DebugMask, GT_ENTER,
++               "Entered PROC_RegisterNotify, args:\n\t"
++               "hProcessor:  0x%x\n\tuEventMask:  0x%x\n\tuNotifyMask:"
++               " 0x%x\n\t hNotification 0x%x\n", hProcessor, uEventMask,
++               uNotifyType, hNotification);
++
++      /* Check processor handle */
++      if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++              status = DSP_EHANDLE;
++              GT_1trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_RegsiterNotify Invalid "
++                       "ProcessorHandle 0x%x\n", hProcessor);
++              goto func_end;
++      }
++      /* Check if event mask is a valid processor related event */
++      if (uEventMask & ~(DSP_PROCESSORSTATECHANGE | DSP_PROCESSORATTACH |
++         DSP_PROCESSORDETACH | DSP_PROCESSORRESTART | DSP_MMUFAULT |
++         DSP_SYSERROR))
++              status = DSP_EVALUE;
++
++      /* Check if notify type is valid */
++      if (uNotifyType != DSP_SIGNALEVENT)
++              status = DSP_EVALUE;
++
++      if (DSP_SUCCEEDED(status)) {
++              /* * If event mask is not DSP_SYSERROR or DSP_MMUFAULT,
++               * then register event immediately.  */
++              if (uEventMask & ~(DSP_SYSERROR | DSP_MMUFAULT)) {
++                      status = NTFY_Register(pProcObject->hNtfy,
++                               hNotification, uEventMask, uNotifyType);
++                      /* * Special case alert, special case alert!
++                       * If we're trying to *deregister* (i.e. uEventMask
++                       * is 0), a DSP_SYSERROR or DSP_MMUFAULT notification,
++                       * we have to deregister with the DEH manager.
++                       * There's no way to know, based on uEventMask which
++                       * manager the notification event was registered with,
++                       * so if we're trying to deregister and NTFY_Register
++                       * failed, we'll give the deh manager a shot.
++                       */
++                      if ((uEventMask == 0) && DSP_FAILED(status)) {
++                              status = DEV_GetDehMgr(pProcObject->hDevObject,
++                                       &hDehMgr);
++                              DBC_Assert(pProcObject->pIntfFxns->
++                                         pfnDehRegisterNotify);
++                              status = (*pProcObject->pIntfFxns->
++                                       pfnDehRegisterNotify)
++                                       (hDehMgr, uEventMask, uNotifyType,
++                                       hNotification);
++                      }
++              } else {
++                      status = DEV_GetDehMgr(pProcObject->hDevObject,
++                                            &hDehMgr);
++                      DBC_Assert(pProcObject->pIntfFxns->
++                                pfnDehRegisterNotify);
++                      status = (*pProcObject->pIntfFxns->pfnDehRegisterNotify)
++                               (hDehMgr, uEventMask, uNotifyType,
++                               hNotification);
++                      if (DSP_FAILED(status))
++                              status = DSP_EFAIL;
++
++              }
++      }
++func_end:
++      return status;
++}
++
++/*
++ *  ======== PROC_ReserveMemory ========
++ *  Purpose:
++ *      Reserve a virtually contiguous region of DSP address space.
++ */
++DSP_STATUS PROC_ReserveMemory(DSP_HPROCESSOR hProcessor, u32 ulSize,
++                           void **ppRsvAddr)
++{
++      struct DMM_OBJECT *hDmmMgr;
++      DSP_STATUS status = DSP_SOK;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++      GT_3trace(PROC_DebugMask, GT_ENTER,
++               "Entered PROC_ReserveMemory, args:\n\t"
++               "hProcessor: 0x%x ulSize: 0x%x ppRsvAddr: 0x%x\n", hProcessor,
++               ulSize, ppRsvAddr);
++      status = DMM_GetHandle(pProcObject, &hDmmMgr);
++      if (DSP_FAILED(status)) {
++              GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_ReserveMemory: "
++                       "Failed to get DMM Mgr handle: 0x%x\n", status);
++      } else
++              status = DMM_ReserveMemory(hDmmMgr, ulSize, (u32 *)ppRsvAddr);
++
++      GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_ReserveMemory [0x%x]",
++               status);
++      return status;
++}
++
++/*
++ *  ======== PROC_Start ========
++ *  Purpose:
++ *      Start a processor running.
++ */
++DSP_STATUS PROC_Start(DSP_HPROCESSOR hProcessor)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++      struct COD_MANAGER *hCodMgr;    /* Code manager handle    */
++      u32 dwDspAddr;  /* Loaded code's entry point.    */
++#ifdef DEBUG
++      BRD_STATUS uBrdState;
++#endif
++      DBC_Require(cRefs > 0);
++      GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Start, args:\n\t"
++               "hProcessor:  0x%x\n", hProcessor);
++      if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++              status = DSP_EHANDLE;
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Start :InValid Handle \n");
++              goto func_end;
++      }
++      /* Call the WMD_BRD_Start */
++      if (pProcObject->sState != PROC_LOADED) {
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Start :Wrong state \n");
++              status = DSP_EWRONGSTATE;
++              goto func_end;
++      }
++      status = DEV_GetCodMgr(pProcObject->hDevObject, &hCodMgr);
++      if (DSP_FAILED(status)) {
++              status = DSP_EFAIL;
++              GT_1trace(PROC_DebugMask, GT_7CLASS,
++                       "Processor Start DSP_FAILED "
++                       "in Getting DEV_GetCodMgr status 0x%x\n", status);
++              goto func_cont;
++      }
++      status = COD_GetEntry(hCodMgr, &dwDspAddr);
++      if (DSP_FAILED(status)) {
++              status = DSP_EFAIL;
++              GT_1trace(PROC_DebugMask, GT_7CLASS,
++                       "Processor Start  DSP_FAILED in "
++                       "Getting COD_GetEntry status 0x%x\n", status);
++              goto func_cont;
++      }
++      status = (*pProcObject->pIntfFxns->pfnBrdStart)
++               (pProcObject->hWmdContext, dwDspAddr);
++      if (DSP_FAILED(status)) {
++              status = DSP_EFAIL;
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Start Failed to Start the board\n");
++              goto func_cont;
++      }
++      /* Call DEV_Create2 */
++      status = DEV_Create2(pProcObject->hDevObject);
++      if (DSP_SUCCEEDED(status)) {
++              pProcObject->sState = PROC_RUNNING;
++              /* Deep sleep switces off the peripheral clocks.
++               * we just put the DSP CPU in idle in the idle loop.
++               * so there is no need to send a command to DSP */
++
++              if (pProcObject->hNtfy) {
++                      PROC_NotifyClients(pProcObject,
++                                        DSP_PROCESSORSTATECHANGE);
++              }
++              GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_Start: Processor "
++                       "Started and running \n");
++      } else {
++              /* Failed to Create Node Manager and DISP Object
++               * Stop the Processor from running. Put it in STOPPED State */
++              (void)(*pProcObject->pIntfFxns->pfnBrdStop)(pProcObject->
++                      hWmdContext);
++              status = DSP_EFAIL;
++              pProcObject->sState = PROC_STOPPED;
++              GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Start "
++                       "Failed to Create the Node Manager\n");
++      }
++func_cont:
++#ifdef DEBUG
++      if (DSP_SUCCEEDED(status)) {
++              if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++                 (pProcObject->hWmdContext, &uBrdState))) {
++                      GT_0trace(PROC_DebugMask, GT_1CLASS,
++                               "PROC_Start: Processor State is RUNNING \n");
++                      DBC_Assert(uBrdState != BRD_HIBERNATION);
++              }
++      }
++#endif
++func_end:
++      GT_1trace(PROC_DebugMask, GT_ENTER,
++               "Exiting PROC_Start, status  0x%x\n", status);
++      DBC_Ensure((DSP_SUCCEEDED(status) && pProcObject->sState ==
++                PROC_RUNNING) || DSP_FAILED(status));
++      return status;
++}
++
++/*
++ *  ======== PROC_Stop ========
++ *  Purpose:
++ *      Stop a processor running.
++ */
++DSP_STATUS PROC_Stop(DSP_HPROCESSOR hProcessor)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++      struct MSG_MGR *hMsgMgr;
++      struct NODE_MGR *hNodeMgr;
++      DSP_HNODE hNode;
++      u32 uNodeTabSize = 1;
++      u32 uNumNodes = 0;
++      u32 uNodesAllocated = 0;
++#ifdef DEBUG
++      BRD_STATUS uBrdState;
++#endif
++      DBC_Require(cRefs > 0);
++      GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Stop, args:\n\t"
++               "hProcessor:  0x%x\n", hProcessor);
++      if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++              status = DSP_EHANDLE;
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Stop :InValid Handle \n");
++              goto func_end;
++      }
++      /* check if there are any running nodes */
++      status = DEV_GetNodeManager(pProcObject->hDevObject, &hNodeMgr);
++      if (DSP_SUCCEEDED(status) && hNodeMgr) {
++              status = NODE_EnumNodes(hNodeMgr, &hNode, uNodeTabSize,
++                                      &uNumNodes, &uNodesAllocated);
++              if ((status == DSP_ESIZE) || (uNodesAllocated > 0)) {
++                      GT_1trace(PROC_DebugMask, GT_7CLASS,
++                               "Can't stop device, Active "
++                               "nodes = 0x%x \n", uNodesAllocated);
++                      return DSP_EWRONGSTATE;
++              }
++      }
++      /* Call the WMD_BRD_Stop */
++      /* It is OK to stop a device that does n't have nodes OR not started */
++      status = (*pProcObject->pIntfFxns->pfnBrdStop)(pProcObject->
++               hWmdContext);
++      if (DSP_SUCCEEDED(status)) {
++              GT_0trace(PROC_DebugMask, GT_1CLASS,
++                       "PROC_Stop: Processor Stopped, "
++                       "i.e in standby mode \n");
++              pProcObject->sState = PROC_STOPPED;
++              /* Destory the Node Manager, MSG Manager */
++              if (DSP_SUCCEEDED(DEV_Destroy2(pProcObject->hDevObject))) {
++                      /* Destroy the MSG by calling MSG_Delete */
++                      DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
++                      if (hMsgMgr) {
++                              MSG_Delete(hMsgMgr);
++                              DEV_SetMsgMgr(pProcObject->hDevObject, NULL);
++                      }
++#ifdef DEBUG
++                      if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->
++                         pfnBrdStatus)(pProcObject->hWmdContext,
++                         &uBrdState))) {
++                              GT_0trace(PROC_DebugMask, GT_1CLASS,
++                                       "PROC_Monitor:Processor Stopped \n");
++                              DBC_Assert(uBrdState == BRD_STOPPED);
++                      }
++#endif
++              } else {
++                      GT_0trace(PROC_DebugMask, GT_7CLASS,
++                               "PROC_Stop Couldn't delete node manager \n");
++              }
++      } else {
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Stop Failed to Stop the processor/device \n");
++      }
++func_end:
++      GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Stop, status  0x%x\n",
++               status);
++
++      return status;
++}
++
++/*
++ *  ======== PROC_UnMap ========
++ *  Purpose:
++ *      Removes a MPU buffer mapping from the DSP address space.
++ */
++DSP_STATUS PROC_UnMap(DSP_HPROCESSOR hProcessor, void *pMapAddr)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++      struct DMM_OBJECT *hDmmMgr;
++      u32 vaAlign;
++      u32 sizeAlign;
++#ifndef RES_CLEANUP_DISABLE
++       u32                   hProcess;
++      HANDLE        pCtxt = NULL;
++      HANDLE        hDrvObject;
++      HANDLE        dmmRes;
++      DSP_STATUS res_status = DSP_SOK;
++#endif
++      GT_2trace(PROC_DebugMask, GT_ENTER,
++               "Entered PROC_UnMap, args:\n\thProcessor:"
++               "0x%x pMapAddr: 0x%x\n", hProcessor, pMapAddr);
++
++      vaAlign = PG_ALIGN_LOW((u32) pMapAddr, PG_SIZE_4K);
++
++      status = DMM_GetHandle(hProcessor, &hDmmMgr);
++      /* Critical section */
++      (void)SYNC_EnterCS(hProcLock);
++      if (DSP_FAILED(status)) {
++              GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_UnMap: "
++                       "Failed to get DMM Mgr handle: 0x%x\n", status);
++      } else {
++              /* Update DMM structures. Get the size to unmap.
++               This function returns error if the VA is not mapped */
++              status = DMM_UnMapMemory(hDmmMgr, (u32) vaAlign, &sizeAlign);
++      }
++      /* Remove mapping from the page tables. */
++      if (DSP_SUCCEEDED(status)) {
++              status = (*pProcObject->pIntfFxns->pfnBrdMemUnMap)
++                       (pProcObject->hWmdContext, vaAlign, sizeAlign);
++      }
++      (void)SYNC_LeaveCS(hProcLock);
++#ifndef RES_CLEANUP_DISABLE
++      GT_1trace(PROC_DebugMask, GT_ENTER,
++                 "PROC_UnMap DRV_GetDMMResElement "
++                 "pMapAddr:[0x%x]", pMapAddr);
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      /* Update the node and stream resource status */
++       /* Return PID instead of process handle */
++       hProcess = current->pid;
++
++      res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++      if (DSP_FAILED(res_status))
++              goto func_end;
++
++       DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDrvObject,
++                       &pCtxt, NULL, (u32)pMapAddr);
++      if (pCtxt != NULL) {
++              if (DRV_GetDMMResElement((u32)pMapAddr, &dmmRes, pCtxt) !=
++                 DSP_ENOTFOUND)
++                      DRV_RemoveDMMResElement(dmmRes, pCtxt);
++      }
++func_end:
++#endif
++      GT_1trace(PROC_DebugMask, GT_ENTER,
++               "Leaving PROC_UnMap [0x%x]", status);
++      return status;
++}
++
++/*
++ *  ======== PROC_UnReserveMemory ========
++ *  Purpose:
++ *      Frees a previously reserved region of DSP address space.
++ */
++DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor, void *pRsvAddr)
++{
++      struct DMM_OBJECT *hDmmMgr;
++      DSP_STATUS status = DSP_SOK;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++      GT_2trace(PROC_DebugMask, GT_ENTER,
++               "Entered PROC_UnReserveMemory, args:\n\t"
++               "hProcessor: 0x%x pRsvAddr: 0x%x\n", hProcessor, pRsvAddr);
++
++      status = DMM_GetHandle(pProcObject, &hDmmMgr);
++      if (DSP_FAILED(status))
++              GT_1trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_UnReserveMemory: Failed to get DMM Mgr "
++                       "handle: 0x%x\n", status);
++      else
++              status = DMM_UnReserveMemory(hDmmMgr, (u32) pRsvAddr);
++
++      GT_1trace(PROC_DebugMask, GT_ENTER,
++               "Leaving PROC_UnReserveMemory [0x%x]",
++               status);
++
++      return status;
++}
++
++/*
++ *  ======== = PROC_Monitor ======== ==
++ *  Purpose:
++ *      Place the Processor in Monitor State. This is an internal
++ *      function and a requirement before Processor is loaded.
++ *      This does a WMD_BRD_Stop, DEV_Destroy2 and WMD_BRD_Monitor.
++ *      In DEV_Destroy2 we delete the node manager.
++ *  Parameters:
++ *      hProcObject:    Handle to Processor Object
++ *  Returns:
++ *      DSP_SOK:      Processor placed in monitor mode.
++ *      !DSP_SOK:       Failed to place processor in monitor mode.
++ *  Requires:
++ *      Valid Processor Handle
++ *  Ensures:
++ *      Success:      ProcObject state is PROC_IDLE
++ */
++static DSP_STATUS PROC_Monitor(struct PROC_OBJECT *hProcObject)
++{
++      DSP_STATUS status = DSP_EFAIL;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcObject;
++      struct MSG_MGR *hMsgMgr;
++#ifdef DEBUG
++      BRD_STATUS uBrdState;
++#endif
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
++
++      GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Monitor, args:\n\t"
++               "hProcessor: 0x%x\n", hProcObject);
++      /* This is needed only when Device is loaded when it is
++       * already 'ACTIVE' */
++      /* Destory the Node Manager, MSG Manager */
++      if (DSP_SUCCEEDED(DEV_Destroy2(pProcObject->hDevObject))) {
++              /* Destroy the MSG by calling MSG_Delete */
++              DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
++              if (hMsgMgr) {
++                      MSG_Delete(hMsgMgr);
++                      DEV_SetMsgMgr(pProcObject->hDevObject, NULL);
++              }
++      }
++      /* Place the Board in the Monitor State */
++      if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdMonitor)
++         (pProcObject->hWmdContext))) {
++              status = DSP_SOK;
++#ifdef DEBUG
++              if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++                 (pProcObject->hWmdContext, &uBrdState))) {
++                      GT_0trace(PROC_DebugMask, GT_1CLASS,
++                               "PROC_Monitor:Processor in "
++                               "Monitor State\n");
++                      DBC_Assert(uBrdState == BRD_IDLE);
++              }
++#endif
++      } else {
++              /* Monitor Failure */
++              GT_0trace(PROC_DebugMask, GT_7CLASS,
++                       "PROC_Monitor: Processor Could not"
++                       "be put in Monitor mode \n");
++      }
++      GT_1trace(PROC_DebugMask, GT_ENTER,
++               "Exiting PROC_Monitor, status  0x%x\n",
++               status);
++#ifdef DEBUG
++      DBC_Ensure((DSP_SUCCEEDED(status) && uBrdState == BRD_IDLE) ||
++                DSP_FAILED(status));
++#endif
++      return status;
++}
++
++/*
++ *  ======== GetEnvpCount ========
++ *  Purpose:
++ *      Return the number of elements in the envp array, including the
++ *      terminating NULL element.
++ */
++static s32 GetEnvpCount(char **envp)
++{
++      s32 cRetval = 0;
++      if (envp) {
++              while (*envp++)
++                      cRetval++;
++
++              cRetval += 1;   /* Include the terminating NULL in the count. */
++      }
++
++      return cRetval;
++}
++
++/*
++ *  ======== PrependEnvp ========
++ *  Purpose:
++ *      Prepend an environment variable=value pair to the new envp array, and
++ *      copy in the existing var=value pairs in the old envp array.
++ */
++static char **PrependEnvp(char **newEnvp, char **envp, s32 cEnvp, s32 cNewEnvp,
++                       char *szVar)
++{
++      char **ppEnvp = newEnvp;
++
++      DBC_Require(newEnvp);
++
++      /* Prepend new environ var=value string */
++      *newEnvp++ = szVar;
++
++      /* Copy user's environment into our own. */
++      while (cEnvp--)
++              *newEnvp++ = *envp++;
++
++      /* Ensure NULL terminates the new environment strings array. */
++      if (cEnvp == 0)
++              *newEnvp = NULL;
++
++      return ppEnvp;
++}
++
++/*
++ *  ======== PROC_NotifyClients ========
++ *  Purpose:
++ *      Notify the processor the events.
++ */
++DSP_STATUS PROC_NotifyClients(DSP_HPROCESSOR hProc, u32 uEvents)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
++
++      DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
++      DBC_Require(IsValidProcEvent(uEvents));
++      DBC_Require(cRefs > 0);
++
++      NTFY_Notify(pProcObject->hNtfy, uEvents);
++      GT_0trace(PROC_DebugMask, GT_1CLASS,
++               "PROC_NotifyClients :Signaled. \n");
++
++      return status;
++}
++
++/*
++ *  ======== PROC_NotifyAllClients ========
++ *  Purpose:
++ *      Notify the processor the events. This includes notifying all clients
++ *      attached to a particulat DSP.
++ */
++DSP_STATUS PROC_NotifyAllClients(DSP_HPROCESSOR hProc, u32 uEvents)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
++
++      DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
++      DBC_Require(IsValidProcEvent(uEvents));
++      DBC_Require(cRefs > 0);
++
++      DEV_NotifyClients(pProcObject->hDevObject, uEvents);
++
++      GT_0trace(PROC_DebugMask, GT_1CLASS,
++               "PROC_NotifyAllClients :Signaled. \n");
++
++      return status;
++}
++
++/*
++ *  ======== PROC_GetProcessorId ========
++ *  Purpose:
++ *      Retrieves the processor ID.
++ */
++DSP_STATUS PROC_GetProcessorId(DSP_HPROCESSOR hProc, u32 *procID)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
++
++      *procID = pProcObject->uProcessor;
++
++      return status;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/pwr.c b/drivers/dsp/bridge/rmgr/pwr.c
+new file mode 100644
+index 0000000..50a3f79
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/pwr.c
+@@ -0,0 +1,184 @@
++/*
++ * pwr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== PWR.c ========
++ *  PWR API for controlling DSP power states.
++ *
++ *  Public Functions:
++ *      PWR_SleepDSP
++ *      PWR_WakeDSP
++ *
++ *! Revision History
++ *! ================
++ *! 18-Feb-2003 vp  Code review updates.
++ *! 18-Oct-2002 vp  Ported to Linux platform.
++ *! 22-May-2002 sg  Do PWR-to-IOCTL code mapping in PWR_SleepDSP.
++ *! 29-Apr-2002 sg  Initial.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/pwr.h>
++
++/*  ----------------------------------- Resource Manager */
++#include <dspbridge/devdefs.h>
++#include <dspbridge/drv.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/*  ----------------------------------- Link Driver */
++#include <dspbridge/wmdioctl.h>
++
++/*
++ *  ======== PWR_SleepDSP ========
++ *    Send command to DSP to enter sleep state.
++ */
++DSP_STATUS PWR_SleepDSP(IN CONST u32 sleepCode, IN CONST u32 timeout)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      struct WMD_DEV_CONTEXT *dwContext;
++      DSP_STATUS status = DSP_EFAIL;
++      struct DEV_OBJECT *hDevObject = NULL;
++      u32 ioctlcode = 0;
++      u32 arg = timeout;
++
++      for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++                        hDevObject != NULL;
++                      hDevObject =
++                              (struct DEV_OBJECT *)DRV_GetNextDevObject
++                              ((u32)hDevObject)) {
++              if (DSP_FAILED(DEV_GetWMDContext(hDevObject,
++                 (struct WMD_DEV_CONTEXT **)&dwContext))) {
++                      continue;
++              }
++              if (DSP_FAILED(DEV_GetIntfFxns(hDevObject,
++                 (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++                      continue;
++              }
++              if (sleepCode == PWR_DEEPSLEEP)
++                      ioctlcode = WMDIOCTL_DEEPSLEEP;
++              else if (sleepCode == PWR_EMERGENCYDEEPSLEEP)
++                      ioctlcode = WMDIOCTL_EMERGENCYSLEEP;
++              else
++                      status = DSP_EINVALIDARG;
++
++              if (status != DSP_EINVALIDARG) {
++                      status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++                               ioctlcode, (void *)&arg);
++              }
++      }
++      return status;
++}
++
++/*
++ *  ======== PWR_WakeDSP ========
++ *    Send command to DSP to wake it from sleep.
++ */
++DSP_STATUS PWR_WakeDSP(IN CONST u32 timeout)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      struct WMD_DEV_CONTEXT *dwContext;
++      DSP_STATUS status = DSP_EFAIL;
++      struct DEV_OBJECT *hDevObject = NULL;
++      u32 arg = timeout;
++
++      for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++           hDevObject != NULL;
++           hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
++                        ((u32)hDevObject)) {
++              if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++                 (struct WMD_DEV_CONTEXT **)&dwContext))) {
++                      if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++                         (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++                              status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++                                       WMDIOCTL_WAKEUP, (void *)&arg);
++                      }
++              }
++      }
++      return status;
++}
++
++/*
++ *  ======== PWR_PM_PreScale========
++ *    Sends pre-notification message to DSP.
++ */
++DSP_STATUS PWR_PM_PreScale(IN u16 voltage_domain, u32 level)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      struct WMD_DEV_CONTEXT *dwContext;
++      DSP_STATUS status = DSP_EFAIL;
++      struct DEV_OBJECT *hDevObject = NULL;
++      u32 arg[2];
++
++      arg[0] = voltage_domain;
++      arg[1] = level;
++
++      for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++          hDevObject != NULL;
++          hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
++                       ((u32)hDevObject)) {
++              if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++                 (struct WMD_DEV_CONTEXT **)&dwContext))) {
++                      if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++                         (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++                              status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++                                       WMDIOCTL_PRESCALE_NOTIFY,
++                                       (void *)&arg);
++                      }
++              }
++      }
++      return status;
++}
++
++/*
++ *  ======== PWR_PM_PostScale========
++ *    Sends post-notification message to DSP.
++ */
++DSP_STATUS PWR_PM_PostScale(IN u16 voltage_domain, u32 level)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      struct WMD_DEV_CONTEXT *dwContext;
++      DSP_STATUS status = DSP_EFAIL;
++      struct DEV_OBJECT *hDevObject = NULL;
++      u32 arg[2];
++
++      arg[0] = voltage_domain;
++      arg[1] = level;
++
++      for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++           hDevObject != NULL;
++           hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
++                        ((u32)hDevObject)) {
++              if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++                 (struct WMD_DEV_CONTEXT **)&dwContext))) {
++                      if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++                         (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++                              status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++                                      WMDIOCTL_POSTSCALE_NOTIFY,
++                                      (void *)&arg);
++                      }
++              }
++      }
++      return status;
++
++}
++
++
+diff --git a/drivers/dsp/bridge/rmgr/rmm.c b/drivers/dsp/bridge/rmgr/rmm.c
+new file mode 100644
+index 0000000..575f675
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/rmm.c
+@@ -0,0 +1,604 @@
++/*
++ * rmm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== rmm.c ========
++ *  Description:
++ *
++ *  This memory manager provides general heap management and arbitrary
++ *  alignment for any number of memory segments.
++ *
++ *  Notes:
++ *
++ *  Memory blocks are allocated from the end of the first free memory
++ *  block large enough to satisfy the request.  Alignment requirements
++ *  are satisfied by "sliding" the block forward until its base satisfies
++ *  the alignment specification; if this is not possible then the next
++ *  free block large enough to hold the request is tried.
++ *
++ *  Since alignment can cause the creation of a new free block - the
++ *  unused memory formed between the start of the original free block
++ *  and the start of the allocated block - the memory manager must free
++ *  this memory to prevent a memory leak.
++ *
++ *  Overlay memory is managed by reserving through RMM_alloc, and freeing
++ *  it through RMM_free. The memory manager prevents DSP code/data that is
++ *  overlayed from being overwritten as long as the memory it runs at has
++ *  been allocated, and not yet freed.
++ *
++ *! Revision History
++ *! ================
++ *! 18-Feb-2003 vp  Code review updates.
++ *! 18-Oct-2002 vp  Ported to Linux Platform.
++ *! 24-Sep-2002 map Updated from Code Review
++ *! 25-Jun-2002 jeh     Free from segid passed to RMM_free().
++ *! 24-Apr-2002 jeh     Determine segid based on address in RMM_free(). (No way
++ *!                     to keep track of segid with dynamic loader library.)
++ *! 16-Oct-2001 jeh     Based on gen tree rm.c. Added support for overlays.
++ */
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/rmm.h>
++
++#define RMM_TARGSIGNATURE   0x544d4d52        /* "TMMR" */
++
++/*
++ *  ======== RMM_Header ========
++ *  This header is used to maintain a list of free memory blocks.
++ */
++struct RMM_Header {
++      struct RMM_Header *next;        /* form a free memory link list */
++      u32 size;               /* size of the free memory */
++      u32 addr;               /* DSP address of memory block */
++} ;
++
++/*
++ *  ======== RMM_OvlySect ========
++ *  Keeps track of memory occupied by overlay section.
++ */
++struct RMM_OvlySect {
++      struct LST_ELEM listElem;
++      u32 addr;               /* Start of memory section */
++      u32 size;               /* Length (target MAUs) of section */
++      s32 page;               /* Memory page */
++};
++
++/*
++ *  ======== RMM_TargetObj ========
++ */
++struct RMM_TargetObj {
++      u32 dwSignature;
++      struct RMM_Segment *segTab;
++      struct RMM_Header **freeList;
++      u32 numSegs;
++      struct LST_LIST *ovlyList;      /* List of overlay memory in use */
++};
++
++#if GT_TRACE
++static struct GT_Mask RMM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs;             /* module reference count */
++
++static bool allocBlock(struct RMM_TargetObj *target, u32 segid, u32 size,
++                    u32 align, u32 *dspAddr);
++static bool freeBlock(struct RMM_TargetObj *target, u32 segid, u32 addr,
++                   u32 size);
++
++/*
++ *  ======== RMM_alloc ========
++ */
++DSP_STATUS RMM_alloc(struct RMM_TargetObj *target, u32 segid, u32 size,
++                  u32 align, u32 *dspAddr, bool reserve)
++{
++      struct RMM_OvlySect *sect;
++      struct RMM_OvlySect *prevSect = NULL;
++      struct RMM_OvlySect *newSect;
++      u32 addr;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
++      DBC_Require(dspAddr != NULL);
++      DBC_Require(size > 0);
++      DBC_Require(reserve || (target->numSegs > 0));
++      DBC_Require(cRefs > 0);
++
++      GT_6trace(RMM_debugMask, GT_ENTER,
++               "RMM_alloc(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
++               "0x%lx, 0x%lx)\n", target, segid, size, align, dspAddr,
++               reserve);
++      if (!reserve) {
++              if (!allocBlock(target, segid, size, align, dspAddr)) {
++                      status = DSP_EMEMORY;
++              } else {
++                      /* Increment the number of allocated blocks in this
++                       * segment */
++                      target->segTab[segid].number++;
++              }
++              goto func_end;
++      }
++      /* An overlay section - See if block is already in use. If not,
++       * insert into the list in ascending address size.  */
++      addr = *dspAddr;
++      sect = (struct RMM_OvlySect *)LST_First(target->ovlyList);
++      /*  Find place to insert new list element. List is sorted from
++       *  smallest to largest address. */
++      while (sect != NULL) {
++              if (addr <= sect->addr) {
++                      /* Check for overlap with sect */
++                      if ((addr + size > sect->addr) || (prevSect &&
++                         (prevSect->addr + prevSect->size > addr))) {
++                              status = DSP_EOVERLAYMEMORY;
++                      }
++                      break;
++              }
++              prevSect = sect;
++              sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList,
++                      (struct LST_ELEM *)sect);
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* No overlap - allocate list element for new section. */
++              newSect = MEM_Calloc(sizeof(struct RMM_OvlySect), MEM_PAGED);
++              if (newSect == NULL) {
++                      status = DSP_EMEMORY;
++              } else {
++                      LST_InitElem((struct LST_ELEM *)newSect);
++                      newSect->addr = addr;
++                      newSect->size = size;
++                      newSect->page = segid;
++                      if (sect == NULL) {
++                              /* Put new section at the end of the list */
++                              LST_PutTail(target->ovlyList,
++                                         (struct LST_ELEM *)newSect);
++                      } else {
++                              /* Put new section just before sect */
++                              LST_InsertBefore(target->ovlyList,
++                                              (struct LST_ELEM *)newSect,
++                                              (struct LST_ELEM *)sect);
++                      }
++              }
++      }
++func_end:
++      return status;
++}
++
++/*
++ *  ======== RMM_create ========
++ */
++DSP_STATUS RMM_create(struct RMM_TargetObj **pTarget,
++                   struct RMM_Segment segTab[], u32 numSegs)
++{
++      struct RMM_Header *hptr;
++      struct RMM_Segment *sptr, *tmp;
++      struct RMM_TargetObj *target;
++      s32 i;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(pTarget != NULL);
++      DBC_Require(numSegs == 0 || segTab != NULL);
++
++      GT_3trace(RMM_debugMask, GT_ENTER,
++               "RMM_create(0x%lx, 0x%lx, 0x%lx)\n",
++               pTarget, segTab, numSegs);
++
++      /* Allocate DBL target object */
++      MEM_AllocObject(target, struct RMM_TargetObj, RMM_TARGSIGNATURE);
++
++      if (target == NULL) {
++              GT_0trace(RMM_debugMask, GT_6CLASS,
++                       "RMM_create: Memory allocation failed\n");
++              status = DSP_EMEMORY;
++      }
++      if (DSP_FAILED(status))
++              goto func_cont;
++
++      target->numSegs = numSegs;
++      if (!(numSegs > 0))
++              goto func_cont;
++
++      /* Allocate the memory for freelist from host's memory */
++      target->freeList = MEM_Calloc(numSegs * sizeof(struct RMM_Header *),
++                                   MEM_PAGED);
++      if (target->freeList == NULL) {
++              GT_0trace(RMM_debugMask, GT_6CLASS,
++                       "RMM_create: Memory allocation failed\n");
++              status = DSP_EMEMORY;
++      } else {
++              /* Allocate headers for each element on the free list */
++              for (i = 0; i < (s32) numSegs; i++) {
++                      target->freeList[i] =
++                                      MEM_Calloc(sizeof(struct RMM_Header),
++                                      MEM_PAGED);
++                      if (target->freeList[i] == NULL) {
++                              GT_0trace(RMM_debugMask, GT_6CLASS,
++                                       "RMM_create: Memory "
++                                       "allocation failed\n");
++                              status = DSP_EMEMORY;
++                              break;
++                      }
++              }
++              /* Allocate memory for initial segment table */
++              target->segTab = MEM_Calloc(numSegs *
++                               sizeof(struct RMM_Segment), MEM_PAGED);
++              if (target->segTab == NULL) {
++                      GT_0trace(RMM_debugMask, GT_6CLASS,
++                               "RMM_create: Memory allocation failed\n");
++                      status = DSP_EMEMORY;
++              } else {
++                      /* Initialize segment table and free list */
++                      sptr = target->segTab;
++                      for (i = 0, tmp = segTab; numSegs > 0; numSegs--, i++) {
++                              *sptr = *tmp;
++                              hptr = target->freeList[i];
++                              hptr->addr = tmp->base;
++                              hptr->size = tmp->length;
++                              hptr->next = NULL;
++                              tmp++;
++                              sptr++;
++                      }
++              }
++      }
++func_cont:
++      /* Initialize overlay memory list */
++      if (DSP_SUCCEEDED(status)) {
++              target->ovlyList = LST_Create();
++              if (target->ovlyList == NULL) {
++                      GT_0trace(RMM_debugMask, GT_6CLASS,
++                               "RMM_create: Memory allocation failed\n");
++                      status = DSP_EMEMORY;
++              }
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              *pTarget = target;
++      } else {
++              *pTarget = NULL;
++              if (target)
++                      RMM_delete(target);
++
++      }
++
++      DBC_Ensure((DSP_SUCCEEDED(status) && MEM_IsValidHandle((*pTarget),
++                RMM_TARGSIGNATURE)) || (DSP_FAILED(status) && *pTarget ==
++                NULL));
++
++      return status;
++}
++
++/*
++ *  ======== RMM_delete ========
++ */
++void RMM_delete(struct RMM_TargetObj *target)
++{
++      struct RMM_OvlySect *pSect;
++      struct RMM_Header *hptr;
++      struct RMM_Header *next;
++      u32 i;
++
++      DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
++
++      GT_1trace(RMM_debugMask, GT_ENTER, "RMM_delete(0x%lx)\n", target);
++
++      if (target->segTab != NULL)
++              MEM_Free(target->segTab);
++
++      if (target->ovlyList) {
++              while ((pSect = (struct RMM_OvlySect *)LST_GetHead
++                    (target->ovlyList))) {
++                      MEM_Free(pSect);
++              }
++              DBC_Assert(LST_IsEmpty(target->ovlyList));
++              LST_Delete(target->ovlyList);
++      }
++
++      if (target->freeList != NULL) {
++              /* Free elements on freelist */
++              for (i = 0; i < target->numSegs; i++) {
++                      hptr = next = target->freeList[i];
++                      while (next) {
++                              hptr = next;
++                              next = hptr->next;
++                              MEM_Free(hptr);
++                      }
++              }
++              MEM_Free(target->freeList);
++      }
++
++      MEM_FreeObject(target);
++}
++
++/*
++ *  ======== RMM_exit ========
++ */
++void RMM_exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      cRefs--;
++
++      GT_1trace(RMM_debugMask, GT_5CLASS, "RMM_exit() ref count: 0x%x\n",
++               cRefs);
++
++      if (cRefs == 0)
++              MEM_Exit();
++
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== RMM_free ========
++ */
++bool RMM_free(struct RMM_TargetObj *target, u32 segid, u32 addr, u32 size,
++      bool reserved)
++
++{
++      struct RMM_OvlySect *sect;
++      bool retVal = true;
++
++      DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
++
++      DBC_Require(reserved || segid < target->numSegs);
++      DBC_Require(reserved || (addr >= target->segTab[segid].base &&
++                 (addr + size) <= (target->segTab[segid].base +
++                 target->segTab[segid].length)));
++
++      GT_5trace(RMM_debugMask, GT_ENTER,
++               "RMM_free(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
++               "0x%lx)\n", target, segid, addr, size, reserved);
++      /*
++       *  Free or unreserve memory.
++       */
++      if (!reserved) {
++              retVal = freeBlock(target, segid, addr, size);
++              if (retVal)
++                      target->segTab[segid].number--;
++
++      } else {
++              /* Unreserve memory */
++              sect = (struct RMM_OvlySect *)LST_First(target->ovlyList);
++              while (sect != NULL) {
++                      if (addr == sect->addr) {
++                              DBC_Assert(size == sect->size);
++                              /* Remove from list */
++                              LST_RemoveElem(target->ovlyList,
++                                            (struct LST_ELEM *)sect);
++                              MEM_Free(sect);
++                              break;
++                      }
++                      sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList,
++                             (struct LST_ELEM *)sect);
++              }
++              if (sect == NULL)
++                      retVal = false;
++
++      }
++      return retVal;
++}
++
++/*
++ *  ======== RMM_init ========
++ */
++bool RMM_init(void)
++{
++      bool retVal = true;
++
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++              DBC_Assert(!RMM_debugMask.flags);
++              GT_create(&RMM_debugMask, "RM");        /* "RM" for RMm */
++
++              retVal = MEM_Init();
++
++              if (!retVal)
++                      MEM_Exit();
++
++      }
++
++      if (retVal)
++              cRefs++;
++
++      GT_1trace(RMM_debugMask, GT_5CLASS,
++               "RMM_init(), ref count:  0x%x\n",
++               cRefs);
++
++      DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
++
++      return retVal;
++}
++
++/*
++ *  ======== RMM_stat ========
++ */
++bool RMM_stat(struct RMM_TargetObj *target, enum DSP_MEMTYPE segid,
++           struct DSP_MEMSTAT *pMemStatBuf)
++{
++      struct RMM_Header *head;
++      bool retVal = false;
++      u32 maxFreeSize = 0;
++      u32 totalFreeSize = 0;
++      u32 freeBlocks = 0;
++
++      DBC_Require(pMemStatBuf != NULL);
++      DBC_Assert(target != NULL);
++
++      if ((u32) segid < target->numSegs) {
++              head = target->freeList[segid];
++
++              /* Collect data from freeList */
++              while (head != NULL) {
++                      maxFreeSize = max(maxFreeSize, head->size);
++                      totalFreeSize += head->size;
++                      freeBlocks++;
++                      head = head->next;
++              }
++
++              /* ulSize */
++              pMemStatBuf->ulSize = target->segTab[segid].length;
++
++              /* ulNumFreeBlocks */
++              pMemStatBuf->ulNumFreeBlocks = freeBlocks;
++
++              /* ulTotalFreeSize */
++              pMemStatBuf->ulTotalFreeSize = totalFreeSize;
++
++              /* ulLenMaxFreeBlock */
++              pMemStatBuf->ulLenMaxFreeBlock = maxFreeSize;
++
++              /* ulNumAllocBlocks */
++              pMemStatBuf->ulNumAllocBlocks = target->segTab[segid].number;
++
++              retVal = true;
++      }
++
++      return retVal;
++}
++
++/*
++ *  ======== balloc ========
++ *  This allocation function allocates memory from the lowest addresses
++ *  first.
++ */
++static bool allocBlock(struct RMM_TargetObj *target, u32 segid, u32 size,
++                    u32 align, u32 *dspAddr)
++{
++      struct RMM_Header *head;
++      struct RMM_Header *prevhead = NULL;
++      struct RMM_Header *next;
++      u32 tmpalign;
++      u32 alignbytes;
++      u32 hsize;
++      u32 allocsize;
++      u32 addr;
++
++      alignbytes = (align == 0) ? 1 : align;
++      prevhead = NULL;
++      head = target->freeList[segid];
++
++      do {
++              hsize = head->size;
++              next = head->next;
++
++              addr = head->addr;      /* alloc from the bottom */
++
++              /* align allocation */
++              (tmpalign = (u32) addr % alignbytes);
++              if (tmpalign != 0)
++                      tmpalign = alignbytes - tmpalign;
++
++              allocsize = size + tmpalign;
++
++              if (hsize >= allocsize) {       /* big enough */
++                      if (hsize == allocsize && prevhead != NULL) {
++                              prevhead->next = next;
++                              MEM_Free(head);
++                      } else {
++                              head->size = hsize - allocsize;
++                              head->addr += allocsize;
++                      }
++
++                      /* free up any hole created by alignment */
++                      if (tmpalign)
++                              freeBlock(target, segid, addr, tmpalign);
++
++                      *dspAddr = addr + tmpalign;
++                      return true;
++              }
++
++              prevhead = head;
++              head = next;
++
++      } while (head != NULL);
++
++      return false;
++}
++
++/*
++ *  ======== freeBlock ========
++ *  TO DO: freeBlock() allocates memory, which could result in failure.
++ *  Could allocate an RMM_Header in RMM_alloc(), to be kept in a pool.
++ *  freeBlock() could use an RMM_Header from the pool, freeing as blocks
++ *  are coalesced.
++ */
++static bool freeBlock(struct RMM_TargetObj *target, u32 segid, u32 addr,
++                   u32 size)
++{
++      struct RMM_Header *head;
++      struct RMM_Header *thead;
++      struct RMM_Header *rhead;
++      bool retVal = true;
++
++      /* Create a memory header to hold the newly free'd block. */
++      rhead = MEM_Calloc(sizeof(struct RMM_Header), MEM_PAGED);
++      if (rhead == NULL) {
++              retVal = false;
++      } else {
++              /* search down the free list to find the right place for addr */
++              head = target->freeList[segid];
++
++              if (addr >= head->addr) {
++                      while (head->next != NULL && addr > head->next->addr)
++                              head = head->next;
++
++                      thead = head->next;
++
++                      head->next = rhead;
++                      rhead->next = thead;
++                      rhead->addr = addr;
++                      rhead->size = size;
++              } else {
++                      *rhead = *head;
++                      head->next = rhead;
++                      head->addr = addr;
++                      head->size = size;
++                      thead = rhead->next;
++              }
++
++              /* join with upper block, if possible */
++              if (thead != NULL && (rhead->addr + rhead->size) ==
++                 thead->addr) {
++                      head->next = rhead->next;
++                      thead->size = size + thead->size;
++                      thead->addr = addr;
++                      MEM_Free(rhead);
++                      rhead = thead;
++              }
++
++              /* join with the lower block, if possible */
++              if ((head->addr + head->size) == rhead->addr) {
++                      head->next = rhead->next;
++                      head->size = head->size + rhead->size;
++                      MEM_Free(rhead);
++              }
++      }
++
++      return retVal;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/strm.c b/drivers/dsp/bridge/rmgr/strm.c
+new file mode 100644
+index 0000000..bd55fd3
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/strm.c
+@@ -0,0 +1,1066 @@
++/*
++ * strm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== strm.c ========
++ *  Description:
++ *      DSP/BIOS Bridge Stream Manager.
++ *
++ *  Public Functions:
++ *      STRM_AllocateBuffer
++ *      STRM_Close
++ *      STRM_Create
++ *      STRM_Delete
++ *      STRM_Exit
++ *      STRM_FreeBuffer
++ *      STRM_GetEventHandle
++ *      STRM_GetInfo
++ *      STRM_Idle
++ *      STRM_Init
++ *      STRM_Issue
++ *      STRM_Open
++ *      STRM_PrepareBuffer
++ *      STRM_Reclaim
++ *      STRM_RegisterNotify
++ *      STRM_Select
++ *      STRM_UnprepareBuffer
++ *
++ *  Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 18-Feb-2003 vp  Code review updates.
++ *! 18-Oct-2002 vp  Ported to Linux platform.
++ *! 13-Mar-2002 map    pStrm init'd to NULL in STRM_Open to prevent error
++ *! 12-Mar-2002 map Changed return var to WSX "wStatus" instead of "status"
++ *!               in DEV and CMM function calls to avoid confusion.
++ *!               Return DSP_SOK instead of S_OK from API fxns.
++ *! 12-Mar-2002 map    Changed FAILED(..) to DSP_FAILED(..)
++ *! 25-Jan-2002 ag  Allow neg seg ids(e.g. DSP_SHMSEG0) to denote SM.
++ *! 15-Nov-2001 ag  Added STRMMODE & SM for DMA/ZCopy streaming.
++ *!            Changed DSP_STREAMINFO to STRM_INFO in STRM_GetInfo().
++ *!            Use strm timeout value for dma flush timeout.
++ *! 09-May-2001 jeh Code review cleanup.
++ *! 06-Feb-2001 kc  Updated DBC_Ensure in STRM_Select to check timeout.
++ *! 23-Oct-2000 jeh Allow NULL STRM_ATTRS passed to STRM_Open() for DLL
++ *!            tests to pass.
++ *! 25-Sep-2000 jeh Created.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/*  ----------------------------------- Mini Driver */
++#include <dspbridge/wmd.h>
++
++/*  ----------------------------------- Resource Manager */
++#include <dspbridge/nodepriv.h>
++
++/*  ----------------------------------- Others */
++#include <dspbridge/cmm.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/strm.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/cfg.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++#define STRM_SIGNATURE      0x4d525453        /* "MRTS" */
++#define STRMMGR_SIGNATURE   0x5254534d        /* "RTSM" */
++
++#define DEFAULTTIMEOUT      10000
++#define DEFAULTNUMBUFS      2
++
++/*
++ *  ======== STRM_MGR ========
++ *  The STRM_MGR contains device information needed to open the underlying
++ *  channels of a stream.
++ */
++struct STRM_MGR {
++      u32 dwSignature;
++      struct DEV_OBJECT *hDev;        /* Device for this processor */
++      struct CHNL_MGR *hChnlMgr;      /* Channel manager */
++      struct WMD_DRV_INTERFACE *pIntfFxns;    /* Function interface to WMD */
++      struct SYNC_CSOBJECT *hSync;    /* For critical sections */
++} ;
++
++/*
++ *  ======== STRM_OBJECT ========
++ *  This object is allocated in STRM_Open().
++ */
++ struct STRM_OBJECT {
++      u32 dwSignature;
++      struct STRM_MGR *hStrmMgr;
++      struct CHNL_OBJECT *hChnl;
++      u32 uDir;               /* DSP_TONODE or DSP_FROMNODE */
++      u32 uTimeout;
++      u32 uNumBufs;           /* Max # of bufs allowed in stream */
++      u32 uNBufsInStrm;       /* Current # of bufs in stream */
++      u32 ulNBytes;           /* bytes transferred since idled */
++      enum DSP_STREAMSTATE strmState; /* STREAM_IDLE, STREAM_READY, ... */
++      HANDLE hUserEvent;      /* Saved for STRM_GetInfo() */
++      enum DSP_STRMMODE lMode;        /* STRMMODE_[PROCCOPY][ZEROCOPY]... */
++      u32 uDMAChnlId; /* DMA chnl id */
++      u32 uDMAPriority;       /* DMA priority:DMAPRI_[LOW][HIGH] */
++      u32 uSegment;           /* >0 is SM segment.=0 is local heap */
++      u32 uAlignment; /* Alignment for stream bufs */
++      struct CMM_XLATOROBJECT *hXlator;  /* Stream's SM address translator */
++} ;
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask STRM_debugMask = { NULL, NULL };        /* GT trace variable */
++#endif
++static u32 cRefs;             /* module reference count */
++
++/*  ----------------------------------- Function Prototypes */
++static DSP_STATUS DeleteStrm(struct STRM_OBJECT *hStrm);
++static void DeleteStrmMgr(struct STRM_MGR *hStrmMgr);
++
++/*
++ *  ======== STRM_AllocateBuffer ========
++ *  Purpose:
++ *      Allocates buffers for a stream.
++ */
++DSP_STATUS STRM_AllocateBuffer(struct STRM_OBJECT *hStrm, u32 uSize,
++                              OUT u8 **apBuffer, u32 uNumBufs)
++{
++      DSP_STATUS status = DSP_SOK;
++      u32 uAllocated = 0;
++      u32 i;
++      #ifndef RES_CLEANUP_DISABLE
++      DSP_STATUS res_status = DSP_SOK;
++       u32                  hProcess;
++      HANDLE       pCtxt = NULL;
++      HANDLE       hDrvObject;
++      HANDLE hSTRMRes;
++      #endif
++      DBC_Require(cRefs > 0);
++      DBC_Require(apBuffer != NULL);
++
++      GT_4trace(STRM_debugMask, GT_ENTER, "STRM_AllocateBuffer: hStrm: 0x%x\t"
++               "uSize: 0x%x\tapBuffer: 0x%x\tuNumBufs: 0x%x\n",
++               hStrm, uSize, apBuffer, uNumBufs);
++      if (MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++              /*
++               * Allocate from segment specified at time of stream open.
++               */
++              if (uSize == 0)
++                      status = DSP_ESIZE;
++
++      }
++      if (DSP_FAILED(status)) {
++              status = DSP_EHANDLE;
++              goto func_end;
++      }
++      for (i = 0; i < uNumBufs; i++) {
++              DBC_Assert(hStrm->hXlator != NULL);
++              (void)CMM_XlatorAllocBuf(hStrm->hXlator, &apBuffer[i], uSize);
++              if (apBuffer[i] == NULL) {
++                      GT_0trace(STRM_debugMask, GT_7CLASS,
++                               "STRM_AllocateBuffer: "
++                               "DSP_FAILED to alloc shared memory.\n");
++                      status = DSP_EMEMORY;
++                      uAllocated = i;
++                      break;
++              }
++      }
++      if (DSP_FAILED(status))
++              STRM_FreeBuffer(hStrm, apBuffer, uAllocated);
++
++#ifndef RES_CLEANUP_DISABLE
++      if (DSP_FAILED(status))
++              goto func_end;
++
++       /* Return PID instead of process handle */
++       hProcess = current->pid;
++
++      res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++      if (DSP_FAILED(res_status))
++              goto func_end;
++
++       DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDrvObject,
++                       &pCtxt, NULL, 0);
++      if (pCtxt != NULL) {
++              if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pCtxt) !=
++                 DSP_ENOTFOUND) {
++                      DRV_ProcUpdateSTRMRes(uNumBufs, hSTRMRes, pCtxt);
++              }
++      }
++#endif
++func_end:
++      return status;
++}
++
++/*
++ *  ======== STRM_Close ========
++ *  Purpose:
++ *      Close a stream opened with STRM_Open().
++ */
++DSP_STATUS STRM_Close(struct STRM_OBJECT *hStrm)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      struct CHNL_INFO chnlInfo;
++      DSP_STATUS status = DSP_SOK;
++
++
++#ifndef RES_CLEANUP_DISABLE
++    u32                      hProcess;
++    HANDLE          pCtxt = NULL;
++    HANDLE          hDrvObject;
++    HANDLE          hSTRMRes;
++    DSP_STATUS          res_status = DSP_SOK;
++#endif
++
++
++      DBC_Require(cRefs > 0);
++
++      GT_1trace(STRM_debugMask, GT_ENTER, "STRM_Close: hStrm: 0x%x\n", hStrm);
++
++      if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++              status = DSP_EHANDLE;
++      } else {
++              /* Have all buffers been reclaimed? If not, return
++               * DSP_EPENDING */
++              pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++              status = (*pIntfFxns->pfnChnlGetInfo) (hStrm->hChnl, &chnlInfo);
++              DBC_Assert(DSP_SUCCEEDED(status));
++
++              if (chnlInfo.cIOCs > 0 || chnlInfo.cIOReqs > 0) {
++                      status = DSP_EPENDING;
++              } else {
++
++                      status = DeleteStrm(hStrm);
++
++                      if (DSP_FAILED(status)) {
++                              /* we already validated the handle. */
++                              DBC_Assert(status != DSP_EHANDLE);
++
++                              /* make sure we return a documented result */
++                              status = DSP_EFAIL;
++                      }
++              }
++      }
++#ifndef RES_CLEANUP_DISABLE
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      /* Update the node and stream resource status */
++       /* Return PID instead of process handle */
++       hProcess = current->pid;
++
++      res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++      if (DSP_FAILED(res_status))
++              goto func_end;
++
++       DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDrvObject,
++                       &pCtxt, NULL, 0);
++      if (pCtxt != NULL) {
++              if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pCtxt) !=
++                 DSP_ENOTFOUND) {
++                      DRV_ProcRemoveSTRMResElement(hSTRMRes, pCtxt);
++              }
++      }
++func_end:
++#endif
++      DBC_Ensure(status == DSP_SOK || status == DSP_EHANDLE ||
++                status == DSP_EPENDING || status == DSP_EFAIL);
++
++      return status;
++}
++
++/*
++ *  ======== STRM_Create ========
++ *  Purpose:
++ *      Create a STRM manager object.
++ */
++DSP_STATUS STRM_Create(OUT struct STRM_MGR **phStrmMgr, struct DEV_OBJECT *hDev)
++{
++      struct STRM_MGR *pStrmMgr;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(phStrmMgr != NULL);
++      DBC_Require(hDev != NULL);
++
++      GT_2trace(STRM_debugMask, GT_ENTER, "STRM_Create: phStrmMgr: "
++               "0x%x\thDev: 0x%x\n", phStrmMgr, hDev);
++      *phStrmMgr = NULL;
++      /* Allocate STRM manager object */
++      MEM_AllocObject(pStrmMgr, struct STRM_MGR, STRMMGR_SIGNATURE);
++      if (pStrmMgr == NULL) {
++              status = DSP_EMEMORY;
++              GT_0trace(STRM_debugMask, GT_6CLASS, "STRM_Create: "
++                       "MEM_AllocObject() failed!\n ");
++      } else {
++              pStrmMgr->hDev = hDev;
++      }
++      /* Get Channel manager and WMD function interface */
++      if (DSP_SUCCEEDED(status)) {
++              status = DEV_GetChnlMgr(hDev, &(pStrmMgr->hChnlMgr));
++              if (DSP_SUCCEEDED(status)) {
++                      (void) DEV_GetIntfFxns(hDev, &(pStrmMgr->pIntfFxns));
++                      DBC_Assert(pStrmMgr->pIntfFxns != NULL);
++              } else {
++                      GT_1trace(STRM_debugMask, GT_6CLASS, "STRM_Create: "
++                               "Failed to get channel manager! status = "
++                               "0x%x\n", status);
++              }
++      }
++      if (DSP_SUCCEEDED(status))
++              status = SYNC_InitializeCS(&pStrmMgr->hSync);
++
++      if (DSP_SUCCEEDED(status))
++              *phStrmMgr = pStrmMgr;
++      else
++              DeleteStrmMgr(pStrmMgr);
++
++      DBC_Ensure(DSP_SUCCEEDED(status) &&
++                (MEM_IsValidHandle((*phStrmMgr), STRMMGR_SIGNATURE) ||
++                (DSP_FAILED(status) && *phStrmMgr == NULL)));
++
++      return status;
++}
++
++/*
++ *  ======== STRM_Delete ========
++ *  Purpose:
++ *      Delete the STRM Manager Object.
++ */
++void STRM_Delete(struct STRM_MGR *hStrmMgr)
++{
++      DBC_Require(cRefs > 0);
++      DBC_Require(MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE));
++
++      GT_1trace(STRM_debugMask, GT_ENTER, "STRM_Delete: hStrmMgr: 0x%x\n",
++               hStrmMgr);
++
++      DeleteStrmMgr(hStrmMgr);
++
++      DBC_Ensure(!MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE));
++}
++
++/*
++ *  ======== STRM_Exit ========
++ *  Purpose:
++ *      Discontinue usage of STRM module.
++ */
++void STRM_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      cRefs--;
++
++      GT_1trace(STRM_debugMask, GT_5CLASS,
++               "Entered STRM_Exit, ref count:  0x%x\n", cRefs);
++
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== STRM_FreeBuffer ========
++ *  Purpose:
++ *      Frees the buffers allocated for a stream.
++ */
++DSP_STATUS STRM_FreeBuffer(struct STRM_OBJECT *hStrm, u8 **apBuffer,
++                        u32 uNumBufs)
++{
++      DSP_STATUS status = DSP_SOK;
++      u32 i = 0;
++
++      #ifndef RES_CLEANUP_DISABLE
++      DSP_STATUS res_status = DSP_SOK;
++       u32                  hProcess;
++      HANDLE       pCtxt = NULL;
++      HANDLE       hDrvObject;
++      HANDLE              hSTRMRes = NULL;
++      #endif
++      DBC_Require(cRefs > 0);
++      DBC_Require(apBuffer != NULL);
++
++      GT_3trace(STRM_debugMask, GT_ENTER, "STRM_FreeBuffer: hStrm: 0x%x\t"
++               "apBuffer: 0x%x\tuNumBufs: 0x%x\n", hStrm, apBuffer, uNumBufs);
++
++      if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE))
++              status = DSP_EHANDLE;
++
++      if (DSP_SUCCEEDED(status)) {
++              for (i = 0; i < uNumBufs; i++) {
++                      DBC_Assert(hStrm->hXlator != NULL);
++                      status = CMM_XlatorFreeBuf(hStrm->hXlator, apBuffer[i]);
++                      if (DSP_FAILED(status)) {
++                              GT_0trace(STRM_debugMask, GT_7CLASS,
++                                       "STRM_FreeBuffer: DSP_FAILED"
++                                       " to free shared memory.\n");
++                              break;
++                      }
++                      apBuffer[i] = NULL;
++              }
++      }
++#ifndef RES_CLEANUP_DISABLE
++      /* Update the node and stream resource status */
++       /* Return PID instead of process handle */
++       hProcess = current->pid;
++
++      res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++      if (DSP_SUCCEEDED(res_status)) {
++               DRV_GetProcContext(hProcess,
++                               (struct DRV_OBJECT *)hDrvObject, &pCtxt,
++                               NULL, 0);
++              if (pCtxt != NULL) {
++                      if (DRV_GetSTRMResElement(hStrm, hSTRMRes, pCtxt) !=
++                         DSP_ENOTFOUND) {
++                              DRV_ProcUpdateSTRMRes(uNumBufs-i, hSTRMRes,
++                                                   pCtxt);
++                      }
++              }
++      }
++#endif
++      return status;
++}
++
++/*
++ *  ======== STRM_GetInfo ========
++ *  Purpose:
++ *      Retrieves information about a stream.
++ */
++DSP_STATUS STRM_GetInfo(struct STRM_OBJECT *hStrm,
++                      OUT struct STRM_INFO *pStreamInfo,
++                      u32 uStreamInfoSize)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      struct CHNL_INFO chnlInfo;
++      DSP_STATUS status = DSP_SOK;
++      void *pVirtBase = NULL; /* NULL if no SM used */
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pStreamInfo != NULL);
++      DBC_Require(uStreamInfoSize >= sizeof(struct STRM_INFO));
++
++      GT_3trace(STRM_debugMask, GT_ENTER, "STRM_GetInfo: hStrm: 0x%x\t"
++               "pStreamInfo: 0x%x\tuStreamInfoSize: 0x%x\n", hStrm,
++               pStreamInfo, uStreamInfoSize);
++      if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++              status = DSP_EHANDLE;
++      } else {
++              if (uStreamInfoSize < sizeof(struct STRM_INFO)) {
++                      /* size of users info */
++                      status = DSP_ESIZE;
++              }
++      }
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++      status = (*pIntfFxns->pfnChnlGetInfo) (hStrm->hChnl, &chnlInfo);
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      if (hStrm->hXlator) {
++              /* We have a translator */
++              DBC_Assert(hStrm->uSegment > 0);
++              CMM_XlatorInfo(hStrm->hXlator, (u8 **)&pVirtBase, 0,
++                            hStrm->uSegment, false);
++      }
++      pStreamInfo->uSegment = hStrm->uSegment;
++      pStreamInfo->lMode = hStrm->lMode;
++      pStreamInfo->pVirtBase = pVirtBase;
++      pStreamInfo->pUser->uNumberBufsAllowed = hStrm->uNumBufs;
++      pStreamInfo->pUser->uNumberBufsInStream = chnlInfo.cIOCs +
++                                               chnlInfo.cIOReqs;
++      /* # of bytes transferred since last call to DSPStream_Idle() */
++      pStreamInfo->pUser->ulNumberBytes = chnlInfo.cPosition;
++      pStreamInfo->pUser->hSyncObjectHandle = chnlInfo.hEvent;
++      /* Determine stream state based on channel state and info */
++      if (chnlInfo.dwState & CHNL_STATEEOS) {
++              pStreamInfo->pUser->ssStreamState = STREAM_DONE;
++      } else {
++              if (chnlInfo.cIOCs > 0)
++                      pStreamInfo->pUser->ssStreamState = STREAM_READY;
++              else if (chnlInfo.cIOReqs > 0)
++                      pStreamInfo->pUser->ssStreamState = STREAM_PENDING;
++              else
++                      pStreamInfo->pUser->ssStreamState = STREAM_IDLE;
++
++      }
++func_end:
++      return status;
++}
++
++/*
++ *  ======== STRM_Idle ========
++ *  Purpose:
++ *      Idles a particular stream.
++ */
++DSP_STATUS STRM_Idle(struct STRM_OBJECT *hStrm, bool fFlush)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++
++      GT_2trace(STRM_debugMask, GT_ENTER, "STRM_Idle: hStrm: 0x%x\t"
++               "fFlush: 0x%x\n", hStrm, fFlush);
++
++      if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++              status = DSP_EHANDLE;
++      } else {
++              pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++              status = (*pIntfFxns->pfnChnlIdle) (hStrm->hChnl,
++                       hStrm->uTimeout, fFlush);
++      }
++      return status;
++}
++
++/*
++ *  ======== STRM_Init ========
++ *  Purpose:
++ *      Initialize the STRM module.
++ */
++bool STRM_Init(void)
++{
++      bool fRetVal = true;
++
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++#if GT_TRACE
++              DBC_Assert(!STRM_debugMask.flags);
++              GT_create(&STRM_debugMask, "ST");       /* "ST" for STrm */
++#endif
++      }
++
++      if (fRetVal)
++              cRefs++;
++
++      GT_1trace(STRM_debugMask, GT_5CLASS, "STRM_Init(), ref count: 0x%x\n",
++               cRefs);
++
++      DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
++
++      return fRetVal;
++}
++
++/*
++ *  ======== STRM_Issue ========
++ *  Purpose:
++ *      Issues a buffer on a stream
++ */
++DSP_STATUS STRM_Issue(struct STRM_OBJECT *hStrm, IN u8 *pBuf, u32 ulBytes,
++                   u32 ulBufSize, u32 dwArg)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      DSP_STATUS status = DSP_SOK;
++      void *pTmpBuf = NULL;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pBuf != NULL);
++
++      GT_4trace(STRM_debugMask, GT_ENTER, "STRM_Issue: hStrm: 0x%x\tpBuf: "
++               "0x%x\tulBytes: 0x%x\tdwArg: 0x%x\n", hStrm, pBuf, ulBytes,
++               dwArg);
++      if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++              status = DSP_EHANDLE;
++      } else {
++              pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++              if (hStrm->uSegment != 0) {
++                      pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
++                                      (void *)pBuf, CMM_VA2DSPPA);
++                      if (pTmpBuf == NULL)
++                              status = DSP_ETRANSLATE;
++
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      status = (*pIntfFxns->pfnChnlAddIOReq)
++                               (hStrm->hChnl, pBuf, ulBytes, ulBufSize,
++                               (u32) pTmpBuf, dwArg);
++              }
++              if (DSP_FAILED(status)) {
++                      if (status == CHNL_E_NOIORPS)
++                              status = DSP_ESTREAMFULL;
++                      else
++                              status = DSP_EFAIL;
++
++              }
++      }
++      return status;
++}
++
++/*
++ *  ======== STRM_Open ========
++ *  Purpose:
++ *      Open a stream for sending/receiving data buffers to/from a task or
++ *      XDAIS socket node on the DSP.
++ */
++DSP_STATUS STRM_Open(struct NODE_OBJECT *hNode, u32 uDir, u32 uIndex,
++                  IN struct STRM_ATTR *pAttr, OUT struct STRM_OBJECT **phStrm)
++{
++      struct STRM_MGR *hStrmMgr;
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      u32 ulChnlId;
++      struct STRM_OBJECT *pStrm = NULL;
++      CHNL_MODE uMode;
++      struct CHNL_ATTRS chnlAttrs;
++      DSP_STATUS status = DSP_SOK;
++      struct CMM_OBJECT *hCmmMgr = NULL;      /* Shared memory manager hndl */
++
++      #ifndef RES_CLEANUP_DISABLE
++      DSP_STATUS res_status = DSP_SOK;
++       u32                  hProcess;
++      HANDLE       pCtxt = NULL;
++      HANDLE       hDrvObject;
++      HANDLE              hSTRMRes;
++      #endif
++      DBC_Require(cRefs > 0);
++      DBC_Require(phStrm != NULL);
++      DBC_Require(pAttr != NULL);
++      GT_5trace(STRM_debugMask, GT_ENTER,
++               "STRM_Open: hNode: 0x%x\tuDir: 0x%x\t"
++               "uIndex: 0x%x\tpAttr: 0x%x\tphStrm: 0x%x\n",
++               hNode, uDir, uIndex, pAttr, phStrm);
++      *phStrm = NULL;
++      if (uDir != DSP_TONODE && uDir != DSP_FROMNODE) {
++              status = DSP_EDIRECTION;
++      } else {
++              /* Get the channel id from the node (set in NODE_Connect()) */
++              status = NODE_GetChannelId(hNode, uDir, uIndex, &ulChnlId);
++      }
++      if (DSP_SUCCEEDED(status))
++              status = NODE_GetStrmMgr(hNode, &hStrmMgr);
++
++      if (DSP_SUCCEEDED(status)) {
++              MEM_AllocObject(pStrm, struct STRM_OBJECT, STRM_SIGNATURE);
++              if (pStrm == NULL) {
++                      status = DSP_EMEMORY;
++                      GT_0trace(STRM_debugMask, GT_6CLASS,
++                               "STRM_Open: MEM_AllocObject() failed!\n ");
++              } else {
++                      pStrm->hStrmMgr = hStrmMgr;
++                      pStrm->uDir = uDir;
++                      pStrm->strmState = STREAM_IDLE;
++                      pStrm->hUserEvent = pAttr->hUserEvent;
++                      if (pAttr->pStreamAttrIn != NULL) {
++                              pStrm->uTimeout = pAttr->pStreamAttrIn->
++                                                uTimeout;
++                              pStrm->uNumBufs = pAttr->pStreamAttrIn->
++                                                uNumBufs;
++                              pStrm->lMode = pAttr->pStreamAttrIn->lMode;
++                              pStrm->uSegment = pAttr->pStreamAttrIn->
++                                                uSegment;
++                              pStrm->uAlignment = pAttr->pStreamAttrIn->
++                                                  uAlignment;
++                              pStrm->uDMAChnlId = pAttr->pStreamAttrIn->
++                                                  uDMAChnlId;
++                              pStrm->uDMAPriority = pAttr->pStreamAttrIn->
++                                                    uDMAPriority;
++                              chnlAttrs.uIOReqs = pAttr->pStreamAttrIn->
++                                                  uNumBufs;
++                      } else {
++                              pStrm->uTimeout = DEFAULTTIMEOUT;
++                              pStrm->uNumBufs = DEFAULTNUMBUFS;
++                              pStrm->lMode = STRMMODE_PROCCOPY;
++                              pStrm->uSegment = 0;    /* local memory */
++                              pStrm->uAlignment = 0;
++                              pStrm->uDMAChnlId = 0;
++                              pStrm->uDMAPriority = 0;
++                              chnlAttrs.uIOReqs = DEFAULTNUMBUFS;
++                      }
++                      chnlAttrs.hReserved1 = NULL;
++                      /* DMA chnl flush timeout */
++                      chnlAttrs.hReserved2 = pStrm->uTimeout;
++                      chnlAttrs.hEvent = NULL;
++                      if (pAttr->hUserEvent != NULL)
++                              chnlAttrs.hEvent = pAttr->hUserEvent;
++
++              }
++      }
++      if (DSP_FAILED(status))
++              goto func_cont;
++
++      if ((pAttr->pVirtBase == NULL) || !(pAttr->ulVirtSize > 0))
++              goto func_cont;
++
++      DBC_Assert(pStrm->lMode != STRMMODE_LDMA);      /* no System DMA */
++      /* Get the shared mem mgr for this streams dev object */
++      status = DEV_GetCmmMgr(hStrmMgr->hDev, &hCmmMgr);
++      if (DSP_FAILED(status)) {
++              GT_1trace(STRM_debugMask, GT_6CLASS, "STRM_Open: Failed to get "
++                       "CMM Mgr handle: 0x%x\n", status);
++      } else {
++              /*Allocate a SM addr translator for this strm.*/
++              status = CMM_XlatorCreate(&pStrm->hXlator, hCmmMgr, NULL);
++              if (DSP_FAILED(status)) {
++                      GT_1trace(STRM_debugMask, GT_6CLASS,
++                               "STRM_Open: Failed to "
++                               "create SM translator: 0x%x\n", status);
++              } else {
++                      DBC_Assert(pStrm->uSegment > 0);
++                      /*  Set translators Virt Addr attributes */
++                      status = CMM_XlatorInfo(pStrm->hXlator,
++                               (u8 **)&pAttr->pVirtBase, pAttr->ulVirtSize,
++                               pStrm->uSegment, true);
++                      if (status != DSP_SOK) {
++                              GT_0trace(STRM_debugMask, GT_6CLASS,
++                                       "STRM_Open: ERROR: "
++                                       "in setting CMM_XlatorInfo.\n");
++                      }
++              }
++      }
++func_cont:
++      if (DSP_SUCCEEDED(status)) {
++              /* Open channel */
++              uMode = (uDir == DSP_TONODE) ?
++                      CHNL_MODETODSP : CHNL_MODEFROMDSP;
++              pIntfFxns = hStrmMgr->pIntfFxns;
++              status = (*pIntfFxns->pfnChnlOpen) (&(pStrm->hChnl),
++                       hStrmMgr->hChnlMgr, uMode, ulChnlId, &chnlAttrs);
++              if (DSP_FAILED(status)) {
++                      /*
++                       * over-ride non-returnable status codes so we return
++                       * something documented
++                       */
++                      if (status != DSP_EMEMORY && status !=
++                         DSP_EINVALIDARG && status != DSP_EFAIL) {
++                              /*
++                               * We got a status that's not return-able.
++                               * Assert that we got something we were
++                               * expecting (DSP_EHANDLE isn't acceptable,
++                               * hStrmMgr->hChnlMgr better be valid or we
++                               * assert here), and then return DSP_EFAIL.
++                               */
++                              DBC_Assert(status == CHNL_E_OUTOFSTREAMS ||
++                                         status == CHNL_E_BADCHANID ||
++                                         status == CHNL_E_CHANBUSY ||
++                                         status == CHNL_E_NOIORPS);
++                              status = DSP_EFAIL;
++                      }
++                      GT_2trace(STRM_debugMask, GT_6CLASS,
++                                "STRM_Open: Channel open failed, "
++                                "chnl id = %d, status = 0x%x\n", ulChnlId,
++                                status);
++              }
++      }
++      if (DSP_SUCCEEDED(status))
++              *phStrm = pStrm;
++      else
++              (void)DeleteStrm(pStrm);
++
++#ifndef RES_CLEANUP_DISABLE
++       /* Return PID instead of process handle */
++       hProcess = current->pid;
++
++      res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++      if (DSP_SUCCEEDED(res_status)) {
++               DRV_GetProcContext(hProcess,
++                               (struct DRV_OBJECT *)hDrvObject, &pCtxt,
++                               hNode, 0);
++              if (pCtxt != NULL)
++                      DRV_ProcInsertSTRMResElement(*phStrm, &hSTRMRes, pCtxt);
++
++      }
++#endif
++
++       /* ensure we return a documented error code */
++      DBC_Ensure((DSP_SUCCEEDED(status) &&
++                MEM_IsValidHandle((*phStrm), STRM_SIGNATURE)) ||
++                (*phStrm == NULL && (status == DSP_EHANDLE ||
++                status == DSP_EDIRECTION || status == DSP_EVALUE ||
++                status == DSP_EFAIL)));
++      return status;
++}
++
++/*
++ *  ======== STRM_Reclaim ========
++ *  Purpose:
++ *      Relcaims a buffer from a stream.
++ */
++DSP_STATUS STRM_Reclaim(struct STRM_OBJECT *hStrm, OUT u8 **pBufPtr,
++                      u32 *pulBytes, u32 *pulBufSize, u32 *pdwArg)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      struct CHNL_IOC chnlIOC;
++      DSP_STATUS status = DSP_SOK;
++      void *pTmpBuf = NULL;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(pBufPtr != NULL);
++      DBC_Require(pulBytes != NULL);
++      DBC_Require(pdwArg != NULL);
++
++      GT_4trace(STRM_debugMask, GT_ENTER,
++               "STRM_Reclaim: hStrm: 0x%x\tpBufPtr: 0x%x"
++               "\tpulBytes: 0x%x\tpdwArg: 0x%x\n", hStrm, pBufPtr, pulBytes,
++               pdwArg);
++
++      if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++              status = DSP_EHANDLE;
++              goto func_end;
++      }
++      pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++      status = (*pIntfFxns->pfnChnlGetIOC)(hStrm->hChnl, hStrm->uTimeout,
++               &chnlIOC);
++      if (DSP_FAILED(status)) {
++              GT_1trace(STRM_debugMask, GT_6CLASS,
++                       "STRM_Reclaim: GetIOC failed! "
++                       "Status = 0x%x\n", status);
++      } else {
++              *pulBytes = chnlIOC.cBytes;
++              if (pulBufSize)
++                      *pulBufSize = chnlIOC.cBufSize;
++
++              *pdwArg = chnlIOC.dwArg;
++              if (!CHNL_IsIOComplete(chnlIOC)) {
++                      if (CHNL_IsTimedOut(chnlIOC)) {
++                              status = DSP_ETIMEOUT;
++                      } else {
++                              /* Allow reclaims after idle to succeed */
++                              if (!CHNL_IsIOCancelled(chnlIOC))
++                                      status = DSP_EFAIL;
++
++                      }
++              }
++              /* Translate zerocopy buffer if channel not canceled. */
++              if (DSP_SUCCEEDED(status) && (!CHNL_IsIOCancelled(chnlIOC)) &&
++                 (hStrm->lMode == STRMMODE_ZEROCOPY)) {
++                      /*
++                       *  This is a zero-copy channel so chnlIOC.pBuf
++                       *  contains the DSP address of SM. We need to
++                       *  translate it to a virtual address for the user
++                       *  thread to access.
++                       *  Note: Could add CMM_DSPPA2VA to CMM in the future.
++                       */
++                      pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
++                                      chnlIOC.pBuf, CMM_DSPPA2PA);
++                      if (pTmpBuf != NULL) {
++                              /* now convert this GPP Pa to Va */
++                              pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
++                                        pTmpBuf, CMM_PA2VA);
++                      }
++                      if (pTmpBuf == NULL) {
++                              GT_0trace(STRM_debugMask, GT_7CLASS,
++                                       "STRM_Reclaim: Failed "
++                                       "SM translation!\n");
++                              status = DSP_ETRANSLATE;
++                      }
++                      chnlIOC.pBuf = pTmpBuf;
++              }
++              *pBufPtr = chnlIOC.pBuf;
++      }
++func_end:
++      /* ensure we return a documented return code */
++      DBC_Ensure(DSP_SUCCEEDED(status) || status == DSP_EHANDLE ||
++                status == DSP_ETIMEOUT || status == DSP_ETRANSLATE ||
++                status == DSP_EFAIL);
++      return status;
++}
++
++/*
++ *  ======== STRM_RegisterNotify ========
++ *  Purpose:
++ *      Register to be notified on specific events for this stream.
++ */
++DSP_STATUS STRM_RegisterNotify(struct STRM_OBJECT *hStrm, u32 uEventMask,
++                            u32 uNotifyType, struct DSP_NOTIFICATION
++                            *hNotification)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(hNotification != NULL);
++
++      GT_4trace(STRM_debugMask, GT_ENTER,
++               "STRM_RegisterNotify: hStrm: 0x%x\t"
++               "uEventMask: 0x%x\tuNotifyType: 0x%x\thNotification: 0x%x\n",
++               hStrm, uEventMask, uNotifyType, hNotification);
++      if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++              status = DSP_EHANDLE;
++      } else if ((uEventMask & ~((DSP_STREAMIOCOMPLETION) |
++               DSP_STREAMDONE)) != 0) {
++              status = DSP_EVALUE;
++      } else {
++              if (uNotifyType != DSP_SIGNALEVENT)
++                      status = DSP_ENOTIMPL;
++
++      }
++      if (DSP_SUCCEEDED(status)) {
++              pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++              status = (*pIntfFxns->pfnChnlRegisterNotify)(hStrm->hChnl,
++                       uEventMask, uNotifyType, hNotification);
++      }
++      /* ensure we return a documented return code */
++      DBC_Ensure(DSP_SUCCEEDED(status) || status == DSP_EHANDLE ||
++                status == DSP_ETIMEOUT || status == DSP_ETRANSLATE ||
++                status == DSP_ENOTIMPL || status == DSP_EFAIL);
++      return status;
++}
++
++/*
++ *  ======== STRM_Select ========
++ *  Purpose:
++ *      Selects a ready stream.
++ */
++DSP_STATUS STRM_Select(IN struct STRM_OBJECT **aStrmTab, u32 nStrms,
++                    OUT u32 *pMask, u32 uTimeout)
++{
++      u32 uIndex;
++      struct CHNL_INFO chnlInfo;
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      struct SYNC_OBJECT **hSyncEvents = NULL;
++      u32 i;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(cRefs > 0);
++      DBC_Require(aStrmTab != NULL);
++      DBC_Require(pMask != NULL);
++      DBC_Require(nStrms > 0);
++
++      GT_4trace(STRM_debugMask, GT_ENTER,
++               "STRM_Select: aStrmTab: 0x%x \tnStrms: "
++               "0x%x\tpMask: 0x%x\tuTimeout: 0x%x\n", aStrmTab,
++               nStrms, pMask, uTimeout);
++      *pMask = 0;
++      for (i = 0; i < nStrms; i++) {
++              if (!MEM_IsValidHandle(aStrmTab[i], STRM_SIGNATURE)) {
++                      status = DSP_EHANDLE;
++                      break;
++              }
++      }
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      /* Determine which channels have IO ready */
++      for (i = 0; i < nStrms; i++) {
++              pIntfFxns = aStrmTab[i]->hStrmMgr->pIntfFxns;
++              status = (*pIntfFxns->pfnChnlGetInfo)(aStrmTab[i]->hChnl,
++                       &chnlInfo);
++              if (DSP_FAILED(status)) {
++                      break;
++              } else {
++                      if (chnlInfo.cIOCs > 0)
++                              *pMask |= (1 << i);
++
++              }
++      }
++      if (DSP_SUCCEEDED(status) && uTimeout > 0 && *pMask == 0) {
++              /* Non-zero timeout */
++              hSyncEvents = (struct SYNC_OBJECT **)MEM_Alloc(nStrms *
++                            sizeof(struct SYNC_OBJECT *), MEM_PAGED);
++              if (hSyncEvents == NULL) {
++                      status = DSP_EMEMORY;
++              } else {
++                      for (i = 0; i < nStrms; i++) {
++                              pIntfFxns = aStrmTab[i]->hStrmMgr->pIntfFxns;
++                              status = (*pIntfFxns->pfnChnlGetInfo)
++                                       (aStrmTab[i]->hChnl, &chnlInfo);
++                              if (DSP_FAILED(status))
++                                      break;
++                              else
++                                      hSyncEvents[i] = chnlInfo.hSyncEvent;
++
++                      }
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      status = SYNC_WaitOnMultipleEvents(hSyncEvents, nStrms,
++                              uTimeout, &uIndex);
++                      if (DSP_SUCCEEDED(status)) {
++                              /* Since we waited on the event, we have to
++                               * reset it */
++                              SYNC_SetEvent(hSyncEvents[uIndex]);
++                              *pMask = 1 << uIndex;
++                      }
++              }
++      }
++func_end:
++      if (hSyncEvents)
++              MEM_Free(hSyncEvents);
++
++      DBC_Ensure((DSP_SUCCEEDED(status) && (*pMask != 0 || uTimeout == 0)) ||
++                (DSP_FAILED(status) && *pMask == 0));
++
++      return status;
++}
++
++/*
++ *  ======== DeleteStrm ========
++ *  Purpose:
++ *      Frees the resources allocated for a stream.
++ */
++static DSP_STATUS DeleteStrm(struct STRM_OBJECT *hStrm)
++{
++      struct WMD_DRV_INTERFACE *pIntfFxns;
++      DSP_STATUS status = DSP_SOK;
++
++      if (MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++              if (hStrm->hChnl) {
++                      pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++                      /* Channel close can fail only if the channel handle
++                       * is invalid. */
++                      status = (*pIntfFxns->pfnChnlClose) (hStrm->hChnl);
++                      /* Free all SM address translator resources */
++                      if (DSP_SUCCEEDED(status)) {
++                              if (hStrm->hXlator) {
++                                      /* force free */
++                                      (void)CMM_XlatorDelete(hStrm->hXlator,
++                                      true);
++                              }
++                      }
++              }
++              MEM_FreeObject(hStrm);
++      } else {
++              status = DSP_EHANDLE;
++      }
++      return status;
++}
++
++/*
++ *  ======== DeleteStrmMgr ========
++ *  Purpose:
++ *      Frees stream manager.
++ */
++static void DeleteStrmMgr(struct STRM_MGR *hStrmMgr)
++{
++      if (MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE)) {
++
++              if (hStrmMgr->hSync)
++                      SYNC_DeleteCS(hStrmMgr->hSync);
++
++              MEM_FreeObject(hStrmMgr);
++      }
++}
++
+diff --git a/drivers/dsp/bridge/services/cfg.c b/drivers/dsp/bridge/services/cfg.c
+new file mode 100644
+index 0000000..67656bf
+--- /dev/null
++++ b/drivers/dsp/bridge/services/cfg.c
+@@ -0,0 +1,483 @@
++/*
++ * cfg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== cfgce.c ========
++ *  Purpose:
++ *      Implementation of platform specific config services.
++ *
++ *  Private Functions:
++ *      CFG_Exit
++ *      CFG_GetAutoStart
++ *      CFG_GetDevObject
++ *      CFG_GetDSPResources
++ *      CFG_GetExecFile
++ *      CFG_GetHostResources
++ *      CFG_GetObject
++ *      CFG_Init
++ *      CFG_SetDevObject
++ *      CFG_SetObject
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Arp-2004 hp  Support for handling more than one Device.
++ *! 26-Feb-2003 kc  Removed unused CFG fxns.
++ *! 10-Nov-2000 rr: CFG_GetBoardName local var initialized.
++ *! 30-Oct-2000 kc: Changed local var. names to use Hungarian notation.
++ *! 10-Aug-2000 rr: Cosmetic changes.
++ *! 26-Jul-2000 rr: Added CFG_GetDCDName. CFG_Get/SetObject(based on a flag)
++ *!                  replaces CFG_GetMgrObject & CFG_SetMgrObject.
++ *! 17-Jul-2000 rr: Added CFG_GetMgrObject & CFG_SetMgrObject.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *!               GT Changes.
++ *! 31-Jan-2000 rr: Comments and bugfixes:  modified after code review
++ *! 07-Jan-2000 rr: CFG_GetBoardName Ensure class checks strlen of the
++ *!                 read value from the registry against the passed in BufSize;
++ *!                 CFG_GetZLFile,CFG_GetWMDFileName and
++ *!                 CFG_GetExecFile also modified same way.
++ *! 06-Jan-2000 rr: CFG_GetSearchPath & CFG_GetWinBRIDGEDir removed.
++ *! 09-Dec-1999 rr: CFG_SetDevObject stores the DevNodeString pointer.
++ *! 03-Dec-1999 rr: CFG_GetDevObject reads stored DevObject from Registry.
++ *!                 CFG_GetDevNode reads the Devnodestring from the registry.
++ *!                 CFG_SetDevObject stores the registry path as
++ *!                 DevNodestring in the registry.
++ *! 02-Dec-1999 rr: CFG_debugMask is declared static now. stdwin.h included
++ *! 22-Nov-1999 kc: Added windows.h to remove warnings.
++ *! 25-Oct-1999 rr: CFG_GetHostResources reads the HostResource structure
++ *!                 from the registry which was set by the DRV Request
++ *!                 Resources.
++ *! 15-Oct-1999 rr: Changes in CFG_SetPrivateDword & HostResources reflecting
++ *!                 changes for  drv.h resource structure and wsxreg.h new
++ *!                 entry(DevObject) Hard coded entries removed for those items
++ *! 08-Oct-1999 rr: CFG_SetPrivateDword modified. it sets devobject into the
++ *!                 registry. CFG_Get HostResources modified for opening up
++ *!                 two mem winodws.
++ *! 24-Sep-1999 rr: CFG_GetHostResources uses hardcoded Registry calls,uses NT
++ *!                 type of Resource Structure.
++ *! 19-Jul-1999 a0216266: Stubbed from cfgnt.c.
++ */
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/reg.h>
++
++/*  ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/cfg.h>
++#include <dspbridge/list.h>
++
++struct DRV_EXT {
++      struct LST_ELEM link;
++      char szString[MAXREGPATHLENGTH];
++};
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CFG_debugMask = { NULL, NULL }; /* CFG debug Mask */
++#endif
++
++/*
++ *  ======== CFG_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the CFG module.
++ */
++void CFG_Exit(void)
++{
++      GT_0trace(CFG_debugMask, GT_5CLASS, "Entered CFG_Exit\n");
++}
++
++/*
++ *  ======== CFG_GetAutoStart ========
++ *  Purpose:
++ *      Retreive the autostart mask, if any, for this board.
++ */
++DSP_STATUS CFG_GetAutoStart(struct CFG_DEVNODE *hDevNode,
++                          OUT u32 *pdwAutoStart)
++{
++      DSP_STATUS status = DSP_SOK;
++      u32 dwBufSize;
++      GT_2trace(CFG_debugMask, GT_ENTER,
++                "Entered CFG_GetAutoStart: \n\thDevNode:"
++                "0x%x\n\tpdwAutoStart: 0x%x\n", hDevNode, pdwAutoStart);
++      dwBufSize = sizeof(*pdwAutoStart);
++      if (!hDevNode)
++              status = CFG_E_INVALIDHDEVNODE;
++      if (!pdwAutoStart)
++              status = CFG_E_INVALIDPOINTER;
++      if (DSP_SUCCEEDED(status)) {
++              status = REG_GetValue(NULL, (char *)hDevNode, AUTOSTART,
++                                   (u8 *)pdwAutoStart, &dwBufSize);
++              if (DSP_FAILED(status))
++                      status = CFG_E_RESOURCENOTAVAIL;
++      }
++#ifdef DEBUG
++      if (DSP_SUCCEEDED(status)) {
++              GT_0trace(CFG_debugMask, GT_1CLASS,
++                       "CFG_GetAutoStart SUCCESS \n");
++      } else {
++              GT_0trace(CFG_debugMask, GT_6CLASS,
++              "CFG_GetAutoStart Failed \n");
++      }
++#endif
++      DBC_Ensure((status == DSP_SOK &&
++              (*pdwAutoStart == 0 || *pdwAutoStart == 1))
++              || status != DSP_SOK);
++      return status;
++}
++
++/*
++ *  ======== CFG_GetDevObject ========
++ *  Purpose:
++ *      Retrieve the Device Object handle for a given devnode.
++ */
++DSP_STATUS CFG_GetDevObject(struct CFG_DEVNODE *hDevNode, OUT u32 *pdwValue)
++{
++      DSP_STATUS status = DSP_SOK;
++      u32 dwBufSize;
++      GT_2trace(CFG_debugMask, GT_ENTER, "Entered CFG_GetDevObject, args: "
++               "\n\thDevNode: 0x%x\n\tpdwValue: 0x%x\n", hDevNode,
++               *pdwValue);
++      if (!hDevNode)
++              status = CFG_E_INVALIDHDEVNODE;
++
++      if (!pdwValue)
++              status = CFG_E_INVALIDHDEVNODE;
++
++      dwBufSize = sizeof(pdwValue);
++      if (DSP_SUCCEEDED(status)) {
++
++              /* check the device string and then call the REG_SetValue*/
++               if (!(strcmp((char *)((struct DRV_EXT *)hDevNode)->szString,
++                                                      "TIOMAP1510"))) {
++                      GT_0trace(CFG_debugMask, GT_1CLASS,
++                                "Fetching DSP Device from "
++                                "Registry \n");
++                      status = REG_GetValue(NULL, (char *)hDevNode,
++                                            "DEVICE_DSP",
++                                            (u8 *)pdwValue, &dwBufSize);
++              } else {
++                      GT_0trace(CFG_debugMask, GT_6CLASS,
++                                "Failed to Identify the Device to Fetch \n");
++              }
++      }
++#ifdef DEBUG
++      if (DSP_SUCCEEDED(status)) {
++              GT_1trace(CFG_debugMask, GT_1CLASS,
++                        "CFG_GetDevObject SUCCESS DevObject"
++                        ": 0x%x\n ", *pdwValue);
++      } else {
++              GT_0trace(CFG_debugMask, GT_6CLASS,
++                        "CFG_GetDevObject Failed \n");
++      }
++#endif
++      return status;
++}
++
++/*
++ *  ======== CFG_GetDSPResources ========
++ *  Purpose:
++ *      Get the DSP resources available to a given device.
++ */
++DSP_STATUS CFG_GetDSPResources(struct CFG_DEVNODE *hDevNode,
++                             OUT struct CFG_DSPRES *pDSPResTable)
++{
++      DSP_STATUS status = DSP_SOK;    /* return value */
++      u32 dwResSize;
++      GT_2trace(CFG_debugMask, GT_ENTER,
++                "Entered CFG_GetDSPResources, args: "
++                "\n\thDevNode:  0x%x\n\tpDSPResTable:  0x%x\n",
++                hDevNode, pDSPResTable);
++      if (!hDevNode) {
++              status = CFG_E_INVALIDHDEVNODE;
++      } else if (!pDSPResTable) {
++              status = CFG_E_INVALIDPOINTER;
++      } else {
++              status = REG_GetValue(NULL, CONFIG, DSPRESOURCES,
++                                   (u8 *)pDSPResTable,
++                                   &dwResSize);
++      }
++      if (DSP_SUCCEEDED(status)) {
++              GT_0trace(CFG_debugMask, GT_1CLASS,
++                        "CFG_GetDSPResources SUCCESS\n");
++      } else {
++              status = CFG_E_RESOURCENOTAVAIL;
++              GT_0trace(CFG_debugMask, GT_6CLASS,
++                        "CFG_GetDSPResources Failed \n");
++      }
++#ifdef DEBUG
++      /* assert that resource values are reasonable */
++      DBC_Assert(pDSPResTable->uChipType < 256);
++      DBC_Assert(pDSPResTable->uWordSize > 0);
++      DBC_Assert(pDSPResTable->uWordSize < 32);
++      DBC_Assert(pDSPResTable->cChips > 0);
++      DBC_Assert(pDSPResTable->cChips < 256);
++#endif
++      return status;
++}
++
++/*
++ *  ======== CFG_GetExecFile ========
++ *  Purpose:
++ *      Retreive the default executable, if any, for this board.
++ */
++DSP_STATUS CFG_GetExecFile(struct CFG_DEVNODE *hDevNode, u32 ulBufSize,
++                         OUT char *pstrExecFile)
++{
++      DSP_STATUS status = DSP_SOK;
++      u32 cExecSize = ulBufSize;
++      GT_3trace(CFG_debugMask, GT_ENTER,
++                "Entered CFG_GetExecFile:\n\tthDevNode: "
++                "0x%x\n\tulBufSize: 0x%x\n\tpstrExecFile: 0x%x\n", hDevNode,
++                ulBufSize, pstrExecFile);
++      if (!hDevNode)
++              status = CFG_E_INVALIDHDEVNODE;
++
++      if (!pstrExecFile)
++              status = CFG_E_INVALIDPOINTER;
++
++      if (DSP_SUCCEEDED(status)) {
++              status = REG_GetValue(NULL, (char *)hDevNode, DEFEXEC,
++                                   (u8 *)pstrExecFile, &cExecSize);
++              if (DSP_FAILED(status))
++                      status = CFG_E_RESOURCENOTAVAIL;
++              else if (cExecSize > ulBufSize)
++                      status = DSP_ESIZE;
++
++      }
++#ifdef DEBUG
++      if (DSP_SUCCEEDED(status)) {
++              GT_1trace(CFG_debugMask, GT_1CLASS,
++                        "CFG_GetExecFile SUCCESS Exec File"
++                        "name : %s\n ", pstrExecFile);
++      } else {
++              GT_0trace(CFG_debugMask, GT_6CLASS,
++                        "CFG_GetExecFile Failed \n");
++      }
++#endif
++      DBC_Ensure(((status == DSP_SOK) &&
++                 (strlen(pstrExecFile) <= ulBufSize)) || (status != DSP_SOK));
++      return status;
++}
++
++/*
++ *  ======== CFG_GetHostResources ========
++ *  Purpose:
++ *      Get the Host allocated resources assigned to a given device.
++ */
++DSP_STATUS CFG_GetHostResources(struct CFG_DEVNODE *hDevNode,
++                              OUT struct CFG_HOSTRES *pHostResTable)
++{
++      DSP_STATUS status = DSP_SOK;
++      u32 dwBufSize;
++      GT_2trace(CFG_debugMask, GT_ENTER,
++                "Entered CFG_GetHostResources, args:\n\t"
++                "pHostResTable:  0x%x\n\thDevNode:  0x%x\n",
++                pHostResTable, hDevNode);
++      if (!hDevNode)
++              status = CFG_E_INVALIDHDEVNODE;
++
++      if (!pHostResTable)
++              status = CFG_E_INVALIDPOINTER;
++
++      if (DSP_SUCCEEDED(status)) {
++              dwBufSize = sizeof(struct CFG_HOSTRES);
++              if (DSP_FAILED(REG_GetValue(NULL, (char *)hDevNode,
++                             CURRENTCONFIG,
++                            (u8 *)pHostResTable, &dwBufSize))) {
++                      status = CFG_E_RESOURCENOTAVAIL;
++              }
++      }
++#ifdef DEBUG
++      if (DSP_SUCCEEDED(status)) {
++              GT_0trace(CFG_debugMask, GT_1CLASS,
++                        "CFG_GetHostResources SUCCESS \n");
++      } else {
++              GT_0trace(CFG_debugMask, GT_6CLASS,
++                        "CFG_GetHostResources Failed \n");
++      }
++#endif
++      return status;
++}
++
++/*
++ *  ======== CFG_GetObject ========
++ *  Purpose:
++ *      Retrieve the Object handle from the Registry
++ */
++DSP_STATUS CFG_GetObject(OUT u32 *pdwValue, u32 dwType)
++{
++      DSP_STATUS status = DSP_EINVALIDARG;
++      u32 dwBufSize;
++      DBC_Require(pdwValue != NULL);
++      GT_1trace(CFG_debugMask, GT_ENTER,
++               "Entered CFG_GetObject, args:pdwValue: "
++               "0x%x\n", *pdwValue);
++      dwBufSize = sizeof(pdwValue);
++      switch (dwType) {
++      case (REG_DRV_OBJECT):
++              status = REG_GetValue(NULL, CONFIG, DRVOBJECT,
++                                   (u8 *)pdwValue,
++                                   &dwBufSize);
++              break;
++      case (REG_MGR_OBJECT):
++              status = REG_GetValue(NULL, CONFIG, MGROBJECT,
++                                   (u8 *)pdwValue,
++                                   &dwBufSize);
++              break;
++      default:
++              break;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              GT_1trace(CFG_debugMask, GT_1CLASS,
++                        "CFG_GetObject SUCCESS DrvObject: "
++                        "0x%x\n ", *pdwValue);
++      } else {
++              status = CFG_E_RESOURCENOTAVAIL;
++              *pdwValue = 0;
++              GT_0trace(CFG_debugMask, GT_6CLASS, "CFG_GetObject Failed \n");
++      }
++      DBC_Ensure((DSP_SUCCEEDED(status) && *pdwValue != 0) ||
++                 (DSP_FAILED(status) && *pdwValue == 0));
++      return status;
++}
++
++/*
++ *  ======== CFG_Init ========
++ *  Purpose:
++ *      Initialize the CFG module's private state.
++ */
++bool CFG_Init(void)
++{
++      struct CFG_DSPRES dspResources;
++      GT_create(&CFG_debugMask, "CF");        /* CF for ConFig */
++      GT_0trace(CFG_debugMask, GT_5CLASS, "Entered CFG_Init\n");
++      GT_0trace(CFG_debugMask, GT_5CLASS, "Intializing DSP Registry Info \n");
++
++      dspResources.uChipType = DSPTYPE_64;
++      dspResources.cChips = 1;
++      dspResources.uWordSize = DSPWORDSIZE;
++      dspResources.cMemTypes = 0;
++      dspResources.aMemDesc[0].uMemType = 0;
++      dspResources.aMemDesc[0].ulMin = 0;
++      dspResources.aMemDesc[0].ulMax = 0;
++      if (DSP_SUCCEEDED(REG_SetValue(NULL, CONFIG, DSPRESOURCES, REG_BINARY,
++                       (u8 *)&dspResources, sizeof(struct CFG_DSPRES)))) {
++              GT_0trace(CFG_debugMask, GT_5CLASS,
++                        "Initialized DSP resources in "
++                        "Registry \n");
++      } else
++              GT_0trace(CFG_debugMask, GT_5CLASS,
++                        "Failed to Initialize DSP resources"
++                        " in Registry \n");
++      return true;
++}
++
++/*
++ *  ======== CFG_SetDevObject ========
++ *  Purpose:
++ *      Store the Device Object handle and devNode pointer for a given devnode.
++ */
++DSP_STATUS CFG_SetDevObject(struct CFG_DEVNODE *hDevNode, u32 dwValue)
++{
++      DSP_STATUS status = DSP_SOK;
++      u32 dwBuffSize;
++      GT_2trace(CFG_debugMask, GT_ENTER,
++                "Entered CFG_SetDevObject, args: \n\t"
++                "hDevNode: 0x%x\n\tdwValue: 0x%x\n", hDevNode, dwValue);
++      if (!hDevNode)
++              status = CFG_E_INVALIDHDEVNODE;
++
++      dwBuffSize = sizeof(dwValue);
++      if (DSP_SUCCEEDED(status)) {
++              /* Store the WCD device object in the Registry */
++
++               if (!(strcmp((char *)hDevNode, "TIOMAP1510"))) {
++                      GT_0trace(CFG_debugMask, GT_1CLASS,
++                                "Registering the DSP Device \n");
++                      status = REG_SetValue(NULL, (char *)hDevNode,
++                                "DEVICE_DSP", REG_DWORD,\
++                                (u8 *)&dwValue, dwBuffSize);
++                      if (DSP_SUCCEEDED(status)) {
++                              dwBuffSize = sizeof(hDevNode);
++                              status = REG_SetValue(NULL,
++                                        (char *)hDevNode, "DEVNODESTRING_DSP",
++                                        REG_DWORD, (u8 *)&hDevNode,
++                                        dwBuffSize);
++                      }
++              } else {
++                      GT_0trace(CFG_debugMask, GT_6CLASS,
++                                "Failed to Register Device \n");
++              }
++      }
++#ifdef DEBUG
++      if (DSP_SUCCEEDED(status)) {
++              GT_0trace(CFG_debugMask, GT_1CLASS,
++                        "CFG_SetDevObject SUCCESS \n");
++      } else {
++              GT_0trace(CFG_debugMask, GT_6CLASS,
++                        "CFG_SetDevObject Failed \n");
++      }
++#endif
++      return status;
++}
++
++/*
++ *  ======== CFG_SetObject ========
++ *  Purpose:
++ *      Store the Driver Object handle
++ */
++DSP_STATUS CFG_SetObject(u32 dwValue, u32 dwType)
++{
++      DSP_STATUS status = DSP_EINVALIDARG;
++      u32 dwBuffSize;
++      GT_1trace(CFG_debugMask, GT_ENTER,
++                "Entered CFG_SetObject, args: dwValue: "
++                "0x%x\n", dwValue);
++      dwBuffSize = sizeof(dwValue);
++      switch (dwType) {
++      case (REG_DRV_OBJECT):
++              status = REG_SetValue(NULL, CONFIG, DRVOBJECT, REG_DWORD,
++                       (u8 *)&dwValue, dwBuffSize);
++              break;
++      case (REG_MGR_OBJECT):
++              status = REG_SetValue(NULL, CONFIG, MGROBJECT, REG_DWORD,
++                       (u8 *) &dwValue, dwBuffSize);
++              break;
++      default:
++              break;
++      }
++#ifdef DEBUG
++      if (DSP_SUCCEEDED(status))
++              GT_0trace(CFG_debugMask, GT_1CLASS, "CFG_SetObject SUCCESS \n");
++      else
++              GT_0trace(CFG_debugMask, GT_6CLASS, "CFG_SetObject Failed \n");
++
++#endif
++      return status;
++}
+diff --git a/drivers/dsp/bridge/services/clk.c b/drivers/dsp/bridge/services/clk.c
+new file mode 100644
+index 0000000..b499b14
+--- /dev/null
++++ b/drivers/dsp/bridge/services/clk.c
+@@ -0,0 +1,375 @@
++/*
++ * clk.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== clk.c ========
++ *  Purpose:
++ *      Clock and Timer services.
++ *
++ *  Public Functions:
++ *      CLK_Exit
++ *      CLK_Init
++ *    CLK_Enable
++ *    CLK_Disable
++ *    CLK_GetRate
++ *    CLK_Set_32KHz
++ *! Revision History:
++ *! ================
++ *! 08-May-2007 rg: moved all clock functions from sync module.
++ *                And added CLK_Set_32KHz, CLK_Set_SysClk.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/clk.h>
++#include <dspbridge/util.h>
++
++
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++
++typedef volatile unsigned long  REG_UWORD32;
++
++#define SSI_Base        0x48058000
++
++#define SSI_BASE                     IO_ADDRESS(SSI_Base)
++
++
++struct SERVICES_Clk_t {
++      struct clk *clk_handle;
++      const char *clk_name;
++      int id;
++};
++
++/* The row order of the below array needs to match with the clock enumerations
++ * 'SERVICES_ClkId' provided in the header file.. any changes in the
++ * enumerations needs to be fixed in the array as well */
++static struct SERVICES_Clk_t SERVICES_Clks[] = {
++      {NULL, "iva2_ck", -1},
++      {NULL, "mailboxes_ick", -1},
++      {NULL, "gpt5_fck", -1},
++      {NULL, "gpt5_ick", -1},
++      {NULL, "gpt6_fck", -1},
++      {NULL, "gpt6_ick", -1},
++      {NULL, "gpt7_fck", -1},
++      {NULL, "gpt7_ick", -1},
++      {NULL, "gpt8_fck", -1},
++      {NULL, "gpt8_ick", -1},
++      {NULL, "wdt_fck", 3},
++      {NULL, "wdt_ick", 3},
++      {NULL, "mcbsp_fck", 1},
++      {NULL, "mcbsp_ick", 1},
++      {NULL, "mcbsp_fck", 2},
++      {NULL, "mcbsp_ick", 2},
++      {NULL, "mcbsp_fck", 3},
++      {NULL, "mcbsp_ick", 3},
++      {NULL, "mcbsp_fck", 4},
++      {NULL, "mcbsp_ick", 4},
++      {NULL, "mcbsp_fck", 5},
++      {NULL, "mcbsp_ick", 5},
++      {NULL, "ssi_ssr_sst_fck", -1},
++      {NULL, "ssi_ick", -1},
++      {NULL, "omap_32k_fck", -1},
++      {NULL, "sys_ck", -1},
++      {NULL, ""}
++};
++
++/* Generic TIMER object: */
++struct TIMER_OBJECT {
++      struct timer_list timer;
++};
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CLK_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++/*
++ *  ======== CLK_Exit ========
++ *  Purpose:
++ *      Cleanup CLK module.
++ */
++void CLK_Exit(void)
++{
++      int i = 0;
++
++      GT_0trace(CLK_debugMask, GT_5CLASS, "CLK_Exit\n");
++      /* Relinquish the clock handles */
++      while (i < SERVICESCLK_NOT_DEFINED) {
++              if (SERVICES_Clks[i].clk_handle)
++                      clk_put(SERVICES_Clks[i].clk_handle);
++
++              SERVICES_Clks[i].clk_handle = NULL;
++              i++;
++      }
++
++}
++
++/*
++ *  ======== CLK_Init ========
++ *  Purpose:
++ *      Initialize CLK module.
++ */
++bool CLK_Init(void)
++{
++      static struct platform_device dspbridge_device;
++      struct clk *clk_handle;
++      int i = 0;
++      GT_create(&CLK_debugMask, "CK");        /* CK for CLK */
++      GT_0trace(CLK_debugMask, GT_5CLASS, "CLK_Init\n");
++
++      dspbridge_device.dev.bus = &platform_bus_type;
++
++      /* Get the clock handles from base port and store locally */
++      while (i < SERVICESCLK_NOT_DEFINED) {
++              /* get the handle from BP */
++              dspbridge_device.id = SERVICES_Clks[i].id;
++
++              clk_handle = clk_get(&dspbridge_device.dev,
++                           SERVICES_Clks[i].clk_name);
++
++              if (!clk_handle) {
++                      GT_2trace(CLK_debugMask, GT_7CLASS,
++                                "CLK_Init: failed to get Clk handle %s, "
++                                "CLK dev id = %d\n",
++                                SERVICES_Clks[i].clk_name,
++                                SERVICES_Clks[i].id);
++                      /* should we fail here?? */
++              } else {
++                      GT_2trace(CLK_debugMask, GT_7CLASS,
++                                "CLK_Init: PASS and Clk handle %s, "
++                                "CLK dev id = %d\n",
++                                SERVICES_Clks[i].clk_name,
++                                SERVICES_Clks[i].id);
++              }
++              SERVICES_Clks[i].clk_handle = clk_handle;
++              i++;
++      }
++
++      return true;
++}
++
++/*
++ *  ======== CLK_Enable ========
++ *  Purpose:
++ *      Enable Clock .
++ *
++*/
++DSP_STATUS CLK_Enable(IN enum SERVICES_ClkId clk_id)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct clk *pClk;
++
++      DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++      GT_2trace(CLK_debugMask, GT_6CLASS, "CLK_Enable: CLK %s, "
++              "CLK dev id = %d\n", SERVICES_Clks[clk_id].clk_name,
++              SERVICES_Clks[clk_id].id);
++
++      pClk = SERVICES_Clks[clk_id].clk_handle;
++      if (pClk) {
++              if (clk_enable(pClk) == 0x0) {
++                      /* Success ? */
++              } else {
++                      pr_err("CLK_Enable: failed to Enable CLK %s, "
++                                      "CLK dev id = %d\n",
++                                      SERVICES_Clks[clk_id].clk_name,
++                                      SERVICES_Clks[clk_id].id);
++                      status = DSP_EFAIL;
++              }
++      } else {
++              pr_err("CLK_Enable: failed to get CLK %s, CLK dev id = %d\n",
++                                      SERVICES_Clks[clk_id].clk_name,
++                                      SERVICES_Clks[clk_id].id);
++              status = DSP_EFAIL;
++      }
++      /* The SSI module need to configured not to have the Forced idle for
++       * master interface. If it is set to forced idle, the SSI module is
++       * transitioning to standby thereby causing the client in the DSP hang
++       * waiting for the SSI module to be active after enabling the clocks
++       */
++      if (clk_id == SERVICESCLK_ssi_fck)
++              SSI_Clk_Prepare(true);
++
++      return status;
++}
++/*
++ *  ======== CLK_Set_32KHz ========
++ *  Purpose:
++ *      To Set parent of a clock to 32KHz.
++ */
++
++DSP_STATUS CLK_Set_32KHz(IN enum SERVICES_ClkId clk_id)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct clk *pClk;
++      struct clk *pClkParent;
++      enum SERVICES_ClkId sys_32k_id = SERVICESCLK_sys_32k_ck;
++      pClkParent =  SERVICES_Clks[sys_32k_id].clk_handle;
++
++      DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++      GT_2trace(CLK_debugMask, GT_6CLASS, "CLK_Set_32KHz: CLK %s, "
++              "CLK dev id = %d is setting to 32KHz \n",
++              SERVICES_Clks[clk_id].clk_name,
++              SERVICES_Clks[clk_id].id);
++      pClk = SERVICES_Clks[clk_id].clk_handle;
++      if (pClk) {
++              if (!(clk_set_parent(pClk, pClkParent) == 0x0)) {
++                     GT_2trace(CLK_debugMask, GT_7CLASS, "CLK_Set_32KHz: "
++                              "Failed to set to 32KHz %s, CLK dev id = %d\n",
++                              SERVICES_Clks[clk_id].clk_name,
++                              SERVICES_Clks[clk_id].id);
++                      status = DSP_EFAIL;
++              }
++      }
++      return status;
++}
++
++/*
++ *  ======== CLK_Disable ========
++ *  Purpose:
++ *      Disable the clock.
++ *
++*/
++DSP_STATUS CLK_Disable(IN enum SERVICES_ClkId clk_id)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct clk *pClk;
++      s32 clkUseCnt;
++
++      DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++      GT_2trace(CLK_debugMask, GT_6CLASS, "CLK_Disable: CLK %s, "
++              "CLK dev id = %d\n", SERVICES_Clks[clk_id].clk_name,
++              SERVICES_Clks[clk_id].id);
++
++      pClk = SERVICES_Clks[clk_id].clk_handle;
++
++      clkUseCnt = CLK_Get_UseCnt(clk_id);
++      if (clkUseCnt == -1) {
++              pr_err("CLK_Disable: failed to get CLK Use count for CLK %s,"
++                              "CLK dev id = %d\n",
++                              SERVICES_Clks[clk_id].clk_name,
++                              SERVICES_Clks[clk_id].id);
++      } else if (clkUseCnt == 0) {
++              pr_err("CLK_Disable: CLK %s, CLK dev id= %d is already"
++                              "disabled\n",
++                              SERVICES_Clks[clk_id].clk_name,
++                              SERVICES_Clks[clk_id].id);
++              return status;
++      }
++      if (clk_id == SERVICESCLK_ssi_ick)
++              SSI_Clk_Prepare(false);
++
++              if (pClk) {
++                      clk_disable(pClk);
++              } else {
++                      pr_err("CLK_Disable: failed to get CLK %s,"
++                                      "CLK dev id = %d\n",
++                                      SERVICES_Clks[clk_id].clk_name,
++                                      SERVICES_Clks[clk_id].id);
++                      status = DSP_EFAIL;
++              }
++      return status;
++}
++
++/*
++ *  ======== CLK_GetRate ========
++ *  Purpose:
++ *      GetClock Speed.
++ *
++ */
++
++DSP_STATUS CLK_GetRate(IN enum SERVICES_ClkId clk_id, u32 *speedKhz)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct clk *pClk;
++      u32 clkSpeedHz;
++
++      DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++      *speedKhz = 0x0;
++
++      GT_2trace(CLK_debugMask, GT_7CLASS, "CLK_GetRate: CLK %s, "
++              "CLK dev Id = %d \n", SERVICES_Clks[clk_id].clk_name,
++              SERVICES_Clks[clk_id].id);
++      pClk = SERVICES_Clks[clk_id].clk_handle;
++      if (pClk) {
++              clkSpeedHz = clk_get_rate(pClk);
++              *speedKhz = clkSpeedHz / 1000;
++              GT_2trace(CLK_debugMask, GT_6CLASS,
++                        "CLK_GetRate: clkSpeedHz = %d , "
++                       "speedinKhz=%d\n", clkSpeedHz, *speedKhz);
++      } else {
++              GT_2trace(CLK_debugMask, GT_7CLASS,
++                       "CLK_GetRate: failed to get CLK %s, "
++                       "CLK dev Id = %d\n", SERVICES_Clks[clk_id].clk_name,
++                       SERVICES_Clks[clk_id].id);
++              status = DSP_EFAIL;
++      }
++      return status;
++}
++
++s32 CLK_Get_UseCnt(IN enum SERVICES_ClkId clk_id)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct clk *pClk;
++      s32 useCount = -1;
++      DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++
++      pClk = SERVICES_Clks[clk_id].clk_handle;
++
++      if (pClk) {
++              useCount =  pClk->usecount; /* FIXME: usecount shouldn't be used */
++      } else {
++              GT_2trace(CLK_debugMask, GT_7CLASS,
++                       "CLK_GetRate: failed to get CLK %s, "
++                       "CLK dev Id = %d\n", SERVICES_Clks[clk_id].clk_name,
++                       SERVICES_Clks[clk_id].id);
++              status = DSP_EFAIL;
++      }
++      return useCount;
++}
++
++void SSI_Clk_Prepare(bool FLAG)
++{
++      u32 ssi_sysconfig;
++      ssi_sysconfig = __raw_readl((SSI_BASE) + 0x10);
++
++      if (FLAG) {
++              /* Set Autoidle, SIDLEMode to smart idle, and MIDLEmode to
++               * no idle
++               */
++              ssi_sysconfig = 0x1011;
++      } else {
++              /* Set Autoidle, SIDLEMode to forced idle, and MIDLEmode to
++               * forced idle
++               */
++              ssi_sysconfig = 0x1;
++      }
++      __raw_writel((u32)ssi_sysconfig, SSI_BASE + 0x10);
++}
+diff --git a/drivers/dsp/bridge/services/csl.c b/drivers/dsp/bridge/services/csl.c
+new file mode 100644
+index 0000000..dd33c2d
+--- /dev/null
++++ b/drivers/dsp/bridge/services/csl.c
+@@ -0,0 +1,173 @@
++/*
++ * csl.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== cslce.c ========
++ *  Purpose:
++ *      Provides platform independent C Standard library functions.
++ *
++ *  Public Functions:
++ *      CSL_Atoi
++ *      CSL_Exit
++ *      CSL_Init
++ *      CSL_NumToAscii
++ *      CSL_Strtokr
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Aug-2002 jeh: Added CSL_Strtokr().
++ *! 21-Sep-2001 jeh: Added CSL_Strncmp(). Alphabetized functions.
++ *! 22-Nov-2000 map: Added CSL_Atoi and CSL_Strtok
++ *! 19-Nov-2000 kc: Added CSL_ByteSwap.
++ *! 09-Nov-2000 kc: Added CSL_Strncat.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *!            GT Changes.
++ *! 15-Dec-1999 ag: Removed incorrect assertion CSL_NumToAscii()
++ *! 29-Oct-1999 kc: Added CSL_Wstrlen for UNICODE strings.
++ *! 30-Sep-1999 ag: Removed DBC assertion (!CSL_DebugMask.flags) in
++ *              CSP_Init().
++ *! 20-Sep-1999 ag: Added CSL_WcharToAnsi().
++ *!            Removed call to GT_set().
++ *! 19-Jan-1998 cr: Code review cleanup.
++ *! 29-Dec-1997 cr: Made platform independant, using MS CRT code, and
++ *!            combined csl32.c csl95.c and cslnt.c into csl.c.  Also
++ *!            changed CSL_lowercase to CSL_Uppercase.
++ *! 21-Aug-1997 gp: Fix to CSL_strcpyn to initialize Source string, the NT way.
++ *! 25-Jun-1997 cr: Created from csl95, added CSL_strcmp.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/csl.h>
++
++/* Is character c in the string pstrDelim? */
++#define IsDelimiter(c, pstrDelim) ((c != '\0') && \
++                                 (strchr(pstrDelim, c) != NULL))
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CSL_DebugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++/*
++ *  ======== CSL_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the CSL module.
++ */
++void CSL_Exit(void)
++{
++      GT_0trace(CSL_DebugMask, GT_5CLASS, "CSL_Exit\n");
++}
++
++/*
++ *  ======== CSL_Init ========
++ *  Purpose:
++ *      Initialize the CSL module's private state.
++ */
++bool CSL_Init(void)
++{
++      GT_create(&CSL_DebugMask, "CS");
++
++      GT_0trace(CSL_DebugMask, GT_5CLASS, "CSL_Init\n");
++
++      return true;
++}
++
++/*
++ *  ======== CSL_NumToAscii ========
++ *  Purpose:
++ *      Convert a 1 or 2 digit number to a 2 digit string.
++ */
++void CSL_NumToAscii(OUT char *pstrNumber, u32 dwNum)
++{
++      char tens;
++
++      DBC_Require(dwNum < 100);
++
++      if (dwNum < 100) {
++              tens = (char) dwNum / 10;
++              dwNum = dwNum % 10;
++
++              if (tens) {
++                      pstrNumber[0] = tens + '0';
++                      pstrNumber[1] = (char) dwNum + '0';
++                      pstrNumber[2] = '\0';
++              } else {
++                      pstrNumber[0] = (char) dwNum + '0';
++                      pstrNumber[1] = '\0';
++              }
++      } else {
++              pstrNumber[0] = '\0';
++      }
++}
++
++
++
++
++/*
++ *  ======= CSL_Strtokr =======
++ *  Purpose:
++ *      Re-entrant version of strtok.
++ */
++char *CSL_Strtokr(IN char *pstrSrc, IN CONST char *szSeparators,
++                OUT char **ppstrLast)
++{
++      char *pstrTemp;
++      char *pstrToken;
++
++      DBC_Require(szSeparators != NULL);
++      DBC_Require(ppstrLast != NULL);
++      DBC_Require(pstrSrc != NULL || *ppstrLast != NULL);
++
++      /*
++       *  Set string location to beginning (pstrSrc != NULL) or to the
++       *  beginning of the next token.
++       */
++      pstrTemp = (pstrSrc != NULL) ? pstrSrc : *ppstrLast;
++      if (*pstrTemp == '\0') {
++              pstrToken = NULL;
++      } else {
++              pstrToken = pstrTemp;
++              while (*pstrTemp != '\0' && !IsDelimiter(*pstrTemp,
++                    szSeparators)) {
++                      pstrTemp++;
++              }
++              if (*pstrTemp != '\0') {
++                      while (IsDelimiter(*pstrTemp, szSeparators)) {
++                              /* TODO: Shouldn't we do this for
++                               * only 1 char?? */
++                              *pstrTemp = '\0';
++                              pstrTemp++;
++                      }
++              }
++
++              /* Location in string for next call */
++              *ppstrLast = pstrTemp;
++      }
++
++      return pstrToken;
++}
+diff --git a/drivers/dsp/bridge/services/dbg.c b/drivers/dsp/bridge/services/dbg.c
+new file mode 100644
+index 0000000..5e1773f
+--- /dev/null
++++ b/drivers/dsp/bridge/services/dbg.c
+@@ -0,0 +1,119 @@
++/*
++ * dbg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dbgce.c ========
++ *  Purpose:
++ *      Provide debugging services for DSP/BIOS Bridge Mini Drivers.
++ *
++ *  Public Functions:
++ *      DBG_Exit
++ *      DBG_Init
++ *      DBG_Trace
++ *
++ *  Notes:
++ *      Requires gt.h.
++ *
++ *      This implementation does not create GT masks on a per WMD basis.
++ *      There is currently no facility for a WMD to alter the GT mask.
++ *
++ *! Revision History:
++ *! ================
++ *! 15-Feb-2000 rr: DBG_Trace prints based on the DebugZones.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *!            GT Changes.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 10-Oct-1997 cr: Added DBG_Printf service.
++ *! 28-May-1997 cr: Added reference counting.
++ *! 23-May-1997 cr: Updated DBG_Trace to new gt interface.
++ *! 29-May-1996 gp: Removed WCD_ prefix.
++ *! 20-May-1996 gp: Remove DEBUG conditional compilation.
++ *! 15-May-1996 gp: Created.
++ */
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/dbg.h>
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask DBG_debugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++#if (defined(DEBUG) || defined (DDSP_DEBUG_PRODUCT)) && GT_TRACE
++
++/*
++ *  ======== DBG_Init ========
++ *  Purpose:
++ *      Ensures trace capability is set up for link drivers.
++ */
++bool DBG_Init(void)
++{
++      GT_create(&DBG_debugMask, "WD");     /* for WmD (link driver) debug */
++
++      GT_0trace(DBG_debugMask, GT_5CLASS, "DBG_Init\n");
++
++      return true;
++}
++
++/*
++ *  ======== DBG_Trace ========
++ *  Purpose:
++ *      Output a trace message to the debugger, if the given trace level
++ *      is unmasked.
++ */
++DSP_STATUS DBG_Trace(u8 bLevel, char *pstrFormat, ...)
++{
++      s32 arg1, arg2, arg3, arg4, arg5, arg6;
++      va_list va;
++
++      va_start(va, pstrFormat);
++
++      arg1 = va_arg(va, s32);
++      arg2 = va_arg(va, s32);
++      arg3 = va_arg(va, s32);
++      arg4 = va_arg(va, s32);
++      arg5 = va_arg(va, s32);
++      arg6 = va_arg(va, s32);
++
++      va_end(va);
++
++      if (bLevel & *(DBG_debugMask).flags)
++              printk(pstrFormat, arg1, arg2, arg3, arg4, arg5, arg6);
++
++      return DSP_SOK;
++}
++
++/*
++ *  ======== DBG_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the DBG module.
++ */
++void DBG_Exit(void)
++{
++      GT_0trace(DBG_debugMask, GT_5CLASS, "DBG_Exit\n");
++}
++
++#endif        /* (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE */
+diff --git a/drivers/dsp/bridge/services/dpc.c b/drivers/dsp/bridge/services/dpc.c
+new file mode 100644
+index 0000000..bd608d1
+--- /dev/null
++++ b/drivers/dsp/bridge/services/dpc.c
+@@ -0,0 +1,274 @@
++/*
++ * dpc.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== dpcce.c ========
++ *  Purpose:
++ *      Deferred Procedure Call(DPC) Services.
++ *
++ *
++ *  Public Functions:
++ *      DPC_Create
++ *      DPC_Destroy
++ *      DPC_Exit
++ *      DPC_Init
++ *      DPC_Schedule
++ *
++ *! Revision History:
++ *! ================
++ *! 28-Mar-2001 ag: Added #ifdef CHNL_NOIPCINTR to set DPC thread priority
++ *!                     to THREAD_PRIORITY_IDLE for polling IPC.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *!            GT Changes.
++ *! 31-Jan-2000 rr: Changes after code review.Terminate thread,handle
++ *!                 modified.DPC_Destroy frees the DPC_Object only on
++ *!                 Successful termination of the thread and the handle.
++ *! 06-Jan-1999 ag: Format cleanup for code review.
++ *!                 Removed DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
++ *! 10-Dec-1999 ag: Added SetProcPermissions in DPC_DeferredProcedure().
++ *!                 (Needed to access client(s) CHNL buffers).
++ *! 19-Sep-1999 a0216266: Stubbed from dpcnt.c.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/dpc.h>
++
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE       0x5f435044    /* "DPC_" (in reverse). */
++
++/* The DPC object, passed to our priority event callback routine: */
++struct DPC_OBJECT {
++      u32 dwSignature;        /* Used for object validation.   */
++      void *pRefData;         /* Argument for client's DPC.    */
++      DPC_PROC pfnDPC;        /* Client's DPC.                 */
++      u32 numRequested;       /* Number of requested DPC's.      */
++      u32 numScheduled;       /* Number of executed DPC's.      */
++      struct tasklet_struct dpc_tasklet;
++
++#ifdef DEBUG
++      u32 cEntryCount;        /* Number of times DPC reentered. */
++      u32 numRequestedMax;    /* Keep track of max pending DPC's. */
++#endif
++
++      spinlock_t dpc_lock;
++};
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask DPC_DebugMask = { NULL, NULL }; /* DPC Debug Mask */
++#endif
++
++/*  ----------------------------------- Function Prototypes */
++static void DPC_DeferredProcedure(IN unsigned long pDeferredContext);
++
++/*
++ *  ======== DPC_Create ========
++ *  Purpose:
++ *      Create a DPC object, allowing a client's own DPC procedure to be
++ *      scheduled for a call with client reference data.
++ */
++DSP_STATUS DPC_Create(OUT struct DPC_OBJECT **phDPC, DPC_PROC pfnDPC,
++                    void *pRefData)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DPC_OBJECT *pDPCObject = NULL;
++
++      if ((phDPC != NULL) && (pfnDPC != NULL)) {
++              /*
++               *  Allocate a DPC object to store information allowing our DPC
++               *  callback to dispatch to the client's DPC.
++               */
++              MEM_AllocObject(pDPCObject, struct DPC_OBJECT, SIGNATURE);
++              if (pDPCObject != NULL) {
++                      tasklet_init(&pDPCObject->dpc_tasklet,
++                                   DPC_DeferredProcedure,
++                                   (u32) pDPCObject);
++                      /* Fill out our DPC Object: */
++                      pDPCObject->pRefData = pRefData;
++                      pDPCObject->pfnDPC = pfnDPC;
++                      pDPCObject->numRequested = 0;
++                      pDPCObject->numScheduled = 0;
++#ifdef DEBUG
++                      pDPCObject->numRequestedMax = 0;
++                      pDPCObject->cEntryCount = 0;
++#endif
++                      spin_lock_init(&pDPCObject->dpc_lock);
++                      *phDPC = pDPCObject;
++              } else {
++                      GT_0trace(DPC_DebugMask, GT_6CLASS,
++                                "DPC_Create: DSP_EMEMORY\n");
++                      status = DSP_EMEMORY;
++              }
++      } else {
++              GT_0trace(DPC_DebugMask, GT_6CLASS,
++                        "DPC_Create: DSP_EPOINTER\n");
++              status = DSP_EPOINTER;
++      }
++      DBC_Ensure((DSP_FAILED(status) && (!phDPC || (phDPC && *phDPC == NULL)))
++                 || DSP_SUCCEEDED(status));
++      return status;
++}
++
++/*
++ *  ======== DPC_Destroy ========
++ *  Purpose:
++ *      Cancel the last scheduled DPC, and deallocate a DPC object previously
++ *      allocated with DPC_Create(). Frees the Object only if the thread
++ *      and the event terminated successfuly.
++ */
++DSP_STATUS DPC_Destroy(struct DPC_OBJECT *hDPC)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)hDPC;
++
++      if (MEM_IsValidHandle(hDPC, SIGNATURE)) {
++
++              /* Free our DPC object: */
++              if (DSP_SUCCEEDED(status)) {
++                      tasklet_kill(&pDPCObject->dpc_tasklet);
++                      MEM_FreeObject(pDPCObject);
++                      pDPCObject = NULL;
++                      GT_0trace(DPC_DebugMask, GT_2CLASS,
++                                "DPC_Destroy: SUCCESS\n");
++              }
++      } else {
++              GT_0trace(DPC_DebugMask, GT_6CLASS,
++                        "DPC_Destroy: DSP_EHANDLE\n");
++              status = DSP_EHANDLE;
++      }
++      DBC_Ensure((DSP_SUCCEEDED(status) && pDPCObject == NULL)
++                 || DSP_FAILED(status));
++      return status;
++}
++
++/*
++ *  ======== DPC_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the DPC module.
++ */
++void DPC_Exit(void)
++{
++      GT_0trace(DPC_DebugMask, GT_5CLASS, "Entered DPC_Exit\n");
++}
++
++/*
++ *  ======== DPC_Init ========
++ *  Purpose:
++ *      Initialize the DPC module's private state.
++ */
++bool DPC_Init(void)
++{
++      GT_create(&DPC_DebugMask, "DP");
++
++      GT_0trace(DPC_DebugMask, GT_5CLASS, "Entered DPC_Init\n");
++
++      return true;
++}
++
++/*
++ *  ======== DPC_Schedule ========
++ *  Purpose:
++ *      Schedule a deferred procedure call to be executed at a later time.
++ *      Latency and order of DPC execution is platform specific.
++ */
++DSP_STATUS DPC_Schedule(struct DPC_OBJECT *hDPC)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)hDPC;
++      unsigned long flags;
++
++      GT_1trace(DPC_DebugMask, GT_ENTER, "DPC_Schedule hDPC %x\n", hDPC);
++      if (MEM_IsValidHandle(hDPC, SIGNATURE)) {
++              /* Increment count of DPC's pending. Needs to be protected
++               * from ISRs since this function is called from process
++               * context also. */
++              spin_lock_irqsave(&hDPC->dpc_lock, flags);
++              pDPCObject->numRequested++;
++              spin_unlock_irqrestore(&hDPC->dpc_lock, flags);
++              tasklet_schedule(&(hDPC->dpc_tasklet));
++#ifdef DEBUG
++              if (pDPCObject->numRequested > pDPCObject->numScheduled +
++                                              pDPCObject->numRequestedMax) {
++                      pDPCObject->numRequestedMax = pDPCObject->numRequested -
++                                              pDPCObject->numScheduled;
++              }
++#endif
++      /*  If an interrupt occurs between incrementing numRequested and the
++       *  assertion below, then DPC will get executed while returning from
++       *  ISR, which will complete all requests and make numRequested equal
++       * to numScheduled, firing this assertion. This happens only when
++       * DPC is being scheduled in process context */
++      } else {
++              GT_0trace(DPC_DebugMask, GT_6CLASS,
++                        "DPC_Schedule: DSP_EHANDLE\n");
++              status = DSP_EHANDLE;
++      }
++      GT_1trace(DPC_DebugMask, GT_ENTER, "DPC_Schedule status %x\n", status);
++      return status;
++}
++
++/*
++ *  ======== DeferredProcedure ========
++ *  Purpose:
++ *      Main DPC routine.  This is called by host OS DPC callback
++ *      mechanism with interrupts enabled.
++ */
++static void DPC_DeferredProcedure(IN unsigned long pDeferredContext)
++{
++      struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)pDeferredContext;
++      /* read numRequested in local variable */
++      u32 requested;
++      u32 serviced;
++
++      DBC_Require(pDPCObject != NULL);
++      requested = pDPCObject->numRequested;
++      serviced = pDPCObject->numScheduled;
++
++      GT_1trace(DPC_DebugMask, GT_ENTER, "> DPC_DeferredProcedure "
++                "pDeferredContext=%x\n", pDeferredContext);
++      /* Rollover taken care of using != instead of < */
++      if (serviced != requested) {
++              if (pDPCObject->pfnDPC != NULL) {
++                      /* Process pending DPC's: */
++                      do {
++                              /* Call client's DPC: */
++                              (*(pDPCObject->pfnDPC))(pDPCObject->pRefData);
++                              serviced++;
++                      } while (serviced != requested);
++              }
++              pDPCObject->numScheduled = requested;
++      }
++      GT_2trace(DPC_DebugMask, GT_ENTER,
++                "< DPC_DeferredProcedure requested %d"
++                " serviced %d\n", requested, serviced);
++}
++
+diff --git a/drivers/dsp/bridge/services/kfile.c b/drivers/dsp/bridge/services/kfile.c
+new file mode 100644
+index 0000000..ba1d26f
+--- /dev/null
++++ b/drivers/dsp/bridge/services/kfile.c
+@@ -0,0 +1,338 @@
++/*
++ * kfile.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== kfilece.c ========
++ *  Purpose:
++ *      This module provides file i/o services.
++ *
++ *  Public Functions:
++ *      KFILE_Close
++ *      KFILE_Exit
++ *      KFILE_Init
++ *      KFILE_Open
++ *      KFILE_Read
++ *      KFILE_Seek
++ *      KFILE_Tell
++ *
++ *! Revision History
++ *! ================
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *!            GT Changes.
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 12-Nov-1999 kc: Enabled CSL for UNICODE/ANSI string conversions.
++ *! 30-Sep-1999 ag: Changed KFILE_Read() GT level from _ENTER to _4CLASS.
++ *!                 Removed GT_set().
++ *! 25-Aug-1999 ag: Changed MEM_Calloc allocation type to MEM_PAGED.
++ *! 13-Jul-1999 a0216266(ww - TID): Stubbed from kfilent.c.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/kfile.h>
++
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE           0x4c49464b        /* hex code of KFIL (reversed) */
++#define MAXFILENAMELENGTH   256
++#define GENERAL_FAILURE     0xffffffff        /* SetFilePointer error */
++
++/* The KFILE_FileObj abstracts the true file handle from a KFILE handle. */
++struct KFILE_FileObj {
++    u32 dwSignature;
++    __kernel_pid_t owner_pid; /* PID of process that opened this file */
++    char      *fileName  ;
++    bool          isOpen    ;
++    u32        size      ;
++    u32        curPos    ;
++    long        hInternal;            /* internal handle of file */
++    struct file *fileDesc;
++
++};
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask KFILE_debugMask = { NULL, NULL };       /* Debug mask */
++#endif
++
++/*
++ *  ======== KFILE_Close ========
++ *  Purpose:
++ *      This function closes a file's stream.
++ */
++s32 KFILE_Close(struct KFILE_FileObj *hFile)
++{
++      s32 cRetVal = 0;        /* 0 indicates success */
++      s32 fRetVal = 0;
++      __kernel_pid_t curr_pid;
++
++      GT_1trace(KFILE_debugMask, GT_ENTER, "KFILE_Close: hFile 0x%x\n",
++                hFile);
++
++      /* Check for valid handle */
++      if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++              /* Close file only if opened by the same process (id). Otherwise
++               * Linux closes all open file handles when process exits.*/
++               /* Return PID instead of process handle */
++               curr_pid = (__kernel_pid_t)current->pid;
++              fRetVal = filp_close(hFile->fileDesc, NULL) ;
++              if (fRetVal) {
++                      cRetVal = E_KFILE_ERROR;
++                      GT_1trace(KFILE_debugMask, GT_6CLASS,
++                                "KFILE_Close: sys_close "
++                                "returned %d\n", fRetVal);
++              }
++              MEM_FreeObject(hFile);
++      } else {
++              cRetVal = E_KFILE_INVALIDHANDLE;
++              GT_0trace(KFILE_debugMask, GT_6CLASS, "KFILE_Close: "
++                        "invalid file handle\n");
++      }
++      return cRetVal;
++}
++
++/*
++ *  ======== KFILE_Exit ========
++ *  Purpose:
++ *      Decrement reference count, and free resources when reference count
++ *      is 0.
++ */
++void KFILE_Exit(void)
++{
++      GT_0trace(KFILE_debugMask, GT_5CLASS, "KFILE_Exit\n");
++}
++
++/*
++ *  ======== KFILE_Init ========
++ */
++bool KFILE_Init(void)
++{
++      GT_create(&KFILE_debugMask, "KF");      /* "KF" for KFile */
++
++      GT_0trace(KFILE_debugMask, GT_5CLASS, "KFILE_Init\n");
++
++      return true;
++}
++
++/*
++ *  ======== KFILE_Open ========
++ *  Purpose:
++ *      Open a file for reading ONLY
++ */
++struct KFILE_FileObj *KFILE_Open(CONST char *pszFileName, CONST char *pszMode)
++{
++      struct KFILE_FileObj *hFile;    /* file handle */
++      DSP_STATUS status;
++      mm_segment_t fs;
++
++      struct file*fileDesc = NULL;
++      DBC_Require(pszMode != NULL);
++      DBC_Require(pszFileName != NULL);
++
++      GT_2trace(KFILE_debugMask, GT_ENTER,
++                "KFILE_Open: pszFileName %s, pszMode "
++                "%s\n", pszFileName, pszMode);
++
++      /* create a KFILE object */
++      MEM_AllocObject(hFile, struct KFILE_FileObj, SIGNATURE);
++
++      if (hFile) {
++              fs = get_fs();
++              set_fs(get_ds());
++      /* Third argument is mode (permissions). Ignored unless creating file */
++              fileDesc = filp_open(pszFileName, O_RDONLY, 0);
++              if ((IS_ERR(fileDesc)) || (fileDesc == NULL) ||
++                   (fileDesc->f_op == NULL) || (fileDesc->f_op->read == NULL)
++                   || (fileDesc->f_op->llseek == NULL)) {
++                      status = DSP_EFILE;
++              } else {
++                      hFile->fileDesc = fileDesc;
++                      hFile->fileName = (char *)pszFileName;
++                      hFile->isOpen      = true;
++                      hFile->curPos   = 0;
++                      hFile->size = fileDesc->f_op->llseek(fileDesc, 0,
++                                                          SEEK_END);
++                      fileDesc->f_op->llseek(fileDesc, 0, SEEK_SET);
++                       /* Return PID instead of process handle */
++                       hFile->owner_pid = current->pid;
++
++                      status = DSP_SOK;
++              }
++              set_fs(fs);
++              if (DSP_FAILED(status)) {
++                      /* free memory, and clear handle */
++                      MEM_FreeObject(hFile);
++                      hFile = NULL;
++              }
++      } else {
++                      GT_0trace(KFILE_debugMask, GT_6CLASS,
++                                "KFILE_Open: MEM_AllocObject failed\n");
++                      status = DSP_EMEMORY;
++      }
++      return hFile;
++}
++
++/*
++ *  ======== KFILE_Read ========
++ *  Purpose:
++ *      Reads a specified number of bytes into a buffer.
++ */
++s32
++KFILE_Read(void __user*pBuffer, s32 cSize, s32 cCount,
++                      struct KFILE_FileObj *hFile)
++{
++      u32 dwBytesRead = 0;
++      s32 cRetVal = 0;
++      mm_segment_t fs;
++
++      DBC_Require(pBuffer != NULL);
++
++      GT_4trace(KFILE_debugMask, GT_4CLASS,
++                "KFILE_Read: buffer 0x%x, cSize 0x%x,"
++                "cCount 0x%x, hFile 0x%x\n", pBuffer, cSize, cCount, hFile);
++
++      /* check for valid file handle */
++      if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++              if ((cSize > 0) && (cCount > 0) && pBuffer) {
++                      /* read from file */
++                      fs = get_fs();
++                      set_fs(get_ds());
++                      dwBytesRead = hFile->fileDesc->f_op->read(hFile->
++                                    fileDesc, pBuffer, cSize *cCount,
++                                    &(hFile->fileDesc->f_pos));
++                      set_fs(fs);
++                      if (dwBytesRead) {
++                              cRetVal = dwBytesRead / cSize;
++                              hFile->curPos += dwBytesRead;
++                              DBC_Assert((dwBytesRead / cSize) <= \
++                                        (u32)cCount);
++                      } else {
++                              cRetVal = E_KFILE_ERROR;
++                              GT_0trace(KFILE_debugMask, GT_6CLASS,
++                                        "KFILE_Read: sys_read() failed\n");
++                      }
++              } else {
++                      cRetVal = DSP_EINVALIDARG;
++                      GT_0trace(KFILE_debugMask, GT_6CLASS,
++                                "KFILE_Read: Invalid argument(s)\n");
++              }
++      } else {
++              cRetVal = E_KFILE_INVALIDHANDLE;
++              GT_0trace(KFILE_debugMask, GT_6CLASS,
++                        "KFILE_Read: invalid file handle\n");
++      }
++
++      return cRetVal;
++}
++
++/*
++ *  ======== KFILE_Seek ========
++ *  Purpose:
++ *      Sets the file position indicator. NOTE:  we don't support seeking
++ *      beyond the boundaries of a file.
++ */
++s32 KFILE_Seek(struct KFILE_FileObj *hFile, s32 lOffset, s32 cOrigin)
++{
++      s32 cRetVal = 0;        /* 0 for success */
++      u32 dwCurPos = 0;
++
++      struct file *fileDesc = NULL;
++
++      GT_3trace(KFILE_debugMask, GT_ENTER, "KFILE_Seek: hFile 0x%x, "
++                "lOffset 0x%x, cOrigin 0x%x\n",
++                hFile, lOffset, cOrigin);
++
++      /* check for valid file handle */
++      if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++              /* based on the origin flag, move the internal pointer */
++
++      fileDesc = hFile->fileDesc;
++              switch (cOrigin) {
++              case KFILE_SEEK_SET:
++                      dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
++                                 fileDesc, lOffset, SEEK_SET);
++                      cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
++                      break;
++
++              case KFILE_SEEK_CUR:
++                      dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
++                                 fileDesc, lOffset, SEEK_CUR);
++                      cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
++                      break;
++              case KFILE_SEEK_END:
++                      dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
++                                 fileDesc, lOffset, SEEK_END);
++                      cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
++                      break;
++              default:
++                      cRetVal = E_KFILE_BADORIGINFLAG;
++                      GT_0trace(KFILE_debugMask, GT_6CLASS,
++                                "KFILE_Seek:bad origin flag\n");
++                      break;
++              }
++      } else {
++              cRetVal = E_KFILE_INVALIDHANDLE;
++              GT_0trace(KFILE_debugMask, GT_6CLASS,
++                        "KFILE_Seek:invalid file handle\n");
++      }
++      return cRetVal;
++}
++
++/*
++ *  ======== KFILE_Tell ========
++ *  Purpose:
++ *      Reports the current value of the position indicator. We did not
++ *        consider 64 bit long file size, which implies a 4GB file limit
++ *      (2 to 32 power).
++ */
++s32 KFILE_Tell(struct KFILE_FileObj *hFile)
++{
++      u32 dwCurPos = 0;
++      s32 lRetVal = E_KFILE_ERROR;
++
++      GT_1trace(KFILE_debugMask, GT_ENTER, "KFILE_Tell: hFile 0x%x\n", hFile);
++
++      if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++
++              /* Get current position. */
++              dwCurPos = hFile->fileDesc->f_op->llseek(hFile->fileDesc, 0,
++                         SEEK_CUR);
++              if (dwCurPos >= 0)
++                      lRetVal = dwCurPos;
++
++      } else {
++              lRetVal = E_KFILE_INVALIDHANDLE;
++              GT_0trace(KFILE_debugMask, GT_6CLASS,
++                        "KFILE_Seek:invalid file handle\n");
++      }
++      return lRetVal;
++}
++
+diff --git a/drivers/dsp/bridge/services/list.c b/drivers/dsp/bridge/services/list.c
+new file mode 100644
+index 0000000..7fa3e76
+--- /dev/null
++++ b/drivers/dsp/bridge/services/list.c
+@@ -0,0 +1,285 @@
++/*
++ * list.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== listce.c ========
++ *  Purpose
++ *      Provides standard circular list handling functions.
++ *
++ *  Public Functions:
++ *      LST_Create
++ *      LST_Delete
++ *      LST_Exit
++ *      LST_First
++ *      LST_GetHead
++ *      LST_Init
++ *      LST_InitElem
++ *      LST_InsertBefore
++ *      LST_Next
++ *      LST_PutTail
++ *      LST_RemoveElem
++ *
++ *! Revision History
++ *! ================
++ *! 06-Mar-2002 jeh Don't set element self to NULL in LST_RemoveElem().
++ *! 10-Aug-2000 ag: Added LST_InsertBefore().
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *!            GT Changes.
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 10-Aug-1999 kc: Based on wsx-c18.
++ *! 16-Jun-1997 gp: Removed unnecessary enabling/disabling of interrupts around
++ *!                 list manipulation code.
++ *! 22-Oct-1996 gp: Added LST_RemoveElem, and LST_First/LST_Next iterators.
++ *! 10-Aug-1996 gp: Acquired from SMM for WinSPOX v. 1.1; renamed identifiers.
++ */
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/list.h>
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask LST_debugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++/*
++ *  ======== LST_Create ========
++ *  Purpose:
++ *      Allocates and initializes a circular list.
++ */
++struct LST_LIST *LST_Create(void)
++{
++      struct LST_LIST *pList;
++
++      GT_0trace(LST_debugMask, GT_ENTER, "LST_Create: entered\n");
++
++      pList = (struct LST_LIST *) MEM_Calloc(sizeof(struct LST_LIST),
++              MEM_NONPAGED);
++      if (pList != NULL) {
++              pList->head.next = &pList->head;
++              pList->head.prev = &pList->head;
++              pList->head.self = NULL;
++      }
++
++      return pList;
++}
++
++/*
++ *  ======== LST_Delete ========
++ *  Purpose:
++ *      Removes a list by freeing its control structure's memory space.
++ */
++void LST_Delete(struct LST_LIST *pList)
++{
++      DBC_Require(pList != NULL);
++
++      GT_1trace(LST_debugMask, GT_ENTER, "LST_Delete: pList 0x%x\n", pList);
++
++      MEM_Free(pList);
++}
++
++/*
++ *  ======== LST_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the LST module.
++ */
++void LST_Exit(void)
++{
++      GT_0trace(LST_debugMask, GT_5CLASS, "LST_Exit\n");
++}
++
++/*
++ *  ======== LST_First ========
++ *  Purpose:
++ *      Returns a pointer to the first element of the list, or NULL if the
++ *      list is empty.
++ */
++struct LST_ELEM *LST_First(struct LST_LIST *pList)
++{
++      struct LST_ELEM *pElem = NULL;
++
++      DBC_Require(pList != NULL);
++
++      GT_1trace(LST_debugMask, GT_ENTER, "LST_First: pList 0x%x\n", pList);
++
++      if (!LST_IsEmpty(pList))
++              pElem = pList->head.next;
++
++      return pElem;
++}
++
++/*
++ *  ======== LST_GetHead ========
++ *  Purpose:
++ *      "Pops" the head off the list and returns a pointer to it.
++ */
++struct LST_ELEM *LST_GetHead(struct LST_LIST *pList)
++{
++      struct LST_ELEM *pElem;
++
++      DBC_Require(pList != NULL);
++
++      GT_1trace(LST_debugMask, GT_ENTER, "LST_GetHead: pList 0x%x\n", pList);
++
++      if (LST_IsEmpty(pList))
++              return NULL;
++
++      /* pElem is always valid because the list cannot be empty
++       * at this point */
++      pElem = pList->head.next;
++      pList->head.next = pElem->next;
++      pElem->next->prev = &pList->head;
++
++      return pElem->self;
++}
++
++/*
++ *  ======== LST_Init ========
++ *  Purpose:
++ *      Initialize LST module private state.
++ */
++bool LST_Init(void)
++{
++      GT_create(&LST_debugMask, "LS");        /* LS for LSt module */
++
++      GT_0trace(LST_debugMask, GT_5CLASS, "LST_Init\n");
++
++      return true;
++}
++
++/*
++ *  ======== LST_InitElem ========
++ *  Purpose:
++ *      Initializes a list element to default (cleared) values
++ */
++void LST_InitElem(struct LST_ELEM *pElem)
++{
++      DBC_Require(pElem != NULL);
++
++      GT_1trace(LST_debugMask, GT_ENTER, "LST_InitElem: pElem 0x%x\n", pElem);
++
++      if (pElem) {
++              pElem->next = NULL;
++              pElem->prev = NULL;
++              pElem->self = pElem;
++      }
++}
++
++/*
++ *  ======== LST_InsertBefore ========
++ *  Purpose:
++ *      Insert the element before the existing element.
++ */
++void LST_InsertBefore(struct LST_LIST *pList, struct LST_ELEM *pElem,
++                    struct LST_ELEM *pElemExisting)
++{
++      DBC_Require(pList != NULL);
++      DBC_Require(pElem != NULL);
++      DBC_Require(pElemExisting != NULL);
++
++      GT_3trace(LST_debugMask, GT_ENTER, "LST_InsertBefore: pList 0x%x, "
++                "pElem 0x%x pElemExisting 0x%x\n", pList, pElem,
++                pElemExisting);
++
++      pElemExisting->prev->next = pElem;
++      pElem->prev = pElemExisting->prev;
++      pElem->next = pElemExisting;
++      pElemExisting->prev = pElem;
++}
++
++/*
++ *  ======== LST_Next ========
++ *  Purpose:
++ *      Returns a pointer to the next element of the list, or NULL if the
++ *      next element is the head of the list or the list is empty.
++ */
++struct LST_ELEM *LST_Next(struct LST_LIST *pList, struct LST_ELEM *pCurElem)
++{
++      struct LST_ELEM *pNextElem = NULL;
++
++      DBC_Require(pList != NULL);
++      DBC_Require(pCurElem != NULL);
++
++      GT_2trace(LST_debugMask, GT_ENTER,
++                "LST_Next: pList 0x%x, pCurElem 0x%x\n",
++                pList, pCurElem);
++
++      if (!LST_IsEmpty(pList)) {
++              if (pCurElem->next != &pList->head)
++                      pNextElem = pCurElem->next;
++      }
++
++      return pNextElem;
++}
++
++/*
++ *  ======== LST_PutTail ========
++ *  Purpose:
++ *      Adds the specified element to the tail of the list
++ */
++void LST_PutTail(struct LST_LIST *pList, struct LST_ELEM *pElem)
++{
++      DBC_Require(pList != NULL);
++      DBC_Require(pElem != NULL);
++
++      GT_2trace(LST_debugMask, GT_ENTER,
++                "LST_PutTail: pList 0x%x, pElem 0x%x\n",
++                pList, pElem);
++
++      pElem->prev = pList->head.prev;
++      pElem->next = &pList->head;
++      pList->head.prev = pElem;
++      pElem->prev->next = pElem;
++
++      DBC_Ensure(!LST_IsEmpty(pList));
++}
++
++/*
++ *  ======== LST_RemoveElem ========
++ *  Purpose:
++ *      Removes (unlinks) the given element from the list, if the list is not
++ *      empty.  Does not free the list element.
++ */
++void LST_RemoveElem(struct LST_LIST *pList, struct LST_ELEM *pCurElem)
++{
++      DBC_Require(pList != NULL);
++      DBC_Require(pCurElem != NULL);
++
++      GT_2trace(LST_debugMask, GT_ENTER,
++                "LST_RemoveElem: pList 0x%x, pCurElem "
++                "0x%x\n", pList, pCurElem);
++
++      if (!LST_IsEmpty(pList)) {
++              pCurElem->prev->next = pCurElem->next;
++              pCurElem->next->prev = pCurElem->prev;
++
++              /* set elem fields to NULL to prevent illegal references */
++              pCurElem->next = NULL;
++              pCurElem->prev = NULL;
++      }
++}
++
+diff --git a/drivers/dsp/bridge/services/mem.c b/drivers/dsp/bridge/services/mem.c
+new file mode 100644
+index 0000000..0a10304
+--- /dev/null
++++ b/drivers/dsp/bridge/services/mem.c
+@@ -0,0 +1,599 @@
++/*
++ * mem.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== mem.c ========
++ *  Purpose:
++ *      Implementation of platform specific memory services.
++ *
++ *  Public Functions:
++ *      MEM_Alloc
++ *      MEM_AllocPhysMem
++ *      MEM_Calloc
++ *      MEM_Exit
++ *      MEM_FlushCache
++ *      MEM_Free
++ *      MEM_FreePhysMem
++ *      MEM_Init
++ *      MEM_ExtPhysPoolInit
++ *
++ *! Revision History:
++ *! =================
++ *! 18-Jan-2004 hp: Added support for External physical memory pool
++ *! 19-Apr-2004 sb: Added Alloc/Free PhysMem, FlushCache, VirtualToPhysical
++ *! 01-Sep-2001 ag: Code cleanup.
++ *! 02-May-2001 ag: MEM_[UnMap]LinearAddress revamped to align Phys to Virt.
++ *!            Set PAGE_PHYSICAL if phy addr <= 512MB. Opposite uSoft doc!
++ *! 29-Aug-2000 rr: MEM_LinearAddress does not check for 512MB for non-x86.
++ *! 28-Mar-2000 rr: MEM_LinearAddress changed.Handles address larger than 512MB
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *!            GT Changes.
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 16-Aug-1999 kc: modified for WinCE.
++ *! 20-Mar-1999 ag: SP 4 fix in MEM_UMBCalloc().
++ *!            Mdl offset now ORed not added to userBuf.
++ *! 23-Dec-1997 cr: Code review changes.
++ *! 08-Dec-1997 cr: Prepared for code review.
++ *! 24-Jun-1997 cr: Created.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/mem.h>
++#include <dspbridge/list.h>
++
++/*  ----------------------------------- Defines */
++#define MEM_512MB   0x1fffffff
++#define memInfoSign 0x464E494D        /* "MINF" (in reverse). */
++
++#ifdef DEBUG
++#define MEM_CHECK             /* Use to detect source of memory leaks */
++#endif
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask MEM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs;             /* module reference count */
++
++static bool extPhysMemPoolEnabled;
++
++struct extPhysMemPool {
++      u32 physMemBase;
++      u32 physMemSize;
++      u32 virtMemBase;
++      u32 nextPhysAllocPtr;
++};
++
++static struct extPhysMemPool extMemPool;
++
++/*  Information about each element allocated on heap */
++struct memInfo {
++      struct LST_ELEM link;           /* Must be first */
++      size_t size;
++      void *caller;
++      u32 dwSignature;        /* Should be last */
++};
++
++#ifdef MEM_CHECK
++
++/*
++ *  This structure holds a linked list to all memory elements allocated on
++ *  heap by DSP/BIOS Bridge. This is used to report memory leaks and free
++ *  such elements while removing the DSP/BIOS Bridge driver
++ */
++struct memMan {
++      struct LST_LIST lst;
++      spinlock_t lock;
++};
++
++static struct memMan mMan;
++
++/*
++ *  These functions are similar to LST_PutTail and LST_RemoveElem and are
++ *  duplicated here to make MEM independent of LST
++ */
++static inline void MLST_PutTail(struct LST_LIST *pList, struct LST_ELEM *pElem)
++{
++      pElem->prev = pList->head.prev;
++      pElem->next = &pList->head;
++      pList->head.prev = pElem;
++      pElem->prev->next = pElem;
++      pElem->self = pElem;
++}
++
++static inline void MLST_RemoveElem(struct LST_LIST *pList,
++                                 struct LST_ELEM *pCurElem)
++{
++      pCurElem->prev->next = pCurElem->next;
++      pCurElem->next->prev = pCurElem->prev;
++      pCurElem->next = NULL;
++      pCurElem->prev = NULL;
++}
++
++static void MEM_Check(void)
++{
++      struct memInfo *pMem;
++      struct LST_ELEM *last = &mMan.lst.head;
++      struct LST_ELEM *curr = mMan.lst.head.next;
++
++      if (!LST_IsEmpty(&mMan.lst)) {
++              GT_0trace(MEM_debugMask, GT_7CLASS, "*** MEMORY LEAK ***\n");
++              GT_0trace(MEM_debugMask, GT_7CLASS,
++                        "Addr      Size      Caller\n");
++              while (curr != last) {
++                      pMem = (struct memInfo *)curr;
++                      curr = curr->next;
++                      if ((u32)pMem > PAGE_OFFSET &&
++                          MEM_IsValidHandle(pMem, memInfoSign)) {
++                              GT_3trace(MEM_debugMask, GT_7CLASS,
++                                      "%lx  %d\t [<%p>]\n",
++                                      (u32) pMem + sizeof(struct memInfo),
++                                      pMem->size, pMem->caller);
++                              MLST_RemoveElem(&mMan.lst,
++                                              (struct LST_ELEM *) pMem);
++                              kfree(pMem);
++                      } else {
++                              GT_1trace(MEM_debugMask, GT_7CLASS,
++                                        "Invalid allocation or "
++                                        "Buffer underflow at %x\n",
++                                        (u32)pMem +   sizeof(struct memInfo));
++                              break;
++                      }
++              }
++      }
++      DBC_Ensure(LST_IsEmpty(&mMan.lst));
++}
++
++#endif
++
++void MEM_ExtPhysPoolInit(u32 poolPhysBase, u32 poolSize)
++{
++      u32 poolVirtBase;
++
++      /* get the virtual address for the physical memory pool passed */
++      poolVirtBase = (u32)ioremap(poolPhysBase, poolSize);
++
++      if ((void **)poolVirtBase == NULL) {
++              GT_0trace(MEM_debugMask, GT_7CLASS,
++                        "[PHYS_POOL]Mapping External "
++                        "physical memory to virt failed \n");
++              extPhysMemPoolEnabled = false;
++      } else {
++              extMemPool.physMemBase = poolPhysBase;
++              extMemPool.physMemSize = poolSize;
++              extMemPool.virtMemBase = poolVirtBase;
++              extMemPool.nextPhysAllocPtr = poolPhysBase;
++              extPhysMemPoolEnabled = true;
++              GT_3trace(MEM_debugMask, GT_1CLASS,
++                        "ExtMemory Pool details " "Pool"
++                        "Physical mem base = %0x " "Pool Physical mem size "
++                        "= %0x" "Pool Virtual mem base = %0x \n",
++                        poolPhysBase, poolSize, poolVirtBase);
++      }
++}
++
++static void MEM_ExtPhysPoolRelease(void)
++{
++      GT_0trace(MEM_debugMask, GT_1CLASS,
++                "Releasing External memory pool \n");
++      if (extPhysMemPoolEnabled) {
++              iounmap((void *)(extMemPool.virtMemBase));
++              extPhysMemPoolEnabled = false;
++      }
++}
++
++/*
++ *  ======== MEM_ExtPhysMemAlloc ========
++ *  Purpose:
++ *     Allocate physically contiguous, uncached memory from external memory pool
++ */
++
++static void *MEM_ExtPhysMemAlloc(u32 bytes, u32 align, OUT u32 *pPhysAddr)
++{
++      u32 newAllocPtr;
++      u32 offset;
++      u32 virtAddr;
++
++      GT_2trace(MEM_debugMask, GT_1CLASS,
++                "Ext Memory Allocation" "bytes=0x%x , "
++                "align=0x%x \n", bytes, align);
++      if (align == 0) {
++              GT_0trace(MEM_debugMask, GT_7CLASS,
++                        "ExtPhysical Memory Allocation "
++                        "No alignment request in allocation call !! \n");
++              align = 1;
++      }
++      if (bytes > ((extMemPool.physMemBase + extMemPool.physMemSize)
++          - extMemPool.nextPhysAllocPtr)) {
++              GT_1trace(MEM_debugMask, GT_7CLASS,
++                        "ExtPhysical Memory Allocation "
++                        "unable to allocate memory for bytes = 0x%x \n",
++                        bytes);
++              pPhysAddr = NULL;
++              return NULL;
++      } else {
++              offset = (extMemPool.nextPhysAllocPtr & (align - 1));
++              if (offset == 0)
++                      newAllocPtr = extMemPool.nextPhysAllocPtr;
++              else
++                      newAllocPtr = (extMemPool.nextPhysAllocPtr) +
++                                    (align - offset);
++              if ((newAllocPtr + bytes) <=
++                  (extMemPool.physMemBase + extMemPool.physMemSize)) {
++                      /* we can allocate */
++                      *pPhysAddr = newAllocPtr;
++                      extMemPool.nextPhysAllocPtr = newAllocPtr + bytes;
++                      virtAddr = extMemPool.virtMemBase + (newAllocPtr -
++                                 extMemPool.physMemBase);
++                      GT_2trace(MEM_debugMask, GT_1CLASS,
++                                "Ext Memory Allocation succedded "
++                                "phys address=0x%x , virtaddress=0x%x \n",
++                                newAllocPtr, virtAddr);
++                      return (void *)virtAddr;
++              } else {
++                      *pPhysAddr = 0;
++                      return NULL;
++              }
++      }
++}
++
++/*
++ *  ======== MEM_Alloc ========
++ *  Purpose:
++ *      Allocate memory from the paged or non-paged pools.
++ */
++void *MEM_Alloc(u32 cBytes, enum MEM_POOLATTRS type)
++{
++      struct memInfo *pMem = NULL;
++
++      GT_2trace(MEM_debugMask, GT_ENTER,
++                "MEM_Alloc: cBytes 0x%x\ttype 0x%x\n", cBytes, type);
++      if (cBytes > 0) {
++              switch (type) {
++              case MEM_NONPAGED:
++              /* If non-paged memory required, see note at top of file. */
++              case MEM_PAGED:
++#ifndef MEM_CHECK
++                                  pMem = kmalloc(cBytes,
++                                              (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++#else
++                      pMem = kmalloc(cBytes + sizeof(struct memInfo),
++                                              (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++                      if (pMem) {
++                              pMem->size = cBytes;
++                              pMem->caller = __builtin_return_address(0);
++                              pMem->dwSignature = memInfoSign;
++
++                              spin_lock(&mMan.lock);
++                              MLST_PutTail(&mMan.lst,
++                                          (struct LST_ELEM *)pMem);
++                              spin_unlock(&mMan.lock);
++
++                              pMem = (void *)((u32)pMem +
++                                      sizeof(struct memInfo));
++                      }
++#endif
++                      break;
++              case MEM_LARGEVIRTMEM:
++#ifndef MEM_CHECK
++                      /* FIXME - Replace with 'vmalloc' after BP fix */
++                                  pMem = __vmalloc(cBytes,
++                                  (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++#else
++                      /* FIXME - Replace with 'vmalloc' after BP fix */
++                      pMem = __vmalloc((cBytes + sizeof(struct memInfo)),
++                                  (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++                      if (pMem) {
++                              pMem->size = cBytes;
++                              pMem->caller = __builtin_return_address(0);
++                              pMem->dwSignature = memInfoSign;
++
++                              spin_lock(&mMan.lock);
++                              MLST_PutTail(&mMan.lst,
++                                          (struct LST_ELEM *) pMem);
++                              spin_unlock(&mMan.lock);
++
++                              pMem = (void *)((u32)pMem +
++                                      sizeof(struct memInfo));
++                      }
++#endif
++                      break;
++
++              default:
++                      GT_0trace(MEM_debugMask, GT_6CLASS,
++                                "MEM_Alloc: unexpected "
++                                "MEM_POOLATTRS value\n");
++                      break;
++              }
++      }
++
++      return pMem;
++}
++
++/*
++ *  ======== MEM_AllocPhysMem ========
++ *  Purpose:
++ *      Allocate physically contiguous, uncached memory
++ */
++void *MEM_AllocPhysMem(u32 cBytes, u32 ulAlign, OUT u32 *pPhysicalAddress)
++{
++      void *pVaMem = NULL;
++      dma_addr_t paMem;
++
++      DBC_Require(cRefs > 0);
++
++      GT_2trace(MEM_debugMask, GT_ENTER,
++                "MEM_AllocPhysMem: cBytes 0x%x\tulAlign"
++                "0x%x\n", cBytes, ulAlign);
++
++      if (cBytes > 0) {
++              if (extPhysMemPoolEnabled) {
++                      pVaMem = MEM_ExtPhysMemAlloc(cBytes, ulAlign,
++                                                  (u32 *)&paMem);
++              } else
++                      pVaMem = dma_alloc_coherent(NULL, cBytes, &paMem,
++                                              (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++              if (pVaMem == NULL) {
++                      *pPhysicalAddress = 0;
++                      GT_1trace(MEM_debugMask, GT_6CLASS,
++                                "MEM_AllocPhysMem failed: "
++                                "0x%x\n", pVaMem);
++              } else {
++                      *pPhysicalAddress = paMem;
++              }
++      }
++      return pVaMem;
++}
++
++/*
++ *  ======== MEM_Calloc ========
++ *  Purpose:
++ *      Allocate zero-initialized memory from the paged or non-paged pools.
++ */
++void *MEM_Calloc(u32 cBytes, enum MEM_POOLATTRS type)
++{
++      struct memInfo *pMem = NULL;
++
++      GT_2trace(MEM_debugMask, GT_ENTER,
++                "MEM_Calloc: cBytes 0x%x\ttype 0x%x\n",
++                cBytes, type);
++
++      if (cBytes > 0) {
++              switch (type) {
++              case MEM_NONPAGED:
++              /* If non-paged memory required, see note at top of file. */
++              case MEM_PAGED:
++#ifndef MEM_CHECK
++                                  pMem = kmalloc(cBytes,
++                                              (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++                      if (pMem)
++                              memset(pMem, 0, cBytes);
++
++#else
++                      pMem = kmalloc(cBytes + sizeof(struct memInfo),
++                                              (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++                      if (pMem) {
++                              memset((void *)((u32)pMem +
++                                      sizeof(struct memInfo)), 0, cBytes);
++                              pMem->size = cBytes;
++                              pMem->caller = __builtin_return_address(0);
++                              pMem->dwSignature = memInfoSign;
++                              spin_lock(&mMan.lock);
++                              MLST_PutTail(&mMan.lst,
++                                      (struct LST_ELEM *) pMem);
++                              spin_unlock(&mMan.lock);
++                              pMem = (void *)((u32)pMem +
++                                      sizeof(struct memInfo));
++                      }
++#endif
++                      break;
++              case MEM_LARGEVIRTMEM:
++#ifndef MEM_CHECK
++                      /* FIXME - Replace with 'vmalloc' after BP fix */
++                                  pMem = __vmalloc(cBytes,
++                                  (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++                      if (pMem)
++                              memset(pMem, 0, cBytes);
++
++#else
++                      /* FIXME - Replace with 'vmalloc' after BP fix */
++                      pMem = __vmalloc(cBytes + sizeof(struct memInfo),
++                                  (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++                      if (pMem) {
++                              memset((void *)((u32)pMem +
++                                      sizeof(struct memInfo)), 0, cBytes);
++                              pMem->size = cBytes;
++                              pMem->caller = __builtin_return_address(0);
++                              pMem->dwSignature = memInfoSign;
++                              spin_lock(&mMan.lock);
++                              MLST_PutTail(&mMan.lst, (struct LST_ELEM *)
++                                      pMem);
++                              spin_unlock(&mMan.lock);
++                              pMem = (void *)((u32)pMem +
++                                      sizeof(struct memInfo));
++                      }
++#endif
++                      break;
++              default:
++                      GT_1trace(MEM_debugMask, GT_6CLASS,
++                                "MEM_Calloc: unexpected "
++                                "MEM_POOLATTRS value 0x%x\n", type);
++                      break;
++              }
++      }
++
++      return pMem;
++}
++
++/*
++ *  ======== MEM_Exit ========
++ *  Purpose:
++ *      Discontinue usage of the MEM module.
++ */
++void MEM_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      GT_1trace(MEM_debugMask, GT_5CLASS, "MEM_Exit: cRefs 0x%x\n", cRefs);
++
++      cRefs--;
++#ifdef MEM_CHECK
++      if (cRefs == 0)
++              MEM_Check();
++
++#endif
++      MEM_ExtPhysPoolRelease();
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== MEM_FlushCache ========
++ *  Purpose:
++ *      Flush cache
++ */
++void MEM_FlushCache(void *pMemBuf, u32 cBytes, s32 FlushType)
++{
++      DBC_Require(cRefs > 0);
++
++      switch (FlushType) {
++      /* invalidate only */
++      case PROC_INVALIDATE_MEM:
++              dmac_inv_range(pMemBuf, pMemBuf + cBytes);
++              outer_inv_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
++                              cBytes));
++      break;
++      /* writeback only */
++      case PROC_WRITEBACK_MEM:
++              dmac_clean_range(pMemBuf, pMemBuf + cBytes);
++              outer_clean_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
++                                cBytes));
++      break;
++      /* writeback and invalidate */
++      case PROC_WRITEBACK_INVALIDATE_MEM:
++              dmac_flush_range(pMemBuf, pMemBuf + cBytes);
++              outer_flush_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
++                                cBytes));
++      break;
++      default:
++              GT_1trace(MEM_debugMask, GT_6CLASS, "MEM_FlushCache: invalid "
++                        "FlushMemType 0x%x\n", FlushType);
++      break;
++      }
++
++}
++
++
++/*
++ *  ======== MEM_Free ========
++ *  Purpose:
++ *      Free the given block of system memory.
++ */
++void MEM_Free(IN void *pMemBuf)
++{
++#ifdef MEM_CHECK
++      struct memInfo *pMem = (void *)((u32)pMemBuf - sizeof(struct memInfo));
++#endif
++
++      DBC_Require(pMemBuf != NULL);
++
++      GT_1trace(MEM_debugMask, GT_ENTER, "MEM_Free: pMemBufs 0x%x\n",
++                pMemBuf);
++
++      if (pMemBuf) {
++#ifndef MEM_CHECK
++              kfree(pMemBuf);
++#else
++              if (pMem) {
++                      if (pMem->dwSignature == memInfoSign) {
++                              spin_lock(&mMan.lock);
++                              MLST_RemoveElem(&mMan.lst,
++                                              (struct LST_ELEM *) pMem);
++                              spin_unlock(&mMan.lock);
++                              pMem->dwSignature = 0;
++                              kfree(pMem);
++                      } else {
++                              GT_1trace(MEM_debugMask, GT_7CLASS,
++                                      "Invalid allocation or "
++                                      "Buffer underflow at %x\n",
++                                      (u32) pMem + sizeof(struct memInfo));
++                      }
++              }
++#endif
++      }
++}
++
++/*
++ *  ======== MEM_FreePhysMem ========
++ *  Purpose:
++ *      Free the given block of physically contiguous memory.
++ */
++void MEM_FreePhysMem(void *pVirtualAddress, u32 pPhysicalAddress,
++                   u32 cBytes)
++{
++      DBC_Require(cRefs > 0);
++      DBC_Require(pVirtualAddress != NULL);
++
++      GT_1trace(MEM_debugMask, GT_ENTER, "MEM_FreePhysMem: pVirtualAddress "
++                "0x%x\n", pVirtualAddress);
++
++      if (!extPhysMemPoolEnabled)
++              dma_free_coherent(NULL, cBytes, pVirtualAddress,
++                               pPhysicalAddress);
++}
++
++/*
++ *  ======== MEM_Init ========
++ *  Purpose:
++ *      Initialize MEM module private state.
++ */
++bool MEM_Init(void)
++{
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++              GT_create(&MEM_debugMask, "MM");        /* MM for MeM module */
++
++#ifdef MEM_CHECK
++              mMan.lst.head.next = &mMan.lst.head;
++              mMan.lst.head.prev = &mMan.lst.head;
++              mMan.lst.head.self = NULL;
++              spin_lock_init(&mMan.lock);
++#endif
++
++      }
++
++      cRefs++;
++
++      GT_1trace(MEM_debugMask, GT_5CLASS, "MEM_Init: cRefs 0x%x\n", cRefs);
++
++      DBC_Ensure(cRefs > 0);
++
++      return true;
++}
+diff --git a/drivers/dsp/bridge/services/ntfy.c b/drivers/dsp/bridge/services/ntfy.c
+new file mode 100644
+index 0000000..2eff3eb
+--- /dev/null
++++ b/drivers/dsp/bridge/services/ntfy.c
+@@ -0,0 +1,329 @@
++/*
++ * ntfy.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== ntfyce.c ========
++ *  Purpose:
++ *      Manage lists of notification events.
++ *
++ *  Public Functions:
++ *      NTFY_Create
++ *      NTFY_Delete
++ *      NTFY_Exit
++ *      NTFY_Init
++ *      NTFY_Notify
++ *      NTFY_Register
++ *
++ *! Revision History:
++ *! =================
++ *! 06-Feb-2003 kc      Removed DSP_POSTMESSAGE related code.
++ *! 05-Nov-2001 kc      Updated DSP_HNOTIFICATION structure.
++ *! 10-May-2001 jeh     Removed SERVICES module init/exit from NTFY_Init/Exit.
++ *!                     NTFY_Register() returns DSP_ENOTIMPL for all but
++ *!                     DSP_SIGNALEVENT.
++ *! 12-Oct-2000 jeh     Use MEM_IsValidHandle().
++ *! 07-Sep-2000 jeh     Created.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/ntfy.h>
++
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++#define NTFY_SIGNATURE      0x5946544e        /* "YFTN" */
++
++/*
++ *  ======== NTFY_OBJECT ========
++ */
++struct NTFY_OBJECT {
++      u32 dwSignature;        /* For object validation */
++      struct LST_LIST *notifyList;    /* List of NOTIFICATION objects */
++      struct SYNC_CSOBJECT *hSync;    /* For critical sections */
++};
++
++/*
++ *  ======== NOTIFICATION ========
++ *  This object will be created when a client registers for events.
++ */
++struct NOTIFICATION {
++      struct LST_ELEM listElem;
++      u32 uEventMask; /* Events to be notified about */
++      u32 uNotifyType;        /* Type of notification to be sent */
++
++      /*
++       *  We keep a copy of the event name to check if the event has
++       *  already been registered. (SYNC also keeps a copy of the name).
++       */
++      char *pstrName;         /* Name of event */
++      HANDLE hEvent;          /* Handle for notification */
++      struct SYNC_OBJECT *hSync;
++};
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask NTFY_debugMask = { NULL, NULL };  /* GT trace variable */
++#endif
++
++/*  ----------------------------------- Function Prototypes */
++static void DeleteNotify(struct NOTIFICATION *pNotify);
++
++/*
++ *  ======== NTFY_Create ========
++ *  Purpose:
++ *      Create an empty list of notifications.
++ */
++DSP_STATUS NTFY_Create(struct NTFY_OBJECT **phNtfy)
++{
++      struct NTFY_OBJECT *pNtfy;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(phNtfy != NULL);
++
++      *phNtfy = NULL;
++      MEM_AllocObject(pNtfy, struct NTFY_OBJECT, NTFY_SIGNATURE);
++
++      if (pNtfy) {
++
++              status = SYNC_InitializeDPCCS(&pNtfy->hSync);
++              if (DSP_SUCCEEDED(status)) {
++                      pNtfy->notifyList = LST_Create();
++                      if (pNtfy->notifyList == NULL) {
++                              (void) SYNC_DeleteCS(pNtfy->hSync);
++                              MEM_FreeObject(pNtfy);
++                              status = DSP_EMEMORY;
++                      } else {
++                              *phNtfy = pNtfy;
++                      }
++              }
++      } else {
++              status = DSP_EMEMORY;
++      }
++
++      DBC_Ensure((DSP_FAILED(status) && *phNtfy == NULL) ||
++                (DSP_SUCCEEDED(status) && MEM_IsValidHandle((*phNtfy),
++                NTFY_SIGNATURE)));
++
++      return status;
++}
++
++/*
++ *  ======== NTFY_Delete ========
++ *  Purpose:
++ *      Free resources allocated in NTFY_Create.
++ */
++void NTFY_Delete(struct NTFY_OBJECT *hNtfy)
++{
++      struct NOTIFICATION *pNotify;
++
++      DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
++
++      /* Remove any elements remaining in list */
++      if (hNtfy->notifyList) {
++              while ((pNotify = (struct NOTIFICATION *)LST_GetHead(hNtfy->
++                                                              notifyList))) {
++                      DeleteNotify(pNotify);
++              }
++              DBC_Assert(LST_IsEmpty(hNtfy->notifyList));
++              LST_Delete(hNtfy->notifyList);
++      }
++      if (hNtfy->hSync)
++              (void)SYNC_DeleteCS(hNtfy->hSync);
++
++      MEM_FreeObject(hNtfy);
++}
++
++/*
++ *  ======== NTFY_Exit ========
++ *  Purpose:
++ *      Discontinue usage of NTFY module.
++ */
++void NTFY_Exit(void)
++{
++      GT_0trace(NTFY_debugMask, GT_5CLASS, "Entered NTFY_Exit\n");
++}
++
++/*
++ *  ======== NTFY_Init ========
++ *  Purpose:
++ *      Initialize the NTFY module.
++ */
++bool NTFY_Init(void)
++{
++      GT_create(&NTFY_debugMask, "NY");       /* "NY" for NtfY */
++
++      GT_0trace(NTFY_debugMask, GT_5CLASS, "NTFY_Init()\n");
++
++      return true;
++}
++
++/*
++ *  ======== NTFY_Notify ========
++ *  Purpose:
++ *      Execute notify function (signal event) for every
++ *      element in the notification list that is to be notified about the
++ *      event specified in uEventMask.
++ */
++void NTFY_Notify(struct NTFY_OBJECT *hNtfy, u32 uEventMask)
++{
++      struct NOTIFICATION *pNotify;
++
++      DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
++
++      /*
++       *  Go through notifyList and notify all clients registered for
++       *  uEventMask events.
++       */
++
++      (void) SYNC_EnterCS(hNtfy->hSync);
++
++      pNotify = (struct NOTIFICATION *)LST_First(hNtfy->notifyList);
++      while (pNotify != NULL) {
++              if (pNotify->uEventMask & uEventMask) {
++                      /* Notify */
++                      if (pNotify->uNotifyType == DSP_SIGNALEVENT)
++                              (void)SYNC_SetEvent(pNotify->hSync);
++
++              }
++              pNotify = (struct NOTIFICATION *)LST_Next(hNtfy->notifyList,
++                        (struct LST_ELEM *)pNotify);
++      }
++
++      (void) SYNC_LeaveCS(hNtfy->hSync);
++}
++
++/*
++ *  ======== NTFY_Register ========
++ *  Purpose:
++ *      Add a notification element to the list. If the notification is already
++ *      registered, and uEventMask != 0, the notification will get posted for
++ *      events specified in the new event mask. If the notification is already
++ *      registered and uEventMask == 0, the notification will be unregistered.
++ */
++DSP_STATUS NTFY_Register(struct NTFY_OBJECT *hNtfy,
++                       struct DSP_NOTIFICATION *hNotification,
++                       u32 uEventMask, u32 uNotifyType)
++{
++      struct NOTIFICATION *pNotify;
++      struct SYNC_ATTRS syncAttrs;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
++
++      if (hNotification == NULL)
++              status = DSP_EHANDLE;
++
++      /* Return DSP_ENOTIMPL if uNotifyType is not supported */
++      if (DSP_SUCCEEDED(status)) {
++              if (!IsValidNotifyMask(uNotifyType))
++                      status = DSP_ENOTIMPL;
++
++      }
++
++      if (DSP_FAILED(status))
++              return status;
++
++      (void)SYNC_EnterCS(hNtfy->hSync);
++
++      pNotify = (struct NOTIFICATION *)LST_First(hNtfy->notifyList);
++      while (pNotify != NULL) {
++              /* If there is more than one notification type, each
++               * type may require its own handler code.  */
++
++              if (hNotification->handle == pNotify->hSync) {
++                      /* found */
++                      break;
++              }
++              pNotify = (struct NOTIFICATION *)LST_Next(hNtfy->notifyList,
++                        (struct LST_ELEM *)pNotify);
++      }
++      if (pNotify == NULL) {
++              /* Not registered */
++              if (uEventMask == 0) {
++                      status = DSP_EVALUE;
++              } else {
++                      /* Allocate NOTIFICATION object, add to list */
++                      pNotify = MEM_Calloc(sizeof(struct NOTIFICATION),
++                                           MEM_PAGED);
++                      if (pNotify == NULL)
++                              status = DSP_EMEMORY;
++
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      LST_InitElem((struct LST_ELEM *) pNotify);
++                       /* If there is more than one notification type, each
++                       * type may require its own handler code. */
++                      status = SYNC_OpenEvent(&pNotify->hSync, &syncAttrs);
++                      hNotification->handle = pNotify->hSync;
++
++                      if (DSP_SUCCEEDED(status)) {
++                              pNotify->uEventMask = uEventMask;
++                              pNotify->uNotifyType = uNotifyType;
++                              LST_PutTail(hNtfy->notifyList,
++                                         (struct LST_ELEM *)pNotify);
++                      } else {
++                              DeleteNotify(pNotify);
++                      }
++              }
++      } else {
++              /* Found in list */
++              if (uEventMask == 0) {
++                      /* Remove from list and free */
++                      LST_RemoveElem(hNtfy->notifyList,
++                                    (struct LST_ELEM *)pNotify);
++                      DeleteNotify(pNotify);
++              } else {
++                      /* Update notification mask (type shouldn't change) */
++                      pNotify->uEventMask = uEventMask;
++              }
++      }
++      (void)SYNC_LeaveCS(hNtfy->hSync);
++      return status;
++}
++
++/*
++ *  ======== DeleteNotify ========
++ *  Purpose:
++ *      Free the notification object.
++ */
++static void DeleteNotify(struct NOTIFICATION *pNotify)
++{
++      if (pNotify->hSync)
++              (void) SYNC_CloseEvent(pNotify->hSync);
++
++      if (pNotify->pstrName)
++              MEM_Free(pNotify->pstrName);
++
++      MEM_Free(pNotify);
++}
++
+diff --git a/drivers/dsp/bridge/services/reg.c b/drivers/dsp/bridge/services/reg.c
+new file mode 100644
+index 0000000..0d85f41
+--- /dev/null
++++ b/drivers/dsp/bridge/services/reg.c
+@@ -0,0 +1,196 @@
++/*
++ * reg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== regce.c ========
++ *  Purpose:
++ *      Provide registry functions.
++ *
++ *  Public Functions:
++ *      REG_DeleteValue
++ *      REG_EnumValue
++ *      REG_Exit
++ *      REG_GetValue
++ *      REG_Init
++ *      REG_SetValue
++ *
++ *! Revision History:
++ *! ================
++ *
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/*  ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/reg.h>
++#include <regsup.h>
++
++#if GT_TRACE
++struct GT_Mask REG_debugMask = { NULL, NULL };        /* GT trace var. */
++#endif
++
++/*
++ *  ======== REG_DeleteValue ========
++ *  Deletes a registry entry value.  NOTE:  A registry entry value is not the
++ *  same as *  a registry key.
++ */
++DSP_STATUS REG_DeleteValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
++                         IN CONST char *pstrValue)
++{
++      DSP_STATUS status;
++      DBC_Require(pstrSubkey && pstrValue);
++      DBC_Require(phKey == NULL);
++       DBC_Require(strlen(pstrSubkey) < REG_MAXREGPATHLENGTH);
++       DBC_Require(strlen(pstrValue) < REG_MAXREGPATHLENGTH);
++
++      GT_0trace(REG_debugMask, GT_ENTER, "REG_DeleteValue: entered\n");
++
++      /*  Note that we don't use phKey */
++      if (regsupDeleteValue(pstrSubkey, pstrValue) == DSP_SOK)
++              status = DSP_SOK;
++      else
++              status = DSP_EFAIL;
++
++      return status;
++}
++
++/*
++ *  ======== REG_EnumValue ========
++ *  Enumerates a registry key and retrieve values stored under the key.
++ *  We will assume the input pdwValueSize is smaller than
++ *  REG_MAXREGPATHLENGTH for implementation purposes.
++ */
++DSP_STATUS REG_EnumValue(IN HANDLE *phKey, IN u32 dwIndex,
++                       IN CONST char *pstrKey, IN OUT char *pstrValue,
++                       IN OUT u32 *pdwValueSize, IN OUT char *pstrData,
++                       IN OUT u32 *pdwDataSize)
++{
++      DSP_STATUS status;
++
++      DBC_Require(pstrKey && pstrValue && pdwValueSize && pstrData &&
++                  pdwDataSize);
++      DBC_Require(*pdwValueSize <= REG_MAXREGPATHLENGTH);
++      DBC_Require(phKey == NULL);
++       DBC_Require(strlen(pstrKey) < REG_MAXREGPATHLENGTH);
++
++      GT_0trace(REG_debugMask, GT_ENTER, "REG_EnumValue: entered\n");
++
++      status = regsupEnumValue(dwIndex, pstrKey, pstrValue, pdwValueSize,
++                               pstrData, pdwDataSize);
++
++      return status;
++}
++
++/*
++ *  ======== REG_Exit ========
++ *  Discontinue usage of the REG module.
++ */
++void REG_Exit(void)
++{
++      GT_0trace(REG_debugMask, GT_5CLASS, "REG_Exit\n");
++
++      regsupExit();
++}
++
++/*
++ *  ======== REG_GetValue ========
++ *  Retrieve a value from the registry.
++ */
++DSP_STATUS REG_GetValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
++                      IN CONST char *pstrValue, OUT u8 *pbData,
++                      IN OUT u32 *pdwDataSize)
++{
++      DSP_STATUS status;
++
++      DBC_Require(pstrSubkey && pstrValue && pbData);
++      DBC_Require(phKey == NULL);
++       DBC_Require(strlen(pstrSubkey) < REG_MAXREGPATHLENGTH);
++       DBC_Require(strlen(pstrValue) < REG_MAXREGPATHLENGTH);
++
++      GT_0trace(REG_debugMask, GT_ENTER, "REG_GetValue: entered\n");
++
++      /*  We need to use regsup calls...  */
++      /*  ...for now we don't need the key handle or  */
++      /*  the subkey, all we need is the value to lookup.  */
++      if (regsupGetValue((char *)pstrValue, pbData, pdwDataSize) == DSP_SOK)
++              status = DSP_SOK;
++      else
++              status = DSP_EFAIL;
++
++      return status;
++}
++
++/*
++ *  ======== REG_Init ========
++ *  Initialize the REG module's private state.
++ */
++bool REG_Init(void)
++{
++      bool fInit;
++
++      GT_create(&REG_debugMask, "RG");        /* RG for ReG */
++
++      fInit = regsupInit();
++
++      GT_0trace(REG_debugMask, GT_5CLASS, "REG_Init\n");
++
++      return fInit;
++}
++
++/*
++ *  ======== REG_SetValue ========
++ *  Set a value in the registry.
++ */
++DSP_STATUS REG_SetValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
++                      IN CONST char *pstrValue, IN CONST u32 dwType,
++                      IN u8 *pbData, IN u32 dwDataSize)
++{
++      DSP_STATUS status;
++
++      DBC_Require(pstrValue && pbData);
++      DBC_Require(phKey == NULL);
++      DBC_Require(dwDataSize > 0);
++       DBC_Require(strlen(pstrValue) < REG_MAXREGPATHLENGTH);
++
++      /*  We need to use regsup calls...  */
++      /*  ...for now we don't need the key handle or  */
++      /*  the subkey, all we need is the value to lookup.  */
++      if (regsupSetValue((char *)pstrValue, pbData, dwDataSize) == DSP_SOK)
++              status = DSP_SOK;
++      else
++              status = DSP_EFAIL;
++
++      return status;
++}
++
+diff --git a/drivers/dsp/bridge/services/regsup.c b/drivers/dsp/bridge/services/regsup.c
+new file mode 100644
+index 0000000..5251b68
+--- /dev/null
++++ b/drivers/dsp/bridge/services/regsup.c
+@@ -0,0 +1,368 @@
++/*
++ * regsup.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== regsup.c ========
++ *  Purpose:
++ *      Provide registry support functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 28-May-2002  map: Integrated PSI's dspimage update mechanism
++ *! 11-May-2002  gp:  Turned PERF "on".
++ *! 21-May-2002  map: Fixed bug in SetValue - if resizing datasize, set
++ *!                 new size too
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/dbreg.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/csl.h>
++
++/*  ----------------------------------- This */
++#include <regsup.h>
++
++struct RegValueStruct {
++      char name[BRIDGE_MAX_NAME_SIZE];   /*  Name of a given value entry  */
++      u32 dataSize;           /*  Size of the data  */
++      void *pData;            /*  Pointer to the actual data  */
++};
++
++struct RegKeyStruct {
++      /*The current number of value entries this key has*/
++      u32 numValueEntries;
++      /* Array of value entries */
++      struct RegValueStruct values[BRIDGE_MAX_NUM_REG_ENTRIES];
++};
++
++
++/*  Pointer to the registry support key  */
++static struct RegKeyStruct *pRegKey;
++
++#if GT_TRACE
++extern struct GT_Mask REG_debugMask;  /* GT trace var. */
++/*
++ *  ======== printS ========
++ *  Purpose:
++ *      Displays printable characters in pBuf, if any.
++ */
++static inline void printS(void *pBuf)
++{
++      int pos = 0;
++      if (*(REG_debugMask).flags & (GT_2CLASS)) {
++              while (*(u8 *)((pBuf)+pos) >= ' ' &&
++                     *(u8 *)((pBuf)+pos) <= '~') {
++                      GT_1trace(REG_debugMask, GT_2CLASS, "%c",
++                                      *(u8 *)((pBuf) + pos++));
++              }
++
++              GT_0trace(REG_debugMask, GT_2CLASS, "\n");
++      }
++}
++#else
++#define printS(pBuf)
++#endif
++
++/*
++ *  ======== regsupInit ========
++ *  Purpose:
++ *      Initialize the Registry Support module's private state.
++ */
++bool regsupInit(void)
++{
++      if (pRegKey != NULL)
++              return true;
++
++      /*  Need to allocate and setup our registry.  */
++      pRegKey = MEM_Calloc(sizeof(struct RegKeyStruct), MEM_NONPAGED);
++      if (pRegKey == NULL)
++              return false;
++
++      return true;
++}
++
++/*
++ *  ======== regsupExit ========
++ *  Purpose:
++ *      Release all registry support allocations.
++ */
++void regsupExit(void)
++{
++      u32 i;
++
++      /*  Make sure data has actually been allocated.  */
++      if (pRegKey == NULL) {
++              /*  Nothing initialized.return!  */
++              return;
++      }
++
++      GT_1trace(REG_debugMask, GT_2CLASS, "pRegKey->numValueEntries %d\n",
++                pRegKey->numValueEntries);
++
++      /*  Now go through each entry and free all resources.  */
++      for (i = 0; ((i < BRIDGE_MAX_NUM_REG_ENTRIES) &&
++          (i < pRegKey->numValueEntries)); i++) {
++              if (pRegKey->values[i].name[0] != '\0') {
++                      /*  We have a valid entry.free it up!  */
++                      if (pRegKey->values[i].pData != NULL) {
++                              GT_3trace(REG_debugMask, GT_2CLASS,
++                                        "E %d\t %s DATA %x ", i,
++                                        pRegKey->values[i].name,
++                                        *(u32 *)pRegKey->values[i].pData);
++                              printS((u8 *)(pRegKey->values[i].pData));
++                              MEM_Free(pRegKey->values[i].pData);
++                      }
++                      pRegKey->values[i].pData = NULL;
++                      pRegKey->values[i].dataSize = 0;
++                      pRegKey->values[i].name[0] = '\0';
++              }
++      }
++
++      /*  Now that all of the resources are freed up, free the main one!  */
++      MEM_Free(pRegKey);
++
++      /*  Don't forget to NULL out the global entry!  */
++      pRegKey = NULL;
++}
++
++/*
++ *  ======== regsupGetValue ========
++ *  Purpose:
++ *      Get the value of the entry having the given name.
++ */
++DSP_STATUS regsupGetValue(char *valName, void *pBuf, u32 *dataSize)
++{
++      DSP_STATUS retVal = DSP_EFAIL;
++      u32 i;
++
++      /*  Need to search through the entries looking for the right one.  */
++      for (i = 0; i < pRegKey->numValueEntries; i++) {
++              /*  See if the name matches.  */
++               if (strncmp(pRegKey->values[i].name, valName,
++                  BRIDGE_MAX_NAME_SIZE) == 0) {
++
++                      /*  We have a match!  Copy out the data.  */
++                      memcpy(pBuf, pRegKey->values[i].pData,
++                             pRegKey->values[i].dataSize);
++
++                      /*  Get the size for the caller.  */
++                      *dataSize = pRegKey->values[i].dataSize;
++
++                      /*  Set our status to good and exit.  */
++                      retVal = DSP_SOK;
++                      break;
++              }
++      }
++
++      if (DSP_SUCCEEDED(retVal)) {
++              GT_2trace(REG_debugMask, GT_2CLASS, "G %s DATA %x ", valName,
++                        *(u32 *)pBuf);
++              printS((u8 *)pBuf);
++      } else {
++              GT_1trace(REG_debugMask, GT_3CLASS, "G %s FAILED\n", valName);
++      }
++
++      return retVal;
++}
++
++/*
++ *  ======== regsupSetValue ========
++ *  Purpose:
++ *      Sets the value of the entry having the given name.
++ */
++DSP_STATUS regsupSetValue(char *valName, void *pBuf, u32 dataSize)
++{
++      DSP_STATUS retVal = DSP_EFAIL;
++      u32 i;
++
++      GT_2trace(REG_debugMask, GT_2CLASS, "S %s DATA %x ", valName,
++                *(u32 *)pBuf);
++      printS((u8 *)pBuf);
++
++      /*  Need to search through the entries looking for the right one.  */
++      for (i = 0; i < pRegKey->numValueEntries; i++) {
++              /*  See if the name matches.  */
++               if (strncmp(pRegKey->values[i].name, valName,
++                  BRIDGE_MAX_NAME_SIZE) == 0) {
++                      /*  Make sure the new data size is the same.  */
++                      if (dataSize != pRegKey->values[i].dataSize) {
++                              /*  The caller needs a different data size!  */
++                              MEM_Free(pRegKey->values[i].pData);
++                              pRegKey->values[i].pData = MEM_Alloc(dataSize,
++                                                         MEM_NONPAGED);
++                              if (pRegKey->values[i].pData == NULL)
++                                      break;
++
++                      }
++
++                      /*  We have a match!  Copy out the data.  */
++                      memcpy(pRegKey->values[i].pData, pBuf, dataSize);
++
++                      /* Reset datasize - overwrite if new or same */
++                      pRegKey->values[i].dataSize = dataSize;
++
++                      /*  Set our status to good and exit.  */
++                      retVal = DSP_SOK;
++                      break;
++              }
++      }
++
++      /*  See if we found a match or if this is a new entry  */
++      if (i == pRegKey->numValueEntries) {
++              /*  No match, need to make a new entry  */
++              /*  First check to see if we can make any more entries.  */
++              if (pRegKey->numValueEntries < BRIDGE_MAX_NUM_REG_ENTRIES) {
++                       strncpy(pRegKey->values[pRegKey->numValueEntries].name,
++                               valName, BRIDGE_MAX_NAME_SIZE);
++                      pRegKey->values[pRegKey->numValueEntries].pData =
++                                      MEM_Alloc(dataSize, MEM_NONPAGED);
++                      if (pRegKey->values[pRegKey->numValueEntries].pData !=
++                                                                      NULL) {
++                              memcpy(pRegKey->
++                                      values[pRegKey->numValueEntries].pData,
++                                      pBuf, dataSize);
++                              pRegKey->
++                                  values[pRegKey->numValueEntries].dataSize =
++                                  dataSize;
++                              pRegKey->numValueEntries++;
++                              retVal = DSP_SOK;
++                      }
++              } else {
++                      GT_0trace(REG_debugMask, GT_7CLASS,
++                                "MAX NUM REG ENTRIES REACHED\n");
++              }
++      }
++
++      return retVal;
++}
++
++/*
++ *  ======== regsupEnumValue ========
++ *  Purpose:
++ *      Returns registry "values" and their "data" under a (sub)key.
++ */
++DSP_STATUS regsupEnumValue(IN u32 dwIndex, IN CONST char *pstrKey,
++                         IN OUT char *pstrValue, IN OUT u32 *pdwValueSize,
++                         IN OUT char *pstrData, IN OUT u32 *pdwDataSize)
++{
++      DSP_STATUS retVal = REG_E_INVALIDSUBKEY;
++      u32 i;
++       u32 dwKeyLen;
++      u32 count = 0;
++
++       DBC_Require(pstrKey);
++       dwKeyLen = strlen(pstrKey);
++
++      /*  Need to search through the entries looking for the right one.  */
++      for (i = 0; i < pRegKey->numValueEntries; i++) {
++              /*  See if the name matches.  */
++               if ((strncmp(pRegKey->values[i].name, pstrKey,
++                  dwKeyLen) == 0) && count++ == dwIndex) {
++                      /*  We have a match!  Copy out the data.  */
++                      memcpy(pstrData, pRegKey->values[i].pData,
++                              pRegKey->values[i].dataSize);
++                      /*  Get the size for the caller.  */
++                      *pdwDataSize = pRegKey->values[i].dataSize;
++                       *pdwValueSize = strlen(&(pRegKey->
++                                              values[i].name[dwKeyLen]));
++                       strncpy(pstrValue,
++                                  &(pRegKey->values[i].name[dwKeyLen]),
++                                  *pdwValueSize + 1);
++                      GT_3trace(REG_debugMask, GT_2CLASS,
++                                "E Key %s, Value %s, Data %x ",
++                                pstrKey, pstrValue, *(u32 *)pstrData);
++                      printS((u8 *)pstrData);
++                      /*  Set our status to good and exit.  */
++                      retVal = DSP_SOK;
++                      break;
++              }
++      }
++
++      if (count && DSP_FAILED(retVal))
++              retVal = REG_E_NOMOREITEMS;
++
++      return retVal;
++}
++
++/*
++ *  ======== regsupDeleteValue ========
++ */
++DSP_STATUS regsupDeleteValue(IN CONST char *pstrSubkey,
++                          IN CONST char *pstrValue)
++{
++      DSP_STATUS retVal = DSP_EFAIL;
++      u32 i;
++
++      for (i = 0; ((i < BRIDGE_MAX_NUM_REG_ENTRIES) &&
++          (i < pRegKey->numValueEntries)); i++) {
++              /*  See if the name matches...  */
++               if (strncmp(pRegKey->values[i].name, pstrValue,
++                  BRIDGE_MAX_NAME_SIZE) == 0) {
++                      /* We have a match!  Delete this key.  To delete a
++                       * key, we free all resources associated with this
++                       * key and, if we're not already the last entry in
++                       * the array, we copy that entry into this deleted
++                       * key.
++                       */
++                      MEM_Free(pRegKey->values[i].pData);
++                      if ((pRegKey->numValueEntries - 1) == i) {
++                              /* we're deleting the last one */
++                              pRegKey->values[i].name[0] = '\0';
++                              pRegKey->values[i].dataSize = 0;
++                              pRegKey->values[i].pData = NULL;
++                      } else {
++                              /* move the last one here */
++                               strncpy(pRegKey->values[i].name, pRegKey->
++                                  values[pRegKey->numValueEntries - 1].name,
++                                  BRIDGE_MAX_NAME_SIZE);
++                              pRegKey->values[i].dataSize =
++                                  pRegKey->
++                                  values[pRegKey->numValueEntries-1].dataSize;
++                              pRegKey->values[i].pData =
++                                  pRegKey->
++                                  values[pRegKey->numValueEntries-1].pData;
++                              /* don't have to do this, but for
++                               * the paranoid... */
++                              pRegKey->
++                                  values[pRegKey->numValueEntries-1].name[0] =
++                                  '\0';
++                      }
++
++                      /* another one bites the dust. */
++                      pRegKey->numValueEntries--;
++
++                      /*  Set our status to good and exit...  */
++                      retVal = DSP_SOK;
++                      break;
++              }
++      }
++      return retVal;
++
++}
++
+diff --git a/drivers/dsp/bridge/services/regsup.h b/drivers/dsp/bridge/services/regsup.h
+new file mode 100644
+index 0000000..011be52
+--- /dev/null
++++ b/drivers/dsp/bridge/services/regsup.h
+@@ -0,0 +1,58 @@
++/*
++ * regsup.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== regsup.h ========
++ *
++ *! Revision History
++ *! ================
++ */
++
++#ifndef _REGSUP_H_
++#define _REGSUP_H_
++
++#define BRIDGE_MAX_NAME_SIZE                     MAXREGPATHLENGTH
++#define BRIDGE_MAX_NUM_REG_ENTRIES               52
++
++/*  Init function. MUST be called BEFORE any calls are  */
++/*  made into this psuedo-registry!!!  Returns TRUE/FALSE for SUCCESS/ERROR  */
++extern bool regsupInit(void);
++
++/*  Release all registry support allocations.  */
++extern void regsupExit(void);
++
++/*
++ *  ======== regsupDeleteValue ========
++ */
++extern DSP_STATUS regsupDeleteValue(IN CONST char *pstrSubkey,
++                                  IN CONST char *pstrValue);
++/*  Get the value of the entry having the given name.  Returns DSP_SOK  */
++/*  if an entry was found and the value retrieved.  Returns DSP_EFAIL
++ *  otherwise.*/
++extern DSP_STATUS regsupGetValue(char *valName, void *pBuf, u32 *dataSize);
++
++/*  Sets the value of the entry having the given name.  Returns DSP_SOK  */
++/*  if an entry was found and the value set.  Returns DSP_EFAIL otherwise.  */
++extern DSP_STATUS regsupSetValue(char *valName, void *pBuf, u32 dataSize);
++
++/*  Returns registry "values" and their "data" under a (sub)key. */
++extern DSP_STATUS regsupEnumValue(IN u32 dwIndex, IN CONST char *pstrKey,
++                      IN OUT char *pstrValue, IN OUT u32 *pdwValueSize,
++                      IN OUT char *pstrData, IN OUT u32 *pdwDataSize);
++
++#endif
++
+diff --git a/drivers/dsp/bridge/services/services.c b/drivers/dsp/bridge/services/services.c
+new file mode 100644
+index 0000000..346007e
+--- /dev/null
++++ b/drivers/dsp/bridge/services/services.c
+@@ -0,0 +1,193 @@
++/*
++ * services.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== services.c ========
++ *  Purpose:
++ *      Provide SERVICES loading.
++ *
++ *  Public Functions:
++ *      SERVICES_Exit
++ *      SERVICES_Init
++ *
++ *
++ *! Revision History
++ *! ================
++ *! 20-Nov-2000 rr: NTFY_Init/Exit added.
++ *! 06-Jul-2000 rr: PROC prefix changed to PRCS to accomodate RM.
++ *! 01-Feb-2000 kc: Created.
++ */
++
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/dbg.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/kfile.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/reg.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/clk.h>
++#include <dspbridge/util.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/services.h>
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask SERVICES_debugMask = { NULL, NULL };  /* GT trace var. */
++#endif
++
++static u32 cRefs;             /* SERVICES module reference count */
++
++/*
++ *  ======== SERVICES_Exit ========
++ *  Purpose:
++ *      Discontinue usage of module; free resources when reference count
++ *      reaches 0.
++ */
++void SERVICES_Exit(void)
++{
++      DBC_Require(cRefs > 0);
++
++      GT_1trace(SERVICES_debugMask, GT_5CLASS, "SERVICES_Exit: cRefs 0x%x\n",
++               cRefs);
++
++      cRefs--;
++      if (cRefs == 0) {
++              /* Uninitialize all SERVICES modules here */
++              NTFY_Exit();
++              UTIL_Exit();
++              SYNC_Exit();
++              CLK_Exit();
++              REG_Exit();
++              LST_Exit();
++              KFILE_Exit();
++              DPC_Exit();
++              DBG_Exit();
++              CSL_Exit();
++              CFG_Exit();
++              MEM_Exit();
++
++              GT_exit();
++      }
++
++      DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ *  ======== SERVICES_Init ========
++ *  Purpose:
++ *      Initializes SERVICES modules.
++ */
++bool SERVICES_Init(void)
++{
++      bool fInit = true;
++       bool fCFG, fCSL, fDBG, fDPC, fKFILE, fLST, fMEM;
++       bool fREG, fSYNC, fCLK, fUTIL, fNTFY;
++
++      DBC_Require(cRefs >= 0);
++
++      if (cRefs == 0) {
++
++              GT_init();
++              GT_create(&SERVICES_debugMask, "OS");   /* OS for OSal */
++
++              GT_0trace(SERVICES_debugMask, GT_ENTER,
++                       "SERVICES_Init: entered\n");
++
++              /* Perform required initialization of SERVICES modules. */
++              fMEM = MEM_Init();
++              fREG = REG_Init();
++              fCFG = CFG_Init();
++              fCSL = CSL_Init();
++              fDBG = DBG_Init();
++              fDPC = DPC_Init();
++              fKFILE = KFILE_Init();
++              fLST = LST_Init();
++              /* fREG = REG_Init(); */
++              fSYNC = SYNC_Init();
++              fCLK  = CLK_Init();
++              fUTIL = UTIL_Init();
++              fNTFY = NTFY_Init();
++
++               fInit = fCFG && fCSL && fDBG && fDPC && fKFILE &&
++                       fLST && fMEM && fREG && fSYNC && fCLK && fUTIL;
++
++              if (!fInit) {
++                      if (fNTFY)
++                              NTFY_Exit();
++
++                      if (fUTIL)
++                              UTIL_Exit();
++
++                      if (fSYNC)
++                              SYNC_Exit();
++
++                      if (fCLK)
++                              CLK_Exit();
++
++                      if (fREG)
++                              REG_Exit();
++
++                      if (fLST)
++                              LST_Exit();
++
++                      if (fKFILE)
++                              KFILE_Exit();
++
++                      if (fDPC)
++                              DPC_Exit();
++
++                      if (fDBG)
++                              DBG_Exit();
++
++                      if (fCSL)
++                              CSL_Exit();
++
++                      if (fCFG)
++                              CFG_Exit();
++
++                      if (fMEM)
++                              MEM_Exit();
++
++              }
++      }
++
++      if (fInit)
++              cRefs++;
++
++      GT_1trace(SERVICES_debugMask, GT_5CLASS, "SERVICES_Init: cRefs 0x%x\n",
++               cRefs);
++
++      DBC_Ensure((fInit && (cRefs > 0)) || (!fInit && (cRefs >= 0)));
++
++      return fInit;
++}
++
+diff --git a/drivers/dsp/bridge/services/sync.c b/drivers/dsp/bridge/services/sync.c
+new file mode 100644
+index 0000000..7ab9347
+--- /dev/null
++++ b/drivers/dsp/bridge/services/sync.c
+@@ -0,0 +1,602 @@
++/*
++ * sync.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== sync.c ========
++ *  Purpose:
++ *      Synchronization services.
++ *
++ *  Public Functions:
++ *      SYNC_CloseEvent
++ *      SYNC_DeleteCS
++ *      SYNC_EnterCS
++ *      SYNC_Exit
++ *      SYNC_Init
++ *      SYNC_InitializeCS
++ *      SYNC_LeaveCS
++ *      SYNC_OpenEvent
++ *      SYNC_ResetEvent
++ *      SYNC_SetEvent
++ *      SYNC_WaitOnEvent
++ *      SYNC_WaitOnMultipleEvents
++ *
++ *! Revision History:
++ *! ================
++ *! 05-Nov-2001 kc: Minor cosmetic changes.
++ *! 05-Oct-2000 jeh Added SYNC_WaitOnMultipleEvents().
++ *! 10-Aug-2000 rr: SYNC_PostMessage added.
++ *! 10-Jul-2000 jeh Modified SYNC_OpenEvent() to handle NULL attrs.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *!            GT Changes.
++ *! 01-Dec-1999 ag: Added optional named event creation in SYNC_OpenEvent().
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 22-Sep-1999 kc: Modified from sync95.c.
++ *! 05-Aug-1996 gp: Created.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/*  ----------------------------------- This */
++#include <dspbridge/sync.h>
++
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE       0x434e5953    /* "SYNC" (in reverse) */
++
++enum wait_state {
++      wo_waiting,
++      wo_signalled
++} ;
++
++enum sync_state {
++      so_reset,
++      so_signalled
++} ;
++
++struct WAIT_OBJECT {
++      enum wait_state state;
++      struct SYNC_OBJECT *signalling_event;
++      struct semaphore sem;
++};
++
++/* Generic SYNC object: */
++struct SYNC_OBJECT {
++      u32 dwSignature;        /* Used for object validation. */
++      enum sync_state state;
++      spinlock_t sync_lock;
++      struct WAIT_OBJECT *pWaitObj;
++};
++
++struct SYNC_DPCCSOBJECT {
++      u32 dwSignature;        /* used for object validation */
++      spinlock_t sync_dpccs_lock;
++      s32 count;
++} ;
++
++/*  ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask SYNC_debugMask = { NULL, NULL };  /* GT trace variable */
++#endif
++
++static int test_and_set(volatile void *ptr, int val)
++{
++      int ret = val;
++      asm volatile (" swp %0, %0, [%1]" : "+r" (ret) : "r"(ptr) : "memory");
++      return ret;
++}
++
++static void timeout_callback(unsigned long hWaitObj);
++
++/*
++ *  ======== SYNC_CloseEvent ========
++ *  Purpose:
++ *      Close an existing SYNC event object.
++ */
++DSP_STATUS SYNC_CloseEvent(struct SYNC_OBJECT *hEvent)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++
++      DBC_Require(pEvent != NULL && pEvent->pWaitObj == NULL);
++
++      GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_CloseEvent: hEvent 0x%x\n",
++                hEvent);
++
++      if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++              if (pEvent->pWaitObj) {
++                      status = DSP_EFAIL;
++                      GT_0trace(SYNC_debugMask, GT_6CLASS,
++                                "SYNC_CloseEvent: Wait object not NULL\n");
++              }
++              MEM_FreeObject(pEvent);
++
++      } else {
++              status = DSP_EHANDLE;
++              GT_1trace(SYNC_debugMask, GT_6CLASS,
++                        "SYNC_CloseEvent: invalid "
++                        "hEvent handle 0x%x\n", hEvent);
++      }
++
++      return status;
++}
++
++/*
++ *  ======== SYNC_Exit ========
++ *  Purpose:
++ *      Cleanup SYNC module.
++ */
++void SYNC_Exit(void)
++{
++      GT_0trace(SYNC_debugMask, GT_5CLASS, "SYNC_Exit\n");
++}
++
++/*
++ *  ======== SYNC_Init ========
++ *  Purpose:
++ *      Initialize SYNC module.
++ */
++bool SYNC_Init(void)
++{
++      GT_create(&SYNC_debugMask, "SY");       /* SY for SYnc */
++
++      GT_0trace(SYNC_debugMask, GT_5CLASS, "SYNC_Init\n");
++
++      return true;
++}
++
++/*
++ *  ======== SYNC_OpenEvent ========
++ *  Purpose:
++ *      Open a new synchronization event object.
++ */
++DSP_STATUS SYNC_OpenEvent(OUT struct SYNC_OBJECT **phEvent,
++                        IN OPTIONAL struct SYNC_ATTRS *pAttrs)
++{
++      struct SYNC_OBJECT *pEvent = NULL;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(phEvent != NULL);
++
++      GT_2trace(SYNC_debugMask, GT_ENTER,
++                "SYNC_OpenEvent: phEvent 0x%x, pAttrs "
++                "0x%x\n", phEvent, pAttrs);
++
++      /* Allocate memory for sync object */
++      MEM_AllocObject(pEvent, struct SYNC_OBJECT, SIGNATURE);
++      if (pEvent != NULL) {
++              pEvent->state = so_reset;
++              pEvent->pWaitObj = NULL;
++              spin_lock_init(&pEvent->sync_lock);
++      } else {
++              status = DSP_EMEMORY;
++              GT_0trace(SYNC_debugMask, GT_6CLASS,
++                        "SYNC_OpenEvent: MEM_AllocObject failed\n");
++      }
++
++      *phEvent = pEvent;
++
++      return status;
++}
++
++/*
++ *  ======== SYNC_ResetEvent ========
++ *  Purpose:
++ *      Reset an event to non-signalled.
++ */
++DSP_STATUS SYNC_ResetEvent(struct SYNC_OBJECT *hEvent)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++
++      GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_ResetEvent: hEvent 0x%x\n",
++                hEvent);
++
++      if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++              pEvent->state = so_reset;
++              status = DSP_SOK;
++      } else {
++              status = DSP_EHANDLE;
++              GT_1trace(SYNC_debugMask, GT_6CLASS,
++                        "SYNC_ResetEvent: invalid hEvent "
++                        "handle 0x%x\n", hEvent);
++      }
++
++      return status;
++}
++
++/*
++ *  ======== SYNC_SetEvent ========
++ *  Purpose:
++ *      Set an event to signaled and unblock one waiting thread.
++ *
++ *  This function is called from ISR, DPC and user context. Hence interrupts
++ *  are disabled to ensure atomicity.
++ */
++
++DSP_STATUS SYNC_SetEvent(struct SYNC_OBJECT *hEvent)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++      unsigned long flags;
++
++      GT_1trace(SYNC_debugMask, GT_6CLASS, "SYNC_SetEvent: hEvent 0x%x\n",
++                hEvent);
++
++      if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++              spin_lock_irqsave(&hEvent->sync_lock, flags);
++              GT_1trace(SYNC_debugMask, GT_6CLASS,
++                      "SYNC_SetEvent: pEvent->pWaitObj "
++                      "= 0x%x \n", pEvent->pWaitObj);
++      if (pEvent->pWaitObj)
++              GT_1trace(SYNC_debugMask, GT_6CLASS, "SYNC_SetEvent: "
++                      "pEvent->pWaitObj->state = 0x%x \n",
++                      pEvent->pWaitObj->state);
++              if (pEvent->pWaitObj != NULL &&
++                 test_and_set(&pEvent->pWaitObj->state,
++                 wo_signalled) == wo_waiting) {
++
++                      pEvent->state = so_reset;
++                      pEvent->pWaitObj->signalling_event = pEvent;
++                      up(&pEvent->pWaitObj->sem);
++                      GT_1trace(SYNC_debugMask, GT_6CLASS,
++                                "SYNC_SetEvent: Unlock "
++                                "Semaphore for hEvent 0x%x\n", hEvent);
++              } else {
++                      pEvent->state = so_signalled;
++              }
++              spin_unlock_irqrestore(&hEvent->sync_lock, flags);
++      } else {
++              status = DSP_EHANDLE;
++              GT_1trace(SYNC_debugMask, GT_6CLASS,
++                        "SYNC_SetEvent: invalid hEvent "
++                        "handle 0x%x\n", hEvent);
++      }
++      return status;
++}
++
++/*
++ *  ======== SYNC_WaitOnEvent ========
++ *  Purpose:
++ *      Wait for an event to be signalled, up to the specified timeout.
++ *      Note: dwTimeOut must be 0xffffffff to signal infinite wait.
++ */
++DSP_STATUS SYNC_WaitOnEvent(struct SYNC_OBJECT *hEvent, u32 dwTimeout)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++      u32 temp;
++
++      GT_2trace(SYNC_debugMask, GT_6CLASS, "SYNC_WaitOnEvent: hEvent 0x%x\n, "
++                "dwTimeOut 0x%x", hEvent, dwTimeout);
++      if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++              status = SYNC_WaitOnMultipleEvents(&pEvent, 1, dwTimeout,
++                                                &temp);
++      } else {
++              status = DSP_EHANDLE;
++              GT_1trace(SYNC_debugMask, GT_6CLASS,
++                        "SYNC_WaitOnEvent: invalid hEvent"
++                        "handle 0x%x\n", hEvent);
++      }
++      return status;
++}
++
++/*
++ *  ======== SYNC_WaitOnMultipleEvents ========
++ *  Purpose:
++ *      Wait for any of an array of events to be signalled, up to the
++ *      specified timeout.
++ */
++DSP_STATUS SYNC_WaitOnMultipleEvents(struct SYNC_OBJECT **hSyncEvents,
++                                   u32 uCount, u32 dwTimeout,
++                                   OUT u32 *puIndex)
++{
++      u32 i;
++      DSP_STATUS status = DSP_SOK;
++      u32 curr;
++      struct WAIT_OBJECT *Wp;
++
++      DBC_Require(uCount > 0);
++      DBC_Require(hSyncEvents != NULL);
++      DBC_Require(puIndex != NULL);
++
++      for (i = 0; i < uCount; i++)
++              DBC_Require(MEM_IsValidHandle(hSyncEvents[i], SIGNATURE));
++
++      GT_4trace(SYNC_debugMask, GT_6CLASS,
++                "SYNC_WaitOnMultipleEvents: hSyncEvents:"
++                "0x%x\tuCount: 0x%x" "\tdwTimeout: 0x%x\tpuIndex: 0x%x\n",
++                hSyncEvents, uCount, dwTimeout, puIndex);
++
++      Wp = MEM_Calloc(sizeof(struct WAIT_OBJECT), MEM_NONPAGED);
++      if (Wp == NULL)
++              return DSP_EMEMORY;
++
++      Wp->state = wo_waiting;
++      Wp->signalling_event = NULL;
++      init_MUTEX_LOCKED(&(Wp->sem));
++
++      for (curr = 0; curr < uCount; curr++) {
++              hSyncEvents[curr]->pWaitObj = Wp;
++              if (hSyncEvents[curr]->state == so_signalled) {
++                      GT_0trace(SYNC_debugMask, GT_6CLASS,
++                               "Detected signaled Event !!!\n");
++                      if (test_and_set(&(Wp->state), wo_signalled) ==
++                         wo_waiting) {
++                              GT_0trace(SYNC_debugMask, GT_6CLASS,
++                                       "Setting Signal Event!!!\n");
++                              hSyncEvents[curr]->state = so_reset;
++                              Wp->signalling_event = hSyncEvents[curr];
++                      }
++              curr++; /* Will try optimizing later */
++              break;
++              }
++      }
++
++      curr--;                 /* Will try optimizing later */
++      if (Wp->state != wo_signalled && dwTimeout > 0) {
++              struct timer_list timeout;
++              if (dwTimeout != SYNC_INFINITE) {
++                      init_timer(&timeout);
++                      timeout.function = timeout_callback;
++                      timeout.data = (unsigned long)Wp;
++                      timeout.expires = jiffies + dwTimeout * HZ / 1000;
++                      add_timer(&timeout);
++              }
++              if (down_interruptible(&(Wp->sem))) {
++                      GT_0trace(SYNC_debugMask, GT_7CLASS, "SYNC: "
++                              "WaitOnMultipleEvents Interrupted by signal\n");
++                      status = DSP_EFAIL;
++              }
++              if (dwTimeout != SYNC_INFINITE) {
++                      if (in_interrupt()) {
++                              if (!del_timer(&timeout)) {
++                                      GT_0trace(SYNC_debugMask, GT_7CLASS,
++                                                "SYNC: Timer expired\n");
++                              }
++                      } else {
++                              if (!del_timer_sync(&timeout)) {
++                                      GT_0trace(SYNC_debugMask, GT_7CLASS,
++                                                "SYNC: Timer expired\n");
++                              }
++                      }
++              }
++      }
++      for (i = 0; i <= curr; i++) {
++              if (MEM_IsValidHandle(hSyncEvents[i], SIGNATURE)) {
++                      /*  Memory corruption here if hSyncEvents[i] is
++                       *  freed before following statememt. */
++                      hSyncEvents[i]->pWaitObj = NULL;
++              }
++              if (hSyncEvents[i] == Wp->signalling_event)
++                      *puIndex = i;
++
++      }
++      if (Wp->signalling_event == NULL && DSP_SUCCEEDED(status)) {
++              GT_0trace(SYNC_debugMask, GT_7CLASS,
++                        "SYNC:Signaling Event NULL!!!(:-\n");
++              status = DSP_ETIMEOUT;
++      }
++      if (Wp)
++              MEM_Free(Wp);
++      return status;
++}
++
++static void timeout_callback(unsigned long hWaitObj)
++{
++      struct WAIT_OBJECT *pWaitObj = (struct WAIT_OBJECT *)hWaitObj;
++      if (test_and_set(&pWaitObj->state, wo_signalled) == wo_waiting)
++              up(&pWaitObj->sem);
++
++}
++
++/*
++ *  ======== SYNC_DeleteCS ========
++ */
++DSP_STATUS SYNC_DeleteCS(struct SYNC_CSOBJECT *hCSObj)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
++
++      GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_DeleteCS\n");
++
++      if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
++              if (down_trylock(&pCSObj->sem) != 0) {
++                      GT_1trace(SYNC_debugMask, GT_7CLASS,
++                                "CS in use (locked) while "
++                                "deleting! pCSObj=0x%X", pCSObj);
++                      DBC_Assert(0);
++              }
++              MEM_FreeObject(hCSObj);
++      } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
++              struct SYNC_DPCCSOBJECT *pDPCCSObj =
++                                       (struct SYNC_DPCCSOBJECT *)hCSObj;
++              if (pDPCCSObj->count != 1) {
++                      GT_1trace(SYNC_debugMask, GT_7CLASS,
++                                "DPC CS in use (locked) while "
++                                "deleting! pCSObj=0x%X", pCSObj);
++                      DBC_Assert(0);
++              }
++              MEM_FreeObject(pDPCCSObj);
++      } else {
++              status = DSP_EHANDLE;
++              GT_1trace(SYNC_debugMask, GT_6CLASS,
++                        "SYNC_DeleteCS: invalid hCSObj "
++                        "handle 0x%x\n", hCSObj);
++      }
++
++      return status;
++}
++
++/*
++ *  ======== SYNC_EnterCS ========
++ */
++DSP_STATUS SYNC_EnterCS(struct SYNC_CSOBJECT *hCSObj)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
++
++      GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_EnterCS: hCSObj %p\n",
++               hCSObj);
++      if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
++              if (in_interrupt()) {
++                      status = DSP_EFAIL;
++                      GT_0trace(SYNC_debugMask, GT_7CLASS,
++                               "SYNC_EnterCS called from "
++                               "ISR/DPC or with ISR/DPC disabled!");
++                      DBC_Assert(0);
++              } else if (down_interruptible(&pCSObj->sem)) {
++                      GT_1trace(SYNC_debugMask, GT_7CLASS,
++                               "CS interrupted by signal! "
++                               "pCSObj=0x%X", pCSObj);
++                      status = DSP_EFAIL;
++              }
++      } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
++              struct SYNC_DPCCSOBJECT *pDPCCSObj =
++                                      (struct SYNC_DPCCSOBJECT *)hCSObj;
++              GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_EnterCS DPC\n");
++              spin_lock_bh(&pDPCCSObj->sync_dpccs_lock);
++              pDPCCSObj->count--;
++              if (pDPCCSObj->count != 0) {
++                      /* FATAL ERROR : Failed to acquire DPC CS */
++                      GT_2trace(SYNC_debugMask, GT_7CLASS,
++                                "SYNC_EnterCS DPCCS %x locked,"
++                                "count %d", pDPCCSObj, pDPCCSObj->count);
++                      spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
++                      DBC_Assert(0);
++              }
++      } else {
++              status = DSP_EHANDLE;
++              GT_1trace(SYNC_debugMask, GT_6CLASS,
++                        "SYNC_EnterCS: invalid hCSObj "
++                        "handle 0x%x\n", hCSObj);
++      }
++
++      return status;
++}
++
++/*
++ *  ======== SYNC_InitializeCS ========
++ */
++DSP_STATUS SYNC_InitializeCS(OUT struct SYNC_CSOBJECT **phCSObj)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct SYNC_CSOBJECT *pCSObj = NULL;
++
++      GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeCS\n");
++
++      /* Allocate memory for sync CS object */
++      MEM_AllocObject(pCSObj, struct SYNC_CSOBJECT, SIGNATURECS);
++      if (pCSObj != NULL) {
++              init_MUTEX(&pCSObj->sem);
++      } else {
++              status = DSP_EMEMORY;
++              GT_0trace(SYNC_debugMask, GT_6CLASS,
++                        "SYNC_InitializeCS: MEM_AllocObject"
++                        "failed\n");
++      }
++      /* return CS object */
++      *phCSObj = pCSObj;
++      DBC_Assert(DSP_FAILED(status) || (pCSObj));
++      return status;
++}
++
++DSP_STATUS SYNC_InitializeDPCCS(OUT struct SYNC_CSOBJECT **phCSObj)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct SYNC_DPCCSOBJECT *pCSObj = NULL;
++
++      DBC_Require(phCSObj);
++
++      GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeDPCCS\n");
++
++      if (phCSObj) {
++              /* Allocate memory for sync CS object */
++              MEM_AllocObject(pCSObj, struct SYNC_DPCCSOBJECT,
++                              SIGNATUREDPCCS);
++              if (pCSObj != NULL) {
++                      pCSObj->count = 1;
++                      spin_lock_init(&pCSObj->sync_dpccs_lock);
++              } else {
++                      status = DSP_EMEMORY;
++                      GT_0trace(SYNC_debugMask, GT_6CLASS,
++                                "SYNC_InitializeDPCCS: "
++                                "MEM_AllocObject failed\n");
++              }
++
++              /* return CS object */
++              *phCSObj = (struct SYNC_CSOBJECT *)pCSObj;
++      } else {
++              status = DSP_EPOINTER;
++      }
++
++      GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeDPCCS "
++                "pCSObj %p\n", pCSObj);
++      DBC_Assert(DSP_FAILED(status) || (pCSObj));
++
++      return status;
++}
++
++/*
++ *  ======== SYNC_LeaveCS ========
++ */
++DSP_STATUS SYNC_LeaveCS(struct SYNC_CSOBJECT *hCSObj)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
++
++      GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_LeaveCS: hCSObj %p\n",
++                hCSObj);
++
++      if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
++              up(&pCSObj->sem);
++      } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
++              struct SYNC_DPCCSOBJECT *pDPCCSObj =
++                                      (struct SYNC_DPCCSOBJECT *)hCSObj;
++              pDPCCSObj->count++;
++              if (pDPCCSObj->count != 1) {
++                      /* FATAL ERROR : Invalid DPC CS count */
++                      GT_2trace(SYNC_debugMask, GT_7CLASS,
++                                "SYNC_LeaveCS DPCCS %x, "
++                                "Invalid count %d", pDPCCSObj,
++                                pDPCCSObj->count);
++                      spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
++                      DBC_Assert(0);
++                      spin_lock_bh(&pDPCCSObj->sync_dpccs_lock);
++              }
++              spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
++              GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_LeaveCS DPC\n");
++      } else {
++              status = DSP_EHANDLE;
++              GT_1trace(SYNC_debugMask, GT_6CLASS,
++                        "SYNC_LeaveCS: invalid hCSObj "
++                        "handle 0x%x\n", hCSObj);
++      }
++
++      return status;
++}
+diff --git a/drivers/dsp/bridge/wmd/_cmm.h b/drivers/dsp/bridge/wmd/_cmm.h
+new file mode 100644
+index 0000000..801b000
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_cmm.h
+@@ -0,0 +1,59 @@
++/*
++ * _cmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== _cmm.h ========
++ *  Description:
++ *      Private header file defining CMM manager objects and defines needed
++ *      by IO manager to register shared memory regions when DSP base image
++ *      is loaded(WMD_IO_OnLoaded).
++ *
++ *  Public Functions:
++ *      None.
++ *
++ *  Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Aug-2001 ag     Created.
++ */
++
++#ifndef _CMM_
++#define _CMM_
++
++/*
++ *  These target side symbols define the beginning and ending addresses
++ *  of the section of shared memory used for shared memory manager CMM.
++ *  They are defined in the *cfg.cmd file by cdb code.
++ */
++#define SHM0_SHARED_BASE_SYM             "_SHM0_BEG"
++#define SHM0_SHARED_END_SYM              "_SHM0_END"
++#define SHM0_SHARED_RESERVED_BASE_SYM    "_SHM0_RSVDSTRT"
++
++/*
++ *  Shared Memory Region #0(SHMSEG0) is used in the following way:
++ *
++ *  |(_SHM0_BEG)                  | (_SHM0_RSVDSTRT)           | (_SHM0_END)
++ *  V                             V                            V
++ *  ------------------------------------------------------------
++ *  |     DSP-side allocations    |    GPP-side allocations    |
++ *  ------------------------------------------------------------
++ *
++ *
++ */
++
++#endif                                /* _CMM_ */
+diff --git a/drivers/dsp/bridge/wmd/_deh.h b/drivers/dsp/bridge/wmd/_deh.h
+new file mode 100644
+index 0000000..df281ad
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_deh.h
+@@ -0,0 +1,46 @@
++/*
++ * _deh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== _deh.h ========
++ *  Description:
++ *      Private header for DEH module.
++ *
++ *! Revision History:
++ *! ================
++ *! 21-Sep-2001 kc: created.
++ */
++
++#ifndef _DEH_
++#define _DEH_
++
++#include <dspbridge/dpc.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/wmd.h>
++
++#define SIGNATURE       0x5f484544    /* "DEH_" backwards */
++
++/* DEH Manager: only one created per board: */
++struct DEH_MGR {
++      u32 dwSignature;        /* Used for object validation.  */
++      struct WMD_DEV_CONTEXT *hWmdContext;    /* WMD device context. */
++      struct NTFY_OBJECT *hNtfy;      /* NTFY object                  */
++      struct DPC_OBJECT *hMmuFaultDpc;        /* DPC object handle.  */
++      struct DSP_ERRORINFO errInfo;   /* DSP exception info.          */
++} ;
++
++#endif                                /* _DEH_ */
+diff --git a/drivers/dsp/bridge/wmd/_msg_sm.h b/drivers/dsp/bridge/wmd/_msg_sm.h
+new file mode 100644
+index 0000000..fa5e9ee
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_msg_sm.h
+@@ -0,0 +1,158 @@
++/*
++ * _msg_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== _msg_sm.h ========
++ *  Description:
++ *      Private header file defining MSG manager objects and defines needed
++ *      by IO manager.
++ *
++ *  Public Functions:
++ *      None.
++ *
++ *  Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 09-May-2001 jeh     Code Review cleanup.
++ *! 08-Nov-2000 jeh     Created.
++ */
++
++#ifndef _MSG_SM_
++#define _MSG_SM_
++
++#include <dspbridge/list.h>
++#include <dspbridge/msgdefs.h>
++
++/*
++ *  These target side symbols define the beginning and ending addresses
++ *  of the section of shared memory used for messages. They are
++ *  defined in the *cfg.cmd file by cdb code.
++ */
++#define MSG_SHARED_BUFFER_BASE_SYM      "_MSG_BEG"
++#define MSG_SHARED_BUFFER_LIMIT_SYM     "_MSG_END"
++
++#ifndef _CHNL_WORDSIZE
++#define _CHNL_WORDSIZE 4      /* default _CHNL_WORDSIZE is 2 bytes/word */
++#endif
++
++/*
++ *  ======== MSG ========
++ *  There is a control structure for messages to the DSP, and a control
++ *  structure for messages from the DSP. The shared memory region for
++ *  transferring messages is partitioned as follows:
++ *
++ *  ----------------------------------------------------------
++ *  |Control | Messages from DSP | Control | Messages to DSP |
++ *  ----------------------------------------------------------
++ *
++ *  MSG control structure for messages to the DSP is used in the following
++ *  way:
++ *
++ *  bufEmpty -      This flag is set to FALSE by the GPP after it has output
++ *                  messages for the DSP. The DSP host driver sets it to
++ *                  TRUE after it has copied the messages.
++ *  postSWI -       Set to 1 by the GPP after it has written the messages,
++ *                  set the size, and set bufEmpty to FALSE.
++ *                  The DSP Host driver uses SWI_andn of the postSWI field
++ *                  when a host interrupt occurs. The host driver clears
++ *                  this after posting the SWI.
++ *  size -          Number of messages to be read by the DSP.
++ *
++ *  For messages from the DSP:
++ *  bufEmpty -      This flag is set to FALSE by the DSP after it has output
++ *                  messages for the GPP. The DPC on the GPP sets it to
++ *                  TRUE after it has copied the messages.
++ *  postSWI -       Set to 1 the DPC on the GPP after copying the messages.
++ *  size -          Number of messages to be read by the GPP.
++ */
++struct MSG {
++      u32 bufEmpty;   /* to/from DSP buffer is empty */
++      u32 postSWI;    /* Set to "1" to post MSG SWI */
++      u32 size;       /* Number of messages to/from the DSP */
++      u32 resvd;
++} ;
++
++/*
++ *  ======== MSG_MGR ========
++ *  The MSG_MGR maintains a list of all MSG_QUEUEs. Each NODE object can
++ *  have MSG_QUEUE to hold all messages that come up from the corresponding
++ *  node on the DSP. The MSG_MGR also has a shared queue of messages
++ *  ready to go to the DSP.
++ */
++struct MSG_MGR {
++      /* The first two fields must match those in msgobj.h */
++      u32 dwSignature;
++      struct WMD_DRV_INTERFACE *pIntfFxns;    /* Function interface to WMD. */
++
++      struct IO_MGR *hIOMgr;  /* IO manager */
++      struct LST_LIST *queueList;     /* List of MSG_QUEUEs */
++      struct SYNC_CSOBJECT *hSyncCS;  /* For critical sections */
++      /* Signalled when MsgFrame is available */
++      struct SYNC_OBJECT *hSyncEvent;
++      struct LST_LIST *msgFreeList;   /* Free MsgFrames ready to be filled */
++      struct LST_LIST *msgUsedList;   /* MsgFrames ready to go to DSP */
++      u32 uMsgsPending;       /* # of queued messages to go to DSP */
++      u32 uMaxMsgs;   /* Max # of msgs that fit in buffer */
++      MSG_ONEXIT onExit;      /* called when RMS_EXIT is received */
++} ;
++
++/*
++ *  ======== MSG_QUEUE ========
++ *  Each NODE has a MSG_QUEUE for receiving messages from the
++ *  corresponding node on the DSP. The MSG_QUEUE object maintains a list
++ *  of messages that have been sent to the host, but not yet read (MSG_Get),
++ *  and a list of free frames that can be filled when new messages arrive
++ *  from the DSP.
++ *  The MSG_QUEUE's hSynEvent gets posted when a message is ready.
++ */
++struct MSG_QUEUE {
++      struct LST_ELEM listElem;
++      u32 dwSignature;
++      struct MSG_MGR *hMsgMgr;
++      u32 uMaxMsgs;   /* Node message depth */
++      u32 dwId;       /* Node environment pointer */
++      struct LST_LIST *msgFreeList;   /* Free MsgFrames ready to be filled */
++      /* Filled MsgFramess waiting to be read */
++      struct LST_LIST *msgUsedList;
++      HANDLE hArg;    /* Handle passed to mgr onExit callback */
++      struct SYNC_OBJECT *hSyncEvent; /* Signalled when message is ready */
++      struct SYNC_OBJECT *hSyncDone;  /* For synchronizing cleanup */
++      struct SYNC_OBJECT *hSyncDoneAck;       /* For synchronizing cleanup */
++      struct NTFY_OBJECT *hNtfy;      /* For notification of message ready */
++      bool fDone;     /* TRUE <==> deleting the object */
++      u32 refCount;   /* Number of pending MSG_get/put calls */
++};
++
++/*
++ *  ======== MSG_DSPMSG ========
++ */
++struct MSG_DSPMSG {
++      struct DSP_MSG msg;
++      u32 dwId;       /* Identifies the node the message goes to */
++} ;
++
++/*
++ *  ======== MSG_FRAME ========
++ */
++struct MSG_FRAME {
++      struct LST_ELEM listElem;
++      struct MSG_DSPMSG msgData;
++} ;
++
++#endif                                /* _MSG_SM_ */
++
+diff --git a/drivers/dsp/bridge/wmd/_tiomap.h b/drivers/dsp/bridge/wmd/_tiomap.h
+new file mode 100644
+index 0000000..815f695
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap.h
+@@ -0,0 +1,384 @@
++/*
++ * _tiomap.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== _tiomap.h ========
++ *  Description:
++ *      Definitions and types private to this WMD.
++ *
++ */
++
++#ifndef _TIOMAP_
++#define _TIOMAP_
++
++#include <dspbridge/devdefs.h>
++#include <hw_defs.h>
++#include <hw_mbox.h>
++#include <dspbridge/wmdioctl.h>               /* for WMDIOCTL_EXTPROC defn */
++#include <dspbridge/sync.h>
++#include <dspbridge/clk.h>
++
++struct MAP_L4PERIPHERAL {
++      u32 physAddr;
++      u32 dspVirtAddr;
++} ;
++
++#define ARM_MAILBOX_START               0xfffcf000
++#define ARM_MAILBOX_LENGTH              0x800
++
++/* New Registers in OMAP3.1 */
++
++#define TESTBLOCK_ID_START              0xfffed400
++#define TESTBLOCK_ID_LENGTH             0xff
++
++/* ID Returned by OMAP1510 */
++#define TBC_ID_VALUE                    0xB47002F
++
++#define SPACE_LENGTH                    0x2000
++#define API_CLKM_DPLL_DMA               0xfffec000
++#define ARM_INTERRUPT_OFFSET            0xb00
++
++#define BIOS_24XX
++
++#define L4_PERIPHERAL_NULL          0x0
++#define DSPVA_PERIPHERAL_NULL       0x0
++
++#define MAX_LOCK_TLB_ENTRIES 15
++
++#define L4_PERIPHERAL_PRM        0x48306000  /*PRM L4 Peripheral */
++#define DSPVA_PERIPHERAL_PRM     0x1181e000
++#define L4_PERIPHERAL_SCM        0x48002000  /*SCM L4 Peripheral */
++#define DSPVA_PERIPHERAL_SCM     0x1181f000
++#define L4_PERIPHERAL_MMU        0x5D000000  /*MMU L4 Peripheral */
++#define DSPVA_PERIPHERAL_MMU     0x11820000
++#define L4_PERIPHERAL_CM        0x48004000       /* Core L4, Clock Management */
++#define DSPVA_PERIPHERAL_CM     0x1181c000
++#define L4_PERIPHERAL_PER        0x48005000       /*  PER */
++#define DSPVA_PERIPHERAL_PER     0x1181d000
++
++#define L4_PERIPHERAL_GPIO1       0x48310000
++#define DSPVA_PERIPHERAL_GPIO1    0x11809000
++#define L4_PERIPHERAL_GPIO2       0x49050000
++#define DSPVA_PERIPHERAL_GPIO2    0x1180a000
++#define L4_PERIPHERAL_GPIO3       0x49052000
++#define DSPVA_PERIPHERAL_GPIO3    0x1180b000
++#define L4_PERIPHERAL_GPIO4       0x49054000
++#define DSPVA_PERIPHERAL_GPIO4    0x1180c000
++#define L4_PERIPHERAL_GPIO5       0x49056000
++#define DSPVA_PERIPHERAL_GPIO5    0x1180d000
++
++#define L4_PERIPHERAL_IVA2WDT      0x49030000
++#define DSPVA_PERIPHERAL_IVA2WDT   0x1180e000
++
++#define L4_PERIPHERAL_DISPLAY     0x48050000
++#define DSPVA_PERIPHERAL_DISPLAY  0x1180f000
++
++#define L4_PERIPHERAL_SSI         0x48058000
++#define DSPVA_PERIPHERAL_SSI      0x11804000
++#define L4_PERIPHERAL_GDD         0x48059000
++#define DSPVA_PERIPHERAL_GDD      0x11805000
++#define L4_PERIPHERAL_SS1         0x4805a000
++#define DSPVA_PERIPHERAL_SS1      0x11806000
++#define L4_PERIPHERAL_SS2         0x4805b000
++#define DSPVA_PERIPHERAL_SS2      0x11807000
++
++#define L4_PERIPHERAL_CAMERA      0x480BC000
++#define DSPVA_PERIPHERAL_CAMERA   0x11819000
++
++#define L4_PERIPHERAL_SDMA        0x48056000
++#define DSPVA_PERIPHERAL_SDMA     0x11810000 /*0x1181d000 conflicts with PER */
++
++#define L4_PERIPHERAL_UART1             0x4806a000
++#define DSPVA_PERIPHERAL_UART1          0x11811000
++#define L4_PERIPHERAL_UART2             0x4806c000
++#define DSPVA_PERIPHERAL_UART2          0x11812000
++#define L4_PERIPHERAL_UART3             0x49020000
++#define DSPVA_PERIPHERAL_UART3    0x11813000
++
++#define L4_PERIPHERAL_MCBSP1      0x48074000
++#define DSPVA_PERIPHERAL_MCBSP1   0x11814000
++#define L4_PERIPHERAL_MCBSP2      0x49022000
++#define DSPVA_PERIPHERAL_MCBSP2   0x11815000
++#define L4_PERIPHERAL_MCBSP3      0x49024000
++#define DSPVA_PERIPHERAL_MCBSP3   0x11816000
++#define L4_PERIPHERAL_MCBSP4      0x49026000
++#define DSPVA_PERIPHERAL_MCBSP4   0x11817000
++#define L4_PERIPHERAL_MCBSP5      0x48096000
++#define DSPVA_PERIPHERAL_MCBSP5   0x11818000
++
++#define L4_PERIPHERAL_GPTIMER5    0x49038000
++#define DSPVA_PERIPHERAL_GPTIMER5 0x11800000
++#define L4_PERIPHERAL_GPTIMER6    0x4903a000
++#define DSPVA_PERIPHERAL_GPTIMER6 0x11801000
++#define L4_PERIPHERAL_GPTIMER7    0x4903c000
++#define DSPVA_PERIPHERAL_GPTIMER7 0x11802000
++#define L4_PERIPHERAL_GPTIMER8    0x4903e000
++#define DSPVA_PERIPHERAL_GPTIMER8 0x11803000
++
++#define L4_PERIPHERAL_SPI1      0x48098000
++#define DSPVA_PERIPHERAL_SPI1   0x1181a000
++#define L4_PERIPHERAL_SPI2      0x4809a000
++#define DSPVA_PERIPHERAL_SPI2   0x1181b000
++
++#define L4_PERIPHERAL_MBOX        0x48094000
++#define DSPVA_PERIPHERAL_MBOX     0x11808000
++
++#define PM_GRPSEL_BASE                        0x48307000
++#define DSPVA_GRPSEL_BASE             0x11821000
++
++#define L4_PERIPHERAL_SIDETONE_MCBSP2        0x49028000
++#define DSPVA_PERIPHERAL_SIDETONE_MCBSP2 0x11824000
++#define L4_PERIPHERAL_SIDETONE_MCBSP3        0x4902a000
++#define DSPVA_PERIPHERAL_SIDETONE_MCBSP3 0x11825000
++
++/* define a static array with L4 mappings */
++static const struct MAP_L4PERIPHERAL L4PeripheralTable[] = {
++      {L4_PERIPHERAL_MBOX, DSPVA_PERIPHERAL_MBOX},
++      {L4_PERIPHERAL_SCM, DSPVA_PERIPHERAL_SCM},
++      {L4_PERIPHERAL_MMU, DSPVA_PERIPHERAL_MMU},
++      {L4_PERIPHERAL_GPTIMER5, DSPVA_PERIPHERAL_GPTIMER5},
++      {L4_PERIPHERAL_GPTIMER6, DSPVA_PERIPHERAL_GPTIMER6},
++      {L4_PERIPHERAL_GPTIMER7, DSPVA_PERIPHERAL_GPTIMER7},
++      {L4_PERIPHERAL_GPTIMER8, DSPVA_PERIPHERAL_GPTIMER8},
++      {L4_PERIPHERAL_GPIO1, DSPVA_PERIPHERAL_GPIO1},
++      {L4_PERIPHERAL_GPIO2, DSPVA_PERIPHERAL_GPIO2},
++      {L4_PERIPHERAL_GPIO3, DSPVA_PERIPHERAL_GPIO3},
++      {L4_PERIPHERAL_GPIO4, DSPVA_PERIPHERAL_GPIO4},
++      {L4_PERIPHERAL_GPIO5, DSPVA_PERIPHERAL_GPIO5},
++      {L4_PERIPHERAL_IVA2WDT, DSPVA_PERIPHERAL_IVA2WDT},
++      {L4_PERIPHERAL_DISPLAY, DSPVA_PERIPHERAL_DISPLAY},
++      {L4_PERIPHERAL_SSI, DSPVA_PERIPHERAL_SSI},
++      {L4_PERIPHERAL_GDD, DSPVA_PERIPHERAL_GDD},
++      {L4_PERIPHERAL_SS1, DSPVA_PERIPHERAL_SS1},
++      {L4_PERIPHERAL_SS2, DSPVA_PERIPHERAL_SS2},
++      {L4_PERIPHERAL_UART1, DSPVA_PERIPHERAL_UART1},
++      {L4_PERIPHERAL_UART2, DSPVA_PERIPHERAL_UART2},
++      {L4_PERIPHERAL_UART3, DSPVA_PERIPHERAL_UART3},
++      {L4_PERIPHERAL_MCBSP1, DSPVA_PERIPHERAL_MCBSP1},
++      {L4_PERIPHERAL_MCBSP2, DSPVA_PERIPHERAL_MCBSP2},
++      {L4_PERIPHERAL_MCBSP3, DSPVA_PERIPHERAL_MCBSP3},
++      {L4_PERIPHERAL_MCBSP4, DSPVA_PERIPHERAL_MCBSP4},
++      {L4_PERIPHERAL_MCBSP5, DSPVA_PERIPHERAL_MCBSP5},
++      {L4_PERIPHERAL_CAMERA, DSPVA_PERIPHERAL_CAMERA},
++      {L4_PERIPHERAL_SPI1, DSPVA_PERIPHERAL_SPI1},
++      {L4_PERIPHERAL_SPI2, DSPVA_PERIPHERAL_SPI2},
++      {L4_PERIPHERAL_PRM, DSPVA_PERIPHERAL_PRM},
++      {L4_PERIPHERAL_CM, DSPVA_PERIPHERAL_CM},
++      {L4_PERIPHERAL_PER, DSPVA_PERIPHERAL_PER},
++      {PM_GRPSEL_BASE, DSPVA_GRPSEL_BASE},
++      {L4_PERIPHERAL_SIDETONE_MCBSP2, DSPVA_PERIPHERAL_SIDETONE_MCBSP2},
++      {L4_PERIPHERAL_SIDETONE_MCBSP3, DSPVA_PERIPHERAL_SIDETONE_MCBSP3},
++      {L4_PERIPHERAL_NULL, DSPVA_PERIPHERAL_NULL}
++};
++
++/*
++ *   15         10                  0
++ *   ---------------------------------
++ *  |0|0|1|0|0|0|c|c|c|i|i|i|i|i|i|i|
++ *  ---------------------------------
++ *  |  (class)  | (module specific) |
++ *
++ *  where  c -> Externel Clock Command: Clk & Autoidle Disable/Enable
++ *  i -> External Clock ID Timers 5,6,7,8, McBSP1,2 and WDT3
++ */
++
++/* MBX_PM_CLK_IDMASK: DSP External clock id mask. */
++#define MBX_PM_CLK_IDMASK   0x7F
++
++/* MBX_PM_CLK_CMDSHIFT: DSP External clock command shift. */
++#define MBX_PM_CLK_CMDSHIFT 7
++
++/* MBX_PM_CLK_CMDMASK: DSP External clock command mask. */
++#define MBX_PM_CLK_CMDMASK 7
++
++/* MBX_PM_MAX_RESOURCES: CORE 1 Clock resources. */
++#define MBX_CORE1_RESOURCES 7
++
++/* MBX_PM_MAX_RESOURCES: CORE 2 Clock Resources. */
++#define MBX_CORE2_RESOURCES 1
++
++/* MBX_PM_MAX_RESOURCES: TOTAL Clock Reosurces. */
++#define MBX_PM_MAX_RESOURCES 11
++
++/*  Power Management Commands */
++enum BPWR_ExtClockCmd {
++      BPWR_DisableClock = 0,
++      BPWR_EnableClock,
++      BPWR_DisableAutoIdle,
++      BPWR_EnableAutoIdle
++} ;
++
++/* OMAP242x specific resources */
++enum BPWR_ExtClockId {
++      BPWR_GPTimer5 = 0x10,
++      BPWR_GPTimer6,
++      BPWR_GPTimer7,
++      BPWR_GPTimer8,
++      BPWR_WDTimer3,
++      BPWR_MCBSP1,
++      BPWR_MCBSP2,
++      BPWR_MCBSP3,
++      BPWR_MCBSP4,
++      BPWR_MCBSP5,
++      BPWR_SSI = 0x20
++} ;
++
++static const u32 BPWR_CLKID[] = {
++      (u32) BPWR_GPTimer5,
++      (u32) BPWR_GPTimer6,
++      (u32) BPWR_GPTimer7,
++      (u32) BPWR_GPTimer8,
++      (u32) BPWR_WDTimer3,
++      (u32) BPWR_MCBSP1,
++      (u32) BPWR_MCBSP2,
++      (u32) BPWR_MCBSP3,
++      (u32) BPWR_MCBSP4,
++      (u32) BPWR_MCBSP5,
++      (u32) BPWR_SSI
++};
++
++struct BPWR_Clk_t {
++      u32 clkId;
++      enum SERVICES_ClkId funClk;
++      enum SERVICES_ClkId intClk;
++} ;
++
++static const struct BPWR_Clk_t BPWR_Clks[] = {
++      {(u32) BPWR_GPTimer5, SERVICESCLK_gpt5_fck, SERVICESCLK_gpt5_ick},
++      {(u32) BPWR_GPTimer6, SERVICESCLK_gpt6_fck, SERVICESCLK_gpt6_ick},
++      {(u32) BPWR_GPTimer7, SERVICESCLK_gpt7_fck, SERVICESCLK_gpt7_ick},
++      {(u32) BPWR_GPTimer8, SERVICESCLK_gpt8_fck, SERVICESCLK_gpt8_ick},
++      {(u32) BPWR_WDTimer3, SERVICESCLK_wdt3_fck, SERVICESCLK_wdt3_ick},
++      {(u32) BPWR_MCBSP1, SERVICESCLK_mcbsp1_fck, SERVICESCLK_mcbsp1_ick},
++      {(u32) BPWR_MCBSP2, SERVICESCLK_mcbsp2_fck, SERVICESCLK_mcbsp2_ick},
++      {(u32) BPWR_MCBSP3, SERVICESCLK_mcbsp3_fck, SERVICESCLK_mcbsp3_ick},
++      {(u32) BPWR_MCBSP4, SERVICESCLK_mcbsp4_fck, SERVICESCLK_mcbsp4_ick},
++      {(u32) BPWR_MCBSP5, SERVICESCLK_mcbsp5_fck, SERVICESCLK_mcbsp5_ick},
++      {(u32) BPWR_SSI, SERVICESCLK_ssi_fck, SERVICESCLK_ssi_ick}
++};
++
++/* Interrupt Register Offsets */
++#define INTH_IT_REG_OFFSET              0x00  /* Interrupt register offset  */
++#define INTH_MASK_IT_REG_OFFSET         0x04  /* Mask Interrupt reg offset  */
++
++#define   DSP_MAILBOX1_INT              10
++
++/*
++ *  INTH_InterruptKind_t
++ *  Identify the kind of interrupt: either FIQ/IRQ
++ */
++enum INTH_InterruptKind_t {
++      INTH_IRQ = 0,
++      INTH_FIQ = 1
++} ;
++
++enum INTH_SensitiveEdge_t {
++      FALLING_EDGE_SENSITIVE = 0,
++      LOW_LEVEL_SENSITIVE = 1
++} ;
++
++/*
++ *  Bit definition of  Interrupt  Level  Registers
++ */
++
++/* Mail Box defines */
++#define MB_ARM2DSP1_REG_OFFSET          0x00
++
++#define MB_ARM2DSP1B_REG_OFFSET         0x04
++
++#define MB_DSP2ARM1B_REG_OFFSET         0x0C
++
++#define MB_ARM2DSP1_FLAG_REG_OFFSET     0x18
++
++#define MB_ARM2DSP_FLAG                 0x0001
++
++#define MBOX_ARM2DSP HW_MBOX_ID_0
++#define MBOX_DSP2ARM HW_MBOX_ID_1
++#define MBOX_ARM HW_MBOX_U0_ARM
++#define MBOX_DSP HW_MBOX_U1_DSP1
++
++#define ENABLE                          true
++#define DISABLE                         false
++
++#define HIGH_LEVEL                      true
++#define LOW_LEVEL                       false
++
++/* Macro's */
++#define REG16(A)    (*(REG_UWORD16 *)(A))
++
++#define ClearBit(reg, mask)             (reg &= ~mask)
++#define SetBit(reg, mask)               (reg |= mask)
++
++#define SetGroupBits16(reg, position, width, value) \
++      do {\
++              reg &= ~((0xFFFF >> (16 - (width))) << (position)) ; \
++              reg |= ((value & (0xFFFF >> (16 - (width)))) << (position)); \
++      } while (0);
++
++#define ClearBitIndex(reg, index)   (reg &= ~(1 << (index)))
++
++/* This mini driver's device context: */
++struct WMD_DEV_CONTEXT {
++      struct DEV_OBJECT *hDevObject;  /* Handle to WCD device object. */
++      u32 dwDspBaseAddr;      /* Arm's API to DSP virtual base addr */
++      /*
++       * DSP External memory prog address as seen virtually by the OS on
++       * the host side.
++       */
++      u32 dwDspExtBaseAddr;   /* See the comment above        */
++      u32 dwAPIRegBase;       /* API memory mapped registers  */
++      u32 dwDSPMmuBase;       /* DSP MMU Mapped registers     */
++      u32 dwMailBoxBase;      /* Mail box mapped registers    */
++      u32 dwAPIClkBase;       /* CLK Registers                */
++      u32 dwDSPClkM2Base;     /* DSP Clock Module m2          */
++      u32 dwPublicRhea;       /* Pub Rhea                     */
++      u32 dwIntAddr;  /* MB INTR reg                  */
++      u32 dwTCEndianism;      /* TC Endianism register        */
++      u32 dwTestBase; /* DSP MMU Mapped registers     */
++      u32 dwSelfLoop; /* Pointer to the selfloop      */
++      u32 dwDSPStartAdd;      /* API Boot vector              */
++      u32 dwInternalSize;     /* Internal memory size         */
++
++      /*
++       * Processor specific info is set when prog loaded and read from DCD.
++       * [See WMD_BRD_Ctrl()]  PROC info contains DSP-MMU TLB entries.
++       */
++      /* DMMU TLB entries */
++      struct WMDIOCTL_EXTPROC aTLBEntry[WMDIOCTL_NUMOFMMUTLB];
++      u32 dwBrdState; /* Last known board state.      */
++      u32 ulIntMask;  /* int mask                     */
++      u16 ioBase;     /* Board I/O base               */
++      u32 numTLBEntries;      /* DSP MMU TLB entry counter    */
++      u32 fixedTLBEntries;    /* Fixed DSPMMU TLB entry count */
++
++      /* TC Settings */
++      bool tcWordSwapOn;      /* Traffic Controller Word Swap */
++      struct PgTableAttrs *pPtAttrs;
++      u32 uDspPerClks;
++} ;
++
++      /*
++       * ======== WMD_TLB_DspVAToMpuPA ========
++       *     Given a DSP virtual address, traverse the page table and return
++       *     a corresponding MPU physical address and size.
++       */
++extern DSP_STATUS WMD_TLB_DspVAToMpuPA(struct WMD_DEV_CONTEXT *pDevContext,
++                                     IN u32 ulVirtAddr,
++                                     OUT u32 *ulPhysAddr,
++                                     OUT u32 *sizeTlb);
++
++#endif                                /* _TIOMAP_ */
++
+diff --git a/drivers/dsp/bridge/wmd/_tiomap_mmu.h b/drivers/dsp/bridge/wmd/_tiomap_mmu.h
+new file mode 100644
+index 0000000..6b21047
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap_mmu.h
+@@ -0,0 +1,53 @@
++/*
++ * _tiomap_mmu.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== _tiomap_mmu.h ========
++ *  Description:
++ *      Definitions and types for the DSP MMU modules
++ *
++ *! Revision History
++ *! ================
++ *! 19-Apr-2004 sb:  Renamed HW types. Removed dspMmuTlbEntry
++ *! 05-Jan-2004 vp:  Moved the file to a platform specific folder from common.
++ *! 21-Mar-2003 sb:  Added macro definition TIHEL_LARGEPAGESIZE
++ *! 08-Oct-2002 rr:  Created.
++ */
++
++#ifndef _TIOMAP_MMU_
++#define _TIOMAP_MMU_
++
++#include "_tiomap.h"
++
++/*
++ *  ======== configureDspMmu ========
++ *
++ *  Make DSP MMu page table entries.
++ *  Note: Not utilizing Coarse / Fine page tables.
++ *  SECTION = 1MB, LARGE_PAGE = 64KB, SMALL_PAGE = 4KB, TINY_PAGE = 1KB.
++ *  DSP Byte address 0x40_0000 is word addr 0x20_0000.
++ */
++extern void configureDspMmu(struct WMD_DEV_CONTEXT *pDevContext,
++                          u32 dataBasePhys,
++                          u32 dspBaseVirt,
++                          u32 sizeInBytes,
++                          s32 nEntryStart,
++                          enum HW_Endianism_t endianism,
++                          enum HW_ElementSize_t elemSize,
++                          enum HW_MMUMixedSize_t mixedSize);
++
++#endif                                /* _TIOMAP_MMU_ */
+diff --git a/drivers/dsp/bridge/wmd/_tiomap_pwr.h b/drivers/dsp/bridge/wmd/_tiomap_pwr.h
+new file mode 100644
+index 0000000..7ebd7b5
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap_pwr.h
+@@ -0,0 +1,102 @@
++/*
++ * _tiomap_pwr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== _tiomap_pwr.h ========
++ *  Description:
++ *      Definitions and types for the DSP wake/sleep routines.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Oct-2002 rr:  Created.
++ */
++
++#ifndef _TIOMAP_PWR_
++#define _TIOMAP_PWR_
++
++/*
++ * ======== WakeDSP =========
++ * Wakes up the DSP from DeepSleep
++ */
++extern DSP_STATUS WakeDSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
++
++/*
++ * ======== SleepDSP =========
++ * Places the DSP in DeepSleep.
++ */
++extern DSP_STATUS SleepDSP(struct WMD_DEV_CONTEXT *pDevContext,
++                         IN u32 dwCmd, IN void *pArgs);
++/*
++ *  ========InterruptDSP========
++ *      Sends an interrupt to DSP unconditionally.
++ */
++extern void InterruptDSP(struct WMD_DEV_CONTEXT *pDevContext, IN u16 wMbVal);
++
++/*
++ * ======== WakeDSP =========
++ * Wakes up the DSP from DeepSleep
++ */
++extern DSP_STATUS DSPPeripheralClkCtrl(struct WMD_DEV_CONTEXT *pDevContext,
++                                     IN void *pArgs);
++/*
++ *  ======== handle_hibernation_fromDSP ========
++ *    Handle Hibernation requested from DSP
++ */
++DSP_STATUS handle_hibernation_fromDSP(struct WMD_DEV_CONTEXT *pDevContext);
++/*
++ *  ======== PostScale_DSP ========
++ *    Handle Post Scale notification to DSP
++ */
++DSP_STATUS PostScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
++/*
++ *  ======== PreScale_DSP ========
++ *    Handle Pre Scale notification to DSP
++ */
++DSP_STATUS PreScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
++/*
++ *  ======== handle_constraints_set ========
++ *    Handle constraints request from DSP
++ */
++DSP_STATUS handle_constraints_set(struct WMD_DEV_CONTEXT *pDevContext,
++                               IN void *pArgs);
++/*
++ *  ======== DSP_PeripheralClocks_Disable ========
++ *    This function disables all the peripheral clocks that
++ *    were enabled by DSP. Call this function only when
++ *    DSP is entering Hibernation or when DSP is in
++ *    Error state
++ */
++DSP_STATUS DSP_PeripheralClocks_Disable(struct WMD_DEV_CONTEXT *pDevContext,
++                                      IN void *pArgs);
++
++/*
++ *  ======== DSP_PeripheralClocks_Enable ========
++ *    This function enables all the peripheral clocks that
++ *    were requested by DSP.
++ */
++DSP_STATUS DSP_PeripheralClocks_Enable(struct WMD_DEV_CONTEXT *pDevContext,
++                                     IN void *pArgs);
++
++/*
++ *  ======== DSPClkWakeupEventCtrl ========
++ *     This function sets the group selction bits for while
++ *     enabling/disabling.
++ */
++void DSPClkWakeupEventCtrl(u32 ClkId, bool enable);
++
++#endif                                /* _TIOMAP_PWR_ */
++
+diff --git a/drivers/dsp/bridge/wmd/_tiomap_util.h b/drivers/dsp/bridge/wmd/_tiomap_util.h
+new file mode 100644
+index 0000000..47e1e5d
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap_util.h
+@@ -0,0 +1,46 @@
++/*
++ * _tiomap_util.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== _tiomap_util.h ========
++ *  Description:
++ *      Definitions and types for the utility routines.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Oct-2002 rr:  Created.
++ */
++
++#ifndef _TIOMAP_UTIL_
++#define _TIOMAP_UTIL_
++
++/* Time out Values in uSeconds*/
++#define TIHELEN_ACKTIMEOUT  10000
++
++/*  Time delay for HOM->SAM transition. */
++#define  WAIT_SAM   1000000   /* in usec (1000 millisec) */
++
++/*
++ *  ======== WaitForStart ========
++ *  Wait for the singal from DSP that it has started, or time out.
++ *  The argument dwSyncAddr is set to 1 before releasing the DSP.
++ *  If the DSP starts running, it will clear this location.
++ */
++extern bool WaitForStart(struct WMD_DEV_CONTEXT *pDevContext, u32 dwSyncAddr);
++
++#endif                                /* _TIOMAP_UTIL_ */
++
+diff --git a/drivers/dsp/bridge/wmd/chnl_sm.c b/drivers/dsp/bridge/wmd/chnl_sm.c
+new file mode 100644
+index 0000000..e8ffb2f
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/chnl_sm.c
+@@ -0,0 +1,1100 @@
++/*
++ * chnl_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== chnl_sm.c ========
++ *  Description:
++ *      Implements upper edge functions for WMD channel module.
++ *
++ *  Public Functions:
++ *      WMD_CHNL_AddIOReq
++ *      WMD_CHNL_CancelIO
++ *      WMD_CHNL_Close
++ *      WMD_CHNL_Create
++ *      WMD_CHNL_Destroy
++ *      WMD_CHNL_FlushIO
++ *      WMD_CHNL_GetInfo
++ *      WMD_CHNL_GetIOC
++ *      WMD_CHNL_GetMgrInfo
++ *      WMD_CHNL_Idle
++ *      WMD_CHNL_Open
++ *
++ *  Notes:
++ *      The lower edge functions must be implemented by the WMD writer, and
++ *      are declared in chnl_sm.h.
++ *
++ *      Care is taken in this code to prevent simulataneous access to channel
++ *      queues from
++ *      1. Threads.
++ *      2. IO_DPC(), scheduled from the IO_ISR() as an event.
++ *
++ *      This is done primarily by:
++ *      - Semaphores.
++ *      - state flags in the channel object; and
++ *      - ensuring the IO_Dispatch() routine, which is called from both
++ *        CHNL_AddIOReq() and the DPC(if implemented), is not re-entered.
++ *
++ *  Channel Invariant:
++ *      There is an important invariant condition which must be maintained per
++ *      channel outside of WMD_CHNL_GetIOC() and IO_Dispatch(), violation of
++ *      which may cause timeouts and/or failure offunction SYNC_WaitOnEvent.
++ *      This invariant condition is:
++ *
++ *          LST_Empty(pChnl->pIOCompletions) ==> pChnl->hSyncEvent is reset
++ *      and
++ *          !LST_Empty(pChnl->pIOCompletions) ==> pChnl->hSyncEvent is set.
++ *
++ *! Revision History:
++ *! ================
++ *! 10-Feb-2004 sb: Consolidated the MAILBOX_IRQ macro at the top of the file.
++ *! 05-Jan-2004 vp: Updated for 2.6 kernel on 24xx platform.
++ *! 23-Apr-2003 sb: Fixed mailbox deadlock
++ *! 24-Feb-2003 vp: Code Review Updates.
++ *! 18-Oct-2002 vp: Ported to Linux platform
++ *! 29-Aug-2002 rr  Changed the SYNC error code return to DSP error code return
++ *            in WMD_CHNL_GetIOC.
++ *! 22-Jan-2002 ag  Zero-copy support added.
++ *!                 CMM_CallocBuf() used for SM allocations.
++ *! 04-Feb-2001 ag  DSP-DMA support added.
++ *! 22-Nov-2000 kc: Updated usage of PERF_RegisterStat.
++ *! 06-Nov-2000 jeh Move ISR_Install, DPC_Create from CHNL_Create to IO_Create.
++ *! 13-Oct-2000 jeh Added dwArg parameter to WMD_CHNL_AddIOReq(), added
++ *!                 WMD_CHNL_Idle and WMD_CHNL_RegisterNotify for DSPStream.
++ *!                 Remove #ifdef DEBUG from around channel cIOCs field.
++ *! 21-Sep-2000 rr: PreOMAP chnl class library acts like a IO class library.
++ *! 25-Sep-2000 ag: MEM_[Unmap]LinearAddress added for #ifdef CHNL_PREOMAP.
++ *! 07-Sep-2000 rr: Added new channel class for PreOMAP.
++ *! 11-Jul-2000 jeh Allow NULL user event in WMD_CHNL_Open().
++ *! 06-Jul-2000 rr: Changed prefix PROC to PRCS for process module calls.
++ *! 20-Jan-2000 ag: Incorporated code review comments.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 07-Dec-1999 ag: Now setting ChnlMgr fSharedIRQ flag before ISR_Install().
++ *! 01-Dec-1999 ag: WMD_CHNL_Open() now accepts named sync event.
++ *! 14-Nov-1999 ag: DPC_Schedule() uncommented.
++ *! 28-Oct-1999 ag: CHNL Attrs userEvent not supported.
++ *!                 SM addrs taken from COFF(IO) or host resource(SM).
++ *! 25-May-1999 jg: CHNL_IOCLASS boards now get their shared memory buffer
++ *!                 address and length from symbols defined in the currently
++ *!                 loaded COFF file. See _chn_sm.h.
++ *! 18-Jun-1997 gp: Moved waiting back to ring 0 to improve performance.
++ *! 22-Jan-1998 gp: Update User's pIOC struct in GetIOC at lower IRQL (NT).
++ *! 16-Jan-1998 gp: Commented out PERF stuff, since it is not all there in NT.
++ *! 13-Jan-1998 gp: Protect IOCTLs from IO_DPC by raising IRQL to DIRQL (NT).
++ *! 22-Oct-1997 gp: Call SYNC_OpenEvent in CHNL_Open, for NT support.
++ *! 18-Jun-1997 gp: Moved waiting back to ring 0 to improve performance.
++ *! 16-Jun-1997 gp: Added call into lower edge CHNL function to allow override
++ *!                 of the SHM window length reported by Windows CM.
++ *! 05-Jun-1997 gp: Removed unnecessary critical sections.
++ *! 18-Mar-1997 gp: Ensured CHNL_FlushIO on input leaves channel in READY state.
++ *! 06-Jan-1997 gp: ifdefed to support the IO variant of SHM channel class lib.
++ *! 21-Jan-1997 gp: CHNL_Close: set pChnl = NULL for DBC_Ensure().
++ *! 14-Jan-1997 gp: Updated based on code review feedback.
++ *! 03-Jan-1997 gp: Added CHNL_E_WAITTIMEOUT error return code to CHNL_FlushIO()
++ *! 23-Oct-1996 gp: Tag channel with ring 0 process handle.
++ *! 13-Sep-1996 gp: Added performance statistics for channel.
++ *! 09-Sep-1996 gp: Added WMD_CHNL_GetMgrInfo().
++ *! 04-Sep-1996 gp: Removed shared memory control struct offset: made zero.
++ *! 01-Aug-1996 gp: Implemented basic channel manager and channel create/delete.
++ *! 17-Jul-1996 gp: Started pseudo coding.
++ *! 11-Jul-1996 gp: Stubbed out.
++ */
++
++/*  ----------------------------------- OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/sync.h>
++
++/*  ----------------------------------- Mini-Driver */
++#include <dspbridge/wmd.h>
++#include <dspbridge/wmdchnl.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/*  ----------------------------------- Others */
++#include <dspbridge/io_sm.h>
++
++/*  ----------------------------------- Define for This */
++#define USERMODE_ADDR   PAGE_OFFSET
++
++#define MAILBOX_IRQ INT_MAIL_MPU_IRQ
++
++/*  ----------------------------------- Function Prototypes */
++static struct LST_LIST *CreateChirpList(u32 uChirps);
++
++static void FreeChirpList(struct LST_LIST *pList);
++
++static struct CHNL_IRP *MakeNewChirp(void);
++
++static DSP_STATUS SearchFreeChannel(struct CHNL_MGR *pChnlMgr,
++                                 OUT u32 *pdwChnl);
++
++/*
++ *  ======== WMD_CHNL_AddIOReq ========
++ *      Enqueue an I/O request for data transfer on a channel to the DSP.
++ *      The direction (mode) is specified in the channel object. Note the DSP
++ *      address is specified for channels opened in direct I/O mode.
++ */
++DSP_STATUS WMD_CHNL_AddIOReq(struct CHNL_OBJECT *hChnl, void *pHostBuf,
++                          u32 cBytes, u32 cBufSize,
++                          OPTIONAL u32 dwDspAddr, u32 dwArg)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++      struct CHNL_IRP *pChirp = NULL;
++      u32 dwState;
++      bool fIsEOS;
++      struct CHNL_MGR *pChnlMgr = pChnl->pChnlMgr;
++      u8 *pHostSysBuf = NULL;
++      bool fSchedDPC = false;
++      u16 wMbVal = 0;
++
++      DBG_Trace(DBG_ENTER,
++                "> WMD_CHNL_AddIOReq pChnl %p CHNL_IsOutput %x uChnlType "
++                "%x Id %d\n", pChnl, CHNL_IsOutput(pChnl->uMode),
++                pChnl->uChnlType, pChnl->uId);
++
++      fIsEOS = (cBytes == 0) ? true : false;
++
++      if (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1 && pHostBuf) {
++              if (!(pHostBuf < (void *)USERMODE_ADDR)) {
++                      pHostSysBuf = pHostBuf;
++                      goto func_cont;
++              }
++              /* if addr in user mode, then copy to kernel space */
++              pHostSysBuf = MEM_Alloc(cBufSize, MEM_NONPAGED);
++              if (pHostSysBuf == NULL) {
++                      status = DSP_EMEMORY;
++                      DBG_Trace(DBG_LEVEL7,
++                               "No memory to allocate kernel buffer\n");
++                      goto func_cont;
++              }
++              if (CHNL_IsOutput(pChnl->uMode)) {
++                      status = copy_from_user(pHostSysBuf, pHostBuf,
++                                              cBufSize);
++                      if (status) {
++                              DBG_Trace(DBG_LEVEL7,
++                                       "Error copying user buffer to "
++                                       "kernel, %d bytes remaining.\n",
++                                       status);
++                              MEM_Free(pHostSysBuf);
++                              pHostSysBuf = NULL;
++                              status = DSP_EPOINTER;
++                      }
++              }
++      }
++func_cont:
++      /* Validate args:  */
++      if (pHostBuf == NULL) {
++              status = DSP_EPOINTER;
++      } else if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++              status = DSP_EHANDLE;
++      } else if (fIsEOS && CHNL_IsInput(pChnl->uMode)) {
++              status = CHNL_E_NOEOS;
++      } else {
++              /* Check the channel state: only queue chirp if channel state
++               * allows */
++              dwState = pChnl->dwState;
++              if (dwState != CHNL_STATEREADY) {
++                      if (dwState & CHNL_STATECANCEL) {
++                              status = CHNL_E_CANCELLED;
++                      } else if ((dwState & CHNL_STATEEOS)
++                                 && CHNL_IsOutput(pChnl->uMode)) {
++                              status = CHNL_E_EOS;
++                      } else {
++                              /* No other possible states left: */
++                              DBC_Assert(0);
++                      }
++              }
++      }
++      /* Mailbox IRQ is disabled to avoid race condition with DMA/ZCPY
++       * channels. DPCCS is held to avoid race conditions with PCPY channels.
++       * If DPC is scheduled in process context (IO_Schedule) and any
++       * non-mailbox interrupt occurs, that DPC will run and break CS. Hence
++       * we disable ALL DPCs. We will try to disable ONLY IO DPC later.  */
++      SYNC_EnterCS(pChnlMgr->hCSObj);
++      disable_irq(MAILBOX_IRQ);
++      if (pChnl->uChnlType == CHNL_PCPY) {
++              /* This is a processor-copy channel. */
++              if (DSP_SUCCEEDED(status) && CHNL_IsOutput(pChnl->uMode)) {
++                      /* Check buffer size on output channels for fit. */
++                      if (cBytes > IO_BufSize(pChnl->pChnlMgr->hIOMgr))
++                              status = CHNL_E_BUFSIZE;
++
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Get a free chirp: */
++              pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pFreeList);
++              if (pChirp == NULL)
++                      status = CHNL_E_NOIORPS;
++
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Enqueue the chirp on the chnl's IORequest queue: */
++              pChirp->pHostUserBuf = pChirp->pHostSysBuf = pHostBuf;
++              if (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1)
++                      pChirp->pHostSysBuf = pHostSysBuf;
++
++              if (DSP_SUCCEEDED(status)) {
++                      /* Note: for dma chans dwDspAddr contains dsp address
++                       * of SM buffer.*/
++                      DBC_Assert(pChnlMgr->uWordSize != 0);
++                      /* DSP address */
++                      pChirp->uDspAddr = dwDspAddr / pChnlMgr->uWordSize;
++                      pChirp->cBytes = cBytes;
++                      pChirp->cBufSize = cBufSize;
++                      /* Only valid for output channel */
++                      pChirp->dwArg = dwArg;
++                      pChirp->status = (fIsEOS ? CHNL_IOCSTATEOS :
++                                       CHNL_IOCSTATCOMPLETE);
++                      LST_PutTail(pChnl->pIORequests, (struct LST_ELEM *)
++                                 pChirp);
++                      pChnl->cIOReqs++;
++                      DBC_Assert(pChnl->cIOReqs <= pChnl->cChirps);
++                      /* If end of stream, update the channel state to prevent
++                       * more IOR's: */
++                      if (fIsEOS)
++                              pChnl->dwState |= CHNL_STATEEOS;
++
++                      {
++                              /* Legacy DSM Processor-Copy */
++                              DBC_Assert(pChnl->uChnlType == CHNL_PCPY);
++                              /* Request IO from the DSP */
++                              IO_RequestChnl(pChnlMgr->hIOMgr, pChnl,
++                                      (CHNL_IsInput(pChnl->uMode) ?
++                                      IO_INPUT : IO_OUTPUT), &wMbVal);
++                              fSchedDPC = true;
++                      }
++              }
++      }
++      enable_irq(MAILBOX_IRQ);
++      SYNC_LeaveCS(pChnlMgr->hCSObj);
++      if (wMbVal != 0)
++              IO_IntrDSP2(pChnlMgr->hIOMgr, wMbVal);
++
++      if (fSchedDPC == true) {
++              /* Schedule a DPC, to do the actual data transfer: */
++              IO_Schedule(pChnlMgr->hIOMgr);
++      }
++      DBG_Trace(DBG_ENTER, "< WMD_CHNL_AddIOReq pChnl %p\n", pChnl);
++      return status;
++}
++
++/*
++ *  ======== WMD_CHNL_CancelIO ========
++ *      Return all I/O requests to the client which have not yet been
++ *      transferred.  The channel's I/O completion object is
++ *      signalled, and all the I/O requests are queued as IOC's, with the
++ *      status field set to CHNL_IOCSTATCANCEL.
++ *      This call is typically used in abort situations, and is a prelude to
++ *      CHNL_Close();
++ */
++DSP_STATUS WMD_CHNL_CancelIO(struct CHNL_OBJECT *hChnl)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++      u32 iChnl = -1;
++      CHNL_MODE uMode;
++      struct CHNL_IRP *pChirp;
++      struct CHNL_MGR *pChnlMgr = NULL;
++
++      /* Check args: */
++      if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++              iChnl = pChnl->uId;
++              uMode = pChnl->uMode;
++              pChnlMgr = pChnl->pChnlMgr;
++      } else {
++              status = DSP_EHANDLE;
++      }
++      if (DSP_FAILED(status))
++              goto func_end;
++
++       /*  Mark this channel as cancelled, to prevent further IORequests or
++       *  IORequests or dispatching.  */
++      SYNC_EnterCS(pChnlMgr->hCSObj);
++      pChnl->dwState |= CHNL_STATECANCEL;
++      if (LST_IsEmpty(pChnl->pIORequests))
++              goto func_cont;
++
++      if (pChnl->uChnlType == CHNL_PCPY) {
++              /* Indicate we have no more buffers available for transfer: */
++              if (CHNL_IsInput(pChnl->uMode)) {
++                      IO_CancelChnl(pChnlMgr->hIOMgr, iChnl);
++              } else {
++                      /* Record that we no longer have output buffers
++                       * available: */
++                      pChnlMgr->dwOutputMask &= ~(1 << iChnl);
++              }
++      }
++      /* Move all IOR's to IOC queue:  */
++      while (!LST_IsEmpty(pChnl->pIORequests)) {
++              pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIORequests);
++              if (pChirp) {
++                      pChirp->cBytes = 0;
++                      pChirp->status |= CHNL_IOCSTATCANCEL;
++                      LST_PutTail(pChnl->pIOCompletions,
++                                 (struct LST_ELEM *)pChirp);
++                      pChnl->cIOCs++;
++                      pChnl->cIOReqs--;
++                      DBC_Assert(pChnl->cIOReqs >= 0);
++              }
++      }
++func_cont:
++              SYNC_LeaveCS(pChnlMgr->hCSObj);
++func_end:
++      return status;
++}
++
++/*
++ *  ======== WMD_CHNL_Close ========
++ *  Purpose:
++ *      Ensures all pending I/O on this channel is cancelled, discards all
++ *      queued I/O completion notifications, then frees the resources allocated
++ *      for this channel, and makes the corresponding logical channel id
++ *      available for subsequent use.
++ */
++DSP_STATUS WMD_CHNL_Close(struct CHNL_OBJECT *hChnl)
++{
++      DSP_STATUS status;
++      struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++
++      /* Check args: */
++      if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++              status = DSP_EHANDLE;
++              goto func_cont;
++      }
++      {
++              /* Cancel IO: this ensures no further IO requests or
++               * notifications.*/
++              status = WMD_CHNL_CancelIO(hChnl);
++      }
++func_cont:
++      if (DSP_SUCCEEDED(status)) {
++              /* Assert I/O on this channel is now cancelled: Protects
++               * from IO_DPC. */
++              DBC_Assert((pChnl->dwState & CHNL_STATECANCEL));
++              /* Invalidate channel object: Protects from
++               * CHNL_GetIOCompletion(). */
++              pChnl->dwSignature = 0x0000;
++              /* Free the slot in the channel manager: */
++              pChnl->pChnlMgr->apChannel[pChnl->uId] = NULL;
++              pChnl->pChnlMgr->cOpenChannels -= 1;
++              if (pChnl->hNtfy) {
++                      NTFY_Delete(pChnl->hNtfy);
++                      pChnl->hNtfy = NULL;
++              }
++              /* Reset channel event: (NOTE: hUserEvent freed in user
++               * context.). */
++              if (pChnl->hSyncEvent) {
++                      SYNC_ResetEvent(pChnl->hSyncEvent);
++                      SYNC_CloseEvent(pChnl->hSyncEvent);
++                      pChnl->hSyncEvent = NULL;
++              }
++              /* Free I/O request and I/O completion queues:  */
++              if (pChnl->pIOCompletions) {
++                      FreeChirpList(pChnl->pIOCompletions);
++                      pChnl->pIOCompletions = NULL;
++                      pChnl->cIOCs = 0;
++              }
++              if (pChnl->pIORequests) {
++                      FreeChirpList(pChnl->pIORequests);
++                      pChnl->pIORequests = NULL;
++                      pChnl->cIOReqs = 0;
++              }
++              if (pChnl->pFreeList) {
++                      FreeChirpList(pChnl->pFreeList);
++                      pChnl->pFreeList = NULL;
++              }
++              /* Release channel object. */
++              MEM_FreeObject(pChnl);
++              pChnl = NULL;
++      }
++      DBC_Ensure(DSP_FAILED(status) ||
++                !MEM_IsValidHandle(pChnl, CHNL_SIGNATURE));
++      return status;
++}
++
++/*
++ *  ======== WMD_CHNL_Create ========
++ *      Create a channel manager object, responsible for opening new channels
++ *      and closing old ones for a given board.
++ */
++DSP_STATUS WMD_CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++                        struct DEV_OBJECT *hDevObject,
++                        IN CONST struct CHNL_MGRATTRS *pMgrAttrs)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct CHNL_MGR *pChnlMgr = NULL;
++      s32 cChannels;
++#ifdef DEBUG
++      struct CHNL_MGR *hChnlMgr;
++#endif
++      /* Check DBC requirements:  */
++      DBC_Require(phChnlMgr != NULL);
++      DBC_Require(pMgrAttrs != NULL);
++      DBC_Require(pMgrAttrs->cChannels > 0);
++      DBC_Require(pMgrAttrs->cChannels <= CHNL_MAXCHANNELS);
++      DBC_Require(pMgrAttrs->uWordSize != 0);
++#ifdef DEBUG
++      /* This for the purposes of DBC_Require: */
++      status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
++      DBC_Require(status != DSP_EHANDLE);
++      DBC_Require(hChnlMgr == NULL);
++#endif
++      if (DSP_SUCCEEDED(status)) {
++              /* Allocate channel manager object: */
++              MEM_AllocObject(pChnlMgr, struct CHNL_MGR, CHNL_MGRSIGNATURE);
++              if (pChnlMgr) {
++                      /* The cChannels attr must equal the # of supported
++                       * chnls for each transport(# chnls for PCPY = DDMA =
++                       * ZCPY): i.e. pMgrAttrs->cChannels = CHNL_MAXCHANNELS =
++                       * DDMA_MAXDDMACHNLS = DDMA_MAXZCPYCHNLS.  */
++                      DBC_Assert(pMgrAttrs->cChannels == CHNL_MAXCHANNELS);
++                      cChannels = (CHNL_MAXCHANNELS + (CHNL_MAXCHANNELS *
++                                  CHNL_PCPY));
++                      /* Create array of channels: */
++                      pChnlMgr->apChannel = MEM_Calloc(
++                                              sizeof(struct CHNL_OBJECT *) *
++                                              cChannels, MEM_NONPAGED);
++                      if (pChnlMgr->apChannel) {
++                              /* Initialize CHNL_MGR object: */
++                              /* Shared memory driver. */
++                              pChnlMgr->dwType = CHNL_TYPESM;
++                              pChnlMgr->uWordSize = pMgrAttrs->uWordSize;
++                              /* total # chnls supported */
++                              pChnlMgr->cChannels = cChannels;
++                              pChnlMgr->cOpenChannels = 0;
++                              pChnlMgr->dwOutputMask = 0;
++                              pChnlMgr->dwLastOutput = 0;
++                              pChnlMgr->hDevObject = hDevObject;
++                              if (DSP_SUCCEEDED(status)) {
++                                      status = SYNC_InitializeDPCCS
++                                              (&pChnlMgr->hCSObj);
++                              }
++                      } else {
++                              status = DSP_EMEMORY;
++                      }
++              } else {
++                      status = DSP_EMEMORY;
++              }
++      }
++      if (DSP_FAILED(status)) {
++              WMD_CHNL_Destroy(pChnlMgr);
++              *phChnlMgr = NULL;
++      } else {
++              /* Return channel manager object to caller... */
++              *phChnlMgr = pChnlMgr;
++      }
++      return status;
++}
++
++/*
++ *  ======== WMD_CHNL_Destroy ========
++ *  Purpose:
++ *      Close all open channels, and destroy the channel manager.
++ */
++DSP_STATUS WMD_CHNL_Destroy(struct CHNL_MGR *hChnlMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct CHNL_MGR *pChnlMgr = hChnlMgr;
++      u32 iChnl;
++
++      if (MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
++              /* Close all open channels: */
++              for (iChnl = 0; iChnl < pChnlMgr->cChannels; iChnl++) {
++                      if (DSP_SUCCEEDED
++                          (WMD_CHNL_Close(pChnlMgr->apChannel[iChnl]))) {
++                              DBC_Assert(pChnlMgr->apChannel[iChnl] == NULL);
++                      }
++              }
++              /* release critical section */
++              if (pChnlMgr->hCSObj)
++                      SYNC_DeleteCS(pChnlMgr->hCSObj);
++
++              /* Free channel manager object: */
++              if (pChnlMgr->apChannel)
++                      MEM_Free(pChnlMgr->apChannel);
++
++              /* Set hChnlMgr to NULL in device object. */
++              DEV_SetChnlMgr(pChnlMgr->hDevObject, NULL);
++              /* Free this Chnl Mgr object: */
++              MEM_FreeObject(hChnlMgr);
++      } else {
++              status = DSP_EHANDLE;
++      }
++      return status;
++}
++
++/*
++ *  ======== WMD_CHNL_FlushIO ========
++ *  purpose:
++ *      Flushes all the outstanding data requests on a channel.
++ */
++DSP_STATUS WMD_CHNL_FlushIO(struct CHNL_OBJECT *hChnl, u32 dwTimeOut)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++      CHNL_MODE uMode = -1;
++      struct CHNL_MGR *pChnlMgr;
++      struct CHNL_IOC chnlIOC;
++      /* Check args:  */
++      if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++              if ((dwTimeOut == CHNL_IOCNOWAIT)
++                  && CHNL_IsOutput(pChnl->uMode)) {
++                      status = DSP_EINVALIDARG;
++              } else {
++                      uMode = pChnl->uMode;
++                      pChnlMgr = pChnl->pChnlMgr;
++              }
++      } else {
++              status = DSP_EHANDLE;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Note: Currently, if another thread continues to add IO
++               * requests to this channel, this function will continue to
++               * flush all such queued IO requests.  */
++              if (CHNL_IsOutput(uMode) && (pChnl->uChnlType == CHNL_PCPY)) {
++                      /* Wait for IO completions, up to the specified
++                       * timeout: */
++                      while (!LST_IsEmpty(pChnl->pIORequests) &&
++                            DSP_SUCCEEDED(status)) {
++                              status = WMD_CHNL_GetIOC(hChnl, dwTimeOut,
++                                                       &chnlIOC);
++                              if (DSP_FAILED(status))
++                                      continue;
++
++                              if (chnlIOC.status & CHNL_IOCSTATTIMEOUT)
++                                      status = CHNL_E_WAITTIMEOUT;
++
++                      }
++              } else {
++                      status = WMD_CHNL_CancelIO(hChnl);
++                      /* Now, leave the channel in the ready state: */
++                      pChnl->dwState &= ~CHNL_STATECANCEL;
++              }
++      }
++      DBC_Ensure(DSP_FAILED(status) || LST_IsEmpty(pChnl->pIORequests));
++      return status;
++}
++
++/*
++ *  ======== WMD_CHNL_GetInfo ========
++ *  Purpose:
++ *      Retrieve information related to a channel.
++ */
++DSP_STATUS WMD_CHNL_GetInfo(struct CHNL_OBJECT *hChnl,
++                         OUT struct CHNL_INFO *pInfo)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++      if (pInfo != NULL) {
++              if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++                      /* Return the requested information:  */
++                      pInfo->hChnlMgr = pChnl->pChnlMgr;
++                      pInfo->hEvent = pChnl->hUserEvent;
++                      pInfo->dwID = pChnl->uId;
++                      pInfo->dwMode = pChnl->uMode;
++                      pInfo->cPosition = pChnl->cBytesMoved;
++                      pInfo->hProcess = pChnl->hProcess;
++                      pInfo->hSyncEvent = pChnl->hSyncEvent;
++                      pInfo->cIOCs = pChnl->cIOCs;
++                      pInfo->cIOReqs = pChnl->cIOReqs;
++                      pInfo->dwState = pChnl->dwState;
++              } else {
++                      status = DSP_EHANDLE;
++              }
++      } else {
++              status = DSP_EPOINTER;
++      }
++      return status;
++}
++
++/*
++ *  ======== WMD_CHNL_GetIOC ========
++ *      Optionally wait for I/O completion on a channel.  Dequeue an I/O
++ *      completion record, which contains information about the completed
++ *      I/O request.
++ *      Note: Ensures Channel Invariant (see notes above).
++ */
++DSP_STATUS WMD_CHNL_GetIOC(struct CHNL_OBJECT *hChnl, u32 dwTimeOut,
++                        OUT struct CHNL_IOC *pIOC)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++      struct CHNL_IRP *pChirp;
++      DSP_STATUS statSync;
++      bool fDequeueIOC = true;
++      struct CHNL_IOC ioc = { NULL, 0, 0, 0, 0 };
++      u8 *pHostSysBuf = NULL;
++
++      DBG_Trace(DBG_ENTER, "> WMD_CHNL_GetIOC pChnl %p CHNL_IsOutput %x "
++               "uChnlType %x\n", pChnl, CHNL_IsOutput(pChnl->uMode),
++               pChnl->uChnlType);
++      /* Check args: */
++      if (pIOC == NULL) {
++              status = DSP_EPOINTER;
++      } else if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++              status = DSP_EHANDLE;
++      } else if (dwTimeOut == CHNL_IOCNOWAIT) {
++              if (LST_IsEmpty(pChnl->pIOCompletions))
++                      status = CHNL_E_NOIOC;
++
++      }
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      ioc.status = CHNL_IOCSTATCOMPLETE;
++      if (dwTimeOut != CHNL_IOCNOWAIT && LST_IsEmpty(pChnl->pIOCompletions)) {
++              if (dwTimeOut == CHNL_IOCINFINITE)
++                      dwTimeOut = SYNC_INFINITE;
++
++              statSync = SYNC_WaitOnEvent(pChnl->hSyncEvent, dwTimeOut);
++              if (statSync == DSP_ETIMEOUT) {
++                      /* No response from DSP */
++                      ioc.status |= CHNL_IOCSTATTIMEOUT;
++                      fDequeueIOC = false;
++              } else if (statSync == DSP_EFAIL) {
++                      /* This can occur when the user mode thread is
++                       * aborted (^C), or when _VWIN32_WaitSingleObject()
++                       * fails due to unkown causes.  */
++                      /* Even though Wait failed, there may be something in
++                       * the Q: */
++                      if (LST_IsEmpty(pChnl->pIOCompletions)) {
++                              ioc.status |= CHNL_IOCSTATCANCEL;
++                              fDequeueIOC = false;
++                      }
++              }
++      }
++      /* See comment in AddIOReq */
++      SYNC_EnterCS(pChnl->pChnlMgr->hCSObj);
++      disable_irq(MAILBOX_IRQ);
++      if (fDequeueIOC) {
++              /* Dequeue IOC and set pIOC; */
++              DBC_Assert(!LST_IsEmpty(pChnl->pIOCompletions));
++              pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIOCompletions);
++              /* Update pIOC from channel state and chirp: */
++              if (pChirp) {
++                      pChnl->cIOCs--;
++                      /*  If this is a zero-copy channel, then set IOC's pBuf
++                       *  to the DSP's address. This DSP address will get
++                       *  translated to user's virtual addr later.  */
++                      {
++                              pHostSysBuf = pChirp->pHostSysBuf;
++                              ioc.pBuf = pChirp->pHostUserBuf;
++                      }
++                      ioc.cBytes = pChirp->cBytes;
++                      ioc.cBufSize = pChirp->cBufSize;
++                      ioc.dwArg = pChirp->dwArg;
++                      ioc.status |= pChirp->status;
++                      /* Place the used chirp on the free list: */
++                      LST_PutTail(pChnl->pFreeList, (struct LST_ELEM *)
++                                 pChirp);
++              } else {
++                      ioc.pBuf = NULL;
++                      ioc.cBytes = 0;
++              }
++      } else {
++              ioc.pBuf = NULL;
++              ioc.cBytes = 0;
++              ioc.dwArg = 0;
++              ioc.cBufSize = 0;
++      }
++      /* Ensure invariant: If any IOC's are queued for this channel... */
++      if (!LST_IsEmpty(pChnl->pIOCompletions)) {
++              /*  Since DSPStream_Reclaim() does not take a timeout
++               *  parameter, we pass the stream's timeout value to
++               *  WMD_CHNL_GetIOC. We cannot determine whether or not
++               *  we have waited in User mode. Since the stream's timeout
++               *  value may be non-zero, we still have to set the event.
++               *  Therefore, this optimization is taken out.
++               *
++               *  if (dwTimeOut == CHNL_IOCNOWAIT) {
++               *    ... ensure event is set..
++               *      SYNC_SetEvent(pChnl->hSyncEvent);
++               *  } */
++              SYNC_SetEvent(pChnl->hSyncEvent);
++      } else {
++              /* else, if list is empty, ensure event is reset. */
++              SYNC_ResetEvent(pChnl->hSyncEvent);
++      }
++      enable_irq(MAILBOX_IRQ);
++      SYNC_LeaveCS(pChnl->pChnlMgr->hCSObj);
++      if (fDequeueIOC && (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1)) {
++              if (!(ioc.pBuf < (void *) USERMODE_ADDR))
++                      goto func_cont;
++
++              /* If the addr is in user mode, then copy it */
++              if (!pHostSysBuf || !ioc.pBuf) {
++                      status = DSP_EPOINTER;
++                      DBG_Trace(DBG_LEVEL7,
++                               "System buffer NULL in IO completion.\n");
++                      goto func_cont;
++              }
++              if (!CHNL_IsInput(pChnl->uMode))
++                      goto func_cont1;
++
++              /*pHostUserBuf */
++              status = copy_to_user(ioc.pBuf, pHostSysBuf, ioc.cBytes);
++#ifndef RES_CLEANUP_DISABLE
++              if (status) {
++                      if (current->flags & PF_EXITING) {
++                              DBG_Trace(DBG_LEVEL7,
++                                       "\n2current->flags ==  PF_EXITING, "
++                                       " current->flags;0x%x\n",
++                                       current->flags);
++                              status = 0;
++                      } else {
++                              DBG_Trace(DBG_LEVEL7,
++                                       "\n2current->flags != PF_EXITING, "
++                                       " current->flags;0x%x\n",
++                                       current->flags);
++                      }
++              }
++#endif
++              if (status) {
++                      DBG_Trace(DBG_LEVEL7,
++                               "Error copying kernel buffer to user, %d"
++                               " bytes remaining.  in_interupt %d\n",
++                               status, in_interrupt());
++                      status = DSP_EPOINTER;
++              }
++func_cont1:
++              MEM_Free(pHostSysBuf);
++      }
++func_cont:
++      /* Update User's IOC block: */
++      *pIOC = ioc;
++func_end:
++      DBG_Trace(DBG_ENTER, "< WMD_CHNL_GetIOC pChnl %p\n", pChnl);
++      return status;
++}
++
++/*
++ *  ======== WMD_CHNL_GetMgrInfo ========
++ *      Retrieve information related to the channel manager.
++ */
++DSP_STATUS WMD_CHNL_GetMgrInfo(struct CHNL_MGR *hChnlMgr, u32 uChnlID,
++                            OUT struct CHNL_MGRINFO *pMgrInfo)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct CHNL_MGR *pChnlMgr = (struct CHNL_MGR *)hChnlMgr;
++
++      if (pMgrInfo != NULL) {
++              if (uChnlID <= CHNL_MAXCHANNELS) {
++                      if (MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
++                              /* Return the requested information:  */
++                              pMgrInfo->hChnl = pChnlMgr->apChannel[uChnlID];
++                              pMgrInfo->cOpenChannels = pChnlMgr->
++                                                        cOpenChannels;
++                              pMgrInfo->dwType = pChnlMgr->dwType;
++                              /* total # of chnls */
++                              pMgrInfo->cChannels = pChnlMgr->cChannels;
++                      } else {
++                              status = DSP_EHANDLE;
++                      }
++              } else {
++                      status = CHNL_E_BADCHANID;
++              }
++      } else {
++              status = DSP_EPOINTER;
++      }
++
++      return status;
++}
++
++/*
++ *  ======== WMD_CHNL_Idle ========
++ *      Idles a particular channel.
++ */
++DSP_STATUS WMD_CHNL_Idle(struct CHNL_OBJECT *hChnl, u32 dwTimeOut,
++                       bool fFlush)
++{
++      CHNL_MODE uMode;
++      struct CHNL_MGR *pChnlMgr;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(MEM_IsValidHandle(hChnl, CHNL_SIGNATURE));
++
++      uMode = hChnl->uMode;
++      pChnlMgr = hChnl->pChnlMgr;
++
++      if (CHNL_IsOutput(uMode) && !fFlush) {
++              /* Wait for IO completions, up to the specified timeout: */
++              status = WMD_CHNL_FlushIO(hChnl, dwTimeOut);
++      } else {
++              status = WMD_CHNL_CancelIO(hChnl);
++
++              /* Reset the byte count and put channel back in ready state. */
++              hChnl->cBytesMoved = 0;
++              hChnl->dwState &= ~CHNL_STATECANCEL;
++      }
++
++      return status;
++}
++
++/*
++ *  ======== WMD_CHNL_Open ========
++ *      Open a new half-duplex channel to the DSP board.
++ */
++DSP_STATUS WMD_CHNL_Open(OUT struct CHNL_OBJECT **phChnl,
++                       struct CHNL_MGR *hChnlMgr, CHNL_MODE uMode,
++                       u32 uChnlId, CONST IN struct CHNL_ATTRS *pAttrs)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct CHNL_MGR *pChnlMgr = hChnlMgr;
++      struct CHNL_OBJECT *pChnl = NULL;
++      struct SYNC_ATTRS *pSyncAttrs = NULL;
++      struct SYNC_OBJECT *hSyncEvent = NULL;
++      /* Ensure DBC requirements:  */
++      DBC_Require(phChnl != NULL);
++      DBC_Require(pAttrs != NULL);
++      *phChnl = NULL;
++      /* Validate Args:  */
++      if (pAttrs->uIOReqs == 0) {
++              status = DSP_EINVALIDARG;
++      } else {
++              if (!MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
++                      status = DSP_EHANDLE;
++              } else {
++                      if (uChnlId != CHNL_PICKFREE) {
++                              if (uChnlId >= pChnlMgr->cChannels) {
++                                      status = CHNL_E_BADCHANID;
++                              } else if (pChnlMgr->apChannel[uChnlId] !=
++                                        NULL) {
++                                      status = CHNL_E_CHANBUSY;
++                              }
++                      } else {
++                              /* Check for free channel */
++                              status = SearchFreeChannel(pChnlMgr, &uChnlId);
++                      }
++              }
++      }
++      if (DSP_FAILED(status))
++              goto func_end;
++
++      DBC_Assert(uChnlId < pChnlMgr->cChannels);
++      /* Create channel object:  */
++      MEM_AllocObject(pChnl, struct CHNL_OBJECT, 0x0000);
++      if (!pChnl) {
++              status = DSP_EMEMORY;
++              goto func_cont;
++      }
++      /* Protect queues from IO_DPC: */
++      pChnl->dwState = CHNL_STATECANCEL;
++      /* Allocate initial IOR and IOC queues: */
++      pChnl->pFreeList = CreateChirpList(pAttrs->uIOReqs);
++      pChnl->pIORequests = CreateChirpList(0);
++      pChnl->pIOCompletions = CreateChirpList(0);
++      pChnl->cChirps = pAttrs->uIOReqs;
++      pChnl->cIOCs = 0;
++      pChnl->cIOReqs = 0;
++      status = SYNC_OpenEvent(&hSyncEvent, pSyncAttrs);
++      if (DSP_SUCCEEDED(status)) {
++              status = NTFY_Create(&pChnl->hNtfy);
++              if (DSP_FAILED(status)) {
++                      /* The only failure that could have occurred */
++                      status = DSP_EMEMORY;
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              if (pChnl->pIOCompletions && pChnl->pIORequests &&
++                 pChnl->pFreeList) {
++                      /* Initialize CHNL object fields:    */
++                      pChnl->pChnlMgr = pChnlMgr;
++                      pChnl->uId = uChnlId;
++                      pChnl->uMode = uMode;
++                      pChnl->hUserEvent = hSyncEvent; /* for Linux */
++                      pChnl->hSyncEvent = hSyncEvent;
++                       /* get the process handle */
++                       pChnl->hProcess = current->pid;
++                      pChnl->pCBArg = 0;
++                      pChnl->cBytesMoved = 0;
++                      /* Default to proc-copy */
++                      pChnl->uChnlType = CHNL_PCPY;
++              } else {
++                      status = DSP_EMEMORY;
++              }
++      } else {
++              status = DSP_EINVALIDARG;
++      }
++      if (DSP_FAILED(status)) {
++              /* Free memory */
++              if (pChnl->pIOCompletions) {
++                      FreeChirpList(pChnl->pIOCompletions);
++                      pChnl->pIOCompletions = NULL;
++                      pChnl->cIOCs = 0;
++              }
++              if (pChnl->pIORequests) {
++                      FreeChirpList(pChnl->pIORequests);
++                      pChnl->pIORequests = NULL;
++              }
++              if (pChnl->pFreeList) {
++                      FreeChirpList(pChnl->pFreeList);
++                      pChnl->pFreeList = NULL;
++              }
++              if (hSyncEvent) {
++                      SYNC_CloseEvent(hSyncEvent);
++                      hSyncEvent = NULL;
++              }
++              if (pChnl->hNtfy) {
++                      NTFY_Delete(pChnl->hNtfy);
++                      pChnl->hNtfy = NULL;
++              }
++              MEM_FreeObject(pChnl);
++      }
++func_cont:
++      if (DSP_SUCCEEDED(status)) {
++              /* Insert channel object in channel manager: */
++              pChnlMgr->apChannel[pChnl->uId] = pChnl;
++              SYNC_EnterCS(pChnlMgr->hCSObj);
++              pChnlMgr->cOpenChannels++;
++              SYNC_LeaveCS(pChnlMgr->hCSObj);
++              /* Return result... */
++              pChnl->dwSignature = CHNL_SIGNATURE;
++              pChnl->dwState = CHNL_STATEREADY;
++              *phChnl = pChnl;
++      }
++func_end:
++      DBC_Ensure((DSP_SUCCEEDED(status) &&
++                MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) ||
++                (*phChnl == NULL));
++      return status;
++}
++
++/*
++ *  ======== WMD_CHNL_RegisterNotify ========
++ *      Registers for events on a particular channel.
++ */
++DSP_STATUS WMD_CHNL_RegisterNotify(struct CHNL_OBJECT *hChnl, u32 uEventMask,
++                                u32 uNotifyType,
++                                struct DSP_NOTIFICATION *hNotification)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Assert(!(uEventMask & ~(DSP_STREAMDONE | DSP_STREAMIOCOMPLETION)));
++
++      status = NTFY_Register(hChnl->hNtfy, hNotification, uEventMask,
++                            uNotifyType);
++
++      return status;
++}
++
++/*
++ *  ======== CreateChirpList ========
++ *  Purpose:
++ *      Initialize a queue of channel I/O Request/Completion packets.
++ *  Parameters:
++ *      uChirps:    Number of Chirps to allocate.
++ *  Returns:
++ *      Pointer to queue of IRPs, or NULL.
++ *  Requires:
++ *  Ensures:
++ */
++static struct LST_LIST *CreateChirpList(u32 uChirps)
++{
++      struct LST_LIST *pChirpList;
++      struct CHNL_IRP *pChirp;
++      u32 i;
++
++      pChirpList = LST_Create();
++
++      if (pChirpList) {
++              /* Make N chirps and place on queue. */
++              for (i = 0; (i < uChirps) && ((pChirp = MakeNewChirp()) !=
++                  NULL); i++) {
++                      LST_PutTail(pChirpList, (struct LST_ELEM *)pChirp);
++              }
++
++              /* If we couldn't allocate all chirps, free those allocated: */
++              if (i != uChirps) {
++                      FreeChirpList(pChirpList);
++                      pChirpList = NULL;
++              }
++      }
++
++      return pChirpList;
++}
++
++/*
++ *  ======== FreeChirpList ========
++ *  Purpose:
++ *      Free the queue of Chirps.
++ */
++static void FreeChirpList(struct LST_LIST *pChirpList)
++{
++      DBC_Require(pChirpList != NULL);
++
++      while (!LST_IsEmpty(pChirpList))
++              MEM_Free(LST_GetHead(pChirpList));
++
++      LST_Delete(pChirpList);
++}
++
++/*
++ *  ======== MakeNewChirp ========
++ *      Allocate the memory for a new channel IRP.
++ */
++static struct CHNL_IRP *MakeNewChirp(void)
++{
++      struct CHNL_IRP *pChirp;
++
++      pChirp = (struct CHNL_IRP *)MEM_Calloc(
++               sizeof(struct CHNL_IRP), MEM_NONPAGED);
++      if (pChirp != NULL) {
++              /* LST_InitElem only resets the list's member values. */
++              LST_InitElem(&pChirp->link);
++      }
++
++      return pChirp;
++}
++
++/*
++ *  ======== SearchFreeChannel ========
++ *      Search for a free channel slot in the array of channel pointers.
++ */
++static DSP_STATUS SearchFreeChannel(struct CHNL_MGR *pChnlMgr,
++                                 OUT u32 *pdwChnl)
++{
++      DSP_STATUS status = CHNL_E_OUTOFSTREAMS;
++      u32 i;
++
++      DBC_Require(MEM_IsValidHandle(pChnlMgr, CHNL_MGRSIGNATURE));
++
++      for (i = 0; i < pChnlMgr->cChannels; i++) {
++              if (pChnlMgr->apChannel[i] == NULL) {
++                      status = DSP_SOK;
++                      *pdwChnl = i;
++                      break;
++              }
++      }
++
++      return status;
++}
+diff --git a/drivers/dsp/bridge/wmd/io_sm.c b/drivers/dsp/bridge/wmd/io_sm.c
+new file mode 100644
+index 0000000..325f1f1
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/io_sm.c
+@@ -0,0 +1,2011 @@
++/*
++ * io_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== io_sm.c ========
++ *  Description:
++ *      IO dispatcher for a shared memory channel driver.
++ *
++ *  Public Functions:
++ *      WMD_IO_Create
++ *      WMD_IO_Destroy
++ *      WMD_IO_OnLoaded
++ *      IO_AndSetValue
++ *      IO_BufSize
++ *      IO_CancelChnl
++ *      IO_DPC
++ *      IO_ISR
++ *      IO_IVAISR
++ *      IO_OrSetValue
++ *      IO_ReadValue
++ *      IO_ReadValueLong
++ *      IO_RequestChnl
++ *      IO_Schedule
++ *      IO_WriteValue
++ *      IO_WriteValueLong
++ *
++ *  Channel Invariant:
++ *      There is an important invariant condition which must be maintained per
++ *      channel outside of WMD_CHNL_GetIOC() and IO_Dispatch(), violation of
++ *      which may cause timeouts and/or failure of the WIN32_WaitSingleObject
++ *      function (SYNC_WaitOnEvent).
++ *
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++#include <linux/workqueue.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/reg.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/*  ----------------------------------- Mini Driver */
++#include <dspbridge/wmddeh.h>
++#include <dspbridge/wmdio.h>
++#include <dspbridge/wmdioctl.h>
++#include <_tiomap.h>
++#include <tiomap_io.h>
++#include <_tiomap_pwr.h>
++#include <tiomap_io.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/chnl_sm.h>
++#include <dspbridge/dbreg.h>
++
++/*  ----------------------------------- Others */
++#include <dspbridge/rms_sh.h>
++#include <dspbridge/mgr.h>
++#include <dspbridge/drv.h>
++#include "_cmm.h"
++
++/*  ----------------------------------- This */
++#include <dspbridge/io_sm.h>
++#include "_msg_sm.h"
++#include <dspbridge/gt.h>
++
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++#define OUTPUTNOTREADY  0xffff
++#define NOTENABLED      0xffff        /* channel(s) not enabled */
++
++#define EXTEND      "_EXT_END"
++
++#define SwapWord(x)     (x)
++#define ulPageAlignSize 0x10000   /* Page Align Size */
++
++#define MAX_PM_REQS 32
++
++/* IO Manager: only one created per board: */
++struct IO_MGR {
++      /* These four fields must be the first fields in a IO_MGR_ struct: */
++      u32 dwSignature;        /* Used for object validation   */
++      struct WMD_DEV_CONTEXT *hWmdContext;    /* WMD device context  */
++      struct WMD_DRV_INTERFACE *pIntfFxns;    /* Function interface to WMD */
++      struct DEV_OBJECT *hDevObject;  /* Device this board represents */
++
++      /* These fields initialized in WMD_IO_Create():    */
++      struct CHNL_MGR *hChnlMgr;
++      struct SHM *pSharedMem;         /* Shared Memory control        */
++      u8 *pInput;             /* Address of input channel     */
++      u8 *pOutput;            /* Address of output channel    */
++      struct MSG_MGR *hMsgMgr;        /* Message manager */
++      struct MSG *pMsgInputCtrl;      /* Msg control for from DSP messages */
++      struct MSG *pMsgOutputCtrl;     /* Msg control for to DSP messages */
++      u8 *pMsgInput;  /* Address of input messages    */
++      u8 *pMsgOutput;         /* Address of output messages   */
++      u32 uSMBufSize;         /* Size of a shared memory I/O channel */
++      bool fSharedIRQ;        /* Is this IRQ shared?    */
++      struct DPC_OBJECT *hDPC;        /* DPC object handle        */
++      struct SYNC_CSOBJECT *hCSObj;   /* Critical section object handle */
++      u32 uWordSize;  /* Size in bytes of DSP word    */
++      u16 wIntrVal;           /* interrupt value            */
++      /* private extnd proc info; mmu setup */
++      struct MGR_PROCESSOREXTINFO extProcInfo;
++      struct CMM_OBJECT *hCmmMgr;     /* Shared Mem Mngr            */
++       struct work_struct io_workq;     /*workqueue */
++      u32 dQuePowerMbxVal[MAX_PM_REQS];
++      u32 iQuePowerHead;
++      u32 iQuePowerTail;
++#ifndef DSP_TRACEBUF_DISABLED
++      u32 ulTraceBufferBegin;         /* Trace message start address */
++      u32 ulTraceBufferEnd;   /* Trace message end address */
++      u32 ulTraceBufferCurrent;       /* Trace message current address */
++      u32 ulGPPReadPointer;   /* GPP Read pointer to Trace buffer */
++      u8 *pMsg;
++      u32 ulGppVa;
++      u32 ulDspVa;
++#endif
++} ;
++
++/*  ----------------------------------- Function Prototypes */
++static void IO_DispatchChnl(IN struct IO_MGR *pIOMgr,
++                         IN OUT struct CHNL_OBJECT *pChnl, u32 iMode);
++static void IO_DispatchMsg(IN struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
++static void IO_DispatchPM(struct work_struct *work);
++static void NotifyChnlComplete(struct CHNL_OBJECT *pChnl,
++                              struct CHNL_IRP *pChirp);
++static void InputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++                      u32 iMode);
++static void OutputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++                      u32 iMode);
++static void InputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
++static void OutputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
++static u32 FindReadyOutput(struct CHNL_MGR *pChnlMgr,
++                           struct CHNL_OBJECT *pChnl, u32 dwMask);
++static u32 ReadData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++                      void *pSrc, u32 uSize);
++static u32 WriteData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++                      void *pSrc, u32 uSize);
++static struct workqueue_struct *bridge_workqueue;
++#ifndef DSP_TRACEBUF_DISABLED
++void PrintDSPDebugTrace(struct IO_MGR *hIOMgr);
++#endif
++
++/* Bus Addr (cached kernel)*/
++static DSP_STATUS registerSHMSegs(struct IO_MGR *hIOMgr,
++                                struct COD_MANAGER *hCodMan,
++                                u32 dwGPPBasePA);
++
++#ifdef CONFIG_BRIDGE_DVFS
++/* The maximum number of OPPs that are supported */
++extern s32 dsp_max_opps;
++/* The Vdd1 opp table information */
++extern u32 vdd1_dsp_freq[6][4] ;
++#endif
++
++#if GT_TRACE
++static struct GT_Mask dsp_trace_mask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++/*
++ *  ======== WMD_IO_Create ========
++ *      Create an IO manager object.
++ */
++DSP_STATUS WMD_IO_Create(OUT struct IO_MGR **phIOMgr,
++                       struct DEV_OBJECT *hDevObject,
++                       IN CONST struct IO_ATTRS *pMgrAttrs)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct IO_MGR *pIOMgr = NULL;
++      struct SHM *pSharedMem = NULL;
++      struct WMD_DEV_CONTEXT *hWmdContext = NULL;
++      struct CFG_HOSTRES hostRes;
++      struct CFG_DEVNODE *hDevNode;
++      struct CHNL_MGR *hChnlMgr;
++       static int ref_count;
++      u32 devType;
++      /* Check DBC requirements:  */
++      DBC_Require(phIOMgr != NULL);
++      DBC_Require(pMgrAttrs != NULL);
++      DBC_Require(pMgrAttrs->uWordSize != 0);
++      /* This for the purposes of DBC_Require: */
++      status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
++      DBC_Require(status != DSP_EHANDLE);
++      DBC_Require(hChnlMgr != NULL);
++      DBC_Require(hChnlMgr->hIOMgr == NULL);
++       /*  Message manager will be created when a file is loaded, since
++       *  size of message buffer in shared memory is configurable in
++       *  the base image.  */
++      DEV_GetWMDContext(hDevObject, &hWmdContext);
++      DBC_Assert(hWmdContext);
++      DEV_GetDevType(hDevObject, &devType);
++      /*  DSP shared memory area will get set properly when
++       *  a program is loaded. They are unknown until a COFF file is
++       *  loaded. I chose the value -1 because it was less likely to be
++       *  a valid address than 0.  */
++      pSharedMem = (struct SHM *) -1;
++      if (DSP_FAILED(status))
++              goto func_cont;
++
++    /*
++     *  Create a Single Threaded Work Queue
++     */
++
++       if (ref_count == 0)
++               bridge_workqueue = create_workqueue("bridge_work-queue");
++
++       if (bridge_workqueue <= 0)
++               DBG_Trace(DBG_LEVEL1, "Workque Create"
++                       " failed 0x%d \n", bridge_workqueue);
++
++
++      /* Allocate IO manager object: */
++      MEM_AllocObject(pIOMgr, struct IO_MGR, IO_MGRSIGNATURE);
++      if (pIOMgr == NULL) {
++              status = DSP_EMEMORY;
++              goto func_cont;
++      }
++       /*Intializing Work Element*/
++       if (ref_count == 0) {
++               INIT_WORK(&pIOMgr->io_workq, (void *)IO_DispatchPM);
++               ref_count = 1;
++       } else
++               PREPARE_WORK(&pIOMgr->io_workq, (void *)IO_DispatchPM);
++
++      /* Initialize CHNL_MGR object:    */
++#ifndef DSP_TRACEBUF_DISABLED
++      pIOMgr->pMsg = NULL;
++#endif
++      pIOMgr->hChnlMgr = hChnlMgr;
++      pIOMgr->uWordSize = pMgrAttrs->uWordSize;
++      pIOMgr->pSharedMem = pSharedMem;
++      if (DSP_SUCCEEDED(status))
++              status = SYNC_InitializeCS(&pIOMgr->hCSObj);
++
++      if (devType == DSP_UNIT) {
++              /* Create a DPC object: */
++              status = DPC_Create(&pIOMgr->hDPC, IO_DPC, (void *)pIOMgr);
++              if (DSP_SUCCEEDED(status))
++                      status = DEV_GetDevNode(hDevObject, &hDevNode);
++
++              pIOMgr->iQuePowerHead = 0;
++              pIOMgr->iQuePowerTail = 0;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              status = CFG_GetHostResources((struct CFG_DEVNODE *)
++                              DRV_GetFirstDevExtension() , &hostRes);
++      }
++      if (DSP_SUCCEEDED(status)) {
++              pIOMgr->hWmdContext = hWmdContext;
++              pIOMgr->fSharedIRQ = pMgrAttrs->fShared;
++              IO_DisableInterrupt(hWmdContext);
++              if (devType == DSP_UNIT) {
++                      /* Plug the channel ISR:. */
++                       if ((request_irq(INT_MAIL_MPU_IRQ, IO_ISR, 0,
++                               "DspBridge\tmailbox", (void *)pIOMgr)) == 0)
++                               status = DSP_SOK;
++                       else
++                               status = DSP_EFAIL;
++              }
++       if (DSP_SUCCEEDED(status))
++               DBG_Trace(DBG_LEVEL1, "ISR_IRQ Object 0x%x \n",
++                               pIOMgr);
++       else
++               status = CHNL_E_ISR;
++       } else
++              status = CHNL_E_ISR;
++func_cont:
++      if (DSP_FAILED(status)) {
++              /* Cleanup: */
++              WMD_IO_Destroy(pIOMgr);
++              *phIOMgr = NULL;
++      } else {
++              /* Return IO manager object to caller... */
++              hChnlMgr->hIOMgr = pIOMgr;
++              *phIOMgr = pIOMgr;
++      }
++      return status;
++}
++
++/*
++ *  ======== WMD_IO_Destroy ========
++ *  Purpose:
++ *      Disable interrupts, destroy the IO manager.
++ */
++DSP_STATUS WMD_IO_Destroy(struct IO_MGR *hIOMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *hWmdContext;
++      if (MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE)) {
++              /* Unplug IRQ:    */
++               /* Disable interrupts from the board:  */
++               if (DSP_SUCCEEDED(DEV_GetWMDContext(hIOMgr->hDevObject, 
++                      &hWmdContext)))
++                               DBC_Assert(hWmdContext);
++               (void)CHNLSM_DisableInterrupt(hWmdContext);
++               destroy_workqueue(bridge_workqueue);
++               /* Linux function to uninstall ISR */
++               free_irq(INT_MAIL_MPU_IRQ, (void *)hIOMgr);
++               (void)DPC_Destroy(hIOMgr->hDPC);
++#ifndef DSP_TRACEBUF_DISABLED
++              if (hIOMgr->pMsg)
++                      MEM_Free(hIOMgr->pMsg);
++#endif
++              SYNC_DeleteCS(hIOMgr->hCSObj);  /* Leak Fix. */
++              /* Free this IO manager object: */
++              MEM_FreeObject(hIOMgr);
++       } else
++              status = DSP_EHANDLE;
++
++      return status;
++}
++
++/*
++ *  ======== WMD_IO_OnLoaded ========
++ *  Purpose:
++ *      Called when a new program is loaded to get shared memory buffer
++ *      parameters from COFF file. ulSharedBufferBase and ulSharedBufferLimit
++ *      are in DSP address units.
++ */
++DSP_STATUS WMD_IO_OnLoaded(struct IO_MGR *hIOMgr)
++{
++      struct COD_MANAGER *hCodMan;
++      struct CHNL_MGR *hChnlMgr;
++      struct MSG_MGR *hMsgMgr;
++      u32 ulShmBase;
++      u32 ulShmBaseOffset;
++      u32 ulShmLimit;
++      u32 ulShmLength = -1;
++      u32 ulMemLength = -1;
++      u32 ulMsgBase;
++      u32 ulMsgLimit;
++      u32 ulMsgLength = -1;
++      u32 ulExtEnd;
++      u32 ulGppPa = 0;
++      u32 ulGppVa = 0;
++      u32 ulDspVa = 0;
++      u32 ulSegSize = 0;
++      u32 ulPadSize = 0;
++      u32 i;
++      DSP_STATUS status = DSP_SOK;
++      u32 uNumProcs = 0;
++      s32 ndx = 0;
++      /* DSP MMU setup table */
++      struct WMDIOCTL_EXTPROC aEProc[WMDIOCTL_NUMOFMMUTLB];
++      struct CFG_HOSTRES hostRes;
++      u32 mapAttrs;
++      u32 ulShm0End;
++      u32 ulDynExtBase;
++      u32 ulSeg1Size = 0;
++      u32 paCurr = 0;
++      u32 vaCurr = 0;
++      u32 gppVaCurr = 0;
++      u32 numBytes = 0;
++      u32 allBits = 0;
++      u32 pgSize[] = { HW_PAGE_SIZE_16MB, HW_PAGE_SIZE_1MB,
++                         HW_PAGE_SIZE_64KB, HW_PAGE_SIZE_4KB };
++
++      status = DEV_GetCodMgr(hIOMgr->hDevObject, &hCodMan);
++      DBC_Assert(DSP_SUCCEEDED(status));
++      hChnlMgr = hIOMgr->hChnlMgr;
++       /*  The message manager is destroyed when the board is stopped.  */
++      DEV_GetMsgMgr(hIOMgr->hDevObject, &hIOMgr->hMsgMgr);
++      hMsgMgr = hIOMgr->hMsgMgr;
++      DBC_Assert(MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE));
++      DBC_Assert(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++      if (hIOMgr->pSharedMem)
++              hIOMgr->pSharedMem = NULL;
++
++      /* Get start and length of channel part of shared memory */
++      status = COD_GetSymValue(hCodMan, CHNL_SHARED_BUFFER_BASE_SYM,
++                               &ulShmBase);
++      if (DSP_FAILED(status)) {
++              status = CHNL_E_NOMEMMAP;
++              goto func_cont1;
++      }
++      status = COD_GetSymValue(hCodMan, CHNL_SHARED_BUFFER_LIMIT_SYM,
++                              &ulShmLimit);
++      if (DSP_FAILED(status)) {
++              status = CHNL_E_NOMEMMAP;
++              goto func_cont1;
++      }
++      if (ulShmLimit <= ulShmBase) {
++              status = CHNL_E_INVALIDMEMBASE;
++      } else {
++              /* get total length in bytes */
++              ulShmLength = (ulShmLimit - ulShmBase + 1) * hIOMgr->uWordSize;
++              /* Calculate size of a PROCCOPY shared memory region */
++              DBG_Trace(DBG_LEVEL7,
++                       "**(proc)PROCCOPY SHMMEM SIZE: 0x%x bytes\n",
++                        (ulShmLength - sizeof(struct SHM)));
++      }
++func_cont1:
++      if (DSP_SUCCEEDED(status)) {
++              /* Get start and length of message part of shared memory */
++              status = COD_GetSymValue(hCodMan, MSG_SHARED_BUFFER_BASE_SYM,
++                                      &ulMsgBase);
++      }
++      if (DSP_SUCCEEDED(status)) {
++              status = COD_GetSymValue(hCodMan, MSG_SHARED_BUFFER_LIMIT_SYM,
++                                      &ulMsgLimit);
++              if (DSP_SUCCEEDED(status)) {
++                      if (ulMsgLimit <= ulMsgBase) {
++                              status = CHNL_E_INVALIDMEMBASE;
++                      } else {
++                              /* Length (bytes) of messaging part of shared
++                               * memory */
++                              ulMsgLength = (ulMsgLimit - ulMsgBase + 1) *
++                                            hIOMgr->uWordSize;
++                              /* Total length (bytes) of shared memory:
++                               * chnl + msg */
++                              ulMemLength = ulShmLength + ulMsgLength;
++                      }
++              } else {
++                      status = CHNL_E_NOMEMMAP;
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++#ifndef DSP_TRACEBUF_DISABLED
++              status = COD_GetSymValue(hCodMan, DSP_TRACESEC_END, &ulShm0End);
++              DBG_Trace(DBG_LEVEL7, "_BRIDGE_TRACE_END value = %x \n",
++                       ulShm0End);
++#else
++              status = COD_GetSymValue(hCodMan, SHM0_SHARED_END_SYM,
++                                       &ulShm0End);
++              DBG_Trace(DBG_LEVEL7, "_SHM0_END = %x \n", ulShm0End);
++#endif
++              if (DSP_FAILED(status))
++                      status = CHNL_E_NOMEMMAP;
++
++      }
++      if (DSP_SUCCEEDED(status)) {
++              status = COD_GetSymValue(hCodMan, DYNEXTBASE, &ulDynExtBase);
++              if (DSP_FAILED(status))
++                      status = CHNL_E_NOMEMMAP;
++
++      }
++      if (DSP_SUCCEEDED(status)) {
++              status = COD_GetSymValue(hCodMan, EXTEND, &ulExtEnd);
++              if (DSP_FAILED(status))
++                      status = CHNL_E_NOMEMMAP;
++
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Get memory reserved in host resources */
++              (void)MGR_EnumProcessorInfo(0,
++                      (struct DSP_PROCESSORINFO *)&hIOMgr->extProcInfo,
++                      sizeof(struct MGR_PROCESSOREXTINFO), &uNumProcs);
++              CFG_GetHostResources((
++                      struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++                      &hostRes);
++              /* The first MMU TLB entry(TLB_0) in DCD is ShmBase. */
++              ndx = 0;
++              ulGppPa = hostRes.dwMemPhys[1];
++              ulGppVa = hostRes.dwMemBase[1];
++              /* THIS IS THE VIRTUAL UNCACHED IOREMAPPED ADDRESS !!! */
++              /* Why can't we directly take the DSPVA from the symbols? */
++              ulDspVa = hIOMgr->extProcInfo.tyTlb[0].ulDspVirt;
++              ulSegSize = (ulShm0End - ulDspVa) * hIOMgr->uWordSize;
++              ulSeg1Size = (ulExtEnd - ulDynExtBase) * hIOMgr->uWordSize;
++              ulSeg1Size = (ulSeg1Size + 0xFFF) & (~0xFFFUL); /* 4K align*/
++              ulSegSize = (ulSegSize + 0xFFFF) & (~0xFFFFUL); /* 64K align*/
++              ulPadSize = ulPageAlignSize - ((ulGppPa + ulSeg1Size) %
++                           ulPageAlignSize);
++                      if (ulPadSize == ulPageAlignSize)
++                              ulPadSize = 0x0;
++
++               DBG_Trace(DBG_LEVEL7, "ulGppPa %x, ulGppVa %x, ulDspVa %x, "
++                        "ulShm0End %x, ulDynExtBase %x, ulExtEnd %x, "
++                        "ulSegSize %x ulSeg1Size %x \n", ulGppPa, ulGppVa,
++                        ulDspVa, ulShm0End, ulDynExtBase, ulExtEnd, ulSegSize,
++                        ulSeg1Size);
++
++              if ((ulSegSize + ulSeg1Size + ulPadSize) >
++                 hostRes.dwMemLength[1]) {
++                      DBG_Trace(DBG_LEVEL7, "ulGppPa %x, ulGppVa %x, ulDspVa "
++                               "%x, ulShm0End %x, ulDynExtBase %x, ulExtEnd "
++                               "%x, ulSegSize %x, ulSeg1Size %x \n", ulGppPa,
++                               ulGppVa, ulDspVa, ulShm0End, ulDynExtBase,
++                               ulExtEnd, ulSegSize, ulSeg1Size);
++                      DBG_Trace(DBG_LEVEL7, "Insufficient SHM Reserved 0x%x. "
++                               "Required 0x%x\n", hostRes.dwMemLength[1],
++                               ulSegSize + ulSeg1Size + ulPadSize);
++                      status = DSP_EMEMORY;
++              }
++      }
++      if (DSP_FAILED(status))
++              goto func_cont;
++
++      paCurr = ulGppPa;
++      vaCurr = ulDynExtBase * hIOMgr->uWordSize;
++      gppVaCurr = ulGppVa;
++      numBytes = ulSeg1Size;
++
++      /*
++       * Try to fit into TLB entries. If not possible, push them to page
++       * tables. It is quite possible that if sections are not on
++       * bigger page boundary, we may end up making several small pages.
++       * So, push them onto page tables, if that is the case.
++       */
++      mapAttrs = 0x00000000;
++      mapAttrs = DSP_MAPLITTLEENDIAN;
++      mapAttrs |= DSP_MAPPHYSICALADDR;
++      mapAttrs |= DSP_MAPELEMSIZE32;
++      mapAttrs |= DSP_MAPDONOTLOCK;
++
++      while (numBytes && DSP_SUCCEEDED(status)) {
++              /* To find the max. page size with which both PA & VA are
++               * aligned */
++              allBits = paCurr | vaCurr;
++              DBG_Trace(DBG_LEVEL1, "allBits %x, paCurr %x, vaCurr %x, "
++                       "numBytes %x\n", allBits, paCurr, vaCurr, numBytes);
++              for (i = 0; i < 4; i++) {
++                      if ((numBytes >= pgSize[i]) && ((allBits &
++                         (pgSize[i] - 1)) == 0)) {
++                              status = hIOMgr->pIntfFxns->pfnBrdMemMap
++                                      (hIOMgr->hWmdContext, paCurr, vaCurr,
++                                      pgSize[i], mapAttrs);
++                              DBC_Assert(DSP_SUCCEEDED(status));
++                              paCurr += pgSize[i];
++                              vaCurr += pgSize[i];
++                              gppVaCurr += pgSize[i];
++                              numBytes -= pgSize[i];
++                              /* Don't try smaller sizes. Hopefully we have
++                               * reached an address aligned to a bigger page
++                               * size*/
++                              break;
++                      }
++              }
++      }
++      paCurr += ulPadSize;
++      vaCurr += ulPadSize;
++      gppVaCurr += ulPadSize;
++
++      /* configure the TLB entries for the next cacheable segment */
++      numBytes = ulSegSize;
++      vaCurr = ulDspVa * hIOMgr->uWordSize;
++      allBits = 0x0;
++      while (numBytes && DSP_SUCCEEDED(status)) {
++              /* To find the max. page size with which both PA & VA are
++               * aligned*/
++              allBits = paCurr | vaCurr;
++              DBG_Trace(DBG_LEVEL1, "allBits for Seg1 %x, paCurr %x, "
++                       "vaCurr %x, numBytes %x\n", allBits, paCurr, vaCurr,
++                       numBytes);
++              for (i = 0; i < 4; i++) {
++                      if (!(numBytes >= pgSize[i]) ||
++                         !((allBits & (pgSize[i]-1)) == 0))
++                              continue;
++                      if (ndx < MAX_LOCK_TLB_ENTRIES) {
++                              /* This is the physical address written to
++                               * DSP MMU */
++                              aEProc[ndx].ulGppPa = paCurr;
++                              /* THIS IS THE VIRTUAL UNCACHED IOREMAPPED
++                               * ADDRESS!!! */
++                              aEProc[ndx].ulGppVa = gppVaCurr;
++                              aEProc[ndx].ulDspVa = vaCurr / hIOMgr->
++                                                    uWordSize;
++                              aEProc[ndx].ulSize = pgSize[i];
++                              aEProc[ndx].endianism = HW_LITTLE_ENDIAN;
++                              aEProc[ndx].elemSize = HW_ELEM_SIZE_16BIT;
++                              aEProc[ndx].mixedMode = HW_MMU_CPUES;
++                              DBG_Trace(DBG_LEVEL1, "SHM MMU TLB entry PA %lx"
++                                       " VA %lx DSP_VA %lx Size %lx\n",
++                                       aEProc[ndx].ulGppPa,
++                                       aEProc[ndx].ulGppVa,
++                                       aEProc[ndx].ulDspVa *
++                                       hIOMgr->uWordSize, pgSize[i]);
++                              ndx++;
++                      } else {
++                              status = hIOMgr->pIntfFxns->pfnBrdMemMap(
++                              hIOMgr->hWmdContext, paCurr, vaCurr, pgSize[i],
++                                      mapAttrs);
++                              DBG_Trace(DBG_LEVEL1, "SHM MMU PTE entry PA %lx"
++                                       " VA %lx DSP_VA %lx Size %lx\n",
++                                       aEProc[ndx].ulGppPa,
++                                       aEProc[ndx].ulGppVa,
++                                       aEProc[ndx].ulDspVa *
++                                       hIOMgr->uWordSize, pgSize[i]);
++                              DBC_Assert(DSP_SUCCEEDED(status));
++                      }
++                      paCurr += pgSize[i];
++                      vaCurr += pgSize[i];
++                      gppVaCurr += pgSize[i];
++                      numBytes -= pgSize[i];
++                      /* Don't try smaller sizes. Hopefully we have reached
++                       an address aligned to a bigger page size*/
++                      break;
++              }
++      }
++
++       /* Copy remaining entries from CDB. All entries are 1 MB and should not
++       * conflict with SHM entries on MPU or DSP side */
++      for (i = 3; i < 7 && ndx < WMDIOCTL_NUMOFMMUTLB &&
++          DSP_SUCCEEDED(status); i++) {
++              if (hIOMgr->extProcInfo.tyTlb[i].ulGppPhys == 0)
++                      continue;
++
++              if ((hIOMgr->extProcInfo.tyTlb[i].ulGppPhys > ulGppPa - 0x100000
++                      && hIOMgr->extProcInfo.tyTlb[i].ulGppPhys <=
++                              ulGppPa + ulSegSize)
++                      || (hIOMgr->extProcInfo.tyTlb[i].ulDspVirt > ulDspVa -
++                              0x100000 / hIOMgr->uWordSize && hIOMgr->
++                              extProcInfo.tyTlb[i].ulDspVirt
++                              <= ulDspVa + ulSegSize / hIOMgr->uWordSize)) {
++                      DBG_Trace(DBG_LEVEL7, "CDB MMU entry %d conflicts with "
++                               "SHM.\n\tCDB: GppPa %x, DspVa %x.\n\tSHM: "
++                               "GppPa %x, DspVa %x, Bytes %x.\n", i,
++                               hIOMgr->extProcInfo.tyTlb[i].ulGppPhys,
++                               hIOMgr->extProcInfo.tyTlb[i].ulDspVirt,
++                               ulGppPa, ulDspVa, ulSegSize);
++                      status = DSP_EFAIL;
++              } else {
++                      if (ndx < MAX_LOCK_TLB_ENTRIES) {
++                              aEProc[ndx].ulDspVa = hIOMgr->extProcInfo.
++                                      tyTlb[i].ulDspVirt;
++                              aEProc[ndx].ulGppPa = hIOMgr->extProcInfo.
++                                      tyTlb[i].ulGppPhys;
++                              aEProc[ndx].ulGppVa = 0;
++                              /* Can't convert, so set to zero*/
++                              aEProc[ndx].ulSize = 0x100000;  /* 1 MB*/
++                              DBG_Trace(DBG_LEVEL1, "SHM MMU entry PA %x "
++                                       "DSP_VA 0x%x\n", aEProc[ndx].ulGppPa,
++                                      aEProc[ndx].ulDspVa);
++                              ndx++;
++                      } else {
++                              status = hIOMgr->pIntfFxns->pfnBrdMemMap
++                                      (hIOMgr->hWmdContext,
++                                      hIOMgr->extProcInfo.tyTlb[i].ulGppPhys,
++                                      hIOMgr->extProcInfo.tyTlb[i].ulDspVirt,
++                                      0x100000, mapAttrs);
++                      }
++              }
++      }
++      if (i < 7 && DSP_SUCCEEDED(status)) {
++              /* All CDB entries could not be made*/
++              status = DSP_EFAIL;
++      }
++func_cont:
++      mapAttrs = 0x00000000;
++      mapAttrs = DSP_MAPLITTLEENDIAN;
++      mapAttrs |= DSP_MAPPHYSICALADDR;
++      mapAttrs |= DSP_MAPELEMSIZE32;
++      mapAttrs |= DSP_MAPDONOTLOCK;
++
++      /* Map the L4 peripherals */
++      i = 0;
++      while (L4PeripheralTable[i].physAddr && DSP_SUCCEEDED(status)) {
++              status = hIOMgr->pIntfFxns->pfnBrdMemMap
++                      (hIOMgr->hWmdContext, L4PeripheralTable[i].physAddr,
++                      L4PeripheralTable[i].dspVirtAddr, HW_PAGE_SIZE_4KB,
++                      mapAttrs);
++              if (DSP_FAILED(status))
++                      break;
++              i++;
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              for (i = ndx; i < WMDIOCTL_NUMOFMMUTLB; i++) {
++                      aEProc[i].ulDspVa = 0;
++                      aEProc[i].ulGppPa = 0;
++                      aEProc[i].ulGppVa = 0;
++                      aEProc[i].ulSize = 0;
++              }
++              /* Set the SHM physical address entry (grayed out in CDB file)
++               * to the virtual uncached ioremapped address of SHM reserved
++               * on MPU */
++              hIOMgr->extProcInfo.tyTlb[0].ulGppPhys = (ulGppVa + ulSeg1Size +
++                                                       ulPadSize);
++              DBG_Trace(DBG_LEVEL1, "*********extProcInfo *********%x \n",
++                        hIOMgr->extProcInfo.tyTlb[0].ulGppPhys);
++              /* Need SHM Phys addr. IO supports only one DSP for now:
++               * uNumProcs=1 */
++              if ((hIOMgr->extProcInfo.tyTlb[0].ulGppPhys == 0) ||
++                 (uNumProcs != 1)) {
++                      status = CHNL_E_NOMEMMAP;
++                      DBC_Assert(false);
++              } else {
++                      DBC_Assert(aEProc[0].ulDspVa <= ulShmBase);
++                      /* ulShmBase may not be at ulDspVa address */
++                      ulShmBaseOffset = (ulShmBase - aEProc[0].ulDspVa) *
++                          hIOMgr->uWordSize;
++                       /* WMD_BRD_Ctrl() will set dev context dsp-mmu info. In
++                       *   _BRD_Start() the MMU will be re-programed with MMU
++                       *   DSPVa-GPPPa pair info while DSP is in a known
++                       *   (reset) state.  */
++                      DBC_Assert(hIOMgr->pIntfFxns != NULL);
++                      DBC_Assert(hIOMgr->hWmdContext != NULL);
++                      status = hIOMgr->pIntfFxns->pfnDevCntrl(hIOMgr->
++                               hWmdContext, WMDIOCTL_SETMMUCONFIG, aEProc);
++                      ulShmBase = hIOMgr->extProcInfo.tyTlb[0].ulGppPhys;
++                      DBG_Trace(DBG_LEVEL1, "extProcInfo.tyTlb[0].ulGppPhys "
++                               "%x \n ", hIOMgr->extProcInfo.tyTlb[0].
++                               ulGppPhys);
++                      ulShmBase += ulShmBaseOffset;
++                      ulShmBase = (u32)MEM_LinearAddress((void *)ulShmBase,
++                                  ulMemLength);
++                      DBC_Assert(ulShmBase != 0);
++                      if (DSP_SUCCEEDED(status)) {
++                              status = registerSHMSegs(hIOMgr, hCodMan,
++                                       aEProc[0].ulGppPa);
++                              /* Register SM */
++                      }
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              hIOMgr->pSharedMem = (struct SHM *)ulShmBase;
++              hIOMgr->pInput = (u8 *)hIOMgr->pSharedMem +
++                               sizeof(struct SHM);
++              hIOMgr->pOutput = hIOMgr->pInput + (ulShmLength -
++                                sizeof(struct SHM))/2;
++              hIOMgr->uSMBufSize = hIOMgr->pOutput - hIOMgr->pInput;
++              DBG_Trace(DBG_LEVEL3,
++                       "hIOMgr: pInput %p pOutput %p ulShmLength %x\n",
++                       hIOMgr->pInput, hIOMgr->pOutput, ulShmLength);
++              DBG_Trace(DBG_LEVEL3,
++                       "pSharedMem %p uSMBufSize %x sizeof(SHM) %x\n",
++                       hIOMgr->pSharedMem, hIOMgr->uSMBufSize,
++                       sizeof(struct SHM));
++               /*  Set up Shared memory addresses for messaging. */
++              hIOMgr->pMsgInputCtrl = (struct MSG *)((u8 *)
++                                      hIOMgr->pSharedMem +
++                                      ulShmLength);
++              hIOMgr->pMsgInput = (u8 *)hIOMgr->pMsgInputCtrl +
++                                  sizeof(struct MSG);
++              hIOMgr->pMsgOutputCtrl = (struct MSG *)((u8 *)hIOMgr->
++                                       pMsgInputCtrl + ulMsgLength / 2);
++              hIOMgr->pMsgOutput = (u8 *)hIOMgr->pMsgOutputCtrl +
++                                   sizeof(struct MSG);
++              hMsgMgr->uMaxMsgs = ((u8 *)hIOMgr->pMsgOutputCtrl -
++                                  hIOMgr->pMsgInput) /
++                                  sizeof(struct MSG_DSPMSG);
++              DBG_Trace(DBG_LEVEL7, "IO MGR SHM details : pSharedMem 0x%x, "
++                       "pInput 0x%x, pOutput 0x%x, pMsgInputCtrl 0x%x, "
++                       "pMsgInput 0x%x, pMsgOutputCtrl 0x%x, pMsgOutput "
++                       "0x%x \n", (u8 *)hIOMgr->pSharedMem,
++                       (u8 *)hIOMgr->pInput, (u8 *)hIOMgr->pOutput,
++                       (u8 *)hIOMgr->pMsgInputCtrl,
++                       (u8 *)hIOMgr->pMsgInput,
++                       (u8 *)hIOMgr->pMsgOutputCtrl,
++                       (u8 *)hIOMgr->pMsgOutput);
++              DBG_Trace(DBG_LEVEL7, "** (proc) MAX MSGS IN SHARED MEMORY: "
++                       "0x%x\n", hMsgMgr->uMaxMsgs);
++              memset((void *) hIOMgr->pSharedMem, 0, sizeof(struct SHM));
++      }
++#ifndef DSP_TRACEBUF_DISABLED
++      if (DSP_SUCCEEDED(status)) {
++              /* Get the start address of trace buffer */
++              if (DSP_SUCCEEDED(status)) {
++                      status = COD_GetSymValue(hCodMan, SYS_PUTCBEG,
++                               &hIOMgr->ulTraceBufferBegin);
++                      if (DSP_FAILED(status))
++                              status = CHNL_E_NOMEMMAP;
++
++              }
++              hIOMgr->ulGPPReadPointer = hIOMgr->ulTraceBufferBegin =
++                      (ulGppVa + ulSeg1Size + ulPadSize) +
++                      (hIOMgr->ulTraceBufferBegin - ulDspVa);
++              /* Get the end address of trace buffer */
++              if (DSP_SUCCEEDED(status)) {
++                      status = COD_GetSymValue(hCodMan, SYS_PUTCEND,
++                               &hIOMgr->ulTraceBufferEnd);
++                      if (DSP_FAILED(status))
++                              status = CHNL_E_NOMEMMAP;
++
++              }
++              hIOMgr->ulTraceBufferEnd = (ulGppVa + ulSeg1Size + ulPadSize) +
++                                         (hIOMgr->ulTraceBufferEnd - ulDspVa);
++              /* Get the current address of DSP write pointer */
++              if (DSP_SUCCEEDED(status)) {
++                      status = COD_GetSymValue(hCodMan,
++                               BRIDGE_SYS_PUTC_current,
++                               &hIOMgr->ulTraceBufferCurrent);
++                      if (DSP_FAILED(status))
++                              status = CHNL_E_NOMEMMAP;
++
++              }
++              hIOMgr->ulTraceBufferCurrent = (ulGppVa + ulSeg1Size +
++                                              ulPadSize) + (hIOMgr->
++                                              ulTraceBufferCurrent - ulDspVa);
++              /* Calculate the size of trace buffer */
++              if (hIOMgr->pMsg)
++                      MEM_Free(hIOMgr->pMsg);
++              hIOMgr->pMsg = MEM_Alloc(((hIOMgr->ulTraceBufferEnd -
++                                      hIOMgr->ulTraceBufferBegin) *
++                                      hIOMgr->uWordSize) + 2, MEM_NONPAGED);
++              if (!hIOMgr->pMsg)
++                      status = DSP_EMEMORY;
++
++              DBG_Trace(DBG_LEVEL1, "** hIOMgr->pMsg: 0x%x\n", hIOMgr->pMsg);
++              hIOMgr->ulDspVa = ulDspVa;
++              hIOMgr->ulGppVa = (ulGppVa + ulSeg1Size + ulPadSize);
++    }
++#endif
++      IO_EnableInterrupt(hIOMgr->hWmdContext);
++      return status;
++}
++
++/*
++ *  ======== IO_BufSize ========
++ *      Size of shared memory I/O channel.
++ */
++u32 IO_BufSize(struct IO_MGR *hIOMgr)
++{
++      DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
++
++      return hIOMgr->uSMBufSize;
++}
++
++/*
++ *  ======== IO_CancelChnl ========
++ *      Cancel IO on a given PCPY channel.
++ */
++void IO_CancelChnl(struct IO_MGR *hIOMgr, u32 ulChnl)
++{
++      struct IO_MGR *pIOMgr = (struct IO_MGR *)hIOMgr;
++      struct SHM *sm;
++
++      DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
++      sm = hIOMgr->pSharedMem;
++
++      /* Inform DSP that we have no more buffers on this channel:  */
++      IO_AndValue(pIOMgr->hWmdContext, struct SHM, sm, hostFreeMask,
++                 (~(1 << ulChnl)));
++
++      CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++}
++
++/*
++ *  ======== IO_DispatchChnl ========
++ *      Proc-copy chanl dispatch.
++ */
++static void IO_DispatchChnl(IN struct IO_MGR *pIOMgr,
++                         IN OUT struct CHNL_OBJECT *pChnl, u32 iMode)
++{
++      DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++
++      DBG_Trace(DBG_LEVEL3, "Entering IO_DispatchChnl \n");
++
++      /* See if there is any data available for transfer: */
++      DBC_Assert(iMode == IO_SERVICE);
++
++      /* Any channel will do for this mode: */
++      InputChnl(pIOMgr, pChnl, iMode);
++      OutputChnl(pIOMgr, pChnl, iMode);
++}
++
++/*
++ *  ======== IO_DispatchMsg ========
++ *      Performs I/O dispatch on message queues.
++ */
++static void IO_DispatchMsg(IN struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
++{
++      DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++
++      DBG_Trace(DBG_LEVEL3, "Entering IO_DispatchMsg \n");
++
++      /*  We are performing both input and output processing. */
++      InputMsg(pIOMgr, hMsgMgr);
++      OutputMsg(pIOMgr, hMsgMgr);
++}
++
++/*
++ *  ======== IO_DispatchPM ========
++ *      Performs I/O dispatch on PM related messages from DSP
++ */
++static void IO_DispatchPM(struct work_struct *work)
++{
++       struct IO_MGR *pIOMgr =
++                               container_of(work, struct IO_MGR, io_workq);
++      DSP_STATUS status;
++      u32 pArg[2];
++
++       /*DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));*/
++
++      DBG_Trace(DBG_LEVEL7, "IO_DispatchPM: Entering IO_DispatchPM : \n");
++
++      /*  Perform Power message processing here  */
++      while (pIOMgr->iQuePowerHead != pIOMgr->iQuePowerTail) {
++              pArg[0] = *(u32 *)&(pIOMgr->dQuePowerMbxVal[pIOMgr->
++                        iQuePowerTail]);
++              DBG_Trace(DBG_LEVEL7, "IO_DispatchPM - pArg[0] - 0x%x: \n",
++                       pArg[0]);
++              /* Send the command to the WMD clk/pwr manager to handle */
++              if (pArg[0] ==  MBX_PM_HIBERNATE_EN) {
++                      DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Hibernate "
++                               "command\n");
++                      status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
++                               hWmdContext, WMDIOCTL_PWR_HIBERNATE, pArg);
++                      if (DSP_FAILED(status)) {
++                              DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : "
++                                       "Hibernation command failed\n");
++                      }
++              } else if (pArg[0] == MBX_PM_OPP_REQ) {
++                      pArg[1] = pIOMgr->pSharedMem->oppRequest.rqstOppPt;
++                      DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Value of OPP "
++                               "value =0x%x \n", pArg[1]);
++                      status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
++                               hWmdContext, WMDIOCTL_CONSTRAINT_REQUEST,
++                               pArg);
++                      if (DSP_FAILED(status)) {
++                              DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Failed "
++                                       "to set constraint = 0x%x \n",
++                                       pArg[1]);
++                      }
++
++              } else {
++                      DBG_Trace(DBG_LEVEL7, "IO_DispatchPM - clock control - "
++                               "value of msg = 0x%x: \n", pArg[0]);
++                      status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
++                               hWmdContext, WMDIOCTL_CLK_CTRL, pArg);
++                      if (DSP_FAILED(status)) {
++                              DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Failed "
++                                       "to control the DSP clk = 0x%x \n",
++                                       *pArg);
++                      }
++              }
++              /* increment the tail count here */
++              pIOMgr->iQuePowerTail++;
++              if (pIOMgr->iQuePowerTail >= MAX_PM_REQS)
++                      pIOMgr->iQuePowerTail = 0;
++
++      }
++
++}
++
++/*
++ *  ======== IO_DPC ========
++ *      Deferred procedure call for shared memory channel driver ISR.  Carries
++ *      out the dispatch of I/O as a non-preemptible event.It can only be
++ *      pre-empted      by an ISR.
++ */
++void IO_DPC(IN OUT void *pRefData)
++{
++      struct IO_MGR *pIOMgr = (struct IO_MGR *)pRefData;
++      struct CHNL_MGR *pChnlMgr;
++      struct MSG_MGR *pMsgMgr;
++      struct DEH_MGR *hDehMgr;
++
++      DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++      pChnlMgr = pIOMgr->hChnlMgr;
++      DEV_GetMsgMgr(pIOMgr->hDevObject, &pMsgMgr);
++      DEV_GetDehMgr(pIOMgr->hDevObject, &hDehMgr);
++      DBC_Require(MEM_IsValidHandle(pChnlMgr, CHNL_MGRSIGNATURE));
++      DBG_Trace(DBG_LEVEL7, "Entering IO_DPC(0x%x)\n", pRefData);
++      /* Check value of interrupt register to ensure it is a valid error */
++      if ((pIOMgr->wIntrVal > DEH_BASE) && (pIOMgr->wIntrVal < DEH_LIMIT)) {
++              /* notify DSP/BIOS exception */
++              if (hDehMgr)
++                      WMD_DEH_Notify(hDehMgr, DSP_SYSERROR, pIOMgr->wIntrVal);
++
++      }
++      IO_DispatchChnl(pIOMgr, NULL, IO_SERVICE);
++#ifdef CHNL_MESSAGES
++      if (pMsgMgr) {
++              DBC_Require(MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
++              IO_DispatchMsg(pIOMgr, pMsgMgr);
++      }
++#endif
++#ifndef DSP_TRACEBUF_DISABLED
++      if (pIOMgr->wIntrVal & MBX_DBG_CLASS) {
++              /* notify DSP Trace message */
++              if (pIOMgr->wIntrVal & MBX_DBG_SYSPRINTF)
++                      PrintDSPDebugTrace(pIOMgr);
++      }
++#endif
++
++#ifndef DSP_TRACEBUF_DISABLED
++      PrintDSPDebugTrace(pIOMgr);
++#endif
++}
++
++
++/*
++ *  ======== IO_ISR ========
++ *      Main interrupt handler for the shared memory IO manager.
++ *      Calls the WMD's CHNL_ISR to determine if this interrupt is ours, then
++ *      schedules a DPC to dispatch I/O.
++ */
++irqreturn_t IO_ISR(int irq, IN void *pRefData)
++{
++      struct IO_MGR *hIOMgr = (struct IO_MGR *)pRefData;
++      bool fSchedDPC;
++       DBC_Require(irq == INT_MAIL_MPU_IRQ);
++      DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
++      DBG_Trace(DBG_LEVEL3, "Entering IO_ISR(0x%x)\n", pRefData);
++
++      /* Call WMD's CHNLSM_ISR() to see if interrupt is ours, and process. */
++      if (IO_CALLISR(hIOMgr->hWmdContext, &fSchedDPC, &hIOMgr->wIntrVal)) {
++              {
++                      DBG_Trace(DBG_LEVEL3, "IO_ISR %x\n", hIOMgr->wIntrVal);
++                      if (hIOMgr->wIntrVal & MBX_PM_CLASS) {
++                              hIOMgr->dQuePowerMbxVal[hIOMgr->iQuePowerHead] =
++                                      hIOMgr->wIntrVal;
++                              hIOMgr->iQuePowerHead++;
++                              if (hIOMgr->iQuePowerHead >= MAX_PM_REQS)
++                                      hIOMgr->iQuePowerHead = 0;
++
++                               queue_work(bridge_workqueue, &hIOMgr->io_workq);
++                      }
++                      if (hIOMgr->wIntrVal == MBX_DEH_RESET) {
++                              DBG_Trace(DBG_LEVEL6, "*** DSP RESET ***\n");
++                              hIOMgr->wIntrVal = 0;
++                      } else if (fSchedDPC) {
++                              /* PROC-COPY defer i/o  */
++                              DPC_Schedule(hIOMgr->hDPC);
++                      }
++              }
++       } else
++              /* Ensure that, if WMD didn't claim it, the IRQ is shared. */
++              DBC_Ensure(hIOMgr->fSharedIRQ);
++       return IRQ_HANDLED;
++}
++
++/*
++ *  ======== IO_RequestChnl ========
++ *  Purpose:
++ *      Request chanenel I/O from the DSP. Sets flags in shared memory, then
++ *      interrupts the DSP.
++ */
++void IO_RequestChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++                 u32 iMode, OUT u16 *pwMbVal)
++{
++      struct CHNL_MGR *pChnlMgr;
++      struct SHM *sm;
++      DBC_Require(pChnl != NULL);
++      DBC_Require(pwMbVal != NULL);
++      pChnlMgr = pIOMgr->hChnlMgr;
++      sm = pIOMgr->pSharedMem;
++      if (iMode == IO_INPUT) {
++              /*  Assertion fires if CHNL_AddIOReq() called on a stream
++               * which was cancelled, or attached to a dead board: */
++              DBC_Assert((pChnl->dwState == CHNL_STATEREADY) ||
++                        (pChnl->dwState == CHNL_STATEEOS));
++              /* Indicate to the DSP we have a buffer available for input: */
++              IO_OrValue(pIOMgr->hWmdContext, struct SHM, sm, hostFreeMask,
++                        (1 << pChnl->uId));
++              *pwMbVal = MBX_PCPY_CLASS;
++      } else if (iMode == IO_OUTPUT) {
++              /*  This assertion fails if CHNL_AddIOReq() was called on a
++               * stream which was cancelled, or attached to a dead board: */
++              DBC_Assert((pChnl->dwState & ~CHNL_STATEEOS) ==
++                        CHNL_STATEREADY);
++              /* Record the fact that we have a buffer available for
++               * output: */
++              pChnlMgr->dwOutputMask |= (1 << pChnl->uId);
++      } else {
++              DBC_Assert(iMode);      /* Shouldn't get here. */
++      }
++}
++
++/*
++ *  ======== IO_Schedule ========
++ *      Schedule DPC for IO.
++ */
++void IO_Schedule(struct IO_MGR *pIOMgr)
++{
++      DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++
++      DPC_Schedule(pIOMgr->hDPC);
++}
++
++/*
++ *  ======== FindReadyOutput ========
++ *      Search for a host output channel which is ready to send.  If this is
++ *      called as a result of servicing the DPC, then implement a round
++ *      robin search; otherwise, this was called by a client thread (via
++ *      IO_Dispatch()), so just start searching from the current channel id.
++ */
++static u32 FindReadyOutput(struct CHNL_MGR *pChnlMgr,
++                           struct CHNL_OBJECT *pChnl, u32 dwMask)
++{
++      u32 uRetval = OUTPUTNOTREADY;
++      u32 id, startId;
++      u32 shift;
++
++      id = (pChnl != NULL ? pChnl->uId : (pChnlMgr->dwLastOutput + 1));
++      id = ((id == CHNL_MAXCHANNELS) ? 0 : id);
++      DBC_Assert(id < CHNL_MAXCHANNELS);
++      if (dwMask) {
++              shift = (1 << id);
++              startId = id;
++              do {
++                      if (dwMask & shift) {
++                              uRetval = id;
++                              if (pChnl == NULL)
++                                      pChnlMgr->dwLastOutput = id;
++
++                              break;
++                      }
++                      id = id + 1;
++                      id = ((id == CHNL_MAXCHANNELS) ? 0 : id);
++                      shift = (1 << id);
++              } while (id != startId);
++      }
++      DBC_Ensure((uRetval == OUTPUTNOTREADY) || (uRetval < CHNL_MAXCHANNELS));
++      return uRetval;
++}
++
++/*
++ *  ======== InputChnl ========
++ *      Dispatch a buffer on an input channel.
++ */
++static void InputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++                    u32 iMode)
++{
++      struct CHNL_MGR *pChnlMgr;
++      struct SHM *sm;
++      u32 chnlId;
++      u32 uBytes;
++      struct CHNL_IRP *pChirp = NULL;
++      u32 dwArg;
++      bool fClearChnl = false;
++      bool fNotifyClient = false;
++
++      sm = pIOMgr->pSharedMem;
++      pChnlMgr = pIOMgr->hChnlMgr;
++
++      DBG_Trace(DBG_LEVEL3, "> InputChnl\n");
++
++      /* Attempt to perform input.... */
++      if (!IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputFull))
++              goto func_end;
++
++      uBytes = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputSize) *
++                          pChnlMgr->uWordSize;
++      chnlId = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputId);
++      dwArg = IO_GetLong(pIOMgr->hWmdContext, struct SHM, sm, arg);
++      if (!(chnlId >= 0) || !(chnlId < CHNL_MAXCHANNELS)) {
++              /* Shouldn't be here: would indicate corrupted SHM. */
++              DBC_Assert(chnlId);
++              goto func_end;
++      }
++      pChnl = pChnlMgr->apChannel[chnlId];
++      if ((pChnl != NULL) && CHNL_IsInput(pChnl->uMode)) {
++              if ((pChnl->dwState & ~CHNL_STATEEOS) == CHNL_STATEREADY) {
++                       if (!pChnl->pIORequests)
++                               goto func_end;
++                      /* Get the I/O request, and attempt a transfer:  */
++                      pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->
++                               pIORequests);
++                      if (pChirp) {
++                              pChnl->cIOReqs--;
++                              DBC_Assert(pChnl->cIOReqs >= 0);
++                              /* Ensure we don't overflow the client's
++                               * buffer: */
++                              uBytes = min(uBytes, pChirp->cBytes);
++                              /* Transfer buffer from DSP side: */
++                              uBytes = ReadData(pIOMgr->hWmdContext,
++                                              pChirp->pHostSysBuf,
++                                              pIOMgr->pInput, uBytes);
++                              pChnl->cBytesMoved += uBytes;
++                              pChirp->cBytes = uBytes;
++                              pChirp->dwArg = dwArg;
++                              pChirp->status = CHNL_IOCSTATCOMPLETE;
++                              DBG_Trace(DBG_LEVEL7, "Input Chnl:status= 0x%x "
++                                       "\n", *((RMS_WORD *)(pChirp->
++                                       pHostSysBuf)));
++                              if (uBytes == 0) {
++                                      /* This assertion fails if the DSP
++                                       * sends EOS more than once on this
++                                       * channel: */
++                                      DBC_Assert(!(pChnl->dwState &
++                                                CHNL_STATEEOS));
++                                       /* Zero bytes indicates EOS. Update
++                                        * IOC status for this chirp, and also
++                                        * the channel state: */
++                                      pChirp->status |= CHNL_IOCSTATEOS;
++                                      pChnl->dwState |= CHNL_STATEEOS;
++                                      /* Notify that end of stream has
++                                       * occurred */
++                                      NTFY_Notify(pChnl->hNtfy,
++                                                 DSP_STREAMDONE);
++                                      DBG_Trace(DBG_LEVEL7, "Input Chnl NTFY "
++                                               "chnl = 0x%x\n", pChnl);
++                              }
++                              /* Tell DSP if no more I/O buffers available: */
++                               if (!pChnl->pIORequests)
++                                       goto func_end;
++                              if (LST_IsEmpty(pChnl->pIORequests)) {
++                                      IO_AndValue(pIOMgr->hWmdContext,
++                                                 struct SHM, sm, hostFreeMask,
++                                                 ~(1 << pChnl->uId));
++                              }
++                              fClearChnl = true;
++                              fNotifyClient = true;
++                      } else {
++                              /* Input full for this channel, but we have no
++                               * buffers available.  The channel must be
++                               * "idling". Clear out the physical input
++                               * channel.  */
++                              fClearChnl = true;
++                      }
++              } else {
++                      /* Input channel cancelled:  clear input channel.  */
++                      fClearChnl = true;
++              }
++      } else {
++              /* DPC fired after host closed channel: clear input channel. */
++              fClearChnl = true;
++      }
++      if (fClearChnl) {
++              /* Indicate to the DSP we have read the input: */
++              IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, inputFull, 0);
++              CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++      }
++      if (fNotifyClient) {
++              /* Notify client with IO completion record:  */
++              NotifyChnlComplete(pChnl, pChirp);
++      }
++func_end:
++      DBG_Trace(DBG_LEVEL3, "< InputChnl\n");
++}
++
++/*
++ *  ======== InputMsg ========
++ *      Copies messages from shared memory to the message queues.
++ */
++static void InputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
++{
++      u32 uMsgs;
++      u32 i;
++      u8 *pMsgInput;
++      struct MSG_QUEUE *hMsgQueue;
++      struct MSG_FRAME *pMsg;
++      struct MSG_DSPMSG msg;
++      struct MSG *pCtrl;
++      u32 fInputEmpty;
++      u32 addr;
++
++      pCtrl = pIOMgr->pMsgInputCtrl;
++      /* Get the number of input messages to be read. */
++      fInputEmpty = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++                               bufEmpty);
++      uMsgs = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, size);
++      if (fInputEmpty || uMsgs >= hMsgMgr->uMaxMsgs)
++              return;
++
++      pMsgInput = pIOMgr->pMsgInput;
++      for (i = 0; i < uMsgs; i++) {
++              /* Read the next message */
++              addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwCmd);
++              msg.msg.dwCmd = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++              addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwArg1);
++              msg.msg.dwArg1 = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++              addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwArg2);
++              msg.msg.dwArg2 = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++              addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->dwId);
++              msg.dwId = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++              pMsgInput += sizeof(struct MSG_DSPMSG);
++               if (!hMsgMgr->queueList)
++                       goto func_end;
++
++              /* Determine which queue to put the message in */
++              hMsgQueue = (struct MSG_QUEUE *)LST_First(hMsgMgr->queueList);
++              DBG_Trace(DBG_LEVEL7, "InputMsg RECVD: dwCmd=0x%x dwArg1=0x%x "
++                       "dwArg2=0x%x dwId=0x%x \n", msg.msg.dwCmd,
++                       msg.msg.dwArg1, msg.msg.dwArg2, msg.dwId);
++               /*  Interrupt may occur before shared memory and message
++               *  input locations have been set up. If all nodes were
++               *  cleaned up, hMsgMgr->uMaxMsgs should be 0.  */
++               if (hMsgQueue && uMsgs > hMsgMgr->uMaxMsgs)
++                       goto func_end;
++
++              while (hMsgQueue != NULL) {
++                      if (msg.dwId == hMsgQueue->dwId) {
++                              /* Found it */
++                              if (msg.msg.dwCmd == RMS_EXITACK) {
++                                      /* The exit message does not get
++                                       * queued */
++                                      /* Call the node exit notification */
++                                      /* Node handle */ /* status */
++                                      (*hMsgMgr->onExit)((HANDLE)hMsgQueue->
++                                              hArg, msg.msg.dwArg1);
++                              } else {
++                                      /* Not an exit acknowledgement, queue
++                                       * the message */
++                                       if (!hMsgQueue->msgFreeList)
++                                               goto func_end;
++                                      pMsg = (struct MSG_FRAME *)LST_GetHead
++                                              (hMsgQueue->msgFreeList);
++                                       if (hMsgQueue->msgUsedList && pMsg) {
++                                              pMsg->msgData = msg;
++                                              LST_PutTail(hMsgQueue->
++                                                    msgUsedList,
++                                                    (struct LST_ELEM *)pMsg);
++                                              NTFY_Notify(hMsgQueue->hNtfy,
++                                                      DSP_NODEMESSAGEREADY);
++                                              SYNC_SetEvent(hMsgQueue->
++                                                      hSyncEvent);
++                                      } else {
++                                              /* No free frame to copy the
++                                               * message into */
++                                              DBG_Trace(DBG_LEVEL7, "NO FREE "
++                                                      "MSG FRAMES, DISCARDING"
++                                                      " MESSAGE\n");
++                                      }
++                              }
++                              break;
++                      }
++
++                       if (!hMsgMgr->queueList || !hMsgQueue)
++                               goto func_end;
++                      hMsgQueue = (struct MSG_QUEUE *)LST_Next(hMsgMgr->
++                                  queueList, (struct LST_ELEM *)hMsgQueue);
++              }
++      }
++      /* Set the post SWI flag */
++      if (uMsgs > 0) {
++              /* Tell the DSP we've read the messages */
++              IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, bufEmpty,
++                         true);
++              IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, postSWI,
++                         true);
++              CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++      }
++func_end:
++       return;
++
++}
++
++/*
++ *  ======== NotifyChnlComplete ========
++ *  Purpose:
++ *      Signal the channel event, notifying the client that I/O has completed.
++ */
++static void NotifyChnlComplete(struct CHNL_OBJECT *pChnl,
++                            struct CHNL_IRP *pChirp)
++{
++      bool fSignalEvent;
++
++      DBC_Require(MEM_IsValidHandle(pChnl, CHNL_SIGNATURE));
++      DBC_Require(pChnl->hSyncEvent != NULL);
++       /*  Note: we signal the channel event only if the queue of IO
++        *  completions is empty.  If it is not empty, the event is sure to be
++        *  signalled by the only IO completion list consumer:
++        *  WMD_CHNL_GetIOC().  */
++      fSignalEvent = LST_IsEmpty(pChnl->pIOCompletions);
++      /* Enqueue the IO completion info for the client: */
++      LST_PutTail(pChnl->pIOCompletions, (struct LST_ELEM *) pChirp);
++      pChnl->cIOCs++;
++      DBC_Assert(pChnl->cIOCs <= pChnl->cChirps);
++      /* Signal the channel event (if not already set) that IO is complete: */
++      if (fSignalEvent)
++              SYNC_SetEvent(pChnl->hSyncEvent);
++
++      /* Notify that IO is complete */
++      NTFY_Notify(pChnl->hNtfy, DSP_STREAMIOCOMPLETION);
++}
++
++/*
++ *  ======== OutputChnl ========
++ *  Purpose:
++ *      Dispatch a buffer on an output channel.
++ */
++static void OutputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++                      u32 iMode)
++{
++      struct CHNL_MGR *pChnlMgr;
++      struct SHM *sm;
++      u32 chnlId;
++      struct CHNL_IRP *pChirp;
++      u32 dwDspFMask;
++
++      pChnlMgr = pIOMgr->hChnlMgr;
++      sm = pIOMgr->pSharedMem;
++      DBG_Trace(DBG_LEVEL3, "> OutputChnl\n");
++      /* Attempt to perform output: */
++      if (IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, outputFull))
++              goto func_end;
++
++      if (pChnl && !((pChnl->dwState & ~CHNL_STATEEOS) == CHNL_STATEREADY))
++              goto func_end;
++
++      /* Look to see if both a PC and DSP output channel are ready: */
++      dwDspFMask = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm,
++                               dspFreeMask);
++      chnlId = FindReadyOutput(pChnlMgr, pChnl, (pChnlMgr->dwOutputMask &
++                               dwDspFMask));
++      if (chnlId == OUTPUTNOTREADY)
++              goto func_end;
++
++      pChnl = pChnlMgr->apChannel[chnlId];
++       if (!pChnl || !pChnl->pIORequests) {
++              /* Shouldn't get here: */
++              goto func_end;
++      }
++      /* Get the I/O request, and attempt a transfer:  */
++      pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIORequests);
++      if (!pChirp)
++              goto func_end;
++
++      pChnl->cIOReqs--;
++       if (pChnl->cIOReqs < 0 || !pChnl->pIORequests)
++               goto func_end;
++
++      /* Record fact that no more I/O buffers available:  */
++      if (LST_IsEmpty(pChnl->pIORequests))
++              pChnlMgr->dwOutputMask &= ~(1 << chnlId);
++
++      /* Transfer buffer to DSP side: */
++      pChirp->cBytes = WriteData(pIOMgr->hWmdContext, pIOMgr->pOutput,
++                      pChirp->pHostSysBuf, min(pIOMgr->uSMBufSize, pChirp->
++                      cBytes));
++      pChnl->cBytesMoved += pChirp->cBytes;
++      /* Write all 32 bits of arg */
++      IO_SetLong(pIOMgr->hWmdContext, struct SHM, sm, arg, pChirp->dwArg);
++#if _CHNL_WORDSIZE == 2
++      IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputId,
++                 (u16)chnlId);
++      IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputSize,
++                 (u16)(pChirp->cBytes + (pChnlMgr->uWordSize-1)) /
++                 (u16)pChnlMgr->uWordSize);
++#else
++      IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputId, chnlId);
++      IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputSize,
++                 (pChirp->cBytes + (pChnlMgr->uWordSize - 1)) / pChnlMgr->
++                 uWordSize);
++#endif
++      IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputFull, 1);
++      /* Indicate to the DSP we have written the output: */
++      CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++      /* Notify client with IO completion record (keep EOS) */
++      pChirp->status &= CHNL_IOCSTATEOS;
++      NotifyChnlComplete(pChnl, pChirp);
++      /* Notify if stream is done. */
++      if (pChirp->status & CHNL_IOCSTATEOS)
++              NTFY_Notify(pChnl->hNtfy, DSP_STREAMDONE);
++
++func_end:
++      DBG_Trace(DBG_LEVEL3, "< OutputChnl\n");
++}
++/*
++ *  ======== OutputMsg ========
++ *      Copies messages from the message queues to the shared memory.
++ */
++static void OutputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
++{
++      u32 uMsgs = 0;
++      u32 i;
++      u8 *pMsgOutput;
++      struct MSG_FRAME *pMsg;
++      struct MSG *pCtrl;
++      u32 fOutputEmpty;
++      u32 val;
++      u32 addr;
++
++      pCtrl = pIOMgr->pMsgOutputCtrl;
++
++      /* Check if output has been cleared */
++      fOutputEmpty = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++                                bufEmpty);
++      if (fOutputEmpty) {
++              uMsgs = (hMsgMgr->uMsgsPending > hMsgMgr->uMaxMsgs) ?
++                       hMsgMgr->uMaxMsgs : hMsgMgr->uMsgsPending;
++              pMsgOutput = pIOMgr->pMsgOutput;
++              /* Copy uMsgs messages into shared memory */
++              for (i = 0; i < uMsgs; i++) {
++                       if (!hMsgMgr->msgUsedList) {
++                               DBG_Trace(DBG_LEVEL3, "msgUsedList is NULL\n");
++                               pMsg = NULL;
++                               goto func_end;
++                       } else
++                               pMsg = (struct MSG_FRAME *)LST_GetHead(
++                                       hMsgMgr->msgUsedList);
++                      if (pMsg != NULL) {
++                              val = (pMsg->msgData).dwId;
++                              addr = (u32)&(((struct MSG_DSPMSG *)
++                                      pMsgOutput)->dwId);
++                              WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++                                                   val);
++                              val = (pMsg->msgData).msg.dwCmd;
++                              addr = (u32)&((((struct MSG_DSPMSG *)
++                                      pMsgOutput)->msg).dwCmd);
++                              WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++                                                   val);
++                              val = (pMsg->msgData).msg.dwArg1;
++                              addr =
++                                      (u32)&((((struct MSG_DSPMSG *)
++                                      pMsgOutput)->msg).dwArg1);
++                              WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++                                                  val);
++                              val = (pMsg->msgData).msg.dwArg2;
++                              addr =
++                                      (u32)&((((struct MSG_DSPMSG *)
++                                      pMsgOutput)->msg).dwArg2);
++                              WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++                                                  val);
++                              pMsgOutput += sizeof(struct MSG_DSPMSG);
++                               if (!hMsgMgr->msgFreeList)
++                                       goto func_end;
++                              LST_PutTail(hMsgMgr->msgFreeList,
++                                         (struct LST_ELEM *) pMsg);
++                              SYNC_SetEvent(hMsgMgr->hSyncEvent);
++                      } else {
++                              DBG_Trace(DBG_LEVEL3, "pMsg is NULL\n");
++                      }
++              }
++
++              if (uMsgs > 0) {
++                      hMsgMgr->uMsgsPending -= uMsgs;
++#if _CHNL_WORDSIZE == 2
++                      IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++                                 size, (u16)uMsgs);
++#else
++                      IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++                                 size, uMsgs);
++#endif
++                      IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++                                 bufEmpty, false);
++                      /* Set the post SWI flag */
++                      IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++                                 postSWI, true);
++                      /* Tell the DSP we have written the output. */
++                      CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++              }
++      }
++func_end:
++       return;
++
++}
++
++/*
++ *  ======== registerSHMSegs ========
++ *  purpose:
++ *      Registers GPP SM segment with CMM.
++ */
++static DSP_STATUS registerSHMSegs(struct IO_MGR *hIOMgr,
++                               struct COD_MANAGER *hCodMan,
++                               u32 dwGPPBasePA)
++{
++      DSP_STATUS status = DSP_SOK;
++      u32 ulShm0_Base = 0;
++      u32 ulShm0_End = 0;
++      u32 ulShm0_RsrvdStart = 0;
++      u32 ulRsrvdSize = 0;
++      u32 ulGppPhys;
++      u32 ulDspVirt;
++      u32 ulShmSegId0 = 0;
++      u32 dwOffset, dwGPPBaseVA, ulDSPSize;
++
++      /* Read address and size info for first SM region.*/
++      /* Get start of 1st SM Heap region */
++      status = COD_GetSymValue(hCodMan, SHM0_SHARED_BASE_SYM, &ulShm0_Base);
++      DBC_Assert(ulShm0_Base != 0);
++      /* Get end of 1st SM Heap region */
++      if (DSP_SUCCEEDED(status)) {
++              /* Get start and length of message part of shared memory */
++              status = COD_GetSymValue(hCodMan, SHM0_SHARED_END_SYM,
++                                       &ulShm0_End);
++              DBC_Assert(ulShm0_End != 0);
++      }
++      /* start of Gpp reserved region */
++      if (DSP_SUCCEEDED(status)) {
++              /* Get start and length of message part of shared memory */
++              status = COD_GetSymValue(hCodMan, SHM0_SHARED_RESERVED_BASE_SYM,
++                                      &ulShm0_RsrvdStart);
++              DBG_Trace(DBG_LEVEL1, "***ulShm0_RsrvdStart  0x%x \n",
++                       ulShm0_RsrvdStart);
++              DBC_Assert(ulShm0_RsrvdStart != 0);
++      }
++      /* Register with CMM */
++      if (DSP_SUCCEEDED(status)) {
++              status = DEV_GetCmmMgr(hIOMgr->hDevObject, &hIOMgr->hCmmMgr);
++              if (DSP_SUCCEEDED(status)) {
++                      status = CMM_UnRegisterGPPSMSeg(hIOMgr->hCmmMgr,
++                               CMM_ALLSEGMENTS);
++                      if (DSP_FAILED(status)) {
++                              DBG_Trace(DBG_LEVEL7, "ERROR - Unable to "
++                                       "Un-Register SM segments \n");
++                      }
++              } else {
++                      DBG_Trace(DBG_LEVEL7, "ERROR - Unable to get CMM "
++                               "Handle \n");
++              }
++      }
++      /* Register new SM region(s) */
++      if (DSP_SUCCEEDED(status) && (ulShm0_End - ulShm0_Base) > 0) {
++              /* calc size (bytes) of SM the GPP can alloc from */
++              ulRsrvdSize = (ulShm0_End - ulShm0_RsrvdStart + 1) * hIOMgr->
++                            uWordSize;
++              DBC_Assert(ulRsrvdSize > 0);
++              /* calc size of SM DSP can alloc from */
++              ulDSPSize = (ulShm0_RsrvdStart - ulShm0_Base) * hIOMgr->
++                      uWordSize;
++              DBC_Assert(ulDSPSize > 0);
++              /*  First TLB entry reserved for Bridge SM use.*/
++              ulGppPhys = hIOMgr->extProcInfo.tyTlb[0].ulGppPhys;
++              /* get size in bytes */
++              ulDspVirt = hIOMgr->extProcInfo.tyTlb[0].ulDspVirt * hIOMgr->
++                      uWordSize;
++               /* Calc byte offset used to convert GPP phys <-> DSP byte
++                * address.*/
++              if (dwGPPBasePA > ulDspVirt)
++                      dwOffset = dwGPPBasePA - ulDspVirt;
++              else
++                      dwOffset = ulDspVirt - dwGPPBasePA;
++
++              DBC_Assert(ulShm0_RsrvdStart * hIOMgr->uWordSize >= ulDspVirt);
++              /* calc Gpp phys base of SM region */
++              /* Linux - this is actually uncached kernel virtual address*/
++              dwGPPBaseVA = ulGppPhys + ulShm0_RsrvdStart * hIOMgr->uWordSize
++                              - ulDspVirt;
++              /* calc Gpp phys base of SM region */
++              /* Linux - this is the physical address*/
++              dwGPPBasePA = dwGPPBasePA + ulShm0_RsrvdStart * hIOMgr->
++                            uWordSize - ulDspVirt;
++               /* Register SM Segment 0.*/
++              status = CMM_RegisterGPPSMSeg(hIOMgr->hCmmMgr, dwGPPBasePA,
++                       ulRsrvdSize, dwOffset, (dwGPPBasePA > ulDspVirt) ?
++                       CMM_ADDTODSPPA : CMM_SUBFROMDSPPA,
++                       (u32)(ulShm0_Base * hIOMgr->uWordSize),
++                       ulDSPSize, &ulShmSegId0, dwGPPBaseVA);
++              if (DSP_FAILED(status)) {
++                      DBG_Trace(DBG_LEVEL7, "ERROR - Failed to register SM "
++                               "Seg 0 \n");
++              }
++              /* first SM region is segId = 1 */
++              DBC_Assert(ulShmSegId0 == 1);
++      }
++      return status;
++}
++
++/*
++ *  ======== ReadData ========
++ *      Copies buffers from the shared memory to the host buffer.
++ */
++static u32 ReadData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++                   void *pSrc, u32 uSize)
++{
++      memcpy(pDest, pSrc, uSize);
++      return uSize;
++}
++
++/*
++ *  ======== WriteData ========
++ *      Copies buffers from the host side buffer to the shared memory.
++ */
++static u32 WriteData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++                     void *pSrc, u32 uSize)
++{
++      memcpy(pDest, pSrc, uSize);
++      return uSize;
++}
++
++/* ZCPY IO routines. */
++void IO_IntrDSP2(IN struct IO_MGR *pIOMgr, IN u16 wMbVal)
++{
++      CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, wMbVal);
++}
++
++/*
++ *  ======== IO_SHMcontrol ========
++ *      Sets the requested SHM setting.
++ */
++DSP_STATUS IO_SHMsetting(IN struct IO_MGR *hIOMgr, IN enum SHM_DESCTYPE desc,
++                       IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++      u32 i;
++      struct dspbridge_platform_data *pdata =
++                              omap_dspbridge_dev->dev.platform_data;
++
++      switch (desc) {
++      case SHM_CURROPP:
++              /* Update the shared memory with requested OPP information */
++              if (pArgs != NULL)
++                      hIOMgr->pSharedMem->oppTableStruct.currOppPt =
++                              *(u32 *)pArgs;
++              else
++                      return DSP_EFAIL;
++              break;
++      case SHM_OPPINFO:
++              /* Update the shared memory with the voltage, frequency,
++                                 min and max frequency values for an OPP */
++              for (i = 0; i <= dsp_max_opps; i++) {
++                      hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].voltage =
++                              vdd1_dsp_freq[i][0];
++                      DBG_Trace(DBG_LEVEL5, "OPP shared memory -voltage: "
++                               "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++                               oppPoint[i].voltage);
++                      hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].
++                              frequency = vdd1_dsp_freq[i][1];
++                      DBG_Trace(DBG_LEVEL5, "OPP shared memory -frequency: "
++                               "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++                               oppPoint[i].frequency);
++                      hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].minFreq =
++                              vdd1_dsp_freq[i][2];
++                      DBG_Trace(DBG_LEVEL5, "OPP shared memory -min value: "
++                               "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++                                oppPoint[i].minFreq);
++                      hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].maxFreq =
++                              vdd1_dsp_freq[i][3];
++                      DBG_Trace(DBG_LEVEL5, "OPP shared memory -max value: "
++                               "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++                               oppPoint[i].maxFreq);
++              }
++              hIOMgr->pSharedMem->oppTableStruct.numOppPts = dsp_max_opps;
++              DBG_Trace(DBG_LEVEL5, "OPP shared memory - max OPP number: "
++                       "%d\n", hIOMgr->pSharedMem->oppTableStruct.numOppPts);
++              /* Update the current OPP number */
++              if (pdata->dsp_get_opp)
++                      i = (*pdata->dsp_get_opp)();
++              hIOMgr->pSharedMem->oppTableStruct.currOppPt = i;
++              DBG_Trace(DBG_LEVEL7, "OPP value programmed to shared memory: "
++                       "%d\n", i);
++              break;
++      case SHM_GETOPP:
++              /* Get the OPP that DSP has requested */
++              *(u32 *)pArgs = hIOMgr->pSharedMem->oppRequest.rqstOppPt;
++              break;
++      default:
++              break;
++
++                              queue_work(bridge_workqueue,
++                                                       &(hIOMgr->io_workq));
++      }
++#endif
++      return DSP_SOK;
++}
++
++/*
++ *  ======== WMD_IO_GetProcLoad ========
++ *      Gets the Processor's Load information
++ */
++DSP_STATUS WMD_IO_GetProcLoad(IN struct IO_MGR *hIOMgr,
++                           OUT struct DSP_PROCLOADSTAT *pProcStat)
++{
++      pProcStat->uCurrLoad = hIOMgr->pSharedMem->loadMonInfo.currDspLoad;
++      pProcStat->uPredictedLoad = hIOMgr->pSharedMem->loadMonInfo.predDspLoad;
++      pProcStat->uCurrDspFreq = hIOMgr->pSharedMem->loadMonInfo.currDspFreq;
++      pProcStat->uPredictedFreq = hIOMgr->pSharedMem->loadMonInfo.predDspFreq;
++
++      DBG_Trace(DBG_LEVEL4, "Curr Load =%d, Pred Load = %d, Curr Freq = %d, "
++                           "Pred Freq = %d\n", pProcStat->uCurrLoad,
++                           pProcStat->uPredictedLoad, pProcStat->uCurrDspFreq,
++                           pProcStat->uPredictedFreq);
++      return DSP_SOK;
++}
++
++#ifndef DSP_TRACEBUF_DISABLED
++void PrintDSPDebugTrace(struct IO_MGR *hIOMgr)
++{
++      u32 ulNewMessageLength = 0, ulGPPCurPointer;
++
++       GT_0trace(dsp_trace_mask, GT_ENTER, "Entering PrintDSPDebugTrace\n");
++
++      while (true) {
++              /* Get the DSP current pointer */
++              ulGPPCurPointer = *(u32 *) (hIOMgr->ulTraceBufferCurrent);
++              ulGPPCurPointer = hIOMgr->ulGppVa + (ulGPPCurPointer -
++                                hIOMgr->ulDspVa);
++
++              /* No new debug messages available yet */
++              if (ulGPPCurPointer == hIOMgr->ulGPPReadPointer)
++                      break;
++
++              /* Continuous data */
++              else if (ulGPPCurPointer > hIOMgr->ulGPPReadPointer) {
++                      ulNewMessageLength = ulGPPCurPointer - hIOMgr->
++                                           ulGPPReadPointer;
++
++                      memcpy(hIOMgr->pMsg, (char *)hIOMgr->ulGPPReadPointer,
++                             ulNewMessageLength);
++                      hIOMgr->pMsg[ulNewMessageLength] = '\0';
++                      /* Advance the GPP trace pointer to DSP current
++                       * pointer */
++                      hIOMgr->ulGPPReadPointer += ulNewMessageLength;
++                      /* Print the trace messages */
++                       GT_0trace(dsp_trace_mask, GT_1CLASS, hIOMgr->pMsg);
++              }
++              /* Handle trace buffer wraparound */
++              else if (ulGPPCurPointer < hIOMgr->ulGPPReadPointer) {
++                      memcpy(hIOMgr->pMsg, (char *)hIOMgr->ulGPPReadPointer,
++                              hIOMgr->ulTraceBufferEnd -
++                              hIOMgr->ulGPPReadPointer);
++                      ulNewMessageLength = ulGPPCurPointer -
++                              hIOMgr->ulTraceBufferBegin;
++                      memcpy(&hIOMgr->pMsg[hIOMgr->ulTraceBufferEnd -
++                              hIOMgr->ulGPPReadPointer],
++                              (char *)hIOMgr->ulTraceBufferBegin,
++                              ulNewMessageLength);
++                      hIOMgr->pMsg[hIOMgr->ulTraceBufferEnd -
++                              hIOMgr->ulGPPReadPointer +
++                              ulNewMessageLength] = '\0';
++                      /* Advance the GPP trace pointer to DSP current
++                       * pointer */
++                      hIOMgr->ulGPPReadPointer = hIOMgr->ulTraceBufferBegin +
++                                                 ulNewMessageLength;
++                      /* Print the trace messages */
++                       GT_0trace(dsp_trace_mask, GT_1CLASS, hIOMgr->pMsg);
++              }
++      }
++}
++#endif
++
++/*
++ *  ======== PackTraceBuffer ========
++ *      Removes extra nulls from the trace buffer returned from the DSP.
++ *      Works even on buffers that already are packed (null removed); but has
++ *      one bug in that case -- loses the last character (replaces with '\0').
++ *      Continues through conversion for full set of nBytes input characters.
++ *  Parameters:
++ *    lpBuf:            Pointer to input/output buffer
++ *    nBytes:           Number of characters in the buffer
++ *    ulNumWords:       Number of DSP words in the buffer.  Indicates potential
++ *                      number of extra carriage returns to generate.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Unable to allocate memory.
++ *  Requires:
++ *      lpBuf must be a fully allocated writable block of at least nBytes.
++ *      There are no more than ulNumWords extra characters needed (the number of
++ *      linefeeds minus the number of NULLS in the input buffer).
++ */
++#if (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE
++static DSP_STATUS PackTraceBuffer(char *lpBuf, u32 nBytes, u32 ulNumWords)
++{
++       DSP_STATUS status = DSP_SOK;
++       char *lpTmpBuf;
++       char *lpBufStart;
++       char *lpTmpStart;
++       u32 nCnt;
++       char thisChar;
++
++       /* tmp workspace, 1 KB longer than input buf */
++       lpTmpBuf = MEM_Calloc((nBytes + ulNumWords), MEM_PAGED);
++       if (lpTmpBuf == NULL) {
++               DBG_Trace(DBG_LEVEL7, "PackTrace buffer:OutofMemory \n");
++               status = DSP_EMEMORY;
++       }
++
++       if (DSP_SUCCEEDED(status)) {
++               lpBufStart = lpBuf;
++               lpTmpStart = lpTmpBuf;
++               for (nCnt = nBytes; nCnt > 0; nCnt--) {
++                       thisChar = *lpBuf++;
++                       switch (thisChar) {
++                       case '\0':      /* Skip null bytes */
++                       break;
++                       case '\n':      /* Convert \n to \r\n */
++                       /* NOTE: do not reverse order; Some OS */
++                       /* editors control doesn't understand "\n\r" */
++                       *lpTmpBuf++ = '\r';
++                       *lpTmpBuf++ = '\n';
++                       break;
++                       default:        /* Copy in the actual ascii byte */
++                       *lpTmpBuf++ = thisChar;
++                       break;
++                       }
++               }
++               *lpTmpBuf = '\0';    /* Make sure tmp buf is null terminated */
++               /* Cut output down to input buf size */
++               strncpy(lpBufStart, lpTmpStart, nBytes);
++               /*Make sure output is null terminated */
++               lpBufStart[nBytes - 1] = '\0';
++               MEM_Free(lpTmpStart);
++       }
++
++       return status;
++}
++#endif    /* (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE */
++
++/*
++ *  ======== PrintDspTraceBuffer ========
++ *      Prints the trace buffer returned from the DSP (if DBG_Trace is enabled).
++ *  Parameters:
++ *    hDehMgr:          Handle to DEH manager object
++ *                      number of extra carriage returns to generate.
++ *  Returns:
++ *      DSP_SOK:        Success.
++ *      DSP_EMEMORY:    Unable to allocate memory.
++ *  Requires:
++ *      hDehMgr muse be valid. Checked in WMD_DEH_Notify.
++ */
++DSP_STATUS PrintDspTraceBuffer(struct WMD_DEV_CONTEXT *hWmdContext)
++{
++       DSP_STATUS status = DSP_SOK;
++
++#if (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE
++       struct COD_MANAGER *hCodMgr;
++       u32 ulTraceEnd;
++       u32 ulTraceBegin;
++       u32 ulNumBytes = 0;
++       u32 ulNumWords = 0;
++       u32 ulWordSize = 2;
++       CONST u32 uMaxSize = 512;
++       char *pszBuf;
++       u16 *lpszBuf;
++
++       struct WMD_DEV_CONTEXT *pWmdContext = (struct WMD_DEV_CONTEXT *)
++                                               hWmdContext;
++       struct WMD_DRV_INTERFACE *pIntfFxns;
++       struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)
++                                       pWmdContext->hDevObject;
++
++       status = DEV_GetCodMgr(pDevObject, &hCodMgr);
++       if (DSP_FAILED(status))
++               GT_0trace(dsp_trace_mask, GT_2CLASS,
++               "PrintDspTraceBuffer: Failed on DEV_GetCodMgr.\n");
++
++       if (DSP_SUCCEEDED(status)) {
++               /* Look for SYS_PUTCBEG/SYS_PUTCEND: */
++               status = COD_GetSymValue(hCodMgr, COD_TRACEBEG, &ulTraceBegin);
++               GT_1trace(dsp_trace_mask, GT_2CLASS,
++                       "PrintDspTraceBuffer: ulTraceBegin Value 0x%x\n",
++                       ulTraceBegin);
++               if (DSP_FAILED(status))
++                       GT_0trace(dsp_trace_mask, GT_2CLASS,
++                               "PrintDspTraceBuffer: Failed on "
++                               "COD_GetSymValue.\n");
++       }
++       if (DSP_SUCCEEDED(status)) {
++               status = COD_GetSymValue(hCodMgr, COD_TRACEEND, &ulTraceEnd);
++               GT_1trace(dsp_trace_mask, GT_2CLASS,
++                       "PrintDspTraceBuffer: ulTraceEnd Value 0x%x\n",
++                       ulTraceEnd);
++               if (DSP_FAILED(status))
++                       GT_0trace(dsp_trace_mask, GT_2CLASS,
++                               "PrintDspTraceBuffer: Failed on "
++                               "COD_GetSymValue.\n");
++       }
++       if (DSP_SUCCEEDED(status)) {
++               ulNumBytes = (ulTraceEnd - ulTraceBegin) * ulWordSize;
++               /*  If the chip type is 55 then the addresses will be
++               *  byte addresses; convert them to word addresses.  */
++               if (ulNumBytes > uMaxSize)
++                       ulNumBytes = uMaxSize;
++
++               /* make sure the data we request fits evenly */
++               ulNumBytes = (ulNumBytes / ulWordSize) * ulWordSize;
++               GT_1trace(dsp_trace_mask, GT_2CLASS, "PrintDspTraceBuffer: "
++                       "ulNumBytes 0x%x\n", ulNumBytes);
++               ulNumWords = ulNumBytes * ulWordSize;
++               GT_1trace(dsp_trace_mask, GT_2CLASS, "PrintDspTraceBuffer: "
++                       "ulNumWords 0x%x\n", ulNumWords);
++               status = DEV_GetIntfFxns(pDevObject, &pIntfFxns);
++       }
++
++       if (DSP_SUCCEEDED(status)) {
++               pszBuf = MEM_Calloc(uMaxSize, MEM_NONPAGED);
++               lpszBuf = MEM_Calloc(ulNumBytes * 2, MEM_NONPAGED);
++               if (pszBuf != NULL) {
++                       /* Read bytes from the DSP trace buffer... */
++                       status = (*pIntfFxns->pfnBrdRead)(hWmdContext,
++                               (u8 *)pszBuf, (u32)ulTraceBegin,
++                               ulNumBytes, 0);
++                       if (DSP_FAILED(status))
++                               GT_0trace(dsp_trace_mask, GT_2CLASS,
++                                       "PrintDspTraceBuffer: "
++                                       "Failed to Read Trace Buffer.\n");
++
++                       if (DSP_SUCCEEDED(status)) {
++                               /* Pack and do newline conversion */
++                               GT_0trace(dsp_trace_mask, GT_2CLASS,
++                                       "PrintDspTraceBuffer: "
++                                       "before pack and unpack.\n");
++                               PackTraceBuffer(pszBuf, ulNumBytes, ulNumWords);
++                               GT_1trace(dsp_trace_mask, GT_1CLASS,
++                                       "DSP Trace Buffer:\n%s\n", pszBuf);
++                       }
++                       MEM_Free(pszBuf);
++                       MEM_Free(lpszBuf);
++               } else {
++                       GT_0trace(dsp_trace_mask, GT_2CLASS,
++                               "PrintDspTraceBuffer: Failed to "
++                               "allocate trace buffer.\n");
++                       status = DSP_EMEMORY;
++               }
++       }
++#endif
++       return status;
++}
++
++void IO_SM_init(void)
++{
++
++       GT_create(&dsp_trace_mask, "DT"); /* DSP Trace Mask */
++
++}
+diff --git a/drivers/dsp/bridge/wmd/mmu_fault.c b/drivers/dsp/bridge/wmd/mmu_fault.c
+new file mode 100644
+index 0000000..5585cdb
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/mmu_fault.c
+@@ -0,0 +1,172 @@
++/*
++ * mmu_fault.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== mmu_fault.c ========
++ *  Description:
++ *      Implements DSP MMU fault handling functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Dec-2004 hn: Support for IVA MMU exception.
++ *! 06-Mar-2003 sb: Print MMU fault address. Cosmetic changes.
++ *! 16-Feb-2003 vp: Fixed warning in MMU_FaultIsr
++ *! 05-Jan-2004 vp: Updated support for 24xx silicon
++ *! 19-Feb-2003 vp: Code review updates.
++ *!                 - Cosmetic changes.
++ *! 18-Oct-2002 sb: Ported to Linux platform.
++ *! 10-Sep-2001 kc: created.
++ */
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/host_os.h>
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/dpc.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/drv.h>
++
++/*  ----------------------------------- Link Driver */
++#include <dspbridge/wmddeh.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/*  ----------------------------------- This */
++#include "_deh.h"
++#include <dspbridge/cfg.h>
++#include "_tiomap_mmu.h"
++#include "_tiomap.h"
++#include "mmu_fault.h"
++
++static u32 dmmuEventMask;
++u32 faultAddr;
++
++static bool MMU_CheckIfFault(struct WMD_DEV_CONTEXT *pDevContext);
++
++/*
++ *  ======== MMU_FaultDpc ========
++ *      Deferred procedure call to handle DSP MMU fault.
++ */
++void MMU_FaultDpc(IN void *pRefData)
++{
++      struct DEH_MGR *hDehMgr = (struct DEH_MGR *)pRefData;
++      struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++      DBG_Trace(DBG_LEVEL1, "MMU_FaultDpc Enter: 0x%x\n", pRefData);
++
++      if (pDehMgr)
++              WMD_DEH_Notify(hDehMgr, DSP_MMUFAULT, 0L);
++
++      DBG_Trace(DBG_LEVEL1, "MMU_FaultDpc Exit: 0x%x\n", pRefData);
++}
++
++/*
++ *  ======== MMU_FaultIsr ========
++ *      ISR to be triggered by a DSP MMU fault interrupt.
++ */
++irqreturn_t  MMU_FaultIsr(int irq, IN void *pRefData)
++{
++      struct DEH_MGR *pDehMgr = (struct DEH_MGR *)pRefData;
++      struct WMD_DEV_CONTEXT *pDevContext;
++      struct CFG_HOSTRES resources;
++      DSP_STATUS status = DSP_SOK;
++
++
++      DBG_Trace(DBG_LEVEL1, "Entering DEH_DspMmuIsr: 0x%x\n", pRefData);
++       DBC_Require(irq == INT_DSP_MMU_IRQ);
++      DBC_Require(MEM_IsValidHandle(pDehMgr, SIGNATURE));
++
++      if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++
++              pDevContext = (struct WMD_DEV_CONTEXT *)pDehMgr->hWmdContext;
++              status = CFG_GetHostResources(
++                       (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++                       &resources);
++              if (DSP_FAILED(status))
++                      DBG_Trace(DBG_LEVEL7,
++                               "**Failed to get Host Resources "
++                               "in MMU ISR **\n");
++              if (MMU_CheckIfFault(pDevContext)) {
++                      printk(KERN_INFO "***** DSPMMU FAULT ***** IRQStatus "
++                              "0x%x\n", dmmuEventMask);
++                      printk(KERN_INFO "***** DSPMMU FAULT ***** faultAddr "
++                              "0x%x\n", faultAddr);
++                      /* Disable the MMU events, else once we clear it will
++                       * start to raise INTs again */
++                      /*
++                       * Schedule a DPC directly. In the future, it may be
++                       * necessary to check if DSP MMU fault is intended for
++                       * Bridge.
++                       */
++                      DPC_Schedule(pDehMgr->hMmuFaultDpc);
++                      /* Reset errInfo structure before use. */
++                      pDehMgr->errInfo.dwErrMask = DSP_MMUFAULT;
++                      pDehMgr->errInfo.dwVal1 = faultAddr >> 16;
++                      pDehMgr->errInfo.dwVal2 = faultAddr & 0xFFFF;
++                      pDehMgr->errInfo.dwVal3 = 0L;
++                      /* Disable the MMU events, else once we clear it will
++                       * start to raise INTs again */
++                      HW_MMU_EventDisable(resources.dwDmmuBase,
++                                          HW_MMU_TRANSLATION_FAULT);
++              } else {
++                      DBG_Trace(DBG_LEVEL7,
++                               "***** MMU FAULT ***** faultcode 0x%x\n",
++                               dmmuEventMask);
++                      HW_MMU_EventDisable(resources.dwDmmuBase,
++                                          HW_MMU_ALL_INTERRUPTS);
++              }
++      }
++       return IRQ_HANDLED;
++}
++
++
++/*
++ *  ======== MMU_CheckIfFault ========
++ *      Check to see if MMU Fault is valid TLB miss from DSP
++ *  Note: This function is called from an ISR
++ */
++static bool MMU_CheckIfFault(struct WMD_DEV_CONTEXT *pDevContext)
++{
++
++
++      bool retVal = false;
++      DSP_STATUS status = DSP_SOK;
++      HW_STATUS hwStatus;
++      struct CFG_HOSTRES resources;
++      status = CFG_GetHostResources(
++              (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++      if (DSP_FAILED(status))
++              DBG_Trace(DBG_LEVEL7, "**Failed to get Host Resources in "
++                       "MMU_CheckIfFault **\n");
++
++      hwStatus = HW_MMU_EventStatus(resources.dwDmmuBase, &dmmuEventMask);
++      if (dmmuEventMask  ==  HW_MMU_TRANSLATION_FAULT) {
++              HW_MMU_FaultAddrRead(resources.dwDmmuBase, &faultAddr);
++              DBG_Trace(DBG_LEVEL1, "WMD_DEH_Notify: DSP_MMUFAULT, fault "
++                       "address = 0x%x\n", faultAddr);
++              retVal = true;
++      }
++      return retVal;
++}
+diff --git a/drivers/dsp/bridge/wmd/mmu_fault.h b/drivers/dsp/bridge/wmd/mmu_fault.h
+new file mode 100644
+index 0000000..be59333
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/mmu_fault.h
+@@ -0,0 +1,45 @@
++/*
++ * mmu_fault.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== mmu_fault.h ========
++ *  Description:
++ *      Defines DSP MMU fault handling functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Dec-2004 hn: IVA MMU handlers.
++ *! 10-Sep-2001 kc: created.
++ */
++
++#ifndef MMU_FAULT_
++#define MMU_FAULT_
++
++/*
++ *  ======== MMU_FaultDpc ========
++ *      Deferred procedure call to handle DSP MMU fault.
++ */
++      void MMU_FaultDpc(IN void *pRefData);
++
++/*
++ *  ======== MMU_FaultIsr ========
++ *      ISR to be triggered by a DSP MMU fault interrupt.
++ */
++irqreturn_t  MMU_FaultIsr(int irq, IN void *pRefData);
++
++#endif                                /* MMU_FAULT_ */
++
+diff --git a/drivers/dsp/bridge/wmd/msg_sm.c b/drivers/dsp/bridge/wmd/msg_sm.c
+new file mode 100644
+index 0000000..b9b2bec
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/msg_sm.c
+@@ -0,0 +1,643 @@
++/*
++ * msg_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== msg_sm.c ========
++ *  Description:
++ *      Implements upper edge functions for WMD message module.
++ *
++ *  Public Functions:
++ *      WMD_MSG_Create
++ *      WMD_MSG_CreateQueue
++ *      WMD_MSG_Delete
++ *      WMD_MSG_DeleteQueue
++ *      WMD_MSG_Get
++ *      WMD_MSG_Put
++ *      WMD_MSG_RegisterNotify
++ *      WMD_MSG_SetQueueId
++ *
++ *! Revision History:
++ *! =================
++ *! 24-Jul-2002 jeh     Release critical section in WMD_MSG_Put() before
++ *!                     scheduling DPC.
++ *! 09-May-2001 jeh     Free MSG queue NTFY object, remove unnecessary set/
++ *!                     reset of events.
++ *! 10-Jan-2001 jeh     Set/Reset message manager and message queue events
++ *!                     correctly.
++ *! 04-Dec-2000 jeh     Bug fixes.
++ *! 12-Sep-2000 jeh     Created.
++ */
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/*  ----------------------------------- Others */
++#include <dspbridge/io_sm.h>
++
++/*  ----------------------------------- This */
++#include <_msg_sm.h>
++#include <dspbridge/wmdmsg.h>
++
++/*  ----------------------------------- Defines, Data Structures, Typedefs */
++#define MSGQ_SIGNATURE      0x5147534d        /* "QGSM" */
++
++/*  ----------------------------------- Function Prototypes */
++static DSP_STATUS AddNewMsg(struct LST_LIST *msgList);
++static void DeleteMsgMgr(struct MSG_MGR *hMsgMgr);
++static void DeleteMsgQueue(struct MSG_QUEUE *hMsgQueue, u32 uNumToDSP);
++static void FreeMsgList(struct LST_LIST *msgList);
++
++/*
++ *  ======== WMD_MSG_Create ========
++ *      Create an object to manage message queues. Only one of these objects
++ *      can exist per device object.
++ */
++DSP_STATUS WMD_MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++                       struct DEV_OBJECT *hDevObject, MSG_ONEXIT msgCallback)
++{
++      struct MSG_MGR *pMsgMgr;
++      struct IO_MGR *hIOMgr;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(phMsgMgr != NULL);
++      DBC_Require(msgCallback != NULL);
++      DBC_Require(hDevObject != NULL);
++      DEV_GetIOMgr(hDevObject, &hIOMgr);
++      DBC_Assert(hIOMgr != NULL);
++      *phMsgMgr = NULL;
++      /* Allocate MSG manager object */
++      MEM_AllocObject(pMsgMgr, struct MSG_MGR, MSGMGR_SIGNATURE);
++
++      if (pMsgMgr) {
++              pMsgMgr->onExit = msgCallback;
++              pMsgMgr->hIOMgr = hIOMgr;
++              /* List of MSG_QUEUEs */
++              pMsgMgr->queueList = LST_Create();
++               /*  Queues of message frames for messages to the DSP. Message
++                * frames will only be added to the free queue when a
++                * MSG_QUEUE object is created.  */
++              pMsgMgr->msgFreeList = LST_Create();
++              pMsgMgr->msgUsedList = LST_Create();
++              if (pMsgMgr->queueList == NULL ||
++                  pMsgMgr->msgFreeList == NULL ||
++                  pMsgMgr->msgUsedList == NULL)
++                      status = DSP_EMEMORY;
++              if (DSP_SUCCEEDED(status))
++                      status = SYNC_InitializeDPCCS(&pMsgMgr->hSyncCS);
++
++               /*  Create an event to be used by WMD_MSG_Put() in waiting
++               *  for an available free frame from the message manager.  */
++              if (DSP_SUCCEEDED(status))
++                      status = SYNC_OpenEvent(&pMsgMgr->hSyncEvent, NULL);
++
++              if (DSP_SUCCEEDED(status))
++                      *phMsgMgr = pMsgMgr;
++              else
++                      DeleteMsgMgr(pMsgMgr);
++
++      } else {
++              status = DSP_EMEMORY;
++      }
++      return status;
++}
++
++/*
++ *  ======== WMD_MSG_CreateQueue ========
++ *      Create a MSG_QUEUE for sending/receiving messages to/from a node
++ *      on the DSP.
++ */
++DSP_STATUS WMD_MSG_CreateQueue(struct MSG_MGR *hMsgMgr,
++                            OUT struct MSG_QUEUE **phMsgQueue,
++                            u32 dwId, u32 uMaxMsgs, HANDLE hArg)
++{
++      u32 i;
++      u32 uNumAllocated = 0;
++      struct MSG_QUEUE *pMsgQ;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++      DBC_Require(phMsgQueue != NULL);
++
++      *phMsgQueue = NULL;
++      /* Allocate MSG_QUEUE object */
++      MEM_AllocObject(pMsgQ, struct MSG_QUEUE, MSGQ_SIGNATURE);
++      if (!pMsgQ) {
++              status = DSP_EMEMORY;
++              goto func_end;
++      }
++      LST_InitElem((struct LST_ELEM *) pMsgQ);
++      pMsgQ->uMaxMsgs = uMaxMsgs;
++      pMsgQ->hMsgMgr = hMsgMgr;
++      pMsgQ->hArg = hArg;     /* Node handle */
++      pMsgQ->dwId = dwId;     /* Node env (not valid yet) */
++      /* Queues of Message frames for messages from the DSP */
++      pMsgQ->msgFreeList = LST_Create();
++      pMsgQ->msgUsedList = LST_Create();
++      if (pMsgQ->msgFreeList == NULL || pMsgQ->msgUsedList == NULL)
++              status = DSP_EMEMORY;
++
++       /*  Create event that will be signalled when a message from
++       *  the DSP is available.  */
++      if (DSP_SUCCEEDED(status))
++              status = SYNC_OpenEvent(&pMsgQ->hSyncEvent, NULL);
++
++      /* Create a notification list for message ready notification. */
++      if (DSP_SUCCEEDED(status))
++              status = NTFY_Create(&pMsgQ->hNtfy);
++
++       /*  Create events that will be used to synchronize cleanup
++       *  when the object is deleted. hSyncDone will be set to
++       *  unblock threads in MSG_Put() or MSG_Get(). hSyncDoneAck
++       *  will be set by the unblocked thread to signal that it
++       *  is unblocked and will no longer reference the object.  */
++      if (DSP_SUCCEEDED(status))
++              status = SYNC_OpenEvent(&pMsgQ->hSyncDone, NULL);
++
++      if (DSP_SUCCEEDED(status))
++              status = SYNC_OpenEvent(&pMsgQ->hSyncDoneAck, NULL);
++
++      if (DSP_SUCCEEDED(status)) {
++               if (!hMsgMgr->msgFreeList) {
++                       status = DSP_EHANDLE;
++                       goto func_end;
++               }
++              /* Enter critical section */
++              (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++              /* Initialize message frames and put in appropriate queues */
++              for (i = 0; i < uMaxMsgs && DSP_SUCCEEDED(status); i++) {
++                      status = AddNewMsg(hMsgMgr->msgFreeList);
++                      if (DSP_SUCCEEDED(status)) {
++                              uNumAllocated++;
++                              status = AddNewMsg(pMsgQ->msgFreeList);
++                      }
++              }
++              if (DSP_FAILED(status)) {
++                      /*  Stay inside CS to prevent others from taking any
++                       *  of the newly allocated message frames.  */
++                      DeleteMsgQueue(pMsgQ, uNumAllocated);
++              } else {
++                      LST_PutTail(hMsgMgr->queueList,
++                                 (struct LST_ELEM *)pMsgQ);
++                      *phMsgQueue = pMsgQ;
++                      /* Signal that free frames are now available */
++                      if (!LST_IsEmpty(hMsgMgr->msgFreeList))
++                              SYNC_SetEvent(hMsgMgr->hSyncEvent);
++
++              }
++              /* Exit critical section */
++              (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++      } else {
++              DeleteMsgQueue(pMsgQ, 0);
++      }
++func_end:
++      return status;
++}
++
++/*
++ *  ======== WMD_MSG_Delete ========
++ *      Delete a MSG manager allocated in WMD_MSG_Create().
++ */
++void WMD_MSG_Delete(struct MSG_MGR *hMsgMgr)
++{
++      DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++
++      DeleteMsgMgr(hMsgMgr);
++}
++
++/*
++ *  ======== WMD_MSG_DeleteQueue ========
++ *      Delete a MSG queue allocated in WMD_MSG_CreateQueue.
++ */
++void WMD_MSG_DeleteQueue(struct MSG_QUEUE *hMsgQueue)
++{
++      struct MSG_MGR *hMsgMgr = hMsgQueue->hMsgMgr;
++      u32 refCount;
++
++      DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++      hMsgQueue->fDone = true;
++       /*  Unblock all threads blocked in MSG_Get() or MSG_Put().  */
++      refCount = hMsgQueue->refCount;
++      while (refCount) {
++              /* Unblock thread */
++              SYNC_SetEvent(hMsgQueue->hSyncDone);
++              /* Wait for acknowledgement */
++              SYNC_WaitOnEvent(hMsgQueue->hSyncDoneAck, SYNC_INFINITE);
++              refCount = hMsgQueue->refCount;
++      }
++      /* Remove message queue from hMsgMgr->queueList */
++      (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++      LST_RemoveElem(hMsgMgr->queueList, (struct LST_ELEM *)hMsgQueue);
++      /* Free the message queue object */
++      DeleteMsgQueue(hMsgQueue, hMsgQueue->uMaxMsgs);
++       if (!hMsgMgr->msgFreeList)
++               goto func_cont;
++      if (LST_IsEmpty(hMsgMgr->msgFreeList))
++              SYNC_ResetEvent(hMsgMgr->hSyncEvent);
++func_cont:
++      (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++}
++
++/*
++ *  ======== WMD_MSG_Get ========
++ *      Get a message from a MSG queue.
++ */
++DSP_STATUS WMD_MSG_Get(struct MSG_QUEUE *hMsgQueue,
++                    struct DSP_MSG *pMsg, u32 uTimeout)
++{
++      struct MSG_FRAME *pMsgFrame;
++      struct MSG_MGR *hMsgMgr;
++      bool fGotMsg = false;
++      struct SYNC_OBJECT *hSyncs[2];
++      u32 uIndex;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++      DBC_Require(pMsg != NULL);
++
++      hMsgMgr = hMsgQueue->hMsgMgr;
++       if (!hMsgQueue->msgUsedList) {
++               status = DSP_EHANDLE;
++               goto func_end;
++       }
++
++      /* Enter critical section */
++      (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++      /* If a message is already there, get it */
++      if (!LST_IsEmpty(hMsgQueue->msgUsedList)) {
++              pMsgFrame = (struct MSG_FRAME *)LST_GetHead(hMsgQueue->
++                          msgUsedList);
++              if (pMsgFrame != NULL) {
++                      *pMsg = pMsgFrame->msgData.msg;
++                      LST_PutTail(hMsgQueue->msgFreeList,
++                                 (struct LST_ELEM *)pMsgFrame);
++                      if (LST_IsEmpty(hMsgQueue->msgUsedList))
++                              SYNC_ResetEvent(hMsgQueue->hSyncEvent);
++
++                      fGotMsg = true;
++              }
++      } else {
++              if (hMsgQueue->fDone)
++                      status = DSP_EFAIL;
++              else
++                      hMsgQueue->refCount++;
++
++      }
++      /* Exit critical section */
++      (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++      if (DSP_SUCCEEDED(status) && !fGotMsg) {
++              /*  Wait til message is available, timeout, or done. We don't
++               *  have to schedule the DPC, since the DSP will send messages
++               *  when they are available.  */
++              hSyncs[0] = hMsgQueue->hSyncEvent;
++              hSyncs[1] = hMsgQueue->hSyncDone;
++              status = SYNC_WaitOnMultipleEvents(hSyncs, 2, uTimeout,
++                       &uIndex);
++              /* Enter critical section */
++              (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++              if (hMsgQueue->fDone) {
++                      hMsgQueue->refCount--;
++                      /* Exit critical section */
++                      (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++                       /*  Signal that we're not going to access hMsgQueue
++                        *  anymore, so it can be deleted.  */
++                      (void)SYNC_SetEvent(hMsgQueue->hSyncDoneAck);
++                      status = DSP_EFAIL;
++              } else {
++                      if (DSP_SUCCEEDED(status)) {
++                              DBC_Assert(!LST_IsEmpty(hMsgQueue->
++                                        msgUsedList));
++                              /* Get msg from used list */
++                              pMsgFrame = (struct MSG_FRAME *)
++                                         LST_GetHead(hMsgQueue->msgUsedList);
++                              /* Copy message into pMsg and put frame on the
++                               * free list */
++                              if (pMsgFrame != NULL) {
++                                      *pMsg = pMsgFrame->msgData.msg;
++                                      LST_PutTail(hMsgQueue->msgFreeList,
++                                      (struct LST_ELEM *)pMsgFrame);
++                              }
++                      }
++                      hMsgQueue->refCount--;
++                      /* Reset the event if there are still queued messages */
++                      if (!LST_IsEmpty(hMsgQueue->msgUsedList))
++                              SYNC_SetEvent(hMsgQueue->hSyncEvent);
++
++                      /* Exit critical section */
++                      (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++              }
++      }
++func_end:
++      return status;
++}
++
++/*
++ *  ======== WMD_MSG_Put ========
++ *      Put a message onto a MSG queue.
++ */
++DSP_STATUS WMD_MSG_Put(struct MSG_QUEUE *hMsgQueue,
++                    IN CONST struct DSP_MSG *pMsg, u32 uTimeout)
++{
++      struct MSG_FRAME *pMsgFrame;
++      struct MSG_MGR *hMsgMgr;
++      bool fPutMsg = false;
++      struct SYNC_OBJECT *hSyncs[2];
++      u32 uIndex;
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++      DBC_Require(pMsg != NULL);
++
++      hMsgMgr = hMsgQueue->hMsgMgr;
++
++       if (!hMsgMgr->msgFreeList) {
++               status = DSP_EHANDLE;
++               goto func_end;
++       }
++
++
++      (void) SYNC_EnterCS(hMsgMgr->hSyncCS);
++
++      /* If a message frame is available, use it */
++      if (!LST_IsEmpty(hMsgMgr->msgFreeList)) {
++              pMsgFrame = (struct MSG_FRAME *)LST_GetHead(hMsgMgr->
++                          msgFreeList);
++              if (pMsgFrame != NULL) {
++                      pMsgFrame->msgData.msg = *pMsg;
++                      pMsgFrame->msgData.dwId = hMsgQueue->dwId;
++                      LST_PutTail(hMsgMgr->msgUsedList, (struct LST_ELEM *)
++                                 pMsgFrame);
++                      hMsgMgr->uMsgsPending++;
++                      fPutMsg = true;
++              }
++              if (LST_IsEmpty(hMsgMgr->msgFreeList))
++                      SYNC_ResetEvent(hMsgMgr->hSyncEvent);
++
++              /* Release critical section before scheduling DPC */
++              (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++              /* Schedule a DPC, to do the actual data transfer: */
++              IO_Schedule(hMsgMgr->hIOMgr);
++      } else {
++              if (hMsgQueue->fDone)
++                      status = DSP_EFAIL;
++              else
++                      hMsgQueue->refCount++;
++
++              (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++      }
++      if (DSP_SUCCEEDED(status) && !fPutMsg) {
++              /* Wait til a free message frame is available, timeout,
++               * or done */
++              hSyncs[0] = hMsgMgr->hSyncEvent;
++              hSyncs[1] = hMsgQueue->hSyncDone;
++              status = SYNC_WaitOnMultipleEvents(hSyncs, 2, uTimeout,
++                       &uIndex);
++              /* Enter critical section */
++              (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++              if (hMsgQueue->fDone) {
++                      hMsgQueue->refCount--;
++                      /* Exit critical section */
++                      (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++                       /*  Signal that we're not going to access hMsgQueue
++                        *  anymore, so it can be deleted.  */
++                      (void)SYNC_SetEvent(hMsgQueue->hSyncDoneAck);
++                      status = DSP_EFAIL;
++              } else {
++                      if (DSP_SUCCEEDED(status)) {
++                               if (LST_IsEmpty(hMsgMgr->msgFreeList)) {
++                                       status = DSP_EPOINTER;
++                                       goto func_cont;
++                               }
++                              /* Get msg from free list */
++                              pMsgFrame = (struct MSG_FRAME *)
++                                          LST_GetHead(hMsgMgr->msgFreeList);
++                              /* Copy message into pMsg and put frame on the
++                               * used list */
++                              if (pMsgFrame != NULL) {
++                                      pMsgFrame->msgData.msg = *pMsg;
++                                      pMsgFrame->msgData.dwId =
++                                              hMsgQueue->dwId;
++                                      LST_PutTail(hMsgMgr->msgUsedList,
++                                                 (struct LST_ELEM *)
++                                                 pMsgFrame);
++                                      hMsgMgr->uMsgsPending++;
++                                      /* Schedule a DPC, to do the actual
++                                       * data transfer: */
++                                      IO_Schedule(hMsgMgr->hIOMgr);
++                              }
++                      }
++                      hMsgQueue->refCount--;
++                      /* Reset event if there are still frames available */
++                      if (!LST_IsEmpty(hMsgMgr->msgFreeList))
++                              SYNC_SetEvent(hMsgMgr->hSyncEvent);
++func_cont:
++                      /* Exit critical section */
++                      (void) SYNC_LeaveCS(hMsgMgr->hSyncCS);
++              }
++      }
++func_end:
++      return status;
++}
++
++/*
++ *  ======== WMD_MSG_RegisterNotify ========
++ */
++DSP_STATUS WMD_MSG_RegisterNotify(struct MSG_QUEUE *hMsgQueue, u32 uEventMask,
++                                u32 uNotifyType,
++                                struct DSP_NOTIFICATION *hNotification)
++{
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++      DBC_Require(hNotification != NULL);
++      DBC_Require(uEventMask == DSP_NODEMESSAGEREADY || uEventMask == 0);
++      DBC_Require(uNotifyType == DSP_SIGNALEVENT);
++
++      status = NTFY_Register(hMsgQueue->hNtfy, hNotification, uEventMask,
++                            uNotifyType);
++
++      if (status == DSP_EVALUE) {
++              /*  Not registered. Ok, since we couldn't have known. Node
++               *  notifications are split between node state change handled
++               *  by NODE, and message ready handled by MSG.  */
++              status = DSP_SOK;
++      }
++
++      return status;
++}
++
++/*
++ *  ======== WMD_MSG_SetQueueId ========
++ */
++void WMD_MSG_SetQueueId(struct MSG_QUEUE *hMsgQueue, u32 dwId)
++{
++      DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++      /* DBC_Require(dwId != 0); */
++
++      /*
++       *  A message queue must be created when a node is allocated,
++       *  so that NODE_RegisterNotify() can be called before the node
++       *  is created. Since we don't know the node environment until the
++       *  node is created, we need this function to set hMsgQueue->dwId
++       *  to the node environment, after the node is created.
++       */
++      hMsgQueue->dwId = dwId;
++}
++
++/*
++ *  ======== AddNewMsg ========
++ *      Must be called in message manager critical section.
++ */
++static DSP_STATUS AddNewMsg(struct LST_LIST *msgList)
++{
++      struct MSG_FRAME *pMsg;
++      DSP_STATUS status = DSP_SOK;
++
++      pMsg = (struct MSG_FRAME *)MEM_Calloc(sizeof(struct MSG_FRAME),
++              MEM_PAGED);
++      if (pMsg != NULL) {
++              LST_InitElem((struct LST_ELEM *) pMsg);
++              LST_PutTail(msgList, (struct LST_ELEM *) pMsg);
++      } else {
++              status = DSP_EMEMORY;
++      }
++
++      return status;
++}
++
++/*
++ *  ======== DeleteMsgMgr ========
++ */
++static void DeleteMsgMgr(struct MSG_MGR *hMsgMgr)
++{
++      DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++
++      if (hMsgMgr->queueList) {
++               if (LST_IsEmpty(hMsgMgr->queueList)) {
++                       LST_Delete(hMsgMgr->queueList);
++                       hMsgMgr->queueList = NULL;
++               }
++      }
++
++       if (hMsgMgr->msgFreeList) {
++              FreeMsgList(hMsgMgr->msgFreeList);
++               hMsgMgr->msgFreeList = NULL;
++       }
++
++       if (hMsgMgr->msgUsedList) {
++              FreeMsgList(hMsgMgr->msgUsedList);
++               hMsgMgr->msgUsedList = NULL;
++       }
++
++      if (hMsgMgr->hSyncEvent)
++              SYNC_CloseEvent(hMsgMgr->hSyncEvent);
++
++      if (hMsgMgr->hSyncCS)
++              SYNC_DeleteCS(hMsgMgr->hSyncCS);
++
++      MEM_FreeObject(hMsgMgr);
++}
++
++/*
++ *  ======== DeleteMsgQueue ========
++ */
++static void DeleteMsgQueue(struct MSG_QUEUE *hMsgQueue, u32 uNumToDSP)
++{
++       struct MSG_MGR *hMsgMgr;
++      struct MSG_FRAME *pMsg;
++      u32 i;
++
++       if (!MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE)
++               || !hMsgQueue->hMsgMgr || !hMsgQueue->hMsgMgr->msgFreeList)
++               goto func_end;
++       hMsgMgr = hMsgQueue->hMsgMgr;
++
++
++      /* Pull off uNumToDSP message frames from Msg manager and free */
++      for (i = 0; i < uNumToDSP; i++) {
++
++              if (!LST_IsEmpty(hMsgMgr->msgFreeList)) {
++                      pMsg = (struct MSG_FRAME *)LST_GetHead(hMsgMgr->
++                              msgFreeList);
++                      MEM_Free(pMsg);
++              } else {
++                      /* Cannot free all of the message frames */
++                      break;
++              }
++      }
++
++       if (hMsgQueue->msgFreeList) {
++              FreeMsgList(hMsgQueue->msgFreeList);
++               hMsgQueue->msgFreeList = NULL;
++       }
++
++       if (hMsgQueue->msgUsedList) {
++              FreeMsgList(hMsgQueue->msgUsedList);
++               hMsgQueue->msgUsedList = NULL;
++       }
++
++
++      if (hMsgQueue->hNtfy)
++              NTFY_Delete(hMsgQueue->hNtfy);
++
++      if (hMsgQueue->hSyncEvent)
++              SYNC_CloseEvent(hMsgQueue->hSyncEvent);
++
++      if (hMsgQueue->hSyncDone)
++              SYNC_CloseEvent(hMsgQueue->hSyncDone);
++
++      if (hMsgQueue->hSyncDoneAck)
++              SYNC_CloseEvent(hMsgQueue->hSyncDoneAck);
++
++      MEM_FreeObject(hMsgQueue);
++func_end:
++       return;
++
++}
++
++/*
++ *  ======== FreeMsgList ========
++ */
++static void FreeMsgList(struct LST_LIST *msgList)
++{
++      struct MSG_FRAME *pMsg;
++
++       if (!msgList)
++               goto func_end;
++
++      while ((pMsg = (struct MSG_FRAME *)LST_GetHead(msgList)) != NULL)
++              MEM_Free(pMsg);
++
++      DBC_Assert(LST_IsEmpty(msgList));
++
++      LST_Delete(msgList);
++func_end:
++       return;
++}
++
+diff --git a/drivers/dsp/bridge/wmd/tiomap3430.c b/drivers/dsp/bridge/wmd/tiomap3430.c
+new file mode 100644
+index 0000000..2ab585d
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap3430.c
+@@ -0,0 +1,2149 @@
++/*
++ * tiomap.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== tiomap.c ========
++ *  Processor Manager Driver for TI OMAP3430 EVM.
++ *
++ *  Public Function:
++ *      WMD_DRV_Entry
++ *
++ *! Revision History:
++ *! ================
++ *   26-March-2008 HK and AL:  Added WMD_DEV_WalkTbl funciton.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++#include <linux/mm.h>
++#include <linux/mmzone.h>
++#include <mach-omap2/prm.h>
++#include <mach-omap2/cm.h>
++#include <mach-omap2/prm-regbits-34xx.h>
++#include <mach-omap2/cm-regbits-34xx.h>
++#include <mach/control.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++#include <dspbridge/reg.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/sync.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_dspssC64P.h>
++#include <hw_prcm.h>
++#include <hw_mmu.h>
++#include <hw_mbox.h>
++
++/*  ----------------------------------- Link Driver */
++#include <dspbridge/wmd.h>
++#include <dspbridge/wmdchnl.h>
++#include <dspbridge/wmddeh.h>
++#include <dspbridge/wmdio.h>
++#include <dspbridge/wmdmsg.h>
++#include <dspbridge/pwr.h>
++#include <dspbridge/chnl_sm.h>
++#include <dspbridge/io_sm.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/wcd.h>
++#include <dspbridge/dmm.h>
++
++/*  ----------------------------------- Local */
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++#include "_tiomap_mmu.h"
++#include "_tiomap_util.h"
++#include "tiomap_io.h"
++
++
++/* Offset in shared mem to write to in order to synchronize start with DSP */
++#define SHMSYNCOFFSET 4               /* GPP byte offset */
++
++#define BUFFERSIZE 1024
++
++#define MMU_SECTION_ADDR_MASK    0xFFF00000
++#define MMU_SSECTION_ADDR_MASK   0xFF000000
++#define MMU_LARGE_PAGE_MASK      0xFFFF0000
++#define MMU_SMALL_PAGE_MASK      0xFFFFF000
++#define PAGES_II_LVL_TABLE   512
++#define phys_to_page(phys)      pfn_to_page((phys) >> PAGE_SHIFT)
++
++#define MMU_GFLUSH 0x60
++
++/* Forward Declarations: */
++static DSP_STATUS WMD_BRD_Monitor(struct WMD_DEV_CONTEXT *pDevContext);
++static DSP_STATUS WMD_BRD_Read(struct WMD_DEV_CONTEXT *pDevContext,
++                      OUT u8 *pbHostBuf,
++                      u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_Start(struct WMD_DEV_CONTEXT *pDevContext,
++                      u32 dwDSPAddr);
++static DSP_STATUS WMD_BRD_Status(struct WMD_DEV_CONTEXT *pDevContext,
++                      OUT BRD_STATUS *pdwState);
++static DSP_STATUS WMD_BRD_Stop(struct WMD_DEV_CONTEXT *pDevContext);
++static DSP_STATUS WMD_BRD_Write(struct WMD_DEV_CONTEXT *pDevContext,
++                      IN u8 *pbHostBuf,
++                      u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_SetState(struct WMD_DEV_CONTEXT *hDevContext,
++                      u32 ulBrdState);
++static DSP_STATUS WMD_BRD_MemCopy(struct WMD_DEV_CONTEXT *hDevContext,
++                      u32 ulDspDestAddr, u32 ulDspSrcAddr,
++                      u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_MemWrite(struct WMD_DEV_CONTEXT *pDevContext,
++                      IN u8 *pbHostBuf, u32 dwDSPAddr,
++                      u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext,
++                      u32 ulMpuAddr, u32 ulVirtAddr, u32 ulNumBytes,
++                      u32 ulMapAttr);
++static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,
++                      u32 ulVirtAddr, u32 ulNumBytes);
++static DSP_STATUS WMD_DEV_Create(OUT struct WMD_DEV_CONTEXT **ppDevContext,
++                      struct DEV_OBJECT *hDevObject,
++                      IN CONST struct CFG_HOSTRES *pConfig,
++                      IN CONST struct CFG_DSPRES *pDspConfig);
++static DSP_STATUS WMD_DEV_Ctrl(struct WMD_DEV_CONTEXT *pDevContext, u32 dwCmd,
++                      IN OUT void *pArgs);
++static DSP_STATUS WMD_DEV_Destroy(struct WMD_DEV_CONTEXT *pDevContext);
++static u32 user_va2pa(struct mm_struct *mm, u32 address);
++static DSP_STATUS PteUpdate(struct WMD_DEV_CONTEXT *hDevContext, u32 pa,
++                      u32 va, u32 size,
++                      struct HW_MMUMapAttrs_t *mapAttrs);
++static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,
++                      u32 size, struct HW_MMUMapAttrs_t *attrs);
++static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *hDevContext,
++                      u32 ulMpuAddr, u32 ulVirtAddr,
++                      u32 ulNumBytes, struct HW_MMUMapAttrs_t *hwAttrs);
++static DSP_STATUS run_IdleBoot(u32 prcm_base, u32 cm_base,
++                      u32 sysctrl_base);
++void GetHWRegs(u32 prcm_base, u32 cm_base);
++
++/*  ----------------------------------- Globals */
++
++/* Attributes of L2 page tables for DSP MMU */
++struct PageInfo {
++      u32 numEntries; /* Number of valid PTEs in the L2 PT */
++} ;
++
++/* Attributes used to manage the DSP MMU page tables */
++struct PgTableAttrs {
++      struct SYNC_CSOBJECT *hCSObj;   /* Critical section object handle */
++
++      u32 L1BasePa;           /* Physical address of the L1 PT */
++      u32 L1BaseVa;           /* Virtual  address of the L1 PT */
++      u32 L1size;             /* Size of the L1 PT */
++      u32 L1TblAllocPa;
++      /* Physical address of Allocated mem for L1 table. May not be aligned */
++      u32 L1TblAllocVa;
++      /* Virtual address of Allocated mem for L1 table. May not be aligned */
++      u32 L1TblAllocSz;
++      /* Size of consistent memory allocated for L1 table.
++       * May not be aligned */
++
++      u32 L2BasePa;           /* Physical address of the L2 PT */
++      u32 L2BaseVa;           /* Virtual  address of the L2 PT */
++      u32 L2size;             /* Size of the L2 PT */
++      u32 L2TblAllocPa;
++      /* Physical address of Allocated mem for L2 table. May not be aligned */
++      u32 L2TblAllocVa;
++      /* Virtual address of Allocated mem for L2 table. May not be aligned */
++      u32 L2TblAllocSz;
++      /* Size of consistent memory allocated for L2 table.
++       * May not be aligned */
++
++      u32 L2NumPages; /* Number of allocated L2 PT */
++      struct PageInfo *pgInfo;  /* Array [L2NumPages] of L2 PT info structs */
++} ;
++
++/*
++ *  If dsp_debug is true, do not branch to the DSP entry point and wait for DSP
++ *  to boot
++ */
++extern s32 dsp_debug;
++
++
++/*
++ *  This mini driver's function interface table.
++ */
++static struct WMD_DRV_INTERFACE drvInterfaceFxns = {
++      WCD_MAJOR_VERSION,  /* WCD ver. for which this mini driver is built. */
++      WCD_MINOR_VERSION,
++      WMD_DEV_Create,
++      WMD_DEV_Destroy,
++      WMD_DEV_Ctrl,
++      WMD_BRD_Monitor,
++      WMD_BRD_Start,
++      WMD_BRD_Stop,
++      WMD_BRD_Status,
++      WMD_BRD_Read,
++      WMD_BRD_Write,
++      WMD_BRD_SetState,
++      WMD_BRD_MemCopy,
++      WMD_BRD_MemWrite,
++      WMD_BRD_MemMap,
++      WMD_BRD_MemUnMap,
++      /* The following CHNL functions are provided by chnl_io.lib: */
++      WMD_CHNL_Create,
++      WMD_CHNL_Destroy,
++      WMD_CHNL_Open,
++      WMD_CHNL_Close,
++      WMD_CHNL_AddIOReq,
++      WMD_CHNL_GetIOC,
++      WMD_CHNL_CancelIO,
++      WMD_CHNL_FlushIO,
++      WMD_CHNL_GetInfo,
++      WMD_CHNL_GetMgrInfo,
++      WMD_CHNL_Idle,
++      WMD_CHNL_RegisterNotify,
++      /* The following DEH functions are provided by tihelen_ue_deh.c */
++      WMD_DEH_Create,
++      WMD_DEH_Destroy,
++      WMD_DEH_Notify,
++      WMD_DEH_RegisterNotify,
++      WMD_DEH_GetInfo,
++      /* The following IO functions are provided by chnl_io.lib: */
++      WMD_IO_Create,
++      WMD_IO_Destroy,
++      WMD_IO_OnLoaded,
++      WMD_IO_GetProcLoad,
++      /* The following MSG functions are provided by chnl_io.lib: */
++      WMD_MSG_Create,
++      WMD_MSG_CreateQueue,
++      WMD_MSG_Delete,
++      WMD_MSG_DeleteQueue,
++      WMD_MSG_Get,
++      WMD_MSG_Put,
++      WMD_MSG_RegisterNotify,
++      WMD_MSG_SetQueueId,
++};
++
++static inline void tlb_flush_all(const u32 base)
++{
++    __raw_writeb(__raw_readb(base + MMU_GFLUSH) | 1, base + MMU_GFLUSH);
++}
++
++static inline void flush_all(struct WMD_DEV_CONTEXT *pDevContext)
++{
++      struct CFG_HOSTRES resources;
++      u32 temp = 0;
++
++      CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++      HW_PWRST_IVA2RegGet(resources.dwPrmBase, &temp);
++
++      if ((temp & HW_PWR_STATE_ON) == HW_PWR_STATE_OFF ||
++          (temp & HW_PWR_STATE_ON) == HW_PWR_STATE_RET) {
++              CLK_Enable(SERVICESCLK_iva2_ck);
++              WakeDSP(pDevContext, NULL);
++              tlb_flush_all(pDevContext->dwDSPMmuBase);
++              CLK_Disable(SERVICESCLK_iva2_ck);
++      } else
++              tlb_flush_all(pDevContext->dwDSPMmuBase);
++}
++
++static void bad_page_dump(u32 pa, struct page *pg)
++{
++      pr_emerg("DSPBRIDGE: MAP function: COUNT 0 FOR PA 0x%x\n", pa);
++      pr_emerg("Bad page state in process '%s'\n"
++              "page:%p flags:0x%0*lx mapping:%p mapcount:%d count:%d\n"
++              "Backtrace:\n",
++              current->comm, pg, (int)(2*sizeof(unsigned long)),
++              (unsigned long)pg->flags, pg->mapping,
++              page_mapcount(pg), page_count(pg));
++      BUG();
++}
++
++/*
++ *  ======== WMD_DRV_Entry ========
++ *  purpose:
++ *      Mini Driver entry point.
++ */
++void WMD_DRV_Entry(OUT struct WMD_DRV_INTERFACE **ppDrvInterface,
++            IN CONST char *pstrWMDFileName)
++{
++
++      DBC_Require(pstrWMDFileName != NULL);
++      DBG_Trace(DBG_ENTER, "In the WMD_DRV_Entry \n");
++
++       IO_SM_init(); /* Initialization of io_sm module */
++
++       if (strcmp(pstrWMDFileName, "UMA") == 0)
++              *ppDrvInterface = &drvInterfaceFxns;
++      else
++              DBG_Trace(DBG_LEVEL7, "WMD_DRV_Entry Unknown WMD file name");
++
++}
++
++/*
++ *  ======== WMD_BRD_Monitor ========
++ *  purpose:
++ *      This WMD_BRD_Monitor puts DSP into a Loadable state.
++ *      i.e Application can load and start the device.
++ *
++ *  Preconditions:
++ *      Device in 'OFF' state.
++ */
++static DSP_STATUS WMD_BRD_Monitor(struct WMD_DEV_CONTEXT *hDevContext)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++      struct CFG_HOSTRES resources;
++      u32 temp;
++      enum HW_PwrState_t    pwrState;
++
++      DBG_Trace(DBG_ENTER, "Board in the monitor state  \n");
++      status = CFG_GetHostResources(
++               (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++      if (DSP_FAILED(status))
++              goto error_return;
++
++      GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++      HW_PWRST_IVA2RegGet(resources.dwPrmBase, &temp);
++    if ((temp & 0x03) != 0x03 || (temp & 0x03) != 0x02) {
++              /* IVA2 is not in ON state */
++              /* Read and set PM_PWSTCTRL_IVA2  to ON */
++              HW_PWR_IVA2PowerStateSet(resources.dwPrmBase,
++                                        HW_PWR_DOMAIN_DSP,
++                                        HW_PWR_STATE_ON);
++              /* Set the SW supervised state transition */
++              HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase,
++                                         HW_SW_SUP_WAKEUP);
++              /* Wait until the state has moved to ON */
++              HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++                                   &pwrState);
++              /* Disable Automatic transition */
++      HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase, HW_AUTOTRANS_DIS);
++      }
++      DBG_Trace(DBG_LEVEL6, "WMD_BRD_Monitor - Middle ****** \n");
++      GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++      status = run_IdleBoot(resources.dwPrmBase, resources.dwCmBase,
++                            resources.dwSysCtrlBase);
++      if (DSP_SUCCEEDED(status)) {
++              /* set the device state to IDLE */
++              pDevContext->dwBrdState = BRD_IDLE;
++
++      }
++error_return:
++      DBG_Trace(DBG_LEVEL6, "WMD_BRD_Monitor - End ****** \n");
++      GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++      return status;
++}
++
++/*
++ *  ======== WMD_BRD_Read ========
++ *  purpose:
++ *      Reads buffers for DSP memory.
++ */
++static DSP_STATUS WMD_BRD_Read(struct WMD_DEV_CONTEXT *hDevContext,
++                             OUT u8 *pbHostBuf, u32 dwDSPAddr,
++                             u32 ulNumBytes, u32 ulMemType)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++      u32 offset;
++      u32 dspBaseAddr = hDevContext->dwDspBaseAddr;
++
++      DBG_Trace(DBG_ENTER, "WMD_BRD_Read, pDevContext: 0x%x\n\t\tpbHostBuf:"
++                " 0x%x\n\t\tdwDSPAddr:  0x%x\n\t\tulNumBytes:  0x%x\n\t\t"
++                "ulMemType:  0x%x\n", pDevContext, pbHostBuf,
++                dwDSPAddr, ulNumBytes, ulMemType);
++      if (dwDSPAddr < pDevContext->dwDSPStartAdd) {
++              DBG_Trace(DBG_LEVEL7,
++                        "WMD_BRD_Read: DSP address < start address \n ");
++              status = DSP_EFAIL;
++              return status;
++      }
++      /* change here to account for the 3 bands of the DSP internal memory */
++      if ((dwDSPAddr - pDevContext->dwDSPStartAdd) <
++          pDevContext->dwInternalSize) {
++              offset = dwDSPAddr - pDevContext->dwDSPStartAdd;
++      } else {
++              DBG_Trace(DBG_LEVEL1,
++                        "**** Reading From external memory ****  \n ");
++              status = ReadExtDspData(pDevContext, pbHostBuf, dwDSPAddr,
++                                      ulNumBytes, ulMemType);
++              return status;
++      }
++      /* copy the data from  DSP memory, */
++      memcpy(pbHostBuf, (void *)(dspBaseAddr + offset), ulNumBytes);
++      return status;
++}
++
++/*
++ *  ======== WMD_BRD_SetState ========
++ *  purpose:
++ *      This routine updates the Board status.
++ */
++static DSP_STATUS WMD_BRD_SetState(struct WMD_DEV_CONTEXT *hDevContext,
++                                 u32 ulBrdState)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++
++      DBG_Trace(DBG_ENTER, "WMD_BRD_SetState: Board State: 0x%x \n",
++                ulBrdState);
++      pDevContext->dwBrdState = ulBrdState;
++      return status;
++}
++
++/*
++ *  ======== WMD_BRD_Start ========
++ *  purpose:
++ *      Initializes DSP MMU and Starts DSP.
++ *
++ *  Preconditions:
++ *  a) DSP domain is 'ACTIVE'.
++ *  b) DSP_RST1 is asserted.
++ *  b) DSP_RST2 is released.
++ */
++static DSP_STATUS WMD_BRD_Start(struct WMD_DEV_CONTEXT *hDevContext,
++                              u32 dwDSPAddr)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++      u32 dwSyncAddr = 0;
++      u32 ulShmBase;  /* Gpp Phys SM base addr(byte) */
++      u32 ulShmBaseVirt;      /* Dsp Virt SM base addr */
++      u32 ulTLBBaseVirt;      /* Base of MMU TLB entry */
++      u32 ulShmOffsetVirt;    /* offset of ulShmBaseVirt from ulTLBBaseVirt */
++      s32 iEntryNdx;
++      s32 itmpEntryNdx = 0;   /* DSP-MMU TLB entry base address */
++      struct CFG_HOSTRES resources;
++      u32 temp;
++      u32 ulDspClkRate;
++      u32 ulDspClkAddr;
++      u32 ulBiosGpTimer;
++      u32 uClkCmd;
++      struct IO_MGR *hIOMgr;
++      u32 ulLoadMonitorTimer;
++      u32 extClkId = 0;
++      u32 tmpIndex;
++      u32 clkIdIndex = MBX_PM_MAX_RESOURCES;
++
++      DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Start:\n hDevContext: 0x%x\n\t "
++                           "dwDSPAddr: 0x%x\n", hDevContext, dwDSPAddr);
++
++       /* The device context contains all the mmu setup info from when the
++       * last dsp base image was loaded. The first entry is always
++       * SHMMEM base. */
++      /* Get SHM_BEG - convert to byte address */
++      (void) DEV_GetSymbol(pDevContext->hDevObject, SHMBASENAME,
++                           &ulShmBaseVirt);
++      ulShmBaseVirt *= DSPWORDSIZE;
++      DBC_Assert(ulShmBaseVirt != 0);
++      /* DSP Virtual address */
++      ulTLBBaseVirt = pDevContext->aTLBEntry[0].ulDspVa;
++      DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
++      ulShmOffsetVirt = ulShmBaseVirt - (ulTLBBaseVirt * DSPWORDSIZE);
++      /* Kernel logical address */
++      ulShmBase = pDevContext->aTLBEntry[0].ulGppVa + ulShmOffsetVirt;
++
++      DBC_Assert(ulShmBase != 0);
++      /* 2nd wd is used as sync field */
++      dwSyncAddr = ulShmBase + SHMSYNCOFFSET;
++       /* Write a signature into the SHM base + offset; this will
++       * get cleared when the DSP program starts.  */
++      if ((ulShmBaseVirt == 0) || (ulShmBase == 0)) {
++              DBG_Trace(DBG_LEVEL6, "WMD_BRD_Start: Illegal SM base\n");
++              status = DSP_EFAIL;
++      } else
++              *((volatile u32 *)dwSyncAddr) = 0xffffffff;
++
++      if (DSP_SUCCEEDED(status)) {
++              status = CFG_GetHostResources(
++                      (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++                      &resources);
++              /* Assert RST1 i.e only the RST only for DSP megacell  */
++              /* HW_RST_Reset(resources.dwPrcmBase, HW_RST1_IVA2);*/
++              if (DSP_SUCCEEDED(status)) {
++                      HW_RST_Reset(resources.dwPrmBase, HW_RST1_IVA2);
++                      if (dsp_debug) {
++                              /* Set the bootmode to self loop  */
++                              DBG_Trace(DBG_LEVEL7,
++                                              "Set boot mode to self loop"
++                                              " for IVA2 Device\n");
++                              HW_DSPSS_BootModeSet(resources.dwSysCtrlBase,
++                                      HW_DSPSYSC_SELFLOOPBOOT, dwDSPAddr);
++                      } else {
++                              /* Set the bootmode to '0' - direct boot */
++                              DBG_Trace(DBG_LEVEL7,
++                                              "Set boot mode to direct"
++                                              " boot for IVA2 Device \n");
++                              HW_DSPSS_BootModeSet(resources.dwSysCtrlBase,
++                                      HW_DSPSYSC_DIRECTBOOT, dwDSPAddr);
++                      }
++              }
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Reset and Unreset the RST2, so that BOOTADDR is copied to
++               * IVA2 SYSC register */
++              HW_RST_Reset(resources.dwPrmBase, HW_RST2_IVA2);
++              udelay(100);
++              HW_RST_UnReset(resources.dwPrmBase, HW_RST2_IVA2);
++              udelay(100);
++              DBG_Trace(DBG_LEVEL6, "WMD_BRD_Start 0 ****** \n");
++              GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++              /* Disbale the DSP MMU */
++              HW_MMU_Disable(resources.dwDmmuBase);
++              /* Disable TWL */
++              HW_MMU_TWLDisable(resources.dwDmmuBase);
++
++              /* Only make TLB entry if both addresses are non-zero */
++              for (iEntryNdx = 0; iEntryNdx < WMDIOCTL_NUMOFMMUTLB;
++                      iEntryNdx++) {
++                      if ((pDevContext->aTLBEntry[iEntryNdx].ulGppPa != 0) &&
++                               (pDevContext->aTLBEntry[iEntryNdx].ulDspVa != 0)) {
++                              DBG_Trace(DBG_LEVEL4, "** (proc) MMU %d GppPa:"
++                                       " 0x%x DspVa 0x%x Size 0x%x\n",
++                                       itmpEntryNdx,
++                                       pDevContext->aTLBEntry[iEntryNdx].ulGppPa,
++                                       pDevContext->aTLBEntry[iEntryNdx].ulDspVa,
++                                       pDevContext->aTLBEntry[iEntryNdx].ulSize);
++                              configureDspMmu(pDevContext,
++                                       pDevContext->aTLBEntry[iEntryNdx].ulGppPa,
++                                       pDevContext->aTLBEntry[iEntryNdx].ulDspVa *
++                                              DSPWORDSIZE,
++                                       pDevContext->aTLBEntry[iEntryNdx].ulSize,
++                                       itmpEntryNdx,
++                                       pDevContext->aTLBEntry[iEntryNdx].endianism,
++                                       pDevContext->aTLBEntry[iEntryNdx].elemSize,
++                                       pDevContext->aTLBEntry[iEntryNdx].
++                                              mixedMode);
++                              itmpEntryNdx++;
++                      }
++              }               /* end for */
++      }
++
++      /* Lock the above TLB entries and get the BIOS and load monitor timer
++       * information*/
++      if (DSP_SUCCEEDED(status)) {
++              HW_MMU_NumLockedSet(resources.dwDmmuBase, itmpEntryNdx);
++              HW_MMU_VictimNumSet(resources.dwDmmuBase, itmpEntryNdx);
++              HW_MMU_TTBSet(resources.dwDmmuBase,
++                              pDevContext->pPtAttrs->L1BasePa);
++              HW_MMU_TWLEnable(resources.dwDmmuBase);
++              /* Enable the SmartIdle and AutoIdle bit for MMU_SYSCONFIG */
++
++              temp = (u32) *((REG_UWORD32 *)
++                              ((u32) (resources.dwDmmuBase) + 0x10));
++              temp = (temp & 0xFFFFFFEF) | 0x11;
++              *((REG_UWORD32 *) ((u32) (resources.dwDmmuBase) + 0x10)) =
++                      (u32) temp;
++
++              /* Let the DSP MMU run */
++              HW_MMU_Enable(resources.dwDmmuBase);
++
++              /* Enable the BIOS clock  */
++              (void)DEV_GetSymbol(pDevContext->hDevObject,
++                                      BRIDGEINIT_BIOSGPTIMER,
++                                   &ulBiosGpTimer);
++              DBG_Trace(DBG_LEVEL7, "BIOS GPTimer : 0x%x\n", ulBiosGpTimer);
++              (void)DEV_GetSymbol(pDevContext->hDevObject,
++                              BRIDGEINIT_LOADMON_GPTIMER,
++                                   &ulLoadMonitorTimer);
++              DBG_Trace(DBG_LEVEL7, "Load Monitor Timer : 0x%x\n",
++                        ulLoadMonitorTimer);
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              if (ulLoadMonitorTimer != 0xFFFF) {
++                      uClkCmd = (BPWR_DisableClock << MBX_PM_CLK_CMDSHIFT) |
++                                              ulLoadMonitorTimer;
++                      DBG_Trace(DBG_LEVEL7,
++                                       "encoded LoadMonitor cmd for Disable: 0x%x\n",
++                                       uClkCmd);
++                      DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++                      extClkId = uClkCmd & MBX_PM_CLK_IDMASK;
++                      for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES;
++                                       tmpIndex++) {
++                              if (extClkId == BPWR_CLKID[tmpIndex]) {
++                                      clkIdIndex = tmpIndex;
++                                      break;
++                              }
++                      }
++
++                      if (clkIdIndex < MBX_PM_MAX_RESOURCES)
++                              status = CLK_Set_32KHz(
++                                              BPWR_Clks[clkIdIndex].funClk);
++                      else
++                              status = DSP_EFAIL;
++
++                      if (DSP_FAILED(status)) {
++                              DBG_Trace(DBG_LEVEL7, " Error while setting"
++                                                      "LM Timer  to 32KHz\n");
++                      }
++                      uClkCmd = (BPWR_EnableClock << MBX_PM_CLK_CMDSHIFT) |
++                                ulLoadMonitorTimer;
++                      DBG_Trace(DBG_LEVEL7,
++                               "encoded LoadMonitor cmd for Enable : 0x%x\n",
++                               uClkCmd);
++                      DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++              } else {
++                      DBG_Trace(DBG_LEVEL7,
++                                "Not able to get the symbol for Load "
++                                "Monitor Timer\n");
++              }
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              if (ulBiosGpTimer != 0xFFFF) {
++                      uClkCmd = (BPWR_DisableClock << MBX_PM_CLK_CMDSHIFT) |
++                                                              ulBiosGpTimer;
++                      DBG_Trace(DBG_LEVEL7, "encoded BIOS GPTimer cmd for"
++                                      "Disable: 0x%x\n", uClkCmd);
++                      DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++                      extClkId = uClkCmd & MBX_PM_CLK_IDMASK;
++
++                      for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES;
++                           tmpIndex++) {
++                              if (extClkId == BPWR_CLKID[tmpIndex]) {
++                                      clkIdIndex = tmpIndex;
++                                      break;
++                              }
++                      }
++
++                      if (clkIdIndex < MBX_PM_MAX_RESOURCES)
++                              status = CLK_Set_32KHz(
++                                              BPWR_Clks[clkIdIndex].funClk);
++                      else
++                              status = DSP_EFAIL;
++
++                      if (DSP_FAILED(status)) {
++                              DBG_Trace(DBG_LEVEL7,
++                              " Error while setting BIOS Timer  to 32KHz\n");
++                      }
++
++                      uClkCmd = (BPWR_EnableClock << MBX_PM_CLK_CMDSHIFT) |
++                                 ulBiosGpTimer;
++                      DBG_Trace(DBG_LEVEL7, "encoded BIOS GPTimer cmd :"
++                                              "0x%x\n", uClkCmd);
++                      DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++              } else {
++              DBG_Trace(DBG_LEVEL7,
++                               "Not able to get the symbol for BIOS Timer\n");
++              }
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              /* Set the DSP clock rate */
++              (void)DEV_GetSymbol(pDevContext->hDevObject,
++                                      "_BRIDGEINIT_DSP_FREQ", &ulDspClkAddr);
++               /*Set Autoidle Mode for IVA2 PLL */
++               temp = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwCmBase) + 0x34));
++               temp = (temp & 0xFFFFFFFE) | 0x1;
++               *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) =
++                       (u32) temp;
++              DBG_Trace(DBG_LEVEL5, "WMD_BRD_Start: _BRIDGE_DSP_FREQ Addr:"
++                              "0x%x \n", ulDspClkAddr);
++              if ((unsigned int *)ulDspClkAddr != NULL) {
++                      /* Get the clock rate */
++                      status = CLK_GetRate(SERVICESCLK_iva2_ck,
++                               &ulDspClkRate);
++                      DBG_Trace(DBG_LEVEL5,
++                               "WMD_BRD_Start: DSP clock rate (KHZ): 0x%x \n",
++                               ulDspClkRate);
++                      (void)WMD_BRD_Write(pDevContext, (u8 *)&ulDspClkRate,
++                               ulDspClkAddr, sizeof(u32), 0);
++              }
++/*PM_IVA2GRPSEL_PER = 0xC0;*/
++               temp = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA8));
++               temp = (temp & 0xFFFFFF30) | 0xC0;
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8)) =
++                       (u32) temp;
++
++/*PM_MPUGRPSEL_PER &= 0xFFFFFF3F;*/
++               temp = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA4));
++               temp = (temp & 0xFFFFFF3F);
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4)) =
++                       (u32) temp;
++/*CM_SLEEPDEP_PER |= 0x04;*/
++               temp = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerBase) + 0x44));
++               temp = (temp & 0xFFFFFFFB) | 0x04;
++               *((REG_UWORD32 *) ((u32) (resources.dwPerBase) + 0x44)) =
++                       (u32) temp;
++
++/*CM_CLKSTCTRL_IVA2 = 0x00000003 -To Allow automatic transitions*/
++               temp = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwCmBase) + 0x48));
++               temp = (temp & 0xFFFFFFFC) | 0x03;
++               *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x48)) =
++                       (u32) temp;
++
++
++              /* Enable Mailbox events and also drain any pending
++               * stale messages */
++              (void)CHNLSM_EnableInterrupt(pDevContext);
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              HW_RSTCTRL_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++              DBG_Trace(DBG_LEVEL7, "BRD_Start: RM_RSTCTRL_DSP = 0x%x \n",
++                              temp);
++              HW_RSTST_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++              DBG_Trace(DBG_LEVEL7, "BRD_Start0: RM_RSTST_DSP = 0x%x \n",
++                              temp);
++
++              /* Let DSP go */
++              DBG_Trace(DBG_LEVEL7, "Unreset, WMD_BRD_Start\n");
++              /* Enable DSP MMU Interrupts */
++              HW_MMU_EventEnable(resources.dwDmmuBase,
++                              HW_MMU_ALL_INTERRUPTS);
++              /* release the RST1, DSP starts executing now .. */
++              HW_RST_UnReset(resources.dwPrmBase, HW_RST1_IVA2);
++
++              HW_RSTST_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++              DBG_Trace(DBG_LEVEL7, "BRD_Start: RM_RSTST_DSP = 0x%x \n",
++                              temp);
++              HW_RSTCTRL_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++              DBG_Trace(DBG_LEVEL5, "WMD_BRD_Start: CM_RSTCTRL_DSP: 0x%x \n",
++                              temp);
++              DBG_Trace(DBG_LEVEL7, "Driver waiting for Sync @ 0x%x \n",
++                              dwSyncAddr);
++              DBG_Trace(DBG_LEVEL7, "DSP c_int00 Address =  0x%x \n",
++                              dwDSPAddr);
++              if (dsp_debug)
++                      while (*((volatile u16 *)dwSyncAddr))
++                              ;;
++      }
++
++      if (DSP_SUCCEEDED(status)) {
++              /* Wait for DSP to clear word in shared memory */
++              /* Read the Location */
++              if (!WaitForStart(pDevContext, dwSyncAddr)) {
++                      status = WMD_E_TIMEOUT;
++                      DBG_Trace(DBG_LEVEL7,
++                               "WMD_BRD_Start Failed to Synchronize\n");
++              }
++              status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++              if (DSP_SUCCEEDED(status)) {
++                      IO_SHMsetting(hIOMgr, SHM_OPPINFO, NULL);
++                      DBG_Trace(DBG_LEVEL7,
++                      "WMD_BRD_Start: OPP information initialzed\n");
++                      /* Write the synchronization bit to indicate the
++                       * completion of OPP table update to DSP
++                       */
++                      *((volatile u32 *)dwSyncAddr) = 0XCAFECAFE;
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      /* update board state */
++                      pDevContext->dwBrdState = BRD_RUNNING;
++                      /* (void)CHNLSM_EnableInterrupt(pDevContext);*/
++                      DBG_Trace(DBG_LEVEL7, "Device Started \n ");
++              } else {
++                      pDevContext->dwBrdState = BRD_UNKNOWN;
++                      DBG_Trace(DBG_LEVEL7, "Device not Started \n ");
++              }
++      }
++      return status;
++}
++
++/*
++ *  ======== WMD_BRD_Stop ========
++ *  purpose:
++ *      Puts DSP in self loop.
++ *
++ *  Preconditions :
++ *  a) None
++ */
++static DSP_STATUS WMD_BRD_Stop(struct WMD_DEV_CONTEXT *hDevContext)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++      struct CFG_HOSTRES resources;
++      struct PgTableAttrs *pPtAttrs;
++      u32 dspPwrState;
++      DSP_STATUS clk_status;
++
++      DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Stop:\nhDevContext: 0x%x\n",
++                hDevContext);
++
++      /* Disable the mail box interrupts */
++      (void)CHNLSM_DisableInterrupt(pDevContext);
++
++      if (pDevContext->dwBrdState == BRD_STOPPED)
++              return status;
++
++      /* as per TRM, it is advised to first drive the IVA2 to 'Standby' mode,
++       * before turning off the clocks.. This is to ensure that there are no
++       * pending L3 or other transactons from IVA2 */
++      status = CFG_GetHostResources(
++                      (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++                      &resources);
++      if (DSP_FAILED(status)) {
++              DBG_Trace(DBG_LEVEL7,
++                        "WMD_BRD_Stop: Get Host resources failed \n");
++              DBG_Trace(DBG_LEVEL1, "Device Stopp failed \n ");
++              return DSP_EFAIL;
++      }
++
++      HW_PWRST_IVA2RegGet(resources.dwPrmBase, &dspPwrState);
++      if (dspPwrState != HW_PWR_STATE_OFF) {
++
++                      CHNLSM_InterruptDSP2(pDevContext, MBX_PM_DSPIDLE);
++
++                      mdelay(10);
++
++                      GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++
++              run_IdleBoot(resources.dwPrmBase, resources.dwCmBase,
++                           resources.dwSysCtrlBase);
++
++              udelay(50);
++
++              clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
++              if (DSP_FAILED(clk_status)) {
++                      DBG_Trace(DBG_LEVEL6,
++                               "\n WMD_BRD_Stop: CLK_Disable failed "
++                               "for iva2_fck\n");
++                      }
++              /* IVA2 is not in OFF state */
++              /* Set PM_PWSTCTRL_IVA2  to OFF */
++              HW_PWR_IVA2PowerStateSet(resources.dwPrmBase,
++                                        HW_PWR_DOMAIN_DSP,
++                                        HW_PWR_STATE_OFF);
++              /* Set the SW supervised state transition for Sleep */
++              HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase,
++                                         HW_SW_SUP_SLEEP);
++      } else {
++              clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
++              if (DSP_FAILED(clk_status)) {
++                      DBG_Trace(DBG_LEVEL6,
++                               "\n WMD_BRD_Stop: Else loop CLK_Disable failed"
++                               " for iva2_fck\n");
++              }
++      }
++      udelay(10);
++      /* Release the Ext Base virtual Address as the next DSP Program
++       * may have a different load address */
++      if (pDevContext->dwDspExtBaseAddr)
++              pDevContext->dwDspExtBaseAddr = 0;
++
++      pDevContext->dwBrdState = BRD_STOPPED;  /* update board state */
++      DBG_Trace(DBG_LEVEL1, "Device Stopped \n ");
++      /* This is a good place to clear the MMU page tables as well */
++      if (pDevContext->pPtAttrs) {
++              pPtAttrs = pDevContext->pPtAttrs;
++              memset((u8 *) pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
++              memset((u8 *) pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
++              memset((u8 *) pPtAttrs->pgInfo, 0x00,
++                     (pPtAttrs->L2NumPages * sizeof(struct PageInfo)));
++      }
++
++              DBG_Trace(DBG_LEVEL6, "WMD_BRD_Stop - End ****** \n");
++
++      return status;
++}
++
++
++/*
++ *  ======== WMD_BRD_Delete ========
++ *  purpose:
++ *      Puts DSP in Low power mode
++ *
++ *  Preconditions :
++ *  a) None
++ */
++static DSP_STATUS WMD_BRD_Delete(struct WMD_DEV_CONTEXT *hDevContext)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++      struct CFG_HOSTRES resources;
++      struct PgTableAttrs *pPtAttrs;
++      DSP_STATUS clk_status;
++
++      DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Delete:\nhDevContext: 0x%x\n",
++                hDevContext);
++
++      /* Disable the mail box interrupts */
++      (void) CHNLSM_DisableInterrupt(pDevContext);
++
++      if (pDevContext->dwBrdState == BRD_STOPPED)
++              return status;
++
++      /* as per TRM, it is advised to first drive
++       * the IVA2 to 'Standby' mode, before turning off the clocks.. This is
++       * to ensure that there are no pending L3 or other transactons from
++       * IVA2 */
++      status = CFG_GetHostResources(
++              (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++      if (DSP_FAILED(status)) {
++              DBG_Trace(DBG_LEVEL7,
++                       "WMD_BRD_Stop: Get Host resources failed \n");
++              DBG_Trace(DBG_LEVEL1, "Device Delete failed \n ");
++              return DSP_EFAIL;
++      }
++      status = SleepDSP(pDevContext, PWR_EMERGENCYDEEPSLEEP, NULL);
++      clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
++      if (DSP_FAILED(clk_status)) {
++              DBG_Trace(DBG_LEVEL6, "\n WMD_BRD_Stop: CLK_Disable failed for"
++                        " iva2_fck\n");
++      }
++      /* Release the Ext Base virtual Address as the next DSP Program
++       * may have a different load address */
++      if (pDevContext->dwDspExtBaseAddr)
++              pDevContext->dwDspExtBaseAddr = 0;
++
++      pDevContext->dwBrdState = BRD_STOPPED;  /* update board state */
++      DBG_Trace(DBG_LEVEL1, "Device Stopped \n ");
++      /* This is a good place to clear the MMU page tables as well */
++      if (pDevContext->pPtAttrs) {
++              pPtAttrs = pDevContext->pPtAttrs;
++              memset((u8 *)pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
++              memset((u8 *)pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
++              memset((u8 *)pPtAttrs->pgInfo, 0x00,
++                      (pPtAttrs->L2NumPages * sizeof(struct PageInfo)));
++      }
++      DBG_Trace(DBG_LEVEL6, "WMD_BRD_Stop - End ****** \n");
++      return status;
++}
++
++
++/*
++ *  ======== WMD_BRD_Status ========
++ *      Returns the board status.
++ */
++static DSP_STATUS WMD_BRD_Status(struct WMD_DEV_CONTEXT *hDevContext,
++                               OUT BRD_STATUS *pdwState)
++{
++      struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++      *pdwState = pDevContext->dwBrdState;
++      return DSP_SOK;
++}
++
++/*
++ *  ======== WMD_BRD_Write ========
++ *      Copies the buffers to DSP internal or external memory.
++ */
++static DSP_STATUS WMD_BRD_Write(struct WMD_DEV_CONTEXT *hDevContext,
++                              IN u8 *pbHostBuf, u32 dwDSPAddr,
++                              u32 ulNumBytes, u32 ulMemType)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++
++      DBG_Trace(DBG_ENTER, "WMD_BRD_Write, pDevContext: 0x%x\n\t\t "
++               "pbHostBuf: 0x%x\n\t\tdwDSPAddr: 0x%x\n\t\tulNumBytes: "
++               "0x%x\n \t\t ulMemtype: 0x%x\n", pDevContext, pbHostBuf,
++               dwDSPAddr, ulNumBytes, ulMemType);
++      if (dwDSPAddr < pDevContext->dwDSPStartAdd) {
++              DBG_Trace(DBG_LEVEL7,
++                       "WMD_BRD_Write: DSP address < start address \n ");
++              status = DSP_EFAIL;
++              return status;
++      }
++      if ((dwDSPAddr - pDevContext->dwDSPStartAdd) <
++         pDevContext->dwInternalSize) {
++              status = WriteDspData(hDevContext, pbHostBuf, dwDSPAddr,
++                       ulNumBytes, ulMemType);
++      } else {
++              status = WriteExtDspData(pDevContext, pbHostBuf, dwDSPAddr,
++                                       ulNumBytes, ulMemType, false);
++      }
++
++      DBG_Trace(DBG_ENTER, "WMD_BRD_Write, memcopy :  DspLogicAddr=0x%x \n",
++                      pDevContext->dwDspBaseAddr);
++      return status;
++}
++
++/*
++ *  ======== WMD_DEV_Create ========
++ *      Creates a driver object. Puts DSP in self loop.
++ */
++static DSP_STATUS WMD_DEV_Create(OUT struct WMD_DEV_CONTEXT **ppDevContext,
++                               struct DEV_OBJECT *hDevObject,
++                               IN CONST struct CFG_HOSTRES *pConfig,
++                               IN CONST struct CFG_DSPRES *pDspConfig)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *pDevContext = NULL;
++      s32 iEntryNdx;
++      s32 tcWordSwap;
++      u32 tcWordSwapSize = sizeof(tcWordSwap);
++      struct CFG_HOSTRES resources;
++      struct PgTableAttrs *pPtAttrs;
++      u32   pg_tbl_pa;
++      u32   pg_tbl_va;
++      u32   align_size;
++
++      DBG_Trace(DBG_ENTER, "WMD_DEV_Create, ppDevContext: 0x%x\n\t\t "
++                "hDevObject: 0x%x\n\t\tpConfig: 0x%x\n\t\tpDspConfig: 0x%x\n",
++                ppDevContext, hDevObject, pConfig, pDspConfig);
++       /* Allocate and initialize a data structure to contain the mini driver
++       *  state, which becomes the context for later calls into this WMD.  */
++      pDevContext = MEM_Calloc(sizeof(struct WMD_DEV_CONTEXT), MEM_NONPAGED);
++      if (!pDevContext) {
++              DBG_Trace(DBG_ENTER, "Failed to allocate mem  \n");
++              status = DSP_EMEMORY;
++              goto func_end;
++      }
++      status = CFG_GetHostResources(
++              (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++      if (DSP_FAILED(status)) {
++              DBG_Trace(DBG_ENTER, "Failed to get host resources   \n");
++              status = DSP_EMEMORY;
++              goto func_end;
++      }
++
++      pDevContext->dwDSPStartAdd = (u32)OMAP_GEM_BASE;
++      pDevContext->dwSelfLoop = (u32)NULL;
++      pDevContext->uDspPerClks = 0;
++      pDevContext->dwInternalSize = OMAP_DSP_SIZE;
++      /*  Clear dev context MMU table entries.
++       *  These get set on WMD_BRD_IOCTL() call after program loaded. */
++      for (iEntryNdx = 0; iEntryNdx < WMDIOCTL_NUMOFMMUTLB; iEntryNdx++) {
++              pDevContext->aTLBEntry[iEntryNdx].ulGppPa =
++                      pDevContext->aTLBEntry[iEntryNdx].ulDspVa = 0;
++      }
++      pDevContext->numTLBEntries = 0;
++      pDevContext->dwDspBaseAddr = (u32)MEM_LinearAddress((void *)
++                      (pConfig->dwMemBase[3]), pConfig->dwMemLength[3]);
++      if (!pDevContext->dwDspBaseAddr) {
++              status = DSP_EFAIL;
++              DBG_Trace(DBG_LEVEL7,
++                       "WMD_DEV_Create: failed to Map the API memory\n");
++      }
++      pPtAttrs = MEM_Calloc(sizeof(struct PgTableAttrs), MEM_NONPAGED);
++      if (pPtAttrs != NULL) {
++              /* Assuming that we use only DSP's memory map
++               * until 0x4000:0000 , we would need only 1024
++               * L1 enties i.e L1 size = 4K */
++              pPtAttrs->L1size = 0x1000;
++              align_size = pPtAttrs->L1size;
++              /* Align sizes are expected to be power of 2 */
++              /* we like to get aligned on L1 table size */
++              pg_tbl_va = (u32)MEM_AllocPhysMem(pPtAttrs->L1size,
++                  align_size, &pg_tbl_pa);
++      /* Check if the PA is aligned for us */
++      if ((pg_tbl_pa) & (align_size-1)) {
++                       /* PA not aligned to page table size ,
++                       * try with more allocation and align */
++                       MEM_FreePhysMem((void *)pg_tbl_va, pg_tbl_pa, pPtAttrs->L1size);
++                       /* we like to get aligned on L1 table size */
++                       pg_tbl_va = (u32) MEM_AllocPhysMem((pPtAttrs->L1size)*2,
++                       align_size, &pg_tbl_pa);
++                       /* We should be able to get aligned table now */
++                       pPtAttrs->L1TblAllocPa = pg_tbl_pa;
++                       pPtAttrs->L1TblAllocVa = pg_tbl_va;
++                       pPtAttrs->L1TblAllocSz = pPtAttrs->L1size * 2;
++                       /* Align the PA to the next 'align'  boundary */
++                       pPtAttrs->L1BasePa = ((pg_tbl_pa) + (align_size-1)) &
++                               (~(align_size-1));
++                       pPtAttrs->L1BaseVa = pg_tbl_va + (pPtAttrs->L1BasePa -
++                               pg_tbl_pa);
++      } else {
++                       /* We got aligned PA, cool */
++                       pPtAttrs->L1TblAllocPa = pg_tbl_pa;
++                       pPtAttrs->L1TblAllocVa = pg_tbl_va;
++                       pPtAttrs->L1TblAllocSz = pPtAttrs->L1size;
++                       pPtAttrs->L1BasePa = pg_tbl_pa;
++                       pPtAttrs->L1BaseVa = pg_tbl_va;
++      }
++       if (pPtAttrs->L1BaseVa)
++                       memset((u8 *)pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
++
++              /* number of L2 page tables = DMM pool used + SHMMEM +EXTMEM +
++               * L4 pages */
++              pPtAttrs->L2NumPages = ((DMMPOOLSIZE >> 20) + 6);
++              pPtAttrs->L2size = HW_MMU_COARSE_PAGE_SIZE *
++                                 pPtAttrs->L2NumPages;
++              align_size = 4; /* Make it u32 aligned  */
++              /* we like to get aligned on L1 table size */
++              pg_tbl_va = (u32)MEM_AllocPhysMem(pPtAttrs->L2size,
++                          align_size, &pg_tbl_pa);
++      pPtAttrs->L2TblAllocPa = pg_tbl_pa;
++      pPtAttrs->L2TblAllocVa = pg_tbl_va;
++      pPtAttrs->L2TblAllocSz = pPtAttrs->L2size;
++      pPtAttrs->L2BasePa = pg_tbl_pa;
++      pPtAttrs->L2BaseVa = pg_tbl_va;
++
++       if (pPtAttrs->L2BaseVa)
++                       memset((u8 *)pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
++
++      pPtAttrs->pgInfo = MEM_Calloc(pPtAttrs->L2NumPages *
++                              sizeof(struct PageInfo), MEM_NONPAGED);
++              DBG_Trace(DBG_LEVEL1, "L1 pa %x, va %x, size %x\n L2 pa %x, va "
++                       "%x, size %x\n", pPtAttrs->L1BasePa,
++                       pPtAttrs->L1BaseVa, pPtAttrs->L1size,
++                       pPtAttrs->L2BasePa, pPtAttrs->L2BaseVa,
++                       pPtAttrs->L2size);
++              DBG_Trace(DBG_LEVEL1, "pPtAttrs %x L2 NumPages %x pgInfo %x\n",
++                       pPtAttrs, pPtAttrs->L2NumPages, pPtAttrs->pgInfo);
++      }
++      if ((pPtAttrs != NULL) && (pPtAttrs->L1BaseVa != 0) &&
++         (pPtAttrs->L2BaseVa != 0) && (pPtAttrs->pgInfo != NULL))
++              pDevContext->pPtAttrs = pPtAttrs;
++      else
++              status = DSP_EMEMORY;
++
++      if (DSP_SUCCEEDED(status))
++              status = SYNC_InitializeCS(&pPtAttrs->hCSObj);
++
++      if (DSP_SUCCEEDED(status)) {
++              /* Set the Endianism Register */ /* Need to set this */
++              /* Retrieve the TC u16 SWAP Option */
++              status = REG_GetValue(NULL, CURRENTCONFIG, TCWORDSWAP,
++                                   (u8 *)&tcWordSwap, &tcWordSwapSize);
++              /* Save the value */
++              pDevContext->tcWordSwapOn = tcWordSwap;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              /* Set the Clock Divisor for the DSP module */
++              DBG_Trace(DBG_LEVEL7, "WMD_DEV_create:Reset mail box and "
++                        "enable the clock \n");
++              status = CLK_Enable(SERVICESCLK_mailbox_ick);
++              if (DSP_FAILED(status)) {
++                      DBG_Trace(DBG_LEVEL7,
++                               "WMD_DEV_create:Reset mail box and "
++                               "enable the clock Fail\n");
++              }
++              udelay(5);
++              /* 24xx-Linux MMU address is obtained from the host
++               * resources struct */
++              pDevContext->dwDSPMmuBase = resources.dwDmmuBase;
++      }
++      if (DSP_SUCCEEDED(status)) {
++              pDevContext->hDevObject = hDevObject;
++              pDevContext->ulIntMask = 0;
++              /* Store current board state. */
++              pDevContext->dwBrdState = BRD_STOPPED;
++              /* Return this ptr to our device state to the WCD for storage:*/
++              *ppDevContext = pDevContext;
++              DBG_Trace(DBG_ENTER, "Device Created \n");
++      } else {
++              if (pPtAttrs != NULL) {
++                      if (pPtAttrs->hCSObj)
++                              SYNC_DeleteCS(pPtAttrs->hCSObj);
++
++                      if (pPtAttrs->pgInfo)
++                              MEM_Free(pPtAttrs->pgInfo);
++
++                      if (pPtAttrs->L2TblAllocVa) {
++                              MEM_FreePhysMem((void *)pPtAttrs->L2TblAllocVa,
++                                              pPtAttrs->L2TblAllocPa,
++                                              pPtAttrs->L2TblAllocSz);
++                      }
++                      if (pPtAttrs->L1TblAllocVa) {
++                              MEM_FreePhysMem((void *)pPtAttrs->L1TblAllocVa,
++                                              pPtAttrs->L1TblAllocPa,
++                                              pPtAttrs->L1TblAllocSz);
++                      }
++              }
++              if (pPtAttrs)
++                      MEM_Free(pPtAttrs);
++
++              if (pDevContext)
++                      MEM_Free(pDevContext);
++
++              DBG_Trace(DBG_LEVEL7,
++                       "WMD_DEV_Create Error Device  not created\n");
++      }
++func_end:
++      return status;
++}
++
++/*
++ *  ======== WMD_DEV_Ctrl ========
++ *      Receives device specific commands.
++ */
++static DSP_STATUS WMD_DEV_Ctrl(struct WMD_DEV_CONTEXT *pDevContext, u32 dwCmd,
++                              IN OUT void *pArgs)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct WMDIOCTL_EXTPROC *paExtProc = (struct WMDIOCTL_EXTPROC *)pArgs;
++      s32 ndx;
++
++      DBG_Trace(DBG_ENTER, "WMD_DEV_Ctrl, pDevContext:  0x%x\n\t\t dwCmd:  "
++                "0x%x\n\t\tpArgs:  0x%x\n", pDevContext, dwCmd, pArgs);
++      switch (dwCmd) {
++      case WMDIOCTL_CHNLREAD:
++              break;
++      case WMDIOCTL_CHNLWRITE:
++              break;
++      case WMDIOCTL_SETMMUCONFIG:
++              /* store away dsp-mmu setup values for later use */
++              for (ndx = 0; ndx < WMDIOCTL_NUMOFMMUTLB; ndx++, paExtProc++)
++                      pDevContext->aTLBEntry[ndx] = *paExtProc;
++
++              break;
++      case WMDIOCTL_DEEPSLEEP:
++      case WMDIOCTL_EMERGENCYSLEEP:
++              /* Currently only DSP Idle is supported Need to update for
++               * later releases */
++              DBG_Trace(DBG_LEVEL5, "WMDIOCTL_DEEPSLEEP\n");
++              status = SleepDSP(pDevContext, PWR_DEEPSLEEP, pArgs);
++              break;
++      case WMDIOCTL_WAKEUP:
++              DBG_Trace(DBG_LEVEL5, "WMDIOCTL_WAKEUP\n");
++              status = WakeDSP(pDevContext, pArgs);
++              break;
++      case WMDIOCTL_CLK_CTRL:
++              DBG_Trace(DBG_LEVEL5, "WMDIOCTL_CLK_CTRL\n");
++              status = DSP_SOK;
++              /* Looking For Baseport Fix for Clocks */
++              status = DSPPeripheralClkCtrl(pDevContext, pArgs);
++              break;
++      case WMDIOCTL_PWR_HIBERNATE:
++              DBG_Trace(DBG_LEVEL5, "WMDIOCTL_PWR_HIBERNATE\n");
++              status = handle_hibernation_fromDSP(pDevContext);
++              break;
++      case WMDIOCTL_PRESCALE_NOTIFY:
++              DBG_Trace(DBG_LEVEL5, "WMDIOCTL_PRESCALE_NOTIFY\n");
++              status = PreScale_DSP(pDevContext, pArgs);
++              break;
++      case WMDIOCTL_POSTSCALE_NOTIFY:
++              DBG_Trace(DBG_LEVEL5, "WMDIOCTL_POSTSCALE_NOTIFY\n");
++              status = PostScale_DSP(pDevContext, pArgs);
++              break;
++      case WMDIOCTL_CONSTRAINT_REQUEST:
++              DBG_Trace(DBG_LEVEL5, "WMDIOCTL_CONSTRAINT_REQUEST\n");
++              status = handle_constraints_set(pDevContext, pArgs);
++              break;
++      default:
++              status = DSP_EFAIL;
++              DBG_Trace(DBG_LEVEL7, "Error in WMD_BRD_Ioctl \n");
++              break;
++      }
++      return status;
++}
++
++/*
++ *  ======== WMD_DEV_Destroy ========
++ *      Destroys the driver object.
++ */
++static DSP_STATUS WMD_DEV_Destroy(struct WMD_DEV_CONTEXT *hDevContext)
++{
++      struct PgTableAttrs *pPtAttrs;
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *pDevContext = (struct WMD_DEV_CONTEXT *)
++                                              hDevContext;
++      DBG_Trace(DBG_ENTER, "Entering WMD_DEV_Destroy:n hDevContext ::0x%x\n",
++                hDevContext);
++      /* first put the device to stop state */
++      WMD_BRD_Delete(pDevContext);
++      if (pDevContext && pDevContext->pPtAttrs) {
++              pPtAttrs = pDevContext->pPtAttrs;
++              if (pPtAttrs->hCSObj)
++                      SYNC_DeleteCS(pPtAttrs->hCSObj);
++
++              if (pPtAttrs->pgInfo)
++                      MEM_Free(pPtAttrs->pgInfo);
++
++              if (pPtAttrs->L2TblAllocVa) {
++                      MEM_FreePhysMem((void *)pPtAttrs->L2TblAllocVa,
++                                      pPtAttrs->L2TblAllocPa, pPtAttrs->
++                                      L2TblAllocSz);
++              }
++              if (pPtAttrs->L1TblAllocVa) {
++                      MEM_FreePhysMem((void *)pPtAttrs->L1TblAllocVa,
++                                      pPtAttrs->L1TblAllocPa, pPtAttrs->
++                                      L1TblAllocSz);
++              }
++              if (pPtAttrs)
++                      MEM_Free(pPtAttrs);
++
++      }
++      /* Free the driver's device context: */
++      MEM_Free((void *) hDevContext);
++      return status;
++}
++
++static DSP_STATUS WMD_BRD_MemCopy(struct WMD_DEV_CONTEXT *hDevContext,
++                                u32 ulDspDestAddr, u32 ulDspSrcAddr,
++                                u32 ulNumBytes, u32 ulMemType)
++{
++      DSP_STATUS status = DSP_SOK;
++      u32 srcAddr = ulDspSrcAddr;
++      u32 destAddr = ulDspDestAddr;
++      u32 copyBytes = 0;
++      u32 totalBytes = ulNumBytes;
++      u8 hostBuf[BUFFERSIZE];
++      struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++      while ((totalBytes > 0) && DSP_SUCCEEDED(status)) {
++              copyBytes = totalBytes > BUFFERSIZE ? BUFFERSIZE : totalBytes;
++              /* Read from External memory */
++              status = ReadExtDspData(hDevContext, hostBuf, srcAddr,
++                                      copyBytes, ulMemType);
++              if (DSP_SUCCEEDED(status)) {
++                      if (destAddr < (pDevContext->dwDSPStartAdd +
++                          pDevContext->dwInternalSize)) {
++                              /* Write to Internal memory */
++                              status = WriteDspData(hDevContext, hostBuf,
++                                       destAddr, copyBytes, ulMemType);
++                      } else {
++                              /* Write to External memory */
++                              status = WriteExtDspData(hDevContext, hostBuf,
++                                       destAddr, copyBytes, ulMemType, false);
++                      }
++              }
++              totalBytes -= copyBytes;
++              srcAddr += copyBytes;
++              destAddr += copyBytes;
++      }
++      return status;
++}
++
++/* Mem Write does not halt the DSP to write unlike WMD_BRD_Write */
++static DSP_STATUS WMD_BRD_MemWrite(struct WMD_DEV_CONTEXT *hDevContext,
++                                 IN u8 *pbHostBuf, u32 dwDSPAddr,
++                                 u32 ulNumBytes, u32 ulMemType)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++      u32 ulRemainBytes = 0;
++      u32 ulBytes = 0;
++      ulRemainBytes = ulNumBytes;
++      while (ulRemainBytes > 0 && DSP_SUCCEEDED(status)) {
++              ulBytes =
++                      ulRemainBytes > BUFFERSIZE ? BUFFERSIZE : ulRemainBytes;
++              if (dwDSPAddr < (pDevContext->dwDSPStartAdd +
++                  pDevContext->dwInternalSize)) {
++                      status = WriteDspData(hDevContext, pbHostBuf, dwDSPAddr,
++                                            ulBytes, ulMemType);
++              } else {
++                      status = WriteExtDspData(hDevContext, pbHostBuf,
++                               dwDSPAddr, ulBytes, ulMemType, true);
++              }
++              ulRemainBytes -= ulBytes;
++              dwDSPAddr += ulBytes;
++              pbHostBuf = pbHostBuf + ulBytes;
++      }
++      return status;
++}
++
++/*
++ *  ======== WMD_BRD_MemMap ========
++ *      This function maps MPU buffer to the DSP address space. It performs
++ *  linear to physical address translation if required. It translates each
++ *  page since linear addresses can be physically non-contiguous
++ *  All address & size arguments are assumed to be page aligned (in proc.c)
++ *
++ *  TODO: Disable MMU while updating the page tables (but that'll stall DSP)
++ */
++static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext,
++                               u32 ulMpuAddr, u32 ulVirtAddr,
++                               u32 ulNumBytes, u32 ulMapAttr)
++{
++      u32 attrs;
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++      struct HW_MMUMapAttrs_t hwAttrs;
++      struct vm_area_struct *vma;
++      struct mm_struct *mm = current->mm;
++      u32 write = 0;
++      u32 numUsrPgs = 0;
++      struct page *mappedPage, *pg;
++      s32 pgNum;
++      u32 va = ulVirtAddr;
++      struct task_struct *curr_task = current;
++      u32 pgI = 0;
++      u32 mpuAddr, pa;
++
++      DBG_Trace(DBG_ENTER, "> WMD_BRD_MemMap hDevContext %x, pa %x, va %x, "
++               "size %x, ulMapAttr %x\n", hDevContext, ulMpuAddr, ulVirtAddr,
++               ulNumBytes, ulMapAttr);
++      if (ulNumBytes == 0)
++              return DSP_EINVALIDARG;
++
++      if (ulMapAttr != 0) {
++              attrs = ulMapAttr;
++      } else {
++              /* Assign default attributes */
++              attrs = DSP_MAPVIRTUALADDR | DSP_MAPELEMSIZE16;
++      }
++      /* Take mapping properties */
++      if (attrs & DSP_MAPBIGENDIAN)
++              hwAttrs.endianism = HW_BIG_ENDIAN;
++      else
++              hwAttrs.endianism = HW_LITTLE_ENDIAN;
++
++      hwAttrs.mixedSize = (enum HW_MMUMixedSize_t)
++                               ((attrs & DSP_MAPMIXEDELEMSIZE) >> 2);
++      /* Ignore elementSize if mixedSize is enabled */
++      if (hwAttrs.mixedSize == 0) {
++              if (attrs & DSP_MAPELEMSIZE8) {
++                      /* Size is 8 bit */
++                      hwAttrs.elementSize = HW_ELEM_SIZE_8BIT;
++              } else if (attrs & DSP_MAPELEMSIZE16) {
++                      /* Size is 16 bit */
++                      hwAttrs.elementSize = HW_ELEM_SIZE_16BIT;
++              } else if (attrs & DSP_MAPELEMSIZE32) {
++                      /* Size is 32 bit */
++                      hwAttrs.elementSize = HW_ELEM_SIZE_32BIT;
++              } else if (attrs & DSP_MAPELEMSIZE64) {
++                      /* Size is 64 bit */
++                      hwAttrs.elementSize = HW_ELEM_SIZE_64BIT;
++              } else {
++                      /*
++                       * Mixedsize isn't enabled, so size can't be
++                       * zero here
++                       */
++                      DBG_Trace(DBG_LEVEL7,
++                               "WMD_BRD_MemMap: MMU element size is zero\n");
++                      return DSP_EINVALIDARG;
++              }
++      }
++      if (attrs & DSP_MAPDONOTLOCK)
++              hwAttrs.donotlockmpupage = 1;
++      else
++              hwAttrs.donotlockmpupage = 0;
++
++      if (attrs & DSP_MAPVMALLOCADDR) {
++              return MemMapVmalloc(hDevContext, ulMpuAddr, ulVirtAddr,
++                                     ulNumBytes, &hwAttrs);
++      }
++      /*
++       * Do OS-specific user-va to pa translation.
++       * Combine physically contiguous regions to reduce TLBs.
++       * Pass the translated pa to PteUpdate.
++       */
++      if ((attrs & DSP_MAPPHYSICALADDR)) {
++              status = PteUpdate(pDevContext, ulMpuAddr, ulVirtAddr,
++                       ulNumBytes, &hwAttrs);
++              goto func_cont;
++      }
++
++      /*
++       * Important Note: ulMpuAddr is mapped from user application process
++       * to current process - it must lie completely within the current
++       * virtual memory address space in order to be of use to us here!
++       */
++      down_read(&mm->mmap_sem);
++      vma = find_vma(mm, ulMpuAddr);
++      if (vma)
++              DBG_Trace(DBG_LEVEL6, "VMAfor UserBuf: ulMpuAddr=%x, "
++                      "ulNumBytes=%x, vm_start=%x vm_end=%x vm_flags=%x \n",
++                      ulMpuAddr, ulNumBytes, vma->vm_start,
++                      vma->vm_end, vma->vm_flags);
++
++      /*
++       * It is observed that under some circumstances, the user buffer is
++       * spread across several VMAs. So loop through and check if the entire
++       * user buffer is covered
++       */
++      while ((vma) && (ulMpuAddr + ulNumBytes > vma->vm_end)) {
++              /* jump to the next VMA region */
++              vma = find_vma(mm, vma->vm_end + 1);
++              DBG_Trace(DBG_LEVEL6, "VMAfor UserBuf ulMpuAddr=%x, "
++                       "ulNumBytes=%x, vm_start=%x vm_end=%x vm_flags=%x\n",
++                       ulMpuAddr, ulNumBytes, vma->vm_start,
++                       vma->vm_end, vma->vm_flags);
++      }
++      if (!vma) {
++              DBG_Trace(DBG_LEVEL7, "Failed to get the VMA region for "
++                        "MPU Buffer !!! \n");
++              status = DSP_EINVALIDARG;
++              up_read(&mm->mmap_sem);
++              goto func_cont;
++      }
++
++      if (vma->vm_flags & VM_IO) {
++              numUsrPgs =  ulNumBytes / PG_SIZE_4K;
++              mpuAddr = ulMpuAddr;
++              DBG_Trace(DBG_LEVEL4, "WMD_BRD_MemMap:numOfActualTabEntries=%d,"
++                        "ulNumBytes= %d\n",  numUsrPgs, ulNumBytes);
++              /* Get the physical addresses for user buffer */
++              for (pgI = 0; pgI < numUsrPgs; pgI++) {
++                      pa = user_va2pa(mm, mpuAddr);
++                      if (!pa) {
++                              status = DSP_EFAIL;
++                              pr_err("DSPBRIDGE: VM_IO mapping physical"
++                                              "address is invalid\n");
++                              break;
++                      }
++                      if (pfn_valid(__phys_to_pfn(pa))) {
++                              pg = phys_to_page(pa);
++                              get_page(pg);
++                              if (page_count(pg) < 1) {
++                                      pr_err("Bad page in VM_IO buffer\n");
++                                      bad_page_dump(pa, pg);
++                              }
++                      }
++                      status = PteSet(pDevContext->pPtAttrs, pa,
++                                      va, HW_PAGE_SIZE_4KB, &hwAttrs);
++                      if (DSP_FAILED(status)) {
++                              DBG_Trace(DBG_LEVEL7,
++                                      "WMD_BRD_MemMap: FAILED IN VM_IO"
++                                      "PTESET \n");
++                              break;
++                      }
++                      va += HW_PAGE_SIZE_4KB;
++                      mpuAddr += HW_PAGE_SIZE_4KB;
++                      pa += HW_PAGE_SIZE_4KB;
++              }
++      } else {
++              numUsrPgs =  ulNumBytes / PG_SIZE_4K;
++              if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE))
++                      write = 1;
++
++              for (pgI = 0; pgI < numUsrPgs; pgI++) {
++                      pgNum = get_user_pages(curr_task, mm, ulMpuAddr, 1,
++                                              write, 1, &mappedPage, NULL);
++                      if (pgNum > 0) {
++                              if (page_count(mappedPage) < 1) {
++                                      pr_err("Bad page count after doing"
++                                                      "get_user_pages on"
++                                                      "user buffer\n");
++                                      bad_page_dump(page_to_phys(mappedPage),
++                                                              mappedPage);
++                              }
++                              status = PteSet(pDevContext->pPtAttrs,
++                                      page_to_phys(mappedPage), va,
++                                      HW_PAGE_SIZE_4KB, &hwAttrs);
++                              if (DSP_FAILED(status)) {
++                                      DBG_Trace(DBG_LEVEL7,
++                                      "WMD_BRD_MemMap: FAILED IN PTESET \n");
++                                      break;
++                              }
++                              va += HW_PAGE_SIZE_4KB;
++                              ulMpuAddr += HW_PAGE_SIZE_4KB;
++                      } else {
++                              pr_err("DSPBRIDGE: get_user_pages FAILED,"
++                                              "MPU addr = 0x%x,"
++                                              "vma->vm_flags = 0x%lx,"
++                                              "get_user_pages Err"
++                                              "Value = %d, Buffer"
++                                              "size=0x%x\n", ulMpuAddr,
++                                              vma->vm_flags, pgNum,
++                                              ulNumBytes);
++                              status = DSP_EFAIL;
++                              break;
++                      }
++              }
++      }
++      up_read(&mm->mmap_sem);
++func_cont:
++      /* Don't propogate Linux or HW status to upper layers */
++      if (DSP_SUCCEEDED(status)) {
++              status = DSP_SOK;
++      } else {
++              DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap status %x\n", status);
++              /*
++               * Roll out the mapped pages incase it failed in middle of
++               * mapping
++               */
++              if (pgI) {
++                      WMD_BRD_MemUnMap(pDevContext, ulVirtAddr,
++                                              (pgI * PG_SIZE_4K));
++              }
++              status = DSP_EFAIL;
++      }
++      /*
++       * In any case, flush the TLB
++       * This is called from here instead from PteUpdate to avoid unnecessary
++       * repetition while mapping non-contiguous physical regions of a virtual
++       * region
++       */
++      flush_all(pDevContext);
++      DBG_Trace(DBG_ENTER, "< WMD_BRD_MemMap status %x\n", status);
++      return status;
++}
++
++/*
++ *  ======== WMD_BRD_MemUnMap ========
++ *      Invalidate the PTEs for the DSP VA block to be unmapped.
++ *
++ *      PTEs of a mapped memory block are contiguous in any page table
++ *      So, instead of looking up the PTE address for every 4K block,
++ *      we clear consecutive PTEs until we unmap all the bytes
++ */
++static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,
++                                 u32 ulVirtAddr, u32 ulNumBytes)
++{
++      u32 L1BaseVa;
++      u32 L2BaseVa;
++      u32 L2BasePa;
++      u32 L2PageNum;
++      u32 pteVal;
++      u32 pteSize;
++      u32 pteCount;
++      u32 pteAddrL1;
++      u32 pteAddrL2 = 0;
++      u32 remBytes;
++      u32 remBytesL2;
++      u32 vaCurr;
++      struct page *pg = NULL;
++      DSP_STATUS status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++      struct PgTableAttrs *pt = pDevContext->pPtAttrs;
++      u32 pacount = 0;
++      u32 *pPhysAddrPageTbl = NULL;
++      u32 temp;
++      u32 patemp = 0;
++      u32 pAddr;
++      u32 numof4KPages = 0;
++
++      DBG_Trace(DBG_ENTER, "> WMD_BRD_MemUnMap hDevContext %x, va %x, "
++                "NumBytes %x\n", hDevContext, ulVirtAddr, ulNumBytes);
++      pPhysAddrPageTbl = DMM_GetPhysicalAddrTable();
++      vaCurr = ulVirtAddr;
++      remBytes = ulNumBytes;
++      remBytesL2 = 0;
++      L1BaseVa = pt->L1BaseVa;
++      pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, vaCurr);
++      DBG_Trace(DBG_ENTER, "WMD_BRD_MemUnMap L1BaseVa %x, pteAddrL1 %x "
++                "vaCurr %x remBytes %x\n", L1BaseVa, pteAddrL1,
++                vaCurr, remBytes);
++      while (remBytes && (DSP_SUCCEEDED(status))) {
++              u32 vaCurrOrig = vaCurr;
++              /* Find whether the L1 PTE points to a valid L2 PT */
++              pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, vaCurr);
++              pteVal = *(u32 *)pteAddrL1;
++              pteSize = HW_MMU_PteSizeL1(pteVal);
++              if (pteSize == HW_MMU_COARSE_PAGE_SIZE) {
++                      /*
++                       * Get the L2 PA from the L1 PTE, and find
++                       * corresponding L2 VA
++                       */
++                      L2BasePa = HW_MMU_PteCoarseL1(pteVal);
++                      L2BaseVa = L2BasePa - pt->L2BasePa + pt->L2BaseVa;
++                      L2PageNum = (L2BasePa - pt->L2BasePa) /
++                                  HW_MMU_COARSE_PAGE_SIZE;
++                      /*
++                       * Find the L2 PTE address from which we will start
++                       * clearing, the number of PTEs to be cleared on this
++                       * page, and the size of VA space that needs to be
++                       * cleared on this L2 page
++                       */
++                      pteAddrL2 = HW_MMU_PteAddrL2(L2BaseVa, vaCurr);
++                      pteCount = pteAddrL2 & (HW_MMU_COARSE_PAGE_SIZE - 1);
++                      pteCount = (HW_MMU_COARSE_PAGE_SIZE - pteCount) /
++                                  sizeof(u32);
++                      if (remBytes < (pteCount * PG_SIZE_4K))
++                              pteCount = remBytes / PG_SIZE_4K;
++
++                      remBytesL2 = pteCount * PG_SIZE_4K;
++                      DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap L2BasePa %x, "
++                                "L2BaseVa %x pteAddrL2 %x, remBytesL2 %x\n",
++                                L2BasePa, L2BaseVa, pteAddrL2, remBytesL2);
++                      /*
++                       * Unmap the VA space on this L2 PT. A quicker way
++                       * would be to clear pteCount entries starting from
++                       * pteAddrL2. However, below code checks that we don't
++                       * clear invalid entries or less than 64KB for a 64KB
++                       * entry. Similar checking is done for L1 PTEs too
++                       * below
++                       */
++                      while (remBytesL2 && (DSP_SUCCEEDED(status))) {
++                              pteVal = *(u32 *)pteAddrL2;
++                              pteSize = HW_MMU_PteSizeL2(pteVal);
++                              /* vaCurr aligned to pteSize? */
++                              if ((pteSize != 0) && (remBytesL2 >= pteSize) &&
++                                 !(vaCurr & (pteSize - 1))) {
++                                      /* Collect Physical addresses from VA */
++                                      pAddr = (pteVal & ~(pteSize - 1));
++                                      if (pteSize == HW_PAGE_SIZE_64KB)
++                                              numof4KPages = 16;
++                                      else
++                                              numof4KPages = 1;
++                                      temp = 0;
++                                      while (temp++ < numof4KPages) {
++                                              pPhysAddrPageTbl[pacount++] =
++                                                                      pAddr;
++                                              pAddr += HW_PAGE_SIZE_4KB;
++                                      }
++                                      if (HW_MMU_PteClear(pteAddrL2,
++                                              vaCurr, pteSize) == RET_OK) {
++                                              status = DSP_SOK;
++                                              remBytesL2 -= pteSize;
++                                              vaCurr += pteSize;
++                                              pteAddrL2 += (pteSize >> 12) *
++                                                              sizeof(u32);
++                                      } else {
++                                              status = DSP_EFAIL;
++                                              goto EXIT_LOOP;
++                                      }
++                              } else {
++                                      status = DSP_EFAIL;
++                              }
++                      }
++                      SYNC_EnterCS(pt->hCSObj);
++                      if (remBytesL2 == 0) {
++                              pt->pgInfo[L2PageNum].numEntries -= pteCount;
++                              if (pt->pgInfo[L2PageNum].numEntries == 0) {
++                                      /*
++                                       * Clear the L1 PTE pointing to the
++                                       * L2 PT
++                                       */
++                                      if (RET_OK == HW_MMU_PteClear(L1BaseVa,
++                                      vaCurrOrig, HW_MMU_COARSE_PAGE_SIZE))
++                                              status = DSP_SOK;
++                                      else {
++                                              status = DSP_EFAIL;
++                                              SYNC_LeaveCS(pt->hCSObj);
++                                              goto EXIT_LOOP;
++                                      }
++                              }
++                              remBytes -= pteCount * PG_SIZE_4K;
++                      } else {
++                              status = DSP_EFAIL;
++                      }
++                      DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap L2PageNum %x, "
++                                "numEntries %x, pteCount %x, status: 0x%x\n",
++                                L2PageNum, pt->pgInfo[L2PageNum].numEntries,
++                                pteCount, status);
++                      SYNC_LeaveCS(pt->hCSObj);
++              } else
++                      /* vaCurr aligned to pteSize? */
++                      /* pteSize = 1 MB or 16 MB */
++                      if ((pteSize != 0) && (remBytes >= pteSize) &&
++                         !(vaCurr & (pteSize - 1))) {
++                              if (pteSize == HW_PAGE_SIZE_1MB)
++                                      numof4KPages = 256;
++                              else
++                                      numof4KPages = 4096;
++                              temp = 0;
++                              /* Collect Physical addresses from VA */
++                              pAddr = (pteVal & ~(pteSize - 1));
++                              while (temp++ < numof4KPages) {
++                                      pPhysAddrPageTbl[pacount++] = pAddr;
++                                      pAddr += HW_PAGE_SIZE_4KB;
++                              }
++                              if (HW_MMU_PteClear(L1BaseVa, vaCurr, pteSize)
++                                             == RET_OK) {
++                                      status = DSP_SOK;
++                                      remBytes -= pteSize;
++                                      vaCurr += pteSize;
++                              } else {
++                                      status = DSP_EFAIL;
++                                      goto EXIT_LOOP;
++                              }
++              } else {
++                      status = DSP_EFAIL;
++              }
++      }
++      /*
++       * It is better to flush the TLB here, so that any stale old entries
++       * get flushed
++       */
++EXIT_LOOP:
++      flush_all(pDevContext);
++      for (temp = 0; temp < pacount; temp++) {
++              patemp = pPhysAddrPageTbl[temp];
++              if (pfn_valid(__phys_to_pfn(patemp))) {
++                      pg = phys_to_page(patemp);
++                      if (page_count(pg) < 1) {
++                              pr_info("DSPBRIDGE:UNMAP function: COUNT 0"
++                                              "FOR PA 0x%x, size = 0x%x\n",
++                                              patemp, ulNumBytes);
++                              bad_page_dump(patemp, pg);
++                      }
++                      SetPageDirty(pg);
++                      page_cache_release(pg);
++              }
++      }
++      DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap vaCurr %x, pteAddrL1 %x "
++                "pteAddrL2 %x\n", vaCurr, pteAddrL1, pteAddrL2);
++      DBG_Trace(DBG_ENTER, "< WMD_BRD_MemUnMap status %x remBytes %x, "
++                "remBytesL2 %x\n", status, remBytes, remBytesL2);
++      return status;
++}
++
++/*
++ *  ======== user_va2pa ========
++ *  Purpose:
++ *      This function walks through the Linux page tables to convert a userland
++ *      virtual address to physical address
++ */
++static u32 user_va2pa(struct mm_struct *mm, u32 address)
++{
++      pgd_t *pgd;
++      pmd_t *pmd;
++      pte_t *ptep, pte;
++
++      pgd = pgd_offset(mm, address);
++      if (!(pgd_none(*pgd) || pgd_bad(*pgd))) {
++              pmd = pmd_offset(pgd, address);
++              if (!(pmd_none(*pmd) || pmd_bad(*pmd))) {
++                      ptep = pte_offset_map(pmd, address);
++                      if (ptep) {
++                              pte = *ptep;
++                              if (pte_present(pte))
++                                      return pte & PAGE_MASK;
++                      }
++              }
++      }
++
++      return 0;
++}
++
++
++/*
++ *  ======== PteUpdate ========
++ *      This function calculates the optimum page-aligned addresses and sizes
++ *      Caller must pass page-aligned values
++ */
++static DSP_STATUS PteUpdate(struct WMD_DEV_CONTEXT *hDevContext, u32 pa,
++                          u32 va, u32 size,
++                          struct HW_MMUMapAttrs_t *mapAttrs)
++{
++      u32 i;
++      u32 allBits;
++      u32 paCurr = pa;
++      u32 vaCurr = va;
++      u32 numBytes = size;
++      struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++      DSP_STATUS status = DSP_SOK;
++      u32 pgSize[] = { HW_PAGE_SIZE_16MB, HW_PAGE_SIZE_1MB,
++                         HW_PAGE_SIZE_64KB, HW_PAGE_SIZE_4KB };
++      DBG_Trace(DBG_ENTER, "> PteUpdate hDevContext %x, pa %x, va %x, "
++               "size %x, mapAttrs %x\n", hDevContext, pa, va, size, mapAttrs);
++      while (numBytes && DSP_SUCCEEDED(status)) {
++              /* To find the max. page size with which both PA & VA are
++               * aligned */
++              allBits = paCurr | vaCurr;
++              DBG_Trace(DBG_LEVEL1, "allBits %x, paCurr %x, vaCurr %x, "
++                       "numBytes %x ", allBits, paCurr, vaCurr, numBytes);
++              for (i = 0; i < 4; i++) {
++                      if ((numBytes >= pgSize[i]) && ((allBits &
++                         (pgSize[i] - 1)) == 0)) {
++                              DBG_Trace(DBG_LEVEL1, "pgSize %x\n", pgSize[i]);
++                              status = PteSet(pDevContext->pPtAttrs, paCurr,
++                                              vaCurr, pgSize[i], mapAttrs);
++                              paCurr += pgSize[i];
++                              vaCurr += pgSize[i];
++                              numBytes -= pgSize[i];
++                               /* Don't try smaller sizes. Hopefully we have
++                               * reached an address aligned to a bigger page
++                               * size */
++                              break;
++                      }
++              }
++      }
++      DBG_Trace(DBG_ENTER, "< PteUpdate status %x numBytes %x\n", status,
++                numBytes);
++      return status;
++}
++
++/*
++ *  ======== PteSet ========
++ *      This function calculates PTE address (MPU virtual) to be updated
++ *      It also manages the L2 page tables
++ */
++static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,
++                       u32 size, struct HW_MMUMapAttrs_t *attrs)
++{
++      u32 i;
++      u32 pteVal;
++      u32 pteAddrL1;
++      u32 pteSize;
++      u32 pgTblVa;      /* Base address of the PT that will be updated */
++      u32 L1BaseVa;
++       /* Compiler warns that the next three variables might be used
++       * uninitialized in this function. Doesn't seem so. Working around,
++       * anyways.  */
++      u32 L2BaseVa = 0;
++      u32 L2BasePa = 0;
++      u32 L2PageNum = 0;
++      DSP_STATUS status = DSP_SOK;
++      DBG_Trace(DBG_ENTER, "> PteSet pPgTableAttrs %x, pa %x, va %x, "
++               "size %x, attrs %x\n", pt, pa, va, size, attrs);
++      L1BaseVa = pt->L1BaseVa;
++      pgTblVa = L1BaseVa;
++      if ((size == HW_PAGE_SIZE_64KB) || (size == HW_PAGE_SIZE_4KB)) {
++              /* Find whether the L1 PTE points to a valid L2 PT */
++              pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, va);
++              if (pteAddrL1 <= (pt->L1BaseVa + pt->L1size)) {
++                      pteVal = *(u32 *)pteAddrL1;
++                      pteSize = HW_MMU_PteSizeL1(pteVal);
++              } else {
++                      return DSP_EFAIL;
++              }
++              SYNC_EnterCS(pt->hCSObj);
++              if (pteSize == HW_MMU_COARSE_PAGE_SIZE) {
++                      /* Get the L2 PA from the L1 PTE, and find
++                       * corresponding L2 VA */
++                      L2BasePa = HW_MMU_PteCoarseL1(pteVal);
++                      L2BaseVa = L2BasePa - pt->L2BasePa + pt->L2BaseVa;
++                      L2PageNum = (L2BasePa - pt->L2BasePa) /
++                                  HW_MMU_COARSE_PAGE_SIZE;
++              } else if (pteSize == 0) {
++                      /* L1 PTE is invalid. Allocate a L2 PT and
++                       * point the L1 PTE to it */
++                      /* Find a free L2 PT. */
++                      for (i = 0; (i < pt->L2NumPages) &&
++                          (pt->pgInfo[i].numEntries != 0); i++)
++                              ;;
++                      if (i < pt->L2NumPages) {
++                              L2PageNum = i;
++                              L2BasePa = pt->L2BasePa + (L2PageNum *
++                                         HW_MMU_COARSE_PAGE_SIZE);
++                              L2BaseVa = pt->L2BaseVa + (L2PageNum *
++                                         HW_MMU_COARSE_PAGE_SIZE);
++                              /* Endianness attributes are ignored for
++                               * HW_MMU_COARSE_PAGE_SIZE */
++                              status = HW_MMU_PteSet(L1BaseVa, L2BasePa, va,
++                                       HW_MMU_COARSE_PAGE_SIZE, attrs);
++                      } else {
++                              status = DSP_EMEMORY;
++                      }
++              } else {
++                      /* Found valid L1 PTE of another size.
++                       * Should not overwrite it. */
++                      status = DSP_EFAIL;
++              }
++              if (DSP_SUCCEEDED(status)) {
++                      pgTblVa = L2BaseVa;
++                      if (size == HW_PAGE_SIZE_64KB)
++                              pt->pgInfo[L2PageNum].numEntries += 16;
++                      else
++                              pt->pgInfo[L2PageNum].numEntries++;
++                      DBG_Trace(DBG_LEVEL1, "L2 BaseVa %x, BasePa %x, "
++                               "PageNum %x numEntries %x\n", L2BaseVa,
++                               L2BasePa, L2PageNum,
++                               pt->pgInfo[L2PageNum].numEntries);
++              }
++              SYNC_LeaveCS(pt->hCSObj);
++      }
++      if (DSP_SUCCEEDED(status)) {
++              DBG_Trace(DBG_LEVEL1, "PTE pgTblVa %x, pa %x, va %x, size %x\n",
++                       pgTblVa, pa, va, size);
++              DBG_Trace(DBG_LEVEL1, "PTE endianism %x, elementSize %x, "
++                        "mixedSize %x\n", attrs->endianism,
++                        attrs->elementSize, attrs->mixedSize);
++              status = HW_MMU_PteSet(pgTblVa, pa, va, size, attrs);
++      }
++      DBG_Trace(DBG_ENTER, "< PteSet status %x\n", status);
++      return status;
++}
++
++/* Memory map kernel VA -- memory allocated with vmalloc */
++static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *pDevContext,
++                              u32 ulMpuAddr, u32 ulVirtAddr, u32 ulNumBytes,
++                              struct HW_MMUMapAttrs_t *hwAttrs)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct page *pPage[1];
++      u32 i;
++      u32 paCurr;
++      u32 paNext;
++      u32 vaCurr;
++      u32 sizeCurr;
++      u32 numPages;
++      u32 pa;
++      u32 numOf4KPages;
++      u32 temp = 0;
++
++      DBG_Trace(DBG_ENTER, "> MemMapVmalloc hDevContext %x, pa %x, va %x, "
++                "size %x\n", pDevContext, ulMpuAddr, ulVirtAddr, ulNumBytes);
++
++      /*
++       * Do Kernel va to pa translation.
++       * Combine physically contiguous regions to reduce TLBs.
++       * Pass the translated pa to PteUpdate.
++       */
++      numPages = ulNumBytes / PAGE_SIZE; /* PAGE_SIZE = OS page size */
++      i = 0;
++      vaCurr = ulMpuAddr;
++      pPage[0] = vmalloc_to_page((void *)vaCurr);
++      paNext = page_to_phys(pPage[0]);
++      while (DSP_SUCCEEDED(status) && (i < numPages)) {
++              /*
++               * Reuse paNext from the previous iteraion to avoid
++               * an extra va2pa call
++               */
++              paCurr = paNext;
++              sizeCurr = PAGE_SIZE;
++              /*
++               * If the next page is physically contiguous,
++               * map it with the current one by increasing
++               * the size of the region to be mapped
++               */
++              while (++i < numPages) {
++                      pPage[0] = vmalloc_to_page((void *)(vaCurr + sizeCurr));
++                      paNext = page_to_phys(pPage[0]);
++                      DBG_Trace(DBG_LEVEL5, "Xlate Vmalloc VA=0x%x , "
++                               "PA=0x%x \n", (vaCurr + sizeCurr), paNext);
++                      if (paNext == (paCurr + sizeCurr))
++                              sizeCurr += PAGE_SIZE;
++                      else
++                              break;
++
++              }
++              if (paNext == 0) {
++                      status = DSP_EMEMORY;
++                      break;
++              }
++              pa = paCurr;
++              numOf4KPages = sizeCurr / HW_PAGE_SIZE_4KB;
++              while (temp++ < numOf4KPages) {
++                      get_page(phys_to_page(pa));
++                      pa += HW_PAGE_SIZE_4KB;
++              }
++              status = PteUpdate(pDevContext, paCurr, ulVirtAddr +
++                                (vaCurr - ulMpuAddr), sizeCurr, hwAttrs);
++              vaCurr += sizeCurr;
++      }
++      /* Don't propogate Linux or HW status to upper layers */
++      if (DSP_SUCCEEDED(status)) {
++              status = DSP_SOK;
++              DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap succeeded %x\n",
++                       status);
++      } else {
++              DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap status %x\n", status);
++              status = DSP_EFAIL;
++      }
++      /*
++       * In any case, flush the TLB
++       * This is called from here instead from PteUpdate to avoid unnecessary
++       * repetition while mapping non-contiguous physical regions of a virtual
++       * region
++       */
++      flush_all(pDevContext);
++      DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap at end status %x\n", status);
++      return status;
++}
++
++static DSP_STATUS run_IdleBoot(u32 prm_base, u32 cm_base,
++                             u32 sysctrl_base)
++{
++      u32 temp;
++      DSP_STATUS status = DSP_SOK;
++      enum HW_PwrState_t    pwrState;
++
++      /* Read PM_PWSTST_IVA2 */
++      HW_PWRST_IVA2RegGet(prm_base, &temp);
++       if ((temp & 0x03) != 0x03 || (temp & 0x03) != 0x02) {
++              /* IVA2 is not in ON state */
++              /* Set PM_PWSTCTRL_IVA2  to ON */
++              HW_PWR_IVA2PowerStateSet(prm_base, HW_PWR_DOMAIN_DSP,
++                                        HW_PWR_STATE_ON);
++              /* Set the SW supervised state transition */
++              HW_PWR_CLKCTRL_IVA2RegSet(cm_base, HW_SW_SUP_WAKEUP);
++              /* Wait until the state has moved to ON */
++              HW_PWR_IVA2StateGet(prm_base, HW_PWR_DOMAIN_DSP, &pwrState);
++      }
++      CLK_Disable(SERVICESCLK_iva2_ck);
++      udelay(10);
++      /* Assert IVA2-RST1 and IVA2-RST2  */
++      *((REG_UWORD32 *)((u32)(prm_base) + 0x50)) = (u32)0x07;
++      udelay(30);
++      /* set the SYSC for Idle Boot */
++      *((REG_UWORD32 *)((u32)(sysctrl_base) + 0x404)) = (u32)0x01;
++               temp = (u32) *((REG_UWORD32 *)
++                               ((u32) (cm_base) + 0x34));
++               temp = (temp & 0xFFFFFFFE) | 0x1;
++               *((REG_UWORD32 *) ((u32) (cm_base) + 0x34)) =
++                       (u32) temp;
++               temp = (u32) *((REG_UWORD32 *)
++                       ((u32) (cm_base) + 0x4));
++               temp =  (temp & 0xFFFFFC8) | 0x37;
++               *((REG_UWORD32 *) ((u32) (cm_base) + 0x4)) =
++                       (u32) temp;
++      CLK_Enable(SERVICESCLK_iva2_ck);
++      udelay(20);
++      GetHWRegs(prm_base, cm_base);
++      /* Release Reset1 and Reset2 */
++      *((REG_UWORD32 *)((u32)(prm_base) + 0x50)) = (u32)0x05;
++      udelay(20);
++      *((REG_UWORD32 *)((u32)(prm_base) + 0x50)) = (u32)0x04;
++      udelay(30);
++      return status;
++}
++
++
++void GetHWRegs(u32 prm_base, u32 cm_base)
++{
++      u32 temp;
++       temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x00));
++         DBG_Trace(DBG_LEVEL6, "CM_FCLKEN_IVA2 = 0x%x \n", temp);
++       temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x10));
++         DBG_Trace(DBG_LEVEL6, "CM_ICLKEN1_IVA2 = 0x%x \n", temp);
++       temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x20));
++         DBG_Trace(DBG_LEVEL6, "CM_IDLEST_IVA2 = 0x%x \n", temp);
++       temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x48));
++         DBG_Trace(DBG_LEVEL6, "CM_CLKSTCTRL_IVA2 = 0x%x \n", temp);
++       temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x4c));
++         DBG_Trace(DBG_LEVEL6, "CM_CLKSTST_IVA2 = 0x%x \n", temp);
++       temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0x50));
++         DBG_Trace(DBG_LEVEL6, "RM_RSTCTRL_IVA2 = 0x%x \n", temp);
++       temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0x58));
++         DBG_Trace(DBG_LEVEL6, "RM_RSTST_IVA2 = 0x%x \n", temp);
++       temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0xE0));
++         DBG_Trace(DBG_LEVEL6, "PM_PWSTCTRL_IVA2 = 0x%x \n", temp);
++       temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0xE4));
++         DBG_Trace(DBG_LEVEL6, "PM_PWSTST_IVA2 = 0x%x \n", temp);
++       temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0xA10));
++         DBG_Trace(DBG_LEVEL6, "CM_ICLKEN1_CORE = 0x%x \n", temp);
++}
++
++/*
++ *  ======== configureDspMmu ========
++ *      Make DSP MMU page table entries.
++ */
++void configureDspMmu(struct WMD_DEV_CONTEXT *pDevContext, u32 dataBasePhys,
++                  u32 dspBaseVirt, u32 sizeInBytes, s32 nEntryStart,
++                  enum HW_Endianism_t endianism,
++                  enum HW_ElementSize_t elemSize,
++                  enum HW_MMUMixedSize_t mixedSize)
++{
++      struct CFG_HOSTRES resources;
++      struct HW_MMUMapAttrs_t mapAttrs = { endianism, elemSize, mixedSize };
++      DSP_STATUS status = DSP_SOK;
++
++      DBC_Require(sizeInBytes > 0);
++      DBG_Trace(DBG_LEVEL1,
++               "configureDspMmu entry %x pa %x, va %x, bytes %x ",
++               nEntryStart, dataBasePhys, dspBaseVirt, sizeInBytes);
++
++      DBG_Trace(DBG_LEVEL1, "endianism %x, elemSize %x, mixedSize %x\n",
++               endianism, elemSize, mixedSize);
++      status = CFG_GetHostResources(
++               (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++      status = HW_MMU_TLBAdd(pDevContext->dwDSPMmuBase, dataBasePhys,
++                              dspBaseVirt, sizeInBytes, nEntryStart,
++                              &mapAttrs, HW_SET, HW_SET);
++}
++
++/*
++ *  ======== WaitForStart ========
++ *      Wait for the singal from DSP that it has started, or time out.
++ */
++bool WaitForStart(struct WMD_DEV_CONTEXT *pDevContext, u32 dwSyncAddr)
++{
++      u16 usCount = TIHELEN_ACKTIMEOUT;
++
++      /*  Wait for response from board */
++      while (*((volatile u16 *)dwSyncAddr) && --usCount)
++              udelay(10);
++
++      /*  If timed out: return FALSE */
++      if (!usCount) {
++              DBG_Trace(DBG_LEVEL7, "Timed out Waiting for DSP to Start\n");
++              return FALSE;
++      }
++      return TRUE;
++}
+diff --git a/drivers/dsp/bridge/wmd/tiomap3430_pwr.c b/drivers/dsp/bridge/wmd/tiomap3430_pwr.c
+new file mode 100644
+index 0000000..cbf6925
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap3430_pwr.c
+@@ -0,0 +1,731 @@
++/*
++ * tiomap_pwr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ *  ======== _tiomap_pwr.c ========
++ *  Description:
++ *      Implementation of DSP wake/sleep routines.
++ *
++ *! Revision History
++ *! ================
++ *! 01-Nov-2007 HK: Added Off mode(Hibernation) support and DVFS support
++ *! 05-Jan-2004 vp: Moved the file to platform specific folder and commented the
++ *!               code.
++ *! 27-Mar-2003 vp: Added support for DSP boot idle mode.
++ *! 06-Dec-2002 cring:  Added Palm support.
++ *! 08-Oct-2002 rr:  Created.
++ */
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/io_sm.h>
++#include <dspbridge/chnl_sm.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbg.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/brddefs.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/iodefs.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_dspssC64P.h>
++#include <hw_prcm.h>
++#include <hw_mmu.h>
++
++#include <dspbridge/pwr_sh.h>
++
++/*  ----------------------------------- specific to this file */
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++#include "_tiomap_util.h"
++#include <mach-omap2/prm-regbits-34xx.h>
++#include <mach-omap2/cm-regbits-34xx.h>
++
++#ifdef CONFIG_PM
++#include <mach/board-3430sdp.h>
++#endif
++extern struct MAILBOX_CONTEXT mboxsetting;
++static unsigned short enable_off_mode = 0;
++/*
++ *  ======== handle_constraints_set ========
++ *    Sets new DSP constraint
++ */
++DSP_STATUS handle_constraints_set(struct WMD_DEV_CONTEXT *pDevContext,
++                                IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++      u32 *pConstraintVal;
++       DSP_STATUS status = DSP_SOK;
++       struct CFG_HOSTRES resources;
++       struct dspbridge_platform_data *pdata =
++             omap_dspbridge_dev->dev.platform_data;
++       status = CFG_GetHostResources(
++                (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++
++      pConstraintVal = (u32 *)(pArgs);
++      /* Read the target value requested by DSP  */
++       DBG_Trace(DBG_LEVEL7, "handle_constraints_set:"
++               "opp requested = 0x%x\n", (u32)*(pConstraintVal+1));
++       status = HW_MBOX_saveSettings(resources.dwMboxBase);
++
++      /* Set the new opp value */
++      if (pdata->dsp_set_min_opp)
++                       (*pdata->dsp_set_min_opp)((u32)*(pConstraintVal+1));
++      return DSP_SOK;
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++      return DSP_SOK;
++}
++
++/*
++ *  ======== handle_hibernation_fromDSP ========
++ *    Handle Hibernation requested from DSP
++ */
++DSP_STATUS handle_hibernation_fromDSP(struct WMD_DEV_CONTEXT *pDevContext)
++{
++      DSP_STATUS status = DSP_SOK;
++#ifdef CONFIG_PM
++      u16 usCount = TIHELEN_ACKTIMEOUT;
++      struct CFG_HOSTRES resources;
++      enum HW_PwrState_t pwrState;
++#ifdef CONFIG_BRIDGE_DVFS
++      u32 opplevel;
++      struct IO_MGR *hIOMgr;
++      struct dspbridge_platform_data *pdata =
++                              omap_dspbridge_dev->dev.platform_data;
++#endif
++
++      status = CFG_GetHostResources(
++               (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++      if (DSP_FAILED(status))
++              return status;
++
++      HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++                          &pwrState);
++      /* Wait for DSP to move into Off state,  how much time should
++       * we wait? */
++      while ((pwrState != HW_PWR_STATE_OFF) && --usCount) {
++              udelay(500);
++              HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++                                  &pwrState);
++      }
++      if (usCount == 0) {
++              DBG_Trace(DBG_LEVEL7, "Timed out Waiting for DSP Off mode \n");
++              status = WMD_E_TIMEOUT;
++              return status;
++      } else {
++
++              /* Save mailbox settings */
++              status = HW_MBOX_saveSettings(resources.dwMboxBase);
++              DBG_Trace(DBG_LEVEL6, "MailBoxSettings: SYSCONFIG = 0x%x\n",
++                       mboxsetting.sysconfig);
++              DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE0 = 0x%x\n",
++                       mboxsetting.irqEnable0);
++              DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE1 = 0x%x\n",
++                       mboxsetting.irqEnable1);
++              /* Turn off DSP Peripheral clocks and DSP Load monitor timer */
++              status = DSP_PeripheralClocks_Disable(pDevContext, NULL);
++
++              if (DSP_SUCCEEDED(status)) {
++                      /* Update the Bridger Driver state */
++                      pDevContext->dwBrdState = BRD_DSP_HIBERNATION;
++#ifdef CONFIG_BRIDGE_DVFS
++                      status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++                      if (DSP_FAILED(status))
++                              return status;
++                      IO_SHMsetting(hIOMgr, SHM_GETOPP, &opplevel);
++                      /* Set the OPP to low level before moving to OFF mode */
++                      if (opplevel != VDD1_OPP1) {
++                              DBG_Trace(DBG_LEVEL5,
++                                      "Tiomap_pwr.c - DSP requested"
++                                      " OPP = %d, MPU requesting low"
++                                      " OPP %d instead\n", opplevel,
++                                      VDD1_OPP1);
++                              if (pdata->dsp_set_min_opp)
++                                      (*pdata->dsp_set_min_opp)(VDD1_OPP1);
++                              status = DSP_SOK;
++                      }
++#endif /* CONFIG_BRIDGE_DVFS */
++              } else {
++                      DBG_Trace(DBG_LEVEL7,
++                               "handle_hibernation_fromDSP- FAILED\n");
++              }
++      }
++#endif
++      return status;
++}
++
++/*
++ *  ======== SleepDSP ========
++ *    Put DSP in low power consuming state.
++ */
++DSP_STATUS SleepDSP(struct WMD_DEV_CONTEXT *pDevContext, IN u32 dwCmd,
++                 IN void *pArgs)
++{
++      DSP_STATUS status = DSP_SOK;
++#ifdef CONFIG_PM
++      struct CFG_HOSTRES resources;
++      u16 usCount = TIHELEN_ACKTIMEOUT;
++      enum HW_PwrState_t pwrState;
++      enum HW_PwrState_t targetPwrState;
++
++      status = CFG_GetHostResources(
++               (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++      if (DSP_FAILED(status))
++              return status;
++      DBG_Trace(DBG_LEVEL7, "SleepDSP- Enter function \n");
++
++              /* next, check if sleep code is valid... */
++      if ((dwCmd != PWR_DEEPSLEEP) && (dwCmd != PWR_EMERGENCYDEEPSLEEP)) {
++              DBG_Trace(DBG_LEVEL7, "SleepDSP- Illegal sleep command\n");
++              return DSP_EINVALIDARG;
++      }
++      switch (pDevContext->dwBrdState) {
++      case BRD_RUNNING:
++              status = HW_MBOX_saveSettings(resources.dwMboxBase);
++              if (enable_off_mode) {
++                      CHNLSM_InterruptDSP2(pDevContext,
++                                           MBX_PM_DSPHIBERNATE);
++                      DBG_Trace(DBG_LEVEL7,
++                               "SleepDSP - Sent hibernate "
++                               "command to DSP\n");
++                      targetPwrState = HW_PWR_STATE_OFF;
++              } else {
++                      CHNLSM_InterruptDSP2(pDevContext,
++                                           MBX_PM_DSPRETENTION);
++                      targetPwrState = HW_PWR_STATE_RET;
++              }
++              break;
++      case BRD_RETENTION:
++              status = HW_MBOX_saveSettings(resources.dwMboxBase);
++              if (enable_off_mode) {
++                      CHNLSM_InterruptDSP2(pDevContext,
++                                           MBX_PM_DSPHIBERNATE);
++                      targetPwrState = HW_PWR_STATE_OFF;
++              } else
++                      return DSP_SOK;
++              break;
++      case BRD_HIBERNATION:
++      case BRD_DSP_HIBERNATION:
++               status = HW_MBOX_saveSettings(resources.dwMboxBase);
++              /* Already in Hibernation, so just return */
++              DBG_Trace(DBG_LEVEL7, "SleepDSP- DSP already in "
++                       "hibernation\n");
++              return DSP_SOK;
++      case BRD_STOPPED:
++              DBG_Trace(DBG_LEVEL7,
++                       "SleepDSP- Board in STOP state \n");
++              return DSP_SALREADYASLEEP;
++      default:
++              DBG_Trace(DBG_LEVEL7,
++                       "SleepDSP- Bridge in Illegal state\n");
++                      return DSP_EFAIL;
++      }
++      /* Get the PRCM DSP power domain status */
++      HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++                          &pwrState);
++      /* Wait for DSP to move into Standby state,  how much time
++       * should we wait?*/
++      while ((pwrState != targetPwrState) && --usCount) {
++              udelay(500);
++              HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++                                  &pwrState);
++      }
++      if (usCount == 0) {
++              DBG_Trace(DBG_LEVEL7, "SleepDSP: Timed out Waiting for DSP"
++                       " STANDBY %x \n", pwrState);
++              return WMD_E_TIMEOUT;
++      } else {
++              DBG_Trace(DBG_LEVEL7, "SleepDSP: DSP STANDBY Pwr state %x \n",
++                       pwrState);
++              /* Update the Bridger Driver state */
++              if (enable_off_mode)
++                      pDevContext->dwBrdState = BRD_HIBERNATION;
++              else
++                      pDevContext->dwBrdState = BRD_RETENTION;
++              /* Turn off DSP Peripheral clocks  */
++              status = DSP_PeripheralClocks_Disable(pDevContext, NULL);
++              if (DSP_FAILED(status))
++                      DBG_Trace(DBG_LEVEL7, "SleepDSP- FAILED\n");
++      }
++#endif
++      return status;
++}
++
++
++/*
++ *  ======== WakeDSP ========
++ *    Wake up DSP from sleep.
++ */
++DSP_STATUS WakeDSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
++{
++      DSP_STATUS status = DSP_SOK;
++#ifdef CONFIG_PM
++      struct CFG_HOSTRES resources;
++      enum HW_PwrState_t pwrState;
++      u32 temp;
++
++      status = CFG_GetHostResources(
++               (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++      if (DSP_FAILED(status))
++              return status;
++      /* check the BRD/WMD state, if it is not 'SLEEP' then return failure */
++      if (pDevContext->dwBrdState == BRD_RUNNING ||
++              pDevContext->dwBrdState == BRD_STOPPED ||
++              pDevContext->dwBrdState == BRD_DSP_HIBERNATION) {
++              /* The Device is in 'RET' or 'OFF' state and WMD state is not
++               * 'SLEEP', this means state inconsistency, so return  */
++              status = DSP_SOK;
++              return status;
++      }
++      /* Enable the DSP peripheral clocks and load monitor timer
++       * before waking the DSP */
++      DBG_Trace(DBG_LEVEL6, "WakeDSP: enable DSP Peripheral Clks = 0x%x \n",
++               pDevContext->uDspPerClks);
++      status = DSP_PeripheralClocks_Enable(pDevContext, NULL);
++
++      /* Enabling Dppll in lock mode */
++               temp = (u32) *((REG_UWORD32 *)
++                       ((u32) (resources.dwCmBase) + 0x34));
++               temp = (temp & 0xFFFFFFFE) | 0x1;
++               *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) =
++                                               (u32) temp;
++               temp = (u32) *((REG_UWORD32 *)
++                       ((u32) (resources.dwCmBase) + 0x4));
++               temp = (temp & 0xFFFFFC8) | 0x37;
++
++               *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x4)) =
++               (u32) temp;
++
++      udelay(10);
++      if (DSP_SUCCEEDED(status)) {
++              /* Send a message to DSP to wake up */
++              CHNLSM_InterruptDSP2(pDevContext, MBX_PM_DSPWAKEUP);
++              HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++                                  &pwrState);
++              DBG_Trace(DBG_LEVEL7,
++                       "\nWakeDSP: Power State After sending Interrupt "
++                       "to DSP %x\n", pwrState);
++              /* set the device state to RUNNIG */
++              pDevContext->dwBrdState = BRD_RUNNING;
++      } else {
++              DBG_Trace(DBG_LEVEL6, "WakeDSP: FAILED\n");
++      }
++#endif
++      return status;
++}
++
++/*
++ *  ======== DSPPeripheralClkCtrl ========
++ *    Enable/Disable the DSP peripheral clocks as needed..
++ */
++DSP_STATUS DSPPeripheralClkCtrl(struct WMD_DEV_CONTEXT *pDevContext,
++                              IN void *pArgs)
++{
++      u32 extClk = 0;
++      u32 extClkId = 0;
++      u32 extClkCmd = 0;
++      u32 clkIdIndex = MBX_PM_MAX_RESOURCES;
++      u32 tmpIndex;
++      u32 dspPerClksBefore;
++      DSP_STATUS status = DSP_SOK;
++      DSP_STATUS status1 = DSP_SOK;
++
++      DBG_Trace(DBG_ENTER, "Entering DSPPeripheralClkCtrl \n");
++      dspPerClksBefore = pDevContext->uDspPerClks;
++      DBG_Trace(DBG_ENTER, "DSPPeripheralClkCtrl : uDspPerClks = 0x%x \n",
++                dspPerClksBefore);
++
++      extClk = (u32)*((u32 *)pArgs);
++
++      DBG_Trace(DBG_LEVEL3, "DSPPeripheralClkCtrl : extClk+Cmd = 0x%x \n",
++               extClk);
++
++      extClkId = extClk & MBX_PM_CLK_IDMASK;
++
++      /* process the power message -- TODO, keep it in a separate function */
++      for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES; tmpIndex++) {
++              if (extClkId == BPWR_CLKID[tmpIndex]) {
++                      clkIdIndex = tmpIndex;
++                      break;
++              }
++      }
++      /* TODO -- Assert may be a too hard restriction here.. May be we should
++       * just return with failure when the CLK ID does not match */
++      /* DBC_Assert(clkIdIndex < MBX_PM_MAX_RESOURCES);*/
++      if (clkIdIndex == MBX_PM_MAX_RESOURCES) {
++              DBG_Trace(DBG_LEVEL7,
++                       "DSPPeripheralClkCtrl : Could n't get clock Id for"
++                       "clkid 0x%x \n", clkIdIndex);
++              /* return with a more meaningfull error code */
++              return DSP_EFAIL;
++      }
++      extClkCmd = (extClk >> MBX_PM_CLK_CMDSHIFT) & MBX_PM_CLK_CMDMASK;
++      switch (extClkCmd) {
++      case BPWR_DisableClock:
++              /* Call BP to disable the needed clock */
++              DBG_Trace(DBG_LEVEL3,
++                       "DSPPeripheralClkCtrl : Disable CLK for \n");
++              status1 = CLK_Disable(BPWR_Clks[clkIdIndex].intClk);
++              status = CLK_Disable(BPWR_Clks[clkIdIndex].funClk);
++               DSPClkWakeupEventCtrl(BPWR_Clks[clkIdIndex].clkId, false);
++              if ((DSP_SUCCEEDED(status)) && (DSP_SUCCEEDED(status1))) {
++                      (pDevContext->uDspPerClks) &=
++                              (~((u32) (1 << clkIdIndex)));
++              } else {
++                      DBG_Trace(DBG_LEVEL7, "DSPPeripheralClkCtrl : Failed "
++                               "to disable clk\n");
++              }
++              break;
++      case BPWR_EnableClock:
++              DBG_Trace(DBG_LEVEL3,
++                       "DSPPeripheralClkCtrl : Enable CLK for \n");
++              status1 = CLK_Enable(BPWR_Clks[clkIdIndex].intClk);
++              status = CLK_Enable(BPWR_Clks[clkIdIndex].funClk);
++               DSPClkWakeupEventCtrl(BPWR_Clks[clkIdIndex].clkId, true);
++              if ((DSP_SUCCEEDED(status)) && (DSP_SUCCEEDED(status1))) {
++                      (pDevContext->uDspPerClks) |= (1 << clkIdIndex);
++              } else {
++                      DBG_Trace(DBG_LEVEL7,
++                               "DSPPeripheralClkCtrl:Failed to Enable clk\n");
++              }
++              break;
++      default:
++              DBG_Trace(DBG_LEVEL3,
++                       "DSPPeripheralClkCtrl : Unsupported CMD \n");
++              /* unsupported cmd */
++              /* TODO -- provide support for AUTOIDLE Enable/Disable
++               * commands */
++      }
++      return status;
++}
++
++/*
++ *  ========PreScale_DSP========
++ *  Sends prescale notification to DSP
++ *
++ */
++DSP_STATUS PreScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++      u32 level;
++      u32 voltage_domain;
++
++      voltage_domain = *((u32 *)pArgs);
++      level = *((u32 *)pArgs + 1);
++
++      DBG_Trace(DBG_LEVEL7, "PreScale_DSP: voltage_domain = %x, level = "
++               "0x%x\n", voltage_domain, level);
++       if ((pDevContext->dwBrdState == BRD_HIBERNATION) ||
++               (pDevContext->dwBrdState == BRD_RETENTION) ||
++               (pDevContext->dwBrdState == BRD_DSP_HIBERNATION)) {
++              DBG_Trace(DBG_LEVEL7, "PreScale_DSP: IVA in sleep. "
++                       "No notification to DSP\n");
++              return DSP_SOK;
++       } else if ((pDevContext->dwBrdState == BRD_RUNNING)) {
++              /* Send a prenotificatio to DSP */
++              DBG_Trace(DBG_LEVEL7,
++                       "PreScale_DSP: Sent notification to DSP\n");
++              CHNLSM_InterruptDSP2(pDevContext, MBX_PM_SETPOINT_PRENOTIFY);
++              return DSP_SOK;
++      } else {
++              DBG_Trace(DBG_LEVEL7, "PreScale_DSP: Failed - DSP BRD"
++                        " state in wrong state");
++              return DSP_EFAIL;
++      }
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++      return DSP_SOK;
++}
++
++/*
++ *  ========PostScale_DSP========
++ *  Sends postscale notification to DSP
++ *
++ */
++DSP_STATUS PostScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++      u32 level;
++      u32 voltage_domain;
++      struct IO_MGR *hIOMgr;
++      DSP_STATUS status = DSP_SOK;
++
++      status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++
++      voltage_domain = *((u32 *)pArgs);
++      level = *((u32 *)pArgs + 1);
++      DBG_Trace(DBG_LEVEL7,
++               "PostScale_DSP: voltage_domain = %x, level = 0x%x\n",
++               voltage_domain, level);
++       if ((pDevContext->dwBrdState == BRD_HIBERNATION) ||
++                       (pDevContext->dwBrdState == BRD_RETENTION) ||
++                       (pDevContext->dwBrdState == BRD_DSP_HIBERNATION)) {
++              /* Update the OPP value in shared memory */
++              IO_SHMsetting(hIOMgr, SHM_CURROPP, &level);
++              DBG_Trace(DBG_LEVEL7,
++                       "PostScale_DSP: IVA in sleep. Wrote to shared "
++                       "memory \n");
++              return DSP_SOK;
++      } else  if ((pDevContext->dwBrdState == BRD_RUNNING)) {
++              /* Update the OPP value in shared memory */
++              IO_SHMsetting(hIOMgr, SHM_CURROPP, &level);
++              /* Send a post notification to DSP */
++              CHNLSM_InterruptDSP2(pDevContext, MBX_PM_SETPOINT_POSTNOTIFY);
++              DBG_Trace(DBG_LEVEL7,
++                       "PostScale_DSP: Wrote to shared memory Sent post"
++                       " notification to DSP\n");
++              return DSP_SOK;
++      } else {
++              DBG_Trace(DBG_LEVEL7, "PostScale_DSP: Failed - DSP BRD state "
++                       "in wrong state");
++              return DSP_EFAIL;
++      }
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++      return DSP_SOK;
++}
++
++/*
++ *  ========DSP_PeripheralClocks_Disable========
++ *  Disables all the peripheral clocks that were requested by DSP
++ */
++DSP_STATUS DSP_PeripheralClocks_Disable(struct WMD_DEV_CONTEXT *pDevContext,
++                                      IN void *pArgs)
++{
++
++      u32 clkIdx;
++      DSP_STATUS status = DSP_SOK;
++
++      for (clkIdx = 0; clkIdx < MBX_PM_MAX_RESOURCES; clkIdx++) {
++              if (((pDevContext->uDspPerClks) >> clkIdx) & 0x01) {
++                      /* Disables the interface clock of the peripheral */
++                      status = CLK_Disable(BPWR_Clks[clkIdx].intClk);
++                      if (DSP_FAILED(status)) {
++                              DBG_Trace(DBG_LEVEL7,
++                                       "Failed to Enable the DSP Peripheral"
++                                       "Clk 0x%x \n", BPWR_Clks[clkIdx]);
++                      }
++                      /* Disables the functional clock of the periphearl */
++                      status = CLK_Disable(BPWR_Clks[clkIdx].funClk);
++                      if (DSP_FAILED(status)) {
++                              DBG_Trace(DBG_LEVEL7,
++                                       "Failed to Enable the DSP Peripheral"
++                                       "Clk 0x%x \n", BPWR_Clks[clkIdx]);
++                      }
++              }
++      }
++      return status;
++}
++
++/*
++ *  ========DSP_PeripheralClocks_Enable========
++ *  Enables all the peripheral clocks that were requested by DSP
++ */
++DSP_STATUS DSP_PeripheralClocks_Enable(struct WMD_DEV_CONTEXT *pDevContext,
++                                    IN void *pArgs)
++{
++      u32 clkIdx;
++      DSP_STATUS int_clk_status = DSP_EFAIL, fun_clk_status = DSP_EFAIL;
++
++      for (clkIdx = 0; clkIdx < MBX_PM_MAX_RESOURCES; clkIdx++) {
++              if (((pDevContext->uDspPerClks) >> clkIdx) & 0x01) {
++                      /* Enable the interface clock of the peripheral */
++                      int_clk_status = CLK_Enable(BPWR_Clks[clkIdx].intClk);
++                      /* Enable the functional clock of the periphearl */
++                      fun_clk_status = CLK_Enable(BPWR_Clks[clkIdx].funClk);
++              }
++      }
++      if ((int_clk_status | fun_clk_status) != DSP_SOK)
++              return DSP_EFAIL;
++      return DSP_SOK;
++}
++
++void DSPClkWakeupEventCtrl(u32 ClkId, bool enable)
++{
++       struct CFG_HOSTRES resources;
++       DSP_STATUS status = DSP_SOK;
++       u32 iva2_grpsel;
++       u32 mpu_grpsel;
++
++       status = CFG_GetHostResources(
++                (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++       if (DSP_FAILED(status))
++               return;
++
++       switch (ClkId) {
++       case BPWR_GPTimer5:
++               iva2_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA8));
++               mpu_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA4));
++               if (enable) {
++                       iva2_grpsel |= OMAP3430_GRPSEL_GPT5;
++                       mpu_grpsel &= ~OMAP3430_GRPSEL_GPT5;
++               } else {
++                       mpu_grpsel |= OMAP3430_GRPSEL_GPT5;
++                       iva2_grpsel &= ~OMAP3430_GRPSEL_GPT5;
++               }
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++                               = iva2_grpsel;
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++                               = mpu_grpsel;
++       break;
++       case BPWR_GPTimer6:
++               iva2_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA8));
++               mpu_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA4));
++               if (enable) {
++                       iva2_grpsel |= OMAP3430_GRPSEL_GPT6;
++                       mpu_grpsel &= ~OMAP3430_GRPSEL_GPT6;
++               } else {
++                       mpu_grpsel |= OMAP3430_GRPSEL_GPT6;
++                       iva2_grpsel &= ~OMAP3430_GRPSEL_GPT6;
++               }
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++                                                       = iva2_grpsel;
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++                                                       = mpu_grpsel;
++       break;
++       case BPWR_GPTimer7:
++               iva2_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA8));
++               mpu_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA4));
++               if (enable) {
++                       iva2_grpsel |= OMAP3430_GRPSEL_GPT7;
++                       mpu_grpsel &= ~OMAP3430_GRPSEL_GPT7;
++               } else {
++                       mpu_grpsel |= OMAP3430_GRPSEL_GPT7;
++                       iva2_grpsel &= ~OMAP3430_GRPSEL_GPT7;
++               }
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++                                                       = iva2_grpsel;
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++                                                       = mpu_grpsel;
++       break;
++       case BPWR_GPTimer8:
++               iva2_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA8));
++               mpu_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA4));
++               if (enable) {
++                       iva2_grpsel |= OMAP3430_GRPSEL_GPT8;
++                       mpu_grpsel &= ~OMAP3430_GRPSEL_GPT8;
++               } else {
++                       mpu_grpsel |= OMAP3430_GRPSEL_GPT8;
++                       iva2_grpsel &= ~OMAP3430_GRPSEL_GPT8;
++               }
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++                                                       = iva2_grpsel;
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++                                                       = mpu_grpsel;
++       break;
++       case BPWR_MCBSP1:
++               iva2_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwCorePmBase) + 0xA8));
++               mpu_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwCorePmBase) + 0xA4));
++               if (enable) {
++                       iva2_grpsel |= OMAP3430_GRPSEL_MCBSP1;
++                       mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP1;
++               } else {
++                       mpu_grpsel |= OMAP3430_GRPSEL_MCBSP1;
++                       iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP1;
++               }
++               *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA8))
++                                                       = iva2_grpsel;
++               *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA4))
++                                                       = mpu_grpsel;
++       break;
++       case BPWR_MCBSP2:
++               iva2_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA8));
++               mpu_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA4));
++               if (enable) {
++                       iva2_grpsel |= OMAP3430_GRPSEL_MCBSP2;
++                       mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP2;
++               } else {
++                       mpu_grpsel |= OMAP3430_GRPSEL_MCBSP2;
++                       iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP2;
++               }
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++                                                       = iva2_grpsel;
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++                                                       = mpu_grpsel;
++       break;
++       case BPWR_MCBSP3:
++               iva2_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA8));
++               mpu_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA4));
++               if (enable) {
++                       iva2_grpsel |= OMAP3430_GRPSEL_MCBSP3;
++                       mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP3;
++               } else {
++                       mpu_grpsel |= OMAP3430_GRPSEL_MCBSP3;
++                       iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP3;
++               }
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++                                                       = iva2_grpsel;
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++                                                       = mpu_grpsel;
++       break;
++       case BPWR_MCBSP4:
++               iva2_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA8));
++               mpu_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwPerPmBase) + 0xA4));
++               if (enable) {
++                       iva2_grpsel |= OMAP3430_GRPSEL_MCBSP4;
++                       mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP4;
++               } else {
++                       mpu_grpsel |= OMAP3430_GRPSEL_MCBSP4;
++                       iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP4;
++               }
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++                                                       = iva2_grpsel;
++               *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++                                                       = mpu_grpsel;
++       break;
++       case BPWR_MCBSP5:
++               iva2_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwCorePmBase) + 0xA8));
++               mpu_grpsel = (u32) *((REG_UWORD32 *)
++                               ((u32) (resources.dwCorePmBase) + 0xA4));
++               if (enable) {
++                       iva2_grpsel |= OMAP3430_GRPSEL_MCBSP5;
++                       mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP5;
++               } else {
++                       mpu_grpsel |= OMAP3430_GRPSEL_MCBSP5;
++                       iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP5;
++               }
++               *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA8))
++                                                       = iva2_grpsel;
++               *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA4))
++                                                       = mpu_grpsel;
++       break;
++       }
++}
+diff --git a/drivers/dsp/bridge/wmd/tiomap_io.c b/drivers/dsp/bridge/wmd/tiomap_io.c
+new file mode 100644
+index 0000000..6121e8f
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap_io.c
+@@ -0,0 +1,427 @@
++/*
++ * tiomap_io.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== _tiomap_io.c ========
++ *  Description:
++ *      Implementation for the io read/write routines.
++ *
++ *! Revision History
++ *! ================
++ *! 16-Feb-2004 vp:  Fixed warning in WriteDspData function.
++ *! 16-Apr-2003 vp:  Added support for TC word swap
++ *! 26-Feb-2003 vp:  Fixed issue with EXT_BEG and EXT_END address.
++ *! 24-Feb-2003 vp:  Ported to Linux platform
++ *! 08-Oct-2002 rr:  Created.
++ */
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/drv.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++#include <dspbridge/cfg.h>
++
++/*  ----------------------------------- specific to this file */
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++#include "tiomap_io.h"
++
++static u32 ulExtBase;
++static u32 ulExtEnd;
++
++static u32 ulShm0End;
++static u32 ulDynExtBase;
++static u32 ulTraceSecBeg;
++static u32 ulTraceSecEnd;
++static u32 ulShmBaseVirt;
++
++bool bSymbolsReloaded = true;
++
++/*
++ *  ======== ReadExtDspData ========
++ *      Copies DSP external memory buffers to the host side buffers.
++ */
++DSP_STATUS ReadExtDspData(struct WMD_DEV_CONTEXT *hDevContext,
++                       OUT u8 *pbHostBuf, u32 dwDSPAddr,
++                       u32 ulNumBytes, u32 ulMemType)
++{
++      DSP_STATUS      status = DSP_SOK;
++      struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++      u32     offset;
++      u32     ulTLBBaseVirt = 0;
++      u32     ulShmOffsetVirt = 0;
++      u32     dwExtProgVirtMem;
++      u32     dwBaseAddr = pDevContext->dwDspExtBaseAddr;
++      bool    bTraceRead = false;
++
++      DBG_Trace(DBG_ENTER, "ReadExtDspData,"
++      "hDevContext: 0x%x\n\t\tpbHostBuf: 0x%x"
++      "\n\t\tdwDSPAddr:  0x%x\n\t\tulNumBytes:  0x%x\n\t\t"
++      "ulMemType:  0x%x\n", pDevContext, pbHostBuf, dwDSPAddr,
++      ulNumBytes, ulMemType);
++
++      if (!ulShmBaseVirt) {
++              status = DEV_GetSymbol(pDevContext->hDevObject,
++              SHMBASENAME, &ulShmBaseVirt);
++      }
++      DBC_Assert(ulShmBaseVirt != 0);
++
++      /* Check if it is a read of Trace section */
++      if (!ulTraceSecBeg) {
++              status = DEV_GetSymbol(pDevContext->hDevObject,
++              DSP_TRACESEC_BEG, &ulTraceSecBeg);
++      }
++      DBC_Assert(ulTraceSecBeg != 0);
++
++      if (DSP_SUCCEEDED(status) && !ulTraceSecEnd) {
++              status = DEV_GetSymbol(pDevContext->hDevObject,
++              DSP_TRACESEC_END, &ulTraceSecEnd);
++      }
++      DBC_Assert(ulTraceSecEnd != 0);
++
++      if (DSP_SUCCEEDED(status)) {
++              if ((dwDSPAddr <= ulTraceSecEnd) &&
++                      (dwDSPAddr >= ulTraceSecBeg)) {
++                      DBG_Trace(DBG_LEVEL5, "Reading from DSP Trace"
++                               "section 0x%x \n", dwDSPAddr);
++                      bTraceRead = true;
++              }
++      }
++
++      /* If reading from TRACE, force remap/unmap */
++      if ((bTraceRead) && dwBaseAddr) {
++              dwBaseAddr = 0;
++              pDevContext->dwDspExtBaseAddr = 0;
++      }
++
++      if (!dwBaseAddr) {
++              /* Initialize ulExtBase and ulExtEnd */
++              ulExtBase = 0;
++              ulExtEnd = 0;
++
++              /* Get DYNEXT_BEG, EXT_BEG and EXT_END.*/
++              if (DSP_SUCCEEDED(status) && !ulDynExtBase) {
++                      status = DEV_GetSymbol(pDevContext->hDevObject,
++                                      DYNEXTBASE, &ulDynExtBase);
++              }
++              DBC_Assert(ulDynExtBase != 0);
++
++              if (DSP_SUCCEEDED(status)) {
++                      status = DEV_GetSymbol(pDevContext->hDevObject,
++                               EXTBASE, &ulExtBase);
++              }
++              DBC_Assert(ulExtBase != 0);
++
++              if (DSP_SUCCEEDED(status)) {
++                      status = DEV_GetSymbol(pDevContext->hDevObject,
++                                      EXTEND, &ulExtEnd);
++              }
++              DBC_Assert(ulExtEnd != 0);
++
++      /* Trace buffer is right after the SHM SEG0,
++      *  so set the base address to SHMBASE */
++              if (bTraceRead) {
++                      ulExtBase = ulShmBaseVirt;
++                      ulExtEnd = ulTraceSecEnd;
++              }
++
++              DBC_Assert(ulExtEnd != 0);
++              DBC_Assert(ulExtEnd > ulExtBase);
++
++              if (ulExtEnd < ulExtBase)
++                      status = DSP_EFAIL;
++
++              if (DSP_SUCCEEDED(status)) {
++                      ulTLBBaseVirt =
++                      pDevContext->aTLBEntry[0].ulDspVa * DSPWORDSIZE;
++                      DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
++                      dwExtProgVirtMem = pDevContext->aTLBEntry[0].ulGppVa;
++
++                      if (bTraceRead) {
++                              DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
++                              "GPP VA pointing to SHMMEMBASE 0x%x \n",
++                               dwExtProgVirtMem);
++                      } else {
++                              ulShmOffsetVirt = ulShmBaseVirt - ulTLBBaseVirt;
++                              ulShmOffsetVirt += PG_ALIGN_HIGH(ulExtEnd -
++                                              ulDynExtBase + 1,
++                                              HW_PAGE_SIZE_64KB);
++                              dwExtProgVirtMem -= ulShmOffsetVirt;
++                              dwExtProgVirtMem += (ulExtBase - ulDynExtBase);
++                              DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
++                              "GPP VA pointing to EXTMEMBASE 0x%x \n",
++                              dwExtProgVirtMem);
++                              pDevContext->dwDspExtBaseAddr =
++                                              dwExtProgVirtMem;
++
++      /* This dwDspExtBaseAddr will get cleared only when the board is
++      * stopped. */
++                              if (!pDevContext->dwDspExtBaseAddr) {
++                                      status = DSP_EFAIL;
++                                      DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
++                                      "failed to Map the program memory\n");
++                              }
++                      }
++
++                      dwBaseAddr = dwExtProgVirtMem;
++              }
++      }
++
++      if (!dwBaseAddr || !ulExtBase || !ulExtEnd) {
++              DBG_Trace(DBG_LEVEL7,
++              "Symbols missing for Ext Prog reading \n");
++              status = DSP_EFAIL;
++      }
++
++      offset = dwDSPAddr - ulExtBase;
++
++      if (DSP_SUCCEEDED(status))
++              memcpy(pbHostBuf, (u8 *)dwBaseAddr+offset, ulNumBytes);
++
++      return status;
++}
++/*
++ *  ======== WriteDspData ========
++ *  purpose:
++ *      Copies buffers to the DSP internal/external memory.
++ */
++DSP_STATUS WriteDspData(struct WMD_DEV_CONTEXT *hDevContext, IN u8 *pbHostBuf,
++                      u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType)
++{
++      u32 offset;
++      u32 dwBaseAddr = hDevContext->dwDspBaseAddr;
++      struct CFG_HOSTRES resources;
++      DSP_STATUS status;
++      u32 base1, base2, base3;
++      base1 = OMAP_DSP_MEM1_SIZE;
++      base2 = OMAP_DSP_MEM2_BASE - OMAP_DSP_MEM1_BASE;
++      base3 = OMAP_DSP_MEM3_BASE - OMAP_DSP_MEM1_BASE;
++      DBG_Trace(DBG_ENTER, "Entered WriteDspData \n");
++
++      status =  CFG_GetHostResources(
++               (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++
++      offset = dwDSPAddr - hDevContext->dwDSPStartAdd;
++      if (offset < base1) {
++              dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[2],
++                                              resources.dwMemLength[2]);
++      } else if (offset > base1 && offset < base2+OMAP_DSP_MEM2_SIZE) {
++              dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[3],
++                                              resources.dwMemLength[3]);
++              offset = offset - base2;
++      } else if (offset >= base2+OMAP_DSP_MEM2_SIZE &&
++              offset < base3 + OMAP_DSP_MEM3_SIZE) {
++              dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[4],
++                                              resources.dwMemLength[4]);
++              offset = offset - base3;
++      } else{
++              status = DSP_EFAIL;
++              return status;
++      }
++      if (ulNumBytes)
++              memcpy((u8 *) (dwBaseAddr+offset), pbHostBuf, ulNumBytes);
++      else
++              *((u32 *) pbHostBuf) = dwBaseAddr+offset;
++
++      return status;
++}
++
++/*
++ *  ======== WriteExtDspData ========
++ *  purpose:
++ *      Copies buffers to the external memory.
++ *
++ */
++DSP_STATUS WriteExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
++                        IN u8 *pbHostBuf, u32 dwDSPAddr, u32 ulNumBytes,
++                        u32 ulMemType, bool bDynamicLoad)
++{
++      u32 dwBaseAddr = pDevContext->dwDspExtBaseAddr;
++      u32 dwOffset = 0;
++      u8 bTempByte1, bTempByte2;
++      u8 remainByte[4];
++      s32 i;
++      DSP_STATUS retVal = DSP_SOK;
++      u32 dwExtProgVirtMem;
++      u32 ulTLBBaseVirt = 0;
++      u32 ulShmOffsetVirt = 0;
++      struct CFG_HOSTRES hostRes;
++      bool bTraceLoad = false;
++      bTempByte1 = 0x0;
++      bTempByte2 = 0x0;
++
++      DBG_Trace(DBG_ENTER, "Entered WriteExtDspData dwDSPAddr 0x%x "
++               "ulNumBytes 0x%x \n", dwDSPAddr, ulNumBytes);
++        if (bSymbolsReloaded) {
++              /* Check if it is a load to Trace section */
++              retVal = DEV_GetSymbol(pDevContext->hDevObject,
++                                      DSP_TRACESEC_BEG, &ulTraceSecBeg);
++              if (DSP_SUCCEEDED(retVal))
++                      retVal = DEV_GetSymbol(pDevContext->hDevObject,
++                               DSP_TRACESEC_END, &ulTraceSecEnd);
++      }
++      if (DSP_SUCCEEDED(retVal)) {
++              if ((dwDSPAddr <= ulTraceSecEnd) &&
++                 (dwDSPAddr >= ulTraceSecBeg)) {
++                      DBG_Trace(DBG_LEVEL5, "Writing to DSP Trace "
++                               "section 0x%x \n", dwDSPAddr);
++                      bTraceLoad = true;
++              }
++      }
++
++      /* If dynamic, force remap/unmap */
++      if ((bDynamicLoad || bTraceLoad) && dwBaseAddr) {
++              dwBaseAddr = 0;
++              MEM_UnmapLinearAddress((void *)pDevContext->dwDspExtBaseAddr);
++              pDevContext->dwDspExtBaseAddr = 0x0;
++      }
++      if (!dwBaseAddr) {
++              if (bSymbolsReloaded)
++                      /* Get SHM_BEG  EXT_BEG and EXT_END. */
++                      retVal = DEV_GetSymbol(pDevContext->hDevObject,
++                                              SHMBASENAME, &ulShmBaseVirt);
++              DBC_Assert(ulShmBaseVirt != 0);
++              if (bDynamicLoad) {
++                      if (DSP_SUCCEEDED(retVal)) {
++                              if (bSymbolsReloaded)
++                                      retVal = DEV_GetSymbol(pDevContext->
++                                              hDevObject, DYNEXTBASE,
++                                              &ulExtBase);
++                      }
++                      DBC_Assert(ulExtBase != 0);
++                      if (DSP_SUCCEEDED(retVal)) {
++                              /* DR  OMAPS00013235 : DLModules array may be
++                               * in EXTMEM. It is expected that DYNEXTMEM and
++                               * EXTMEM are contiguous, so checking for the
++                               * upper bound at EXTEND should be Ok. */
++                              if (bSymbolsReloaded)
++                                      retVal = DEV_GetSymbol(pDevContext->
++                                              hDevObject, EXTEND, &ulExtEnd);
++                      }
++              } else {
++                      if (bSymbolsReloaded) {
++                              if (DSP_SUCCEEDED(retVal))
++                                      retVal = DEV_GetSymbol(pDevContext->
++                                              hDevObject, EXTBASE,
++                                              &ulExtBase);
++                              DBC_Assert(ulExtBase != 0);
++                              if (DSP_SUCCEEDED(retVal))
++                                      retVal = DEV_GetSymbol(pDevContext->
++                                              hDevObject, EXTEND, &ulExtEnd);
++                      }
++              }
++              /* Trace buffer it right after the SHM SEG0, so set the
++               *      base address to SHMBASE */
++              if (bTraceLoad)
++                      ulExtBase = ulShmBaseVirt;
++
++              DBC_Assert(ulExtEnd != 0);
++              DBC_Assert(ulExtEnd > ulExtBase);
++              if (ulExtEnd < ulExtBase)
++                      retVal = DSP_EFAIL;
++
++              if (DSP_SUCCEEDED(retVal)) {
++                      ulTLBBaseVirt = pDevContext->aTLBEntry[0].ulDspVa *
++                                      DSPWORDSIZE;
++                      DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
++
++                      if (bSymbolsReloaded) {
++                              if (DSP_SUCCEEDED(retVal)) {
++                                      retVal = DEV_GetSymbol(pDevContext->
++                                               hDevObject, DSP_TRACESEC_END,
++                                               &ulShm0End);
++                              }
++                              if (DSP_SUCCEEDED(retVal)) {
++                                      retVal = DEV_GetSymbol(pDevContext->
++                                               hDevObject, DYNEXTBASE,
++                                               &ulDynExtBase);
++                              }
++                      }
++                      ulShmOffsetVirt = ulShmBaseVirt - ulTLBBaseVirt;
++                      if (bTraceLoad) {
++                              dwExtProgVirtMem = pDevContext->aTLBEntry[0].
++                                                 ulGppVa;
++                      } else {
++                              CFG_GetHostResources(
++                                      (struct CFG_DEVNODE *)
++                                      DRV_GetFirstDevExtension(), &hostRes);
++                              dwExtProgVirtMem = hostRes.dwMemBase[1];
++                              dwExtProgVirtMem += (ulExtBase - ulDynExtBase);
++                      }
++                      DBG_Trace(DBG_LEVEL7, "WriteExtDspData: GPP VA "
++                               "pointing to EXTMEMBASE 0x%x \n",
++                               dwExtProgVirtMem);
++
++                      pDevContext->dwDspExtBaseAddr =
++                              (u32)MEM_LinearAddress((void *)
++                              TO_VIRTUAL_UNCACHED(dwExtProgVirtMem), ulExtEnd
++                              - ulExtBase);
++                      dwBaseAddr += pDevContext->dwDspExtBaseAddr;
++                      /* This dwDspExtBaseAddr will get cleared only when
++                       * the board is stopped.  */
++                      if (!pDevContext->dwDspExtBaseAddr) {
++                              retVal = DSP_EFAIL;
++                              DBG_Trace(DBG_LEVEL7, "WriteExtDspData: failed "
++                                       "to Map the program memory\n");
++                      }
++              }
++      }
++      if (!dwBaseAddr || !ulExtBase || !ulExtEnd) {
++              DBG_Trace(DBG_LEVEL7, "Symbols missing for Ext Prog loading\n");
++              retVal = DSP_EFAIL;
++      }
++      if (DSP_SUCCEEDED(retVal)) {
++              for (i = 0; i < 4; i++)
++                      remainByte[i] = 0x0;
++
++              dwOffset = dwDSPAddr - ulExtBase;
++              /* Also make sure the dwDSPAddr is < ulExtEnd */
++              if (dwDSPAddr > ulExtEnd || dwOffset > dwDSPAddr) {
++                      DBG_Trace(DBG_LEVEL7, "We can not load at this address "
++                               "dwDSPAddr=0x%x, ulExt/DynBase=0x%x, "
++                               "ulExtEnd=0x%x\n", dwDSPAddr, ulExtBase,
++                               ulExtEnd);
++                      retVal = DSP_EFAIL;
++              }
++      }
++      if (DSP_SUCCEEDED(retVal)) {
++              if (ulNumBytes)
++                      memcpy((u8 *) dwBaseAddr + dwOffset, pbHostBuf,
++                              ulNumBytes);
++              else
++                      *((u32 *) pbHostBuf) = dwBaseAddr+dwOffset;
++      }
++      /* Unmap here to force remap for other Ext loads */
++      if ((bDynamicLoad || bTraceLoad) && pDevContext->dwDspExtBaseAddr) {
++              MEM_UnmapLinearAddress((void *) pDevContext->dwDspExtBaseAddr);
++              pDevContext->dwDspExtBaseAddr = 0x0;
++      }
++      bSymbolsReloaded = false;
++      return retVal;
++}
++
+diff --git a/drivers/dsp/bridge/wmd/tiomap_io.h b/drivers/dsp/bridge/wmd/tiomap_io.h
+new file mode 100644
+index 0000000..84a7553
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap_io.h
+@@ -0,0 +1,112 @@
++/*
++ * tiomap_io.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== _tiomap_io.h ========
++ *  Description:
++ *      Definitions, types and function prototypes for the io
++ *      (r/w external mem).
++ *
++ *! Revision History
++ *! ================
++ *! 08-Oct-2002 rr:  Created.
++ */
++
++#ifndef _TIOMAP_IO_
++#define _TIOMAP_IO_
++
++/*
++ * Symbol that defines beginning of shared memory.
++ * For OMAP (Helen) this is the DSP Virtual base address of SDRAM.
++ * This will be used to program DSP MMU to map DSP Virt to GPP phys.
++ * (see dspMmuTlbEntry()).
++ */
++#define SHMBASENAME "SHM_BEG"
++#define EXTBASE     "EXT_BEG"
++#define EXTEND      "_EXT_END"
++#define DYNEXTBASE  "_DYNEXT_BEG"
++#define DYNEXTEND   "_DYNEXT_END"
++#define IVAEXTMEMBASE   "_IVAEXTMEM_BEG"
++#define IVAEXTMEMEND   "_IVAEXTMEM_END"
++
++
++#define DSP_TRACESEC_BEG  "_BRIDGE_TRACE_BEG"
++#define DSP_TRACESEC_END  "_BRIDGE_TRACE_END"
++
++#define SYS_PUTCBEG               "_SYS_PUTCBEG"
++#define SYS_PUTCEND               "_SYS_PUTCEND"
++#define BRIDGE_SYS_PUTC_current   "_BRIDGE_SYS_PUTC_current"
++
++
++#define WORDSWAP_ENABLE 0x3   /* Enable word swap */
++
++/*
++ *  ======== ReadExtDspData ========
++ *  Reads it from DSP External memory. The external memory for the DSP
++ * is configured by the combination of DSP MMU and SHM Memory manager in the CDB
++ */
++extern DSP_STATUS ReadExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
++                              OUT u8 *pbHostBuf, u32 dwDSPAddr,
++                              u32 ulNumBytes, u32 ulMemType);
++
++/*
++ *  ======== WriteDspData ========
++ */
++extern DSP_STATUS WriteDspData(struct WMD_DEV_CONTEXT *pDevContext,
++                             OUT u8 *pbHostBuf, u32 dwDSPAddr,
++                             u32 ulNumBytes, u32 ulMemType);
++
++/*
++ *  ======== WriteExtDspData ========
++ *  Writes to the DSP External memory for external program.
++ *  The ext mem for progra is configured by the combination of DSP MMU and
++ *  SHM Memory manager in the CDB
++ */
++extern DSP_STATUS WriteExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
++                               IN u8 *pbHostBuf, u32 dwDSPAddr,
++                               u32 ulNumBytes, u32 ulMemType,
++                               bool bDynamicLoad);
++
++/*
++ * ======== WriteExt32BitDspData ========
++ * Writes 32 bit data to the external memory
++ */
++extern inline void WriteExt32BitDspData(IN const
++              struct WMD_DEV_CONTEXT *pDevContext, IN u32 dwDSPAddr,
++              IN u32 val)
++{
++      *(u32 *)dwDSPAddr = ((pDevContext->tcWordSwapOn) ? (((val << 16) &
++                            0xFFFF0000) | ((val >> 16) & 0x0000FFFF)) : val);
++}
++
++/*
++ * ======== ReadExt32BitDspData ========
++ * Reads 32 bit data from the external memory
++ */
++extern inline u32 ReadExt32BitDspData(IN const struct WMD_DEV_CONTEXT
++                                     *pDevContext, IN u32 dwDSPAddr)
++{
++      u32 retVal;
++      retVal = *(u32 *)dwDSPAddr;
++
++      retVal = ((pDevContext->tcWordSwapOn) ? (((retVal << 16)
++               & 0xFFFF0000) | ((retVal >> 16) & 0x0000FFFF)) : retVal);
++      return retVal;
++}
++
++#endif                                /* _TIOMAP_IO_ */
++
+diff --git a/drivers/dsp/bridge/wmd/tiomap_sm.c b/drivers/dsp/bridge/wmd/tiomap_sm.c
+new file mode 100644
+index 0000000..a6d5d62
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap_sm.c
+@@ -0,0 +1,195 @@
++/*
++ * tiomap_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++#include <dspbridge/cfg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++
++#include <dspbridge/dbg.h>
++
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++
++#define MAILBOX_FIFOSTATUS(m) (0x80 + 4 * (m))
++
++static inline unsigned int fifo_full(void __iomem *mbox_base, int mbox_id)
++{
++      return __raw_readl(mbox_base + MAILBOX_FIFOSTATUS(mbox_id)) & 0x1;
++}
++
++DSP_STATUS CHNLSM_EnableInterrupt(struct WMD_DEV_CONTEXT *pDevContext)
++{
++      DSP_STATUS status = DSP_SOK;
++      u32 numMbxMsg;
++      u32 mbxValue;
++      struct CFG_HOSTRES resources;
++      u32 devType;
++      struct IO_MGR *hIOMgr;
++
++      DBG_Trace(DBG_ENTER, "CHNLSM_EnableInterrupt(0x%x)\n", pDevContext);
++
++      /* Read the messages in the mailbox until the message queue is empty */
++
++      CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++                           &resources);
++      DEV_GetDevType(pDevContext->hDevObject, &devType);
++      status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++      if (devType == DSP_UNIT) {
++              HW_MBOX_NumMsgGet(resources.dwMboxBase,
++                                MBOX_DSP2ARM, &numMbxMsg);
++              while (numMbxMsg != 0) {
++                      HW_MBOX_MsgRead(resources.dwMboxBase,
++                                      MBOX_DSP2ARM,
++                                      &mbxValue);
++                      numMbxMsg--;
++              }
++              /* clear the DSP mailbox as well...*/
++              HW_MBOX_NumMsgGet(resources.dwMboxBase,
++                                MBOX_ARM2DSP, &numMbxMsg);
++              while (numMbxMsg != 0) {
++                      HW_MBOX_MsgRead(resources.dwMboxBase,
++                                      MBOX_ARM2DSP, &mbxValue);
++                      numMbxMsg--;
++                      udelay(10);
++
++                      HW_MBOX_EventAck(resources.dwMboxBase, MBOX_ARM2DSP,
++                                       HW_MBOX_U1_DSP1,
++                                       HW_MBOX_INT_NEW_MSG);
++              }
++              /* Enable the new message events on this IRQ line */
++              HW_MBOX_EventEnable(resources.dwMboxBase,
++                                  MBOX_DSP2ARM,
++                                  MBOX_ARM,
++                                  HW_MBOX_INT_NEW_MSG);
++      }
++
++      return status;
++}
++
++DSP_STATUS CHNLSM_DisableInterrupt(struct WMD_DEV_CONTEXT *pDevContext)
++{
++      struct CFG_HOSTRES resources;
++
++      DBG_Trace(DBG_ENTER, "CHNLSM_DisableInterrupt(0x%x)\n", pDevContext);
++
++      CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++                           &resources);
++      HW_MBOX_EventDisable(resources.dwMboxBase, MBOX_DSP2ARM,
++                           MBOX_ARM, HW_MBOX_INT_NEW_MSG);
++      return DSP_SOK;
++}
++
++DSP_STATUS CHNLSM_InterruptDSP2(struct WMD_DEV_CONTEXT *pDevContext,
++                              u16 wMbVal)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++      struct dspbridge_platform_data *pdata =
++              omap_dspbridge_dev->dev.platform_data;
++      u32 opplevel = 0;
++#endif
++      struct CFG_HOSTRES resources;
++      DSP_STATUS status = DSP_SOK;
++      unsigned long timeout;
++      u32 temp;
++
++      status = CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++                                    &resources);
++      if (DSP_FAILED(status))
++              return DSP_EFAIL;
++#ifdef CONFIG_BRIDGE_DVFS
++      if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION ||
++          pDevContext->dwBrdState == BRD_HIBERNATION) {
++              if (pdata->dsp_get_opp)
++                      opplevel = (*pdata->dsp_get_opp)();
++              if (opplevel == 1) {
++                      if (pdata->dsp_set_min_opp)
++                              (*pdata->dsp_set_min_opp)(opplevel+1);
++              }
++      }
++#endif
++
++      if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION ||
++          pDevContext->dwBrdState == BRD_HIBERNATION) {
++              /* Restore mailbox settings */
++              /* Restart the peripheral clocks that were disabled only
++               * in DSP initiated Hibernation case.*/
++              if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION) {
++                      DSP_PeripheralClocks_Enable(pDevContext, NULL);
++                      /* Enabling Dpll in lock mode*/
++                      temp = (u32) *((REG_UWORD32 *)
++                                     ((u32) (resources.dwCmBase) + 0x34));
++                      temp = (temp & 0xFFFFFFFE) | 0x1;
++                      *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) =
++                              (u32) temp;
++                      temp = (u32) *((REG_UWORD32 *)
++                                     ((u32) (resources.dwCmBase) + 0x4));
++                      temp = (temp & 0xFFFFFC8) | 0x37;
++
++                      *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x4)) =
++                              (u32) temp;
++              }
++              HW_MBOX_restoreSettings(resources.dwMboxBase);
++
++              /*  Access MMU SYS CONFIG register to generate a short wakeup */
++              temp = (u32) *((REG_UWORD32 *) ((u32)
++                                              (resources.dwDmmuBase) + 0x10));
++
++              pDevContext->dwBrdState = BRD_RUNNING;
++      }
++      timeout = jiffies + msecs_to_jiffies(1);
++      while (fifo_full((void __iomem *) resources.dwMboxBase, 0)) {
++              if (time_after(jiffies, timeout)) {
++                      printk(KERN_ERR "dspbridge: timed out waiting for mailbox\n");
++                      return WMD_E_TIMEOUT;
++              }
++      }
++      DBG_Trace(DBG_LEVEL3, "writing %x to Mailbox\n",
++                wMbVal);
++
++      HW_MBOX_MsgWrite(resources.dwMboxBase, MBOX_ARM2DSP,
++                       wMbVal);
++      return DSP_SOK;
++}
++
++bool CHNLSM_ISR(struct WMD_DEV_CONTEXT *pDevContext, bool *pfSchedDPC,
++              u16 *pwIntrVal)
++{
++      struct CFG_HOSTRES resources;
++      u32 numMbxMsg;
++      u32 mbxValue;
++
++      DBG_Trace(DBG_ENTER, "CHNLSM_ISR(0x%x)\n", pDevContext);
++
++      CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++
++      HW_MBOX_NumMsgGet(resources.dwMboxBase, MBOX_DSP2ARM, &numMbxMsg);
++
++      if (numMbxMsg > 0) {
++              HW_MBOX_MsgRead(resources.dwMboxBase, MBOX_DSP2ARM, &mbxValue);
++
++              HW_MBOX_EventAck(resources.dwMboxBase, MBOX_DSP2ARM,
++                               HW_MBOX_U0_ARM, HW_MBOX_INT_NEW_MSG);
++
++              DBG_Trace(DBG_LEVEL3, "Read %x from Mailbox\n", mbxValue);
++              *pwIntrVal = (u16) mbxValue;
++      }
++      /* Set *pfSchedDPC to true; */
++      *pfSchedDPC = true;
++      return true;
++}
+diff --git a/drivers/dsp/bridge/wmd/ue_deh.c b/drivers/dsp/bridge/wmd/ue_deh.c
+new file mode 100644
+index 0000000..d5551cb
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/ue_deh.c
+@@ -0,0 +1,329 @@
++/*
++ * ue_deh.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ *  ======== ue_deh.c ========
++ *  Description:
++ *      Implements upper edge DSP exception handling (DEH) functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Jan-2005 hn: Support for IVA DEH.
++ *! 05-Jan-2004 vp: Updated for the 24xx HW library.
++ *! 19-Feb-2003 vp: Code review updates.
++ *!                 - Cosmetic changes.
++ *! 18-Oct-2002 sb: Ported to Linux platform.
++ *! 10-Dec-2001 kc: Updated DSP error reporting in DEBUG mode.
++ *! 10-Sep-2001 kc: created.
++ */
++
++/*  ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/*  ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/*  ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/*  ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/drv.h>
++
++/*  ----------------------------------- Link Driver */
++#include <dspbridge/wmddeh.h>
++
++/*  ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/wcd.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/*  ----------------------------------- This */
++#include "mmu_fault.h"
++#include "_tiomap.h"
++#include "_deh.h"
++#include "_tiomap_mmu.h"
++#include "_tiomap_pwr.h"
++#include <dspbridge/io_sm.h>
++
++static struct HW_MMUMapAttrs_t  mapAttrs = { HW_LITTLE_ENDIAN,
++                                      HW_ELEM_SIZE_16BIT,
++                                      HW_MMU_CPUES} ;
++#define VirtToPhys(x)       ((x) - PAGE_OFFSET + PHYS_OFFSET)
++/*
++ *  ======== WMD_DEH_Create ========
++ *      Creates DEH manager object.
++ */
++DSP_STATUS WMD_DEH_Create(OUT struct DEH_MGR **phDehMgr,
++                       struct DEV_OBJECT *hDevObject)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEH_MGR *pDehMgr = NULL;
++      struct CFG_HOSTRES cfgHostRes;
++      struct CFG_DEVNODE *hDevNode;
++      struct WMD_DEV_CONTEXT *hWmdContext = NULL;
++
++      DBG_Trace(DBG_LEVEL1, "Entering DEH_Create: 0x%x\n", phDehMgr);
++       /*  Message manager will be created when a file is loaded, since
++       *  size of message buffer in shared memory is configurable in
++       *  the base image.  */
++      /* Get WMD context info. */
++      DEV_GetWMDContext(hDevObject, &hWmdContext);
++      DBC_Assert(hWmdContext);
++      /* Allocate IO manager object: */
++      MEM_AllocObject(pDehMgr, struct DEH_MGR, SIGNATURE);
++      if (pDehMgr == NULL) {
++              status = DSP_EMEMORY;
++      } else {
++              /* Create an NTFY object to manage notifications */
++              if (DSP_SUCCEEDED(status))
++                      status = NTFY_Create(&pDehMgr->hNtfy);
++
++              /* Create a DPC object. */
++              status = DPC_Create(&pDehMgr->hMmuFaultDpc, MMU_FaultDpc,
++                                 (void *)pDehMgr);
++              if (DSP_SUCCEEDED(status))
++                      status = DEV_GetDevNode(hDevObject, &hDevNode);
++
++              if (DSP_SUCCEEDED(status))
++                      status = CFG_GetHostResources(hDevNode, &cfgHostRes);
++
++              if (DSP_SUCCEEDED(status)) {
++                      /* Fill in context structure */
++                      pDehMgr->hWmdContext = hWmdContext;
++                      pDehMgr->errInfo.dwErrMask = 0L;
++                      pDehMgr->errInfo.dwVal1 = 0L;
++                      pDehMgr->errInfo.dwVal2 = 0L;
++                      pDehMgr->errInfo.dwVal3 = 0L;
++                      /* Install ISR function for DSP MMU fault */
++                       if ((request_irq(INT_DSP_MMU_IRQ, MMU_FaultIsr, 0,
++                                           "DspBridge\tiommu fault", (void *)pDehMgr)) == 0)
++                               status = DSP_SOK;
++                       else
++                               status = DSP_EFAIL;
++              }
++      }
++      if (DSP_FAILED(status)) {
++              /* If create failed, cleanup */
++              WMD_DEH_Destroy((struct DEH_MGR *)pDehMgr);
++              *phDehMgr = NULL;
++      } else {
++              *phDehMgr = (struct DEH_MGR *)pDehMgr;
++               DBG_Trace(DBG_LEVEL1, "ISR_IRQ Object 0x%x \n",
++                                        pDehMgr);
++      }
++      DBG_Trace(DBG_LEVEL1, "Exiting DEH_Create.\n");
++      return status;
++}
++
++/*
++ *  ======== WMD_DEH_Destroy ========
++ *      Destroys DEH manager object.
++ */
++DSP_STATUS WMD_DEH_Destroy(struct DEH_MGR *hDehMgr)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++      DBG_Trace(DBG_LEVEL1, "Entering DEH_Destroy: 0x%x\n", pDehMgr);
++      if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++              /* If notification object exists, delete it */
++              if (pDehMgr->hNtfy)
++                      (void)NTFY_Delete(pDehMgr->hNtfy);
++              /* Disable DSP MMU fault */
++               free_irq(INT_DSP_MMU_IRQ, pDehMgr);
++              (void)DPC_Destroy(pDehMgr->hMmuFaultDpc);
++              /* Deallocate the DEH manager object */
++              MEM_FreeObject(pDehMgr);
++      }
++      DBG_Trace(DBG_LEVEL1, "Exiting DEH_Destroy.\n");
++      return status;
++}
++
++/*
++ *  ======== WMD_DEH_RegisterNotify ========
++ *      Registers for DEH notifications.
++ */
++DSP_STATUS WMD_DEH_RegisterNotify(struct DEH_MGR *hDehMgr, u32 uEventMask,
++                               u32 uNotifyType,
++                               struct DSP_NOTIFICATION *hNotification)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++      DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_RegisterNotify: 0x%x\n",
++               pDehMgr);
++
++      if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++              status = NTFY_Register(pDehMgr->hNtfy, hNotification,
++                       uEventMask, uNotifyType);
++      }
++      DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_RegisterNotify.\n");
++      return status;
++}
++
++
++/*
++ *  ======== WMD_DEH_Notify ========
++ *      DEH error notification function. Informs user about the error.
++ */
++void WMD_DEH_Notify(struct DEH_MGR *hDehMgr, u32 ulEventMask,
++                       u32 dwErrInfo)
++{
++      struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++      struct WMD_DEV_CONTEXT *pDevContext;
++      DSP_STATUS status = DSP_SOK;
++      u32 memPhysical = 0;
++      u32 HW_MMU_MAX_TLB_COUNT = 31;
++      u32 extern faultAddr;
++      struct CFG_HOSTRES resources;
++      u32 dummyVaAddr;
++      HW_STATUS hwStatus;
++
++      status = CFG_GetHostResources(
++                      (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++                      &resources);
++      if (DSP_FAILED(status))
++              DBG_Trace(DBG_LEVEL7,
++                       "**Failed to get Host Resources in MMU ISR **\n");
++
++      DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_Notify: 0x%x, 0x%x\n", pDehMgr,
++               ulEventMask);
++      if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++              printk(KERN_INFO "WMD_DEH_Notify: ********** DEVICE EXCEPTION "
++                      "**********\n");
++              pDevContext = (struct WMD_DEV_CONTEXT *)pDehMgr->hWmdContext;
++
++              switch (ulEventMask) {
++              case DSP_SYSERROR:
++                      /* reset errInfo structure before use */
++                      pDehMgr->errInfo.dwErrMask = DSP_SYSERROR;
++                      pDehMgr->errInfo.dwVal1 = 0L;
++                      pDehMgr->errInfo.dwVal2 = 0L;
++                      pDehMgr->errInfo.dwVal3 = 0L;
++                      pDehMgr->errInfo.dwVal1 = dwErrInfo;
++                      printk(KERN_ERR "WMD_DEH_Notify: DSP_SYSERROR, errInfo "
++                              "= 0x%x\n", dwErrInfo);
++                      break;
++              case DSP_MMUFAULT:
++                      /* MMU fault routine should have set err info
++                       * structure */
++                      pDehMgr->errInfo.dwErrMask = DSP_MMUFAULT;
++                      printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT,"
++                              "errInfo = 0x%x\n", dwErrInfo);
++                      printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, High "
++                              "Address = 0x%x\n",
++                              (unsigned int)pDehMgr->errInfo.dwVal1);
++                      printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, Low "
++                              "Address = 0x%x\n",
++                              (unsigned int)pDehMgr->errInfo.dwVal2);
++                      printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, fault "
++                              "address = 0x%x\n", (unsigned int)faultAddr);
++                      dummyVaAddr = (u32)MEM_Calloc(sizeof(char) * 0x1000,
++                                      MEM_PAGED);
++                      memPhysical = (u32)MEM_Calloc(sizeof(char) * 0x1000,
++                                      MEM_PAGED);
++                      dummyVaAddr = PG_ALIGN_LOW((u32)dummyVaAddr,
++                                      PG_SIZE_4K);
++                      memPhysical  = VirtToPhys(dummyVaAddr);
++                      DBG_Trace(DBG_LEVEL6, "WMD_DEH_Notify: DSP_MMUFAULT, "
++                               "mem Physical= 0x%x\n", memPhysical);
++                      pDevContext = (struct WMD_DEV_CONTEXT *)
++                                              pDehMgr->hWmdContext;
++                      /* Reset the dynamic mmu index to fixed count if it
++                       * exceeds 31. So that the dynmmuindex is always
++                       * between the range of standard/fixed entries
++                       * and 31.  */
++                      if (pDevContext->numTLBEntries >
++                         HW_MMU_MAX_TLB_COUNT) {
++                              pDevContext->numTLBEntries = pDevContext->
++                                      fixedTLBEntries;
++                      }
++                      DBG_Trace(DBG_LEVEL6, "Adding TLB Entry %d: VA: 0x%x, "
++                               "PA: 0x%x\n", pDevContext->
++                              numTLBEntries, faultAddr, memPhysical);
++                      if (DSP_SUCCEEDED(status)) {
++                              hwStatus = HW_MMU_TLBAdd(resources.dwDmmuBase,
++                                      memPhysical, faultAddr,
++                                      HW_PAGE_SIZE_4KB, 1, &mapAttrs,
++                                      HW_SET, HW_SET);
++                      }
++                      /* send an interrupt to DSP */
++                      HW_MBOX_MsgWrite(resources.dwMboxBase, MBOX_ARM2DSP,
++                                       MBX_DEH_CLASS | MBX_DEH_EMMU);
++                      /* Clear MMU interrupt */
++                      HW_MMU_EventAck(resources.dwDmmuBase,
++                                       HW_MMU_TRANSLATION_FAULT);
++                      break;
++              default:
++                      DBG_Trace(DBG_LEVEL6,
++                               "WMD_DEH_Notify: Unknown Error, errInfo = "
++                               "0x%x\n", dwErrInfo);
++                      break;
++              }
++              /* Set the Board state as ERROR */
++              pDevContext->dwBrdState = BRD_ERROR;
++              /* Disable all the clocks that were enabled by DSP */
++              (void)DSP_PeripheralClocks_Disable(pDevContext, NULL);
++              /* Call DSP Trace Buffer */
++              PrintDspTraceBuffer(hDehMgr->hWmdContext);
++
++              /* Signal DSP error/exception event. */
++              NTFY_Notify(pDehMgr->hNtfy, ulEventMask);
++      }
++      DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_Notify\n");
++
++}
++
++/*
++ *  ======== WMD_DEH_GetInfo ========
++ *      Retrieves error information.
++ */
++DSP_STATUS WMD_DEH_GetInfo(struct DEH_MGR *hDehMgr,
++                        struct DSP_ERRORINFO *pErrInfo)
++{
++      DSP_STATUS status = DSP_SOK;
++      struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++      DBC_Require(pDehMgr);
++      DBC_Require(pErrInfo);
++
++      DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_GetInfo: 0x%x\n", hDehMgr);
++
++      if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++              /* Copy DEH error info structure to PROC error info
++               * structure. */
++              pErrInfo->dwErrMask = pDehMgr->errInfo.dwErrMask;
++              pErrInfo->dwVal1 = pDehMgr->errInfo.dwVal1;
++              pErrInfo->dwVal2 = pDehMgr->errInfo.dwVal2;
++              pErrInfo->dwVal3 = pDehMgr->errInfo.dwVal3;
++      }
++
++      DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_GetInfo\n");
++
++      return status;
++}
+-- 
+1.5.6.3
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-blank-rotate-accessible-by-user.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-blank-rotate-accessible-by-user.patch
new file mode 100644 (file)
index 0000000..d75f15d
--- /dev/null
@@ -0,0 +1,20 @@
+--- a/drivers/video/fbsysfs.c  2009-07-17 12:23:16.000000000 -0700
++++ b/drivers/video/fbsysfs.c  2009-07-17 12:24:32.000000000 -0700
+@@ -489,7 +489,7 @@
+  * fbdev to use configfs instead of sysfs */
+ static struct device_attribute device_attrs[] = {
+       __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
+-      __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
++      __ATTR(blank, S_IRUGO|S_IWUGO, show_blank, store_blank),
+       __ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console),
+       __ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor),
+       __ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode),
+@@ -498,7 +498,7 @@
+       __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual),
+       __ATTR(name, S_IRUGO, show_name, NULL),
+       __ATTR(stride, S_IRUGO, show_stride, NULL),
+-      __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
++      __ATTR(rotate, S_IRUGO|S_IWUGO, show_rotate, store_rotate),
+       __ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate),
+ #ifdef CONFIG_FB_BACKLIGHT
+       __ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve),
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-export-status.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-export-status.patch
new file mode 100644 (file)
index 0000000..eaa78e2
--- /dev/null
@@ -0,0 +1,44 @@
+From c78da49092fd206943f77aa9ebc3fa2c1301ac5a Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Thu, 23 Apr 2009 18:19:32 -0700
+Subject: [PATCH] DSS2: Export display status to sysfs
+
+It is useful to know from userspace if the display has been turned off,
+e.g. to toggle display power from userspace.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ drivers/video/omap2/omapfb/omapfb-sysfs.c |   10 ++++++++++
+ 1 files changed, 10 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+index 2c88718..28438fb 100644
+--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
++++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
+@@ -326,6 +326,15 @@ static ssize_t show_virt(struct device *dev,
+       return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region.vaddr);
+ }
++static ssize_t show_display_state(struct device *dev,
++              struct device_attribute *attr, char *buf)
++{
++      struct fb_info *fbi = dev_get_drvdata(dev);
++      struct omap_display *display = fb2display(fbi);
++
++      return snprintf(buf, PAGE_SIZE, "%d\n", display->state);
++}
++
+ static struct device_attribute omapfb_attrs[] = {
+       __ATTR(rotate_type, S_IRUGO, show_rotate_type, NULL),
+       __ATTR(mirror, S_IRUGO | S_IWUSR, show_mirror, store_mirror),
+@@ -333,6 +342,7 @@ static struct device_attribute omapfb_attrs[] = {
+       __ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
+       __ATTR(phys_addr, S_IRUGO, show_phys, NULL),
+       __ATTR(virt_addr, S_IRUGO, show_virt, NULL),
++      __ATTR(display_state, S_IRUGO, show_display_state, NULL),
+ };
+ int omapfb_create_sysfs(struct omapfb2_device *fbdev)
+-- 
+1.5.6.3
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-fix-XY-coordinates-when-rotating.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-fix-XY-coordinates-when-rotating.patch
new file mode 100644 (file)
index 0000000..98a82c8
--- /dev/null
@@ -0,0 +1,177 @@
+From a9cc890ffea21fa492678b1755a263120cbddf0e Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Mon, 20 Apr 2009 20:29:11 -0700
+Subject: [PATCH] DSS2: OMAPFB: Translate X/Y coordinates for the video planes when rotating.
+
+When rotating the video planes, translate the X/Y coordinates such that
+a [0,0] from userspace always maps to the correct upper left corner of
+the display. This patch assumes that you rotate plane 0 before rotating
+plane 1. Patch also corrects the scaling parameters so that the video is
+displayed in the correct orientation (vertically, instead of horizontally)
+when rotating by 90 / 270 degrees.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ drivers/video/omap2/dss/dispc.c           |   16 ++++++++++++----
+ drivers/video/omap2/dss/overlay.c         |    6 ++++++
+ drivers/video/omap2/omapfb/omapfb-ioctl.c |   28 ++++++++++++++++++++++++++++
+ 3 files changed, 46 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 7e551c2..bece91d 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1580,10 +1580,18 @@ static int _dispc_setup_plane(enum omap_plane plane,
+       _dispc_set_pic_size(plane, width, height);
+       if (plane != OMAP_DSS_GFX) {
+-              _dispc_set_scaling(plane, width, height,
+-                                 out_width, out_height,
+-                                 ilace, five_taps, fieldmode);
+-              _dispc_set_vid_size(plane, out_width, out_height);
++              if (rotation == 1 || rotation == 3) {
++                      _dispc_set_scaling(plane, width, height,
++                                         out_height, out_width,
++                                         ilace, five_taps, fieldmode);
++                      _dispc_set_vid_size(plane, out_height, out_width);
++              } else {
++                      _dispc_set_scaling(plane, width, height,
++                                         out_width, out_height,
++                                         ilace, five_taps, fieldmode);
++                      _dispc_set_vid_size(plane, out_width, out_height);
++              }
++
+               _dispc_set_vid_color_conv(plane, cconv);
+       }
+diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
+index c047206..a1a02b5 100644
+--- a/drivers/video/omap2/dss/overlay.c
++++ b/drivers/video/omap2/dss/overlay.c
+@@ -344,6 +344,20 @@
+                       outh = info->out_height;
+       }
++      if ((ovl->supported_modes & info->color_mode) == 0) {
++              DSSERR("overlay doesn't support mode %d\n", info->color_mode);
++              return -EINVAL;
++      }
++
++      if (ovl->id != OMAP_DSS_GFX && (info->rotation == 1 ||
++          info->rotation == 3)) {
++              if(outw > dh || outh > dw)
++                      return -EINVAL;
++
++              /* If coordinates are invalid, they will be clipped later... */
++              return 0;
++      }
++
+       if (dw < info->pos_x + outw) {
+               DSSDBG("check_overlay failed 1: %d < %d + %d\n",
+                               dw, info->pos_x, outw);
+@@ -356,11 +370,6 @@
+               return -EINVAL;
+       }
+-      if ((ovl->supported_modes & info->color_mode) == 0) {
+-              DSSERR("overlay doesn't support mode %d\n", info->color_mode);
+-              return -EINVAL;
+-      }
+-
+       return 0;
+ }
+diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
+index 79d8916..b548f62 100644
+--- a/drivers/video/omap2/dss/manager.c
++++ b/drivers/video/omap2/dss/manager.c
+@@ -400,7 +400,7 @@
+       struct omap_overlay *ovl;
+       bool ilace = 0;
+       int outw, outh;
+-      int r;
++      int r, pos_x = 0, pos_y = 0;
+       int num_planes_enabled = 0;
+       DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
+@@ -451,11 +451,51 @@
+               else
+                       outh = ovl->info.out_height;
++              if (ovl->id != OMAP_DSS_GFX && ovl->info.rotation != 0) {
++                      /* We need to rotate pos_x and pos_y with respect
++                         to OMAP_DSS_GFX */
++
++                      u16 dw, dh;
++                      display->get_resolution(display, &dw, &dh);
++
++                      DSSDBG("plane pos was: (%d, %d), %dx%d, scr: %dx%d \n", ovl->info.pos_x,
++                              ovl->info.pos_y, outw, outh, dw, dh);
++
++                      switch (ovl->info.rotation) {
++                      case 1:
++                              pos_y = ovl->info.pos_x;
++                              pos_x = dw - ovl->info.pos_y - outh;
++                              break;
++                      case 2:
++                              pos_x = dw - ovl->info.pos_x - outw;
++                              pos_y = dh - ovl->info.pos_y - outh;
++                              break;
++                      case 3:
++                              pos_x = ovl->info.pos_y;
++                              pos_y = dh - ovl->info.pos_x - outw;
++                              break;
++                      }
++
++                      /* Check sanity */
++                      if (ovl->info.rotation != 2) {
++                              if (dw < pos_x + outh)
++                                      pos_x = pos_y = 0;
++                              else if (dh < pos_y + outw)
++                                      pos_x = pos_y = 0;
++                      } else if ( (dw < ovl->info.pos_x + outw) || (dh < ovl->info.pos_y + outh) )
++                              pos_x = pos_y = 0;
++
++                      DSSDBG("pos_x is %d, pos_y is %d\n", pos_x, pos_y);
++              } else {
++                      pos_x = ovl->info.pos_x;
++                      pos_y = ovl->info.pos_y;
++              }
++
+               r = dispc_setup_plane(ovl->id, ovl->manager->id,
+                               ovl->info.paddr,
+                               ovl->info.screen_width,
+-                              ovl->info.pos_x,
+-                              ovl->info.pos_y,
++                              pos_x,
++                              pos_y,
+                               ovl->info.width,
+                               ovl->info.height,
+                               outw,
+diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
+index 79d8916..b548f62 100644
+--- a/drivers/video/omap2/omapfb/omapfb-main.c
++++ b/drivers/video/omap2/omapfb/omapfb-main.c
+@@ -484,22 +484,7 @@
+       if (var->rotate != fbi->var.rotate) {
+               DBG("rotation changing\n");
+-
+               ofbi->rotation = var->rotate;
+-
+-              if (abs(var->rotate - fbi->var.rotate) != 2) {
+-                      int tmp;
+-                      DBG("rotate changing 90/270 degrees. "
+-                                      "swapping x/y res\n");
+-
+-                      tmp = var->yres;
+-                      var->yres = var->xres;
+-                      var->xres = tmp;
+-
+-                      tmp = var->yres_virtual;
+-                      var->yres_virtual = var->xres_virtual;
+-                      var->xres_virtual = tmp;
+-              }
+       }
+       xres_min = OMAPFB_PLANE_XRES_MIN;
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-fix-scaling-when-rotating.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/dss2-fix-scaling-when-rotating.patch
new file mode 100644 (file)
index 0000000..7cb8a7d
--- /dev/null
@@ -0,0 +1,52 @@
+From 19a31ba4e8408ce80a4dbb96af489304c5e8128f Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Fri, 22 May 2009 18:58:33 -0700
+Subject: [PATCH] Fix scaling checks when rotation is 90 or 270 degrees.
+
+---
+ drivers/video/omap2/dss/dispc.c |   25 +++++++++++++++++++------
+ 1 files changed, 19 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
+index 088d353..77ca81b 100644
+--- a/drivers/video/omap2/dss/dispc.c
++++ b/drivers/video/omap2/dss/dispc.c
+@@ -1508,16 +1508,29 @@ static int _dispc_setup_plane(enum omap_plane plane,
+               }
+       } else {
+               /* video plane */
+-
++              u8 error = 0;
+               unsigned long fclk = 0;
+-              if (out_width < width / maxdownscale ||
+-                 out_width > width * 8)
+-                      return -EINVAL;
++              if(rotation == 1 || rotation == 3)
++              {
++                      if (out_width < height / maxdownscale || out_width > height * 8)
++                              error = 1;
++
++                      if (out_height < width / maxdownscale || out_height > width * 8)
++                              error = 1;
++              } else {
++                      if (out_width < width / maxdownscale || out_width > width * 8)
++                              error = 1;
+-              if (out_height < height / maxdownscale ||
+-                 out_height > height * 8)
++                      if (out_height < height / maxdownscale || out_height > height * 8)
++                              error = 1;
++              }
++
++              if(error != 0)
++              {
++                      printk("DSS: Unable to down/up scale video plane\n");
+                       return -EINVAL;
++              }
+               switch (color_mode) {
+               case OMAP_DSS_COLOR_RGB16:
+-- 
+1.5.6.3
+
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/ehci.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/ehci.patch
new file mode 100644 (file)
index 0000000..5a8c844
--- /dev/null
@@ -0,0 +1,131 @@
+Index: git/arch/arm/mach-omap2/board-omap3beagle.c
+===================================================================
+--- git.orig/arch/arm/mach-omap2/board-omap3beagle.c
++++ git/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -154,6 +154,7 @@ static int beagle_twl_gpio_setup(struct
+        * power switch and overcurrent detect
+        */
++#if 0 /* TODO: This needs to be modified to not rely on u-boot */
+       gpio_request(gpio + 1, "EHCI_nOC");
+       gpio_direction_input(gpio + 1);
+@@ -163,7 +164,7 @@ static int beagle_twl_gpio_setup(struct
+       /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
+       gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
+-
++#endif
+       return 0;
+ }
+Index: git/arch/arm/mach-omap2/usb-ehci.c
+===================================================================
+--- git.orig/arch/arm/mach-omap2/usb-ehci.c
++++ git/arch/arm/mach-omap2/usb-ehci.c
+@@ -147,9 +147,11 @@ static void setup_ehci_io_mux(void)
+ void __init usb_ehci_init(void)
+ {
++#if 0 /* TODO: Setup Pin IO MUX for EHCI - moved this temporarily to U-boot */
+       /* Setup Pin IO MUX for EHCI */
+       if (cpu_is_omap34xx())
+               setup_ehci_io_mux();
++#endif
+       if (platform_device_register(&ehci_device) < 0) {
+               printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n");
+Index: git/drivers/usb/host/ehci-omap.c
+===================================================================
+--- git.orig/drivers/usb/host/ehci-omap.c
++++ git/drivers/usb/host/ehci-omap.c
+@@ -48,16 +48,25 @@
+  *            to get the PHY state machine in working state
+  */
+ #define EXTERNAL_PHY_RESET
++#ifdef CONFIG_MACH_OMAP3_BEAGLE
++#define        EXT_PHY_RESET_GPIO_PORT2        (147)
++#else
+ #define       EXT_PHY_RESET_GPIO_PORT1        (57)
+ #define       EXT_PHY_RESET_GPIO_PORT2        (61)
++#endif
+ #define       EXT_PHY_RESET_DELAY             (10)
++#define PHY_STP_PULLUP_ENABLE           (0x10)
++#define PHY_STP_PULLUP_DISABLE          (0x90)
++
+ /* ISSUE2:
+  * USBHOST supports External charge pump PHYs only
+  * Use the VBUS from Port1 to power VBUS of Port2 externally
+  * So use Port2 as the working ULPI port
+  */
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+ #define VBUS_INTERNAL_CHARGEPUMP_HACK
++#endif
+ #endif /* CONFIG_OMAP_EHCI_PHY_MODE */
+@@ -225,14 +234,43 @@ static int omap_start_ehc(struct platfor
+ #ifdef EXTERNAL_PHY_RESET
+       /* Refer: ISSUE1 */
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+       gpio_request(EXT_PHY_RESET_GPIO_PORT1, "USB1 PHY reset");
+       gpio_direction_output(EXT_PHY_RESET_GPIO_PORT1, 0);
++#endif
+       gpio_request(EXT_PHY_RESET_GPIO_PORT2, "USB2 PHY reset");
+       gpio_direction_output(EXT_PHY_RESET_GPIO_PORT2, 0);
++      gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 0);
+       /* Hold the PHY in RESET for enough time till DIR is high */
+       udelay(EXT_PHY_RESET_DELAY);
+ #endif
++        /*
++         * The PHY register 0x7 - Interface Control register is
++         * configured to disable the integrated STP pull-up resistor
++         * used for interface protection.
++        *
++        * May not need to be here.
++         */
++        omap_writel((0x7 << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* interface reg */
++                (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/*   Write */
++                (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
++                (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
++                (PHY_STP_PULLUP_DISABLE),
++                EHCI_INSNREG05_ULPI);
++
++        while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
++
++        /* Force PHY to HS */
++        omap_writel((0x4 << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* function ctrl */
++                (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/*   Write */
++                (1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
++                (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
++                (0x40),
++                EHCI_INSNREG05_ULPI);
++
++        while (!(omap_readl(EHCI_INSNREG05_ULPI) & (1<<EHCI_INSNREG05_ULPI_CONTROL_SHIFT)));
++
+       /* Configure TLL for 60Mhz clk for ULPI */
+       ehci_clocks->usbtll_fck_clk = clk_get(&dev->dev, USBHOST_TLL_FCLK);
+       if (IS_ERR(ehci_clocks->usbtll_fck_clk))
+@@ -307,7 +345,9 @@ static int omap_start_ehc(struct platfor
+        * Hold the PHY in RESET for enough time till PHY is settled and ready
+        */
+       udelay(EXT_PHY_RESET_DELAY);
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+       gpio_set_value(EXT_PHY_RESET_GPIO_PORT1, 1);
++#endif
+       gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 1);
+ #endif
+@@ -393,7 +433,9 @@ static void omap_stop_ehc(struct platfor
+ #ifdef EXTERNAL_PHY_RESET
++#ifndef CONFIG_MACH_OMAP3_BEAGLE
+       gpio_free(EXT_PHY_RESET_GPIO_PORT1);
++#endif
+       gpio_free(EXT_PHY_RESET_GPIO_PORT2);
+ #endif
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/logo_linux_clut224.ppm b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/logo_linux_clut224.ppm
new file mode 100644 (file)
index 0000000..76b746b
--- /dev/null
@@ -0,0 +1,773 @@
+P3
+171 35
+255
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 
+85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 17 17 17 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 204 204 204 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 170 170 170 204 204 204 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 187 187 187 0 0 0 0 0 0 
+85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 17 17 17 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 204 204 204 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 17 17 17 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255 
+119 119 119 0 0 0 0 0 0 34 34 34 221 221 221 255 255 255 68 68 68 0 0 0 
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 17 17 17 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255 
+119 119 119 0 0 0 0 0 0 0 0 0 136 136 136 255 255 255 119 119 119 0 0 0 
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 136 136 136 238 238 238 255 255 255 255 255 255 
+187 187 187 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 187 187 187 
+255 255 255 255 255 255 255 255 255 187 187 187 85 85 85 0 0 0 0 0 0 0 0 0 
+0 0 0 17 17 17 153 153 153 255 255 255 255 255 255 255 255 255 238 238 238 255 255 255 
+85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 187 187 187 255 255 255 255 255 255 
+238 238 238 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 102 102 102 
+255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 187 187 187 255 255 255 
+255 255 255 255 255 255 68 68 68 0 0 0 119 119 119 187 187 187 255 255 255 255 255 255 
+255 255 255 187 187 187 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 
+255 255 255 255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 153 153 153 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 
+255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255 
+119 119 119 0 0 0 0 0 0 85 85 85 238 238 238 255 255 255 51 51 51 0 0 0 
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0 
+0 0 0 0 0 0 17 17 17 204 204 204 255 255 255 255 255 255 255 255 255 255 255 255 
+255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 51 51 51 0 0 0 0 0 0 
+0 0 0 221 221 221 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 
+119 119 119 0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 255 255 255 
+255 255 255 255 255 255 204 204 204 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 102 102 102 
+255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 187 187 187 255 255 255 
+255 255 255 255 255 255 68 68 68 0 0 0 204 204 204 255 255 255 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 51 51 51 0 0 0 0 0 0 0 0 0 204 204 204 
+255 255 255 255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 153 153 153 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 
+255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255 
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 153 153 153 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0 
+0 0 0 0 0 0 153 153 153 255 255 255 170 170 170 17 17 17 0 0 0 0 0 0 
+102 102 102 221 221 221 238 238 238 17 17 17 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 102 102 102 0 0 0 0 0 0 
+34 34 34 255 255 255 238 238 238 17 17 17 0 0 0 0 0 0 136 136 136 255 255 255 
+85 85 85 0 0 0 34 34 34 255 255 255 221 221 221 102 102 102 0 0 0 0 0 0 
+17 17 17 170 170 170 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+119 119 119 255 255 255 119 119 119 68 68 68 255 255 255 221 221 221 0 0 0 187 187 187 
+255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 204 204 204 255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 85 85 85 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 17 17 17 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255 
+255 255 255 255 255 255 255 255 255 221 221 221 119 119 119 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0 
+0 0 0 0 0 0 238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 51 51 51 170 170 170 
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 
+0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 187 187 187 136 136 136 51 51 51 
+0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 221 221 221 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+68 68 68 255 255 255 187 187 187 153 153 153 255 255 255 255 255 255 85 85 85 238 238 238 
+255 255 255 34 34 34 0 0 0 0 0 0 51 51 51 170 170 170 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 85 85 85 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 17 17 17 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255 
+119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0 
+0 0 0 0 0 0 238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 68 68 68 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 
+0 0 0 0 0 0 51 51 51 136 136 136 136 136 136 136 136 136 255 255 255 255 255 255 
+102 102 102 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 238 238 238 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 238 238 238 221 221 221 238 238 238 255 255 255 255 255 255 204 204 204 255 255 255 
+221 221 221 0 0 0 0 0 0 68 68 68 255 255 255 255 255 255 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 85 85 85 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 17 17 17 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255 
+119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 17 17 17 0 0 0 0 0 0 
+0 0 0 0 0 0 170 170 170 255 255 255 153 153 153 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 136 136 136 
+0 0 0 0 0 0 51 51 51 204 204 204 255 255 255 119 119 119 0 0 0 0 0 0 
+102 102 102 255 255 255 153 153 153 0 0 0 0 0 0 0 0 0 102 102 102 255 255 255 
+204 204 204 0 0 0 51 51 51 255 255 255 204 204 204 85 85 85 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 204 204 204 255 255 255 255 255 255 170 170 170 221 221 221 255 255 255 255 255 255 
+153 153 153 0 0 0 0 0 0 170 170 170 255 255 255 136 136 136 0 0 0 0 0 0 
+51 51 51 204 204 204 255 255 255 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 85 85 85 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 238 238 238 255 255 255 51 51 51 0 0 0 0 0 0 
+119 119 119 238 238 238 119 119 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 17 17 17 
+238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 
+85 85 85 0 0 0 17 17 17 221 221 221 255 255 255 255 255 255 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 102 102 102 0 0 0 136 136 136 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 
+136 136 136 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 
+136 136 136 0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 221 221 221 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 153 153 153 255 255 255 255 255 255 85 85 85 119 119 119 255 255 255 255 255 255 
+102 102 102 0 0 0 0 0 0 136 136 136 255 255 255 255 255 255 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 136 136 136 255 255 255 
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 
+0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 
+255 255 255 255 255 255 136 136 136 0 0 0 0 0 0 0 0 0 17 17 17 221 221 221 
+255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 68 68 68 255 255 255 238 238 238 34 34 34 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 68 68 68 255 255 255 238 238 238 34 34 34 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 204 204 204 255 255 255 255 255 255 
+255 255 255 255 255 255 255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 17 17 17 
+238 238 238 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 
+85 85 85 0 0 0 0 0 0 17 17 17 136 136 136 255 255 255 255 255 255 255 255 255 
+255 255 255 187 187 187 136 136 136 17 17 17 0 0 0 0 0 0 119 119 119 255 255 255 
+255 255 255 255 255 255 136 136 136 187 187 187 255 255 255 255 255 255 204 204 204 0 0 0 
+102 102 102 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 119 119 119 
+0 0 0 0 0 0 0 0 0 0 0 0 102 102 102 187 187 187 255 255 255 255 255 255 
+255 255 255 255 255 255 136 136 136 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 102 102 102 255 255 255 221 221 221 0 0 0 17 17 17 238 238 238 255 255 255 
+34 34 34 0 0 0 0 0 0 0 0 0 119 119 119 255 255 255 255 255 255 255 255 255 
+136 136 136 187 187 187 255 255 255 255 255 255 204 204 204 0 0 0 136 136 136 255 255 255 
+255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 204 204 204 0 0 0 
+0 0 0 0 0 0 0 0 0 17 17 17 170 170 170 255 255 255 255 255 255 255 255 255 
+153 153 153 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 17 17 17 221 221 221 
+255 255 255 102 102 102 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 68 68 68 255 255 255 238 238 238 34 34 34 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 68 68 68 255 255 255 238 238 238 34 34 34 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/memory-move-malloc-end.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/memory-move-malloc-end.patch
new file mode 100644 (file)
index 0000000..9000642
--- /dev/null
@@ -0,0 +1,9 @@
+--- git/arch/arm/plat-omap/include/mach/vmalloc.h      2009-06-09 15:14:54.000000000 -0700
++++ git/arch/arm/plat-omap/include/mach/vmalloc.h      2009-06-09 15:06:35.000000000 -0700
+@@ -17,5 +17,5 @@
+  * along with this program; if not, write to the Free Software
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+  */
+-#define VMALLOC_END     (PAGE_OFFSET + 0x18000000)
++#define VMALLOC_END     (PAGE_OFFSET + 0x28000000)
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/screen-backlight-accessible-by-user.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/screen-backlight-accessible-by-user.patch
new file mode 100644 (file)
index 0000000..14e0934
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/drivers/video/backlight/backlight.c      2009-07-17 12:20:05.000000000 -0700
++++ b/drivers/video/backlight/backlight.c      2009-07-17 12:20:46.000000000 -0700
+@@ -205,7 +205,7 @@
+ static struct device_attribute bl_device_attributes[] = {
+       __ATTR(bl_power, 0644, backlight_show_power, backlight_store_power),
+-      __ATTR(brightness, 0644, backlight_show_brightness,
++      __ATTR(brightness, 0666, backlight_show_brightness,
+                    backlight_store_brightness),
+       __ATTR(actual_brightness, 0444, backlight_show_actual_brightness,
+                    NULL),
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/screen-backlight.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/screen-backlight.patch
new file mode 100644 (file)
index 0000000..65b551f
--- /dev/null
@@ -0,0 +1,10 @@
+--- a/arch/arm/mach-omap2/Kconfig
++++ b/arch/arm/mach-omap2/Kconfig
+@@ -128,6 +128,7 @@ config MACH_OMAP3EVM
+ config MACH_OMAP3_BEAGLE
+       bool "OMAP3 BEAGLE board"
+       depends on ARCH_OMAP3 && ARCH_OMAP34XX
++      select BACKLIGHT_CLASS_DEVICE
+ config MACH_OVERO
+       bool "Gumstix Overo board"
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/sound-headphone-detection.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/sound-headphone-detection.patch
new file mode 100644 (file)
index 0000000..ef8b362
--- /dev/null
@@ -0,0 +1,93 @@
+From db8f1eba9154789c45c6a92413bbbd94f5d9c7f5 Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Wed, 29 Apr 2009 17:30:25 -0700
+Subject: [PATCH] Touch Book: turn on/off the class D amplifier depending on whether the
+ headphones are plugged into the jack or not.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ sound/soc/omap/omap3beagle.c |   33 +++++++++++++++++++++++++++++++++
+ 1 files changed, 33 insertions(+), 0 deletions(-)
+
+diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
+index fd24a4a..1236638 100644
+--- a/sound/soc/omap/omap3beagle.c
++++ b/sound/soc/omap/omap3beagle.c
+@@ -20,7 +20,10 @@
+  */
+ #include <linux/clk.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
+ #include <linux/platform_device.h>
++
+ #include <sound/core.h>
+ #include <sound/pcm.h>
+ #include <sound/soc.h>
+@@ -35,6 +38,9 @@
+ #include "omap-pcm.h"
+ #include "../codecs/twl4030.h"
++#define TB_HEADPHONE_GPIO 56
++#define TB_HEADPHONE_IRQ  OMAP_GPIO_IRQ(TB_HEADPHONE_GPIO)
++
+ static int omap3beagle_hw_params(struct snd_pcm_substream *substream,
+       struct snd_pcm_hw_params *params)
+ {
+@@ -103,6 +109,33 @@ static struct snd_soc_device omap3beagle_snd_devdata = {
+ static struct platform_device *omap3beagle_snd_device;
++static void jack_work_func(struct work_struct *wq)
++{
++      struct snd_soc_device *socdev = platform_get_drvdata(omap3beagle_snd_device);
++      struct snd_soc_codec *codec = socdev->codec;
++
++      snd_soc_dapm_sync(codec);
++}
++DECLARE_WORK(jack_work, jack_work_func);
++
++static irqreturn_t touchbook_headphone_event(int irq, void *snd)
++{
++      int status = gpio_get_value(TB_HEADPHONE_GPIO);
++      struct snd_soc_device *socdev = platform_get_drvdata(omap3beagle_snd_device);
++      struct snd_soc_codec *codec = socdev->codec;
++
++      if(status) {
++              snd_soc_dapm_disable_pin(codec, "HFL");
++              snd_soc_dapm_disable_pin(codec, "HFR");
++        } else {
++              snd_soc_dapm_enable_pin(codec, "HFL");
++              snd_soc_dapm_enable_pin(codec, "HFR");
++      }
++
++      schedule_work(&jack_work);
++      return IRQ_HANDLED;
++}
++
+ static int __init omap3beagle_soc_init(void)
+ {
+       int ret;
+@@ -123,10 +156,22 @@ static int __init omap3beagle_soc_init(void)
+       omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev;
+       *(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */
++      /* Touch Book -- headphone jack sensor */
++      omap_set_gpio_debounce(TB_HEADPHONE_GPIO, 1);
++      omap_set_gpio_debounce_time(TB_HEADPHONE_GPIO, 0xff);
++
++      ret = request_irq(TB_HEADPHONE_IRQ, touchbook_headphone_event, IRQF_TRIGGER_RISING |
++                        IRQF_TRIGGER_FALLING, "touchbook_headphone", omap3beagle_snd_device);
++      if (ret < 0)
++              goto err1;
++
+       ret = platform_device_add(omap3beagle_snd_device);
+       if (ret)
+               goto err1;
++      /* Detect headphone status */
++      touchbook_headphone_event(0, omap3beagle_snd_device);
++
+       return 0;
+ err1:
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/tincantools-puppy.diff b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/tincantools-puppy.diff
new file mode 100644 (file)
index 0000000..c785673
--- /dev/null
@@ -0,0 +1,66 @@
+--- /tmp/board-omap3beagle.c   2009-07-01 01:06:44.000000000 +0200
++++ git/arch/arm/mach-omap2/board-omap3beagle.c        2009-07-01 01:06:50.000000000 +0200
+@@ -125,6 +125,13 @@
+               .wires          = 8,
+               .gpio_wp        = 29,
+       },
++      {
++              .mmc            = 2,
++              .wires          = 4,
++              .gpio_wp        = 141,
++              .gpio_cd        = 162,
++        .transceiver    = true,
++      },
+       {}      /* Terminator */
+ };
+@@ -132,6 +139,11 @@
+       .supply                 = "vmmc",
+ };
++static struct regulator_consumer_supply beagle_vmmc2_supply = {
++    .supply         = "vmmc",
++};
++
++
+ static struct regulator_consumer_supply beagle_vsim_supply = {
+       .supply                 = "vmmc_aux",
+ };
+@@ -148,6 +160,7 @@
+       /* link regulators to MMC adapters */
+       beagle_vmmc1_supply.dev = mmc[0].dev;
++      beagle_vmmc2_supply.dev = mmc[1].dev;
+       beagle_vsim_supply.dev = mmc[0].dev;
+       /* REVISIT: need ehci-omap hooks for external VBUS
+@@ -209,6 +222,21 @@
+       .consumer_supplies      = &beagle_vmmc1_supply,
+ };
++/* VMMC2 for MMC2 pins CMD, CLK, DAT0..DAT3 (max 100 mA) */
++static struct regulator_init_data beagle_vmmc2 = {
++      .constraints = {
++              .min_uV                 = 2700000,
++              .max_uV                 = 3150000,
++              .valid_modes_mask       = REGULATOR_MODE_NORMAL
++                                      | REGULATOR_MODE_STANDBY,
++              .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE
++                                      | REGULATOR_CHANGE_MODE
++                                      | REGULATOR_CHANGE_STATUS,
++      },
++      .num_consumer_supplies  = 1,
++      .consumer_supplies      = &beagle_vmmc2_supply,
++};
++
+ /* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
+ static struct regulator_init_data beagle_vsim = {
+       .constraints = {
+@@ -284,6 +312,7 @@
+       .gpio           = &beagle_gpio_data,
+       .power          = &beagle_power_data,
+       .vmmc1          = &beagle_vmmc1,
++      .vmmc2          = &beagle_vmmc2,
+       .vsim           = &beagle_vsim,
+       .vdac           = &beagle_vdac,
+       .vpll2          = &beagle_vpll2,
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/touchscreen-ads7846-export-settings.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/touchscreen-ads7846-export-settings.patch
new file mode 100644 (file)
index 0000000..f8353af
--- /dev/null
@@ -0,0 +1,87 @@
+diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
+index 7c3897f..0c62ace 100644
+--- a/drivers/input/touchscreen/ads7846.c
++++ b/drivers/input/touchscreen/ads7846.c
+@@ -491,9 +491,82 @@ static ssize_t ads7846_disable_store(struct device *dev,
+ static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);
++static ssize_t show_debounce_max(struct device *dev, struct device_attribute *attr, char *buf) {
++      struct ads7846 *ts = dev_get_drvdata(dev);
++      return sprintf(buf, "%u\n", ts->debounce_max);
++}
++
++static ssize_t show_debounce_tol(struct device *dev, struct device_attribute *attr, char *buf) {
++      struct ads7846 *ts = dev_get_drvdata(dev);
++      return sprintf(buf, "%u\n", ts->debounce_tol);
++}
++
++static ssize_t show_debounce_rep(struct device *dev, struct device_attribute *attr, char *buf) {
++      struct ads7846 *ts = dev_get_drvdata(dev);
++      return sprintf(buf, "%u\n", ts->debounce_rep);
++}
++
++static ssize_t show_x_plate_ohms(struct device *dev, struct device_attribute *attr, char *buf) {
++      struct ads7846 *ts = dev_get_drvdata(dev);
++      return sprintf(buf, "%u\n", ts->x_plate_ohms);
++}
++
++static ssize_t write_debounce_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
++      struct ads7846 *ts = dev_get_drvdata(dev);
++      unsigned long i;
++
++        if (strict_strtoul(buf, 10, &i))
++              return -EINVAL;
++
++      ts->debounce_max = i;
++      return count;
++}
++
++static ssize_t write_debounce_tol(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
++      struct ads7846 *ts = dev_get_drvdata(dev);
++      unsigned long i;
++
++        if (strict_strtoul(buf, 10, &i))
++              return -EINVAL;
++
++      ts->debounce_tol = i;
++      return count;
++}
++
++static ssize_t write_debounce_rep(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
++      struct ads7846 *ts = dev_get_drvdata(dev);
++      unsigned long i;
++
++        if (strict_strtoul(buf, 10, &i))
++              return -EINVAL;
++
++      ts->debounce_rep = i;
++      return count;
++}
++
++static ssize_t write_x_plate_ohms(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
++      struct ads7846 *ts = dev_get_drvdata(dev);
++      unsigned long i;
++
++        if (strict_strtoul(buf, 10, &i))
++              return -EINVAL;
++
++      ts->x_plate_ohms = i;
++      return count;
++}
++
++static DEVICE_ATTR(debounce_max, S_IRUGO | S_IWUGO, show_debounce_max, write_debounce_max);
++static DEVICE_ATTR(debounce_tol, S_IRUGO | S_IWUGO, show_debounce_tol, write_debounce_tol);
++static DEVICE_ATTR(debounce_rep, S_IRUGO | S_IWUGO, show_debounce_rep, write_debounce_rep);
++static DEVICE_ATTR(x_plate_ohms, S_IRUGO | S_IWUGO, show_x_plate_ohms, write_x_plate_ohms);
++
+ static struct attribute *ads784x_attributes[] = {
+       &dev_attr_pen_down.attr,
+       &dev_attr_disable.attr,
++      &dev_attr_debounce_max.attr,
++      &dev_attr_debounce_tol.attr,
++      &dev_attr_debounce_rep.attr,
++      &dev_attr_x_plate_ohms.attr,
+       NULL,
+ };
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/touchscreen-ads7846-rotation-support.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/touchscreen-ads7846-rotation-support.patch
new file mode 100644 (file)
index 0000000..6196716
--- /dev/null
@@ -0,0 +1,108 @@
+diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
+index 0c62ace..8f6e83c 100644
+--- a/drivers/input/touchscreen/ads7846.c
++++ b/drivers/input/touchscreen/ads7846.c
+@@ -127,6 +127,7 @@ struct ads7846 {
+       void                    (*filter_cleanup)(void *data);
+       int                     (*get_pendown_state)(void);
+       int                     gpio_pendown;
++      int                     rotate;
+ };
+ /* leave chip selected when we're done, for quicker re-select? */
+@@ -511,6 +512,11 @@ static ssize_t show_x_plate_ohms(struct device *dev, struct device_attribute *at
+       return sprintf(buf, "%u\n", ts->x_plate_ohms);
+ }
++static ssize_t show_rotate(struct device *dev, struct device_attribute *attr, char *buf) {
++      struct ads7846 *ts = dev_get_drvdata(dev);
++      return sprintf(buf, "%u\n", ts->rotate);
++}
++
+ static ssize_t write_debounce_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
+       struct ads7846 *ts = dev_get_drvdata(dev);
+       unsigned long i;
+@@ -555,10 +561,22 @@ static ssize_t write_x_plate_ohms(struct device *dev, struct device_attribute *a
+       return count;
+ }
++static ssize_t write_rotate(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
++        struct ads7846 *ts = dev_get_drvdata(dev);
++        unsigned long i = 0;
++
++        if (strict_strtoul(buf, 10, &i) || i > 3)
++                return -EINVAL;
++
++        ts->rotate = i;
++        return count;
++}
++
+ static DEVICE_ATTR(debounce_max, S_IRUGO | S_IWUGO, show_debounce_max, write_debounce_max);
+ static DEVICE_ATTR(debounce_tol, S_IRUGO | S_IWUGO, show_debounce_tol, write_debounce_tol);
+ static DEVICE_ATTR(debounce_rep, S_IRUGO | S_IWUGO, show_debounce_rep, write_debounce_rep);
+ static DEVICE_ATTR(x_plate_ohms, S_IRUGO | S_IWUGO, show_x_plate_ohms, write_x_plate_ohms);
++static DEVICE_ATTR(rotate, S_IRUGO | S_IWUGO, show_rotate, write_rotate);
+ static struct attribute *ads784x_attributes[] = {
+       &dev_attr_pen_down.attr,
+@@ -567,6 +585,7 @@ static struct attribute *ads784x_attributes[] = {
+       &dev_attr_debounce_tol.attr,
+       &dev_attr_debounce_rep.attr,
+       &dev_attr_x_plate_ohms.attr,
++      &dev_attr_rotate.attr,
+       NULL,
+ };
+@@ -596,6 +615,8 @@ static void ads7846_rx(void *ads)
+ {
+       struct ads7846          *ts = ads;
+       struct ads7846_packet   *packet = ts->packet;
++      struct ads7846_platform_data *pdata = ts->spi->dev.platform_data;
++
+       unsigned                Rt;
+       u16                     x, y, z1, z2;
+@@ -657,6 +678,7 @@ static void ads7846_rx(void *ads)
+        * timer by reading the pen signal state (it's a GPIO _and_ IRQ).
+        */
+       if (Rt) {
++              int t;
+               struct input_dev *input = ts->input;
+               if (!ts->pendown) {
+@@ -666,6 +688,27 @@ static void ads7846_rx(void *ads)
+                       dev_dbg(&ts->spi->dev, "DOWN\n");
+ #endif
+               }
++
++              switch(ts->rotate)
++              {
++                      case 0:
++                              x = pdata->x_max - x + pdata->x_min;
++                              y = pdata->y_max - y + pdata->y_min;
++                              break;
++                      case 1:
++                              t = x;
++                              x = pdata->x_max - (((y - pdata->y_min) * (pdata->x_max - pdata->x_min)) / (pdata->y_max - pdata->y_min));
++                              y = pdata->y_min + (((t - pdata->x_min) * (pdata->y_max - pdata->y_min)) / (pdata->x_max - pdata->x_min));
++                              break;
++                      case 2:
++                              break;
++                      case 3:
++                              t = x;
++                              x = pdata->x_min + (((y - pdata->y_min) * (pdata->x_max - pdata->x_min)) / (pdata->y_max - pdata->y_min));
++                              y = pdata->y_max - (((t - pdata->x_min) * (pdata->y_max - pdata->y_min)) / (pdata->x_max - pdata->x_min));
++                              break;
++              }
++
+               input_report_abs(input, ABS_X, x);
+               input_report_abs(input, ABS_Y, y);
+               input_report_abs(input, ABS_PRESSURE, Rt);
+@@ -980,6 +1023,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
+       dev_set_drvdata(&spi->dev, ts);
++      ts->rotate = 0;
+       ts->packet = packet;
+       ts->spi = spi;
+       ts->input = input_dev;
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/usb-lower-current-consumption-upon-insertion.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/usb-lower-current-consumption-upon-insertion.patch
new file mode 100644 (file)
index 0000000..e2df6cf
--- /dev/null
@@ -0,0 +1,30 @@
+--- a/drivers/usb/core/hub.c   2009-07-28 08:47:00.000000000 -0700
++++ b/drivers/usb/core/hub.c   2009-07-28 08:32:20.000000000 -0700
+@@ -22,6 +22,7 @@
+ #include <linux/kthread.h>
+ #include <linux/mutex.h>
+ #include <linux/freezer.h>
++#include <linux/gpio.h>
+ #include <asm/uaccess.h>
+ #include <asm/byteorder.h>
+@@ -3129,9 +3130,18 @@
+                                       USB_PORT_FEAT_C_RESET);
+                       }
+-                      if (connect_change)
++                      if (connect_change) {
++                              if(portstatus & USB_PORT_STAT_CONNECTION) {
++                                      gpio_set_value(176,0);
++                                      mdelay(25);
++                              }
+                               hub_port_connect_change(hub, i,
+                                               portstatus, portchange);
++                              if(portstatus & USB_PORT_STAT_CONNECTION) {
++                                      mdelay(75);
++                                      gpio_set_value(176,1);
++                              }
++                      }
+               } /* end for i */
+               /* deal with hub status changes */
diff --git a/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/usb-otg-pc-connection.patch b/recipes/linux/linux-omap-pm-2.6.29/omap3-touchbook/usb-otg-pc-connection.patch
new file mode 100644 (file)
index 0000000..2bcfbdc
--- /dev/null
@@ -0,0 +1,36 @@
+--- git/drivers/usb/gadget/file_storage.c      2009-06-07 12:18:05.000000000 -0700
++++ git/drivers/usb/gadget/file_storage.c      2009-06-07 12:08:36.000000000 -0700
+@@ -283,8 +283,8 @@
+  *
+  * DO NOT REUSE THESE IDs with any other driver!!  Ever!!
+  * Instead:  allocate your own, using normal USB-IF procedures. */
+-#define DRIVER_VENDOR_ID      0x0525  // NetChip
+-#define DRIVER_PRODUCT_ID     0xa4a5  // Linux-USB File-backed Storage Gadget
++#define DRIVER_VENDOR_ID      0xa110  // Always Innovating, Inc.
++#define DRIVER_PRODUCT_ID     0x0001  // Tablet product
+ /*
+@@ -2025,9 +2025,9 @@
+ {
+       u8      *buf = (u8 *) bh->buf;
+-      static char vendor_id[] = "Linux   ";
++      static char vendor_id[] = "AI, Inc.";
+       static char product_disk_id[] = "File-Stor Gadget";
+-      static char product_cdrom_id[] = "File-CD Gadget  ";
++      static char product_cdrom_id[] = "Touch Book      ";
+       if (!fsg->curlun) {             // Unsupported LUNs are okay
+               fsg->bad_lun_okay = 1;
+@@ -3671,8 +3671,8 @@
+       }
+       if (num_sectors < min_sectors) {
+               LINFO(curlun, "file too small: %s\n", filename);
+-              rc = -ETOOSMALL;
+-              goto out;
++//            rc = -ETOOSMALL;
++//            goto out;
+       }
+       get_file(filp);
index 3a587b2..b635f21 100644 (file)
@@ -3,7 +3,7 @@ require linux.inc
 DESCRIPTION = "Linux kernel for OMAP processors"
 KERNEL_IMAGETYPE = "uImage"
 
-COMPATIBLE_MACHINE = "omap5912osk|omap1710h3|omap2430sdp|omap2420h4|beagleboard|omap3evm|omap3-pandora|overo"
+COMPATIBLE_MACHINE = "omap5912osk|omap1710h3|omap2430sdp|omap2420h4|beagleboard|omap3evm|omap3-pandora|overo|omap3-touchbook"
 
 SRCREV = "e63cf0710a4fb639d91d3e8b05aa485fbfa381b3"
 
@@ -165,6 +165,39 @@ SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \
                                file://tincantools-zippy.diff;patch=1 \
 "
 
+SRC_URI_append_omap3-touchbook = " \
+           file://beagle-asoc.patch;patch=1 \
+           file://accelerometer-mma7455l.patch;patch=1 \
+           file://accelerometer-touchscreen-mux-spi.patch;patch=1 \
+           file://touchscreen-ads7846-export-settings.patch;patch=1 \
+           file://touchscreen-ads7846-rotation-support.patch;patch=1 \
+           file://dspbridge.patch;patch=1 \
+           file://battery2-bq27200-no-error-message.patch;patch=1 \
+           file://sound-headphone-detection.patch;patch=1 \
+           file://dss2-fix-XY-coordinates-when-rotating.patch;patch=1 \
+           file://screen-backlight.patch;patch=1 \
+           file://battery1-tps65950-charging-management-1.patch;patch=1 \
+           file://dss2-fix-scaling-when-rotating.patch;patch=1 \
+           file://dss2-export-status.patch;patch=1 \
+           file://usb-otg-pc-connection.patch;patch=1 \
+           file://battery1-tps65950-charging-management-2.patch;patch=1 \
+           file://memory-move-malloc-end.patch;patch=1 \
+           file://aufs-1.patch;patch=1 \
+           file://aufs-2.patch;patch=1 \
+           file://aufs-3.patch;patch=1 \
+           file://aufs-squashfs-mount-to-avoid-initramfs.patch;patch=1 \
+           file://screen-backlight-accessible-by-user.patch;patch=1 \
+           file://dss2-blank-rotate-accessible-by-user.patch;patch=1 \
+           file://boot-no-power-message.patch;patch=1 \
+           file://usb-lower-current-consumption-upon-insertion.patch;patch=1 \
+           file://battery2-bq27200-gpio-charged.patch;patch=1 \
+           file://board-omap3beagle.c \
+"
+
+do_configure_prepend_omap3-touchbook() {
+    cp ${WORKDIR}/board-omap3beagle.c ${S}/arch/arm/mach-omap2
+}
+
 SRC_URI_append_omap3evm = " \
        file://evm-mcspi-ts.diff;patch=1 \
 "