[patch V2 1/8] staging: visorutil driver to provide common functionality to other s-Par drivers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The visorutil module is a support library required by all other s-Par
driver modules. Among its features it abstracts reading, writing, and
manipulating a block of memory.


Signed-off-by: Ken Cox <jkc@xxxxxxxxxx>
Cc: Ben Romer <sparmaintainer@xxxxxxxxxx>

Index: upstream-staging/drivers/staging/Kconfig
===================================================================
--- upstream-staging.orig/drivers/staging/Kconfig
+++ upstream-staging/drivers/staging/Kconfig
@@ -146,4 +146,6 @@ source "drivers/staging/dgnc/Kconfig"
 
 source "drivers/staging/dgap/Kconfig"
 
+source "drivers/staging/unisys/Kconfig"
+
 endif # STAGING
Index: upstream-staging/drivers/staging/Makefile
===================================================================
--- upstream-staging.orig/drivers/staging/Makefile
+++ upstream-staging/drivers/staging/Makefile
@@ -65,3 +65,4 @@ obj-$(CONFIG_XILLYBUS)		+= xillybus/
 obj-$(CONFIG_DGNC)			+= dgnc/
 obj-$(CONFIG_DGAP)			+= dgap/
 obj-$(CONFIG_MTD_SPINAND_MT29F)	+= mt29f_spinand/
