]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ludev.git/commitdiff
Initial commit
authorRobert Tivy <rtivy@ti.com>
Wed, 15 May 2013 18:06:58 +0000 (11:06 -0700)
committerRobert Tivy <rtivy@ti.com>
Wed, 15 May 2013 18:06:58 +0000 (11:06 -0700)
The CMEM module has been taken from the linuxutils stream and ported to
use in-kernel CMA. The user API set remains the same.

24 files changed:
.gitignore [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
Makefile.in [new file with mode: 0644]
configure.ac [new file with mode: 0644]
include/ti/cmem.h [new file with mode: 0755]
lu.mak [new file with mode: 0644]
products.mak [new file with mode: 0644]
src/cmem/Makefile.am [new file with mode: 0644]
src/cmem/Makefile.in [new file with mode: 0644]
src/cmem/README [new file with mode: 0644]
src/cmem/api/Makefile.am [new file with mode: 0644]
src/cmem/api/Makefile.in [new file with mode: 0644]
src/cmem/api/cmem.c [new file with mode: 0644]
src/cmem/module/Makefile [new file with mode: 0644]
src/cmem/module/cmemk.c [new file with mode: 0644]
src/cmem/module/kernel/drivers/Makefile [new file with mode: 0644]
src/cmem/module/kernel/drivers/cmem/Makefile [new file with mode: 0644]
src/cmem/module/kernel/drivers/cmem/cmemk_stub.c [new file with mode: 0644]
src/cmem/module/kernel/include/linux/cmemk_stub.h [new file with mode: 0644]
src/cmem/tests/Makefile.am [new file with mode: 0644]
src/cmem/tests/Makefile.in [new file with mode: 0644]
src/cmem/tests/apitest.c [new file with mode: 0644]
src/cmem/tests/multi_process.c [new file with mode: 0644]
src/cmem/tests/translate.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..c123773
--- /dev/null
@@ -0,0 +1,30 @@
+*.tar.gz
+
+# Linux stuff
+/autom4te.cache
+/aclocal.m4
+/build-aux
+/linuxutils-*
+/config.log
+/config.status
+/configure
+/libtool
+.deps/
+/Makefile
+/src/cmem/Makefile
+/src/cmem/api/Makefile
+/src/cmem/tests/Makefile
+/src/cmem/*/.libs
+/src/cmem/*/.deps
+/src/cmem/*/*.o
+/src/cmem/*/*.la
+/src/cmem/*/*.lo
+/src/cmem/tests/apitest
+/src/cmem/tests/multi_process
+/src/cmem/tests/translate
+/src/cmem/module/.tmp_versions
+/src/cmem/module/*.ko
+/src/cmem/module/*.cmd
+/src/cmem/module/modules.order
+/src/cmem/module/Module.symvers
+/src/cmem/module/cmemk.mod.c
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..8687b69
--- /dev/null
@@ -0,0 +1,39 @@
+##
+##  Copyright (c) 2013, Texas Instruments Incorporated
+##
+##  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.
+##
+##  *  Neither the name of Texas Instruments Incorporated nor the names of
+##     its contributors may 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 OWNER 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.
+##
+##  ======== Makefile.am ========
+##
+
+# the subdirectories of the project to go into
+SUBDIRS =  src/cmem/api src/cmem/tests
+
+# hook to remove libtools library extention files (.la)
+install-exec-hook:
+       rm -f $(DESTDIR)$(libdir)/*.la
diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..b2f39d0
--- /dev/null
@@ -0,0 +1,599 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = .
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am \
+       $(srcdir)/Makefile.in $(top_srcdir)/configure \
+       build-aux/config.guess build-aux/config.sub build-aux/depcomp \
+       build-aux/install-sh build-aux/ltmain.sh build-aux/missing
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno configure.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+       html-recursive info-recursive install-data-recursive \
+       install-exec-recursive install-info-recursive \
+       install-recursive installcheck-recursive installdirs-recursive \
+       pdf-recursive ps-recursive uninstall-info-recursive \
+       uninstall-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  { test ! -d $(distdir) \
+    || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+         && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+
+# the subdirectories of the project to go into
+SUBDIRS = src/cmem/api src/cmem/tests
+all: all-recursive
+
+.SUFFIXES:
+am--refresh:
+       @:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
+             cd $(srcdir) && $(AUTOMAKE) --foreign  \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           echo ' $(SHELL) ./config.status'; \
+           $(SHELL) ./config.status;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+       @failcom='exit 1'; \
+       for f in x $$MAKEFLAGS; do \
+         case $$f in \
+           *=* | --[!k]*);; \
+           *k*) failcom='fail=yes';; \
+         esac; \
+       done; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+       @failcom='exit 1'; \
+       for f in x $$MAKEFLAGS; do \
+         case $$f in \
+           *=* | --[!k]*);; \
+           *k*) failcom='fail=yes';; \
+         esac; \
+       done; \
+       dot_seen=no; \
+       case "$@" in \
+         distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+         *) list='$(SUBDIRS)' ;; \
+       esac; \
+       rev=''; for subdir in $$list; do \
+         if test "$$subdir" = "."; then :; else \
+           rev="$$subdir $$rev"; \
+         fi; \
+       done; \
+       rev="$$rev ."; \
+       target=`echo $@ | sed s/-recursive//`; \
+       for subdir in $$rev; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done && test -z "$$fail"
+tags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+       done
+ctags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+       done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+         include_option=--etags-include; \
+         empty_fix=.; \
+       else \
+         include_option=--include; \
+         empty_fix=; \
+       fi; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test ! -f $$subdir/TAGS || \
+             tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+         fi; \
+       done; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       $(am__remove_distdir)
+       mkdir $(distdir)
+       $(mkdir_p) $(distdir)/build-aux
+       @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+       list='$(DISTFILES)'; for file in $$list; do \
+         case $$file in \
+           $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+           $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+         esac; \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           dir="/$$dir"; \
+           $(mkdir_p) "$(distdir)$$dir"; \
+         else \
+           dir=''; \
+         fi; \
+         if test -d $$d/$$file; then \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+       list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test -d "$(distdir)/$$subdir" \
+           || $(mkdir_p) "$(distdir)/$$subdir" \
+           || exit 1; \
+           distdir=`$(am__cd) $(distdir) && pwd`; \
+           top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+           (cd $$subdir && \
+             $(MAKE) $(AM_MAKEFLAGS) \
+               top_distdir="$$top_distdir" \
+               distdir="$$distdir/$$subdir" \
+               distdir) \
+             || exit 1; \
+         fi; \
+       done
+       -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+         ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
+       || chmod -R a+r $(distdir)
+dist-gzip: distdir
+       tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       $(am__remove_distdir)
+
+dist-bzip2: distdir
+       tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+       $(am__remove_distdir)
+
+dist-tarZ: distdir
+       tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+       $(am__remove_distdir)
+
+dist-shar: distdir
+       shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+       $(am__remove_distdir)
+
+dist-zip: distdir
+       -rm -f $(distdir).zip
+       zip -rq $(distdir).zip $(distdir)
+       $(am__remove_distdir)
+
+dist dist-all: distdir
+       tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+       case '$(DIST_ARCHIVES)' in \
+       *.tar.gz*) \
+         GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+       *.tar.bz2*) \
+         bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+       *.tar.Z*) \
+         uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+       *.shar.gz*) \
+         GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+       *.zip*) \
+         unzip $(distdir).zip ;;\
+       esac
+       chmod -R a-w $(distdir); chmod a+w $(distdir)
+       mkdir $(distdir)/_build
+       mkdir $(distdir)/_inst
+       chmod a-w $(distdir)
+       dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+         && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+         && cd $(distdir)/_build \
+         && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+           $(DISTCHECK_CONFIGURE_FLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) dvi \
+         && $(MAKE) $(AM_MAKEFLAGS) check \
+         && $(MAKE) $(AM_MAKEFLAGS) install \
+         && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+         && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+         && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+               distuninstallcheck \
+         && chmod -R a-w "$$dc_install_base" \
+         && ({ \
+              (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+                   distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+             } || { rm -rf "$$dc_destdir"; exit 1; }) \
+         && rm -rf "$$dc_destdir" \
+         && $(MAKE) $(AM_MAKEFLAGS) dist \
+         && rm -rf $(DIST_ARCHIVES) \
+         && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+       $(am__remove_distdir)
+       @(echo "$(distdir) archives ready for distribution: "; \
+         list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+         sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}'
+distuninstallcheck:
+       @cd $(distuninstallcheck_dir) \
+       && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+          || { echo "ERROR: files left after uninstall:" ; \
+               if test -n "$(DESTDIR)"; then \
+                 echo "  (check DESTDIR support)"; \
+               fi ; \
+               $(distuninstallcheck_listfiles) ; \
+               exit 1; } >&2
+distcleancheck: distclean
+       @if test '$(srcdir)' = . ; then \
+         echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+         exit 1 ; \
+       fi
+       @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+         || { echo "ERROR: files left in build directory after distclean:" ; \
+              $(distcleancheck_listfiles) ; \
+              exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-libtool \
+       distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+       @$(NORMAL_INSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -rf $(top_srcdir)/autom4te.cache
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am am--refresh check \
+       check-am clean clean-generic clean-libtool clean-recursive \
+       ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \
+       dist-shar dist-tarZ dist-zip distcheck distclean \
+       distclean-generic distclean-libtool distclean-recursive \
+       distclean-tags distcleancheck distdir distuninstallcheck dvi \
+       dvi-am html html-am info info-am install install-am \
+       install-data install-data-am install-exec install-exec-am \
+       install-exec-hook install-info install-info-am install-man \
+       install-strip installcheck installcheck-am installdirs \
+       installdirs-am maintainer-clean maintainer-clean-generic \
+       maintainer-clean-recursive mostlyclean mostlyclean-generic \
+       mostlyclean-libtool mostlyclean-recursive pdf pdf-am ps ps-am \
+       tags tags-recursive uninstall uninstall-am uninstall-info-am
+
+
+# hook to remove libtools library extention files (.la)
+install-exec-hook:
+       rm -f $(DESTDIR)$(libdir)/*.la
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..adec9e4
--- /dev/null
@@ -0,0 +1,85 @@
+#
+#   Copyright (c) 2013, Texas Instruments Incorporated
+#
+#   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.
+#
+#   *  Neither the name of Texas Instruments Incorporated nor the names of
+#      its contributors may 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 OWNER 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.
+#
+# ======== configure.ac ========
+#
+
+# Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.59)
+
+AC_INIT(LinuxUtils, 4.0.0, )
+
+# Check common src files to ensure integrity of the package
+AC_CONFIG_SRCDIR([src/cmem/api/cmem.c])
+
+# Set auxiliary build tools directory
+AC_CONFIG_AUX_DIR([build-aux])
+
+# Initilize automake
+AM_INIT_AUTOMAKE([foreign])
+
+# Disabling maintainer mode to prevent rebuild of configure script
+AM_MAINTAINER_MODE([disable])
+
+# Initalize libtool but disable fortran check
+define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl
+AC_PROG_LIBTOOL(gcc)
+
+# Checks for programs.
+AC_PROG_CC(gcc)
+AC_PROG_INSTALL
+
+# Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS([fcntl.h string.h sys/ioctl.h unistd.h])
+
+# Export CFLAGS and LDFLAGS to Makefile(s)
+AC_SUBST([AM_CFLAGS])
+AC_SUBST([AM_LDFLAGS])
+
+# Generate Makefile(s)
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([src/cmem/api/Makefile])
+AC_CONFIG_FILES([src/cmem/tests/Makefile])
+AC_OUTPUT
+
+echo \
+"-----------------------------------------------------------
+
+Thank you for installing the ${PACKAGE_NAME} package
+
+Installation directory prefix: '${prefix}'.
+Compilation command: '${CC} ${CFLAGS} ${CPPFLAGS}'
+
+Now type 'make; sudo make install' to generate the program
+and install it to your system.
+
+------------------------------------------------------------"
+
diff --git a/include/ti/cmem.h b/include/ti/cmem.h
new file mode 100755 (executable)
index 0000000..db307fa
--- /dev/null
@@ -0,0 +1,594 @@
+/**
+ * @file    cmem.h
+ * @brief   Describes the interface to the contiguous memory allocator.
+ *
+ * The cmem user interface library wraps file system calls to an associated
+ * kernel module (cmemk.ko), which needs to be loaded in order for calls to
+ * this library to succeed.
+ *
+ * The following is an example of installing the cmem kernel module:
+ * 
+ * @verbatim /sbin/insmod cmemk.ko pools=4x30000,2x500000 phys_start=0x0 phys_end=0x3000000 @endverbatim
+ *     - phys_start and phys_end must be specified in hexadecimal format
+ *     - phys_start is "inclusive" and phys_end is "exclusive", i.e.,
+ *       phys_end should be "end address + 1".
+ *     - pools must be specified using decimal format (for both number and
+ *       size), since using hexadecimal format would visually clutter the
+ *       specification due to the use of "x" as a token separator
+ *     - it's possible to insmod cmemk.ko without specifying any memory blocks,
+ *       in which case CMEM_getPhys() and CMEM_cache*() APIs can still be
+ *       utilized by an application.
+ *
+ * This particular command creates 2 pools. The first pool is created with 4
+ * buffers of size 30000 bytes and the second pool is created with 2 buffers
+ * of size 500000 bytes. The CMEM pool buffers start at 0x0 and end at
+ * 0x2FFFFFF (max). 
+ *
+ * There is also support for a 2nd contiguous memory block to be specified,
+ * with all the same features supported for the 2nd block as with the 1st.
+ * This 2nd block is specified with *_1 parameters.  The following example
+ * expands upon the first example above:
+ * 
+ * @verbatim /sbin/insmod cmemk.ko pools=4x30000,2x500000 phys_start=0x0 phys_end=0x3000000
+    pools_1=4x65536 phys_start_1=0x80000000 phys_end_1=0x80010000 @endverbatim
+ *
+ * This particular command, in addition to the pools explained above,
+ * creates 1 pool (with 4 buffers of size 64KB) in a 2nd memory block which
+ * starts at 0x80000000 and ends at 0x8000FFFF (specified as "end + 1" on the
+ * insmod command).
+ *
+ * In order to access this 2nd memory block, new APIs have been added to
+ * CMEM which allow specification of the block ID.
+ *
+ * There are two more configuration "switches" for the cmemk.ko kernel module,
+ * which can be specified on the 'insmod' (or 'modprobe') command lines:
+ *     useHeapIfPoolUnavailable=[0|1]
+ *     allowOverlap=[0|1]
+ *
+ * 'useHeapIfPoolUnavailable', when set to 1, will cause pool-based allocations
+ * to fallback to a heap-based allocation if no pool buffer of sufficient size
+ * is available (the CMEM heap is described below).
+ *
+ * 'allowOverlap', when set to 1, causes cmemk.ko to not fail when it detects
+ * that a CMEM memory block location conflicts with the Linux kernel memory,
+ * and instead an informational message is printed on the console.  When set to
+ * 0, cmemk.ko insertion will fail when this condition is detected.  The
+ * overlap detection is fairly crude, however, checking only that the end of
+ * the kernel's memory (assigned by way of the u-boot 'bootargs' parameter
+ * "mem=##M") is not above the beginning location of a CMEM memory block.  For
+ * example, on most TI processor-based systems the kernel's memory starts at
+ * 0x80000000 and ends at (0x80000000 + ##M), so a CMEM block starting at
+ * 0x1000 would be detected as overlapping since the beginning location of that
+ * block is not greater than the end location of the kernel's memory.  To
+ * allow this situation, cmemk.ko should be inserted using "allowOverlap=1".
+ *
+ * Pool buffers are aligned on a module-dependent boundary, and their sizes are
+ * rounded up to this same boundary.  This applies to each buffer within a
+ * pool.  The total space used by an individual pool will therefore be greater
+ * than (or equal to) the exact amount requested in the installation of the
+ * module.
+ *
+ * The poolid used in the driver calls would be 0 for the first pool and 1 for
+ * the second pool.
+ *
+ * Pool allocations can be requested explicitly by pool number, or more
+ * generally by just a size.  For size-based allocations, the pool which best
+ * fits the requested size is automatically chosen.  Some CMEM APIs (newer
+ * ones) accept a blockid as a parameter, in order to specify which of the
+ * multiple blocks to operate on.  For 'legacy' APIs (ones that existed before
+ * the support for multiple blocks) where a blockid is still needed, block 0
+ * is assumed.
+ *
+ * There is also support for a general purpose heap.  In addition to the 2
+ * pools described above, a general purpose heap block is created from which
+ * allocations of any size can be requested.  Internally, allocation sizes are
+ * rounded up to a module-dependent boundary and allocation addresses are
+ * aligned either to this same boundary or to the requested alignment
+ * (whichever is greater).
+ *
+ * The size of the heap block is the amount of CMEM memory remaining after all
+ * pool allocations.  If more heap space is needed than is available after pool
+ * allocations, you must reduce the amount of CMEM memory granted to the pools.
+ *
+ * Buffer allocation is tracked at the file descriptor level by way of a
+ * 'registration' list.  The initial allocator of a buffer (the process that
+ * calls CMEM_alloc()) is automatically added to the registration list,
+ * and further processes can become registered for the same buffer by way
+ * of the CMEM_registerAlloc() API (and unregister with the
+ * CMEM_unregister() API).  This registration list for each buffer
+ * allows for buffer ownership tracking and cleanup on a
+ * per-file-descriptor basis, so that when a process exits or dies without
+ * having explicitly freed/unregistered its buffers, they get automatically
+ * unregistered (and freed when no more registered file descriptors exist).
+ * Only when the last registered file descriptor frees a buffer (either
+ * explictily, or by auto-cleanup) does a buffer actually get freed back to
+ * the kernel module.
+ *
+ * Since the CMEM interface library doesn't use the GT tracing facility, there
+ * is one configuration option available for the CMEM module to control
+ * whether the debug or release interface library is used for building the
+ * application.  This config parameter is named 'debug' and is of type bool,
+ * and the default value is 'false'.
+ *
+ * The following line is an example of enabling usage of the debug interface
+ * library:
+ *     var cmem = xdc.useModule('ti.sdo.linuxutils.cmem.CMEM');
+ *     cmem.debug = true;
+ * This will enable "CMEM Debug" statements to be printed to stdout.
+ */
+/**
+ *  @defgroup   ti_sdo_linuxutils_cmem_CMEM  Contiguous Memory Manager
+ *
+ *  This is the API for the Contiguous Memory Manager.
+ */
+
+#ifndef ti_sdo_linuxutils_cmem_CMEM_H
+#define ti_sdo_linuxutils_cmem_CMEM_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+/** @ingroup    ti_sdo_linuxutils_cmem_CMEM */
+/*@{*/
+
+#define CMEM_VERSION    0x03000100U
+
+/* ioctl cmd "flavors" */
+#define CMEM_WB                                0x00010000
+#define CMEM_INV                       0x00020000
+#define CMEM_HEAP                      0x00040000  /**< operation applies to heap */
+#define CMEM_POOL                      0x00000000  /**< operation applies to a pool */
+#define CMEM_CACHED                    0x00080000  /**< allocated buffer is cached */
+#define CMEM_NONCACHED                 0x00000000  /**< allocated buffer is not cached */
+#define CMEM_PHYS                      0x00100000
+
+#define CMEM_IOCMAGIC                  0x0000fe00
+
+/* supported "base" ioctl cmds for the driver. */
+#define CMEM_IOCALLOC                   1
+#define CMEM_IOCALLOCHEAP               2
+#define CMEM_IOCFREE                    3
+#define CMEM_IOCGETPHYS                 4
+#define CMEM_IOCGETSIZE                 5
+#define CMEM_IOCGETPOOL                 6
+#define CMEM_IOCCACHE                   7
+#define CMEM_IOCGETVERSION              8
+#define CMEM_IOCGETBLOCK                9
+#define CMEM_IOCREGUSER                 10
+#define CMEM_IOCGETNUMBLOCKS            11
+/*
+ * New ioctl cmds should use integers greater than the largest current cmd
+ * in order to not break backward compatibility.
+ */
+
+/* supported "flavors" to "base" ioctl cmds for the driver. */
+#define CMEM_IOCCACHEWBINV              CMEM_IOCCACHE | CMEM_WB | CMEM_INV
+#define CMEM_IOCCACHEWB                 CMEM_IOCCACHE | CMEM_WB
+#define CMEM_IOCCACHEINV                CMEM_IOCCACHE | CMEM_INV
+#define CMEM_IOCALLOCCACHED             CMEM_IOCALLOC | CMEM_CACHED
+#define CMEM_IOCALLOCHEAPCACHED         CMEM_IOCALLOCHEAP | CMEM_CACHED
+#define CMEM_IOCFREEHEAP                CMEM_IOCFREE | CMEM_HEAP
+#define CMEM_IOCFREEPHYS                CMEM_IOCFREE | CMEM_PHYS
+#define CMEM_IOCFREEHEAPPHYS            CMEM_IOCFREE | CMEM_HEAP | CMEM_PHYS
+
+#define CMEM_IOCCMDMASK                        0x000000ff
+
+/**
+ * @brief Parameters for CMEM_alloc(), CMEM_alloc2(), CMEM_allocPool(),
+ * CMEM_allocPool2(), CMEM_free().
+ */
+typedef struct CMEM_AllocParams {
+    int type;          /**< either CMEM_HEAP or CMEM_POOL */
+    int flags;         /**< either CMEM_CACHED or CMEM_NONCACHED */
+    size_t alignment;  /**<
+                         * only used for heap allocations, must be power of 2
+                         */
+} CMEM_AllocParams;
+
+extern CMEM_AllocParams CMEM_DEFAULTPARAMS;
+
+typedef struct CMEM_BlockAttrs {
+    unsigned long phys_base;
+    size_t size;
+} CMEM_BlockAttrs;
+
+/** @cond INTERNAL */
+
+/**
+ */
+union CMEM_AllocUnion {
+    struct {                   /**< */
+       size_t size;
+       size_t align;
+       int blockid;
+    } alloc_heap_inparams;     /**< */
+    struct {                   /**< */
+       int poolid;
+       int blockid;
+    } alloc_pool_inparams;     /**< */
+    struct {                   /**< */
+       int poolid;
+       int blockid;
+    } get_size_inparams;       /**< */
+    struct {                   /**< */
+       size_t size;
+       int blockid;
+    } get_pool_inparams;       /**< */
+    struct {                   /**< */
+       unsigned long physp;
+       size_t size;
+    } alloc_pool_outparams;    /**< */
+    struct {                   /**< */
+       unsigned long physp;
+       size_t size;
+    } get_block_outparams;     /**< */
+    struct {                   /**< */
+       int poolid;
+       size_t size;
+    } free_outparams;          /**< */
+    unsigned long physp;
+    unsigned long virtp;
+    size_t size;
+    int poolid;
+    int blockid;
+};
+
+/** @endcond */
+
+/**
+ * @brief Initialize the CMEM module. Must be called before other API calls.
+ *
+ * @return 0 for success or -1 for failure.
+ *
+ * @sa CMEM_exit
+ */
+int CMEM_init(void);
+
+/**
+ * @brief Find the pool that best fits a given buffer size and has a buffer
+ * available.
+ *
+ * @param   size    The buffer size for which a pool is needed.
+ *
+ * @return A poolid that can be passed to CMEM_allocPool(), or -1 for error.
+ *
+ * @pre Must have called CMEM_init()
+ *
+ * @sa CMEM_allocPool()
+ * @sa CMEM_allocPool2()
+ * @sa CMEM_free()
+ * @sa CMEM_getPool2()
+ */
+int CMEM_getPool(size_t size);
+
+/**
+ * @brief Find the pool in memory block blockid that best fits a given
+ * buffer size and has a buffer available.
+ *
+ * @param   blockid  Block number
+ * @param   size     The buffer size for which a pool is needed.
+ *
+ * @return A poolid that can be passed to CMEM_allocPool2(), or -1 for error.
+ *
+ * @pre Must have called CMEM_init()
+ *
+ * @sa CMEM_allocPool()
+ * @sa CMEM_allocPool2()
+ * @sa CMEM_free()
+ * @sa CMEM_getPool()
+ */
+int CMEM_getPool2(int blockid, size_t size);
+
+/**
+ * @brief Allocate memory from a specified pool.
+ *
+ * @param   poolid  The pool from which to allocate memory.
+ * @param   params  Allocation parameters.
+ *
+ * @remarks @c params->type is ignored - a pool will always be used.
+ * @remarks @c params->alignment is unused, since pool buffers are already
+ *          aligned to specific boundaries.
+ *
+ * @return A pointer to the allocated buffer, or NULL for failure.
+ *
+ * @pre Must have called CMEM_init()
+ *
+ * @sa CMEM_alloc()
+ * @sa CMEM_alloc2()
+ * @sa CMEM_allocPool2()
+ * @sa CMEM_registerAlloc()
+ * @sa CMEM_unregister()
+ * @sa CMEM_free()
+ */
+void *CMEM_allocPool(int poolid, CMEM_AllocParams *params);
+
+/**
+ * @brief Allocate memory from a specified pool in a specified memory block.
+ *
+ * @param   blockid The memory block from which to allocate.
+ * @param   poolid  The pool from which to allocate memory.
+ * @param   params  Allocation parameters.
+ *
+ * @remarks @c params->type is ignored - a pool will always be used.
+ * @remarks @c params->alignment is unused, since pool buffers are already
+ *          aligned to specific boundaries.
+ *
+ * @return A pointer to the allocated buffer, or NULL for failure.
+ *
+ * @pre Must have called CMEM_init()
+ *
+ * @sa CMEM_alloc()
+ * @sa CMEM_alloc2()
+ * @sa CMEM_allocPool()
+ * @sa CMEM_registerAlloc()
+ * @sa CMEM_unregister()
+ * @sa CMEM_free()
+ */
+void *CMEM_allocPool2(int blockid, int poolid, CMEM_AllocParams *params);
+
+/**
+ * @brief Allocate memory of a specified size
+ *
+ * @param   size    The size of the buffer to allocate.
+ * @param   params  Allocation parameters.
+ *
+ * @remarks Used to allocate memory from either a pool or the heap.
+ *          If doing a pool allocation, the pool that best fits the requested
+ *          size will be selected.  Use CMEM_allocPool() to allocate from a
+ *          specific pool.
+ *          Allocation will be cached or noncached, as specified by params.
+ *          params->alignment valid only for heap allocation.
+ *
+ * @return A pointer to the allocated buffer, or NULL for failure.
+ *
+ * @pre Must have called CMEM_init()
+ *
+ * @sa CMEM_allocPool()
+ * @sa CMEM_allocPool2()
+ * @sa CMEM_alloc2()
+ * @sa CMEM_registerAlloc()
+ * @sa CMEM_unregister()
+ * @sa CMEM_free()
+ */
+void *CMEM_alloc(size_t size, CMEM_AllocParams *params);
+
+/**
+ * @brief Allocate memory of a specified size from a specified memory block
+ *
+ * @param   blockid The memory block from which to allocate.
+ * @param   size    The size of the buffer to allocate.
+ * @param   params  Allocation parameters.
+ *
+ * @remarks Used to allocate memory from either a pool or the heap.
+ *          If doing a pool allocation, the pool that best fits the requested
+ *          size will be selected.  Use CMEM_allocPool() to allocate from a
+ *          specific pool.
+ *
+ * @remarks Allocation will be cached or noncached, as specified by params.
+ *          params->alignment valid only for heap allocation.
+ *
+ * @return A pointer to the allocated buffer, or NULL for failure.
+ *
+ * @pre Must have called CMEM_init()
+ *
+ * @sa CMEM_allocPool()
+ * @sa CMEM_allocPool2()
+ * @sa CMEM_alloc()
+ * @sa CMEM_registerAlloc()
+ * @sa CMEM_unregister()
+ * @sa CMEM_free()
+ */
+void *CMEM_alloc2(int blockid, size_t size, CMEM_AllocParams *params);
+
+/**
+ * @brief Register shared usage of an already-allocated buffer
+ *
+ * @param   physp  Physical address of the already-allocated buffer.
+ *
+ * @remarks Used to register the calling process for usage of an
+ *          already-allocated buffer, for the purpose of shared usage of
+ *          the buffer.
+ *
+ * @remarks Allocation properties (such as cached/noncached or heap/pool)
+ *          are inherited from original allocation call.
+ *
+ * @return  A process-specific pointer to the allocated buffer, or NULL
+ *          for failure.
+ *
+ * @pre Must have called some form of CMEM_alloc*()
+ *
+ * @sa CMEM_allocPool()
+ * @sa CMEM_allocPool2()
+ * @sa CMEM_alloc()
+ * @sa CMEM_free()
+ * @sa CMEM_unregister()
+ */
+void *CMEM_registerAlloc(unsigned long physp);
+
+/**
+ * @brief Free a buffer previously allocated with
+ *        CMEM_alloc()/CMEM_allocPool().
+ *
+ * @param   ptr     The pointer to the buffer.
+ * @param   params  Allocation parameters.
+ *
+ * @remarks Use the same CMEM_AllocParams as was used for the allocation.
+ *          params->flags is "don't care".  params->alignment is "don't
+ *          care".
+ *
+ * @return 0 for success or -1 for failure.
+ *
+ * @pre Must have called CMEM_init()
+ *
+ * @sa CMEM_alloc()
+ * @sa CMEM_alloc2()
+ * @sa CMEM_allocPool()
+ * @sa CMEM_allocPool2()
+ * @sa CMEM_registerAlloc()
+ * @sa CMEM_unregister()
+ */
+int CMEM_free(void *ptr, CMEM_AllocParams *params);
+
+/**
+ * @brief Unregister use of a buffer previously registered with
+ *        CMEM_registerAlloc().
+ *
+ * @param   ptr     The pointer to the buffer.
+ * @param   params  Allocation parameters.
+ *
+ * @remarks Use the same CMEM_AllocParams as was used for the allocation.
+ *          params->flags is "don't care".  params->alignment is "don't
+ *          care".
+ *
+ * @return 0 for success or -1 for failure.
+ *
+ * @pre Must have called CMEM_init()
+ *
+ * @sa CMEM_alloc()
+ * @sa CMEM_alloc2()
+ * @sa CMEM_allocPool()
+ * @sa CMEM_allocPool2()
+ * @sa CMEM_registerAlloc()
+ * @sa CMEM_free()
+ */
+int CMEM_unregister(void *ptr, CMEM_AllocParams *params);
+
+/**
+ * @brief Get the physical address of a contiguous buffer.
+ *
+ * @param   ptr     The pointer to the buffer.
+ *
+ * @return The physical address of the buffer or 0 for failure.
+ *
+ * @pre Must have called CMEM_init()
+ */
+unsigned long CMEM_getPhys(void *ptr);
+
+/**
+ * @brief Do a cache writeback of the block pointed to by @c ptr/@c size
+ *
+ * @param   ptr     Pointer to block to writeback
+ * @param   size    Size in bytes of block to writeback.
+ *
+ * @return Success/failure boolean value
+ *
+ * @pre Must have called CMEM_init()
+ *
+ * @sa CMEM_cacheInv()
+ * @sa CMEM_cacheWbInv()
+ */
+int CMEM_cacheWb(void *ptr, size_t size);
+
+/**
+ * @brief Do a cache invalidate of the block pointed to by @c ptr/@c size
+ *
+ * @param   ptr     Pointer to block to invalidate
+ * @param   size    Size in bytes of block to invalidate
+ *
+ * @return Success/failure boolean value
+ *
+ * @pre Must have called CMEM_init()
+ *
+ * @sa CMEM_cacheWb()
+ * @sa CMEM_cacheWbInv()
+ */
+int CMEM_cacheInv(void *ptr, size_t size);
+
+/**
+ * @brief Do a cache writeback/invalidate of the block pointed to by
+ *        @c ptr/@c size
+ *
+ * @param   ptr     Pointer to block to writeback/invalidate
+ * @param   size    Size in bytes of block to writeback/invalidate
+ *
+ * @return Success/failure boolean value
+ *
+ * @pre Must have called CMEM_init()
+ *
+ * @sa CMEM_cacheInv()
+ * @sa CMEM_cacheWb()
+ */
+int CMEM_cacheWbInv(void *ptr, size_t size);
+
+/**
+ * @brief Retrieve version from CMEM driver.
+ *
+ * @return Installed CMEM driver's version number.
+ *
+ * @pre Must have called CMEM_init()
+ */
+int CMEM_getVersion(void);
+
+/**
+ * @brief Retrieve memory block bounds from CMEM driver
+ *
+ * @param   pphys_base   Pointer to storage for base physical address of
+ *                       CMEM's memory block
+ * @param   psize        Pointer to storage for size of CMEM's memory block
+ *
+ * @return Success (0) or failure (-1).
+ *
+ * @pre Must have called CMEM_init()
+ *
+ * @sa  CMEM_getBlockAttrs()
+ * @sa  CMEM_getNumBlocks()
+ */
+int CMEM_getBlock(unsigned long *pphys_base, size_t *psize);
+
+/**
+ * @brief Retrieve extended memory block attributes from CMEM driver
+ *
+ * @param   blockid      Block number
+ * @param   pattrs       Pointer to CMEM_BlockAttrs struct
+ *
+ * @return Success (0) or failure (-1).
+ *
+ * @remarks Currently this API returns the same values as CMEM_getBlock().
+ *
+ * @pre Must have called CMEM_init()
+ *
+ * @sa  CMEM_getBlock()
+ * @sa  CMEM_getNumBlocks()
+ */
+int CMEM_getBlockAttrs(int blockid, CMEM_BlockAttrs *pattrs);
+
+/**
+ * @brief Retrieve number of blocks configured into CMEM driver
+ *
+ * @param   pnblocks     Pointer to storage for holding number of blocks
+ * @param   pattrs       Pointer to CMEM_BlockAttrs struct
+ *
+ * @return Success (0) or failure (-1).
+ *
+ * @remarks Blocks are configured into CMEM through the Linux 'insmod'
+ *          command.
+ *
+ * @pre Must have called CMEM_init()
+ *
+ * @sa  CMEM_getBlock()
+ * @sa  CMEM_getBlockAttrs()
+ */
+int CMEM_getNumBlocks(int *pnblocks);
+
+/**
+ * @brief Finalize the CMEM module.
+ *
+ * @return 0 for success or -1 for failure.
+ *
+ * @remarks After this function has been called, no other CMEM function may be
+ *          called (unless CMEM is reinitialized).
+ *
+ * @pre Must have called CMEM_init()
+ *
+ * @sa CMEM_init()
+ */
+int CMEM_exit(void);
+
+/*@}*/
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
diff --git a/lu.mak b/lu.mak
new file mode 100644 (file)
index 0000000..c2f2c3a
--- /dev/null
+++ b/lu.mak
@@ -0,0 +1,60 @@
+#
+#   Copyright (c) 2012-2013, Texas Instruments Incorporated
+#
+#   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.
+#
+#   *  Neither the name of Texas Instruments Incorporated nor the names of
+#      its contributors may 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 OWNER 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.
+#
+# ======== lu.mak ========
+#
+
+include products.mak
+
+.PHONY: config config-static config-shared module module_install module_clean
+
+config:
+       @echo "Configuring Linux Utils ..."
+       ./configure --host=$(TOOLCHAIN_LONGNAME) \
+            CC=$(TOOLCHAIN_PREFIX)gcc
+
+config-static:
+       @echo "Configuring Linux Utils static only libaries ..."
+       ./configure --host=$(TOOLCHAIN_LONGNAME) --disable-shared \
+            CC=$(TOOLCHAIN_PREFIX)gcc
+
+config-shared:
+       @echo "Configuring Linux Utils shared (dynamic) only libaries ..."
+       ./configure --host=$(TOOLCHAIN_LONGNAME) --disable-static \
+            CC=$(TOOLCHAIN_PREFIX)gcc
+
+module:
+       $(MAKE) -C src/cmem/module
+
+module_install:
+       $(MAKE) -C src/cmem/module install
+
+module_clean:
+       $(MAKE) -C src/cmem/module clean
diff --git a/products.mak b/products.mak
new file mode 100644 (file)
index 0000000..0305fe2
--- /dev/null
@@ -0,0 +1,44 @@
+#
+#   Copyright (c) 2012-2013, Texas Instruments Incorporated
+#
+#   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.
+#
+#   *  Neither the name of Texas Instruments Incorporated nor the names of
+#      its contributors may 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 OWNER 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.
+#
+#  ======== products.mak ========
+#
+
+# Set up required cross compiler path for Linux Utils configuration and build
+
+TOOLCHAIN_LONGNAME ?= arm-none-linux-gnueabi
+TOOLCHAIN_INSTALL_DIR ?= $(VENDORS)/cs/arm/arm-2010q1
+TOOLCHAIN_PREFIX = $(TOOLCHAIN_INSTALL_DIR)/bin/$(TOOLCHAIN_LONGNAME)-
+
+#=============== CMEM module component paths and opions  ======================
+
+#KERNEL_INSTALL_DIR ?= /db/toolsrc/library/vendors2005/kernel_org/arm/TI81XX-LINUX-PSP-04.04.00.01.patch1/src/kernel/ti814x/linux-04.04.00.01
+KERNEL_INSTALL_DIR ?= /db/atree/rt/git/linux-davinci
+
diff --git a/src/cmem/Makefile.am b/src/cmem/Makefile.am
new file mode 100644 (file)
index 0000000..f899c52
--- /dev/null
@@ -0,0 +1,41 @@
+##
+##  Copyright (c) 2012-2013, Texas Instruments Incorporated
+##
+##  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.
+##
+##  *  Neither the name of Texas Instruments Incorporated nor the names of
+##     its contributors may 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 OWNER 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.
+##
+## ======== etc/Makefile.am ========
+##
+
+###############################################################################
+
+# Additional file to be added to the distribution
+EXTRA_DIST =    \
+                 module/cmemk.c \
+                 module/Makefile
+                                               
+###############################################################################
diff --git a/src/cmem/Makefile.in b/src/cmem/Makefile.in
new file mode 100644 (file)
index 0000000..b9bd41d
--- /dev/null
@@ -0,0 +1,321 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+###############################################################################
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/cmem
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+
+# Additional file to be added to the distribution
+EXTRA_DIST = \
+                 module/cmemk.c \
+                 module/Makefile \
+                 module/Module.symvers
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  src/cmem/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  src/cmem/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+uninstall-info-am:
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+       $(mkdir_p) $(distdir)/module
+       @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+       list='$(DISTFILES)'; for file in $$list; do \
+         case $$file in \
+           $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+           $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+         esac; \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           dir="/$$dir"; \
+           $(mkdir_p) "$(distdir)$$dir"; \
+         else \
+           dir=''; \
+         fi; \
+         if test -d $$d/$$file; then \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+       distclean distclean-generic distclean-libtool distdir dvi \
+       dvi-am html html-am info info-am install install-am \
+       install-data install-data-am install-exec install-exec-am \
+       install-info install-info-am install-man install-strip \
+       installcheck installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-generic \
+       mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \
+       uninstall-info-am
+
+
+###############################################################################
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/cmem/README b/src/cmem/README
new file mode 100644 (file)
index 0000000..ae5e48f
--- /dev/null
@@ -0,0 +1,119 @@
+                       Linux Utils CMEM module
+                       -----------------------
+
+
+This package contains a Linux kernel loadable module as well as the user
+interface library.  It also contains a small set of tests.
+
+This particular implementation of CMEM's loadable kernel module is based
+on the Linux kernel's CMA support.  It requires a small in-kernel stub that
+must be added to your Linux kernel source tree.
+
+In order to build the source code you will need to edit products.mak, pointing
+it to your KERNEL_INSTALL_DIR and your codegen directories.
+
+Linux kernel stub
+=================
+
+There are a few files that must be placed in your kernel's source tree.
+These files can be found in 'cmem/module/kernel'.
+
+The file cmemk_stub.c must be added to your Linux kernel source tree.  While
+it can reside anywhere, it is recommended to create a new 'drivers/cmem'
+directory and place the files cmemk_stub.c and Makefile in there.  Since a
+new directory is being added below 'drivers', you will need to modify the
+file 'drivers/Makefile' to point to the 'cmem' subdirectory.  This can be
+accomplished by adding the following line to the 'drivers/Makefile' file:
+        obj-y  += cmem/
+
+The header file cmemk_stub.h must be added to your Linux kernel 'include'
+directory.  Place it in:
+        <linux_kernel>/include/linux/cmemk_stub.h
+
+You must also insert a call to a function defined in cmemk_stub.c to your
+machine's "early boot" code.  This function is named 'cmem_reserve_cma()'.
+The basic way to do this is to add a '.reserve' element to your machine's
+'MACHINE_START()' macro/struct.  There can be only one 'MACHINE_START()'
+defined for your particular board.  For instance, with OMAP-L138 there is a
+file named 'arch/arm/mach-davinci/board-da850-evm.c' that contains the
+following:
+MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM")
+        .atag_offset    = 0x100,
+        .map_io         = da850_evm_map_io,
+        .init_irq       = cp_intc_init,
+        .timer          = &davinci_timer,
+        .init_machine   = da850_evm_init,
+        .init_late      = davinci_init_late,
+        .dma_zone_size  = SZ_128M,
+        .restart        = da8xx_restart,
+MACHINE_END
+You should add the following to this struct:
+        .reserve        = cmem_reserve_cma,
+If there is already a '.reserve' function defined then you will need to
+either add a call to 'cmem_reserve_cma()' to the function assigned to the
+'.reserve' element, or define a new function that calls the existing
+function in addition to calling 'cmem_reserve_cma()', and assign that new
+function to the '.reserve' struct element.
+
+Stub kernel command-line parameters
+-----------------------------------
+
+The CMEM kernel stub cmemk_stub.c supports two kernel parameters that control
+how much CMA memory to reserve.  These parameters are added to the u-boot
+'bootargs' variable.
+
+cmem_heapsize: specifies how much CMA memory to reserve for the CMEM heap.
+cmem_pools: specifies how many buffers of a specified size are allocated for
+        the specified number of pools.
+Each size-type parameter can be specified using the standard "KMG" formatting.
+
+For example, the following:
+        cmem_heapsize=100000 cmem_pools=10x4096,2x1M,4x256K
+says to allocate 3 pools:
+        pool 1 w/ 10 buffers of size 4096
+        pool 2 w/ 2 buffers of size 1 MB
+        pool 3 w/ 4 buffers of size 256 KB
+and a heap of size 100000.
+
+A separate CMA region will be allocated for the heap as well as for each pool.
+
+Building the code
+=================
+
+The file products.mak (at the top level of this tree) contains two
+definitions used by the build subsystem:
+        KERNEL_INSTALL_DIR - The base directory of your Linux kernel
+        source tree
+        TOOLCHAIN_PREFIX - the 'prefix' for the GNU ARM codegen tools
+The TOOLCHAIN_PREFIX can contain the full path of the codegen tools, ending
+with the tool prefix, i.e.:
+        TOOLCHAIN_PREFIX=/db/toolsrc/library/vendors2005/cs/arm/arm-2008q1-126/bin/arm-none-linux-gnueabi-
+
+or it can be just the tool prefix if your shell's $PATH contains your
+codegen's 'bin' directory:
+        TOOLCHAIN_PREFIX=arm-none-linux-gnueabi-
+where you $PATH contains:
+       /db/toolsrc/library/vendors2005/cs/arm/arm-2008q1-126/bin
+
+Installing the loadable kernel module
+=====================================
+
+The loadable kernel module 'cmemk.ko' can be installed into a running
+system with the command:
+        % insmod cmemk.ko
+The traditional non-CMA CMEM implementation supports a number of module
+parameters to define block start/end and pool geometry.  With this CMA
+CMEM implementation, these parameters have been superceded by the kernel
+command-line parameters specified above (although block start/end is not
+yet supported).  However, one can still specifiy 'useHeapIfPoolUnavailable=1'
+when insmod'ing cmemk.ko.
+
+API test
+========
+
+There is an API test contained in 'cmem/tests/apitest.c'.  To run
+this test, suppy a buffer size as the only test parameter:
+        % apitest 10240
+If you have no heap space allocated (with 'heapsize=##' on the kernel
+command-line) then the heap portion of the test will fail.
+
diff --git a/src/cmem/api/Makefile.am b/src/cmem/api/Makefile.am
new file mode 100644 (file)
index 0000000..b5d02d5
--- /dev/null
@@ -0,0 +1,58 @@
+##
+##  Copyright (c) 2013, Texas Instruments Incorporated
+##
+##  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.
+##
+##  *  Neither the name of Texas Instruments Incorporated nor the names of
+##     its contributors may 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 OWNER 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.
+##
+## ======== src/cmem/api/Makefile.am ========
+##
+
+# additional include paths necessary to compile the library
+AM_CFLAGS = -I$(top_srcdir)/include -Wall @AM_CFLAGS@
+
+###############################################################################
+# THE LIBRARIES TO BUILD
+###############################################################################
+
+# the library names to build (note we are building shared libs)
+lib_LTLIBRARIES = libticmem.la
+
+# where to install the headers on the system
+libticmem_ladir = $(includedir)/ti
+
+# the list of header files that belong to the library (to be installed later)
+libticmem_la_HEADERS = $(top_srcdir)/include/ti/cmem.h
+
+# the sources to add to the library and to add to the source distribution
+libticmem_la_SOURCES =  \
+                        $(libticmem_la_HEADERS) \
+                        cmem.c
+
+# Add version info to the shared library
+libticmem_la_LDFLAGS = -version-info 1:0:0
+                                               
+###############################################################################
diff --git a/src/cmem/api/Makefile.in b/src/cmem/api/Makefile.in
new file mode 100644 (file)
index 0000000..5904439
--- /dev/null
@@ -0,0 +1,498 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/cmem/api
+DIST_COMMON = $(libticmem_la_HEADERS) $(srcdir)/Makefile.am \
+       $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libticmem_ladir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libticmem_la_LIBADD =
+am__objects_1 =
+am_libticmem_la_OBJECTS = $(am__objects_1) cmem.lo
+libticmem_la_OBJECTS = $(am_libticmem_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+       $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libticmem_la_SOURCES)
+DIST_SOURCES = $(libticmem_la_SOURCES)
+libticmem_laHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(libticmem_la_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+
+# additional include paths necessary to compile the library
+AM_CFLAGS = -I$(top_srcdir)/include -Wall @AM_CFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+
+###############################################################################
+# THE LIBRARIES TO BUILD
+###############################################################################
+
+# the library names to build (note we are building shared libs)
+lib_LTLIBRARIES = libticmem.la
+
+# where to install the headers on the system
+libticmem_ladir = $(includedir)/ti
+
+# the list of header files that belong to the library (to be installed later)
+libticmem_la_HEADERS = $(top_srcdir)/include/ti/cmem.h
+
+# the sources to add to the library and to add to the source distribution
+libticmem_la_SOURCES = \
+                        $(libticmem_la_HEADERS) \
+                        cmem.c
+
+
+# Add version info to the shared library
+libticmem_la_LDFLAGS = -version-info 1:0:0
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  src/cmem/api/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  src/cmem/api/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+       @$(NORMAL_INSTALL)
+       test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+       @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+         if test -f $$p; then \
+           f=$(am__strip_dir) \
+           echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+           $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+         else :; fi; \
+       done
+
+uninstall-libLTLIBRARIES:
+       @$(NORMAL_UNINSTALL)
+       @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+         p=$(am__strip_dir) \
+         echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+         $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+       done
+
+clean-libLTLIBRARIES:
+       -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+       @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+         dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+         test "$$dir" != "$$p" || dir=.; \
+         echo "rm -f \"$${dir}/so_locations\""; \
+         rm -f "$${dir}/so_locations"; \
+       done
+libticmem.la: $(libticmem_la_OBJECTS) $(libticmem_la_DEPENDENCIES) 
+       $(LINK) -rpath $(libdir) $(libticmem_la_LDFLAGS) $(libticmem_la_OBJECTS) $(libticmem_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmem.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@   if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+uninstall-info-am:
+install-libticmem_laHEADERS: $(libticmem_la_HEADERS)
+       @$(NORMAL_INSTALL)
+       test -z "$(libticmem_ladir)" || $(mkdir_p) "$(DESTDIR)$(libticmem_ladir)"
+       @list='$(libticmem_la_HEADERS)'; for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         f=$(am__strip_dir) \
+         echo " $(libticmem_laHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libticmem_ladir)/$$f'"; \
+         $(libticmem_laHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libticmem_ladir)/$$f"; \
+       done
+
+uninstall-libticmem_laHEADERS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(libticmem_la_HEADERS)'; for p in $$list; do \
+         f=$(am__strip_dir) \
+         echo " rm -f '$(DESTDIR)$(libticmem_ladir)/$$f'"; \
+         rm -f "$(DESTDIR)$(libticmem_ladir)/$$f"; \
+       done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       $(mkdir_p) $(distdir)/../../../include/ti
+       @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+       list='$(DISTFILES)'; for file in $$list; do \
+         case $$file in \
+           $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+           $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+         esac; \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           dir="/$$dir"; \
+           $(mkdir_p) "$(distdir)$$dir"; \
+         else \
+           dir=''; \
+         fi; \
+         if test -d $$d/$$file; then \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+       for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libticmem_ladir)"; do \
+         test -z "$$dir" || $(mkdir_p) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+       mostlyclean-am
+
+distclean: distclean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libticmem_laHEADERS
+
+install-exec-am: install-libLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES \
+       uninstall-libticmem_laHEADERS
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+       clean-libLTLIBRARIES clean-libtool ctags distclean \
+       distclean-compile distclean-generic distclean-libtool \
+       distclean-tags distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-exec \
+       install-exec-am install-info install-info-am \
+       install-libLTLIBRARIES install-libticmem_laHEADERS install-man \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+       pdf pdf-am ps ps-am tags uninstall uninstall-am \
+       uninstall-info-am uninstall-libLTLIBRARIES \
+       uninstall-libticmem_laHEADERS
+
+
+###############################################################################
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/cmem/api/cmem.c b/src/cmem/api/cmem.c
new file mode 100644 (file)
index 0000000..8aac0bd
--- /dev/null
@@ -0,0 +1,635 @@
+/*
+ * cmem.c
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+#include <ti/cmem.h>
+
+CMEM_AllocParams CMEM_DEFAULTPARAMS = {
+    CMEM_POOL,         /* type */
+    CMEM_NONCACHED,    /* flags */
+    1                  /* alignment */
+};
+
+#ifdef __DEBUG
+#define __D(fmt, args...) fprintf(stderr, "CMEM Debug: " fmt, ## args)
+#else
+#define __D(fmt, args...)
+#endif
+
+#define __E(fmt, args...) fprintf(stderr, "CMEM Error: " fmt, ## args)
+
+struct block_struct {
+    unsigned long addr;
+    size_t size;
+};
+
+/* set cmem_fd to -2 to distinguish from failed open (-1) */
+static int cmem_fd = -2;
+static int ref_count = 0;
+
+static void *getAndAllocFromPool(int blockid, size_t size, CMEM_AllocParams *params);
+static void *allocFromHeap(int blockid, size_t size, CMEM_AllocParams *params);
+static void *allocFromPool(int blockid, int poolid, CMEM_AllocParams *params);
+
+static int validate_init()
+{
+    switch (cmem_fd) {
+      case -3:
+       __E("CMEM_exit() already called, check stderr output for earlier "
+           "CMEM failure messages (possibly version mismatch).\n");
+
+       return 0;
+
+      case -2:
+        __E("CMEM_init() not called, you must initialize CMEM before "
+           "making API calls.\n");
+
+       return 0;
+
+      case -1:
+        __E("CMEM file descriptor -1 (failed 'open()'), ensure CMEMK "
+           "kernel module cmemk.ko has been installed with 'insmod'");
+
+       return 0;
+
+      default:
+       return 1;
+    }
+}
+
+int CMEM_init(void)
+{
+    int flags;
+    unsigned int version;
+
+    __D("init: entered - ref_count %d, cmem_fd %d\n", ref_count, cmem_fd);
+
+    if (cmem_fd >= 0) {
+       ref_count++;
+       __D("init: /dev/cmem already opened, incremented ref_count %d\n",
+            ref_count);
+       return 0;
+    }
+
+    cmem_fd = open("/dev/cmem", O_RDWR);
+
+    if (cmem_fd == -1) {
+        __E("init: Failed to open /dev/cmem: '%s'\n", strerror(errno));
+        return -1;
+    }
+
+    ref_count++;
+
+    __D("init: successfully opened /dev/cmem, matching driver version...\n");
+
+    version = CMEM_getVersion();
+    if ((version & 0xffff0000) != (CMEM_VERSION & 0xffff0000)) {
+        __E("init: major version mismatch between interface and driver.\n");
+        __E("    needs driver version %#x, got %#x\n", CMEM_VERSION, version);
+       CMEM_exit();
+       return -1;
+    }
+    else if ((version & 0x0000ffff) < (CMEM_VERSION & 0x0000ffff)) {
+        __E("init: minor version mismatch between interface and driver.\n");
+        __E("    needs driver minor version %#x or greater.\n"
+           "    got minor version %#x (full version %#x)\n",
+           CMEM_VERSION & 0x0000ffff, version & 0x0000ffff, version);
+       CMEM_exit();
+       return -1;
+    }
+
+    __D("init: ... match good (%#x)\n", version);
+
+    flags = fcntl(cmem_fd, F_GETFD);
+    if (flags != -1) {
+        fcntl(cmem_fd, F_SETFD, flags | FD_CLOEXEC);
+    }
+    else {
+        __E("init: fcntl(F_GETFD) failed: '%s'\n", strerror(errno));
+    }
+
+    __D("init: exiting, returning success\n");
+
+    return 0;
+}
+
+static void *allocFromPool(int blockid, int poolid, CMEM_AllocParams *params)
+{
+    union CMEM_AllocUnion allocDesc;
+    unsigned long physp;
+    void *userp;
+    size_t size;
+    unsigned int cmd;
+    int rv;
+
+    allocDesc.alloc_pool_inparams.poolid = poolid;
+    allocDesc.alloc_pool_inparams.blockid = blockid;
+    cmd = CMEM_IOCALLOC | params->flags;
+    rv = ioctl(cmem_fd, cmd | CMEM_IOCMAGIC, &allocDesc);
+    if (rv != 0) {
+        __E("allocPool: ioctl %s failed from pool %d: %d\n",
+           cmd == CMEM_IOCALLOC ? "CMEM_IOCALLOC" : "CMEM_IOCALLOCCACHED",
+           poolid, rv);
+        return NULL;
+    }
+    physp = allocDesc.alloc_pool_outparams.physp;
+    size = allocDesc.alloc_pool_outparams.size;
+
+    __D("allocPool: allocated phys buffer %#lx, size %#x\n", physp, size);
+
+    /* Map the physical address to user space */
+    userp = mmap(0,                       // Preferred start address
+                 size,                    // Length to be mapped
+                 PROT_WRITE | PROT_READ,  // Read and write access
+                 MAP_SHARED,              // Shared memory
+                 cmem_fd,                 // File descriptor
+                 physp);                  // The byte offset from fd
+
+    if (userp == MAP_FAILED) {
+        __E("allocPool: Failed to mmap buffer at physical address %#lx\n",
+            physp);
+        __E("    Freeing phys buffer %#lx\n", physp);
+        ioctl(cmem_fd, CMEM_IOCFREEPHYS | CMEM_IOCMAGIC , &physp);
+        return NULL;
+    }
+
+    __D("allocPool: mmap succeeded, returning virt buffer %p\n", userp);
+
+    return userp;
+}
+
+static void *getAndAllocFromPool(int blockid, size_t size, CMEM_AllocParams *params)
+{
+    int poolid;
+
+    poolid = CMEM_getPool2(blockid, size);
+
+    if (poolid == -1) {
+       return NULL;
+    }
+    if (poolid == -2) {
+       return allocFromHeap(blockid, size, params);
+    }
+    else {
+       return allocFromPool(blockid, poolid, params);
+    }
+}
+
+static void *allocFromHeap(int blockid, size_t size, CMEM_AllocParams *params)
+{
+    void *userp;
+    union CMEM_AllocUnion allocDesc;
+    unsigned long physp;
+    unsigned int cmd;
+    int rv;
+
+    cmd = CMEM_IOCALLOCHEAP | params->flags;
+    allocDesc.alloc_heap_inparams.size = size;
+    allocDesc.alloc_heap_inparams.align = params->alignment == 0 ?
+                                  1 : params->alignment;
+    allocDesc.alloc_heap_inparams.blockid = blockid;
+
+    rv = ioctl(cmem_fd, cmd | CMEM_IOCMAGIC, &allocDesc);
+    if (rv != 0) {
+        __E("allocHeap: ioctl %s failed: %d\n",
+           cmd == CMEM_IOCALLOCHEAP ?
+                  "CMEM_IOCALLOCHEAP" : "CMEM_IOCALLOCHEAPCACHED",
+           rv);
+        return NULL;
+    }
+    physp = allocDesc.physp;
+
+    __D("allocHeap: allocated phys buffer %#lx\n", physp);
+
+    /* Map the physical address to user space */
+    userp = mmap(0,                       // Preferred start address
+                 size,                    // Length to be mapped
+                 PROT_WRITE | PROT_READ,  // Read and write access
+                 MAP_SHARED,              // Shared memory
+                 cmem_fd,                 // File descriptor
+                 physp);                  // The byte offset from fd
+
+    if (userp == MAP_FAILED) {
+        __E("allocHeap: Failed to mmap buffer at physical address %#lx\n",
+            physp);
+        __E("    Freeing phys buffer %#lx\n", physp);
+        ioctl(cmem_fd, CMEM_IOCFREEHEAPPHYS | CMEM_IOCMAGIC, &physp);
+        return NULL;
+    }
+
+    __D("allocHeap: mmap succeeded, returning virt buffer %p\n", userp);
+
+    return userp;
+}
+
+/*
+ *  Single interface into all flavors of alloc.
+ *  Need to support:
+ *    - cached vs. noncached
+ *    - heap vs. pool
+ *    - alignment w/ heap allocs
+ */
+static void *alloc(int blockid, size_t size, CMEM_AllocParams *params)
+{
+    if (params == NULL) {
+       params = &CMEM_DEFAULTPARAMS;
+    }
+
+    __D("alloc: entered w/ size %#x, params - type %s, flags %s, align %#x%s\n",
+        size,
+        params->type == CMEM_POOL ? "POOL" : "HEAP",
+        params->flags & CMEM_CACHED ? "CACHED" : "NONCACHED",
+        params->alignment,
+        params == &CMEM_DEFAULTPARAMS ? " (default)" : "");
+
+    if (!validate_init()) {
+       return NULL;
+    }
+
+    if (params->type == CMEM_POOL) {
+       return getAndAllocFromPool(blockid, size, params);
+    }
+    else {
+       return allocFromHeap(blockid, size, params);
+    }
+}
+
+void *CMEM_alloc(size_t size, CMEM_AllocParams *params)
+{
+    return alloc(0, size, params);
+}
+
+void *CMEM_alloc2(int blockid, size_t size, CMEM_AllocParams *params)
+{
+    return alloc(blockid, size, params);
+}
+
+void *CMEM_registerAlloc(unsigned long physp)
+{
+    union CMEM_AllocUnion allocDesc;
+    void *userp;
+    size_t size;
+    int rv;
+
+    allocDesc.physp = physp;
+    rv = ioctl(cmem_fd, CMEM_IOCREGUSER | CMEM_IOCMAGIC, &allocDesc);
+    if (rv != 0) {
+        __E("registerAlloc: ioctl CMEM_IOCREGUSER failed for phys addr %#lx: %d\n",
+           physp, rv);
+
+        return NULL;
+    }
+    size = allocDesc.size;
+
+    __D("registerAlloc: registered use of phys buffer %#lx, size %#x\n",
+        physp, size);
+
+    /* Map the physical address to user space */
+    userp = mmap(0,                       // Preferred start address
+                 size,                    // Length to be mapped
+                 PROT_WRITE | PROT_READ,  // Read and write access
+                 MAP_SHARED,              // Shared memory
+                 cmem_fd,                 // File descriptor
+                 physp);               // The byte offset from fd
+
+    if (userp == MAP_FAILED) {
+        __E("registerAlloc: Failed to mmap buffer at physical address %#lx\n",
+            physp);
+        __E("    Unregistering use of phys buffer %#lx\n", physp);
+        ioctl(cmem_fd, CMEM_IOCFREEPHYS | CMEM_IOCMAGIC, &physp);
+
+        return NULL;
+    }
+
+    __D("registerAlloc: mmap succeeded, returning virt buffer %p\n", userp);
+
+    return userp;
+}
+
+static void *allocPool(int blockid, int poolid, CMEM_AllocParams *params)
+{
+    if (params == NULL) {
+       params = &CMEM_DEFAULTPARAMS;
+    }
+
+    __D("allocPool: entered w/ poolid %d, params - flags %s%s\n", poolid,
+        params->flags & CMEM_CACHED ? "CACHED" : "NONCACHED",
+        params == &CMEM_DEFAULTPARAMS ? " (default)" : "");
+
+    if (!validate_init()) {
+       return NULL;
+    }
+
+    return allocFromPool(blockid, poolid, params);
+}
+
+void *CMEM_allocPool(int poolid, CMEM_AllocParams *params)
+{
+    return allocPool(0, poolid, params);
+}
+
+void *CMEM_allocPool2(int blockid, int poolid, CMEM_AllocParams *params)
+{
+    return allocPool(blockid, poolid, params);
+}
+
+int CMEM_free(void *ptr, CMEM_AllocParams *params)
+{
+    union CMEM_AllocUnion freeDesc;
+    unsigned int cmd;
+    size_t size;
+
+    if (params == NULL) {
+       params = &CMEM_DEFAULTPARAMS;
+    }
+
+    __D("free: entered w/ ptr %p, params - type %s%s\n",
+        ptr,
+        params->type == CMEM_POOL ? "POOL" : "HEAP",
+        params == &CMEM_DEFAULTPARAMS ? " (default)" : "");
+
+    if (!validate_init()) {
+       return -1;
+    }
+
+    freeDesc.virtp = (int)ptr;
+    cmd = CMEM_IOCFREE | params->type;
+    if (ioctl(cmem_fd, cmd | CMEM_IOCMAGIC, &freeDesc) == -1) {
+        __E("free: failed to free %#x\n", (unsigned int) ptr);
+        return -1;
+    }
+    size = freeDesc.free_outparams.size;
+
+    __D("free: ioctl CMEM_IOCFREE%s succeeded, size %#x\n",
+        params->type == CMEM_POOL ? "POOL" : "HEAP", size);
+
+    if (munmap(ptr, size) == -1) {
+        __E("free: failed to munmap %#x\n", (unsigned int) ptr);
+        return -1;
+    }
+
+    __D("free: munmap succeeded, returning 0\n");
+
+    return 0;
+}
+
+int CMEM_unregister(void *ptr, CMEM_AllocParams *params)
+{
+    __D("unregister: delegating to CMEM_free()...\n");
+
+    return CMEM_free(ptr, params);
+}
+
+static int getPoolFromBlock(int blockid, size_t size)
+{
+    union CMEM_AllocUnion poolDesc;
+
+    if (!validate_init()) {
+       return -1;
+    }
+
+    poolDesc.get_pool_inparams.size = size;
+    poolDesc.get_pool_inparams.blockid = blockid;
+    if (ioctl(cmem_fd, CMEM_IOCGETPOOL | CMEM_IOCMAGIC, &poolDesc) == -1) {
+        __E("getPool: Failed to get a pool fitting a size %d\n", size);
+        return -1;
+    }
+
+    __D("getPool: exiting, ioctl CMEM_IOCGETPOOL succeeded, returning %d\n",
+        poolDesc.poolid);
+
+    return poolDesc.poolid;
+}
+
+int CMEM_getPool(size_t size)
+{
+    __D("getPool: entered w/ size %#x\n", size);
+
+    return getPoolFromBlock(0, size);
+}
+
+int CMEM_getPool2(int blockid, size_t size)
+{
+    __D("getPool2: entered w/ size %#x\n", size);
+
+    return getPoolFromBlock(blockid, size);
+}
+
+unsigned long CMEM_getPhys(void *ptr)
+{
+    union CMEM_AllocUnion getDesc;
+
+    __D("getPhys: entered w/ addr %p\n", ptr);
+
+    if (!validate_init()) {
+       return 0;
+    }
+
+    getDesc.virtp = (unsigned long)ptr;
+    if (ioctl(cmem_fd, CMEM_IOCGETPHYS | CMEM_IOCMAGIC, &getDesc) == -1) {
+        __E("getPhys: Failed to get physical address of %#x\n",
+            (unsigned int) ptr);
+        return 0;
+    }
+
+    __D("getPhys: exiting, ioctl CMEM_IOCGETPHYS succeeded, returning %#lx\n",
+        getDesc.physp);
+
+    return getDesc.physp;
+}
+
+int CMEM_cacheWb(void *ptr, size_t size)
+{
+    struct block_struct block;
+
+    __D("cacheWb: entered w/ addr %p, size %#x\n", ptr, size);
+
+    if (!validate_init()) {
+       return -1;
+    }
+
+    block.addr = (unsigned long)ptr;
+    block.size = size;
+    if (ioctl(cmem_fd, CMEM_IOCCACHEWB | CMEM_IOCMAGIC, &block) == -1) {
+        __E("cacheWb: Failed to writeback %#x\n", (unsigned int) ptr);
+
+        return -1;
+    }
+
+    __D("cacheWb: exiting, ioctl CMEM_IOCCACHEWB succeeded, returning 0\n");
+
+    return 0;
+}
+
+int CMEM_cacheWbInv(void *ptr, size_t size)
+{
+    struct block_struct block;
+
+    __D("cacheWbInv: entered w/ addr %p, size %#x\n", ptr, size);
+
+    if (!validate_init()) {
+       return -1;
+    }
+
+    block.addr = (unsigned long)ptr;
+    block.size = size;
+    if (ioctl(cmem_fd, CMEM_IOCCACHEWBINV | CMEM_IOCMAGIC, &block) == -1) {
+        __E("cacheWbInv: Failed to writeback & invalidate %#x\n",
+            (unsigned int) ptr);
+
+        return -1;
+    }
+
+    __D("cacheWbInv: exiting, ioctl CMEM_IOCCACHEWBINV succeeded, returning 0\n");
+
+    return 0;
+}
+
+int CMEM_cacheInv(void *ptr, size_t size)
+{
+    struct block_struct block;
+
+    __D("cacheInv: entered w/ addr %p, size %#x\n", ptr, size);
+
+    if (!validate_init()) {
+       return -1;
+    }
+
+    block.addr = (unsigned long)ptr;
+    block.size = size;
+    if (ioctl(cmem_fd, CMEM_IOCCACHEINV | CMEM_IOCMAGIC, &block) == -1) {
+        __E("cacheInv: Failed to invalidate %#x\n", (unsigned int) ptr);
+
+        return -1;
+    }
+
+    __D("cacheInv: exiting, ioctl CMEM_IOCCACHEINV succeeded, returning 0\n");
+
+    return 0;
+}
+
+int CMEM_getVersion(void)
+{
+    unsigned int version;
+    int rv;
+
+    __D("getVersion: entered\n");
+
+    if (!validate_init()) {
+       return -1;
+    }
+
+    rv = ioctl(cmem_fd, CMEM_IOCGETVERSION | CMEM_IOCMAGIC, &version);
+    if (rv != 0) {
+       __E("getVersion: Failed to retrieve version from driver: %d.\n", rv);
+
+       return -1;
+    }
+
+    __D("getVersion: exiting, ioctl CMEM_IOCGETVERSION returned %#x\n",
+        version);
+
+    return version;
+}
+
+static int getBlock(int blockid, unsigned long *pphys_base, size_t *psize)
+{
+    union CMEM_AllocUnion block;
+    int rv;
+
+    __D("getBlock: entered\n");
+
+    if (!validate_init()) {
+       return -1;
+    }
+
+    block.blockid = blockid;
+    rv = ioctl(cmem_fd, CMEM_IOCGETBLOCK | CMEM_IOCMAGIC, &block);
+    if (rv != 0) {
+       __E("getBlock: Failed to retrieve memory block bounds for block %d "
+            "from driver: %d.\n", blockid, rv);
+
+       return -1;
+    }
+
+    *pphys_base = block.get_block_outparams.physp;
+    *psize = block.get_block_outparams.size;
+
+    __D("getBlock: exiting, ioctl CMEM_IOCGETBLOCK succeeded, "
+        "returning *pphys_base=0x%lx, *psize=0x%x\n", *pphys_base, *psize);
+
+    return 0;
+}
+
+int CMEM_getBlock(unsigned long *pphys_base, size_t *psize)
+{
+    return getBlock(0, pphys_base, psize);
+}
+
+int CMEM_getBlockAttrs(int blockid, CMEM_BlockAttrs *pattrs)
+{
+    return getBlock(blockid, &pattrs->phys_base, &pattrs->size);
+}
+
+int CMEM_getNumBlocks(int *pnblocks)
+{
+    int rv;
+
+    __D("getNumBlocks: entered\n");
+
+    if (!validate_init()) {
+       return -1;
+    }
+
+    rv = ioctl(cmem_fd, CMEM_IOCGETNUMBLOCKS | CMEM_IOCMAGIC, pnblocks);
+    if (rv != 0) {
+       __E("getBlock: Failed to retrieve number of blocks "
+            "from driver: %d.\n", rv);
+
+       return -1;
+    }
+
+    __D("getNumBlocks: exiting, ioctl CMEM_IOCGETNUMBLOCKS succeeded, "
+        "returning *pnblocks=%d\n", *pnblocks);
+
+    return 0;
+}
+
+int CMEM_exit(void)
+{
+    int result = 0;
+
+    __D("exit: entered - ref_count %d, cmem_fd %d\n", ref_count, cmem_fd);
+
+    if (!validate_init()) {
+       return -1;
+    }
+
+    __D("exit: decrementing ref_count\n");
+
+    ref_count--;
+    if (ref_count == 0) {
+       result = close(cmem_fd);
+
+       __D("exit: ref_count == 0, closed /dev/cmem (%s)\n",
+            result == -1 ? strerror(errno) : "succeeded");
+
+       /* setting -3 allows to distinguish CMEM exit from CMEM failed */
+       cmem_fd = -3;
+    }
+
+    __D("exit: exiting, returning %d\n", result);
+
+    return result;
+}
+
diff --git a/src/cmem/module/Makefile b/src/cmem/module/Makefile
new file mode 100644 (file)
index 0000000..3069d9c
--- /dev/null
@@ -0,0 +1,42 @@
+ROOTDIR = ../../..
+
+# need an absolute path for -I switch below in EXTRA_CFLAGS
+ABS_ROOTDIR = $(shell cd $(ROOTDIR); pwd)
+
+# We conditionally include $(ROOTDIR)/Rules.make because when the
+# kernel make system invokes us, it won't be found... but that's okay.
+-include $(ROOTDIR)/products.mak
+
+TARGET = cmemk.ko
+
+obj-m += cmemk.o
+
+EXTRA_CFLAGS +=        -I $(ABS_ROOTDIR)/include
+
+MAKE_ENV = ARCH=arm CROSS_COMPILE=$(TOOLCHAIN_PREFIX)
+
+debug: EXTRA_CFLAGS += -D__DEBUG
+
+.PHONY: clean debug release install glibc
+
+glibc: release
+
+docs:
+
+release:
+       @echo Making module release...
+       make -C $(KERNEL_INSTALL_DIR) M=`pwd` $(MAKE_ENV) \
+               EXTRA_CFLAGS="$(EXTRA_CFLAGS)" modules
+
+debug:
+       @echo Making module debug...
+       make -C $(KERNEL_INSTALL_DIR) M=`pwd` $(MAKE_ENV) \
+               EXTRA_CFLAGS="$(EXTRA_CFLAGS)" modules
+
+install:
+       @echo Making module install...
+       install -d $(EXEC_DIR)
+       install $(TARGET) $(EXEC_DIR)
+
+clean:
+       -rm -rf *.o *mod* *.ko .cmem* .tmp* Module.symvers
diff --git a/src/cmem/module/cmemk.c b/src/cmem/module/cmemk.c
new file mode 100644 (file)
index 0000000..d4cf2c3
--- /dev/null
@@ -0,0 +1,1149 @@
+/*
+ * cmemk.c
+ */
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/list.h>
+#include <linux/cdev.h>
+#include <linux/proc_fs.h>
+#include <linux/mm.h>
+#include <linux/seq_file.h>
+#include <linux/vmalloc.h>
+#include <linux/sched.h>
+#include <asm/cacheflush.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+
+#include <linux/version.h>
+
+#include <linux/cmemk_stub.h>
+
+#include <ti/cmem.h>
+
+
+/*
+ * Poor man's config params
+ */
+
+#ifdef __DEBUG
+#define __D(fmt, args...) printk(KERN_DEBUG "CMEMK Debug: " fmt, ## args)
+#else
+#define __D(fmt, args...)
+#endif
+
+#define __E(fmt, args...) printk(KERN_ERR "CMEMK Error: " fmt, ## args)
+
+#define MAXTYPE(T) ((T) (((T)1 << ((sizeof(T) * 8) - 1) ^ ((T) -1))))
+
+#ifndef VM_RESERVED
+#define VM_RESERVED 0x00080000
+#endif
+
+static int heap_pool = 0;
+
+static int cmem_major;
+static struct proc_dir_entry *cmem_proc_entry;
+static atomic_t reference_count = ATOMIC_INIT(0);
+static unsigned int version = CMEM_VERSION;
+
+static struct class *cmem_class;
+static struct mutex cmem_mutex;
+
+/* Register the module parameters. */
+
+static int useHeapIfPoolUnavailable = 0;
+MODULE_PARM_DESC(useHeapIfPoolUnavailable,
+    "\n\t\t Set to 1 if you want a pool-based allocation request to"
+    "\n\t\t fall back to a heap-based allocation attempt");
+module_param(useHeapIfPoolUnavailable, int, S_IRUGO);
+
+/* Describes a pool buffer */
+typedef struct pool_buffer {
+    struct list_head element;
+    struct list_head users;
+    struct page *start_page;
+    unsigned long physp;
+    size_t size;               /* used only for heap-based allocs */
+    int count;
+    int flags;                 /* CMEM_CACHED or CMEM_NONCACHED */
+} pool_buffer;
+
+typedef struct registered_user {
+    struct list_head element;
+    struct file *filp;
+} registered_user;
+
+/* Forward declaration of system calls */
+static long ioctl(struct file *filp, unsigned int cmd, unsigned long args);
+static int mmap(struct file *filp, struct vm_area_struct *vma);
+static int open(struct inode *inode, struct file *filp);
+static int release(struct inode *inode, struct file *filp);
+
+static struct file_operations cmem_fxns = {
+    owner:   THIS_MODULE,
+    unlocked_ioctl: ioctl,
+    mmap:    mmap,
+    open:    open,
+    release: release
+};
+
+
+/* Traverses the page tables and translates a virtual adress to a physical. */
+static unsigned long get_phys(unsigned long virtp)
+{
+    unsigned long physp = ~(0L);
+    struct mm_struct *mm = current->mm;
+    struct vm_area_struct *vma;
+
+    /* For kernel direct-mapped memory, take the easy way */
+    if (virtp >= PAGE_OFFSET) {
+        physp = virt_to_phys((void *)virtp);
+       __D("get_phys: virt_to_phys translated direct-mapped %#lx to %#lx\n",
+           virtp, physp);
+    }
+
+    /* this will catch, kernel-allocated, mmaped-to-usermode addresses */
+    else if ((vma = find_vma(mm, virtp)) &&
+             (vma->vm_flags & VM_IO) &&
+             (vma->vm_pgoff)) {
+        physp =  (vma->vm_pgoff << PAGE_SHIFT) + (virtp - vma->vm_start);
+       __D("get_phys: find_vma translated user %#lx to %#lx\n", virtp, physp);
+    }
+
+    /* otherwise, use get_user_pages() for general userland pages */
+    else {
+        int res, nr_pages = 1;
+        struct page *pages;
+
+        down_read(&current->mm->mmap_sem);
+
+        res = get_user_pages(current, current->mm,
+                             virtp, nr_pages,
+                             1, 0,
+                             &pages, NULL);
+        up_read(&current->mm->mmap_sem);
+
+        if (res == nr_pages) {
+            physp = __pa(page_address(&pages[0]) + (virtp & ~PAGE_MASK));
+           __D("get_phys: get_user_pages translated user %#lx to %#lx\n",
+               virtp, physp);
+        } else {
+            __E("%s: Unable to find phys addr for 0x%08lx\n",
+                __FUNCTION__, virtp);
+            __E("%s: get_user_pages() failed: %d\n", __FUNCTION__, res);
+        }
+    }
+
+    return physp;
+}
+
+#ifdef __DEBUG
+/* Only for debug */
+static void dump_lists(int idx)
+{
+    struct list_head *busylistp = &cmem_p_objs[idx].busylist;
+    struct list_head *e;
+    struct pool_buffer *entry;
+
+    if (mutex_lock_interruptible(&cmem_mutex)) {
+        return;
+    }
+
+    __D("Busylist for pool %d:\n", idx);
+    for (e = busylistp->next; e != busylistp; e = e->next) {
+
+        entry = list_entry(e, struct pool_buffer, element);
+
+        __D("Busy: Buffer with physical address %#lx\n", entry->physp);
+    }
+
+    mutex_unlock(&cmem_mutex);
+}
+#endif
+
+/*
+ *  ======== find_busy_entry ========
+ *  find_busy_entry looks for an allocated pool buffer with
+ *  phyisical addr physp.
+ *
+ *  Should be called with the cmem_mutex held.
+ */
+static struct pool_buffer *find_busy_entry(unsigned long physp, int *poolp, struct list_head **ep)
+{
+    struct list_head *busylistp;
+    struct list_head *e;
+    struct pool_buffer *entry;
+    int i;
+
+    for (i = 0; i < cmem_npools; i++) {
+       busylistp = &cmem_p_objs[i].busylist;
+
+       for (e = busylistp->next; e != busylistp; e = e->next) {
+           entry = list_entry(e, struct pool_buffer, element);
+           if (entry->physp == physp) {
+               if (poolp) {
+                   *poolp = i;
+               }
+               if (ep) {
+                   *ep = e;
+               }
+
+               return entry;
+           }
+       }
+    }
+
+    return NULL;
+}
+
+static int set_noncached(struct vm_area_struct *vma)
+{
+    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+    vma->vm_flags |= VM_RESERVED | VM_IO;
+
+    if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+                        vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
+        __E("set_noncached: failed remap_pfn_range\n");
+        return -EAGAIN;
+    }
+
+    return 0;
+}
+
+static int set_cached(struct vm_area_struct *vma)
+{
+    vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) |
+                                 (L_PTE_MT_WRITETHROUGH | L_PTE_MT_BUFFERABLE)
+                                );
+    vma->vm_flags |= VM_RESERVED | VM_IO;
+
+    if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+                        vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
+        __E("set_cached: failed remap_pfn_range\n");
+        return -EAGAIN;
+    }
+
+    return 0;
+}
+
+struct block_struct {
+    unsigned long addr;
+    size_t size;
+};
+
+static long ioctl(struct file *filp, unsigned int cmd, unsigned long args)
+{
+    unsigned int __user *argp = (unsigned int __user *) args;
+    struct page *page;
+    struct list_head *busylistp = NULL;
+    struct list_head *registeredlistp;
+    struct list_head *e = NULL;
+    struct list_head *u;
+    struct list_head *unext;
+    struct pool_buffer *entry;
+    struct registered_user *user;
+    unsigned long physp;
+    unsigned long virtp, virtp_end;
+    size_t reqsize, align;
+    size_t size = 0;
+    int delta = MAXTYPE(int);
+    int count;
+    int order;
+    int pool = -1;
+    int i;
+    struct block_struct block;
+    union CMEM_AllocUnion allocDesc;
+
+    if (_IOC_TYPE(cmd) != _IOC_TYPE(CMEM_IOCMAGIC)) {
+       __E("ioctl(): bad command type 0x%x (should be 0x%x)\n",
+           _IOC_TYPE(cmd), _IOC_TYPE(CMEM_IOCMAGIC));
+    }
+
+    switch (cmd & CMEM_IOCCMDMASK) {
+        /*
+         * argp contains a pointer to an alloc descriptor coming in, and the
+         * physical address and size of the allocated buffer when returning.
+         */
+        case CMEM_IOCALLOC:
+           if (copy_from_user(&allocDesc, argp, sizeof(allocDesc))) {
+                return -EFAULT;
+            }
+
+           pool = allocDesc.alloc_pool_inparams.poolid;
+
+            __D("ALLOC%s ioctl received on pool %d\n",
+               cmd & CMEM_CACHED ? "CACHED" : "", pool);
+
+            if (pool >= cmem_npools || pool < 0) {
+                __E("ALLOC%s: invalid pool (%d) passed.\n",
+                   cmd & CMEM_CACHED ? "CACHED" : "", pool);
+                return -EINVAL;
+            }
+
+           size = cmem_p_objs[pool].size;
+           align = 0;
+
+           goto alloc;
+
+        case CMEM_IOCALLOCHEAP:
+           if (copy_from_user(&allocDesc, argp, sizeof(allocDesc))) {
+               return -EFAULT;
+           }
+
+           size = allocDesc.alloc_heap_inparams.size;
+           align = allocDesc.alloc_heap_inparams.align;
+
+            __D("ALLOCHEAP%s ioctl received on heap pool\n",
+               cmd & CMEM_CACHED ? "CACHED" : "");
+           __D("  size=%d align=%d\n", size, align);
+
+           if (cmem_heapsize == 0) {
+               __E("ioctl: no heap available\n");
+               return -EINVAL;
+           }
+
+           pool = 0;
+alloc:
+           /* round up to next page size */
+           count = ((size - 1) >> PAGE_SHIFT) + 1;
+
+           order = 0;
+           align = align >> PAGE_SHIFT;
+           while (align) {
+               align = align >> 1;
+               order++;
+           }
+
+           entry = kmalloc(sizeof(struct pool_buffer), GFP_KERNEL);
+           if (!entry) {
+               __E("ioctl: failed to kmalloc pool_buffer struct for heap");
+
+               return -ENOMEM;
+           }
+
+           if (mutex_lock_interruptible(&cmem_mutex)) {
+               return -ERESTARTSYS;
+           }
+
+           __D("ioctl: cmem_alloc(&cmem_dev[%d], %d, %d)...\n",
+               pool, count, order);
+
+           page = cmem_alloc(&cmem_dev[pool], count, order);
+           if (page == NULL) {
+               __E("ioctl: failed to alloc contiguous buffer of size %#x\n",
+                   size);
+
+               mutex_unlock(&cmem_mutex);
+               kfree(entry);
+
+               return -ENOMEM;
+           }
+
+           virtp = (unsigned long)page_address(page);
+           physp = page_to_pfn(page) << PAGE_SHIFT;
+
+           entry->start_page = page;
+           entry->count = count;
+           entry->physp = physp;
+           entry->size = size;
+           entry->flags = cmd & ~CMEM_IOCCMDMASK;
+           INIT_LIST_HEAD(&entry->users);
+
+            busylistp = &cmem_p_objs[pool].busylist;
+           list_add_tail(&entry->element, busylistp);
+
+           user = kmalloc(sizeof(struct registered_user), GFP_KERNEL);
+           user->filp = filp;
+           list_add(&user->element, &entry->users);
+
+            mutex_unlock(&cmem_mutex);
+
+           if ((cmd & CMEM_IOCCMDMASK) == CMEM_IOCALLOC) {
+                   allocDesc.alloc_pool_outparams.physp = entry->physp;
+                   allocDesc.alloc_pool_outparams.size = entry->size;
+
+                   if (copy_to_user(argp, &allocDesc, sizeof(allocDesc))) {
+                       return -EFAULT;
+                   }
+           }
+           else {
+                   if (put_user(physp, argp)) {
+                       return -EFAULT;
+                   }
+           }
+
+            __D("ALLOC%s%s: allocated %#x size buffer at %#lx (phys address)\n",
+               (cmd & CMEM_IOCCMDMASK) == CMEM_IOCALLOCHEAP ? "HEAP" : "",
+               cmd & CMEM_CACHED ? "CACHED" : "", entry->size, entry->physp);
+
+           break;
+
+        /*
+         * argp contains either the user virtual address or the physical
+        * address of the buffer to free coming in, and contains the pool
+        * where it was freed from and the size of the block on return.
+         */
+        case CMEM_IOCFREE:
+            __D("FREE%s%s ioctl received.\n",
+               cmd & CMEM_HEAP ? "HEAP" : "",
+               cmd & CMEM_PHYS ? "PHYS" : "");
+
+           if (!(cmd & CMEM_PHYS)) {
+               if (get_user(virtp, argp)) {
+                   return -EFAULT;
+               }
+
+               physp = get_phys(virtp);
+
+               if (physp == ~(0L)) {
+                   __E("FREE%s: Failed to convert virtual %#lx to physical\n",
+                       cmd & CMEM_HEAP ? "HEAP" : "", virtp);
+                   return -EFAULT;
+               }
+
+               __D("FREE%s: translated %#lx user virtual to %#lx physical\n",
+                   cmd & CMEM_HEAP ? "HEAP" : "", virtp, physp);
+           }
+           else {
+               virtp = 0L;    /* silence the compiler warning */
+               if (get_user(physp, argp)) {
+                   return -EFAULT;
+               }
+           }
+
+           if (mutex_lock_interruptible(&cmem_mutex)) {
+               return -ERESTARTSYS;
+           }
+
+           size = 0;
+
+           entry = find_busy_entry(physp, &pool, &e);
+           if (entry) {
+               /* record values in case entry gets kfree()'d for CMEM_HEAP */
+               size = entry->size;
+
+               registeredlistp = &entry->users;
+               u = registeredlistp->next;
+               while (u != registeredlistp) {
+                   unext = u->next;
+
+                   user = list_entry(u, struct registered_user, element);
+                   if (user->filp == filp) {
+                       __D("FREE%s%s: Removing file %p from user list of buffer %#lx...\n",
+                           cmd & CMEM_HEAP ? "HEAP" : "",
+                           cmd & CMEM_PHYS ? "PHYS" : "", filp, physp);
+
+                       list_del(u);
+                       kfree(user);
+
+                       break;
+                   }
+
+                   u = unext;
+               }
+
+               if (u == registeredlistp) {
+                   __E("FREE%s%s: Not a registered user of physical buffer %#lx\n",
+                       cmd & CMEM_HEAP ? "HEAP" : "",
+                       cmd & CMEM_PHYS ? "PHYS" : "", physp);
+                   mutex_unlock(&cmem_mutex);
+
+                   return -EFAULT;
+               }
+
+               if (registeredlistp->next == registeredlistp) {
+                   /* no more registered users, free buffer */
+
+                   page = entry->start_page;
+                   count = entry->count;
+
+                   list_del(e);
+                   kfree(entry);
+
+                   cmem_release(&cmem_dev[pool], page, count);
+
+                   __D("FREE%s%s: Successfully freed buffer from pool %d\n",
+                       cmd & CMEM_HEAP ? "HEAP" : "",
+                       cmd & CMEM_PHYS ? "PHYS" : "", pool);
+               }
+           }
+
+            mutex_unlock(&cmem_mutex);
+
+            if (!entry) {
+                __E("Failed to free memory at %#lx\n", physp);
+                return -EFAULT;
+            }
+
+#ifdef __DEBUG
+            dump_lists(pool);
+#endif
+
+           if (pool == heap_pool) {
+               allocDesc.free_outparams.size = size;
+           }
+           else {
+               allocDesc.free_outparams.size = cmem_p_objs[pool].size;
+           }
+           allocDesc.free_outparams.poolid = pool;
+           if (copy_to_user(argp, &allocDesc, sizeof(allocDesc))) {
+                return -EFAULT;
+            }
+
+            __D("FREE%s%s: returning size %d, poolid %d\n",
+               cmd & CMEM_HEAP ? "HEAP" : "",
+               cmd & CMEM_PHYS ? "PHYS" : "",
+               allocDesc.free_outparams.size,
+               allocDesc.free_outparams.poolid);
+
+            break;
+
+        /*
+         * argp contains the user virtual address of the buffer to translate
+         * coming in, and the translated physical address on return.
+         */
+        case CMEM_IOCGETPHYS:
+            __D("GETPHYS ioctl received.\n");
+            if (get_user(virtp, argp)) {
+                return -EFAULT;
+            }
+
+            physp = get_phys(virtp);
+
+            if (physp == ~(0L)) {
+                __E("GETPHYS: Failed to convert virtual %#lx to physical.\n",
+                    virtp);
+                return -EFAULT;
+            }
+
+            if (put_user(physp, argp)) {
+                return -EFAULT;
+            }
+
+            __D("GETPHYS: returning %#lx\n", physp);
+            break;
+
+        /*
+         * argp contains the pool to query for size coming in, and the size
+         * of the pool on return.
+         */
+        case CMEM_IOCGETSIZE:
+            __D("GETSIZE ioctl received\n");
+           if (copy_from_user(&allocDesc, argp, sizeof(allocDesc))) {
+                return -EFAULT;
+            }
+
+           pool = allocDesc.get_size_inparams.poolid;
+
+            if (pool >= cmem_npools || pool < 0) {
+                __E("GETSIZE: invalid pool (%d) passed.\n", pool);
+                return -EINVAL;
+            }
+
+            if (put_user(cmem_p_objs[pool].size, argp)) {
+                return -EFAULT;
+            }
+            __D("GETSIZE returning %d\n", cmem_p_objs[pool].size);
+            break;
+
+        /*
+         * argp contains the requested pool buffers size coming in, and the
+         * pool id (index) on return.
+         */
+        case CMEM_IOCGETPOOL:
+            __D("GETPOOL ioctl received.\n");
+           if (copy_from_user(&allocDesc, argp, sizeof(allocDesc))) {
+                return -EFAULT;
+            }
+
+           reqsize = allocDesc.get_pool_inparams.size;
+
+           if (mutex_lock_interruptible(&cmem_mutex)) {
+               return -ERESTARTSYS;
+           }
+
+            __D("GETPOOL: Trying to find a pool to fit size %d\n", reqsize);
+            for (i = 1; i < cmem_npools; i++) {
+                size = cmem_p_objs[i].size;
+
+                __D("GETPOOL: size (%d) > reqsize (%d)?\n", size, reqsize);
+                if (size >= reqsize) {
+                    __D("GETPOOL: delta (%d) < olddelta (%d)?\n",
+                        size - reqsize, delta);
+                    if ((size - reqsize) < delta) {
+                       delta = size - reqsize;
+                       __D("GETPOOL: Found a best fit delta %d\n", delta);
+                       pool = i;
+                    }
+                }
+            }
+
+           if (pool == -1 && cmem_heapsize != 0) {
+               if (useHeapIfPoolUnavailable) {
+                   /* no pool buffer available, try heap */
+
+                   /*
+                    * Indicate heap pool with magic negative value.
+                    * -1 indicates no pool and no heap.
+                    * -2 indicates no pool but heap available and allowed.
+                    */
+                   pool = -2;
+
+                   __D("GETPOOL: no pool-based buffer available, "
+                       "returning heap \"pool\" instead (due to config "
+                       "override)\n");
+               }
+           }
+
+            mutex_unlock(&cmem_mutex);
+
+           if (pool == -1) {
+               __E("Failed to find a pool which fits %d\n", reqsize);
+
+               return -ENOMEM;
+            }
+
+            if (put_user(pool, argp)) {
+                return -EFAULT;
+            }
+            __D("GETPOOL: returning %d\n", pool);
+            break;
+
+        case CMEM_IOCCACHE:
+            __D("CACHE%s%s ioctl received.\n",
+               cmd & CMEM_WB ? "WB" : "", cmd & CMEM_INV ? "INV" : "");
+
+           if (copy_from_user(&block, argp, sizeof(block))) {
+               return -EFAULT;
+           }
+           virtp = block.addr;
+           virtp_end = virtp + block.size;
+
+           switch (cmd & ~CMEM_IOCMAGIC) {
+             case CMEM_IOCCACHEWB:
+               dmac_map_area((void *)virtp, block.size, DMA_TO_DEVICE);
+               outer_clean_range(__pa((u32)(void *)virtp),
+                                 __pa((u32)(void *)virtp + block.size));
+               __D("CACHEWB: cleaned user virtual %#lx->%#lx\n",
+                      virtp, virtp_end);
+
+               break;
+
+             case CMEM_IOCCACHEINV:
+               dmac_map_area((void *)virtp, block.size, DMA_FROM_DEVICE);
+               outer_inv_range(__pa((u32)(void *)virtp),
+                               __pa((u32)(void *)virtp + block.size));
+               __D("CACHEINV: invalidated user virtual %#lx->%#lx\n",
+                      virtp, virtp_end);
+
+               break;
+
+             case CMEM_IOCCACHEWBINV:
+               dmac_map_area((void *)virtp, block.size, DMA_BIDIRECTIONAL);
+               outer_flush_range(__pa((u32)(void *)virtp),
+                                 __pa((u32)(void *)virtp + block.size));
+               __D("CACHEWBINV: flushed user virtual %#lx->%#lx\n",
+                      virtp, virtp_end);
+
+               break;
+           }
+
+           break;
+
+        case CMEM_IOCGETVERSION:
+            __D("GETVERSION ioctl received, returning %#x.\n", version);
+
+            if (put_user(version, argp)) {
+                return -EFAULT;
+            }
+
+           break;
+
+        case CMEM_IOCREGUSER:
+            __D("REGUSER ioctl received.\n");
+
+           if (get_user(physp, argp)) {
+               return -EFAULT;
+           }
+
+           if (mutex_lock_interruptible(&cmem_mutex)) {
+               return -ERESTARTSYS;
+           }
+
+           entry = find_busy_entry(physp, &pool, &e);
+           if (entry) {
+               /*
+                * Should we check if the "current" process is already on
+                * the list and return error if so?  Or should we just
+                * silently not put it on the list twice and return success?
+                * Or should we put it on the list a second time, which seems
+                * to be OK to do and will require being removed from the
+                * list twice?  So many questions...
+                *
+                * The code below, lacking the test, will put a process on
+                * the list multiple times (every time IOCREGUSER is called).
+                */
+               user = kmalloc(sizeof(struct registered_user), GFP_KERNEL);
+               user->filp = filp;
+               list_add(&user->element, &entry->users);
+           }
+
+            mutex_unlock(&cmem_mutex);
+
+            if (!entry) {
+                return -EFAULT;
+            }
+
+            if (put_user(entry->size, argp)) {
+                return -EFAULT;
+            }
+
+           break;
+
+        default:
+            __E("Unknown ioctl received.\n");
+            return -EINVAL;
+    }
+
+    return 0;
+}
+
+static int mmap(struct file *filp, struct vm_area_struct *vma)
+{
+    unsigned long physp;
+    struct pool_buffer *entry;
+
+    __D("mmap: vma->vm_start     = %#lx\n", vma->vm_start);
+    __D("mmap: vma->vm_pgoff     = %#lx\n", vma->vm_pgoff);
+    __D("mmap: vma->vm_end       = %#lx\n", vma->vm_end);
+    __D("mmap: size              = %#lx\n", vma->vm_end - vma->vm_start);
+
+    physp = vma->vm_pgoff << PAGE_SHIFT;
+
+    if (mutex_lock_interruptible(&cmem_mutex)) {
+       return -ERESTARTSYS;
+    }
+
+    entry = find_busy_entry(physp, NULL, NULL);
+    mutex_unlock(&cmem_mutex);
+
+    if (entry != NULL) {
+       if (entry->flags & CMEM_CACHED) {
+           __D("mmap: calling set_cached(%p) ...\n", vma);
+
+           return set_cached(vma);
+       }
+       else {
+           __D("mmap: calling set_noncached(%p) ...\n", vma);
+
+           return set_noncached(vma);
+       }
+    }
+    else {
+       __E("mmap: can't find allocated buffer with physp %lx\n", physp);
+
+       return -EINVAL;
+    }
+}
+
+static int open(struct inode *inode, struct file *filp)
+{
+    __D("open: called.\n");
+
+    atomic_inc(&reference_count);
+
+    return 0;
+}
+
+static int release(struct inode *inode, struct file *filp)
+{
+    struct list_head *registeredlistp;
+    struct list_head *busylistp;
+    struct list_head *e;
+    struct list_head *u;
+    struct list_head *next;
+    struct list_head *unext;
+    struct page *page;
+    struct pool_buffer *entry;
+    struct registered_user *user;
+    int last_close = 0;
+    int count;
+    int i;
+
+    __D("close: called.\n");
+
+    /* Force free all buffers owned by the 'current' process */
+
+    if (atomic_dec_and_test(&reference_count)) {
+        __D("close: all references closed, force freeing all busy buffers.\n");
+
+       last_close = 1;
+    }
+
+    /* Clean up any buffers on the busy list when cmem is closed */
+    for (i = 0; i < cmem_npools; i++) {
+       __D("Forcing free on pool %d\n", i);
+
+       /* acquire the mutex in case this isn't the last close */
+       if (mutex_lock_interruptible(&cmem_mutex)) {
+           return -ERESTARTSYS;
+       }
+
+       busylistp = &cmem_p_objs[i].busylist;
+
+       e = busylistp->next;
+       while (e != busylistp) {
+           __D("busy entry(s) found\n");
+
+           next = e->next;
+
+           entry = list_entry(e, struct pool_buffer, element);
+           registeredlistp = &entry->users;
+           u = registeredlistp->next;
+           while (u != registeredlistp) {
+               unext = u->next;
+
+               user = list_entry(u, struct registered_user, element);
+
+               if (last_close || user->filp == filp) {
+                   __D("Removing file %p from user list of buffer %#lx...\n",
+                       user->filp, entry->physp);
+
+                   list_del(u);
+                   kfree(user);
+               }
+
+               u = unext;
+           }
+
+           if (registeredlistp->next == registeredlistp) {
+               /* no more registered users, free buffer */
+
+               __D("Warning: Freeing 'busy' buffer at %#lx\n",
+                   entry->physp);
+
+               page = entry->start_page;
+               count = entry->count;
+               cmem_release(&cmem_dev[i], page, count);
+
+               list_del(e);
+               kfree(entry);
+           }
+
+           e = next;
+       }
+
+       mutex_unlock(&cmem_mutex);
+    }
+
+    __D("close: returning\n");
+
+    return 0;
+}
+
+static void banner(void)
+{
+    printk(KERN_INFO "CMEMK module: built on " __DATE__ " at " __TIME__ "\n");
+    printk(KERN_INFO "  Reference Linux version %d.%d.%d\n",
+           (LINUX_VERSION_CODE & 0x00ff0000) >> 16,
+           (LINUX_VERSION_CODE & 0x0000ff00) >> 8,
+           (LINUX_VERSION_CODE & 0x000000ff) >> 0
+          );
+    printk(KERN_INFO "  File " __FILE__ "\n");
+}
+
+#if 0
+void __init cmem_test_init(void)
+{
+    printk("cmem_test_init(): calling test_dma_contig(1, 0)...\n");
+
+    test_dma_contig(1, 0);
+#if 0
+    test_dma_contig(2, 0);
+    test_dma_contig(4, 0);
+    test_dma_contig(1, 1);
+    test_dma_contig(2, 1);
+    test_dma_contig(4, 1);
+    test_dma_contig(1, 2);
+    test_dma_contig(2, 2);
+    test_dma_contig(4, 2);
+#endif
+    test_dma_contig(1, 3); // order 3 = pages aligned to 0x8000
+    test_dma_contig(8, 3);
+    test_dma_contig(9, 3);
+    test_dma_contig(16, 3);
+
+    printk("...done\n");
+}
+#endif
+
+struct device dev;
+
+int __init cmem_init(void)
+{
+    int i;
+    int err;
+
+    banner();
+
+    mutex_init(&cmem_mutex);
+
+    cmem_major = register_chrdev(0, "cmem", &cmem_fxns);
+    if (cmem_major < 0) {
+        __E("Failed to allocate major number.\n");
+        return -ENODEV;
+    }
+
+    __D("Allocated major number: %d\n", cmem_major);
+
+    cmem_class = class_create(THIS_MODULE, "cmem");
+    if (IS_ERR(cmem_class)) {
+        __E("Error creating cmem device class.\n");
+       err = -EIO;
+       goto fail_after_reg;
+    }
+
+    dev.devt = MKDEV(cmem_major, 0);
+    dev.class = cmem_class;
+    dev_set_name(&dev, "cmem");
+
+    err = device_register(&dev);
+    if (err) {
+       __E("Unable to register dev\n");
+       err = -EIO;
+       goto fail_after_class;
+    }
+
+    for (i = 0; i < cmem_npools; i++) {
+       cmem_dev[i].devt = MKDEV(cmem_major, i+1);
+       cmem_dev[i].class = cmem_class;
+       dev_set_name(&cmem_dev[i], "cmem%d", i+1);
+
+       err = device_register(&cmem_dev[i]);
+       if (err) {
+           __E("Unable to register cmem_dev[i]\n");
+           err = -EIO;
+           goto fail_after_class;
+       }
+    }
+
+#if 0
+    cmem_test_init();
+#endif
+
+    /* Create the /proc entry */
+    cmem_proc_entry = create_proc_entry("cmem", 0, NULL);
+    if (cmem_proc_entry) {
+//     cmem_proc_entry->proc_fops = &cmem_proc_ops;
+    }
+
+    printk(KERN_INFO "cmemk initialized\n");
+
+    return 0;
+
+fail_after_class:
+    __D("Destroying class cmem\n");
+    class_destroy(cmem_class);
+
+fail_after_reg:
+    __D("Unregistering character device cmem\n");
+    unregister_chrdev(cmem_major, "cmem");
+
+    return err;
+}
+
+void __exit cmem_exit(void)
+{
+    struct list_head *registeredlistp;
+    struct list_head *busylistp;
+    struct list_head *e;
+    struct list_head *u;
+    struct list_head *unext;
+    struct pool_buffer *entry;
+    struct registered_user *user;
+    int i;
+
+    __D("In cmem_exit()\n");
+
+    /* Remove the /proc entry */
+    remove_proc_entry("cmem", NULL);
+
+    /* Free the pool structures and empty the lists. */
+    for (i = 0; i < cmem_npools; i++) {
+       __D("Freeing memory associated with pool %d\n", i);
+
+       busylistp = &cmem_p_objs[i].busylist;
+
+       e = busylistp->next;
+       while (e != busylistp) {
+           entry = list_entry(e, struct pool_buffer, element);
+
+           __D("Warning: Freeing busy entry at %#lx\n", entry->physp);
+
+           registeredlistp = &entry->users;
+           u = registeredlistp->next;
+           while (u != registeredlistp) {
+               unext = u->next;
+
+               user = list_entry(u, struct registered_user, element);
+
+               __D("Removing file %p from user list of buffer %#lx...\n",
+                   user->filp, entry->physp);
+
+               list_del(u);
+               kfree(user);
+
+               u = unext;
+           }
+
+           e = e->next;
+           kfree(entry);
+       }
+    }
+
+    for (i = 0; i < cmem_npools; i++) {
+       __D("Unregistering device minor %d\n", i);
+       device_unregister(&cmem_dev[i]);
+    }
+
+    __D("Destroying class cmem\n");
+    class_destroy(cmem_class);
+
+    __D("Unregistering character device cmem\n");
+    unregister_chrdev(cmem_major, "cmem");
+
+    printk(KERN_INFO "cmemk unregistered\n");
+}
+
+MODULE_LICENSE("GPL");
+module_init(cmem_init);
+module_exit(cmem_exit);
+
+
+#if !defined(MULTI_CACHE)
+
+#warning "MULTI_CACHE is *not* #defined, using work-around for asm cache functions"
+
+/*
+ * The following assembly functions were taken from
+ *     arch/arm/mm/proc-arm926.S
+ * Since we can't use the C preprocessor to evaluate #defines, the
+ * code that was taken is the code encapsulated by
+ *     #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
+ *     ...
+ *     #endif
+ * (note that this is #ifndef, i.e., #if !defined)
+ */
+
+/*
+ * the cache line size of the I and D cache
+ */
+/*
+ * Leave here for documentation purposes, but we don't use it since
+ * asm("") statements won't get preprocessed (inside a string).
+ */
+#define CACHE_DLINESIZE 32
+
+asm("\n \
+        .global arm926_dma_map_area\n \
+arm926_dma_map_area:\n \
+        add     r1, r1, r0\n \
+@        cmp     r2, #DMA_TO_DEVICE\n \
+        cmp     r2, #1\n \
+        beq     arm926_dma_clean_range\n \
+        bcs     arm926_dma_inv_range\n \
+        b       arm926_dma_flush_range\n \
+");
+
+/*
+ *      dma_inv_range(start, end)
+ *
+ *      Invalidate (discard) the specified virtual address range.
+ *      May not write back any entries.  If 'start' or 'end'
+ *      are not cache line aligned, those lines must be written
+ *      back.
+ *
+ *      - start - virtual start address
+ *      - end   - virtual end address
+ *
+ * (same as v4wb)
+ENTRY(arm926_dma_inv_range)
+ */
+asm("\n \
+       .global arm926_dma_inv_range\n \
+arm926_dma_inv_range:\n \
+@        tst     r0, #CACHE_DLINESIZE - 1\n \
+        tst     r0, #32 - 1\n \
+        mcrne   p15, 0, r0, c7, c10, 1          @ clean D entry\n \
+@        tst     r1, #CACHE_DLINESIZE - 1\n \
+        tst     r1, #32 - 1\n \
+        mcrne   p15, 0, r1, c7, c10, 1          @ clean D entry\n \
+@        bic     r0, r0, #CACHE_DLINESIZE - 1\n \
+        bic     r0, r0, #32 - 1\n \
+1:      mcr     p15, 0, r0, c7, c6, 1           @ invalidate D entry\n \
+@        add     r0, r0, #CACHE_DLINESIZE\n \
+        add     r0, r0, #32\n \
+        cmp     r0, r1\n \
+        blo     1b\n \
+        mcr     p15, 0, r0, c7, c10, 4          @ drain WB\n \
+        mov     pc, lr\n \
+");
+
+/*
+ *      dma_clean_range(start, end)
+ *
+ *      Clean the specified virtual address range.
+ *
+ *      - start - virtual start address
+ *      - end   - virtual end address
+ *
+ * (same as v4wb)
+ENTRY(arm926_dma_clean_range)
+ */
+asm("\n \
+       .global arm926_dma_clean_range\n \
+arm926_dma_clean_range:\n \
+@        bic     r0, r0, #CACHE_DLINESIZE - 1\n \
+        bic     r0, r0, #32 - 1\n \
+1:      mcr     p15, 0, r0, c7, c10, 1          @ clean D entry\n \
+@        add     r0, r0, #CACHE_DLINESIZE\n \
+        add     r0, r0, #32\n \
+        cmp     r0, r1\n \
+        blo     1b\n \
+        mcr     p15, 0, r0, c7, c10, 4          @ drain WB\n \
+        mov     pc, lr\n \
+");
+
+/*
+ *      dma_flush_range(start, end)
+ *
+ *      Clean and invalidate the specified virtual address range.
+ *
+ *      - start - virtual start address
+ *      - end   - virtual end address
+ENTRY(arm926_dma_flush_range)
+ */
+asm("\n \
+       .global arm926_dma_flush_range\n \
+arm926_dma_flush_range:\n \
+@        bic     r0, r0, #CACHE_DLINESIZE - 1\n \
+        bic     r0, r0, #32 - 1\n \
+1:\n \
+        mcr     p15, 0, r0, c7, c14, 1          @ clean+invalidate D entry\n \
+@        add     r0, r0, #CACHE_DLINESIZE\n \
+        add     r0, r0, #32\n \
+        cmp     r0, r1\n \
+        blo     1b\n \
+        mcr     p15, 0, r0, c7, c10, 4          @ drain WB\n \
+        mov     pc, lr\n \
+");
+
+#endif /* !defined(MULTI_CACHE) */
+
diff --git a/src/cmem/module/kernel/drivers/Makefile b/src/cmem/module/kernel/drivers/Makefile
new file mode 100644 (file)
index 0000000..4a3c68f
--- /dev/null
@@ -0,0 +1 @@
+obj-y          += cmem/
diff --git a/src/cmem/module/kernel/drivers/cmem/Makefile b/src/cmem/module/kernel/drivers/cmem/Makefile
new file mode 100644 (file)
index 0000000..06b3af7
--- /dev/null
@@ -0,0 +1,3 @@
+
+obj-y += cmemk_stub.o
+
diff --git a/src/cmem/module/kernel/drivers/cmem/cmemk_stub.c b/src/cmem/module/kernel/drivers/cmem/cmemk_stub.c
new file mode 100644 (file)
index 0000000..714605a
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * cmemk_stub.c
+ */
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/string.h>
+
+#include <linux/cmemk_stub.h>
+
+int cmem_npools = 1;
+int cmem_heapsize = 0;
+struct device cmem_dev[CMEM_MAXPOOLS];
+struct pool_object cmem_p_objs[CMEM_MAXPOOLS];
+
+EXPORT_SYMBOL(cmem_npools);
+EXPORT_SYMBOL(cmem_heapsize);
+EXPORT_SYMBOL(cmem_dev);
+EXPORT_SYMBOL(cmem_p_objs);
+
+static int __init early_cmemheapsize(char *p)
+{
+    cmem_heapsize = memparse(p, NULL);
+    cmem_p_objs[0].reqsize = cmem_heapsize;
+    cmem_p_objs[0].numbufs = 1;
+
+    pr_debug("cmemheapsize: heapsize=0x%x\n", cmem_heapsize);
+
+    return 0;
+}
+early_param("cmem_heapsize", early_cmemheapsize);
+
+static int __init early_cmempools(char *p)
+{
+    int done = 0;
+    int n;
+    char *x;
+
+    do {
+       x = strchr(p, 'x');
+       if (x != NULL) {
+           *x = '\0';
+           n = cmem_npools;
+           if (n == CMEM_MAXPOOLS) {
+               pr_err("cmempools: CMEM_MAXPOOLS reached!\n");
+
+               break;
+           }
+           cmem_p_objs[n].numbufs = memparse(p, NULL);
+           cmem_p_objs[n].reqsize = memparse(x + 1, &x);
+
+           pr_debug("cmempools: pool %d = %d * 0x%x\n", n, cmem_p_objs[n].numbufs, cmem_p_objs[n].reqsize);
+
+           cmem_npools++;
+
+           if (*x++ == ',') {
+               p = x;
+           }
+           else {
+               done = 1;
+           }
+       }
+       else {
+           done = 1;
+       }
+    } while (!done);
+
+    return 0;
+}
+early_param("cmem_pools", early_cmempools);
+
+
+struct page *cmem_alloc(struct device *dev, int count, int order)
+{
+    return dma_alloc_from_contiguous(dev, count, order);
+}
+EXPORT_SYMBOL(cmem_alloc);
+
+
+int cmem_release(struct device *dev, struct page *page, int count)
+{
+    return dma_release_from_contiguous(dev, page, count);
+}
+EXPORT_SYMBOL(cmem_release);
+
+static void cmem_device_release(struct device *dev)
+{
+    pr_debug("cmem_device_release(%p)...\n", dev);
+
+    put_device(dev);
+}
+
+
+/* this function is registered in arch/arm/plat-omap/common.c */
+void __init cmem_reserve_cma(void)
+{
+    int poolsize;
+    int reqsize;
+    int size;
+    int nbufs;
+    int i;
+    int rv;
+
+    pr_debug("cmem_reserve_cma()...\n");
+
+    for (i = 0; i < cmem_npools; i++) {
+       if (i == 0) {
+           pr_debug("cmem_reserve_cma: heapsize 0x%x specified\n", cmem_heapsize);
+       }
+       reqsize = cmem_p_objs[i].reqsize;
+       if (reqsize != 0) {
+           nbufs = cmem_p_objs[i].numbufs;
+           size = round_up(reqsize, PAGE_SIZE);
+           poolsize = nbufs * size;
+           rv = dma_declare_contiguous(&cmem_dev[i], poolsize, 0, 0xffffffff);
+
+           if (rv) {
+               pr_err("cmem_reserve_cma: dma_declare_contiguous failed %d\n", rv);
+
+               /* size of 0 means no buffers available */
+               cmem_p_objs[i].size = 0;
+           }
+           else {
+               pr_debug("cmem_reserve_cma: dma_declare_contiguous succeeded\n");
+               cmem_dev[i].release = cmem_device_release;
+
+               /* numbufs and reqsize already set in early_cmempools() */
+               INIT_LIST_HEAD(&cmem_p_objs[i].busylist);
+               cmem_p_objs[i].size = size;
+           }
+       }
+       else {
+           INIT_LIST_HEAD(&cmem_p_objs[i].busylist);
+       }
+    }
+}
+
+#if 0
+void __init test_dma_contig(struct device *dev, int count, int order)
+{
+    struct page *cma_page[16];
+    void *va;
+    int i;
+
+    for (i = 0; i < 16; i++) {
+       cma_page[i] = dma_alloc_from_contiguous(dev, count, order);
+       if (!cma_page[i]) {
+           printk("dma_alloc_from_contiguous(%p, %d, %d) failed\n", dev, count, order);
+       }
+       else {
+           printk("dma_alloc_from_contiguous(%p, %d, %d) SUCCEEDED: page=%p pfn=0x%lx(000)\n", dev, count, order, cma_page[i], page_to_pfn(cma_page[i]));
+           va = page_address(cma_page[i]);
+//         printk("page_address()=%p, getPhys(%p)=0x%lx\n", va, va, get_phys((unsigned long)va));
+           printk("page_address()=%p, getPhys(%p)=0x%lx\n", va, va, page_to_pfn(cma_page[i]) << PAGE_SHIFT);
+       }
+    }
+    for (i = 0; i < 16; i++) {
+       if (cma_page[i]) {
+           printk("dma_release_from_contiguous(%p, %p, %d)...\n", dev, cma_page[i], count);
+           dma_release_from_contiguous(dev, cma_page[i], count);
+       }
+    }
+}
+
+void __init cmem_test_init(void)
+{
+    printk("cmem_test_init(): calling test_dma_contig(1, 0)...\n");
+
+    test_dma_contig(&cmem_dev[0], 1, 0);
+    test_dma_contig(&cmem_dev[0], 2, 0);
+    test_dma_contig(&cmem_dev[0], 4, 0);
+    test_dma_contig(&cmem_dev[0], 1, 1);
+    test_dma_contig(&cmem_dev[0], 2, 1);
+    test_dma_contig(&cmem_dev[0], 4, 1);
+    test_dma_contig(&cmem_dev[0], 1, 2);
+    test_dma_contig(&cmem_dev[0], 2, 2);
+    test_dma_contig(&cmem_dev[0], 4, 2);
+    test_dma_contig(&cmem_dev[0], 1, 3); // order 3 = pages aligned to 0x8000
+    test_dma_contig(&cmem_dev[0], 8, 3);
+    test_dma_contig(&cmem_dev[0], 9, 3);
+    test_dma_contig(&cmem_dev[0], 16, 3);
+
+    printk("...done\n");
+}
+#endif
+
+MODULE_LICENSE("GPL");
+
diff --git a/src/cmem/module/kernel/include/linux/cmemk_stub.h b/src/cmem/module/kernel/include/linux/cmemk_stub.h
new file mode 100644 (file)
index 0000000..6767a4d
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ *  @defgroup   ti_sdo_linuxutils_cmem_CMEM  Contiguous Memory Manager
+ *
+ *  This is the API for the Contiguous Memory Manager.
+ */
+
+#ifndef _CMEMK_STUB_H
+#define _CMEMK_STUB_H
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+#define CMEM_MAXPOOLS 8
+
+struct pool_object {
+    struct list_head busylist;
+    unsigned int numbufs;
+    unsigned int size;
+    unsigned int reqsize;
+};
+
+extern struct pool_object cmem_p_objs[CMEM_MAXPOOLS];
+extern struct device cmem_dev[CMEM_MAXPOOLS];
+extern int cmem_heapsize;
+extern int cmem_npools;
+
+extern struct page *cmem_alloc(struct device *dev, int count, int order);
+extern int cmem_release(struct device *dev, struct page *page, int count);
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif
diff --git a/src/cmem/tests/Makefile.am b/src/cmem/tests/Makefile.am
new file mode 100644 (file)
index 0000000..d5e1454
--- /dev/null
@@ -0,0 +1,70 @@
+##
+##  Copyright (c) 2013, Texas Instruments Incorporated
+##
+##  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.
+##
+##  *  Neither the name of Texas Instruments Incorporated nor the names of
+##     its contributors may 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 OWNER 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.
+##
+## ======== src/test/Makefile.am ========
+##
+
+# additional include paths necessary to compile the program
+AM_CFLAGS = -I$(top_srcdir)/include -Wall @AM_CFLAGS@
+
+###############################################################################
+# THE PROGRAMS TO BUILD
+###############################################################################
+
+# the program to build (the names of the final binaries)
+bin_PROGRAMS = apitest multi_process translate
+
+common_sources = $(top_srcdir)/include/ti/cmem.h
+
+# list of sources for the 'apitest' binary
+apitest_SOURCES = $(common_sources) apitest.c
+
+# list of sources for the 'multi_process' binary
+multi_process_SOURCES = $(common_sources) multi_process.c
+
+# list of sources for the 'translate' binary
+translate_SOURCES = $(common_sources) translate.c
+
+common_libraries = $(top_builddir)/src/cmem/api/libticmem.la
+
+# the additional libraries needed to link 'apitest'
+apitest_LDADD = $(common_libraries) \
+                $(AM_LDFLAGS)
+
+# the additional libraries needed to link 'multi_process'
+multi_process_LDADD = $(common_libraries) \
+                $(AM_LDFLAGS)
+
+# the additional libraries needed to link 'translate'
+translate_LDADD = $(common_libraries) \
+                $(AM_LDFLAGS)
+
+###############################################################################
+
diff --git a/src/cmem/tests/Makefile.in b/src/cmem/tests/Makefile.in
new file mode 100644 (file)
index 0000000..5d44354
--- /dev/null
@@ -0,0 +1,493 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+bin_PROGRAMS = apitest$(EXEEXT) multi_process$(EXEEXT) \
+       translate$(EXEEXT)
+subdir = src/cmem/tests
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS)
+am__objects_1 =
+am_apitest_OBJECTS = $(am__objects_1) apitest.$(OBJEXT)
+apitest_OBJECTS = $(am_apitest_OBJECTS)
+am__DEPENDENCIES_1 = $(top_builddir)/src/cmem/api/libticmem.la
+am__DEPENDENCIES_2 =
+apitest_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
+am_multi_process_OBJECTS = $(am__objects_1) multi_process.$(OBJEXT)
+multi_process_OBJECTS = $(am_multi_process_OBJECTS)
+multi_process_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+       $(am__DEPENDENCIES_2)
+am_translate_OBJECTS = $(am__objects_1) translate.$(OBJEXT)
+translate_OBJECTS = $(am_translate_OBJECTS)
+translate_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
+DEFAULT_INCLUDES = -I. -I$(srcdir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+       $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(apitest_SOURCES) $(multi_process_SOURCES) \
+       $(translate_SOURCES)
+DIST_SOURCES = $(apitest_SOURCES) $(multi_process_SOURCES) \
+       $(translate_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+
+# additional include paths necessary to compile the program
+AM_CFLAGS = -I$(top_srcdir)/include -Wall @AM_CFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+common_sources = $(top_srcdir)/include/ti/cmem.h
+
+# list of sources for the 'apitest' binary
+apitest_SOURCES = $(common_sources) apitest.c
+
+# list of sources for the 'multi_process' binary
+multi_process_SOURCES = $(common_sources) multi_process.c
+
+# list of sources for the 'translate' binary
+translate_SOURCES = $(common_sources) translate.c
+common_libraries = $(top_builddir)/src/cmem/api/libticmem.la
+
+# the additional libraries needed to link 'apitest'
+apitest_LDADD = $(common_libraries) \
+                $(AM_LDFLAGS)
+
+
+# the additional libraries needed to link 'multi_process'
+multi_process_LDADD = $(common_libraries) \
+                $(AM_LDFLAGS)
+
+
+# the additional libraries needed to link 'translate'
+translate_LDADD = $(common_libraries) \
+                $(AM_LDFLAGS)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  src/cmem/tests/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  src/cmem/tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-binPROGRAMS: $(bin_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       test -z "$(bindir)" || $(mkdir_p) "$(DESTDIR)$(bindir)"
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         if test -f $$p \
+            || test -f $$p1 \
+         ; then \
+           f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+          echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+          $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+         else :; fi; \
+       done
+
+uninstall-binPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+         echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+         rm -f "$(DESTDIR)$(bindir)/$$f"; \
+       done
+
+clean-binPROGRAMS:
+       @list='$(bin_PROGRAMS)'; for p in $$list; do \
+         f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         echo " rm -f $$p $$f"; \
+         rm -f $$p $$f ; \
+       done
+apitest$(EXEEXT): $(apitest_OBJECTS) $(apitest_DEPENDENCIES) 
+       @rm -f apitest$(EXEEXT)
+       $(LINK) $(apitest_LDFLAGS) $(apitest_OBJECTS) $(apitest_LDADD) $(LIBS)
+multi_process$(EXEEXT): $(multi_process_OBJECTS) $(multi_process_DEPENDENCIES) 
+       @rm -f multi_process$(EXEEXT)
+       $(LINK) $(multi_process_LDFLAGS) $(multi_process_OBJECTS) $(multi_process_LDADD) $(LIBS)
+translate$(EXEEXT): $(translate_OBJECTS) $(translate_DEPENDENCIES) 
+       @rm -f translate$(EXEEXT)
+       $(LINK) $(translate_LDFLAGS) $(translate_OBJECTS) $(translate_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/apitest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multi_process.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/translate.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@   if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+           $$tags $$unique; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+       list='$(DISTFILES)'; for file in $$list; do \
+         case $$file in \
+           $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+           $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+         esac; \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           dir="/$$dir"; \
+           $(mkdir_p) "$(distdir)$$dir"; \
+         else \
+           dir=''; \
+         fi; \
+         if test -d $$d/$$file; then \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+       for dir in "$(DESTDIR)$(bindir)"; do \
+         test -z "$$dir" || $(mkdir_p) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+       clean-generic clean-libtool ctags distclean distclean-compile \
+       distclean-generic distclean-libtool distclean-tags distdir dvi \
+       dvi-am html html-am info info-am install install-am \
+       install-binPROGRAMS install-data install-data-am install-exec \
+       install-exec-am install-info install-info-am install-man \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+       pdf pdf-am ps ps-am tags uninstall uninstall-am \
+       uninstall-binPROGRAMS uninstall-info-am
+
+
+###############################################################################
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/cmem/tests/apitest.c b/src/cmem/tests/apitest.c
new file mode 100644 (file)
index 0000000..b7d5810
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * apitest.c
+ *
+ * Tests basic API usage and memory allocation. Inserting CMEM with the
+ * following options works on the DVEVM (if mem=120M):
+ *
+ * insmod cmemk.ko phys_start=0x87800000 phys_end=0x87F00000 pools=4xBUFSIZE phys_start_1=0x87F00000 phys_end_1=0x88000000 pools_1=4xBUFSIZE
+ *
+ * where BUFSIZE is the number of bytes you plan on passing as command
+ * line parameter to apitest. If in doubt, use a larger number as BUFSIZE
+ * denotes the maximum buffer you can allocate.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <ti/cmem.h>
+
+#define NUMHEAPPTRS 0x1000
+unsigned int *heap_ptrs[NUMHEAPPTRS];
+
+void testHeap(int size, int block)
+{
+    int rv;
+    int num_buffers;
+    int i;
+    CMEM_AllocParams params;
+
+    printf("allocating heap buffers from CMEM memory block %d...\n", block);
+    num_buffers = 0;
+    params.type = CMEM_HEAP;
+    params.flags = CMEM_NONCACHED;
+    params.alignment = 0;
+    while (num_buffers < NUMHEAPPTRS) {
+       heap_ptrs[num_buffers] = CMEM_alloc2(block, size, &params);
+       if (heap_ptrs[num_buffers] == NULL) {
+           break;
+       }
+       num_buffers++;
+    }
+    printf("...done, %d allocated\n", num_buffers);
+
+    printf("Press ENTER to continue (after 'cat /proc/cmem' if desired).\n");
+    getchar();
+
+    printf("freeing heap blocks...\n");
+    for (i = 0; i < num_buffers; i++) {
+       rv = CMEM_free(heap_ptrs[i], &params);
+       if (rv < 0) {
+           printf("error freeing blocks\n");
+           break;
+       }
+       heap_ptrs[i] = NULL;
+    }
+
+    /* make sure we can still allocate num_buffers after freeing */
+    printf("allocating %d heap blocks...\n", num_buffers);
+    for (i = 0; i < num_buffers; i++) {
+       heap_ptrs[i] = CMEM_alloc2(block, size, &params);
+       if (heap_ptrs[i] == NULL) {
+           printf("error re-allocating %d heap blocks\n", num_buffers);
+           break;
+       }
+    }
+    printf("...done, freeing heap blocks...\n");
+    for (i = 0; i < num_buffers; i++) {
+       rv = CMEM_free(heap_ptrs[i], &params);
+       if (rv < 0) {
+           printf("error freeing blocks\n");
+           break;
+       }
+    }
+
+    printf("...done\n");
+}
+
+void testCache(int size, int block)
+{
+    unsigned int *ptr1_nocache = NULL;
+    unsigned int *ptr1_cache = NULL;
+    unsigned int *ptr1_dma = NULL;
+    unsigned int *ptr2 = NULL;
+    unsigned long physp;
+    unsigned long physp_dma;
+    unsigned long physp_nocache;
+    unsigned long physp_cache;
+    int poolid;
+    int i, j;
+    struct timeval start_tv, end_tv;
+    unsigned long diff;
+    int foo, bar;
+    CMEM_AllocParams params;
+
+    printf("Allocating first noncached buffer.\n");
+
+    /* First allocate a buffer from the pool that best fits */
+    ptr1_nocache = CMEM_alloc(size, NULL);
+
+    if (ptr1_nocache == NULL) {
+        fprintf(stderr, "Failed to allocate buffer of size %d\n", size);
+        goto cleanup;
+    }
+
+    printf("Allocated buffer of size %d at address %#x.\n", size,
+           (unsigned int) ptr1_nocache);
+
+    /* Find out and print the physical address of this buffer */
+    physp_nocache = CMEM_getPhys(ptr1_nocache);
+
+    if (physp_nocache == 0) {
+        fprintf(stderr, "Failed to get physical address of buffer %#x\n",
+                (unsigned int) ptr1_nocache);
+        goto cleanup;
+    }
+
+    printf("Physical address of allocated buffer is %#x.\n",
+           (unsigned int) physp_nocache);
+
+    /* Write some data into this buffer */
+    for (i=0; i < size / sizeof(int) ; i++) {
+        ptr1_nocache[i] = 0xbeefbeef;
+    }
+
+    printf("Allocating first cached buffer.\n");
+
+    /* First allocate a buffer from the pool that best fits */
+    params = CMEM_DEFAULTPARAMS;
+    params.flags = CMEM_CACHED;
+    ptr1_cache = CMEM_alloc2(block, size, &params);
+
+    if (ptr1_cache == NULL) {
+        fprintf(stderr, "Failed to allocate buffer of size %d\n", size);
+        goto cleanup;
+    }
+
+    printf("Allocated buffer of size %d at address %#x.\n", size,
+           (unsigned int) ptr1_cache);
+
+    /* Find out and print the physical address of this buffer */
+    physp_cache = CMEM_getPhys(ptr1_cache);
+
+    if (physp_cache == 0) {
+        fprintf(stderr, "Failed to get physical address of buffer %#x\n",
+                (unsigned int) ptr1_cache);
+        goto cleanup;
+    }
+
+    printf("Physical address of allocated buffer is %#x.\n",
+           (unsigned int) physp_cache);
+
+    /* Write some data into this buffer */
+    for (i = 0; i < size / sizeof(int); i++) {
+        ptr1_cache[i] = 0x0dead1ce;
+    }
+
+    printf("Allocating noncached DMA source buffer.\n");
+
+    /* Allocate a noncached buffer for the DMA source */
+    ptr1_dma = CMEM_alloc(size, NULL);
+
+    if (ptr1_dma == NULL) {
+        fprintf(stderr, "Failed to allocate buffer of size %d\n", size);
+        goto cleanup;
+    }
+
+    printf("Allocated buffer of size %d at address %#x.\n", size,
+           (unsigned int) ptr1_dma);
+
+    /* Find out and print the physical address of this buffer */
+    physp_dma = CMEM_getPhys(ptr1_dma);
+
+    if (physp_dma == 0) {
+        fprintf(stderr, "Failed to get physical address of buffer %#x\n",
+                (unsigned int) ptr1_dma);
+        goto cleanup;
+    }
+
+    printf("Physical address of allocated buffer is %#x.\n",
+           (unsigned int) physp_dma);
+
+    /* Initialize DMA source buffer */
+    for (i = 0; i < size / sizeof(int); i++) {
+        ptr1_cache[i] = 0x0dead1ce;
+    }
+
+    /*
+     * Measure the write performance of each buffer to check that one
+     * is cached and the other isn't.
+     */
+    printf("Measuring R-M-W performance (cached should be quicker).\n");
+    for (j = 0; j < 3; j++) {
+       printf("R-M-W noncached buffer %lx\n", physp_nocache);
+       gettimeofday(&start_tv, NULL);
+       for (i = 0; i < (size / sizeof(int)); i += 1) {
+           ptr1_nocache[i] += 1;
+       }
+       gettimeofday(&end_tv, NULL);
+       diff = end_tv.tv_usec - start_tv.tv_usec;
+       if (end_tv.tv_sec > start_tv.tv_sec) {
+           diff += (end_tv.tv_sec - start_tv.tv_sec) * 1000000;
+       }
+       printf("  diff=%ld\n", diff);
+
+       printf("R-M-W cached buffer %lx\n", physp_cache);
+       gettimeofday(&start_tv, NULL);
+       for (i = 0; i < (size / sizeof(int)); i += 1) {
+           ptr1_cache[i] += 1;
+       }
+       gettimeofday(&end_tv, NULL);
+       diff = end_tv.tv_usec - start_tv.tv_usec;
+       if (end_tv.tv_sec > start_tv.tv_sec) {
+           diff += (end_tv.tv_sec - start_tv.tv_sec) * 1000000;
+       }
+       printf("  diff=%ld\n", diff);
+    }
+
+    printf("Invalidate cached buffer %p\n", ptr1_cache);
+
+    foo = *ptr1_cache;
+    bar = foo;
+    bar++;
+    *ptr1_cache = bar;
+    CMEM_cacheInv(ptr1_cache, size);
+    printf("post-flush *ptr1_cache=0x%x\n", foo);
+    printf("wrote 0x%x to *ptr1_cache\n", bar);
+    printf("post-inv *ptr1_cache=0x%x\n", *ptr1_cache);
+
+    printf("R-M-W cached buffer %lx\n", physp_cache);
+    gettimeofday(&start_tv, NULL);
+    for (i = 0; i < (size / sizeof(int)); i += 1) {
+       ptr1_cache[i] += 1;
+    }
+    gettimeofday(&end_tv, NULL);
+    diff = end_tv.tv_usec - start_tv.tv_usec;
+    if (end_tv.tv_sec > start_tv.tv_sec) {
+       diff += (end_tv.tv_sec - start_tv.tv_sec) * 1000000;
+    }
+    printf("  diff=%ld\n", diff);
+
+    /* 
+     * Now allocate another buffer by first finding out which pool that fits
+     * best, and then explicitly allocating from that pool. This gives more
+     * control at the cost of an extra function call, but essentially does
+     * the same thing as the above CMEM_alloc() call.
+     */
+    printf("Allocating second buffer.\n");
+
+    poolid = CMEM_getPool(size);
+
+    if (poolid == -1) {
+        fprintf(stderr, "Failed to get a pool which fits size %d\n", size);
+        goto cleanup;
+    }
+
+    printf("Got a pool (%d) that fits the size %d\n", poolid, size);
+
+    ptr2 = CMEM_allocPool(poolid, NULL);
+
+    if (ptr2 == NULL) {
+        fprintf(stderr, "Failed to allocate buffer of size %d\n", size);
+        goto cleanup;
+    }
+
+    printf("Allocated buffer of size %d at address %#x.\n", size,
+           (unsigned int) ptr2);
+
+    /* Find out and print the physical address of this buffer */
+    physp = CMEM_getPhys(ptr2);
+
+    if (physp == 0) {
+        fprintf(stderr, "Failed to get physical address of buffer %#x\n",
+                (unsigned int) ptr2);
+        goto cleanup;
+    }
+
+    printf("Physical address of allocated buffer is %#x.\n",
+           (unsigned int) physp);
+
+    /* Write some data into this buffer */
+    for (i=0; i < size / sizeof(int); i++) {
+        ptr2[i] = 0xfeebfeeb;
+    }
+
+    printf("Inspect your memory map in /proc/%d/maps.\n", getpid());
+    printf("Also look at your pool info under /proc/cmem\n");
+    printf("Press ENTER to exit (after 'cat /proc/cmem' if desired).\n");
+    getchar();
+
+cleanup:
+    if (ptr1_nocache != NULL) {
+       if (CMEM_free(ptr1_nocache, NULL) < 0) {
+           fprintf(stderr, "Failed to free buffer at %#x\n",
+                   (unsigned int) ptr1_nocache);
+       }
+       printf("Successfully freed buffer at %#x.\n",
+              (unsigned int) ptr1_nocache);
+    }
+
+    if (ptr1_cache != NULL) {
+       if (CMEM_free(ptr1_cache, &params) < 0) {
+           fprintf(stderr, "Failed to free buffer at %#x\n",
+                   (unsigned int) ptr1_cache);
+       }
+       printf("Successfully freed buffer at %#x.\n",
+              (unsigned int) ptr1_cache);
+    }
+
+    if (ptr1_dma != NULL) {
+       if (CMEM_free(ptr1_dma, NULL) < 0) {
+           fprintf(stderr, "Failed to free buffer at %#x\n",
+                   (unsigned int) ptr1_dma);
+       }
+       printf("Successfully freed buffer at %#x.\n",
+              (unsigned int) ptr1_dma);
+    }
+
+    if (ptr2 != NULL) {
+       if (CMEM_free(ptr2, NULL) < 0) {
+           fprintf(stderr, "Failed to free buffer at %#x\n",
+                   (unsigned int) ptr2);
+       }
+       printf("Successfully freed buffer at %#x.\n",
+              (unsigned int) ptr2);
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    int size;
+    int version;
+    CMEM_BlockAttrs attrs;
+
+    if (argc != 2) {
+        fprintf(stderr, "Usage: %s <Number of bytes to allocate>\n", argv[0]);
+        exit(EXIT_FAILURE);
+    }
+
+    size = atoi(argv[1]);
+
+    /* First initialize the CMEM module */
+    if (CMEM_init() == -1) {
+        fprintf(stderr, "Failed to initialize CMEM\n");
+        exit(EXIT_FAILURE);
+    }
+
+    printf("CMEM initialized.\n");
+
+    version = CMEM_getVersion();
+    if (version == -1) {
+       fprintf(stderr, "Failed to retrieve CMEM version\n");
+    }
+    printf("CMEM version = 0x%x\n", version);
+
+    if (CMEM_getBlockAttrs(0, &attrs) == -1) {
+       fprintf(stderr, "Failed to retrieve CMEM memory block 0 bounds\n");
+    }
+    printf("CMEM memory block 0: phys start = 0x%lx, size = 0x%x\n",
+           attrs.phys_base, attrs.size);
+
+    if (CMEM_getBlockAttrs(1, &attrs) == -1) {
+       fprintf(stderr, "Failed to retrieve CMEM memory block 1 bounds\n");
+    }
+    printf("CMEM memory block 1: phys start = 0x%lx, size = 0x%x\n",
+           attrs.phys_base, attrs.size);
+
+    testHeap(size, 0);
+    testHeap(size, 1);
+
+    testCache(size, 0);
+    testCache(size, 1);
+
+    if (CMEM_exit() < 0) {
+        fprintf(stderr, "Failed to finalize the CMEM module\n");
+    }
+
+    exit(EXIT_SUCCESS);
+}
+
diff --git a/src/cmem/tests/multi_process.c b/src/cmem/tests/multi_process.c
new file mode 100644 (file)
index 0000000..18d8d05
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * multi_process.c
+ *
+ * This app tries to use CMEM from multiple processes. It takes the number
+ * of processes to start as a parameter.
+ *
+ * Make sure you insert CMEM with enough buffers of the right size (specified
+ * by BUFFER_SIZE below). You can also tweak the random time span the processes
+ * sleep by changing DELAYSPAN.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include <ti/cmem.h>
+
+#define BUFFER_SIZE 1000
+
+#define DELAYSPAN 5.0
+
+int main(int argc, char *argv[])
+{
+    unsigned int *ptr = NULL;
+    pid_t newPid = 0;
+    int pid = 0;
+    int numProcesses;
+    int r;
+    int i;
+
+    if (argc != 2) {
+        fprintf(stderr, "Usage: %s <Number of processes to fork>\n", argv[0]);
+        exit(EXIT_FAILURE);
+    }
+
+    numProcesses = atoi(argv[1]);
+
+    for (i=0; i<numProcesses; i++) {
+        newPid = fork(); 
+
+        if (newPid == -1) {
+            fprintf(stderr, "Failed to fork off new process\n");
+            exit(EXIT_FAILURE);
+        }
+        else if (newPid == 0) {
+            pid = i;
+            break;
+        }
+
+        printf("Forked off process %d\n", newPid);
+    }
+
+    if (newPid != 0) {
+        printf("Main process exiting\n");
+        exit(EXIT_SUCCESS);
+    }
+
+    /* First initialize the CMEM module */
+    if (CMEM_init() == -1) {
+        fprintf(stderr, "Process %d: Failed to initialize CMEM\n", pid);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("Process %d: CMEM initialized.\n", pid);
+
+    /* First allocate a buffer from the pool that best fits */
+    ptr = CMEM_alloc(BUFFER_SIZE, NULL);
+
+    if (ptr == NULL) {
+        fprintf(stderr, "Process %d: Failed to allocate buffer of size %d\n",
+                pid, BUFFER_SIZE);
+        exit(EXIT_FAILURE);
+    }
+
+    printf("Process %d: Allocated buffer at %#x\n", pid, (unsigned int) ptr);
+
+    /* Write some data into this buffer */
+    for (i=0; i < BUFFER_SIZE / sizeof(int) ; i++) {
+        ptr[i] = 0xbeefbeef;
+    }
+
+#if 0
+    srand(pid * 1024);
+
+    r = 1 + (int) (DELAYSPAN * (rand() / (RAND_MAX + 1.0)));
+#else
+    r = (pid * 3) + 3;
+#endif
+
+    printf("Process %d: Sleeping for %d seconds\n", pid, r);
+
+    sleep(r);
+
+    if (pid % 2) {
+       printf("Process %d: Freeing buffer at %#x\n", pid, (unsigned int) ptr);
+
+       if (CMEM_free(ptr, NULL) < 0) {
+           fprintf(stderr, "Process %d: Failed to free buffer at %#x\n",
+                   pid, (unsigned int) ptr);
+       }
+    }
+    else {
+       printf("Process %d: intentionally neglecting to call CMEM_free()\n",
+              pid);
+    }
+
+
+    if (pid != 0) {
+       printf("Process %d: Exiting CMEM\n", pid);
+       if (CMEM_exit() < 0) {
+           fprintf(stderr, "Process %d: Failed to finalize the CMEM module\n",
+                   pid);
+       }
+    }
+    else {
+       printf("Process %d: sleeping 5 ...\n", pid);
+       sleep(5);
+       printf("Process %d: exiting, intentionally forgetting to call "
+              "CMEM_exit()\n", pid);
+    }
+
+    exit(EXIT_SUCCESS);
+}
diff --git a/src/cmem/tests/translate.c b/src/cmem/tests/translate.c
new file mode 100644 (file)
index 0000000..f792b93
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * translate.c
+ *
+ * Tests the address translation. Inserting CMEM with the following
+ * options works on the DVEVM (if mem=120M):
+ *
+ * insmod cmemk.ko phys_start=0x87800000 phys_end=0x88000000 pools=1x3145728 
+ *
+ * You should see lots of address translations on screen keeping "even steps"
+ * as the increase (same offset).
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <ti/cmem.h>
+
+#define BUFSIZE 1024 * 1024 * 3
+
+int main(int argc, char *argv[])
+{
+    unsigned char *ptr, *orig;
+    unsigned long physp;
+    int i;
+    int inc;
+    
+
+    /* First initialize the CMEM module */
+    if (CMEM_init() == -1) {
+        fprintf(stderr, "Failed to initialize CMEM\n");
+        exit(EXIT_FAILURE);
+    }
+
+    printf("CMEM initialized.\n");
+
+    /* First allocate a buffer from the pool that best fits */
+    ptr = CMEM_alloc(BUFSIZE, NULL);
+
+    if (ptr == NULL) {
+        fprintf(stderr, "Failed to allocate buffer of size %d\n", BUFSIZE);
+        CMEM_exit();
+        exit(EXIT_FAILURE);
+    }
+
+    printf("Allocated buffer of size %d at virtual address %#x.\n", BUFSIZE,
+           (unsigned int) ptr);
+
+    orig = ptr;
+
+    inc = 4096;
+    printf("\nUsing inc = %d\n", inc);
+    for (i=0; i<BUFSIZE; i+=inc) {
+        physp = CMEM_getPhys(ptr);
+
+        if (physp == 0) {
+            fprintf(stderr, "Failed to get physical address of %#x\n",
+                    (unsigned int) ptr);
+            goto cleanup;
+        }
+
+        printf("virtual=%#x physical=%#x\n", (unsigned int) ptr,
+                                             (unsigned int) physp);
+
+        ptr += inc;
+    } 
+
+    ptr = orig;
+    inc = 4096 / 2;
+    printf("\nUsing inc = %d\n", inc);
+    for (i=0; i<BUFSIZE; i+=inc) {
+        physp = CMEM_getPhys(ptr);
+
+        if (physp == 0) {
+            fprintf(stderr, "Failed to get physical address of %#x\n",
+                    (unsigned int) ptr);
+            goto cleanup;
+        }
+
+        printf("virtual=%#x physical=%#x\n", (unsigned int) ptr,
+                                             (unsigned int) physp);
+
+        ptr += inc;
+    } 
+
+    ptr = orig;
+    inc = 4096 / 3;
+    printf("\nUsing inc = %d\n", inc);
+    for (i=0; i<BUFSIZE; i+=inc) {
+        physp = CMEM_getPhys(ptr);
+
+        if (physp == 0) {
+            fprintf(stderr, "Failed to get physical address of %#x\n",
+                    (unsigned int) ptr);
+            goto cleanup;
+        }
+
+        printf("virtual=%#x physical=%#x\n", (unsigned int) ptr,
+                                             (unsigned int) physp);
+
+        ptr += inc;
+    } 
+
+    ptr = orig;
+    inc = 4096 / 4;
+    printf("\nUsing inc = %d\n", inc);
+    for (i=0; i<BUFSIZE; i+=inc) {
+        physp = CMEM_getPhys(ptr);
+
+        if (physp == 0) {
+            fprintf(stderr, "Failed to get physical address of %#x\n",
+                    (unsigned int) ptr);
+            goto cleanup;
+        }
+
+        printf("virtual=%#x physical=%#x\n", (unsigned int) ptr,
+                                             (unsigned int) physp);
+
+        ptr += inc;
+    }
+cleanup:
+    ptr = orig;
+    if (CMEM_free(ptr, NULL) < 0) {
+        fprintf(stderr, "Failed to free buffer at %#x\n",
+                (unsigned int) ptr);
+    }
+
+    printf("Successfully freed buffer at %#x.\n", (unsigned int) ptr);
+
+    if (CMEM_exit() < 0) {
+        fprintf(stderr, "Failed to finalize the CMEM module\n");
+    }
+
+    exit(EXIT_SUCCESS);
+}