aboutsummaryrefslogtreecommitdiff
path: root/drivers/mxc/amd-gpu/common/gsl_driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mxc/amd-gpu/common/gsl_driver.c')
-rw-r--r--drivers/mxc/amd-gpu/common/gsl_driver.c329
1 files changed, 329 insertions, 0 deletions
diff --git a/drivers/mxc/amd-gpu/common/gsl_driver.c b/drivers/mxc/amd-gpu/common/gsl_driver.c
new file mode 100644
index 00000000000..b8c5170a142
--- /dev/null
+++ b/drivers/mxc/amd-gpu/common/gsl_driver.c
@@ -0,0 +1,329 @@
+/* Copyright (c) 2008-2010, Advanced Micro Devices. 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 version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include "gsl.h"
+#include "gsl_hal.h"
+
+
+//////////////////////////////////////////////////////////////////////////////
+// defines
+//////////////////////////////////////////////////////////////////////////////
+#define GSL_PROCESSID_NONE 0x00000000
+
+#define GSL_DRVFLAGS_EXTERNAL 0x10000000
+#define GSL_DRVFLAGS_INTERNAL 0x20000000
+
+
+//////////////////////////////////////////////////////////////////////////////
+// globals
+//////////////////////////////////////////////////////////////////////////////
+#ifndef KGSL_USER_MODE
+static gsl_flags_t gsl_driver_initialized = 0;
+gsl_driver_t gsl_driver;
+#else
+extern gsl_flags_t gsl_driver_initialized;
+extern gsl_driver_t gsl_driver;
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////////
+// functions
+//////////////////////////////////////////////////////////////////////////////
+
+int
+kgsl_driver_init0(gsl_flags_t flags, gsl_flags_t flags_debug)
+{
+ int status = GSL_SUCCESS;
+
+ if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED0))
+ {
+#ifdef GSL_LOG
+ // Uncomment these to enable logging.
+ //kgsl_log_init();
+ //kgsl_log_open_stdout( KGSL_LOG_GROUP_ALL | KGSL_LOG_LEVEL_ALL | KGSL_LOG_TIMESTAMP
+ // | KGSL_LOG_THREAD_ID | KGSL_LOG_PROCESS_ID );
+ //kgsl_log_open_file( "c:\\kgsl_log.txt", KGSL_LOG_GROUP_ALL | KGSL_LOG_LEVEL_ALL | KGSL_LOG_TIMESTAMP
+ // | KGSL_LOG_THREAD_ID | KGSL_LOG_PROCESS_ID );
+#endif
+ kos_memset(&gsl_driver, 0, sizeof(gsl_driver_t));
+
+ GSL_API_MUTEX_CREATE();
+ }
+
+#ifdef _DEBUG
+ // set debug flags on every entry, and prior to hal initialization
+ gsl_driver.flags_debug |= flags_debug;
+#else
+ (void) flags_debug; // unref formal parameter
+#endif // _DEBUG
+
+
+ KGSL_DEBUG(GSL_DBGFLAGS_DUMPX,
+ {
+ KGSL_DEBUG_DUMPX_OPEN("dumpx.tb", 0);
+ KGSL_DEBUG_DUMPX( BB_DUMP_ENABLE, 0, 0, 0, " ");
+ });
+
+ KGSL_DEBUG_TBDUMP_OPEN("tbdump.txt");
+
+ if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED0))
+ {
+ GSL_API_MUTEX_LOCK();
+
+ // init hal
+ status = kgsl_hal_init();
+
+ if (status == GSL_SUCCESS)
+ {
+ gsl_driver_initialized |= flags;
+ gsl_driver_initialized |= GSL_FLAGS_INITIALIZED0;
+ }
+
+ GSL_API_MUTEX_UNLOCK();
+ }
+
+ return (status);
+}
+
+//----------------------------------------------------------------------------
+
+int
+kgsl_driver_close0(gsl_flags_t flags)
+{
+ int status = GSL_SUCCESS;
+
+ if ((gsl_driver_initialized & GSL_FLAGS_INITIALIZED0) && (gsl_driver_initialized & flags))
+ {
+ GSL_API_MUTEX_LOCK();
+
+ // close hall
+ status = kgsl_hal_close();
+
+ GSL_API_MUTEX_UNLOCK();
+
+ GSL_API_MUTEX_FREE();
+
+#ifdef GSL_LOG
+ kgsl_log_close();
+#endif
+
+ gsl_driver_initialized &= ~flags;
+ gsl_driver_initialized &= ~GSL_FLAGS_INITIALIZED0;
+
+ KGSL_DEBUG(GSL_DBGFLAGS_DUMPX,
+ {
+ KGSL_DEBUG_DUMPX_CLOSE();
+ });
+
+ KGSL_DEBUG_TBDUMP_CLOSE();
+ }
+
+ return (status);
+}
+
+//----------------------------------------------------------------------------
+
+KGSL_API int
+kgsl_driver_init()
+{
+ // only an external (platform specific device driver) component should call this
+
+ return(kgsl_driver_init0(GSL_DRVFLAGS_EXTERNAL, 0));
+}
+
+//----------------------------------------------------------------------------
+
+KGSL_API int
+kgsl_driver_close()
+{
+ // only an external (platform specific device driver) component should call this
+
+ return(kgsl_driver_close0(GSL_DRVFLAGS_EXTERNAL));
+}
+
+//----------------------------------------------------------------------------
+
+KGSL_API int
+kgsl_driver_entry(gsl_flags_t flags)
+{
+ int status = GSL_FAILURE;
+ int index, i;
+ unsigned int pid;
+
+ if (kgsl_driver_init0(GSL_DRVFLAGS_INTERNAL, flags) != GSL_SUCCESS)
+ {
+ return (GSL_FAILURE);
+ }
+
+ kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_driver_entry( gsl_flags_t flags=%d )\n", flags );
+
+ GSL_API_MUTEX_LOCK();
+
+ pid = GSL_CALLER_PROCESSID_GET();
+
+ // if caller process has not already opened access
+ status = kgsl_driver_getcallerprocessindex(pid, &index);
+ if (status != GSL_SUCCESS)
+ {
+ // then, add caller pid to process table
+ status = kgsl_driver_getcallerprocessindex(GSL_PROCESSID_NONE, &index);
+ if (status == GSL_SUCCESS)
+ {
+ gsl_driver.callerprocess[index] = pid;
+ gsl_driver.refcnt++;
+ }
+ }
+
+ if (status == GSL_SUCCESS)
+ {
+ if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED))
+ {
+ // init memory apertures
+ status = kgsl_sharedmem_init(&gsl_driver.shmem);
+ if (status == GSL_SUCCESS)
+ {
+ // init devices
+ status = GSL_FAILURE;
+ for (i = 0; i < GSL_DEVICE_MAX; i++)
+ {
+ if (kgsl_device_init(&gsl_driver.device[i], (gsl_deviceid_t)(i + 1)) == GSL_SUCCESS) {
+ status = GSL_SUCCESS;
+ }
+ }
+ }
+
+ if (status == GSL_SUCCESS)
+ {
+ gsl_driver_initialized |= GSL_FLAGS_INITIALIZED;
+ }
+ }
+
+ // walk through process attach callbacks
+ if (status == GSL_SUCCESS)
+ {
+ for (i = 0; i < GSL_DEVICE_MAX; i++)
+ {
+ status = kgsl_device_attachcallback(&gsl_driver.device[i], pid);
+ if (status != GSL_SUCCESS)
+ {
+ break;
+ }
+ }
+ }
+
+ // if something went wrong
+ if (status != GSL_SUCCESS)
+ {
+ // then, remove caller pid from process table
+ if (kgsl_driver_getcallerprocessindex(pid, &index) == GSL_SUCCESS)
+ {
+ gsl_driver.callerprocess[index] = GSL_PROCESSID_NONE;
+ gsl_driver.refcnt--;
+ }
+ }
+ }
+
+ GSL_API_MUTEX_UNLOCK();
+
+ kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_driver_entry. Return value: %B\n", status );
+
+ return (status);
+}
+
+//----------------------------------------------------------------------------
+
+int
+kgsl_driver_exit0(unsigned int pid)
+{
+ int status = GSL_SUCCESS;
+ int index, i;
+
+ GSL_API_MUTEX_LOCK();
+
+ if (gsl_driver_initialized & GSL_FLAGS_INITIALIZED)
+ {
+ if (kgsl_driver_getcallerprocessindex(pid, &index) == GSL_SUCCESS)
+ {
+ // walk through process detach callbacks
+ for (i = 0; i < GSL_DEVICE_MAX; i++)
+ {
+ // Empty the freememqueue of this device
+ kgsl_cmdstream_memqueue_drain(&gsl_driver.device[i]);
+
+ // Detach callback
+ status = kgsl_device_detachcallback(&gsl_driver.device[i], pid);
+ if (status != GSL_SUCCESS)
+ {
+ break;
+ }
+ }
+
+ // last running caller process
+ if (gsl_driver.refcnt - 1 == 0)
+ {
+ // close devices
+ for (i = 0; i < GSL_DEVICE_MAX; i++)
+ {
+ kgsl_device_close(&gsl_driver.device[i]);
+ }
+
+ // shutdown memory apertures
+ kgsl_sharedmem_close(&gsl_driver.shmem);
+
+ gsl_driver_initialized &= ~GSL_FLAGS_INITIALIZED;
+ }
+
+ // remove caller pid from process table
+ gsl_driver.callerprocess[index] = GSL_PROCESSID_NONE;
+ gsl_driver.refcnt--;
+ }
+ }
+
+ GSL_API_MUTEX_UNLOCK();
+
+ if (!(gsl_driver_initialized & GSL_FLAGS_INITIALIZED))
+ {
+ kgsl_driver_close0(GSL_DRVFLAGS_INTERNAL);
+ }
+
+ return (status);
+}
+
+//----------------------------------------------------------------------------
+
+KGSL_API int
+kgsl_driver_exit(void)
+{
+ int status;
+
+ kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_driver_exit()\n" );
+
+ status = kgsl_driver_exit0(GSL_CALLER_PROCESSID_GET());
+
+ kgsl_log_write( KGSL_LOG_GROUP_DRIVER | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_driver_exit(). Return value: %B\n", status );
+
+ return (status);
+}
+
+//----------------------------------------------------------------------------
+
+KGSL_API int
+kgsl_driver_destroy(unsigned int pid)
+{
+ return (kgsl_driver_exit0(pid));
+}