+obj-$(CONFIG_UNISYSSPAR)	+= unisys/
Index: upstream-staging/drivers/staging/unisys/include/periodic_work.h
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/include/periodic_work.h
@@ -0,0 +1,40 @@
+/* periodic_work.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __PERIODIC_WORK_H__
+#define __PERIODIC_WORK_H__
+
+#include "timskmod.h"
+
+
+
+/* PERIODIC_WORK an opaque structure to users.
+ * Fields are declared only in the implementation .c files.
+ */
+typedef struct PERIODIC_WORK_Tag PERIODIC_WORK;
+
+PERIODIC_WORK *periodic_work_create(ulong jiffy_interval,
+				     struct workqueue_struct *workqueue,
+				     void (*workfunc)(void *),
+				     void *workfuncarg,
+				     const char *devnam);
+void            periodic_work_destroy(PERIODIC_WORK *periodic_work);
+BOOL            periodic_work_nextperiod(PERIODIC_WORK *periodic_work);
+BOOL            periodic_work_start(PERIODIC_WORK *periodic_work);
+BOOL            periodic_work_stop(PERIODIC_WORK *periodic_work);
+
+#endif
Index: upstream-staging/drivers/staging/unisys/include/procobjecttree.h
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/include/procobjecttree.h
@@ -0,0 +1,48 @@
+/* procobjecttree.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/** @file *********************************************************************
+ *
+ *  This describes the interfaces necessary for creating a tree of types,
+ *  objects, and properties in /proc.
+ *
+ ******************************************************************************
+ */
+
+#ifndef __PROCOBJECTTREE_H__
+#define __PROCOBJECTTREE_H__
+
+#include "uniklog.h"
+#include "timskmod.h"
+
+/* These are opaque structures to users.
+ * Fields are declared only in the implementation .c files.
+ */
+typedef struct MYPROCOBJECT_Tag MYPROCOBJECT;
+typedef struct MYPROCTYPE_Tag   MYPROCTYPE;
+
+MYPROCOBJECT *proc_CreateObject(MYPROCTYPE *type, const char *name,
+				void *context);
+void          proc_DestroyObject(MYPROCOBJECT *obj);
+MYPROCTYPE   *proc_CreateType(struct proc_dir_entry *procRootDir,
+			      const char **name,
+			      const char **propertyNames,
+			      void (*show_property)(struct seq_file *,
+						    void *, int));
+void          proc_DestroyType(MYPROCTYPE *type);
+
+#endif
Index: upstream-staging/drivers/staging/unisys/include/timskmod.h
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/include/timskmod.h
@@ -0,0 +1,558 @@
+/* timskmod.h
+ *
+ * Copyright � 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __TIMSKMOD_H__
+#define __TIMSKMOD_H__
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
+#include <linux/cdev.h>
+#include <linux/types.h>
+#include <asm/irq.h>
+#include <linux/io.h>
+#include <asm/dma.h>
+#include <linux/uaccess.h>
+#include <linux/list.h>
+#include <linux/poll.h>
+/* #define EXPORT_SYMTAB */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/fcntl.h>
+#include <linux/aio.h>
+#include <linux/workqueue.h>
+#include <linux/kthread.h>
+#include <linux/seq_file.h>
+#include <linux/mm.h>
+
+/* #define DEBUG */
+#ifndef BOOL
+#define BOOL    int
+#endif
+#define FALSE   0
+#define TRUE    1
+#if !defined SUCCESS
+#define SUCCESS 0
+#endif
+#define FAILURE (-1)
+#define DRIVERNAMEMAX 50
+#define MIN(a, b)     (((a) < (b)) ? (a) : (b))
+#define MAX(a, b)     (((a) > (b)) ? (a) : (b))
+#define STRUCTSEQUAL(x, y) (memcmp(&x, &y, sizeof(x)) == 0)
+#ifndef HOSTADDRESS
+#define HOSTADDRESS unsigned long long
+#endif
+
+typedef long VMMIO;  /**< Virtual MMIO address (returned from ioremap), which
+    *   is a virtual address pointer to a memory-mapped region.
+    *   These are declared as "long" instead of u32* to force you to
+    *   use readb()/writeb()/memcpy_fromio()/etc to access them.
+    *   (On x86 we could probably get away with treating them as
+    *   pointers.)
+    */
+typedef long VMMIO8; /**< #VMMIO pointing to  8-bit data */
+typedef long VMMIO16;/**< #VMMIO pointing to 16-bit data */
+typedef long VMMIO32;/**< #VMMIO pointing to 32-bit data */
+
+#define LOCKSEM(sem)                   down_interruptible(sem)
+#define LOCKSEM_UNINTERRUPTIBLE(sem)   down(sem)
+#define UNLOCKSEM(sem)                 up(sem)
+
+/** lock read/write semaphore for reading.
+    Note that all read/write semaphores are of the "uninterruptible" variety.
+    @param sem (rw_semaphore *) points to semaphore to lock
+ */
+#define LOCKREADSEM(sem)               down_read(sem)
+
+/** unlock read/write semaphore for reading.
+    Note that all read/write semaphores are of the "uninterruptible" variety.
+    @param sem (rw_semaphore *) points to semaphore to unlock
+ */
+#define UNLOCKREADSEM(sem)             up_read(sem)
+
+/** lock read/write semaphore for writing.
+    Note that all read/write semaphores are of the "uninterruptible" variety.
+    @param sem (rw_semaphore *) points to semaphore to lock
+ */
+#define LOCKWRITESEM(sem)              down_write(sem)
+
+/** unlock read/write semaphore for writing.
+    Note that all read/write semaphores are of the "uninterruptible" variety.
+    @param sem (rw_semaphore *) points to semaphore to unlock
+ */
+#define UNLOCKWRITESEM(sem)            up_write(sem)
+
+#ifdef ENABLE_RETURN_TRACE
+#define RETTRACE(x)                                            \
+	do {						       \
+		if (1) {				       \
+			INFODRV("RET 0x%lx in %s",	       \
+				(ulong)(x), __func__);     \
+		}					   \
+	} while (0)
+#else
+#define RETTRACE(x)
+#endif
+
+/** return from a void function, using a common exit point "Away" */
+#define RETVOID    do { RETTRACE(0); goto Away; } while (0)
+/** return from an int function, using a common exit point "Away"
+ *  @param x the value to return
+ */
+#define RETINT(x)  do { rc = (x); RETTRACE(x); goto Away; } while (0)
+/** return from a void* function, using a common exit point "Away"
+ *  @param x the value to return
+ */
+#define RETPTR(x)  do { rc = (x); RETTRACE(x); goto Away; } while (0)
+/** return from a BOOL function, using a common exit point "Away"
+ *  @param x the value to return
+ */
+#define RETBOOL(x) do { rc = (x); RETTRACE(x); goto Away; } while (0)
+/** Given a typedef/struct/union and a member field name,
+ *  return the number of bytes occupied by that field.
+ *  @param TYPE     the typedef name, or "struct xx" or "union xx"
+ *  @param MEMBER   the name of the member field whose size is to be determined
+ *  @return         the size of the field in bytes
+ */
+#define FAIL(msg, status) do {          \
+		ERRDRV("'%s'"					      \
+		       ": error (status=%d)\n",			      \
+		       msg, status);				      \
+		RETINT(status);					      \
+	} while (0)
+#define FAIL_WPOSTCODE_1(msg, status, EVENT_PC) do {          \
+		ERRDRV("'%s'"					      \
+		       ": error (status=%d)\n",			      \
+		       msg, status);					\
+		POSTCODE_LINUX_2(EVENT_PC, DIAG_SEVERITY_ERR);		\
+		RETINT(status);						\
+	} while (0)
+#define FAIL_WPOSTCODE_2(msg, status, EVENT_PC, pcval32bit) do {          \
+		ERRDRV("'%s'"						\
+		       ": error (status=%d)\n",				\
+		       msg, status);					\
+		POSTCODE_LINUX_3(EVENT_PC, pcval32bit, DIAG_SEVERITY_ERR); \
+		RETINT(status);						\
+	} while (0)
+#define FAIL_WPOSTCODE_3(msg, status, EVENT_PC, pcval16bit1, pcval16bit2) \
+	do {								\
+		ERRDRV("'%s'"						\
+		       ": error (status=%d)\n",				\
+		       msg, status);					\
+		POSTCODE_LINUX_4(EVENT_PC, pcval16bit1, pcval16bit2,	\
+				 DIAG_SEVERITY_ERR);			\
+		RETINT(status);						\
+	} while (0)
+/** Try to evaulate the provided expression, and do a RETINT(x) iff
+ *  the expression evaluates to < 0.
+ *  @param x the expression to try
+ */
+#define TRY(x) do { int status = (x);                          \
+		if (status < 0)				       \
+			FAIL(__stringify(x), status);	       \
+	} while (0)
+
+#define TRY_WPOSTCODE_1(x, EVENT_PC) do { \
+		int status = (x);	  \
+		if (status < 0)						\
+			FAIL_WPOSTCODE_1(__stringify(x), status, EVENT_PC); \
+	} while (0)
+
+#define TRY_WPOSTCODE_2(x, EVENT_PC, pcval32bit) do { \
+		int status = (x);		      \
+		if (status < 0)						\
+			FAIL_WPOSTCODE_2(__stringify(x), status, EVENT_PC, \
+					 pcval32bit);			\
+	} while (0)
+
+#define TRY_WPOSTCODE_3(x, EVENT_PC, pcval16bit1, pcval16bit2) do { \
+		int status = (x);				    \
+		if (status < 0)						\
+			FAIL_WPOSTCODE_3(__stringify(x), status, EVENT_PC, \
+					 pcval16bit1, pcval16bit2);	\
+	} while (0)
+
+#define ASSERT(cond)                                           \
+	do { if (!(cond))                                      \
+			HUHDRV("ASSERT failed - %s",	       \
+			       __stringify(cond));	       \
+	} while (0)
+
+#define sizeofmember(TYPE, MEMBER) (sizeof(((TYPE *)0)->MEMBER))
+/** "Covered quotient" function */
+#define COVQ(v, d)  (((v) + (d) - 1) / (d))
+#define SWAPPOINTERS(p1, p2)				\
+	do {						\
+		void *SWAPPOINTERS_TEMP = (void *)p1;	\
+		(void *)(p1) = (void *)(p2);            \
+		(void *)(p2) = SWAPPOINTERS_TEMP;	\
+	} while (0)
+
+/**
+ *  @addtogroup driverlogging
+ *  @{
+ */
+
+#define PRINTKDRV(fmt, args...) LOGINF(fmt, ## args)
+#define TBDDRV(fmt, args...)    LOGERR(fmt, ## args)
+#define HUHDRV(fmt, args...)    LOGERR(fmt, ## args)
+#define ERRDRV(fmt, args...)    LOGERR(fmt, ## args)
+#define WARNDRV(fmt, args...)   LOGWRN(fmt, ## args)
+#define SECUREDRV(fmt, args...) LOGWRN(fmt, ## args)
+#define INFODRV(fmt, args...)   LOGINF(fmt, ## args)
+#define DEBUGDRV(fmt, args...)  DBGINF(fmt, ## args)
+
+#define PRINTKDEV(devname, fmt, args...)  LOGINFDEV(devname, fmt, ## args)
+#define TBDDEV(devname, fmt, args...)     LOGERRDEV(devname, fmt, ## args)
+#define HUHDEV(devname, fmt, args...)     LOGERRDEV(devname, fmt, ## args)
+#define ERRDEV(devname, fmt, args...)     LOGERRDEV(devname, fmt, ## args)
+#define ERRDEVX(devno, fmt, args...)	  LOGERRDEVX(devno, fmt, ## args)
+#define WARNDEV(devname, fmt, args...)    LOGWRNDEV(devname, fmt, ## args)
+#define SECUREDEV(devname, fmt, args...)  LOGWRNDEV(devname, fmt, ## args)
+#define INFODEV(devname, fmt, args...)    LOGINFDEV(devname, fmt, ## args)
+#define INFODEVX(devno, fmt, args...)     LOGINFDEVX(devno, fmt, ## args)
+#define DEBUGDEV(devname, fmt, args...)   DBGINFDEV(devname, fmt, ## args)
+
+
+/* @} */
+
+/** Used to add a single line to the /proc filesystem buffer */
+#define ADDPROCLINE(buf, bufsize, line, linelen, totallen) \
+	{						   \
+		if ((totallen) + (linelen) >= bufsize)     \
+			RETINT(totallen);		   \
+		if (linelen > 0) {			   \
+			strcat(buf, line);		   \
+			totallen += linelen;		   \
+		}                                          \
+	}
+
+
+
+/** Verifies the consistency of your PRIVATEDEVICEDATA structure using
+ *  conventional "signature" fields:
+ *  <p>
+ *  - sig1 should contain the size of the structure
+ *  - sig2 should contain a pointer to the beginning of the structure
+ */
+#define DDLOOKSVALID(dd)                                 \
+		((dd != NULL)                             &&	\
+		 ((dd)->sig1 == sizeof(PRIVATEDEVICEDATA)) &&	\
+		 ((dd)->sig2 == dd))
+
+/** Verifies the consistency of your PRIVATEFILEDATA structure using
+ *  conventional "signature" fields:
+ *  <p>
+ *  - sig1 should contain the size of the structure
+ *  - sig2 should contain a pointer to the beginning of the structure
+ */
+#define FDLOOKSVALID(fd)                               \
+	((fd != NULL)                           &&     \
+	 ((fd)->sig1 == sizeof(PRIVATEFILEDATA)) &&    \
+	 ((fd)->sig2 == fd))
+
+/** Verifies the consistency of a PRIVATEDEVICEDATA structure and reacts
+ *  if necessary
+ */
+#define CHKDDX(dd, x) (					   \
+			if (!DDLOOKSVALID((dd))) {	   \
+				PRINTKDRV("bad device structure");	\
+				RETINT(x);				\
+			})
+
+/** Verifies the consistency of a PRIVATEDEVICEDATA structure and reacts
+ *  if necessary
+ */
+#define CHKDD(dd) (							\
+			if (!DDLOOKSVALID(dd)) {			\
+				PRINTKDRV("bad device structure");	\
+				RETVOID;				\
+			})
+
+/** Verifies the consistency of a PRIVATEFILEDATA structure and reacts
+ *  if necessary
+ */
+#define CHKFDX(fd, x) (					   \
+		if (!FDLOOKSVALID(fd)) {		   \
+			PRINTKDRV("bad file structure");   \
+			RETINT(x);			   \
+		})
+
+/** Verifies the consistency of a PRIVATEFILEDATA structure and reacts
+ *  if necessary
+ */
+#define CHKFD(fd) (					  \
+		if (!FDLOOKSVALID(fd)) {		  \
+			PRINTKDRV("bad file structure");  \
+			RETVOID;			  \
+		})
+
+/** Converts a device index #devix into #devData, after checking for validity.
+ *  Can only be called from functions returning void.
+ *  @param devix your device index within the #DevData array.
+ *  @param devData the #PRIVATEDEVICEDATA pointer that will be set on return.
+ *  @param where string identifying the calling function, to be printed in
+ *         debug message
+ *  @param dbg 1 iff debug messages are enabled
+ */
+#define DEVFROMID(devix, devData, where, dbg)				\
+	{								\
+		if (devix >= MAXDEVICES) {				\
+			PRINTKDRV("bad devix passed to %s()", where);	\
+			RETVOID;					\
+		}							\
+		if (dbg)						\
+			DEBUGDEV(devix, "%s", where);			\
+		if (devix >= MAXDEVICES) {				\
+			DEBUGDEV(devix, "%s - bad devix %d",		\
+				 where, devix);				\
+			RETVOID;					\
+		}							\
+		devData = DevData[devix];				\
+		CHKDD(devData);						\
+	}
+
+/** Converts a device index #devix into #devData, after checking for validity.
+ *  Can only be called from functions returning int.
+ *  @param devix your device index within the #DevData array.
+ *  @param devData the #PRIVATEDEVICEDATA pointer that will be set on return.
+ *  @param errcode error code that your function will return on error.
+ *  @param where string identifying the calling function, to be printed in
+ *         debug message
+ *  @param dbg 1 iff debug messages are enabled
+ */
+#define DEVFROMIDX(devix, devData, errcode, where, dbg)			\
+	{								\
+		if (devix >= MAXDEVICES) {				\
+			PRINTKDRV("bad devix passed to %s()", where);	\
+			RETINT(errcode);				\
+		}							\
+		if (dbg)						\
+			DEBUGDEV(devix, "%s", where);			\
+		if (devix >= MAXDEVICES) {				\
+			DEBUGDEV(devix, "%s - bad devix %d",		\
+				 where, devix);				\
+			RETINT(-ENODEV);				\
+		}							\
+		devData = DevData[devix];				\
+		CHKDDX(devData, -EIO);					\
+	}
+
+/** Converts an inode pointer #inode into a #devix and #devData, after
+ *  checking for validity.
+ *  Can only be called from functions returning int.
+ *  @param devix your device index within the #DevData array.
+ *  @param devData the #PRIVATEDEVICEDATA pointer that will be set on return.
+ *  @param inode input inode pointer
+ *  @param errcode error code that your function will return on error.
+ *  @param where string identifying the calling function, to be printed in
+ *         debug message
+ *  @param dbg 1 iff debug messages are enabled
+ */
+#define DEVFROMINODE(devix, devData, inode, errcode, where, dbg)	\
+	{								\
+		if (inode == NULL) {					\
+			PRINTKDRV("bad inode passed to %s()", where);	\
+			RETINT(errcode);				\
+		}							\
+		devix = MINOR(inode->i_rdev);				\
+		if (dbg)						\
+			DEBUGDEV(devix, "%s", where);			\
+		if (devix >= MAXDEVICES) {				\
+			DEBUGDEV(devix, "%s - bad devix %d",		\
+				 where, devix);				\
+			RETINT(-ENODEV);				\
+		}							\
+		devData = DevData[devix];				\
+		CHKDDX(devData, -EIO);					\
+	}
+
+/** Converts a file pointer #file into a #devix and #devData, after checking
+ *  for validity.
+ *  Can only be called from functions returning int.
+ *  @param devix your device index within the #DevData array.
+ *  @param devData the #PRIVATEDEVICEDATA pointer that will be set on return.
+ *  @param file input file pointer
+ *  @param errcode error code that your function will return on error.
+ *  @param where string identifying the calling function, to be printed in
+ *         debug message
+ *  @param dbg 1 iff debug messages are enabled
+ */
+#define DEVFROMFILE(devix, devData, fileData, file, errcode, where, dbg) \
+		{							\
+		if (file == NULL) {					\
+			PRINTKDRV("bad file passed to %s()", where);	\
+			RETINT(errcode);				\
+		}							\
+		CHKFDX((PRIVATEFILEDATA *)(file->private_data), -EIO);	\
+		fileData = file->private_data;				\
+		devix = fileData->devix;				\
+		if (dbg)						\
+			DEBUGDEV(devix, "%s %p", where, file);		\
+		if (devix >= MAXDEVICES) {				\
+			DEBUGDEV(devix, "%s - bad devix %d",		\
+				 where, devix);				\
+			RETINT(-ENODEV);				\
+		}							\
+		devData = DevData[devix];				\
+		CHKDDX(devData, -EIO);					\
+	}
+
+/** Locks dd->lockDev if you havn't already locked it */
+#define LOCKDEV(dd)                                                    \
+	{                                                              \
+		if (!lockedDev) {				       \
+			spin_lock(&dd->lockDev);		       \
+			lockedDev = TRUE;			       \
+		}						       \
+	}
+
+/** Unlocks dd->lockDev if you previously locked it */
+#define UNLOCKDEV(dd)                                                  \
+	{                                                              \
+		if (lockedDev) {				       \
+			spin_unlock(&dd->lockDev);		       \
+			lockedDev = FALSE;			       \
+		}						       \
+	}
+
+/** Locks dd->lockDevISR if you havn't already locked it */
+#define LOCKDEVISR(dd)                                                 \
+	{                                                              \
+		if (!lockedDevISR) {				       \
+			spin_lock_irqsave(&dd->lockDevISR, flags);     \
+			lockedDevISR = TRUE;			       \
+		}						       \
+	}
+
+/** Unlocks dd->lockDevISR if you previously locked it */
+#define UNLOCKDEVISR(dd)						\
+	{								\
+		if (lockedDevISR) {					\
+			spin_unlock_irqrestore(&dd->lockDevISR, flags); \
+			lockedDevISR = FALSE;				\
+		}							\
+	}
+
+/** Locks LockGlobalISR if you havn't already locked it */
+#define LOCKGLOBALISR                                                  \
+	{                                                              \
+		if (!lockedGlobalISR) {				       \
+			spin_lock_irqsave(&LockGlobalISR, flags);      \
+			lockedGlobalISR = TRUE;			       \
+		}						       \
+	}
+
+/** Unlocks LockGlobalISR if you previously locked it */
+#define UNLOCKGLOBALISR                                                \
+	{                                                              \
+		if (lockedGlobalISR) {				       \
+			spin_unlock_irqrestore(&LockGlobalISR, flags); \
+			lockedGlobalISR = FALSE;		       \
+		}						       \
+	}
+
+/** Locks LockGlobal if you havn't already locked it */
+#define LOCKGLOBAL                                                     \
+	{                                                              \
+		if (!lockedGlobal) {				       \
+			spin_lock(&LockGlobal);			       \
+			lockedGlobal = TRUE;			       \
+		}						       \
+	}
+
+/** Unlocks LockGlobal if you previously locked it */
+#define UNLOCKGLOBAL                                                   \
+	{                                                              \
+		if (lockedGlobal) {				       \
+			spin_unlock(&LockGlobal);		       \
+			lockedGlobal = FALSE;			       \
+		}						       \
+	}
+
+/** Use this at the beginning of functions where you intend to
+ *  use #LOCKDEV/#UNLOCKDEV, #LOCKDEVISR/#UNLOCKDEVISR,
+ *  #LOCKGLOBAL/#UNLOCKGLOBAL, #LOCKGLOBALISR/#UNLOCKGLOBALISR.
+ *
+ *  Note that __attribute__((unused)) is how you tell GNU C to suppress
+ *  any warning messages about the variable being unused.
+ */
+#define LOCKPREAMBLE							\
+	ulong flags __attribute__((unused)) = 0;			\
+	BOOL lockedDev __attribute__((unused)) = FALSE;			\
+	BOOL lockedDevISR __attribute__((unused)) = FALSE;		\
+	BOOL lockedGlobal __attribute__((unused)) = FALSE;		\
+	BOOL lockedGlobalISR __attribute__((unused)) = FALSE
+
+
+
+/** Sleep for an indicated number of seconds (for use in kernel mode).
+ *  @param x the number of seconds to sleep.
+ */
+#define SLEEP(x)					     \
+	do { current->state = TASK_INTERRUPTIBLE;	     \
+		schedule_timeout((x)*HZ);		     \
+	} while (0)
+
+/** Sleep for an indicated number of jiffies (for use in kernel mode).
+ *  @param x the number of jiffies to sleep.
+ */
+#define SLEEPJIFFIES(x)						    \
+	do { current->state = TASK_INTERRUPTIBLE;		    \
+		schedule_timeout(x);				    \
+	} while (0)
+
+#ifndef max
+#define max(a, b) (((a) > (b)) ? (a):(b))
+#endif
+
+static inline struct cdev *cdev_alloc_init(struct module *owner,
+					   const struct file_operations *fops)
+{
+	struct cdev *cdev = NULL;
+	cdev = cdev_alloc();
+	if (!cdev)
+		return NULL;
+	cdev->ops = fops;
+	cdev->owner = owner;
+
+	/* Note that the memory allocated for cdev will be deallocated
+	 * when the usage count drops to 0, because it is controlled
+	 * by a kobject of type ktype_cdev_dynamic.  (This
+	 * deallocation could very well happen outside of our kernel
+	 * module, like via the cdev_put in __fput() for example.)
+	 */
+	return cdev;
+}
+
+#include "timskmodutils.h"
+
+#endif
Index: upstream-staging/drivers/staging/unisys/include/timskmodutils.h
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/include/timskmodutils.h
@@ -0,0 +1,194 @@
+/* timskmodutils.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __TIMSKMODUTILS_H__
+#define __TIMSKMODUTILS_H__
+
+#include "timskmod.h"
+
+void *kmalloc_kernel(size_t siz);
+void *kmalloc_kernel_dma(size_t siz);
+void  kfree_kernel(const void *p, size_t siz);
+void *vmalloc_kernel(size_t siz);
+void  vfree_kernel(const void *p, size_t siz);
+void *pgalloc_kernel(size_t siz);
+void  pgfree_kernel(const void *p, size_t siz);
+void  myprintk(const char *myDrvName, const char *devname,
+		const char *template, ...);
+void  myprintkx(const char *myDrvName, int devno, const char *template, ...);
+
+/** Print the hexadecimal contents of a data buffer to a supplied print buffer.
+ *  @param dest               the print buffer where text characters will be
+ *                            written
+ *  @param destSize           the maximum number of bytes that can be written
+ *                            to #dest
+ *  @param src                the buffer that contains the data that is to be
+ *                            hex-dumped
+ *  @param srcLen             the number of bytes at #src to be hex-dumped
+ *  @param bytesToDumpPerLine output will be formatted such that at most this
+ *                            many of the input data bytes will be represented
+ *                            on each line of output
+ *  @return                   the number of text characters written to #dest
+ *                            (not including the trailing '\0' byte)
+ *  @ingroup internal
+ */
+int   hexDumpToBuffer(char *dest,
+		      int destSize,
+		      char *prefix,
+		      char *src,
+		      int srcLen,
+		      int bytesToDumpPerLine);
+
+/** Print the hexadecimal contents of a data buffer to a supplied print buffer.
+ *  Assume the data buffer contains 32-bit words in little-endian format,
+ *  and dump the words with MSB first and LSB last.
+ *  @param dest               the print buffer where text characters will be
+ *                            written
+ *  @param destSize           the maximum number of bytes that can be written
+ *                            to #dest
+ *  @param src                the buffer that contains the data that is to be
+ *                            hex-dumped
+ *  @param srcWords           the number of 32-bit words at #src to be
+ &                            hex-dumped
+ *  @param wordsToDumpPerLine output will be formatted such that at most this
+ *                            many of the input data words will be represented
+ *                            on each line of output
+ *  @return                   the number of text characters written to #dest
+ *                            (not including the trailing '\0' byte)
+ *  @ingroup internal
+ */
+int   hexDumpWordsToBuffer(char *dest,
+			   int destSize,
+			   char *prefix,
+			   uint32_t *src,
+			   int srcWords,
+			   int wordsToDumpPerLine);
+
+
+/** Use printk to print the hexadecimal contents of a data buffer.
+ *  See #INFOHEXDRV and #INFOHEXDEV for info.
+ *  @ingroup internal
+ */
+int myPrintkHexDump(char *myDrvName,
+		    char *devname,
+		    char *prefix,
+		    char *src,
+		    int srcLen,
+		    int bytesToDumpPerLine);
+
+/** Given as input a number of seconds in #seconds, creates text describing
+ *  the time within #s.  Also breaks down the number of seconds into component
+ *  days, hours, minutes, and seconds, and stores to *#days, *#hours,
+ *  *#minutes, and *#secondsx.
+ *  @param seconds input number of seconds
+ *  @param days    points to a long value where the days component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param hours   points to a long value where the hours component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param minutes points to a long value where the minutes component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param secondsx points to a long value where the seconds component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param s       points to a character buffer where a text representation of
+ *                 the #seconds value will be stored.  This buffer MUST be
+ *                 large enough to hold the resulting string; to be safe it
+ *                 should be at least 100 bytes long.
+ */
+void  expandSeconds(time_t seconds,
+		    long *days, long *hours,
+		    long *minutes,
+		    long *secondsx,
+		    char *s);
+
+/*--------------------------------*
+ *---  GENERAL MESSAGEQ STUFF  ---*
+ *--------------------------------*/
+
+struct MessageQEntry;
+
+/** the data structure used to hold an arbitrary data item that you want
+ *  to place on a #MESSAGEQ.  Declare and initialize as follows:
+ *  @code
+ *      MESSAGEQENTRY myEntry;
+ *      initMessageQEntry (&myEntry, pointerToMyDataItem);
+ *  @endcode
+ *  This structure should be considered opaque; the client using it should
+ *  never access the fields directly.
+ *  Refer to these functions for more info:
+ *  - initMessageQ()
+ *  - initMessageQEntry()
+ *  - enqueueMessage()
+ *  - dequeueMessage()
+ *  - dequeueMessageNoBlock()
+ *  - getQueueCount()
+ *
+ *  @ingroup messageq
+ */
+typedef struct MessageQEntry {
+	void *data;
+	struct MessageQEntry *qNext;
+	struct MessageQEntry *qPrev;
+} MESSAGEQENTRY;
+
+/** the data structure used to hold a FIFO queue of #MESSAGEQENTRY<b></b>s.
+ *  Declare and initialize as follows:
+ *  @code
+ *      MESSAGEQ myQueue;
+ *      initMessageQ (&myQueue);
+ *  @endcode
+ *  This structure should be considered opaque; the client using it should
+ *  never access the fields directly.
+ *  Refer to these functions for more info:
+ *  - initMessageQ()
+ *  - initMessageQEntry()
+ *  - enqueueMessage()
+ *  - dequeueMessage()
+ *  - dequeueMessageNoBlock()
+ *  - getQueueCount()
+ *
+ *  @ingroup messageq
+ */
+typedef struct MessageQ {
+	MESSAGEQENTRY *qHead;
+	MESSAGEQENTRY *qTail;
+	struct semaphore nQEntries;
+	spinlock_t       queueLock;
+} MESSAGEQ;
+
+char *cyclesToSeconds(u64 cycles, u64 cyclesPerSecond,
+		      char *buf, size_t bufsize);
+char *cyclesToIterationSeconds(u64 cycles, u64 cyclesPerSecond,
+			       u64 iterations, char *buf, size_t bufsize);
+char *cyclesToSomethingsPerSecond(u64 cycles, u64 cyclesPerSecond,
+				  u64 somethings, char *buf, size_t bufsize);
+void initMessageQ(MESSAGEQ *q);
+void initMessageQEntry(MESSAGEQENTRY *p, void *data);
+MESSAGEQENTRY *dequeueMessage(MESSAGEQ *q);
+MESSAGEQENTRY *dequeueMessageNoBlock(MESSAGEQ *q);
+void enqueueMessage(MESSAGEQ *q, MESSAGEQENTRY *pEntry);
+size_t getQueueCount(MESSAGEQ *q);
+int waitQueueLen(wait_queue_head_t *q);
+void debugWaitQ(wait_queue_head_t *q);
+struct seq_file *seq_file_new_buffer(void *buf, size_t buf_size);
+void seq_file_done_buffer(struct seq_file *m);
+void seq_hexdump(struct seq_file *seq, u8 *pfx, void *buf, ulong nbytes);
+
+#endif
Index: upstream-staging/drivers/staging/unisys/include/uniklog.h
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/include/uniklog.h
@@ -0,0 +1,193 @@
+/* uniklog.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/* This module contains macros to aid developers in logging messages.
+ *
+ * This module is affected by the DEBUG compiletime option.
+ *
+ */
+#ifndef __UNIKLOG_H__
+#define __UNIKLOG_H__
+
+
+#include <linux/printk.h>
+
+/*
+ * # DBGINF
+ *
+ * \brief Log debug informational message - log a LOG_INFO message only
+ *        if DEBUG compiletime option enabled
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the
+ *             format string.
+ * \return nothing
+ *
+ * Log a message at the LOG_INFO level, but only if DEBUG is enabled.  If
+ * DEBUG is disabled, this expands to a no-op.
+ */
+
+/*
+ * # DBGVER
+ *
+ * \brief Log debug verbose message - log a LOG_DEBUG message only if
+ *        DEBUG compiletime option enabled
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the
+ *             format string.
+ * \return nothing
+ *
+ * Log a message at the LOG_DEBUG level, but only if DEBUG is enabled.  If
+ * DEBUG is disabled, this expands to a no-op.  Note also that LOG_DEBUG
+ * messages can be enabled/disabled at runtime as well.
+ */
+#define DBGINFDEV(devname, fmt, args...)        do { } while (0)
+#define DBGVERDEV(devname, fmt, args...)        do { } while (0)
+#define DBGINF(fmt, args...)                    do { } while (0)
+#define DBGVER(fmt, args...)                    do { } while (0)
+
+/*
+ * # LOGINF
+ *
+ * \brief Log informational message - logs a message at the LOG_INFO level
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the
+ *             format string.
+ * \return nothing
+ *
+ * Logs the specified message at the LOG_INFO level.
+ */
+
+#define LOGINF(fmt, args...) pr_info(fmt, ## args)
+#define LOGINFDEV(devname, fmt, args...) \
+	pr_info("%s " fmt, devname, ## args)
+#define LOGINFDEVX(devno, fmt, args...) \
+	pr_info("dev%d " fmt, devno, ## args)
+#define LOGINFNAME(vnic, fmt, args...)				\
+	do {								\
+		if (vnic != NULL) {					\
+			pr_info("%s " fmt, vnic->name, ## args);	\
+		} else {						\
+			pr_info(fmt, ## args);				\
+		}							\
+	} while (0)
+
+/*
+ * # LOGVER
+ *
+ * \brief Log verbose message - logs a message at the LOG_DEBUG level,
+ *        which can be disabled at runtime
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the format
+ * \param string.
+ * \return nothing
+ *
+ * Logs the specified message at the LOG_DEBUG level.  Note also that
+ * LOG_DEBUG messages can be enabled/disabled at runtime as well.
+ */
+#define LOGVER(fmt, args...) pr_debug(fmt, ## args)
+#define LOGVERDEV(devname, fmt, args...) \
+	pr_debug("%s " fmt, devname, ## args)
+#define LOGVERNAME(vnic, fmt, args...)					\
+	do {								\
+		if (vnic != NULL) {					\
+			pr_debug("%s " fmt, vnic->name, ## args);	\
+		} else {						\
+			pr_debug(fmt, ## args);				\
+		}							\
+	} while (0)
+
+
+/*
+ * # LOGERR
+ *
+ * \brief Log error message - logs a message at the LOG_ERR level,
+ *        including source line number information
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the format
+ * \param string.
+ * \return nothing
+ *
+ * Logs the specified error message at the LOG_ERR level.  It will also
+ * include the file, line number, and function name of where the error
+ * originated in the log message.
+ */
+#define LOGERR(fmt, args...) pr_err(fmt, ## args)
+#define LOGERRDEV(devname, fmt, args...) \
+	pr_err("%s " fmt, devname, ## args)
+#define LOGERRDEVX(devno, fmt, args...) \
+	pr_err("dev%d " fmt, devno, ## args)
+#define LOGERRNAME(vnic, fmt, args...)				\
+	do {								\
+		if (vnic != NULL) {					\
+			pr_err("%s " fmt, vnic->name, ## args);	\
+		} else {						\
+			pr_err(fmt, ## args);				\
+		}							\
+	} while (0)
+#define LOGORDUMPERR(seqfile, fmt, args...) do {		\
+		if (seqfile) {					\
+			seq_printf(seqfile, fmt, ## args);	\
+		} else {					\
+			LOGERR(fmt, ## args);			\
+		}						\
+	} while (0)
+
+/*
+ * # LOGWRN
+ *
+ * \brief Log warning message - Logs a message at the LOG_WARNING level,
+ *        including source line number information
+ *
+ * \param devname the device name of the device reporting this message, or
+ *                NULL if this message is NOT device-related.
+ * \param fmt printf()-style format string containing the message to log.
+ * \param args Optional arguments to be formatted and inserted into the format
+ * \param string.
+ * \return nothing
+ *
+ * Logs the specified error message at the LOG_WARNING level.  It will also
+ * include the file, line number, and function name of where the error
+ * originated in the log message.
+ */
+#define LOGWRN(fmt, args...) pr_warn(fmt, ## args)
+#define LOGWRNDEV(devname, fmt, args...) \
+	pr_warn("%s " fmt, devname, ## args)
+#define LOGWRNNAME(vnic, fmt, args...) \
+	do {								\
+		if (vnic != NULL) {					\
+			pr_warn("%s " fmt, vnic->name, ## args);	\
+		} else {						\
+			pr_warn(fmt, ## args);				\
+		}							\
+	} while (0)
+
+#endif /* __UNIKLOG_H__ */
Index: upstream-staging/drivers/staging/unisys/visorutil/Kconfig
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/visorutil/Kconfig
@@ -0,0 +1,10 @@
+#
+# Unisys timskmod configuration
+#
+
+config UNISYS_VISORUTIL
+	tristate "Unisys visorutil driver"
+	depends on UNISYSSPAR
+	---help---
+	If you say Y here, you will enable the Unisys visorutil driver.
+
Index: upstream-staging/drivers/staging/unisys/visorutil/Makefile
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/visorutil/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for Unisys timskmod
+#
+
+obj-$(CONFIG_UNISYS_VISORUTIL)	+= visorutil.o
+
+visorutil-y := charqueue.o  easyproc.o  periodic_work.o  procobjecttree.o  \
+		memregion_direct.o visorkmodutils.o
+
+ccflags-y += -Idrivers/staging/unisys/include
+ccflags-y += -DCONFIG_SPAR_GUEST -DGUESTDRIVERBUILD -DNOAUTOVERSION
Index: upstream-staging/drivers/staging/unisys/visorutil/charqueue.c
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/visorutil/charqueue.c
@@ -0,0 +1,144 @@
+/* charqueue.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ *  Simple character queue implementation for Linux kernel mode.
+ */
+
+#include "charqueue.h"
+
+#define MYDRVNAME "charqueue"
+
+#define IS_EMPTY(charqueue) (charqueue->head == charqueue->tail)
+
+
+
+struct CHARQUEUE_Tag {
+	int alloc_size;
+	int nslots;
+	spinlock_t lock;
+	int head, tail;
+	unsigned char buf[0];
+};
+
+
+
+CHARQUEUE *charqueue_create(ulong nslots)
+{
+	int alloc_size = sizeof(CHARQUEUE) + nslots + 1;
+	CHARQUEUE *cq = kmalloc(alloc_size, GFP_KERNEL|__GFP_NORETRY);
+	if (cq == NULL) {
+		ERRDRV("charqueue_create allocation failed (alloc_size=%d)",
+		       alloc_size);
+		return NULL;
+	}
+	cq->alloc_size = alloc_size;
+	cq->nslots = nslots;
+	cq->head = cq->tail = 0;
+	spin_lock_init(&cq->lock);
+	return cq;
+}
+EXPORT_SYMBOL_GPL(charqueue_create);
+
+
+
+void charqueue_enqueue(CHARQUEUE *charqueue, unsigned char c)
+{
+	int alloc_slots = charqueue->nslots+1;  /* 1 slot is always empty */
+
+	spin_lock(&charqueue->lock);
+	charqueue->head = (charqueue->head+1) % alloc_slots;
+	if (charqueue->head == charqueue->tail)
+		/* overflow; overwrite the oldest entry */
+		charqueue->tail = (charqueue->tail+1) % alloc_slots;
+	charqueue->buf[charqueue->head] = c;
+	spin_unlock(&charqueue->lock);
+}
+EXPORT_SYMBOL_GPL(charqueue_enqueue);
+
+
+
+BOOL charqueue_is_empty(CHARQUEUE *charqueue)
+{
+	BOOL b;
+	spin_lock(&charqueue->lock);
+	b = IS_EMPTY(charqueue);
+	spin_unlock(&charqueue->lock);
+	return b;
+}
+EXPORT_SYMBOL_GPL(charqueue_is_empty);
+
+
+
+static int charqueue_dequeue_1(CHARQUEUE *charqueue)
+{
+	int alloc_slots = charqueue->nslots + 1;  /* 1 slot is always empty */
+
+	if (IS_EMPTY(charqueue))
+		return -1;
+	charqueue->tail = (charqueue->tail+1) % alloc_slots;
+	return charqueue->buf[charqueue->tail];
+}
+
+
+
+int charqueue_dequeue(CHARQUEUE *charqueue)
+{
+	int rc = -1;
+
+	spin_lock(&charqueue->lock);
+	RETINT(charqueue_dequeue_1(charqueue));
+Away:
+	spin_unlock(&charqueue->lock);
+	return rc;
+}
+
+
+
+int charqueue_dequeue_n(CHARQUEUE *charqueue, unsigned char *buf, int n)
+{
+	int rc = -1, counter = 0, c;
+
+	spin_lock(&charqueue->lock);
+	for (;;) {
+		if (n <= 0)
+			break;  /* no more buffer space */
+		c = charqueue_dequeue_1(charqueue);
+		if (c < 0)
+			break;  /* no more input */
+		*buf = (unsigned char)(c);
+		buf++;
+		n--;
+		counter++;
+	}
+	RETINT(counter);
+
+Away:
+	spin_unlock(&charqueue->lock);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(charqueue_dequeue_n);
+
+
+
+void charqueue_destroy(CHARQUEUE *charqueue)
+{
+	if (charqueue == NULL)
+		return;
+	kfree(charqueue);
+}
+EXPORT_SYMBOL_GPL(charqueue_destroy);
Index: upstream-staging/drivers/staging/unisys/visorutil/charqueue.h
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/visorutil/charqueue.h
@@ -0,0 +1,37 @@
+/* charqueue.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __CHARQUEUE_H__
+#define __CHARQUEUE_H__
+
+#include "uniklog.h"
+#include "timskmod.h"
+
+/* CHARQUEUE is an opaque structure to users.
+ * Fields are declared only in the implementation .c files.
+ */
+typedef struct CHARQUEUE_Tag CHARQUEUE;
+
+CHARQUEUE *charqueue_create(ulong nslots);
+void charqueue_enqueue(CHARQUEUE *charqueue, unsigned char c);
+int charqueue_dequeue(CHARQUEUE *charqueue);
+int charqueue_dequeue_n(CHARQUEUE *charqueue, unsigned char *buf, int n);
+BOOL charqueue_is_empty(CHARQUEUE *charqueue);
+void charqueue_destroy(CHARQUEUE *charqueue);
+
+#endif
+
Index: upstream-staging/drivers/staging/unisys/visorutil/easyproc.c
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/visorutil/easyproc.c
@@ -0,0 +1,365 @@
+/* Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/** @file *********************************************************************
+ *
+ *  Handle procfs-specific tasks.
+ *  Note that this file does not know about any module-specific things, nor
+ *  does it know anything about what information to reveal as part of the proc
+ *  entries.  The 2 functions that take care of displaying device and
+ *  driver specific information are passed as parameters to
+ *  easyproc_InitDriver().
+ *
+ *      void show_device_info(struct seq_file *seq, void *p);
+ *      void show_driver_info(struct seq_file *seq);
+ *
+ *  The second parameter to show_device_info is actually a pointer to the
+ *  device-specific info to show.  It is the context that was originally
+ *  passed to easyproc_InitDevice().
+ *
+ ******************************************************************************
+ */
+
+#include <linux/proc_fs.h>
+
+#include "uniklog.h"
+#include "timskmod.h"
+#include "easyproc.h"
+
+#define MYDRVNAME "easyproc"
+
+
+
+/*
+ *   /proc/<ProcId>                              ProcDir
+ *   /proc/<ProcId>/driver                       ProcDriverDir
+ *   /proc/<ProcId>/driver/diag                  ProcDriverDiagFile
+ *   /proc/<ProcId>/device                       ProcDeviceDir
+ *   /proc/<ProcId>/device/0                     procDevicexDir
+ *   /proc/<ProcId>/device/0/diag                procDevicexDiagFile
+ */
+
+
+static ssize_t proc_write_device(struct file *file, const char __user *buffer,
+				 size_t count, loff_t *ppos);
+static ssize_t proc_write_driver(struct file *file, const char __user *buffer,
+				 size_t count, loff_t *ppos);
+
+static struct proc_dir_entry *
+	createProcDir(char *name, struct proc_dir_entry *parent)
+{
+	struct proc_dir_entry *p = proc_mkdir_mode(name, S_IFDIR, parent);
+	if (p == NULL)
+		ERRDRV("failed to create /proc directory %s", name);
+	return p;
+}
+
+static int seq_show_driver(struct seq_file *seq, void *offset);
+static int proc_open_driver(struct inode *inode, struct file *file)
+{
+	return single_open(file, seq_show_driver, PDE_DATA(inode));
+}
+static const struct file_operations proc_fops_driver = {
+	.open = proc_open_driver,
+	.read = seq_read,
+	.write = proc_write_driver,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int seq_show_device(struct seq_file *seq, void *offset);
+static int seq_show_device_property(struct seq_file *seq, void *offset);
+static int proc_open_device(struct inode *inode, struct file *file)
+{
+	return single_open(file, seq_show_device, PDE_DATA(inode));
+}
+static const struct file_operations proc_fops_device = {
+	.open = proc_open_device,
+	.read = seq_read,
+	.write = proc_write_device,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+static int proc_open_device_property(struct inode *inode, struct file *file)
+{
+	return single_open(file, seq_show_device_property, PDE_DATA(inode));
+}
+static const struct file_operations proc_fops_device_property = {
+	.open = proc_open_device_property,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+
+
+void easyproc_InitDriver(struct easyproc_driver_info *pdriver,
+			 char *procId,
+			 void (*show_driver_info)(struct seq_file *),
+			 void (*show_device_info)(struct seq_file *, void *))
+{
+	memset(pdriver, 0, sizeof(struct easyproc_driver_info));
+	pdriver->ProcId = procId;
+	if (pdriver->ProcId == NULL)
+		ERRDRV("ProcId cannot be NULL (trouble ahead)!");
+	pdriver->Show_driver_info = show_driver_info;
+	pdriver->Show_device_info = show_device_info;
+	if (pdriver->ProcDir == NULL)
+		pdriver->ProcDir = createProcDir(pdriver->ProcId, NULL);
+	if ((pdriver->ProcDir != NULL) && (pdriver->ProcDriverDir == NULL))
+		pdriver->ProcDriverDir = createProcDir("driver",
+						       pdriver->ProcDir);
+	if ((pdriver->ProcDir != NULL) && (pdriver->ProcDeviceDir == NULL))
+		pdriver->ProcDeviceDir = createProcDir("device",
+						       pdriver->ProcDir);
+	if ((pdriver->ProcDriverDir != NULL) &&
+	    (pdriver->ProcDriverDiagFile == NULL)) {
+		pdriver->ProcDriverDiagFile =
+			proc_create_data("diag", 0,
+					 pdriver->ProcDriverDir,
+					 &proc_fops_driver, pdriver);
+		if (pdriver->ProcDriverDiagFile == NULL)
+			ERRDRV("failed to register /proc/%s/driver/diag entry",
+			       pdriver->ProcId);
+	}
+}
+EXPORT_SYMBOL_GPL(easyproc_InitDriver);
+
+
+
+void easyproc_InitDriverEx(struct easyproc_driver_info *pdriver,
+			   char *procId,
+			   void (*show_driver_info)(struct seq_file *),
+			   void (*show_device_info)(struct seq_file *, void *),
+			   void (*write_driver_info)(char *buf, size_t count,
+						     loff_t *ppos),
+			   void (*write_device_info)(char *buf, size_t count,
+						     loff_t *ppos, void *p))
+{
+	easyproc_InitDriver(pdriver, procId,
+			    show_driver_info, show_device_info);
+	pdriver->Write_driver_info = write_driver_info;
+	pdriver->Write_device_info = write_device_info;
+}
+EXPORT_SYMBOL_GPL(easyproc_InitDriverEx);
+
+
+
+void easyproc_DeInitDriver(struct easyproc_driver_info *pdriver)
+{
+	if (pdriver->ProcDriverDiagFile != NULL) {
+		remove_proc_entry("diag", pdriver->ProcDriverDir);
+		pdriver->ProcDriverDiagFile = NULL;
+	}
+	if (pdriver->ProcDriverDir != NULL) {
+		remove_proc_entry("driver", pdriver->ProcDir);
+		pdriver->ProcDriverDir = NULL;
+	}
+	if (pdriver->ProcDeviceDir != NULL) {
+		remove_proc_entry("device", pdriver->ProcDir);
+		pdriver->ProcDeviceDir = NULL;
+	}
+	if (pdriver->ProcDir != NULL) {
+		remove_proc_entry(pdriver->ProcId, NULL);
+		pdriver->ProcDir = NULL;
+	}
+	pdriver->ProcId = NULL;
+	pdriver->Show_driver_info = NULL;
+	pdriver->Show_device_info = NULL;
+	pdriver->Write_driver_info = NULL;
+	pdriver->Write_device_info = NULL;
+}
+EXPORT_SYMBOL_GPL(easyproc_DeInitDriver);
+
+
+
+void easyproc_InitDevice(struct easyproc_driver_info *pdriver,
+			 struct easyproc_device_info *p, int devno,
+			 void *devdata)
+{
+	if ((pdriver->ProcDeviceDir != NULL) && (p->procDevicexDir == NULL)) {
+		char s[29];
+		sprintf(s, "%d", devno);
+		p->procDevicexDir = createProcDir(s, pdriver->ProcDeviceDir);
+		p->devno = devno;
+	}
+	p->devdata = devdata;
+	p->pdriver = pdriver;
+	p->devno = devno;
+	if ((p->procDevicexDir != NULL) && (p->procDevicexDiagFile == NULL)) {
+		p->procDevicexDiagFile =
+			proc_create_data("diag", 0, p->procDevicexDir,
+					 &proc_fops_device, p);
+		if (p->procDevicexDiagFile == NULL)
+			ERRDEVX(devno, "failed to register /proc/%s/device/%d/diag entry",
+				pdriver->ProcId, devno
+			       );
+	}
+	memset(&(p->device_property_info[0]), 0,
+	       sizeof(p->device_property_info));
+}
+EXPORT_SYMBOL_GPL(easyproc_InitDevice);
+
+
+
+void easyproc_CreateDeviceProperty(struct easyproc_device_info *p,
+				   void (*show_property_info)(struct seq_file *, void *),
+				   char *property_name)
+{
+	size_t i;
+	struct easyproc_device_property_info *px = NULL;
+
+	if (p->procDevicexDir == NULL) {
+		ERRDRV("state error");
+		return;
+	}
+	for (i = 0; i < ARRAY_SIZE(p->device_property_info); i++) {
+		if (p->device_property_info[i].procEntry == NULL) {
+			px = &(p->device_property_info[i]);
+			break;
+		}
+	}
+	if (!px) {
+		ERRDEVX(p->devno, "too many device properties");
+		return;
+	}
+	px->devdata = p->devdata;
+	px->pdriver = p->pdriver;
+	px->procEntry = proc_create_data(property_name, 0, p->procDevicexDir,
+					 &proc_fops_device_property, px);
+	if (strlen(property_name)+1 > sizeof(px->property_name)) {
+		ERRDEVX(p->devno, "device property name %s too long",
+			property_name);
+		return;
+	}
+	strcpy(px->property_name, property_name);
+	if (px->procEntry == NULL) {
+		ERRDEVX(p->devno, "failed to register /proc/%s/device/%d/%s entry",
+			p->pdriver->ProcId, p->devno, property_name
+		       );
+		return;
+	}
+	px->show_device_property_info = show_property_info;
+}
+EXPORT_SYMBOL_GPL(easyproc_CreateDeviceProperty);
+
+
+
+void easyproc_DeInitDevice(struct easyproc_driver_info *pdriver,
+			   struct easyproc_device_info *p, int devno)
+{
+	size_t i;
+	for (i = 0; i < ARRAY_SIZE(p->device_property_info); i++) {
+		if (p->device_property_info[i].procEntry != NULL) {
+			struct easyproc_device_property_info *px =
+				&(p->device_property_info[i]);
+			remove_proc_entry(px->property_name, p->procDevicexDir);
+			px->procEntry = NULL;
+		}
+	}
+	if (p->procDevicexDiagFile != NULL) {
+		remove_proc_entry("diag", p->procDevicexDir);
+		p->procDevicexDiagFile = NULL;
+	}
+	if (p->procDevicexDir != NULL) {
+		char s[29];
+		sprintf(s, "%d", devno);
+		remove_proc_entry(s, pdriver->ProcDeviceDir);
+		p->procDevicexDir = NULL;
+	}
+	p->devdata = NULL;
+	p->pdriver = NULL;
+}
+EXPORT_SYMBOL_GPL(easyproc_DeInitDevice);
+
+
+
+static int seq_show_driver(struct seq_file *seq, void *offset)
+{
+	struct easyproc_driver_info *p =
+		(struct easyproc_driver_info *)(seq->private);
+	if (!p)
+		return 0;
+	(*(p->Show_driver_info))(seq);
+	return 0;
+}
+
+
+
+static int seq_show_device(struct seq_file *seq, void *offset)
+{
+	struct easyproc_device_info *p =
+		(struct easyproc_device_info *)(seq->private);
+	if ((!p) || (!(p->pdriver)))
+		return 0;
+	(*(p->pdriver->Show_device_info))(seq, p->devdata);
+	return 0;
+}
+
+
+
+static int seq_show_device_property(struct seq_file *seq, void *offset)
+{
+	struct easyproc_device_property_info *p =
+		(struct easyproc_device_property_info *)(seq->private);
+	if ((!p) || (!(p->show_device_property_info)))
+		return 0;
+	(*(p->show_device_property_info))(seq, p->devdata);
+	return 0;
+}
+
+
+
+static ssize_t proc_write_driver(struct file *file, const char __user *buffer,
+				 size_t count, loff_t *ppos)
+{
+	struct seq_file *seq = (struct seq_file *)file->private_data;
+	struct easyproc_driver_info *p = NULL;
+	char local_buf[256];
+	if (seq == NULL)
+		return 0;
+	p = (struct easyproc_driver_info *)(seq->private);
+	if ((!p) || (!(p->Write_driver_info)))
+		return 0;
+	if (count >= sizeof(local_buf))
+		return -ENOMEM;
+	if (copy_from_user(local_buf, buffer, count))
+		return -EFAULT;
+	local_buf[count] = '\0';  /* be friendly */
+	(*(p->Write_driver_info))(local_buf, count, ppos);
+	return count;
+}
+
+
+
+static ssize_t proc_write_device(struct file *file, const char __user *buffer,
+				 size_t count, loff_t *ppos)
+{
+	struct seq_file *seq = (struct seq_file *)file->private_data;
+	struct easyproc_device_info *p = NULL;
+	char local_buf[256];
+	if (seq == NULL)
+		return 0;
+	p = (struct easyproc_device_info *)(seq->private);
+	if ((!p) || (!(p->pdriver)) || (!(p->pdriver->Write_device_info)))
+		return 0;
+	if (count >= sizeof(local_buf))
+		return -ENOMEM;
+	if (copy_from_user(local_buf, buffer, count))
+		return -EFAULT;
+	local_buf[count] = '\0';  /* be friendly */
+	(*(p->pdriver->Write_device_info))(local_buf, count, ppos, p->devdata);
+	return count;
+}
Index: upstream-staging/drivers/staging/unisys/visorutil/easyproc.h
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/visorutil/easyproc.h
@@ -0,0 +1,86 @@
+/* easyproc.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/** @file *********************************************************************
+ *
+ *  This describes the interfaces necessary for a simple /proc file
+ *  implementation for a driver.
+ *
+ ******************************************************************************
+ */
+
+#ifndef __EASYPROC_H__
+#define __EASYPROC_H__
+
+#include "timskmod.h"
+
+
+struct easyproc_driver_info {
+	struct proc_dir_entry *ProcDir;
+	struct proc_dir_entry *ProcDriverDir;
+	struct proc_dir_entry *ProcDriverDiagFile;
+	struct proc_dir_entry *ProcDeviceDir;
+	char *ProcId;
+	void (*Show_device_info)(struct seq_file *seq, void *p);
+	void (*Show_driver_info)(struct seq_file *seq);
+	void (*Write_device_info)(char *buf, size_t count,
+				  loff_t *ppos, void *p);
+	void (*Write_driver_info)(char *buf, size_t count, loff_t *ppos);
+};
+
+/* property is a file under /proc/<x>/device/<x>/<property_name> */
+struct easyproc_device_property_info {
+	char property_name[25];
+	struct proc_dir_entry *procEntry;
+	struct easyproc_driver_info *pdriver;
+	void *devdata;
+	void (*show_device_property_info)(struct seq_file *seq, void *p);
+};
+
+struct easyproc_device_info {
+	struct proc_dir_entry *procDevicexDir;
+	struct proc_dir_entry *procDevicexDiagFile;
+	struct easyproc_driver_info *pdriver;
+	void *devdata;
+	int devno;
+	/*  allow for a number of custom properties for each device: */
+	struct easyproc_device_property_info device_property_info[10];
+};
+
+void easyproc_InitDevice(struct easyproc_driver_info *pdriver,
+			 struct easyproc_device_info *p, int devno,
+			 void *devdata);
+void easyproc_DeInitDevice(struct easyproc_driver_info *pdriver,
+			   struct easyproc_device_info *p, int devno);
+void easyproc_InitDriver(struct easyproc_driver_info *pdriver,
+			 char *procId,
+			 void (*show_driver_info)(struct seq_file *),
+			 void (*show_device_info)(struct seq_file *, void *));
+void easyproc_InitDriverEx(struct easyproc_driver_info *pdriver,
+			   char *procId,
+			   void (*show_driver_info)(struct seq_file *),
+			   void (*show_device_info)(struct seq_file *, void *),
+			   void (*Write_driver_info)(char *buf, size_t count,
+						     loff_t *ppos),
+			   void (*Write_device_info)(char *buf, size_t count,
+						     loff_t *ppos, void *p));
+void easyproc_DeInitDriver(struct easyproc_driver_info *pdriver);
+void easyproc_CreateDeviceProperty(struct easyproc_device_info *p,
+				   void (*show_property_info)(struct seq_file *, void *),
+				   char *property_name);
+
+#endif
Index: upstream-staging/drivers/staging/unisys/visorutil/memregion.h
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/visorutil/memregion.h
@@ -0,0 +1,43 @@
+/* memregion.h
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef __MEMREGION_H__
+#define __MEMREGION_H__
+
+#include "timskmod.h"
+
+/* MEMREGION is an opaque structure to users.
+ * Fields are declared only in the implementation .c files.
+ */
+typedef struct MEMREGION_Tag MEMREGION;
+
+MEMREGION *memregion_create(HOSTADDRESS physaddr, ulong nbytes);
+MEMREGION *memregion_create_overlapped(MEMREGION *parent,
+				       ulong offset, ulong nbytes);
+int memregion_resize(MEMREGION *memregion, ulong newsize);
+int memregion_read(MEMREGION *memregion,
+		   ulong offset, void *dest, ulong nbytes);
+int memregion_write(MEMREGION *memregion,
+		    ulong offset, void *src, ulong nbytes);
+void memregion_destroy(MEMREGION *memregion);
+HOSTADDRESS memregion_get_physaddr(MEMREGION *memregion);
+ulong memregion_get_nbytes(MEMREGION *memregion);
+void memregion_dump(MEMREGION *memregion, char *s,
+		    ulong off, ulong len, struct seq_file *seq);
+void *memregion_get_pointer(MEMREGION *memregion);
+
+#endif
Index: upstream-staging/drivers/staging/unisys/visorutil/memregion_direct.c
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/visorutil/memregion_direct.c
@@ -0,0 +1,221 @@
+/* memregion_direct.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ *  This is an implementation of memory regions that can be used to read/write
+ *  channel memory (in main memory of the host system) from code running in
+ *  a virtual partition.
+ */
+#include "uniklog.h"
+#include "timskmod.h"
+#include "memregion.h"
+
+#define MYDRVNAME "memregion"
+
+struct MEMREGION_Tag {
+	HOSTADDRESS physaddr;
+	ulong nbytes;
+	void *mapped;
+	BOOL requested;
+	BOOL overlapped;
+};
+
+static BOOL mapit(MEMREGION *memregion);
+static void unmapit(MEMREGION *memregion);
+
+MEMREGION *
+memregion_create(HOSTADDRESS physaddr, ulong nbytes)
+{
+	MEMREGION *rc = NULL;
+	MEMREGION *memregion = kmalloc(sizeof(MEMREGION),
+				       GFP_KERNEL|__GFP_NORETRY);
+	if (memregion == NULL) {
+		ERRDRV("memregion_create allocation failed");
+		return NULL;
+	}
+	memset(memregion, 0, sizeof(MEMREGION));
+	memregion->physaddr = physaddr;
+	memregion->nbytes = nbytes;
+	memregion->overlapped = FALSE;
+	if (!mapit(memregion))
+		RETPTR(NULL);
+	RETPTR(memregion);
+
+Away:
+	if (rc == NULL) {
+		if (memregion != NULL) {
+			memregion_destroy(memregion);
+			memregion = NULL;
+		}
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(memregion_create);
+
+MEMREGION *
+memregion_create_overlapped(MEMREGION *parent, ulong offset, ulong nbytes)
+{
+	MEMREGION *memregion = NULL;
+
+	if (parent == NULL) {
+		ERRDRV("%s parent is NULL", __func__);
+		return NULL;
+	}
+	if (parent->mapped == NULL) {
+		ERRDRV("%s parent is not mapped!", __func__);
+		return NULL;
+	}
+	if ((offset >= parent->nbytes) ||
+	    ((offset + nbytes) >= parent->nbytes)) {
+		ERRDRV("%s range (%lu,%lu) out of parent range",
+		       __func__, offset, nbytes);
+		return NULL;
+	}
+	memregion = kmalloc(sizeof(MEMREGION), GFP_KERNEL|__GFP_NORETRY);
+	if (memregion == NULL) {
+		ERRDRV("%s allocation failed", __func__);
+		return NULL;
+	}
+	memset(memregion, 0, sizeof(MEMREGION));
+	memregion->physaddr = parent->physaddr + offset;
+	memregion->nbytes = nbytes;
+	memregion->mapped = ((u8 *) (parent->mapped)) + offset;
+	memregion->requested = FALSE;
+	memregion->overlapped = TRUE;
+	return memregion;
+}
+EXPORT_SYMBOL_GPL(memregion_create_overlapped);
+
+
+static BOOL
+mapit(MEMREGION *memregion)
+{
+	ulong physaddr = (ulong) (memregion->physaddr);
+	ulong nbytes = memregion->nbytes;
+
+	memregion->requested = FALSE;
+	if (!request_mem_region(physaddr, nbytes, MYDRVNAME))
+		ERRDRV("cannot reserve channel memory @0x%lx for 0x%lx-- no big deal", physaddr, nbytes);
+	else
+		memregion->requested = TRUE;
+	memregion->mapped = ioremap_cache(physaddr, nbytes);
+	if (memregion->mapped == NULL) {
+		ERRDRV("cannot ioremap_cache channel memory @0x%lx for 0x%lx",
+		       physaddr, nbytes);
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static void
+unmapit(MEMREGION *memregion)
+{
+	if (memregion->mapped != NULL) {
+		iounmap(memregion->mapped);
+		memregion->mapped = NULL;
+	}
+	if (memregion->requested) {
+		release_mem_region((ulong) (memregion->physaddr),
+				   memregion->nbytes);
+		memregion->requested = FALSE;
+	}
+}
+
+HOSTADDRESS
+memregion_get_physaddr(MEMREGION *memregion)
+{
+	return memregion->physaddr;
+}
+EXPORT_SYMBOL_GPL(memregion_get_physaddr);
+
+ulong
+memregion_get_nbytes(MEMREGION *memregion)
+{
+	return memregion->nbytes;
+}
+EXPORT_SYMBOL_GPL(memregion_get_nbytes);
+
+void *
+memregion_get_pointer(MEMREGION *memregion)
+{
+	return memregion->mapped;
+}
+EXPORT_SYMBOL_GPL(memregion_get_pointer);
+
+int
+memregion_resize(MEMREGION *memregion, ulong newsize)
+{
+	if (newsize == memregion->nbytes)
+		return 0;
+	if (memregion->overlapped)
+		/* no error check here - we no longer know the
+		 * parent's range!
+		 */
+		memregion->nbytes = newsize;
+	else {
+		unmapit(memregion);
+		memregion->nbytes = newsize;
+		if (!mapit(memregion))
+			return -1;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(memregion_resize);
+
+
+static int
+memregion_readwrite(BOOL is_write,
+		    MEMREGION *memregion, ulong offset,
+		    void *local, ulong nbytes)
+{
+	if (offset + nbytes > memregion->nbytes) {
+		ERRDRV("memregion_readwrite offset out of range!!");
+		return -EFAULT;
+	}
+	if (is_write)
+		memcpy_toio(memregion->mapped + offset, local, nbytes);
+	else
+		memcpy_fromio(local, memregion->mapped + offset, nbytes);
+
+	return 0;
+}
+
+int
+memregion_read(MEMREGION *memregion, ulong offset, void *dest, ulong nbytes)
+{
+	return memregion_readwrite(FALSE, memregion, offset, dest, nbytes);
+}
+EXPORT_SYMBOL_GPL(memregion_read);
+
+int
+memregion_write(MEMREGION *memregion, ulong offset, void *src, ulong nbytes)
+{
+	return memregion_readwrite(TRUE, memregion, offset, src, nbytes);
+}
+EXPORT_SYMBOL_GPL(memregion_write);
+
+void
+memregion_destroy(MEMREGION *memregion)
+{
+	if (memregion == NULL)
+		return;
+	if (!memregion->overlapped)
+		unmapit(memregion);
+	kfree(memregion);
+}
+EXPORT_SYMBOL_GPL(memregion_destroy);
+
Index: upstream-staging/drivers/staging/unisys/visorutil/periodic_work.c
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/visorutil/periodic_work.c
@@ -0,0 +1,230 @@
+/* periodic_work.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+/*
+ *  Helper functions to schedule periodic work in Linux kernel mode.
+ */
+
+#include "uniklog.h"
+#include "timskmod.h"
+#include "periodic_work.h"
+
+#define MYDRVNAME "periodic_work"
+
+
+
+struct PERIODIC_WORK_Tag {
+	rwlock_t lock;
+	struct delayed_work work;
+	void (*workfunc)(void *);
+	void *workfuncarg;
+	BOOL is_scheduled;
+	BOOL want_to_stop;
+	ulong jiffy_interval;
+	struct workqueue_struct *workqueue;
+	const char *devnam;
+};
+
+
+
+static void periodic_work_func(struct work_struct *work)
+{
+	PERIODIC_WORK *periodic_work =
+		container_of(work, struct PERIODIC_WORK_Tag, work.work);
+	(*periodic_work->workfunc)(periodic_work->workfuncarg);
+}
+
+
+
+PERIODIC_WORK *periodic_work_create(ulong jiffy_interval,
+				      struct workqueue_struct *workqueue,
+				      void (*workfunc)(void *),
+				      void *workfuncarg,
+				      const char *devnam)
+{
+	PERIODIC_WORK *periodic_work = kmalloc(sizeof(PERIODIC_WORK),
+					       GFP_KERNEL|__GFP_NORETRY);
+	if (periodic_work == NULL) {
+		ERRDRV("periodic_work allocation failed ");
+		return NULL;
+	}
+	memset(periodic_work, '\0', sizeof(PERIODIC_WORK));
+	rwlock_init(&periodic_work->lock);
+	periodic_work->jiffy_interval = jiffy_interval;
+	periodic_work->workqueue = workqueue;
+	periodic_work->workfunc = workfunc;
+	periodic_work->workfuncarg = workfuncarg;
+	periodic_work->devnam = devnam;
+	return periodic_work;
+}
+EXPORT_SYMBOL_GPL(periodic_work_create);
+
+
+
+void periodic_work_destroy(PERIODIC_WORK *periodic_work)
+{
+	if (periodic_work == NULL)
+		return;
+	kfree(periodic_work);
+}
+EXPORT_SYMBOL_GPL(periodic_work_destroy);
+
+
+
+/** Call this from your periodic work worker function to schedule the next
+ *  call.
+ *  If this function returns FALSE, there was a failure and the
+ *  periodic work is no longer scheduled
+ */
+BOOL periodic_work_nextperiod(PERIODIC_WORK *periodic_work)
+{
+	BOOL rc = FALSE;
+	write_lock(&periodic_work->lock);
+	if (periodic_work->want_to_stop) {
+		periodic_work->is_scheduled = FALSE;
+		periodic_work->want_to_stop = FALSE;
+		RETBOOL(TRUE);  /* yes, TRUE; see periodic_work_stop() */
+	} else if (queue_delayed_work(periodic_work->workqueue,
+				      &periodic_work->work,
+				      periodic_work->jiffy_interval) < 0) {
+		ERRDEV(periodic_work->devnam, "queue_delayed_work failed!");
+		periodic_work->is_scheduled = FALSE;
+		RETBOOL(FALSE);
+	}
+	RETBOOL(TRUE);
+Away:
+	write_unlock(&periodic_work->lock);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(periodic_work_nextperiod);
+
+
+
+/** This function returns TRUE iff new periodic work was actually started.
+ *  If this function returns FALSE, then no work was started
+ *  (either because it was already started, or because of a failure).
+ */
+BOOL periodic_work_start(PERIODIC_WORK *periodic_work)
+{
+	BOOL rc = FALSE;
+
+	write_lock(&periodic_work->lock);
+	if (periodic_work->is_scheduled)
+		RETBOOL(FALSE);
+	if (periodic_work->want_to_stop) {
+		ERRDEV(periodic_work->devnam,
+		       "dev_start_periodic_work failed!");
+		RETBOOL(FALSE);
+	}
+	INIT_DELAYED_WORK(&periodic_work->work, &periodic_work_func);
+	if (queue_delayed_work(periodic_work->workqueue,
+			       &periodic_work->work,
+			       periodic_work->jiffy_interval) < 0) {
+		ERRDEV(periodic_work->devnam,
+		       "%s queue_delayed_work failed!", __func__);
+		RETBOOL(FALSE);
+	}
+	periodic_work->is_scheduled = TRUE;
+	RETBOOL(TRUE);
+Away:
+	write_unlock(&periodic_work->lock);
+	return rc;
+
+}
+EXPORT_SYMBOL_GPL(periodic_work_start);
+
+
+
+
+/** This function returns TRUE iff your call actually stopped the periodic
+ *  work.
+ *
+ *  -- PAY ATTENTION... this is important --
+ *
+ *  NO NO #1
+ *
+ *     Do NOT call this function from some function that is running on the
+ *     same workqueue as the work you are trying to stop might be running
+ *     on!  If you violate this rule, periodic_work_stop() MIGHT work, but it
+ *     also MIGHT get hung up in an infinite loop saying
+ *     "waiting for delayed work...".  This will happen if the delayed work
+ *     you are trying to cancel has been put in the workqueue list, but can't
+ *     run yet because we are running that same workqueue thread right now.
+ *
+ *     Bottom line: If you need to call periodic_work_stop() from a workitem,
+ *     be sure the workitem is on a DIFFERENT workqueue than the workitem that
+ *     you are trying to cancel.
+ *
+ *     If I could figure out some way to check for this "no no" condition in
+ *     the code, I would.  It would have saved me the trouble of writing this
+ *     long comment.  And also, don't think this is some "theoretical" race
+ *     condition.  It is REAL, as I have spent the day chasing it.
+ *
+ *  NO NO #2
+ *
+ *     Take close note of the locks that you own when you call this function.
+ *     You must NOT own any locks that are needed by the periodic work
+ *     function that is currently installed.  If you DO, a deadlock may result,
+ *     because stopping the periodic work often involves waiting for the last
+ *     iteration of the periodic work function to complete.  Again, if you hit
+ *     this deadlock, you will get hung up in an infinite loop saying
+ *     "waiting for delayed work...".
+ */
+BOOL periodic_work_stop(PERIODIC_WORK *periodic_work)
+{
+	BOOL stopped_something = FALSE;
+
+	write_lock(&periodic_work->lock);
+	stopped_something = periodic_work->is_scheduled &&
+		(!periodic_work->want_to_stop);
+	while (periodic_work->is_scheduled) {
+		periodic_work->want_to_stop = TRUE;
+		if (cancel_delayed_work(&periodic_work->work)) {
+			/* We get here if the delayed work was pending as
+			 * delayed work, but was NOT run.
+			 */
+			ASSERT(periodic_work->is_scheduled);
+			periodic_work->is_scheduled = FALSE;
+		} else {
+			/* If we get here, either the delayed work:
+			 * - was run, OR,
+			 * - is running RIGHT NOW on another processor, OR,
+			 * - wasn't even scheduled (there is a miniscule
+			 *   timing window where this could be the case)
+			 * flush_workqueue() would make sure it is finished
+			 * executing, but that still isn't very useful, which
+			 * explains the loop...
+			 */
+		}
+		if (periodic_work->is_scheduled) {
+			write_unlock(&periodic_work->lock);
+			WARNDEV(periodic_work->devnam,
+				"waiting for delayed work...");
+			/* We rely on the delayed work function running here,
+			 * and eventually calling periodic_work_nextperiod(),
+			 * which will see that want_to_stop is set, and
+			 * subsequently clear is_scheduled.
+			 */
+			SLEEPJIFFIES(10);
+			write_lock(&periodic_work->lock);
+		} else
+			periodic_work->want_to_stop = FALSE;
+	}
+	write_unlock(&periodic_work->lock);
+	return stopped_something;
+}
+EXPORT_SYMBOL_GPL(periodic_work_stop);
Index: upstream-staging/drivers/staging/unisys/visorutil/procobjecttree.c
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/visorutil/procobjecttree.c
@@ -0,0 +1,334 @@
+/* procobjecttree.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include "procobjecttree.h"
+
+#define MYDRVNAME "procobjecttree"
+
+
+
+/** This is context info that we stash in each /proc file entry, which we
+ *  need in order to call the callback function that supplies the /proc read
+ *  info for that file.
+ */
+typedef struct {
+	void (*show_property)(struct seq_file *, void *, int);
+	MYPROCOBJECT *procObject;
+	int propertyIndex;
+
+} PROCDIRENTRYCONTEXT;
+
+/** This describes the attributes of a tree rooted at
+ *  <procDirRoot>/<name[0]>/<name[1]>/...
+ *  Properties for each object of this type will be located under
+ *  <procDirRoot>/<name[0]>/<name[1]>/.../<objectName>/<propertyName>.
+ */
+struct MYPROCTYPE_Tag {
+	const char **name;  /**< node names for this type, ending with NULL */
+	int nNames;         /**< num of node names in <name> */
+
+	/** root dir for this type tree in /proc */
+	struct proc_dir_entry *procDirRoot;
+
+	struct proc_dir_entry **procDirs;  /**< for each node in <name> */
+
+	/** bottom dir where objects will be rooted; i.e., this is
+	 *  <procDirRoot>/<name[0]>/<name[1]>/.../, which is the same as the
+	 *  last entry in the <procDirs> array. */
+	struct proc_dir_entry *procDir;
+
+	/** name for each property that objects of this type can have */
+	const char **propertyNames;
+
+	int nProperties;       /**< num of names in <propertyNames> */
+
+	/** Call this, passing MYPROCOBJECT.context and the property index
+	 *  whenever someone reads the proc entry */
+	void (*show_property)(struct seq_file *, void *, int);
+};
+
+
+
+struct MYPROCOBJECT_Tag {
+	MYPROCTYPE *type;
+
+	/** This is the name of the dir node in /proc under which the
+	 *  properties of this object will appear as files. */
+	char *name;
+
+	int namesize;   /**< number of bytes allocated for name */
+	void *context;  /**< passed to MYPROCTYPE.show_property */
+
+	/** <type.procDirRoot>/<type.name[0]>/<type.name[1]>/.../<name> */
+	struct proc_dir_entry *procDir;
+
+	/** a proc dir entry for each of the properties of the object;
+	 *  properties are identified in MYPROCTYPE.propertyNames, so each of
+	 *  the <procDirProperties> describes a single file like
+	 *  <type.procDirRoot>/<type.name[0]>/<type.name[1]>/...
+	 *           /<name>/<propertyName>
+	 */
+	struct proc_dir_entry **procDirProperties;
+
+	/** this is a holding area for the context information that is needed
+	 *  to run the /proc callback function */
+	PROCDIRENTRYCONTEXT *procDirPropertyContexts;
+};
+
+
+
+static struct proc_dir_entry *
+createProcDir(const char *name, struct proc_dir_entry *parent)
+{
+	struct proc_dir_entry *p = proc_mkdir_mode(name, S_IFDIR, parent);
+	if (p == NULL)
+		ERRDRV("failed to create /proc directory %s", name);
+	return p;
+}
+
+static struct proc_dir_entry *
+createProcFile(const char *name, struct proc_dir_entry *parent,
+	       const struct file_operations *fops, void *data)
+{
+	struct proc_dir_entry *p = proc_create_data(name, 0, parent,
+						    fops, data);
+	if (p == NULL)
+		ERRDRV("failed to create /proc file %s", name);
+	return p;
+}
+
+static int seq_show(struct seq_file *seq, void *offset);
+static int proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, seq_show, PDE_DATA(inode));
+}
+
+static const struct file_operations proc_fops = {
+	.open = proc_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+
+
+MYPROCTYPE *proc_CreateType(struct proc_dir_entry *procDirRoot,
+			    const char **name,
+			    const char **propertyNames,
+			    void (*show_property)(struct seq_file *,
+						  void *, int))
+{
+	int i = 0;
+	MYPROCTYPE *rc = NULL, *type = NULL;
+	struct proc_dir_entry *parent = NULL;
+
+	if (procDirRoot == NULL)
+		FAIL("procDirRoot cannot be NULL!", 0);
+	if (name == NULL || name[0] == NULL)
+		FAIL("name must contain at least 1 node name!", 0);
+	type = kmalloc(sizeof(MYPROCTYPE), GFP_KERNEL|__GFP_NORETRY);
+	if (type == NULL)
+		FAIL("out of memory", 0);
+	memset(type, 0, sizeof(MYPROCTYPE));
+	type->name = name;
+	type->propertyNames = propertyNames;
+	type->nProperties = 0;
+	type->nNames = 0;
+	type->show_property = show_property;
+	type->procDirRoot = procDirRoot;
+	if (type->propertyNames != 0)
+		while (type->propertyNames[type->nProperties] != NULL)
+			type->nProperties++;
+	while (type->name[type->nNames] != NULL)
+		type->nNames++;
+	type->procDirs = kmalloc((type->nNames+1)*
+				 sizeof(struct proc_dir_entry *),
+				 GFP_KERNEL|__GFP_NORETRY);
+	if (type->procDirs == NULL)
+		FAIL("out of memory", 0);
+	memset(type->procDirs, 0, (type->nNames + 1) *
+	       sizeof(struct proc_dir_entry *));
+	parent = procDirRoot;
+	for (i = 0; i < type->nNames; i++) {
+		type->procDirs[i] = createProcDir(type->name[i], parent);
+		if (type->procDirs[i] == NULL)
+			RETPTR(NULL);
+		parent = type->procDirs[i];
+	}
+	type->procDir = type->procDirs[type->nNames-1];
+	RETPTR(type);
+Away:
+	if (rc == NULL) {
+		if (type != NULL) {
+			proc_DestroyType(type);
+			type = NULL;
+		}
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(proc_CreateType);
+
+
+
+void proc_DestroyType(MYPROCTYPE *type)
+{
+	if (type == NULL)
+		return;
+	if (type->procDirs != NULL) {
+		int i = type->nNames-1;
+		while (i >= 0) {
+			if (type->procDirs[i] != NULL) {
+				struct proc_dir_entry *parent = NULL;
+				if (i == 0)
+					parent = type->procDirRoot;
+				else
+					parent = type->procDirs[i-1];
+				remove_proc_entry(type->name[i], parent);
+			}
+			i--;
+		}
+		kfree(type->procDirs);
+		type->procDirs = NULL;
+	}
+	kfree(type);
+}
+EXPORT_SYMBOL_GPL(proc_DestroyType);
+
+
+
+MYPROCOBJECT *proc_CreateObject(MYPROCTYPE *type,
+				const char *name, void *context)
+{
+	MYPROCOBJECT *obj = NULL, *rc = NULL;
+	int i = 0;
+
+	if (type == NULL)
+		FAIL("type cannot be NULL", 0);
+	obj = kmalloc(sizeof(MYPROCOBJECT), GFP_KERNEL | __GFP_NORETRY);
+	if (obj == NULL)
+		FAIL("out of memory", 0);
+	memset(obj, 0, sizeof(MYPROCOBJECT));
+	obj->type = type;
+	obj->context = context;
+	if (name == NULL) {
+		obj->name = NULL;
+		obj->procDir = type->procDir;
+	} else {
+		obj->namesize = strlen(name)+1;
+		obj->name = kmalloc(obj->namesize, GFP_KERNEL | __GFP_NORETRY);
+		if (obj->name == NULL) {
+			obj->namesize = 0;
+			FAIL("out of memory", 0);
+		}
+		strcpy(obj->name, name);
+		obj->procDir = createProcDir(obj->name, type->procDir);
+		if (obj->procDir == NULL)
+			RETPTR(NULL);
+	}
+	obj->procDirPropertyContexts =
+		kmalloc((type->nProperties+1)*sizeof(PROCDIRENTRYCONTEXT),
+			GFP_KERNEL|__GFP_NORETRY);
+	if (obj->procDirPropertyContexts == NULL)
+		FAIL("out of memory", 0);
+	memset(obj->procDirPropertyContexts, 0,
+	       (type->nProperties+1)*sizeof(PROCDIRENTRYCONTEXT));
+	obj->procDirProperties =
+		kmalloc((type->nProperties+1) * sizeof(struct proc_dir_entry *),
+			GFP_KERNEL|__GFP_NORETRY);
+	if (obj->procDirProperties == NULL)
+		FAIL("out of memory", 0);
+	memset(obj->procDirProperties, 0,
+	       (type->nProperties+1) * sizeof(struct proc_dir_entry *));
+	for (i = 0; i < type->nProperties; i++) {
+		obj->procDirPropertyContexts[i].procObject = obj;
+		obj->procDirPropertyContexts[i].propertyIndex = i;
+		obj->procDirPropertyContexts[i].show_property =
+			type->show_property;
+		if (type->propertyNames[i][0] != '\0') {
+			/* only create properties that have names */
+			obj->procDirProperties[i] =
+				createProcFile(type->propertyNames[i],
+					       obj->procDir, &proc_fops,
+					       &obj->procDirPropertyContexts[i]);
+			if (obj->procDirProperties[i] == NULL)
+				RETPTR(NULL);
+		}
+	}
+	RETPTR(obj);
+Away:
+	if (rc == NULL) {
+		if (obj != NULL) {
+			proc_DestroyObject(obj);
+			obj = NULL;
+		}
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(proc_CreateObject);
+
+
+
+void proc_DestroyObject(MYPROCOBJECT *obj)
+{
+	MYPROCTYPE *type = NULL;
+	if (obj == NULL)
+		return;
+	type = obj->type;
+	if (type == NULL)
+		return;
+	if (obj->procDirProperties != NULL) {
+		int i = 0;
+		for (i = 0; i < type->nProperties; i++) {
+			if (obj->procDirProperties[i] != NULL) {
+				remove_proc_entry(type->propertyNames[i],
+						  obj->procDir);
+				obj->procDirProperties[i] = NULL;
+			}
+		}
+		kfree(obj->procDirProperties);
+		obj->procDirProperties = NULL;
+	}
+	if (obj->procDirPropertyContexts != NULL) {
+		kfree(obj->procDirPropertyContexts);
+		obj->procDirPropertyContexts = NULL;
+	}
+	if (obj->procDir != NULL) {
+		if (obj->name != NULL)
+			remove_proc_entry(obj->name, type->procDir);
+		obj->procDir = NULL;
+	}
+	if (obj->name != NULL) {
+		kfree(obj->name);
+		obj->name = NULL;
+	}
+	kfree(obj);
+}
+EXPORT_SYMBOL_GPL(proc_DestroyObject);
+
+
+
+static int seq_show(struct seq_file *seq, void *offset)
+{
+	PROCDIRENTRYCONTEXT *ctx = (PROCDIRENTRYCONTEXT *)(seq->private);
+	if (ctx == NULL) {
+		ERRDRV("I don't have a freakin' clue...");
+		return 0;
+	}
+	(*ctx->show_property)(seq, ctx->procObject->context,
+			      ctx->propertyIndex);
+	return 0;
+}
Index: upstream-staging/drivers/staging/unisys/visorutil/visorkmodutils.c
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/visorutil/visorkmodutils.c
@@ -0,0 +1,721 @@
+/* timskmodutils.c
+ *
+ * Copyright © 2010 - 2013 UNISYS CORPORATION
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include "uniklog.h"
+#include "timskmod.h"
+
+#define MYDRVNAME "timskmodutils"
+
+BOOL Debug_Malloc_Enabled = FALSE;
+
+
+
+void myprintk(const char *myDrvName, const char *devname,
+	       const char *template, ...)
+{
+	va_list ap;
+	char temp[999];
+	char *ptemp = temp;
+	char pfx[20];
+	char msg[sizeof(pfx) + strlen(myDrvName) + 50];
+
+	if (myDrvName == NULL)
+		return;
+	temp[sizeof(temp)-1] = '\0';
+	pfx[0]               = '\0';
+	msg[0]               = '\0';
+	va_start(ap, template);
+	vsprintf(temp, template, ap);
+	va_end(ap);
+	if (temp[0] == '<') {
+		size_t i = 0;
+		for (i = 0; i < sizeof(pfx) - 1; i++) {
+			pfx[i] = temp[i];
+			if (pfx[i] == '>' || pfx[i] == '\0') {
+				if (pfx[i] == '>')
+					ptemp = temp+i+1;
+				i++;
+				break;
+			}
+		}
+		pfx[i] = '\0';
+	}
+	if (devname == NULL)
+		sprintf(msg, "%s%s: ", pfx, myDrvName);
+	else
+		sprintf(msg, "%s%s[%s]: ", pfx, myDrvName, devname);
+	printk(KERN_INFO "%s", msg);
+
+	/* The <prefix> applies up until the \n, so we should not include
+	 * it in these printks.  That's why we use <ptemp> to point to the
+	 * first char after the ">" in the prefix.
+	 */
+	printk(KERN_INFO "%s", ptemp);
+	printk("\n");
+
+}
+
+
+
+void myprintkx(const char *myDrvName, int devno, const char *template, ...)
+{
+	va_list ap;
+	char temp[999];
+	char *ptemp = temp;
+	char pfx[20];
+	char msg[sizeof(pfx) + strlen(myDrvName) + 50];
+
+	if (myDrvName == NULL)
+		return;
+	temp[sizeof(temp)-1] = '\0';
+	pfx[0]               = '\0';
+	msg[0]               = '\0';
+	va_start(ap, template);
+	vsprintf(temp, template, ap);
+	va_end(ap);
+	if (temp[0] == '<') {
+		size_t i = 0;
+		for (i = 0; i < sizeof(pfx) - 1; i++) {
+			pfx[i] = temp[i];
+			if (pfx[i] == '>' || pfx[i] == '\0') {
+				if (pfx[i] == '>')
+					ptemp = temp+i+1;
+				i++;
+				break;
+			}
+		}
+		pfx[i] = '\0';
+	}
+	if (devno < 0)
+		sprintf(msg, "%s%s: ", pfx, myDrvName);
+	else
+		sprintf(msg, "%s%s[%d]: ", pfx, myDrvName, devno);
+	printk(KERN_INFO "%s", msg);
+
+	/* The <prefix> applies up until the \n, so we should not include
+	 * it in these printks.  That's why we use <ptemp> to point to the
+	 * first char after the ">" in the prefix.
+	 */
+	printk(KERN_INFO "%s", ptemp);
+	printk("\n");
+}
+
+
+
+int hexDumpWordsToBuffer(char *dest,
+			 int destSize,
+			 char *prefix,
+			 uint32_t *src,
+			 int srcWords,
+			 int wordsToDumpPerLine)
+{
+	int i = 0;
+	int pos = 0;
+	char hex[(wordsToDumpPerLine * 9) + 1];
+	char *line = NULL;
+	int linesize = 1000;
+	int linelen = 0;
+	int currentlen = 0;
+	char emptystring[] = "";
+	char *pfx = prefix;
+	int baseaddr = 0;
+	int rc = 0;
+	uint8_t b1, b2, b3, b4;
+
+	line = vmalloc(linesize);
+	if (line == NULL)
+		RETINT(currentlen);
+
+	if (pfx == NULL || (strlen(pfx) > 50))
+		pfx = emptystring;
+	memset(hex, ' ', wordsToDumpPerLine * 9);
+	hex[wordsToDumpPerLine * 9] = '\0';
+	if (destSize > 0)
+		dest[0] = '\0';
+
+	for (i = 0; i < srcWords; i++) {
+		pos = i % wordsToDumpPerLine;
+		if ((pos == 0) && (i > 0)) {
+			hex[wordsToDumpPerLine * 9] = '\0';
+			linelen = sprintf(line, "%s%-6.6x %s\n", pfx,
+					  baseaddr, hex);
+			if ((currentlen) + (linelen) >= destSize)
+				RETINT(currentlen);
+			strcat(dest, line);
+			currentlen += linelen;
+			memset(hex, ' ', wordsToDumpPerLine * 9);
+			baseaddr = i * 4;
+		}
+		b1 = (uint8_t)((src[i] >> 24) & 0xff);
+		b2 = (uint8_t)((src[i] >> 16) & 0xff);
+		b3 = (uint8_t)((src[i] >>  8) & 0xff);
+		b4 = (uint8_t)((src[i]) & 0xff);
+		sprintf(hex + (pos * 9), "%-2.2x%-2.2x%-2.2x%-2.2x ",
+			b1, b2, b3, b4);
+		*(hex + (pos * 9) + 9) = ' ';  /* get rid of null */
+	}
+	pos = i%wordsToDumpPerLine;
+	if (i > 0) {
+		hex[wordsToDumpPerLine * 9] = '\0';
+		linelen = sprintf(line, "%s%-6.6x %s\n", pfx, baseaddr, hex);
+		if ((currentlen) + (linelen) >= destSize)
+			RETINT(currentlen);
+		strcat(dest, line);
+		currentlen += linelen;
+	}
+	RETINT(currentlen);
+
+Away:
+	if (line)
+		vfree(line);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(hexDumpWordsToBuffer);
+
+
+
+int myPrintkHexDump(char *myDrvName,
+		    char *devname,
+		    char *prefix,
+		    char *src,
+		    int srcLen,
+		    int bytesToDumpPerLine)
+{
+	int i = 0;
+	int pos = 0;
+	char printable[bytesToDumpPerLine + 1];
+	char hex[(bytesToDumpPerLine*3) + 1];
+	char *line = NULL;
+	int linesize = 1000;
+	int linelen = 0;
+	int currentlen = 0;
+	char emptystring[] = "";
+	char *pfx = prefix;
+	int baseaddr = 0;
+	int rc = 0;
+	int linecount = 0;
+
+	line = vmalloc(linesize);
+	if (line == NULL)
+		RETINT(currentlen);
+
+	if (pfx == NULL || (strlen(pfx) > 50))
+		pfx = emptystring;
+	memset(hex, ' ', bytesToDumpPerLine * 3);
+	hex[bytesToDumpPerLine * 3] = '\0';
+	memset(printable, ' ', bytesToDumpPerLine);
+	printable[bytesToDumpPerLine] = '\0';
+
+	for (i = 0; i < srcLen; i++) {
+		pos = i % bytesToDumpPerLine;
+		if ((pos == 0) && (i > 0)) {
+			hex[bytesToDumpPerLine*3] = '\0';
+			linelen = sprintf(line, "%s%-6.6x %s %s",
+					  pfx, baseaddr, hex, printable);
+			myprintk(myDrvName, devname, KERN_INFO "%s", line);
+			currentlen += linelen;
+			linecount++;
+			if ((linecount % 50) == 0)
+				SLEEPJIFFIES(10);
+			memset(hex, ' ', bytesToDumpPerLine*3);
+			memset(printable, ' ', bytesToDumpPerLine);
+			baseaddr = i;
+		}
+		sprintf(hex + (pos * 3), "%-2.2x ", (uint8_t)(src[i]));
+		*(hex + (pos * 3) + 3) = ' ';  /* get rid of null */
+		if (((uint8_t)(src[i]) >= ' ') && (uint8_t)(src[i]) < 127)
+			printable[pos] = src[i];
+		else
+			printable[pos] = '.';
+	}
+	pos = i%bytesToDumpPerLine;
+	if (i > 0) {
+		hex[bytesToDumpPerLine*3] = '\0';
+		linelen = sprintf(line, "%s%-6.6x %s %s",
+				  pfx, baseaddr, hex, printable);
+		myprintk(myDrvName, devname, KERN_INFO "%s", line);
+		currentlen += linelen;
+	}
+	RETINT(currentlen);
+
+Away:
+	if (line)
+		vfree(line);
+	return rc;
+}
+
+
+
+/** Given as input a number of seconds in #seconds, creates text describing
+    the time within #s.  Also breaks down the number of seconds into component
+    days, hours, minutes, and seconds, and stores to *#days, *#hours,
+    *#minutes, and *#secondsx.
+ *  @param seconds input number of seconds
+ *  @param days    points to a long value where the days component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param hours   points to a long value where the hours component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param minutes points to a long value where the minutes component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param secondsx points to a long value where the seconds component for the
+ *                 days+hours+minutes+seconds representation of #seconds will
+ *                 be stored
+ *  @param s       points to a character buffer where a text representation of
+ *		   the #seconds value will be stored.  This buffer MUST be
+ *		   large enough to hold the resulting string; to be safe it
+ *		   should be at least 100 bytes long.
+ */
+void expandSeconds(time_t seconds, long *days, long *hours, long *minutes,
+		   long *secondsx, char *s)
+{
+	BOOL started = FALSE;
+	char buf[99];
+
+	*days = seconds / (60*60*24);
+	seconds -= ((*days)*(60*60*24));
+	*hours = seconds / (60*60);
+	seconds -= ((*hours)*(60*60));
+	*minutes = seconds/60;
+	seconds -= ((*minutes)*60);
+	*secondsx = (long)seconds;
+	if (s == NULL)
+		RETVOID;
+	s[0] = '\0';
+	if (*days > 0) {
+		sprintf(buf, "%lu day", *days);
+		strcat(s, buf);
+		if (*days != 1)
+			strcat(s, "s");
+		started = TRUE;
+	}
+	if ((*hours > 0) || started) {
+		if (started)
+			strcat(s, ", ");
+		sprintf(buf, "%lu hour", *hours);
+		strcat(s, buf);
+		if (*hours != 1)
+			strcat(s, "s");
+		started = TRUE;
+	}
+	if ((*minutes > 0) || started) {
+		if (started)
+			strcat(s, ", ");
+		sprintf(buf, "%lu minute", *minutes);
+		strcat(s, buf);
+		if (*minutes != 1)
+			strcat(s, "s");
+		started = TRUE;
+	}
+	if (started)
+		strcat(s, ", ");
+	sprintf(buf, "%lu second", *secondsx);
+	strcat(s, buf);
+	if (*secondsx != 1)
+		strcat(s, "s");
+
+Away:
+	return;
+}
+
+
+
+/** Initialize a #MESSAGEQ for use (initially it will be empty, of course).
+ *  @param q               the #MESSAGEQ to initialize
+ *  @ingroup messageq
+ */
+void initMessageQ(MESSAGEQ *q)
+{
+	q->qHead = NULL;
+	q->qTail = NULL;
+	sema_init(&q->nQEntries, 0);   /* will block initially */
+	spin_lock_init(&q->queueLock);
+}
+
+
+
+/** Initialize #p with your data structure in #data,
+ *  so you can later place #p onto a #MESSAGEQ.
+ *  @param p               the queue entry that will house your data structure
+ *  @param data            a pointer to your data structure that you want
+ *                         to queue
+ *  @ingroup messageq
+ */
+void initMessageQEntry(MESSAGEQENTRY *p, void *data)
+{
+	p->data = data;
+	p->qNext = NULL;
+	p->qPrev = NULL;
+}
+
+
+
+MESSAGEQENTRY *dequeueMessageGuts(MESSAGEQ *q, BOOL canBlock)
+{
+	MESSAGEQENTRY *pEntry = NULL;
+	MESSAGEQENTRY *rc = NULL;
+	BOOL locked = FALSE;
+	ulong flags = 0;
+	int res = 0;
+
+	if (canBlock) {
+		/* wait for non-empty q */
+		res = down_interruptible(&q->nQEntries);
+		if (signal_pending(current)) {
+			DEBUGDRV("got signal in dequeueMessage");
+			RETPTR(NULL);
+		}
+	} else if (down_trylock(&q->nQEntries))
+		RETPTR(NULL);
+	spin_lock_irqsave(&q->queueLock, flags);
+	locked = TRUE;
+#ifdef PARANOID
+	if (q->qHead == NULL) {
+		HUHDRV("unexpected empty queue in getQueue");
+		RETPTR(NULL);
+	}
+#endif
+	pEntry = q->qHead;
+	if (pEntry == q->qTail) {
+		/* only 1 item in the queue */
+		q->qHead = NULL;
+		q->qTail = NULL;
+	} else {
+		q->qHead = pEntry->qNext;
+		q->qHead->qPrev = NULL;
+	}
+	RETPTR(pEntry);
+Away:
+	if (locked) {
+		spin_unlock_irqrestore(&q->queueLock, flags);
+		locked = FALSE;
+	}
+	return rc;
+}
+
+
+
+/** Remove the next message at the head of the FIFO queue, and return it.
+ *  Wait for the queue to become non-empty if it is empty when this
+ *  function is called.
+ *  @param q               the queue where the message is to be obtained from
+ *  @return                the queue entry obtained from the head of the
+ *                         FIFO queue, or NULL iff a signal was received
+ *                         while waiting for the queue to become non-empty
+ *  @ingroup messageq
+ */
+MESSAGEQENTRY *dequeueMessage(MESSAGEQ *q)
+{
+	return dequeueMessageGuts(q, TRUE);
+}
+
+
+
+/** Remove the next message at the head of the FIFO queue, and return it.
+ *  This function will never block (it returns NULL instead).
+ *  @param q               the queue where the message is to be obtained from
+ *  @return                the queue entry obtained from the head of the
+ *                         FIFO queue, or NULL iff the queue is empty.
+ *  @ingroup messageq
+ */
+MESSAGEQENTRY *dequeueMessageNoBlock(MESSAGEQ *q)
+{
+	return dequeueMessageGuts(q, FALSE);
+}
+
+
+
+/** Add an entry to a FIFO queue.
+ *  @param q               the queue where the entry is to be added
+ *  @param pEntry          the entry you want to add to the queue
+ *  @ingroup messageq
+ */
+void enqueueMessage(MESSAGEQ *q, MESSAGEQENTRY *pEntry)
+{
+	BOOL locked = FALSE;
+	ulong flags = 0;
+
+	spin_lock_irqsave(&q->queueLock, flags);
+	locked = TRUE;
+	if (q->qHead == NULL) {
+#ifdef PARANOID
+		if (q->qTail != NULL) {
+			HUHDRV("qHead/qTail not consistent");
+			RETVOID;
+		}
+#endif
+		q->qHead = pEntry;
+		q->qTail = pEntry;
+		pEntry->qNext = NULL;
+		pEntry->qPrev = NULL;
+	} else {
+#ifdef PARANOID
+		if (q->qTail == NULL) {
+			HUHDRV("qTail should not be NULL here");
+			RETVOID;
+		}
+#endif
+		q->qTail->qNext = pEntry;
+		pEntry->qPrev = q->qTail;
+		pEntry->qNext = NULL;
+		q->qTail = pEntry;
+	}
+	spin_unlock_irqrestore(&q->queueLock, flags);
+	locked = FALSE;
+	up(&q->nQEntries);
+	RETVOID;
+Away:
+	if (locked) {
+		spin_unlock_irqrestore(&q->queueLock, flags);
+		locked = FALSE;
+	}
+	return;
+}
+
+
+
+/** Return the number of entries in the queue.
+ *  @param q               the queue to be examined
+ *  @return                the number of entries on #q
+ *  @ingroup messageq
+ */
+size_t getQueueCount(MESSAGEQ *q)
+{
+	return (size_t)__sync_fetch_and_add(&(q->nQEntries.count), 0);
+}
+
+
+
+/** Return the number of processes waiting in a standard wait queue.
+ *  @param q               the pointer to the wait queue to be
+ *                         examined
+ *  @return                the number of waiters
+ *  @ingroup internal
+ */
+int waitQueueLen(wait_queue_head_t *q)
+{
+	struct list_head *x;
+	int count = 0;
+	list_for_each(x, &(q->task_list))
+		count++;
+	return count;
+}
+
+
+
+/** Display information about the processes on a standard wait queue.
+ *  @param q               the pointer to the wait queue to be
+ *                         examined
+ *  @ingroup internal
+ */
+void debugWaitQ(wait_queue_head_t *q)
+{
+	DEBUGDRV("task_list.next= %-8.8x",
+		 ((struct __wait_queue_head *)(q))->task_list.next);
+	DEBUGDRV("task_list.prev= %-8.8x",
+		 ((struct __wait_queue_head *)(q))->task_list.prev);
+}
+
+
+
+/** Print the hexadecimal contents of a data buffer to a supplied print buffer.
+ *  @param dest               the print buffer where text characters will
+ *			      be written
+ *  @param destSize           the maximum number of bytes that can be written
+ *			      to #dest
+ *  @param src                the buffer that contains the data that is to be
+ *			      hex-dumped
+ *  @param srcLen             the number of bytes at #src to be hex-dumped
+ *  @param bytesToDumpPerLine output will be formatted such that at most
+ *			      this many of the input data bytes will be
+ *			      represented on each line of output
+ *  @return                   the number of text characters written to #dest
+ *                            (not including the trailing '\0' byte)
+ *  @ingroup internal
+ */
+int hexDumpToBuffer(char *dest, int destSize, char *prefix, char *src,
+		    int srcLen, int bytesToDumpPerLine)
+{
+	int i = 0;
+	int pos = 0;
+	char printable[bytesToDumpPerLine + 1];
+	char hex[(bytesToDumpPerLine * 3) + 1];
+	char *line = NULL;
+	int linesize = 1000;
+	int linelen = 0;
+	int currentlen = 0;
+	char emptystring[] = "";
+	char *pfx = prefix;
+	int baseaddr = 0;
+	int rc = 0;
+
+	line = vmalloc(linesize);
+	if (line == NULL)
+		RETINT(currentlen);
+
+	if (pfx == NULL || (strlen(pfx) > 50))
+		pfx = emptystring;
+	memset(hex, ' ', bytesToDumpPerLine * 3);
+	hex[bytesToDumpPerLine * 3] = '\0';
+	memset(printable, ' ', bytesToDumpPerLine);
+	printable[bytesToDumpPerLine] = '\0';
+	if (destSize > 0)
+		dest[0] = '\0';
+
+	for (i = 0; i < srcLen; i++) {
+		pos = i % bytesToDumpPerLine;
+		if ((pos == 0) && (i > 0)) {
+			hex[bytesToDumpPerLine*3] = '\0';
+			linelen = sprintf(line, "%s%-6.6x %s %s\n", pfx,
+					  baseaddr, hex, printable);
+			if ((currentlen) + (linelen) >= destSize)
+				RETINT(currentlen);
+			strcat(dest, line);
+			currentlen += linelen;
+			memset(hex, ' ', bytesToDumpPerLine * 3);
+			memset(printable, ' ', bytesToDumpPerLine);
+			baseaddr = i;
+		}
+		sprintf(hex + (pos * 3), "%-2.2x ", (uint8_t)(src[i]));
+		*(hex + (pos * 3) + 3) = ' ';  /* get rid of null */
+		if (((uint8_t)(src[i]) >= ' ') && (uint8_t)(src[i]) < 127)
+			printable[pos] = src[i];
+		else
+			printable[pos] = '.';
+	}
+	pos = i%bytesToDumpPerLine;
+	if (i > 0) {
+		hex[bytesToDumpPerLine * 3] = '\0';
+		linelen = sprintf(line, "%s%-6.6x %s %s\n",
+				  pfx, baseaddr, hex, printable);
+		if ((currentlen) + (linelen) >= destSize)
+			RETINT(currentlen);
+		strcat(dest, line);
+		currentlen += linelen;
+	}
+	RETINT(currentlen);
+
+Away:
+	if (line)
+		vfree(line);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(hexDumpToBuffer);
+
+
+/** Callers to interfaces that set __GFP_NORETRY flag below
+ *  must check for a NULL (error) result as we are telling the
+ *  kernel interface that it is okay to fail.
+ */
+
+void *kmalloc_kernel(size_t siz)
+{
+	return kmalloc(siz, GFP_KERNEL | __GFP_NORETRY);
+}
+
+void *kmalloc_kernel_dma(size_t siz)
+{
+	return kmalloc(siz, GFP_KERNEL | __GFP_NORETRY|GFP_DMA);
+}
+
+void kfree_kernel(const void *p, size_t siz)
+{
+	kfree(p);
+}
+
+void *vmalloc_kernel(size_t siz)
+{
+	return vmalloc((unsigned long)(siz));
+}
+
+void vfree_kernel(const void *p, size_t siz)
+{
+	vfree((void *)(p));
+}
+
+void *pgalloc_kernel(size_t siz)
+{
+	return (void *)__get_free_pages(GFP_KERNEL|__GFP_NORETRY,
+				       get_order(siz));
+}
+
+void pgfree_kernel(const void *p, size_t siz)
+{
+	free_pages((ulong)(p), get_order(siz));
+}
+
+
+
+/*  Use these handy-dandy seq_file_xxx functions if you want to call some
+ *  functions that write stuff into a seq_file, but you actually just want
+ *  to dump that output into a buffer.  Use them as follows:
+ *  - call seq_file_new_buffer to create the seq_file (you supply the buf)
+ *  - call whatever functions you want that take a seq_file as an argument
+ *    (the buf you supplied will get the output data)
+ *  - call seq_file_done_buffer to dispose of your seq_file
+ */
+struct seq_file *seq_file_new_buffer(void *buf, size_t buf_size)
+{
+	struct seq_file *rc = NULL;
+	struct seq_file *m = kmalloc_kernel(sizeof(struct seq_file));
+
+	if (m == NULL)
+		RETPTR(NULL);
+	memset(m, 0, sizeof(struct seq_file));
+	m->buf = buf;
+	m->size = buf_size;
+	RETPTR(m);
+Away:
+	if (rc == NULL) {
+		seq_file_done_buffer(m);
+		m = NULL;
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(seq_file_new_buffer);
+
+
+
+void seq_file_done_buffer(struct seq_file *m)
+{
+	if (!m)
+		return;
+	kfree(m);
+}
+EXPORT_SYMBOL_GPL(seq_file_done_buffer);
+
+
+
+void seq_hexdump(struct seq_file *seq, u8 *pfx, void *buf, ulong nbytes)
+{
+	int fmtbufsize = 100 * COVQ(nbytes, 16);
+	char *fmtbuf = NULL;
+	int i = 0;
+	if (buf == NULL) {
+		seq_printf(seq, "%s<NULL>\n", pfx);
+		return;
+	}
+	fmtbuf = kmalloc_kernel(fmtbufsize);
+	if (fmtbuf == NULL)
+		return;
+	hexDumpToBuffer(fmtbuf, fmtbufsize, pfx, (char *)(buf), nbytes, 16);
+	for (i = 0; fmtbuf[i] != '\0'; i++)
+		seq_printf(seq, "%c", fmtbuf[i]);
+	kfree(fmtbuf);
+}
Index: upstream-staging/drivers/staging/unisys/Kconfig
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/Kconfig
@@ -0,0 +1,14 @@
+#
+# Unisys SPAR driver configuration
+#
+menuconfig UNISYSSPAR
+	bool "Unisys SPAR driver support"
+	depends on X86_64
+	---help---
+	Support for the Unisys SPAR drivers
+
+if UNISYSSPAR
+
+source "drivers/staging/unisys/visorutil/Kconfig"
+
+endif # UNISYSSPAR
Index: upstream-staging/drivers/staging/unisys/Makefile
===================================================================
--- /dev/null
+++ upstream-staging/drivers/staging/unisys/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for Unisys SPAR drivers
+#
+obj-$(CONFIG_UNISYS_VISORUTIL)		+= visorutil/
+

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux