text:
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:

// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice, this
//   list of conditions and the following disclaimer in the documentation and/or other
//   materials provided with the distribution.
// * The name of the contributors may not be used to endorse or promote products
//   derived from this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef QSLOG_H
#define QSLOG_H

#include "QsLogLevel.h"
#include "QsLogDest.h"
#include <QDebug>
#include <QString>

#define QS_LOG_VERSION "2.0b3"

namespace QsLogging
{
class Destination;
class LoggerImpl; // d pointer

class QSLOG_SHARED_OBJECT Logger
{
public:
    static Logger& instance();
    static void destroyInstance();
    static Level levelFromLogMessage(const QString& logMessage, bool* conversionSucceeded = 0);

    ~Logger();

    //! Adds a log message destination. Don't add null destinations.
    void addDestination(DestinationPtr destination);
    //! Logging at a level < 'newLevel' will be ignored
    void setLoggingLevel(Level newLevel);
    //! The default level is INFO
    Level loggingLevel() const;

    //! The helper forwards the streaming to QDebug and builds the final
    //! log message.
    class QSLOG_SHARED_OBJECT Helper
    {
    public:
        explicit Helper(Level logLevel) :
            level(logLevel),
            qtDebug(&buffer) {}
        ~Helper();
        QDebug& stream(){ return qtDebug; }

    private:
        void writeToLog();

        Level level;
        QString buffer;
        QDebug qtDebug;
    };

private:
    Logger();
    Logger(const Logger&);            // not available
    Logger& operator=(const Logger&); // not available

    void enqueueWrite(const QString& message, Level level);
    void write(const QString& message, Level level);

    LoggerImpl* d;

    friend class LogWriterRunnable;
};

} // end namespace

//! Logging macros: define QS_LOG_LINE_NUMBERS to get the file and line number
//! in the log output.
#ifndef QS_LOG_LINE_NUMBERS
#define QLOG_TRACE() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::TraceLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::TraceLevel).stream()
#define QLOG_DEBUG() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::DebugLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::DebugLevel).stream()
#define QLOG_INFO()  \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::InfoLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::InfoLevel).stream()
#define QLOG_WARN()  \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::WarnLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::WarnLevel).stream()
#define QLOG_ERROR() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::ErrorLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::ErrorLevel).stream()
#define QLOG_FATAL() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::FatalLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::FatalLevel).stream()
#else
#define QLOG_TRACE() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::TraceLevel) {} \
    else  QsLogging::Logger::Helper(QsLogging::TraceLevel).stream() << __FILE__ << '@' << __LINE__
#define QLOG_DEBUG() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::DebugLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::DebugLevel).stream() << __FILE__ << '@' << __LINE__
#define QLOG_INFO()  \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::InfoLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::InfoLevel).stream() << __FILE__ << '@' << __LINE__
#define QLOG_WARN()  \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::WarnLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::WarnLevel).stream() << __FILE__ << '@' << __LINE__
#define QLOG_ERROR() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::ErrorLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::ErrorLevel).stream() << __FILE__ << '@' << __LINE__
#define QLOG_FATAL() \
    if (QsLogging::Logger::instance().loggingLevel() > QsLogging::FatalLevel) {} \
    else QsLogging::Logger::Helper(QsLogging::FatalLevel).stream() << __FILE__ << '@' << __LINE__
#endif

#ifdef QS_LOG_DISABLE
#include "QsLogDisableForThisFile.h"
#endif

#endif // QSLOG_H

redpajama_set_name: RedPajamaGithub


text:
import { Component } from '@angular/core';

import { HighlightDirective } from './shared/highlight.directive';

@Component({
  moduleId: module.id,
  selector: 'sg-app',
  templateUrl: 'app.component.html',
  directives: [HighlightDirective]
})
export class AppComponent { }


text:
package br.senac.tads4.piiv.model;

import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import br.senac.tads4.piiv.model.enumerated.Alimentacao;
import br.senac.tads4.piiv.model.enumerated.Conexao;
import br.senac.tads4.piiv.model.enumerated.Cor;

@Entity
@Table(name = "controle")
@PrimaryKeyJoinColumn(name = "id_produto")
public class Controle extends Produto {

	private static final long serialVersionUID = 1L;

	@NotBlank(message = "Fabricante é obrigatório")
	@Size(max = 50, message = "O campo fabricante deve ter no máximo 50 caracteres")
	private String fabricante;

	@NotNull(message = "Conexão é obrigatório")
	@Enumerated(EnumType.STRING)
	private Conexao conexao;

	@NotNull(message = "Alimentação é obrigatório")
	@Enumerated(EnumType.STRING)
	private Alimentacao alimentacao;

	@NotBlank(message = "Alcance é obrigatório")
	@Size(max = 3, message = "O campo fabricante deve ter no máximo 3 caracteres")
	private String alcance;

	@NotNull(message = "Cor é obrigatório")
	@Enumerated(EnumType.STRING)
	private Cor cor;

	public String getFabricante() {
		return fabricante;
	}
	public void setFabricante(String fabricante) {
		this.fabricante = fabricante;
	}
	public Conexao getConexao() {
		return conexao;
	}
	public void setConexao(Conexao conexao) {
		this.conexao = conexao;
	}
	public Alimentacao getAlimentacao() {
		return alimentacao;
	}
	public void setAlimentacao(Alimentacao alimentacao) {
		this.alimentacao = alimentacao;
	}
	public String getAlcance() {
		return alcance;
	}
	public void setAlcance(String alcance) {
		this.alcance = alcance;
	}
	public Cor getCor() {
		return cor;
	}
	public void setCor(Cor cor) {
		this.cor = cor;
	}
	public static long getSerialversionuid() {
		return serialVersionUID;
	}
}


text:
<?php

/**
 *      [Discuz!] (C)2001-2099 Comsenz Inc.
 *      This is NOT a freeware, use is subject to license terms
 *
 *      $Id: block_myapp.php 28626 2012-03-06 09:10:25Z zhangguosheng $
 */

if(!defined('IN_DISCUZ')) {
	exit('Access Denied');
}

class block_myapp extends discuz_block{

	var $setting = array();

	function block_myapp(){
		$this->setting = array(
			'titlelength' => array(
				'title' => 'myapp_titlelength',
				'type' => 'text',
				'default' => 40
			),
			'startrow' => array(
				'title' => 'myapp_startrow',
				'type' => 'text',
				'default' => 0
			),
		);
	}

	function name() {
		return lang('blockclass', 'blockclass_myapp_script_myapp');
	}

	function blockclass() {
		return array('myapp', lang('blockclass', 'blockclass_html_myapp'));
	}

	function fields() {
		return array(
				'url' => array('name' => lang('blockclass', 'blockclass_myapp_field_url'), 'formtype' => 'text', 'datatype' => 'string'),
				'title' => array('name' => lang('blockclass', 'blockclass_myapp_field_title'), 'formtype' => 'title', 'datatype' => 'title'),
				'icon' => array('name' => lang('blockclass', 'blockclass_myapp_field_icon'), 'formtype' => 'text', 'datatype' => 'string'),
				'icon_small' => array('name' => lang('blockclass', 'blockclass_myapp_field_icon_small'), 'formtype' => 'text', 'datatype' => 'string'),
				'icon_abouts' => array('name' => lang('blockclass', 'blockclass_myapp_field_icon_abouts'), 'formtype' => 'text', 'datatype' => 'string'),
			);
	}

	function getsetting() {
		global $_G;
		$settings = $this->setting;

		return $settings;
	}

