author | Robert Tivy <rtivy@ti.com> | |
Wed, 15 May 2013 18:06:58 +0000 (11:06 -0700) | ||
committer | Robert 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.
use in-kernel CMA. The user API set remains the same.
24 files changed:
diff --git a/.gitignore b/.gitignore
--- /dev/null
+++ b/.gitignore
@@ -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
--- /dev/null
+++ b/Makefile.am
@@ -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
--- /dev/null
+++ b/Makefile.in
@@ -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
--- /dev/null
+++ b/configure.ac
@@ -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
--- /dev/null
+++ b/include/ti/cmem.h
@@ -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
--- /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
--- /dev/null
+++ b/products.mak
@@ -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
--- /dev/null
+++ b/src/cmem/Makefile.am
@@ -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
--- /dev/null
+++ b/src/cmem/Makefile.in
@@ -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
--- /dev/null
+++ b/src/cmem/README
@@ -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
--- /dev/null
+++ b/src/cmem/api/Makefile.am
@@ -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
--- /dev/null
+++ b/src/cmem/api/Makefile.in
@@ -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
--- /dev/null
+++ b/src/cmem/api/cmem.c
@@ -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
--- /dev/null
+++ b/src/cmem/module/Makefile
@@ -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
--- /dev/null
+++ b/src/cmem/module/cmemk.c
@@ -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(¤t->mm->mmap_sem);
+
+ res = get_user_pages(current, current->mm,
+ virtp, nr_pages,
+ 1, 0,
+ &pages, NULL);
+ up_read(¤t->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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /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
--- /dev/null
+++ b/src/cmem/tests/apitest.c
@@ -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, ¶ms);
+ 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], ¶ms);
+ 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, ¶ms);
+ 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], ¶ms);
+ 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, ¶ms);
+
+ 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, ¶ms) < 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
--- /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
--- /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);
+}