	function getdata($style, $parameter) {
		global $_G;

		$parameter = $this->cookparameter($parameter);

		$titlelength	= !empty($parameter['titlelength']) ? intval($parameter['titlelength']) : 40;
		$startrow       = !empty($parameter['startrow']) ? intval($parameter['startrow']) : '0';
		$items          = !empty($parameter['items']) ? intval($parameter['items']) : 10;

		$bannedids = !empty($parameter['bannedids']) ? explode(',', $parameter['bannedids']) : array();
		$bansql = $bannedids ? ' AND appid NOT IN ('.dimplode($bannedids).')' : '';

		$sql = 'SELECT * FROM '.DB::table('common_myapp')." WHERE flag>=0 $bansql ORDER BY flag DESC, displayorder LIMIT $startrow, $items";
		$query = DB::query($sql);
		while($data = DB::fetch($query)) {
			$list[] = array(
				'id' => $data['appid'],
				'idtype' => 'appid',
				'title' => cutstr(str_replace('\\\'', ''', $data['appname']), $titlelength, ''),
				'url' => 'userapp.php?id='.$data['appid'],
				'pic' => '',
				'picflag' => '',
				'summary' => '',
				'fields' => array(
					'icon' => 'http://appicon.manyou.com/logos/'.$data['appid'],
					'icon_small' => 'http://appicon.manyou.com/icons/'.$data['appid'],
					'icon_abouts' => 'http://appicon.manyou.com/abouts/'.$data['appid'],
				)
			);
		}
		return array('html' => '', 'data' => $list);
	}
}

?>


text:
r"""Electronic Voting Example.

In this example we use DeepSets to estimate the winner of an election.
Each vote is represented by a one-hot encoded vector.

It goes without saying, but don't use this in a real election!
Seriously, don't!
"""

import collections
import logging
import random

from absl import app
import haiku as hk
import jax
import jax.numpy as jnp
import jraph
import numpy as np
import optax

Problem = collections.namedtuple("Problem", ("graph", "labels"))

def get_voting_problem(min_n_voters: int, max_n_voters: int) -> Problem:
  """Creates set of one-hot vectors representing a randomly generated election.

  Args:
    min_n_voters: minimum number of voters in the election.
    max_n_voters: maximum number of voters in the election.

  Returns:
    set, one-hot vector encoding the winner.
  """
  n_candidates = 20
  n_voters = random.randint(min_n_voters, max_n_voters)
  votes = np.random.randint(0, n_candidates, size=(n_voters,))
  one_hot_votes = np.eye(n_candidates)[votes]
  winner = np.argmax(np.sum(one_hot_votes, axis=0))
  one_hot_winner = np.eye(n_candidates)[winner]

  graph = jraph.GraphsTuple(
      n_node=np.asarray([n_voters]),
      n_edge=np.asarray([0]),
      nodes=one_hot_votes,
      edges=None,
      globals=np.zeros((1, n_candidates)),
      # There are no edges in our graph.
      senders=np.array([], dtype=np.int32),
      receivers=np.array([], dtype=np.int32))

  # In order to jit compile our code, we have to pad the nodes and edges of
  # the GraphsTuple to a static shape.
  graph = jraph.pad_with_graphs(graph, max_n_voters+1, 0)

  return Problem(graph=graph, labels=one_hot_winner)

def network_definition(
    graph: jraph.GraphsTuple,
    num_message_passing_steps: int = 1) -> jraph.ArrayTree:
  """Defines a graph neural network.

  Args:
    graph: Graphstuple the network processes.
    num_message_passing_steps: number of message passing steps.

  Returns:
    globals.
  """

  @jax.vmap
  def update_fn(*args):
    size = args[0].shape[-1]
    return hk.nets.MLP([size, size])(jnp.concatenate(args, axis=-1))

  for _ in range(num_message_passing_steps):
    gn = jraph.DeepSets(
        update_node_fn=update_fn,
        update_global_fn=update_fn,
        aggregate_nodes_for_globals_fn=jraph.segment_mean,
        )
    graph = gn(graph)

  return hk.Linear(graph.globals.shape[-1])(graph.globals)

def train(num_steps: int):
  """Trains a graph neural network on an electronic voting problem."""
  train_dataset = (2, 15)
  test_dataset = (16, 20)
  random.seed(42)

  network = hk.without_apply_rng(hk.transform(network_definition))
  problem = get_voting_problem(*train_dataset)
  params = network.init(jax.random.PRNGKey(42), problem.graph)

  @jax.jit
  def prediction_loss(params, problem):
    globals_ = network.apply(params, problem.graph)
    # We interpret the globals as logits for the winner.
    # Only the first graph is real, the second graph is for padding.
    log_prob = jax.nn.log_softmax(globals_[0]) * problem.labels
    return -jnp.sum(log_prob)

  @jax.jit
  def accuracy_loss(params, problem):
    globals_ = network.apply(params, problem.graph)
    # We interpret the globals as logits for the winner.
    # Only the first graph is real, the second graph is for padding.
    equal = jnp.argmax(globals_[0]) == jnp.argmax(problem.labels)
    return equal.astype(np.int32)

  opt_init, opt_update = optax.adam(2e-4)
  opt_state = opt_init(params)

  @jax.jit
  def update(params, opt_state, problem):
    g = jax.grad(prediction_loss)(params, problem)
    updates, opt_state = opt_update(g, opt_state)
    return optax.apply_updates(params, updates), opt_state

  for step in range(num_steps):
    problem = get_voting_problem(*train_dataset)
    params, opt_state = update(params, opt_state, problem)
    if step % 1000 == 0:
      train_loss = jnp.mean(
          jnp.asarray([
              accuracy_loss(params, get_voting_problem(*train_dataset))
              for _ in range(100)
          ])).item()
      test_loss = jnp.mean(
          jnp.asarray([
              accuracy_loss(params, get_voting_problem(*test_dataset))
              for _ in range(100)
          ])).item()
      logging.info("step %r loss train %r test %r", step, train_loss, test_loss)

def main(argv):
  if len(argv) > 1:
    raise app.UsageError("Too many command-line arguments.")

  train(num_steps=100000)

if __name__ == "__main__":
  app.run(main)


text:
package integration

import (
	"encoding/base64"
	"encoding/json"
	"os"
	"testing"
	"time"

	"github.com/stretchr/testify/require"
)

func binPath() string {
	return os.Getenv("INTEGRATION_TEST_BINARY_PATH")
}

func toBase64(t *testing.T, str string) string {
	bytes := base64.StdEncoding.EncodeToString([]byte(str))
	return string(bytes)
}

func toJSON(t *testing.T, stringStringMap map[string]string) string {
	bytes, err := json.Marshal(stringStringMap)
	require.NoError(t, err)
	return string(bytes)
}

func withRunningTimeCheck(f func(), ms time.Duration) time.Duration {
	start := time.Now()
	f()
	end := time.Now()

	return end.Sub(start)
}


text:
'use strict';

module.exports = ['tasks'];


text:
(function() {

  var ACTIVE_PUZZLE_EVENTS = ['modifiedPuzzle', 'remoteChange',
    'switchedPuzzle', 'addedPuzzle'];
  var GLOBAL_SETTING_EVENTS = ['remoteChange', 'modifiedGlobalSettings'];
  var LATEST_SOLVE_EVENTS = ['modifiedSolve', 'addedSolve', 'deletedSolve',
    'switchedPuzzle', 'addedPuzzle', 'remoteChange'];
  var PUZZLE_COUNT_EVENTS = ['addedPuzzle', 'deletedPuzzle', 'remoteChange'];

  function Observe() {
  }

  Observe.prototype.activePuzzle = function(attrs, callback) {
    return this._observeAttrs(ACTIVE_PUZZLE_EVENTS, function() {
      return window.app.store.getActivePuzzle();
    }, attrs, callback);
  };

  Observe.prototype.globalSettings = function(attrs, callback) {
    return this._observeAttrs(GLOBAL_SETTING_EVENTS, function() {
      return window.app.store.getGlobalSettings();
    }, attrs, callback);
  };

  Observe.prototype.latestSolve = function(attrs, callback) {
    return this._observeAttrs(LATEST_SOLVE_EVENTS, function() {
      return window.app.store.getLatestSolve();
    }, attrs, callback);
  };

  Observe.prototype.puzzleCount = function(callback) {
    var count = window.app.store.getPuzzles().length;
    return new Observation(PUZZLE_COUNT_EVENTS, function() {
      var newCount = window.app.store.getPuzzles().length;
      if (newCount !== count) {
        count = newCount;
        callback();
      }
    }).start();
  };

  // _observeAttrs observes attribute changes on objFunc() for a set of events.
  Observe.prototype._observeAttrs = function(events, objFunc, attrs, cb) {
    if ('string' === typeof attrs) {
      attrs = [attrs];
    } else {
      attrs = attrs.slice();
    }

    var currentValues = extractProperties(objFunc(), attrs);
    return new Observation(events, function() {
      var changed = false;
      var obj = objFunc();

      if (currentValues === null && obj !== null) {
        changed = true;
        currentValues = extractProperties(obj, attrs);
      } else if (currentValues !== null && obj === null) {
        changed = true;
        currentValues = null;
      } else if (currentValues !== null && obj !== null) {
        for (var i = 0, len = attrs.length; i < len; ++i) {
          var attr = attrs[i];
          var newValue = obj[attr];
          if (newValue !== currentValues[attr]) {
            currentValues[attr] = newValue;
            changed = true;
          }
        }
      }

      if (changed) {
        cb();
      }
    }).start();
  }

  function Observation(events, handler) {
    this._events = events;
    this._handler = handler;
    this._started = false;
  }

  Observation.prototype.isRunning = function() {
    return this._started;
  };

  Observation.prototype.start = function() {
    if (this._started) {
      return this;
    }
    this._started = true;
    for (var i = 0, len = this._events.length; i < len; ++i) {
      window.app.store.on(this._events[i], this._handler);
    }
    return this;
  };

  Observation.prototype.stop = function() {
    if (!this._started) {
      return this;
    }
    this._started = false;
    for (var i = 0, len = this._events.length; i < len; ++i) {
      window.app.model.removeListener(this._events[i], this._handler);
    }
    return this;
  };

  function extractProperties(object, attrs) {
    if (object === null) {
      return null;
    }
    var res = {};
    for (var i = 0, len = attrs.length; i < len; ++i) {
      var attr = attrs[i];
      res[attr] = object[attr];
    }
    return res;
  }

  window.app.observe = new Observe();

})();


text:
/****************************************************************************/
/**
*   @file   dma.c
*
*   @brief  Implements the DMA interface.
*/
/****************************************************************************/

/* ---- Include Files ---------------------------------------------------- */

#include <linux/module.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/irqreturn.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>

#include <mach/timer.h>

#include <linux/mm.h>
#include <linux/pfn.h>
#include <linux/atomic.h>
#include <linux/sched.h>
#include <mach/dma.h>

/* I don't quite understand why dc4 fails when this is set to 1 and DMA is enabled */
/* especially since dc4 doesn't use kmalloc'd memory. */

#define ALLOW_MAP_OF_KMALLOC_MEMORY 0

/* ---- Public Variables ------------------------------------------------- */

/* ---- Private Constants and Types -------------------------------------- */

#define MAKE_HANDLE(controllerIdx, channelIdx)    (((controllerIdx) << 4) | (channelIdx))

#define CONTROLLER_FROM_HANDLE(handle)    (((handle) >> 4) & 0x0f)
#define CHANNEL_FROM_HANDLE(handle)       ((handle) & 0x0f)

#define DMA_MAP_DEBUG   0

#if DMA_MAP_DEBUG
#   define  DMA_MAP_PRINT(fmt, args...)   printk("%s: " fmt, __func__,  ## args)
#else
#   define  DMA_MAP_PRINT(fmt, args...)
#endif

/* ---- Private Variables ------------------------------------------------ */

static DMA_Global_t gDMA;
static struct proc_dir_entry *gDmaDir;

static atomic_t gDmaStatMemTypeKmalloc = ATOMIC_INIT(0);
static atomic_t gDmaStatMemTypeVmalloc = ATOMIC_INIT(0);
static atomic_t gDmaStatMemTypeUser = ATOMIC_INIT(0);
static atomic_t gDmaStatMemTypeCoherent = ATOMIC_INIT(0);

#include "dma_device.c"

/* ---- Private Function Prototypes -------------------------------------- */

/* ---- Functions  ------------------------------------------------------- */

/****************************************************************************/
/**
*   Displays information for /proc/dma/mem-type
*/
/****************************************************************************/

static int dma_proc_read_mem_type(char *buf, char **start, off_t offset,
				  int count, int *eof, void *data)
{
	int len = 0;

	len += sprintf(buf + len, "dma_map_mem statistics\n");
	len +=
	    sprintf(buf + len, "coherent: %d\n",
		    atomic_read(&gDmaStatMemTypeCoherent));
	len +=
	    sprintf(buf + len, "kmalloc:  %d\n",
		    atomic_read(&gDmaStatMemTypeKmalloc));
	len +=
	    sprintf(buf + len, "vmalloc:  %d\n",
		    atomic_read(&gDmaStatMemTypeVmalloc));
	len +=
	    sprintf(buf + len, "user:     %d\n",
		    atomic_read(&gDmaStatMemTypeUser));

	return len;
}

/****************************************************************************/
/**
*   Displays information for /proc/dma/channels
*/
/****************************************************************************/

static int dma_proc_read_channels(char *buf, char **start, off_t offset,
				  int count, int *eof, void *data)
{
	int controllerIdx;
	int channelIdx;
	int limit = count - 200;
	int len = 0;
	DMA_Channel_t *channel;

	if (down_interruptible(&gDMA.lock) < 0) {
		return -ERESTARTSYS;
	}

	for (controllerIdx = 0; controllerIdx < DMA_NUM_CONTROLLERS;
	     controllerIdx++) {
		for (channelIdx = 0; channelIdx < DMA_NUM_CHANNELS;
		     channelIdx++) {
			if (len >= limit) {
				break;
			}

			channel =
			    &gDMA.controller[controllerIdx].channel[channelIdx];

			len +=
			    sprintf(buf + len, "%d:%d ", controllerIdx,
				    channelIdx);

			if ((channel->flags & DMA_CHANNEL_FLAG_IS_DEDICATED) !=
			    0) {
				len +=
				    sprintf(buf + len, "Dedicated for %s ",
					    DMA_gDeviceAttribute[channel->
								 devType].name);
			} else {
				len += sprintf(buf + len, "Shared ");
			}

			if ((channel->flags & DMA_CHANNEL_FLAG_NO_ISR) != 0) {
				len += sprintf(buf + len, "No ISR ");
			}

			if ((channel->flags & DMA_CHANNEL_FLAG_LARGE_FIFO) != 0) {
				len += sprintf(buf + len, "Fifo: 128 ");
			} else {
				len += sprintf(buf + len, "Fifo: 64  ");
			}

			if ((channel->flags & DMA_CHANNEL_FLAG_IN_USE) != 0) {
				len +=
				    sprintf(buf + len, "InUse by %s",
					    DMA_gDeviceAttribute[channel->
								 devType].name);
#if (DMA_DEBUG_TRACK_RESERVATION)
				len +=
				    sprintf(buf + len, " (%s:%d)",
					    channel->fileName,
					    channel->lineNum);
#endif
			} else {
				len += sprintf(buf + len, "Avail ");
			}

			if (channel->lastDevType != DMA_DEVICE_NONE) {
				len +=
				    sprintf(buf + len, "Last use: %s ",
					    DMA_gDeviceAttribute[channel->
								 lastDevType].
					    name);
			}

			len += sprintf(buf + len, "\n");
		}
	}
	up(&gDMA.lock);
	*eof = 1;

	return len;
}

/****************************************************************************/
/**
*   Displays information for /proc/dma/devices
*/
/****************************************************************************/

static int dma_proc_read_devices(char *buf, char **start, off_t offset,
				 int count, int *eof, void *data)
{
	int limit = count - 200;
	int len = 0;
	int devIdx;

	if (down_interruptible(&gDMA.lock) < 0) {
		return -ERESTARTSYS;
	}

	for (devIdx = 0; devIdx < DMA_NUM_DEVICE_ENTRIES; devIdx++) {
		DMA_DeviceAttribute_t *devAttr = &DMA_gDeviceAttribute[devIdx];

		if (devAttr->name == NULL) {
			continue;
		}

		if (len >= limit) {
			break;
		}

		len += sprintf(buf + len, "%-12s ", devAttr->name);

		if ((devAttr->flags & DMA_DEVICE_FLAG_IS_DEDICATED) != 0) {
			len +=
			    sprintf(buf + len, "Dedicated %d:%d ",
				    devAttr->dedicatedController,
				    devAttr->dedicatedChannel);
		} else {
			len += sprintf(buf + len, "Shared DMA:");
			if ((devAttr->flags & DMA_DEVICE_FLAG_ON_DMA0) != 0) {
				len += sprintf(buf + len, "0");
			}
			if ((devAttr->flags & DMA_DEVICE_FLAG_ON_DMA1) != 0) {
				len += sprintf(buf + len, "1");
			}
			len += sprintf(buf + len, " ");
		}
		if ((devAttr->flags & DMA_DEVICE_FLAG_NO_ISR) != 0) {
			len += sprintf(buf + len, "NoISR ");
		}
		if ((devAttr->flags & DMA_DEVICE_FLAG_ALLOW_LARGE_FIFO) != 0) {
			len += sprintf(buf + len, "Allow-128 ");
		}

		len +=
		    sprintf(buf + len,
			    "Xfer #: %Lu Ticks: %Lu Bytes: %Lu DescLen: %u\n",
			    devAttr->numTransfers, devAttr->transferTicks,
			    devAttr->transferBytes,
			    devAttr->ring.bytesAllocated);

	}

	up(&gDMA.lock);
	*eof = 1;

	return len;
}

/****************************************************************************/
/**
*   Determines if a DMA_Device_t is "valid".
*
*   @return
*       TRUE        - dma device is valid
*       FALSE       - dma device isn't valid
*/
/****************************************************************************/

static inline int IsDeviceValid(DMA_Device_t device)
{
	return (device >= 0) && (device < DMA_NUM_DEVICE_ENTRIES);
}

/****************************************************************************/
/**
*   Translates a DMA handle into a pointer to a channel.
*
*   @return
*       non-NULL    - pointer to DMA_Channel_t
*       NULL        - DMA Handle was invalid
*/
/****************************************************************************/

static inline DMA_Channel_t *HandleToChannel(DMA_Handle_t handle)
{
	int controllerIdx;
	int channelIdx;

	controllerIdx = CONTROLLER_FROM_HANDLE(handle);
	channelIdx = CHANNEL_FROM_HANDLE(handle);

	if ((controllerIdx > DMA_NUM_CONTROLLERS)
	    || (channelIdx > DMA_NUM_CHANNELS)) {
		return NULL;
	}
	return &gDMA.controller[controllerIdx].channel[channelIdx];
}

/****************************************************************************/
/**
*   Interrupt handler which is called to process DMA interrupts.
*/
/****************************************************************************/

static irqreturn_t dma_interrupt_handler(int irq, void *dev_id)
{
	DMA_Channel_t *channel;
	DMA_DeviceAttribute_t *devAttr;
	int irqStatus;

	channel = (DMA_Channel_t *) dev_id;

	/* Figure out why we were called, and knock down the interrupt */

	irqStatus = dmacHw_getInterruptStatus(channel->dmacHwHandle);
	dmacHw_clearInterrupt(channel->dmacHwHandle);

	if ((channel->devType < 0)
	    || (channel->devType > DMA_NUM_DEVICE_ENTRIES)) {
		printk(KERN_ERR "dma_interrupt_handler: Invalid devType: %d\n",
		       channel->devType);
		return IRQ_NONE;
	}
	devAttr = &DMA_gDeviceAttribute[channel->devType];

	/* Update stats */

	if ((irqStatus & dmacHw_INTERRUPT_STATUS_TRANS) != 0) {
		devAttr->transferTicks +=
		    (timer_get_tick_count() - devAttr->transferStartTime);
	}

	if ((irqStatus & dmacHw_INTERRUPT_STATUS_ERROR) != 0) {
		printk(KERN_ERR
		       "dma_interrupt_handler: devType :%d DMA error (%s)\n",
		       channel->devType, devAttr->name);
	} else {
		devAttr->numTransfers++;
		devAttr->transferBytes += devAttr->numBytes;
	}

	/* Call any installed handler */

	if (devAttr->devHandler != NULL) {
		devAttr->devHandler(channel->devType, irqStatus,
				    devAttr->userData);
	}

	return IRQ_HANDLED;
}

/****************************************************************************/
/**
*   Allocates memory to hold a descriptor ring. The descriptor ring then
*   needs to be populated by making one or more calls to
*   dna_add_descriptors.
*
*   The returned descriptor ring will be automatically initialized.
*
*   @return
*       0           Descriptor ring was allocated successfully
*       -EINVAL     Invalid parameters passed in
*       -ENOMEM     Unable to allocate memory for the desired number of descriptors.
*/
/****************************************************************************/

int dma_alloc_descriptor_ring(DMA_DescriptorRing_t *ring,	/* Descriptor ring to populate */
			      int numDescriptors	/* Number of descriptors that need to be allocated. */
    ) {
	size_t bytesToAlloc = dmacHw_descriptorLen(numDescriptors);

	if ((ring == NULL) || (numDescriptors <= 0)) {
		return -EINVAL;
	}

	ring->physAddr = 0;
	ring->descriptorsAllocated = 0;
	ring->bytesAllocated = 0;

	ring->virtAddr = dma_alloc_writecombine(NULL,
						     bytesToAlloc,
						     &ring->physAddr,
						     GFP_KERNEL);
	if (ring->virtAddr == NULL) {
		return -ENOMEM;
	}

	ring->bytesAllocated = bytesToAlloc;
	ring->descriptorsAllocated = numDescriptors;

	return dma_init_descriptor_ring(ring, numDescriptors);
}

EXPORT_SYMBOL(dma_alloc_descriptor_ring);

/****************************************************************************/
/**
*   Releases the memory which was previously allocated for a descriptor ring.
*/
/****************************************************************************/

void dma_free_descriptor_ring(DMA_DescriptorRing_t *ring	/* Descriptor to release */
    ) {
	if (ring->virtAddr != NULL) {
		dma_free_writecombine(NULL,
				      ring->bytesAllocated,
				      ring->virtAddr, ring->physAddr);
	}

	ring->bytesAllocated = 0;
	ring->descriptorsAllocated = 0;
	ring->virtAddr = NULL;
	ring->physAddr = 0;
}

EXPORT_SYMBOL(dma_free_descriptor_ring);

/****************************************************************************/
/**
*   Initializes a descriptor ring, so that descriptors can be added to it.
*   Once a descriptor ring has been allocated, it may be reinitialized for
*   use with additional/different regions of memory.
*
*   Note that if 7 descriptors are allocated, it's perfectly acceptable to
*   initialize the ring with a smaller number of descriptors. The amount
*   of memory allocated for the descriptor ring will not be reduced, and
*   the descriptor ring may be reinitialized later
*
*   @return
*       0           Descriptor ring was initialized successfully
*       -ENOMEM     The descriptor which was passed in has insufficient space
*                   to hold the desired number of descriptors.
*/
/****************************************************************************/

int dma_init_descriptor_ring(DMA_DescriptorRing_t *ring,	/* Descriptor ring to initialize */
			     int numDescriptors	/* Number of descriptors to initialize. */
    ) {
	if (ring->virtAddr == NULL) {
		return -EINVAL;
	}
	if (dmacHw_initDescriptor(ring->virtAddr,
				  ring->physAddr,
				  ring->bytesAllocated, numDescriptors) < 0) {
		printk(KERN_ERR
		       "dma_init_descriptor_ring: dmacHw_initDescriptor failed\n");
		return -ENOMEM;
	}

	return 0;
}

EXPORT_SYMBOL(dma_init_descriptor_ring);

/****************************************************************************/
/**
*   Determines the number of descriptors which would be required for a
*   transfer of the indicated memory region.
*
*   This function also needs to know which DMA device this transfer will
*   be destined for, so that the appropriate DMA configuration can be retrieved.
*   DMA parameters such as transfer width, and whether this is a memory-to-memory
*   or memory-to-peripheral, etc can all affect the actual number of descriptors
*   required.
*
*   @return
*       > 0     Returns the number of descriptors required for the indicated transfer
*       -ENODEV - Device handed in is invalid.
*       -EINVAL Invalid parameters
*       -ENOMEM Memory exhausted
*/
/****************************************************************************/

int dma_calculate_descriptor_count(DMA_Device_t device,	/* DMA Device that this will be associated with */
				   dma_addr_t srcData,	/* Place to get data to write to device */
				   dma_addr_t dstData,	/* Pointer to device data address */
				   size_t numBytes	/* Number of bytes to transfer to the device */
    ) {
	int numDescriptors;
	DMA_DeviceAttribute_t *devAttr;

	if (!IsDeviceValid(device)) {
		return -ENODEV;
	}
	devAttr = &DMA_gDeviceAttribute[device];

	numDescriptors = dmacHw_calculateDescriptorCount(&devAttr->config,
							      (void *)srcData,
							      (void *)dstData,
							      numBytes);
	if (numDescriptors < 0) {
		printk(KERN_ERR
		       "dma_calculate_descriptor_count: dmacHw_calculateDescriptorCount failed\n");
		return -EINVAL;
	}

	return numDescriptors;
}

EXPORT_SYMBOL(dma_calculate_descriptor_count);

/****************************************************************************/
/**
*   Adds a region of memory to the descriptor ring. Note that it may take
*   multiple descriptors for each region of memory. It is the callers
*   responsibility to allocate a sufficiently large descriptor ring.
*
*   @return
*       0       Descriptors were added successfully
*       -ENODEV Device handed in is invalid.
*       -EINVAL Invalid parameters
*       -ENOMEM Memory exhausted
*/
/****************************************************************************/

int dma_add_descriptors(DMA_DescriptorRing_t *ring,	/* Descriptor ring to add descriptors to */
			DMA_Device_t device,	/* DMA Device that descriptors are for */
			dma_addr_t srcData,	/* Place to get data (memory or device) */
			dma_addr_t dstData,	/* Place to put data (memory or device) */
			size_t numBytes	/* Number of bytes to transfer to the device */
    ) {
	int rc;
	DMA_DeviceAttribute_t *devAttr;

	if (!IsDeviceValid(device)) {
		return -ENODEV;
	}
	devAttr = &DMA_gDeviceAttribute[device];

	rc = dmacHw_setDataDescriptor(&devAttr->config,
				      ring->virtAddr,
				      (void *)srcData,
				      (void *)dstData, numBytes);
	if (rc < 0) {
		printk(KERN_ERR
		       "dma_add_descriptors: dmacHw_setDataDescriptor failed with code: %d\n",
		       rc);
		return -ENOMEM;
	}

	return 0;
}

EXPORT_SYMBOL(dma_add_descriptors);

/****************************************************************************/
/**
*   Sets the descriptor ring associated with a device.
*
*   Once set, the descriptor ring will be associated with the device, even
*   across channel request/free calls. Passing in a NULL descriptor ring
*   will release any descriptor ring currently associated with the device.
*
*   Note: If you call dma_transfer, or one of the other dma_alloc_ functions
*         the descriptor ring may be released and reallocated.
*
*   Note: This function will release the descriptor memory for any current
*         descriptor ring associated with this device.
*
*   @return
*       0       Descriptors were added successfully
*       -ENODEV Device handed in is invalid.
*/
/****************************************************************************/

int dma_set_device_descriptor_ring(DMA_Device_t device,	/* Device to update the descriptor ring for. */
				   DMA_DescriptorRing_t *ring	/* Descriptor ring to add descriptors to */
    ) {
	DMA_DeviceAttribute_t *devAttr;

	if (!IsDeviceValid(device)) {
		return -ENODEV;
	}
	devAttr = &DMA_gDeviceAttribute[device];

	/* Free the previously allocated descriptor ring */

	dma_free_descriptor_ring(&devAttr->ring);

	if (ring != NULL) {
		/* Copy in the new one */

		devAttr->ring = *ring;
	}

	/* Set things up so that if dma_transfer is called then this descriptor */
	/* ring will get freed. */

	devAttr->prevSrcData = 0;
	devAttr->prevDstData = 0;
	devAttr->prevNumBytes = 0;

	return 0;
}

EXPORT_SYMBOL(dma_set_device_descriptor_ring);

/****************************************************************************/
/**
*   Retrieves the descriptor ring associated with a device.
*
*   @return
*       0       Descriptors were added successfully
*       -ENODEV Device handed in is invalid.
*/
/****************************************************************************/

int dma_get_device_descriptor_ring(DMA_Device_t device,	/* Device to retrieve the descriptor ring for. */
				   DMA_DescriptorRing_t *ring	/* Place to store retrieved ring */
    ) {
	DMA_DeviceAttribute_t *devAttr;

	memset(ring, 0, sizeof(*ring));

	if (!IsDeviceValid(device)) {
		return -ENODEV;
	}
	devAttr = &DMA_gDeviceAttribute[device];

	*ring = devAttr->ring;

	return 0;
}

EXPORT_SYMBOL(dma_get_device_descriptor_ring);

/****************************************************************************/
/**
*   Configures a DMA channel.
*
*   @return
*       >= 0    - Initialization was successful.
*
*       -EBUSY  - Device is currently being used.
*       -ENODEV - Device handed in is invalid.
*/
/****************************************************************************/

static int ConfigChannel(DMA_Handle_t handle)
{
	DMA_Channel_t *channel;
	DMA_DeviceAttribute_t *devAttr;
	int controllerIdx;

	channel = HandleToChannel(handle);
	if (channel == NULL) {
		return -ENODEV;
	}
	devAttr = &DMA_gDeviceAttribute[channel->devType];
	controllerIdx = CONTROLLER_FROM_HANDLE(handle);

	if ((devAttr->flags & DMA_DEVICE_FLAG_PORT_PER_DMAC) != 0) {
		if (devAttr->config.transferType ==
		    dmacHw_TRANSFER_TYPE_MEM_TO_PERIPHERAL) {
			devAttr->config.dstPeripheralPort =
			    devAttr->dmacPort[controllerIdx];
		} else if (devAttr->config.transferType ==
			   dmacHw_TRANSFER_TYPE_PERIPHERAL_TO_MEM) {
			devAttr->config.srcPeripheralPort =
			    devAttr->dmacPort[controllerIdx];
		}
	}

	if (dmacHw_configChannel(channel->dmacHwHandle, &devAttr->config) != 0) {
		printk(KERN_ERR "ConfigChannel: dmacHw_configChannel failed\n");
		return -EIO;
	}

	return 0;
}

/****************************************************************************/
/**
*   Initializes all of the data structures associated with the DMA.
*   @return
*       >= 0    - Initialization was successful.
*
*       -EBUSY  - Device is currently being used.
*       -ENODEV - Device handed in is invalid.
*/
/****************************************************************************/

int dma_init(void)
{
	int rc = 0;
	int controllerIdx;
	int channelIdx;
	DMA_Device_t devIdx;
	DMA_Channel_t *channel;
	DMA_Handle_t dedicatedHandle;

	memset(&gDMA, 0, sizeof(gDMA));

	sema_init(&gDMA.lock, 0);
	init_waitqueue_head(&gDMA.freeChannelQ);

	/* Initialize the Hardware */

	dmacHw_initDma();

	/* Start off by marking all of the DMA channels as shared. */

	for (controllerIdx = 0; controllerIdx < DMA_NUM_CONTROLLERS;
	     controllerIdx++) {
		for (channelIdx = 0; channelIdx < DMA_NUM_CHANNELS;
		     channelIdx++) {
			channel =
			    &gDMA.controller[controllerIdx].channel[channelIdx];

			channel->flags = 0;
			channel->devType = DMA_DEVICE_NONE;
			channel->lastDevType = DMA_DEVICE_NONE;

#if (DMA_DEBUG_TRACK_RESERVATION)
			channel->fileName = "";
			channel->lineNum = 0;
#endif

			channel->dmacHwHandle =
			    dmacHw_getChannelHandle(dmacHw_MAKE_CHANNEL_ID
						    (controllerIdx,
						     channelIdx));
			dmacHw_initChannel(channel->dmacHwHandle);
		}
	}

	/* Record any special attributes that channels may have */

	gDMA.controller[0].channel[0].flags |= DMA_CHANNEL_FLAG_LARGE_FIFO;
	gDMA.controller[0].channel[1].flags |= DMA_CHANNEL_FLAG_LARGE_FIFO;
	gDMA.controller[1].channel[0].flags |= DMA_CHANNEL_FLAG_LARGE_FIFO;
	gDMA.controller[1].channel[1].flags |= DMA_CHANNEL_FLAG_LARGE_FIFO;

	/* Now walk through and record the dedicated channels. */

	for (devIdx = 0; devIdx < DMA_NUM_DEVICE_ENTRIES; devIdx++) {
		DMA_DeviceAttribute_t *devAttr = &DMA_gDeviceAttribute[devIdx];

		if (((devAttr->flags & DMA_DEVICE_FLAG_NO_ISR) != 0)
		    && ((devAttr->flags & DMA_DEVICE_FLAG_IS_DEDICATED) == 0)) {
			printk(KERN_ERR
			       "DMA Device: %s Can only request NO_ISR for dedicated devices\n",
			       devAttr->name);
			rc = -EINVAL;
			goto out;
		}

		if ((devAttr->flags & DMA_DEVICE_FLAG_IS_DEDICATED) != 0) {
			/* This is a dedicated device. Mark the channel as being reserved. */

			if (devAttr->dedicatedController >= DMA_NUM_CONTROLLERS) {
				printk(KERN_ERR
				       "DMA Device: %s DMA Controller %d is out of range\n",
				       devAttr->name,
				       devAttr->dedicatedController);
				rc = -EINVAL;
				goto out;
			}

			if (devAttr->dedicatedChannel >= DMA_NUM_CHANNELS) {
				printk(KERN_ERR
				       "DMA Device: %s DMA Channel %d is out of range\n",
				       devAttr->name,
				       devAttr->dedicatedChannel);
				rc = -EINVAL;
				goto out;
			}

			dedicatedHandle =
			    MAKE_HANDLE(devAttr->dedicatedController,
					devAttr->dedicatedChannel);
			channel = HandleToChannel(dedicatedHandle);

			if ((channel->flags & DMA_CHANNEL_FLAG_IS_DEDICATED) !=
			    0) {
				printk
				    ("DMA Device: %s attempting to use same DMA Controller:Channel (%d:%d) as %s\n",
				     devAttr->name,
				     devAttr->dedicatedController,
				     devAttr->dedicatedChannel,
				     DMA_gDeviceAttribute[channel->devType].
				     name);
				rc = -EBUSY;
				goto out;
			}

			channel->flags |= DMA_CHANNEL_FLAG_IS_DEDICATED;
			channel->devType = devIdx;

			if (devAttr->flags & DMA_DEVICE_FLAG_NO_ISR) {
				channel->flags |= DMA_CHANNEL_FLAG_NO_ISR;
			}

			/* For dedicated channels, we can go ahead and configure the DMA channel now */
			/* as well. */

			ConfigChannel(dedicatedHandle);
		}
	}

	/* Go through and register the interrupt handlers */

	for (controllerIdx = 0; controllerIdx < DMA_NUM_CONTROLLERS;
	     controllerIdx++) {
		for (channelIdx = 0; channelIdx < DMA_NUM_CHANNELS;
		     channelIdx++) {
			channel =
			    &gDMA.controller[controllerIdx].channel[channelIdx];

			if ((channel->flags & DMA_CHANNEL_FLAG_NO_ISR) == 0) {
				snprintf(channel->name, sizeof(channel->name),
					 "dma %d:%d %s", controllerIdx,
					 channelIdx,
					 channel->devType ==
					 DMA_DEVICE_NONE ? "" :
					 DMA_gDeviceAttribute[channel->devType].
					 name);

				rc =
				     request_irq(IRQ_DMA0C0 +
						 (controllerIdx *
						  DMA_NUM_CHANNELS) +
						 channelIdx,
						 dma_interrupt_handler,
						 IRQF_DISABLED, channel->name,
						 channel);
				if (rc != 0) {
					printk(KERN_ERR
					       "request_irq for IRQ_DMA%dC%d failed\n",
					       controllerIdx, channelIdx);
				}
			}
		}
	}

	/* Create /proc/dma/channels and /proc/dma/devices */

	gDmaDir = proc_mkdir("dma", NULL);

	if (gDmaDir == NULL) {
		printk(KERN_ERR "Unable to create /proc/dma\n");
	} else {
		create_proc_read_entry("channels", 0, gDmaDir,
				       dma_proc_read_channels, NULL);
		create_proc_read_entry("devices", 0, gDmaDir,
				       dma_proc_read_devices, NULL);
		create_proc_read_entry("mem-type", 0, gDmaDir,
				       dma_proc_read_mem_type, NULL);
	}

out:

	up(&gDMA.lock);

	return rc;
}

/****************************************************************************/
/**
*   Reserves a channel for use with @a dev. If the device is setup to use
*   a shared channel, then this function will block until a free channel
*   becomes available.
*
*   @return
*       >= 0    - A valid DMA Handle.
*       -EBUSY  - Device is currently being used.
*       -ENODEV - Device handed in is invalid.
*/
/****************************************************************************/

#if (DMA_DEBUG_TRACK_RESERVATION)
DMA_Handle_t dma_request_channel_dbg
    (DMA_Device_t dev, const char *fileName, int lineNum)
#else
DMA_Handle_t dma_request_channel(DMA_Device_t dev)
#endif
{
	DMA_Handle_t handle;
	DMA_DeviceAttribute_t *devAttr;
	DMA_Channel_t *channel;
	int controllerIdx;
	int controllerIdx2;
	int channelIdx;

	if (down_interruptible(&gDMA.lock) < 0) {
		return -ERESTARTSYS;
	}

	if ((dev < 0) || (dev >= DMA_NUM_DEVICE_ENTRIES)) {
		handle = -ENODEV;
		goto out;
	}
	devAttr = &DMA_gDeviceAttribute[dev];

#if (DMA_DEBUG_TRACK_RESERVATION)
	{
		char *s;

		s = strrchr(fileName, '/');
		if (s != NULL) {
			fileName = s + 1;
		}
	}
#endif
	if ((devAttr->flags & DMA_DEVICE_FLAG_IN_USE) != 0) {
		/* This device has already been requested and not been freed */

		printk(KERN_ERR "%s: device %s is already requested\n",
		       __func__, devAttr->name);
		handle = -EBUSY;
		goto out;
	}

	if ((devAttr->flags & DMA_DEVICE_FLAG_IS_DEDICATED) != 0) {
		/* This device has a dedicated channel. */

		channel =
		    &gDMA.controller[devAttr->dedicatedController].
		    channel[devAttr->dedicatedChannel];
		if ((channel->flags & DMA_CHANNEL_FLAG_IN_USE) != 0) {
			handle = -EBUSY;
			goto out;
		}

		channel->flags |= DMA_CHANNEL_FLAG_IN_USE;
		devAttr->flags |= DMA_DEVICE_FLAG_IN_USE;

#if (DMA_DEBUG_TRACK_RESERVATION)
		channel->fileName = fileName;
		channel->lineNum = lineNum;
#endif
		handle =
		    MAKE_HANDLE(devAttr->dedicatedController,
				devAttr->dedicatedChannel);
		goto out;
	}

	/* This device needs to use one of the shared channels. */

	handle = DMA_INVALID_HANDLE;
	while (handle == DMA_INVALID_HANDLE) {
		/* Scan through the shared channels and see if one is available */

		for (controllerIdx2 = 0; controllerIdx2 < DMA_NUM_CONTROLLERS;
		     controllerIdx2++) {
			/* Check to see if we should try on controller 1 first. */

			controllerIdx = controllerIdx2;
			if ((devAttr->
			     flags & DMA_DEVICE_FLAG_ALLOC_DMA1_FIRST) != 0) {
				controllerIdx = 1 - controllerIdx;
			}

			/* See if the device is available on the controller being tested */

			if ((devAttr->
			     flags & (DMA_DEVICE_FLAG_ON_DMA0 << controllerIdx))
			    != 0) {
				for (channelIdx = 0;
				     channelIdx < DMA_NUM_CHANNELS;
				     channelIdx++) {
					channel =
					    &gDMA.controller[controllerIdx].
					    channel[channelIdx];

					if (((channel->
					      flags &
					      DMA_CHANNEL_FLAG_IS_DEDICATED) ==
					     0)
					    &&
					    ((channel->
					      flags & DMA_CHANNEL_FLAG_IN_USE)
					     == 0)) {
						if (((channel->
						      flags &
						      DMA_CHANNEL_FLAG_LARGE_FIFO)
						     != 0)
						    &&
						    ((devAttr->
						      flags &
						      DMA_DEVICE_FLAG_ALLOW_LARGE_FIFO)
						     == 0)) {
							/* This channel is a large fifo - don't tie it up */
							/* with devices that we don't want using it. */

							continue;
						}

						channel->flags |=
						    DMA_CHANNEL_FLAG_IN_USE;
						channel->devType = dev;
						devAttr->flags |=
						    DMA_DEVICE_FLAG_IN_USE;

#if (DMA_DEBUG_TRACK_RESERVATION)
						channel->fileName = fileName;
						channel->lineNum = lineNum;
#endif
						handle =
						    MAKE_HANDLE(controllerIdx,
								channelIdx);

						/* Now that we've reserved the channel - we can go ahead and configure it */

						if (ConfigChannel(handle) != 0) {
							handle = -EIO;
							printk(KERN_ERR
							       "dma_request_channel: ConfigChannel failed\n");
						}
						goto out;
					}
				}
			}
		}

		/* No channels are currently available. Let's wait for one to free up. */

		{
			DEFINE_WAIT(wait);

			prepare_to_wait(&gDMA.freeChannelQ, &wait,
					TASK_INTERRUPTIBLE);
			up(&gDMA.lock);
			schedule();
			finish_wait(&gDMA.freeChannelQ, &wait);

			if (signal_pending(current)) {
				/* We don't currently hold gDMA.lock, so we return directly */

				return -ERESTARTSYS;
			}
		}

		if (down_interruptible(&gDMA.lock)) {
			return -ERESTARTSYS;
		}
	}

out:
	up(&gDMA.lock);

	return handle;
}

/* Create both _dbg and non _dbg functions for modules. */

#if (DMA_DEBUG_TRACK_RESERVATION)
#undef dma_request_channel
DMA_Handle_t dma_request_channel(DMA_Device_t dev)
{
	return dma_request_channel_dbg(dev, __FILE__, __LINE__);
}

EXPORT_SYMBOL(dma_request_channel_dbg);
#endif
EXPORT_SYMBOL(dma_request_channel);

/****************************************************************************/
/**
*   Frees a previously allocated DMA Handle.
*/
/****************************************************************************/

int dma_free_channel(DMA_Handle_t handle	/* DMA handle. */
    ) {
	int rc = 0;
	DMA_Channel_t *channel;
	DMA_DeviceAttribute_t *devAttr;

	if (down_interruptible(&gDMA.lock) < 0) {
		return -ERESTARTSYS;
	}

	channel = HandleToChannel(handle);
	if (channel == NULL) {
		rc = -EINVAL;
		goto out;
	}

	devAttr = &DMA_gDeviceAttribute[channel->devType];

	if ((channel->flags & DMA_CHANNEL_FLAG_IS_DEDICATED) == 0) {
		channel->lastDevType = channel->devType;
		channel->devType = DMA_DEVICE_NONE;
	}
	channel->flags &= ~DMA_CHANNEL_FLAG_IN_USE;
	devAttr->flags &= ~DMA_DEVICE_FLAG_IN_USE;

out:
	up(&gDMA.lock);

	wake_up_interruptible(&gDMA.freeChannelQ);

	return rc;
}

EXPORT_SYMBOL(dma_free_channel);

/****************************************************************************/
/**
*   Determines if a given device has been configured as using a shared
*   channel.
*
*   @return
*       0           Device uses a dedicated channel
*       > zero      Device uses a shared channel
*       < zero      Error code
*/
/****************************************************************************/

int dma_device_is_channel_shared(DMA_Device_t device	/* Device to check. */
    ) {
	DMA_DeviceAttribute_t *devAttr;

	if (!IsDeviceValid(device)) {
		return -ENODEV;
	}
	devAttr = &DMA_gDeviceAttribute[device];

	return ((devAttr->flags & DMA_DEVICE_FLAG_IS_DEDICATED) == 0);
}

EXPORT_SYMBOL(dma_device_is_channel_shared);

/****************************************************************************/
/**
*   Allocates buffers for the descriptors. This is normally done automatically
*   but needs to be done explicitly when initiating a dma from interrupt
*   context.
*
*   @return
*       0       Descriptors were allocated successfully
*       -EINVAL Invalid device type for this kind of transfer
*               (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
*       -ENOMEM Memory exhausted
*/
/****************************************************************************/

int dma_alloc_descriptors(DMA_Handle_t handle,	/* DMA Handle */
			  dmacHw_TRANSFER_TYPE_e transferType,	/* Type of transfer being performed */
			  dma_addr_t srcData,	/* Place to get data to write to device */
			  dma_addr_t dstData,	/* Pointer to device data address */
			  size_t numBytes	/* Number of bytes to transfer to the device */
    ) {
	DMA_Channel_t *channel;
	DMA_DeviceAttribute_t *devAttr;
	int numDescriptors;
	size_t ringBytesRequired;
	int rc = 0;

	channel = HandleToChannel(handle);
	if (channel == NULL) {
		return -ENODEV;
	}

	devAttr = &DMA_gDeviceAttribute[channel->devType];

	if (devAttr->config.transferType != transferType) {
		return -EINVAL;
	}

	/* Figure out how many descriptors we need. */

	/* printk("srcData: 0x%08x dstData: 0x%08x, numBytes: %d\n", */
	/*        srcData, dstData, numBytes); */

	numDescriptors = dmacHw_calculateDescriptorCount(&devAttr->config,
							      (void *)srcData,
							      (void *)dstData,
							      numBytes);
	if (numDescriptors < 0) {
		printk(KERN_ERR "%s: dmacHw_calculateDescriptorCount failed\n",
		       __func__);
		return -EINVAL;
	}

	/* Check to see if we can reuse the existing descriptor ring, or if we need to allocate */
	/* a new one. */

	ringBytesRequired = dmacHw_descriptorLen(numDescriptors);

	/* printk("ringBytesRequired: %d\n", ringBytesRequired); */

	if (ringBytesRequired > devAttr->ring.bytesAllocated) {
		/* Make sure that this code path is never taken from interrupt context. */
		/* It's OK for an interrupt to initiate a DMA transfer, but the descriptor */
		/* allocation needs to have already been done. */

		might_sleep();

		/* Free the old descriptor ring and allocate a new one. */

		dma_free_descriptor_ring(&devAttr->ring);

		/* And allocate a new one. */

		rc =
		     dma_alloc_descriptor_ring(&devAttr->ring,
					       numDescriptors);
		if (rc < 0) {
			printk(KERN_ERR
			       "%s: dma_alloc_descriptor_ring(%d) failed\n",
			       __func__, numDescriptors);
			return rc;
		}
		/* Setup the descriptor for this transfer */

		if (dmacHw_initDescriptor(devAttr->ring.virtAddr,
					  devAttr->ring.physAddr,
					  devAttr->ring.bytesAllocated,
					  numDescriptors) < 0) {
			printk(KERN_ERR "%s: dmacHw_initDescriptor failed\n",
			       __func__);
			return -EINVAL;
		}
	} else {
		/* We've already got enough ring buffer allocated. All we need to do is reset */
		/* any control information, just in case the previous DMA was stopped. */

		dmacHw_resetDescriptorControl(devAttr->ring.virtAddr);
	}

	/* dma_alloc/free both set the prevSrc/DstData to 0. If they happen to be the same */
	/* as last time, then we don't need to call setDataDescriptor again. */

	if (dmacHw_setDataDescriptor(&devAttr->config,
				     devAttr->ring.virtAddr,
				     (void *)srcData,
				     (void *)dstData, numBytes) < 0) {
		printk(KERN_ERR "%s: dmacHw_setDataDescriptor failed\n",
		       __func__);
		return -EINVAL;
	}

	/* Remember the critical information for this transfer so that we can eliminate */
	/* another call to dma_alloc_descriptors if the caller reuses the same buffers */

	devAttr->prevSrcData = srcData;
	devAttr->prevDstData = dstData;
	devAttr->prevNumBytes = numBytes;

	return 0;
}

EXPORT_SYMBOL(dma_alloc_descriptors);

/****************************************************************************/
/**
*   Allocates and sets up descriptors for a double buffered circular buffer.
*
*   This is primarily intended to be used for things like the ingress samples
*   from a microphone.
*
*   @return
*       > 0     Number of descriptors actually allocated.
*       -EINVAL Invalid device type for this kind of transfer
*               (i.e. the device is _MEM_TO_DEV and not _DEV_TO_MEM)
*       -ENOMEM Memory exhausted
*/
/****************************************************************************/

int dma_alloc_double_dst_descriptors(DMA_Handle_t handle,	/* DMA Handle */
				     dma_addr_t srcData,	/* Physical address of source data */
				     dma_addr_t dstData1,	/* Physical address of first destination buffer */
				     dma_addr_t dstData2,	/* Physical address of second destination buffer */
				     size_t numBytes	/* Number of bytes in each destination buffer */
    ) {
	DMA_Channel_t *channel;
	DMA_DeviceAttribute_t *devAttr;
	int numDst1Descriptors;
	int numDst2Descriptors;
	int numDescriptors;
	size_t ringBytesRequired;
	int rc = 0;

	channel = HandleToChannel(handle);
	if (channel == NULL) {
		return -ENODEV;
	}

	devAttr = &DMA_gDeviceAttribute[channel->devType];

	/* Figure out how many descriptors we need. */

	/* printk("srcData: 0x%08x dstData: 0x%08x, numBytes: %d\n", */
	/*        srcData, dstData, numBytes); */

	numDst1Descriptors =
	     dmacHw_calculateDescriptorCount(&devAttr->config, (void *)srcData,
					     (void *)dstData1, numBytes);
	if (numDst1Descriptors < 0) {
		return -EINVAL;
	}
	numDst2Descriptors =
	     dmacHw_calculateDescriptorCount(&devAttr->config, (void *)srcData,
					     (void *)dstData2, numBytes);
	if (numDst2Descriptors < 0) {
		return -EINVAL;
	}
	numDescriptors = numDst1Descriptors + numDst2Descriptors;
	/* printk("numDescriptors: %d\n", numDescriptors); */

	/* Check to see if we can reuse the existing descriptor ring, or if we need to allocate */
	/* a new one. */

	ringBytesRequired = dmacHw_descriptorLen(numDescriptors);

	/* printk("ringBytesRequired: %d\n", ringBytesRequired); */

	if (ringBytesRequired > devAttr->ring.bytesAllocated) {
		/* Make sure that this code path is never taken from interrupt context. */
		/* It's OK for an interrupt to initiate a DMA transfer, but the descriptor */
		/* allocation needs to have already been done. */

		might_sleep();

		/* Free the old descriptor ring and allocate a new one. */

		dma_free_descriptor_ring(&devAttr->ring);

		/* And allocate a new one. */

		rc =
		     dma_alloc_descriptor_ring(&devAttr->ring,
					       numDescriptors);
		if (rc < 0) {
			printk(KERN_ERR
			       "%s: dma_alloc_descriptor_ring(%d) failed\n",
			       __func__, ringBytesRequired);
			return rc;
		}
	}

	/* Setup the descriptor for this transfer. Since this function is used with */
	/* CONTINUOUS DMA operations, we need to reinitialize every time, otherwise */
	/* setDataDescriptor will keep trying to append onto the end. */

	if (dmacHw_initDescriptor(devAttr->ring.virtAddr,
				  devAttr->ring.physAddr,
				  devAttr->ring.bytesAllocated,
				  numDescriptors) < 0) {
		printk(KERN_ERR "%s: dmacHw_initDescriptor failed\n", __func__);
		return -EINVAL;
	}

	/* dma_alloc/free both set the prevSrc/DstData to 0. If they happen to be the same */
	/* as last time, then we don't need to call setDataDescriptor again. */

	if (dmacHw_setDataDescriptor(&devAttr->config,
				     devAttr->ring.virtAddr,
				     (void *)srcData,
				     (void *)dstData1, numBytes) < 0) {
		printk(KERN_ERR "%s: dmacHw_setDataDescriptor 1 failed\n",
		       __func__);
		return -EINVAL;
	}
	if (dmacHw_setDataDescriptor(&devAttr->config,
				     devAttr->ring.virtAddr,
				     (void *)srcData,
				     (void *)dstData2, numBytes) < 0) {
		printk(KERN_ERR "%s: dmacHw_setDataDescriptor 2 failed\n",
		       __func__);
		return -EINVAL;
	}

	/* You should use dma_start_transfer rather than dma_transfer_xxx so we don't */
	/* try to make the 'prev' variables right. */

	devAttr->prevSrcData = 0;
	devAttr->prevDstData = 0;
	devAttr->prevNumBytes = 0;

	return numDescriptors;
}

EXPORT_SYMBOL(dma_alloc_double_dst_descriptors);

/****************************************************************************/
/**
*   Initiates a transfer when the descriptors have already been setup.
*
*   This is a special case, and normally, the dma_transfer_xxx functions should
*   be used.
*
*   @return
*       0       Transfer was started successfully
*       -ENODEV Invalid handle
*/
/****************************************************************************/

int dma_start_transfer(DMA_Handle_t handle)
{
	DMA_Channel_t *channel;
	DMA_DeviceAttribute_t *devAttr;

	channel = HandleToChannel(handle);
	if (channel == NULL) {
		return -ENODEV;
	}
	devAttr = &DMA_gDeviceAttribute[channel->devType];

	dmacHw_initiateTransfer(channel->dmacHwHandle, &devAttr->config,
				devAttr->ring.virtAddr);

	/* Since we got this far, everything went successfully */

	return 0;
}

EXPORT_SYMBOL(dma_start_transfer);

/****************************************************************************/
/**
*   Stops a previously started DMA transfer.
*
*   @return
*       0       Transfer was stopped successfully
*       -ENODEV Invalid handle
*/
/****************************************************************************/

int dma_stop_transfer(DMA_Handle_t handle)
{
	DMA_Channel_t *channel;

	channel = HandleToChannel(handle);
	if (channel == NULL) {
		return -ENODEV;
	}

	dmacHw_stopTransfer(channel->dmacHwHandle);

	return 0;
}

EXPORT_SYMBOL(dma_stop_transfer);

/****************************************************************************/
/**
*   Waits for a DMA to complete by polling. This function is only intended
*   to be used for testing. Interrupts should be used for most DMA operations.
*/
/****************************************************************************/

int dma_wait_transfer_done(DMA_Handle_t handle)
{
	DMA_Channel_t *channel;
	dmacHw_TRANSFER_STATUS_e status;

	channel = HandleToChannel(handle);
	if (channel == NULL) {
		return -ENODEV;
	}

	while ((status =
		dmacHw_transferCompleted(channel->dmacHwHandle)) ==
	       dmacHw_TRANSFER_STATUS_BUSY) {
		;
	}

	if (status == dmacHw_TRANSFER_STATUS_ERROR) {
		printk(KERN_ERR "%s: DMA transfer failed\n", __func__);
		return -EIO;
	}
	return 0;
}

EXPORT_SYMBOL(dma_wait_transfer_done);

/****************************************************************************/
/**
*   Initiates a DMA, allocating the descriptors as required.
*
*   @return
*       0       Transfer was started successfully
*       -EINVAL Invalid device type for this kind of transfer
*               (i.e. the device is _DEV_TO_MEM and not _MEM_TO_DEV)
*/
/****************************************************************************/

int dma_transfer(DMA_Handle_t handle,	/* DMA Handle */
		 dmacHw_TRANSFER_TYPE_e transferType,	/* Type of transfer being performed */
		 dma_addr_t srcData,	/* Place to get data to write to device */
		 dma_addr_t dstData,	/* Pointer to device data address */
		 size_t numBytes	/* Number of bytes to transfer to the device */
    ) {
	DMA_Channel_t *channel;
	DMA_DeviceAttribute_t *devAttr;
	int rc = 0;

	channel = HandleToChannel(handle);
	if (channel == NULL) {
		return -ENODEV;
	}

	devAttr = &DMA_gDeviceAttribute[channel->devType];

	if (devAttr->config.transferType != transferType) {
		return -EINVAL;
	}

	/* We keep track of the information about the previous request for this */
	/* device, and if the attributes match, then we can use the descriptors we setup */
	/* the last time, and not have to reinitialize everything. */

	{
		rc =
		     dma_alloc_descriptors(handle, transferType, srcData,
					   dstData, numBytes);
		if (rc != 0) {
			return rc;
		}
	}

	/* And kick off the transfer */

	devAttr->numBytes = numBytes;
	devAttr->transferStartTime = timer_get_tick_count();

	dmacHw_initiateTransfer(channel->dmacHwHandle, &devAttr->config,
				devAttr->ring.virtAddr);

	/* Since we got this far, everything went successfully */

	return 0;
}

EXPORT_SYMBOL(dma_transfer);

/****************************************************************************/
/**
*   Set the callback function which will be called when a transfer completes.
*   If a NULL callback function is set, then no callback will occur.
*
*   @note   @a devHandler will be called from IRQ context.
*
*   @return
*       0       - Success
*       -ENODEV - Device handed in is invalid.
*/
/****************************************************************************/

int dma_set_device_handler(DMA_Device_t dev,	/* Device to set the callback for. */
			   DMA_DeviceHandler_t devHandler,	/* Function to call when the DMA completes */
			   void *userData	/* Pointer which will be passed to devHandler. */
    ) {
	DMA_DeviceAttribute_t *devAttr;
	unsigned long flags;

	if (!IsDeviceValid(dev)) {
		return -ENODEV;
	}
	devAttr = &DMA_gDeviceAttribute[dev];

	local_irq_save(flags);

	devAttr->userData = userData;
	devAttr->devHandler = devHandler;

	local_irq_restore(flags);

	return 0;
}

EXPORT_SYMBOL(dma_set_device_handler);

/****************************************************************************/
/**
*   Initializes a memory mapping structure
*/
/****************************************************************************/

int dma_init_mem_map(DMA_MemMap_t *memMap)
{
	memset(memMap, 0, sizeof(*memMap));

	sema_init(&memMap->lock, 1);

	return 0;
}

EXPORT_SYMBOL(dma_init_mem_map);

/****************************************************************************/
/**
*   Releases any memory currently being held by a memory mapping structure.
*/
/****************************************************************************/

int dma_term_mem_map(DMA_MemMap_t *memMap)
{
	down(&memMap->lock);	/* Just being paranoid */

	/* Free up any allocated memory */

	up(&memMap->lock);
	memset(memMap, 0, sizeof(*memMap));

	return 0;
}

EXPORT_SYMBOL(dma_term_mem_map);

/****************************************************************************/
/**
*   Looks at a memory address and categorizes it.
*
*   @return One of the values from the DMA_MemType_t enumeration.
*/
/****************************************************************************/

DMA_MemType_t dma_mem_type(void *addr)
{
	unsigned long addrVal = (unsigned long)addr;

	if (addrVal >= VMALLOC_END) {
		/* NOTE: DMA virtual memory space starts at 0xFFxxxxxx */

		/* dma_alloc_xxx pages are physically and virtually contiguous */

		return DMA_MEM_TYPE_DMA;
	}

	/* Technically, we could add one more classification. Addresses between VMALLOC_END */
	/* and the beginning of the DMA virtual address could be considered to be I/O space. */
	/* Right now, nobody cares about this particular classification, so we ignore it. */

	if (is_vmalloc_addr(addr)) {
		/* Address comes from the vmalloc'd region. Pages are virtually */
		/* contiguous but NOT physically contiguous */

		return DMA_MEM_TYPE_VMALLOC;
	}

	if (addrVal >= PAGE_OFFSET) {
		/* PAGE_OFFSET is typically 0xC0000000 */

		/* kmalloc'd pages are physically contiguous */

		return DMA_MEM_TYPE_KMALLOC;
	}

	return DMA_MEM_TYPE_USER;
}

EXPORT_SYMBOL(dma_mem_type);

/****************************************************************************/
/**
*   Looks at a memory address and determines if we support DMA'ing to/from
*   that type of memory.
*
*   @return boolean -
*               return value != 0 means dma supported
*               return value == 0 means dma not supported
*/
/****************************************************************************/

int dma_mem_supports_dma(void *addr)
{
	DMA_MemType_t memType = dma_mem_type(addr);

	return (memType == DMA_MEM_TYPE_DMA)
#if ALLOW_MAP_OF_KMALLOC_MEMORY
	    || (memType == DMA_MEM_TYPE_KMALLOC)
#endif
	    || (memType == DMA_MEM_TYPE_USER);
}

EXPORT_SYMBOL(dma_mem_supports_dma);

/****************************************************************************/
/**
*   Maps in a memory region such that it can be used for performing a DMA.
*
*   @return
*/
/****************************************************************************/

int dma_map_start(DMA_MemMap_t *memMap,	/* Stores state information about the map */
		  enum dma_data_direction dir	/* Direction that the mapping will be going */
    ) {
	int rc;

	down(&memMap->lock);

	DMA_MAP_PRINT("memMap: %p\n", memMap);

	if (memMap->inUse) {
		printk(KERN_ERR "%s: memory map %p is already being used\n",
		       __func__, memMap);
		rc = -EBUSY;
		goto out;
	}

	memMap->inUse = 1;
	memMap->dir = dir;
	memMap->numRegionsUsed = 0;

	rc = 0;

out:

	DMA_MAP_PRINT("returning %d", rc);

	up(&memMap->lock);

	return rc;
}

EXPORT_SYMBOL(dma_map_start);

/****************************************************************************/
/**
*   Adds a segment of memory to a memory map. Each segment is both
*   physically and virtually contiguous.
*
*   @return     0 on success, error code otherwise.
*/
/****************************************************************************/

static int dma_map_add_segment(DMA_MemMap_t *memMap,	/* Stores state information about the map */
			       DMA_Region_t *region,	/* Region that the segment belongs to */
			       void *virtAddr,	/* Virtual address of the segment being added */
			       dma_addr_t physAddr,	/* Physical address of the segment being added */
			       size_t numBytes	/* Number of bytes of the segment being added */
    ) {
	DMA_Segment_t *segment;

	DMA_MAP_PRINT("memMap:%p va:%p pa:0x%x #:%d\n", memMap, virtAddr,
		      physAddr, numBytes);

	/* Sanity check */

	if (((unsigned long)virtAddr < (unsigned long)region->virtAddr)
	    || (((unsigned long)virtAddr + numBytes)) >
	    ((unsigned long)region->virtAddr + region->numBytes)) {
		printk(KERN_ERR
		       "%s: virtAddr %p is outside region @ %p len: %d\n",
		       __func__, virtAddr, region->virtAddr, region->numBytes);
		return -EINVAL;
	}

	if (region->numSegmentsUsed > 0) {
		/* Check to see if this segment is physically contiguous with the previous one */

		segment = &region->segment[region->numSegmentsUsed - 1];

		if ((segment->physAddr + segment->numBytes) == physAddr) {
			/* It is - just add on to the end */

			DMA_MAP_PRINT("appending %d bytes to last segment\n",
				      numBytes);

			segment->numBytes += numBytes;

			return 0;
		}
	}

	/* Reallocate to hold more segments, if required. */

	if (region->numSegmentsUsed >= region->numSegmentsAllocated) {
		DMA_Segment_t *newSegment;
		size_t oldSize =
		    region->numSegmentsAllocated * sizeof(*newSegment);
		int newAlloc = region->numSegmentsAllocated + 4;
		size_t newSize = newAlloc * sizeof(*newSegment);

		newSegment = kmalloc(newSize, GFP_KERNEL);
		if (newSegment == NULL) {
			return -ENOMEM;
		}
		memcpy(newSegment, region->segment, oldSize);
		memset(&((uint8_t *) newSegment)[oldSize], 0,
		       newSize - oldSize);
		kfree(region->segment);

		region->numSegmentsAllocated = newAlloc;
		region->segment = newSegment;
	}

	segment = &region->segment[region->numSegmentsUsed];
	region->numSegmentsUsed++;

	segment->virtAddr = virtAddr;
	segment->physAddr = physAddr;
	segment->numBytes = numBytes;

	DMA_MAP_PRINT("returning success\n");

	return 0;
}

/****************************************************************************/
/**
*   Adds a region of memory to a memory map. Each region is virtually
*   contiguous, but not necessarily physically contiguous.
*
*   @return     0 on success, error code otherwise.
*/
/****************************************************************************/

int dma_map_add_region(DMA_MemMap_t *memMap,	/* Stores state information about the map */
		       void *mem,	/* Virtual address that we want to get a map of */
		       size_t numBytes	/* Number of bytes being mapped */
    ) {
	unsigned long addr = (unsigned long)mem;
	unsigned int offset;
	int rc = 0;
	DMA_Region_t *region;
	dma_addr_t physAddr;

	down(&memMap->lock);

	DMA_MAP_PRINT("memMap:%p va:%p #:%d\n", memMap, mem, numBytes);

	if (!memMap->inUse) {
		printk(KERN_ERR "%s: Make sure you call dma_map_start first\n",
		       __func__);
		rc = -EINVAL;
		goto out;
	}

	/* Reallocate to hold more regions. */

	if (memMap->numRegionsUsed >= memMap->numRegionsAllocated) {
		DMA_Region_t *newRegion;
		size_t oldSize =
		    memMap->numRegionsAllocated * sizeof(*newRegion);
		int newAlloc = memMap->numRegionsAllocated + 4;
		size_t newSize = newAlloc * sizeof(*newRegion);

		newRegion = kmalloc(newSize, GFP_KERNEL);
		if (newRegion == NULL) {
			rc = -ENOMEM;
			goto out;
		}
		memcpy(newRegion, memMap->region, oldSize);
		memset(&((uint8_t *) newRegion)[oldSize], 0, newSize - oldSize);

		kfree(memMap->region);

		memMap->numRegionsAllocated = newAlloc;
		memMap->region = newRegion;
	}

	region = &memMap->region[memMap->numRegionsUsed];
	memMap->numRegionsUsed++;

	offset = addr & ~PAGE_MASK;

	region->memType = dma_mem_type(mem);
	region->virtAddr = mem;
	region->numBytes = numBytes;
	region->numSegmentsUsed = 0;
	region->numLockedPages = 0;
	region->lockedPages = NULL;

	switch (region->memType) {
	case DMA_MEM_TYPE_VMALLOC:
		{
			atomic_inc(&gDmaStatMemTypeVmalloc);

			/* printk(KERN_ERR "%s: vmalloc'd pages are not supported\n", __func__); */

			/* vmalloc'd pages are not physically contiguous */

			rc = -EINVAL;
			break;
		}

	case DMA_MEM_TYPE_KMALLOC:
		{
			atomic_inc(&gDmaStatMemTypeKmalloc);

			/* kmalloc'd pages are physically contiguous, so they'll have exactly */
			/* one segment */

#if ALLOW_MAP_OF_KMALLOC_MEMORY
			physAddr =
			    dma_map_single(NULL, mem, numBytes, memMap->dir);
			rc = dma_map_add_segment(memMap, region, mem, physAddr,
						 numBytes);
#else
			rc = -EINVAL;
#endif
			break;
		}

	case DMA_MEM_TYPE_DMA:
		{
			/* dma_alloc_xxx pages are physically contiguous */

			atomic_inc(&gDmaStatMemTypeCoherent);

			physAddr = (vmalloc_to_pfn(mem) << PAGE_SHIFT) + offset;

			dma_sync_single_for_cpu(NULL, physAddr, numBytes,
						memMap->dir);
			rc = dma_map_add_segment(memMap, region, mem, physAddr,
						 numBytes);
			break;
		}

	case DMA_MEM_TYPE_USER:
		{
			size_t firstPageOffset;
			size_t firstPageSize;
			struct page **pages;
			struct task_struct *userTask;

			atomic_inc(&gDmaStatMemTypeUser);

#if 1
			/* If the pages are user pages, then the dma_mem_map_set_user_task function */
			/* must have been previously called. */

			if (memMap->userTask == NULL) {
				printk(KERN_ERR
				       "%s: must call dma_mem_map_set_user_task when using user-mode memory\n",
				       __func__);
				return -EINVAL;
			}

			/* User pages need to be locked. */

			firstPageOffset =
			    (unsigned long)region->virtAddr & (PAGE_SIZE - 1);
			firstPageSize = PAGE_SIZE - firstPageOffset;

			region->numLockedPages = (firstPageOffset
						  + region->numBytes +
						  PAGE_SIZE - 1) / PAGE_SIZE;
			pages =
			    kmalloc(region->numLockedPages *
				    sizeof(struct page *), GFP_KERNEL);

			if (pages == NULL) {
				region->numLockedPages = 0;
				return -ENOMEM;
			}

			userTask = memMap->userTask;

			down_read(&userTask->mm->mmap_sem);
			rc = get_user_pages(userTask,	/* task */
					    userTask->mm,	/* mm */
					    (unsigned long)region->virtAddr,	/* start */
					    region->numLockedPages,	/* len */
					    memMap->dir == DMA_FROM_DEVICE,	/* write */
					    0,	/* force */
					    pages,	/* pages (array of pointers to page) */
					    NULL);	/* vmas */
			up_read(&userTask->mm->mmap_sem);

			if (rc != region->numLockedPages) {
				kfree(pages);
				region->numLockedPages = 0;

				if (rc >= 0) {
					rc = -EINVAL;
				}
			} else {
				uint8_t *virtAddr = region->virtAddr;
				size_t bytesRemaining;
				int pageIdx;

				rc = 0;	/* Since get_user_pages returns +ve number */

				region->lockedPages = pages;

				/* We've locked the user pages. Now we need to walk them and figure */
				/* out the physical addresses. */

				/* The first page may be partial */

				dma_map_add_segment(memMap,
						    region,
						    virtAddr,
						    PFN_PHYS(page_to_pfn
							     (pages[0])) +
						    firstPageOffset,
						    firstPageSize);

				virtAddr += firstPageSize;
				bytesRemaining =
				    region->numBytes - firstPageSize;

				for (pageIdx = 1;
				     pageIdx < region->numLockedPages;
				     pageIdx++) {
					size_t bytesThisPage =
					    (bytesRemaining >
					     PAGE_SIZE ? PAGE_SIZE :
					     bytesRemaining);

					DMA_MAP_PRINT
					    ("pageIdx:%d pages[pageIdx]=%p pfn=%u phys=%u\n",
					     pageIdx, pages[pageIdx],
					     page_to_pfn(pages[pageIdx]),
					     PFN_PHYS(page_to_pfn
						      (pages[pageIdx])));

					dma_map_add_segment(memMap,
							    region,
							    virtAddr,
							    PFN_PHYS(page_to_pfn
								     (pages
								      [pageIdx])),
							    bytesThisPage);

					virtAddr += bytesThisPage;
					bytesRemaining -= bytesThisPage;
				}
			}
#else
			printk(KERN_ERR
			       "%s: User mode pages are not yet supported\n",
			       __func__);

			/* user pages are not physically contiguous */

			rc = -EINVAL;
#endif
			break;
		}

	default:
		{
			printk(KERN_ERR "%s: Unsupported memory type: %d\n",
			       __func__, region->memType);

			rc = -EINVAL;
			break;
		}
	}

	if (rc != 0) {
		memMap->numRegionsUsed--;
	}

out:

	DMA_MAP_PRINT("returning %d\n", rc);

	up(&memMap->lock);

	return rc;
}

EXPORT_SYMBOL(dma_map_add_segment);

/****************************************************************************/
/**
*   Maps in a memory region such that it can be used for performing a DMA.
*
*   @return     0 on success, error code otherwise.
*/
/****************************************************************************/

int dma_map_mem(DMA_MemMap_t *memMap,	/* Stores state information about the map */
		void *mem,	/* Virtual address that we want to get a map of */
		size_t numBytes,	/* Number of bytes being mapped */
		enum dma_data_direction dir	/* Direction that the mapping will be going */
    ) {
	int rc;

	rc = dma_map_start(memMap, dir);
	if (rc == 0) {
		rc = dma_map_add_region(memMap, mem, numBytes);
		if (rc < 0) {
			/* Since the add fails, this function will fail, and the caller won't */
			/* call unmap, so we need to do it here. */

			dma_unmap(memMap, 0);
		}
	}

	return rc;
}

EXPORT_SYMBOL(dma_map_mem);

/****************************************************************************/
/**
*   Setup a descriptor ring for a given memory map.
*
*   It is assumed that the descriptor ring has already been initialized, and
*   this routine will only reallocate a new descriptor ring if the existing
*   one is too small.
*
*   @return     0 on success, error code otherwise.
*/
/****************************************************************************/

int dma_map_create_descriptor_ring(DMA_Device_t dev,	/* DMA device (where the ring is stored) */
				   DMA_MemMap_t *memMap,	/* Memory map that will be used */
				   dma_addr_t devPhysAddr	/* Physical address of device */
    ) {
	int rc;
	int numDescriptors;
	DMA_DeviceAttribute_t *devAttr;
	DMA_Region_t *region;
	DMA_Segment_t *segment;
	dma_addr_t srcPhysAddr;
	dma_addr_t dstPhysAddr;
	int regionIdx;
	int segmentIdx;

	devAttr = &DMA_gDeviceAttribute[dev];

	down(&memMap->lock);

	/* Figure out how many descriptors we need */

	numDescriptors = 0;
	for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
		region = &memMap->region[regionIdx];

		for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed;
		     segmentIdx++) {
			segment = &region->segment[segmentIdx];

			if (memMap->dir == DMA_TO_DEVICE) {
				srcPhysAddr = segment->physAddr;
				dstPhysAddr = devPhysAddr;
			} else {
				srcPhysAddr = devPhysAddr;
				dstPhysAddr = segment->physAddr;
			}

			rc =
			     dma_calculate_descriptor_count(dev, srcPhysAddr,
							    dstPhysAddr,
							    segment->
							    numBytes);
			if (rc < 0) {
				printk(KERN_ERR
				       "%s: dma_calculate_descriptor_count failed: %d\n",
				       __func__, rc);
				goto out;
			}
			numDescriptors += rc;
		}
	}

	/* Adjust the size of the ring, if it isn't big enough */

	if (numDescriptors > devAttr->ring.descriptorsAllocated) {
		dma_free_descriptor_ring(&devAttr->ring);
		rc =
		     dma_alloc_descriptor_ring(&devAttr->ring,
					       numDescriptors);
		if (rc < 0) {
			printk(KERN_ERR
			       "%s: dma_alloc_descriptor_ring failed: %d\n",
			       __func__, rc);
			goto out;
		}
	} else {
		rc =
		     dma_init_descriptor_ring(&devAttr->ring,
					      numDescriptors);
		if (rc < 0) {
			printk(KERN_ERR
			       "%s: dma_init_descriptor_ring failed: %d\n",
			       __func__, rc);
			goto out;
		}
	}

	/* Populate the descriptors */

	for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
		region = &memMap->region[regionIdx];

		for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed;
		     segmentIdx++) {
			segment = &region->segment[segmentIdx];

			if (memMap->dir == DMA_TO_DEVICE) {
				srcPhysAddr = segment->physAddr;
				dstPhysAddr = devPhysAddr;
			} else {
				srcPhysAddr = devPhysAddr;
				dstPhysAddr = segment->physAddr;
			}

			rc =
			     dma_add_descriptors(&devAttr->ring, dev,
						 srcPhysAddr, dstPhysAddr,
						 segment->numBytes);
			if (rc < 0) {
				printk(KERN_ERR
				       "%s: dma_add_descriptors failed: %d\n",
				       __func__, rc);
				goto out;
			}
		}
	}

	rc = 0;

out:

	up(&memMap->lock);
	return rc;
}

EXPORT_SYMBOL(dma_map_create_descriptor_ring);

/****************************************************************************/
/**
*   Maps in a memory region such that it can be used for performing a DMA.
*
*   @return
*/
/****************************************************************************/

int dma_unmap(DMA_MemMap_t *memMap,	/* Stores state information about the map */
	      int dirtied	/* non-zero if any of the pages were modified */
    ) {

	int rc = 0;
	int regionIdx;
	int segmentIdx;
	DMA_Region_t *region;
	DMA_Segment_t *segment;

	down(&memMap->lock);

	for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
		region = &memMap->region[regionIdx];

		for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed;
		     segmentIdx++) {
			segment = &region->segment[segmentIdx];

			switch (region->memType) {
			case DMA_MEM_TYPE_VMALLOC:
				{
					printk(KERN_ERR
					       "%s: vmalloc'd pages are not yet supported\n",
					       __func__);
					rc = -EINVAL;
					goto out;
				}

			case DMA_MEM_TYPE_KMALLOC:
				{
#if ALLOW_MAP_OF_KMALLOC_MEMORY
					dma_unmap_single(NULL,
							 segment->physAddr,
							 segment->numBytes,
							 memMap->dir);
#endif
					break;
				}

			case DMA_MEM_TYPE_DMA:
				{
					dma_sync_single_for_cpu(NULL,
								segment->
								physAddr,
								segment->
								numBytes,
								memMap->dir);
					break;
				}

			case DMA_MEM_TYPE_USER:
				{
					/* Nothing to do here. */

					break;
				}

			default:
				{
					printk(KERN_ERR
					       "%s: Unsupported memory type: %d\n",
					       __func__, region->memType);
					rc = -EINVAL;
					goto out;
				}
			}

			segment->virtAddr = NULL;
			segment->physAddr = 0;
			segment->numBytes = 0;
		}

		if (region->numLockedPages > 0) {
			int pageIdx;

			/* Some user pages were locked. We need to go and unlock them now. */

			for (pageIdx = 0; pageIdx < region->numLockedPages;
			     pageIdx++) {
				struct page *page =
				    region->lockedPages[pageIdx];

				if (memMap->dir == DMA_FROM_DEVICE) {
					SetPageDirty(page);
				}
				page_cache_release(page);
			}
			kfree(region->lockedPages);
			region->numLockedPages = 0;
			region->lockedPages = NULL;
		}

		region->memType = DMA_MEM_TYPE_NONE;
		region->virtAddr = NULL;
		region->numBytes = 0;
		region->numSegmentsUsed = 0;
	}
	memMap->userTask = NULL;
	memMap->numRegionsUsed = 0;
	memMap->inUse = 0;

out:
	up(&memMap->lock);

	return rc;
}

EXPORT_SYMBOL(dma_unmap);


text:
#ifndef __IGAMEPROPERTY__H
#define __IGAMEPROPERTY__H
#include "maxheap.h"

#pragma once

/*!\file IGameProperty.h
\brief IParamBlock and IParamBlock2 property access.

All properties found by IGame are stored as an IGameProperty.  This gives developers a unified way of accessing
IParamBlock and IParamBlock2 based properties used in 3ds Max
*/

//! Property types
enum PropType{
	IGAME_UNKNOWN_PROP,	/*!<Unkown property Type*/
	IGAME_FLOAT_PROP,	/*!<Property of Type float*/
	IGAME_POINT3_PROP,	/*!<Property of Type Point3*/
	IGAME_INT_PROP,		/*!<Property of Type int*/
	IGAME_STRING_PROP,  /*!<Property of Type TCHAR*/
	IGAME_POINT4_PROP,	/*!<Property of Type Point4*/
};

class IGameControl;

//!Main property definition
/*! IGameProperty provides a wrapper around the standard 3ds Max ParamBlock system.  It works for both
IParamBlock and IParamBlock2, all paramblocks parameters are supported directly.  It provides access to IGameControl and also data access
for floats, ints, strings, etc. It performs the type checking, so the Paramblock system will not assert in case of the wrong data type requested.
The access to User Properties is provided by look up from the IGameProp.xml file.
*/

class IGameProperty: public MaxHeapOperators
{

public:
	//!The name of the Property
	/*! The name as defined in MAXScript or User Property defined in IGameProp.xml file
	\return The parameter name
	*/
	virtual TCHAR * GetName() =0;

	//! Check if the parameter is a IParamBlock2 based
	/*!
	\return TRUE if IParamBlock2, FALSE if IParamBlock
	*/
	virtual bool IsPBlock2()=0;

	//! Check if the parameter animated
	/*!  Use this check to determing whether or not to access the controller
	\return TRUE if animated
	*/
	virtual bool IsPropAnimated()=0;

	//! The controller for the Property
	/*!
	\return A pointer to IGameControl
	*/
	virtual IGameControl * GetIGameControl() =0;

	//! Direct access to the IParamBlock2
	/*!
	\return a pointer to IParamBlock2
	*/
	virtual IParamBlock2 * GetMaxParamBlock2() =0;

	//! Direct access to the IParamBlock
	/*!
	\return a pointer to IParamBlock
	*/
	virtual IParamBlock * GetMaxParamBlock() =0;

	//! Check if the parameter is IParamBlock or IParamBlock2 based
	/*! Specifies whether this parameter is based on either IParamBlock or IParamBlock2.  This is useful as some IGameProperties
	are based on Non paramblocks.  For example node/user data is accessed as an IGame Property but in 3ds Max has no Paramblock representation
	\return TRUE if it is based on a either IParamBlock or IParamBlock2.
	*/
	virtual bool IsParamBlock()=0;

	//! The data type of the Property
	/*! This is used to find out the data type of the property, so the correct GetPropertyValue method can be used
	\return The data type.  Returned value corresponds to PropType enumeration.
	\sa PropType
	*/
	virtual PropType GetType() =0;

	//! Check if User Parameter has a entry in the IGameProp.xml file
	/*! All paramblocks parameters are supported directly. Use this check to decide whether a User Property is defined in the IGameProp.xml file
	\return True if User Parameter has a entry in the IGameProp.xml file
	*/
	virtual bool IsParameterSupported() = 0;

	//! The index of the parameter
	/*! The actual index of the parameter as used by the Paramblock system.  This can be used for direct access to the
	property from the parmblock container.  Also can be used for GetValue/SetValue calls.
	\return The index in the parameter block
	*/
	virtual int GetParamBlockIndex() = 0;

	//! Access to the actual Parameter Data
	/*!
	\param &f  The float to receive the data
	\param t  The time to retrieve the value, defaulted to the static frame.  This is set by IGameScene::SetStaticFrame
	\param p  The flag indicating if percent fraction value (TYPE_PCNT_FRAC) should be converted (0.1 to 10), default:false
	\return TRUE if succesful
	*/
	virtual bool GetPropertyValue(float &f, TimeValue t=TIME_NegInfinity, bool p=false)=0;

	//! Access to the actual Parameter Data
	/*!
	\param &i  The int to receive the data
	\param t  The time to retrieve the value, defaulted to the static frame.  This is set by IGameScene::SetStaticFrame
	\return TRUE if succesful
	*/
	virtual bool GetPropertyValue(int &i, TimeValue t=TIME_NegInfinity)=0;

	//! Access to the actual Parameter Data
	/*!
	\param &p  The Point3 to receive the data
	\param t  The time to retrieve the value, defaulted to the static frame.  This is set by IGameScene::SetStaticFrame
	\return TRUE if succesful
	*/
	virtual bool GetPropertyValue(Point3 &p, TimeValue t=TIME_NegInfinity)=0;

	//! Access to the actual Parameter Data This function is only available in 3ds Max 6.0 and above
	/*!
	\param &p  The Point4 to receive the data
	\param t  The time to retrieve the value, defaulted to the static frame.  This is set by IGameScene::SetStaticFrame
	\return TRUE if succesful
	*/
	virtual bool GetPropertyValue(Point4 &p, TimeValue t=TIME_NegInfinity)=0;

	//! Access to the actual Parameter Data
	/*!
	\param v  The TCHAR to receive the data
	\param t  The time to retrieve the value, defaulted to the static frame.  This is set by IGameScene::SetStaticFrame
	\return TRUE if successful
	*/
	virtual bool GetPropertyValue(TCHAR*& v, TimeValue t=TIME_NegInfinity)=0;

};

//!Property Enumeration
/*! PropertyEnum allows to define a callback for use with EnumerateProperties.  It will be called for
every parameter stored in the system
*/
class PropertyEnum: public MaxHeapOperators
{
public:

	//! The call back function
	/*! This is called for every property in the system, providing a way of stopping the enumeration if needed
	\param *prop The actual property found
	\return TRUE to stop the enumeration
	*/
	virtual bool Proc(IGameProperty* prop) = 0;
};

//! Property container
/*! This class provides an extension mechanism that IGame can use - an Entity is free to use them.
The developer can extend the properties that are "known" to IGame can be extended
this way the property can be retrieved directly by the developer.  As it is "known" to
the developer the property type is also known and can be accessed directly
*/
class IPropertyContainer: public MaxHeapOperators
{
public:

	//! User Defined Property Access
	/*!Using the unique ID in the IGameProp.xml file, the user defined property can be queried directly
	\param PropID User Property ID used in the IGameProp.xml file
	\return A pointer to IGameProperty if found, NULL otherwise
	*/
	virtual IGameProperty * QueryProperty(DWORD PropID) {return NULL;}

	//! The number of Properties for the Entity
	/*!
	\return The number of properties found.  The default is 0
	*/
	virtual int GetNumberOfProperties(){return 0;}

	//!Direct Property Access
	/*! The property can be accessed directly from the index provided by GetNumberOfProperties().  It will return NULL for
	"hidden" paramameters names (defined as empty string in paramblocks)
	\param index The index of the property to return
	\return A pointer to the IGameProperty.  The default is NULL
	*/
	virtual IGameProperty * GetProperty(int index) {return NULL;}

	//! Property Access
	/*!Using the name, the property can be queried directly
	\param propName Property name as defined in MAXScript or User Property name
	\return A pointer to IGameProperty if found.  The default is NULL
	*/
	virtual IGameProperty * QueryProperty(const TCHAR * propName) {return NULL;}

	//!Enumerate the Properties
	/*!All properties can be enumerated by using this method.  A user defined callback is used to provide access to
	the properties.
	\param &Enum The callback object to use.
	*/
	virtual void EnumerateProperties(PropertyEnum & Enum) = 0;

};

//!Main property access
/*!base Class used by all exporters participating in the properties system
*/
class IExportEntity: public MaxHeapOperators
{
public:
	//!Retrieve the Property Container
	/*!
	\return The PropertyContainer for this entity.
	*/
	virtual IPropertyContainer * GetIPropertyContainer(){return NULL;}

	//! Is the Entity directly supported
	/*!IGame provides direct support for certain 3ds Max objects and materials.  For instance, IGame supports the standard material and
	bitmap texture directly, i.e provides direct API calls to get the properties.
	\return TRUE if IGame supports the parameters for a particular ClassID directly through its API
	*/
	virtual bool IsEntitySupported() {return false;}

	//!Retrieves the name of the entity class
	/*!
	\return The name of the entity class
	*/
	virtual TCHAR * GetClassName()=0;
};

#endif  //__IGAMEPROPERTY__H


text:
package com.github.cthulhu314.scalaba

import akka.actor.{ActorSystem, Props}
import akka.io.IO
import spray.can.Http
import com.github.cthulhu314.scalaba.actors.{FileRepositoryActor, RepositoryActor}
import com.github.cthulhu314.scalaba.persistance.{PerformanceLoggingRepositoryDecorator, MongoRepository, SlickRepository}
import akka.routing.RoundRobinRouter
import com.github.cthulhu314.scalaba.persistance.files.NopFileRepository

object Boot extends App {

  // we need an ActorSystem to host our application in
  implicit val system = ActorSystem("scalaba")
  implicit val executionContext = system.dispatcher
  val repository = new PerformanceLoggingRepositoryDecorator(new MongoRepository("","scalaba"))
  val dbActor = system.actorOf(Props(new RepositoryActor(repository))
    .withRouter(RoundRobinRouter(5)))
  val fileActor = system.actorOf(Props(new FileRepositoryActor(new NopFileRepository())))
  // create and start our service actor
  val service = system.actorOf(Props(new ScalabaActor(dbActor,fileActor)), "scalaba-service")

  // start a new HTTP server on port 8080 with our service actor as the handler
  IO(Http) ! Http.Bind(service, interface = "localhost", port = 8080)
}