2002-10-25 01:07:56 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
2011-02-25 01:05:47 +03:00
|
|
|
// $Id$
|
2009-01-10 14:30:20 +03:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2017-01-13 00:39:04 +03:00
|
|
|
// Copyright (C) 2002-2017 The Bochs Project
|
2009-01-10 14:30:20 +03:00
|
|
|
//
|
|
|
|
// This library is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 2 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This library 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
|
|
|
|
// Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
// License along with this library; if not, write to the Free Software
|
2009-08-22 23:30:23 +04:00
|
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
2009-01-10 14:30:20 +03:00
|
|
|
//
|
2002-10-25 01:07:56 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// This file defines the plugin and plugin-device registration functions and
|
|
|
|
// the device registration functions. It handles dynamic loading of modules,
|
|
|
|
// using the LTDL library for cross-platform support.
|
|
|
|
//
|
|
|
|
// This file is based on the plugin.c file from plex86, but with significant
|
|
|
|
// changes to make it work in Bochs.
|
|
|
|
// Plex86 is Copyright (C) 1999-2000 The plex86 developers team
|
|
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#include "bochs.h"
|
2004-06-19 19:20:15 +04:00
|
|
|
#include "iodev/iodev.h"
|
2002-10-25 01:07:56 +04:00
|
|
|
#include "plugin.h"
|
|
|
|
|
|
|
|
#define LOG_THIS genlog->
|
|
|
|
|
2017-02-20 21:21:19 +03:00
|
|
|
#define PLUGIN_INIT_FMT_STRING "lib%s_LTX_plugin_init"
|
|
|
|
#define PLUGIN_FINI_FMT_STRING "lib%s_LTX_plugin_fini"
|
|
|
|
#define GUI_PLUGIN_INIT_FMT_STRING "lib%s_gui_plugin_init"
|
|
|
|
#define GUI_PLUGIN_FINI_FMT_STRING "lib%s_gui_plugin_fini"
|
|
|
|
#define SOUND_PLUGIN_INIT_FMT_STRING "lib%s_sound_plugin_init"
|
|
|
|
#define SOUND_PLUGIN_FINI_FMT_STRING "lib%s_sound_plugin_fini"
|
|
|
|
#define PLUGIN_PATH ""
|
2002-10-25 01:07:56 +04:00
|
|
|
|
|
|
|
#ifndef WIN32
|
2017-02-20 21:21:19 +03:00
|
|
|
#define PLUGIN_FILENAME_FORMAT "libbx_%s.so"
|
|
|
|
#define SOUND_PLUGIN_FILENAME_FORMAT "libbx_sound%s.so"
|
2002-10-25 01:07:56 +04:00
|
|
|
#else
|
2017-02-20 21:21:19 +03:00
|
|
|
#define PLUGIN_FILENAME_FORMAT "bx_%s.dll"
|
|
|
|
#define SOUND_PLUGIN_FILENAME_FORMAT "bx_sound%s.dll"
|
2002-10-25 01:07:56 +04:00
|
|
|
#endif
|
|
|
|
|
2013-12-29 12:45:28 +04:00
|
|
|
logfunctions *pluginlog;
|
|
|
|
|
2004-08-11 15:09:01 +04:00
|
|
|
extern "C" {
|
2002-10-25 01:07:56 +04:00
|
|
|
|
|
|
|
void (*pluginRegisterIRQ)(unsigned irq, const char* name) = 0;
|
|
|
|
void (*pluginUnregisterIRQ)(unsigned irq, const char* name) = 0;
|
|
|
|
|
|
|
|
void (*pluginSetHRQ)(unsigned val) = 0;
|
2008-02-16 01:05:43 +03:00
|
|
|
void (*pluginSetHRQHackCallback)(void (*callback)(void)) = 0;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
|
|
|
int (*pluginRegisterIOReadHandler)(void *thisPtr, ioReadHandler_t callback,
|
2003-07-31 16:04:48 +04:00
|
|
|
unsigned base, const char *name, Bit8u mask) = 0;
|
2002-10-25 01:07:56 +04:00
|
|
|
int (*pluginRegisterIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback,
|
2003-07-31 16:04:48 +04:00
|
|
|
unsigned base, const char *name, Bit8u mask) = 0;
|
2004-01-15 05:08:37 +03:00
|
|
|
int (*pluginUnregisterIOReadHandler)(void *thisPtr, ioReadHandler_t callback,
|
|
|
|
unsigned base, Bit8u mask) = 0;
|
|
|
|
int (*pluginUnregisterIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback,
|
|
|
|
unsigned base, Bit8u mask) = 0;
|
|
|
|
int (*pluginRegisterIOReadHandlerRange)(void *thisPtr, ioReadHandler_t callback,
|
|
|
|
unsigned base, unsigned end, const char *name, Bit8u mask) = 0;
|
|
|
|
int (*pluginRegisterIOWriteHandlerRange)(void *thisPtr, ioWriteHandler_t callback,
|
|
|
|
unsigned base, unsigned end, const char *name, Bit8u mask) = 0;
|
|
|
|
int (*pluginUnregisterIOReadHandlerRange)(void *thisPtr, ioReadHandler_t callback,
|
|
|
|
unsigned begin, unsigned end, Bit8u mask) = 0;
|
|
|
|
int (*pluginUnregisterIOWriteHandlerRange)(void *thisPtr, ioWriteHandler_t callback,
|
|
|
|
unsigned begin, unsigned end, Bit8u mask) = 0;
|
2002-10-25 01:07:56 +04:00
|
|
|
int (*pluginRegisterDefaultIOReadHandler)(void *thisPtr, ioReadHandler_t callback,
|
2003-07-31 16:04:48 +04:00
|
|
|
const char *name, Bit8u mask) = 0;
|
2002-10-25 01:07:56 +04:00
|
|
|
int (*pluginRegisterDefaultIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback,
|
2003-07-31 16:04:48 +04:00
|
|
|
const char *name, Bit8u mask) = 0;
|
2002-10-25 01:07:56 +04:00
|
|
|
int (*pluginRegisterTimer)(void *this_ptr, void (*funct)(void *),
|
2008-02-06 01:57:43 +03:00
|
|
|
Bit32u useconds, bx_bool continuous,
|
2004-01-20 00:43:50 +03:00
|
|
|
bx_bool active, const char* name) = 0;
|
|
|
|
void (*pluginActivateTimer)(unsigned id, Bit32u usec, bx_bool continuous) = 0;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
|
|
|
void (*pluginHRQHackCallback)(void);
|
|
|
|
unsigned pluginHRQ = 0;
|
|
|
|
|
|
|
|
plugin_t *plugins = NULL; /* Head of the linked list of plugins */
|
2003-05-02 16:22:48 +04:00
|
|
|
#if BX_PLUGINS
|
2002-10-25 01:07:56 +04:00
|
|
|
static void plugin_init_one(plugin_t *plugin);
|
2003-05-02 16:22:48 +04:00
|
|
|
#endif
|
2002-10-25 01:07:56 +04:00
|
|
|
|
|
|
|
device_t *devices = NULL; /* Head of the linked list of registered devices */
|
2012-01-13 21:04:47 +04:00
|
|
|
device_t *core_devices = NULL; /* Head of the linked list of registered core devices */
|
2002-10-25 01:07:56 +04:00
|
|
|
|
|
|
|
plugin_t *current_plugin_context = NULL;
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
/* Builtins declarations */
|
|
|
|
/************************************************************************/
|
|
|
|
|
2008-02-06 01:57:43 +03:00
|
|
|
static void
|
|
|
|
builtinRegisterIRQ(unsigned irq, const char* name)
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
pluginlog->panic("builtinRegisterIRQ called, no pic plugin loaded?");
|
|
|
|
#else
|
|
|
|
bx_devices.register_irq(irq, name);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2008-02-06 01:57:43 +03:00
|
|
|
static void
|
2002-10-25 01:07:56 +04:00
|
|
|
builtinUnregisterIRQ(unsigned irq, const char* name)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
pluginlog->panic("builtinUnregisterIRQ called, no pic plugin loaded?");
|
|
|
|
#else
|
|
|
|
bx_devices.unregister_irq(irq, name);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
builtinSetHRQ(unsigned val)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
pluginlog->panic("builtinSetHRQ called, no plugin loaded?");
|
|
|
|
#else
|
|
|
|
pluginHRQ = val;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2008-02-16 01:05:43 +03:00
|
|
|
builtinSetHRQHackCallback(void (*callback)(void))
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
pluginlog->panic("builtinSetHRQHackCallback called, no plugin loaded?");
|
|
|
|
#else
|
|
|
|
pluginHRQHackCallback = callback;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
builtinRegisterIOReadHandler(void *thisPtr, ioReadHandler_t callback,
|
2003-07-31 16:04:48 +04:00
|
|
|
unsigned base, const char *name, Bit8u mask)
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
2004-01-15 05:08:37 +03:00
|
|
|
int ret;
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_ASSERT(mask<8);
|
2004-01-15 05:08:37 +03:00
|
|
|
ret = bx_devices.register_io_read_handler (thisPtr, callback, base, name, mask);
|
2009-04-22 22:37:06 +04:00
|
|
|
pluginlog->ldebug("plugin %s registered I/O read address at %04x", name, base);
|
2004-01-15 05:08:37 +03:00
|
|
|
return ret;
|
2002-10-25 01:07:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
builtinRegisterIOWriteHandler(void *thisPtr, ioWriteHandler_t callback,
|
2003-07-31 16:04:48 +04:00
|
|
|
unsigned base, const char *name, Bit8u mask)
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
2004-01-15 05:08:37 +03:00
|
|
|
int ret;
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_ASSERT(mask<8);
|
2004-01-15 05:08:37 +03:00
|
|
|
ret = bx_devices.register_io_write_handler (thisPtr, callback, base, name, mask);
|
2002-10-25 01:07:56 +04:00
|
|
|
pluginlog->ldebug("plugin %s registered I/O write address at %04x", name, base);
|
2004-01-15 05:08:37 +03:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
builtinUnregisterIOReadHandler(void *thisPtr, ioReadHandler_t callback,
|
|
|
|
unsigned base, Bit8u mask)
|
|
|
|
{
|
|
|
|
int ret;
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_ASSERT(mask<8);
|
2004-01-15 05:08:37 +03:00
|
|
|
ret = bx_devices.unregister_io_read_handler (thisPtr, callback, base, mask);
|
|
|
|
pluginlog->ldebug("plugin unregistered I/O read address at %04x", base);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
builtinUnregisterIOWriteHandler(void *thisPtr, ioWriteHandler_t callback,
|
|
|
|
unsigned base, Bit8u mask)
|
|
|
|
{
|
|
|
|
int ret;
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_ASSERT(mask<8);
|
2004-01-15 05:08:37 +03:00
|
|
|
ret = bx_devices.unregister_io_write_handler (thisPtr, callback, base, mask);
|
|
|
|
pluginlog->ldebug("plugin unregistered I/O write address at %04x", base);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
builtinRegisterIOReadHandlerRange(void *thisPtr, ioReadHandler_t callback,
|
|
|
|
unsigned base, unsigned end, const char *name, Bit8u mask)
|
|
|
|
{
|
|
|
|
int ret;
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_ASSERT(mask<8);
|
2004-01-15 05:08:37 +03:00
|
|
|
ret = bx_devices.register_io_read_handler_range (thisPtr, callback, base, end, name, mask);
|
|
|
|
pluginlog->ldebug("plugin %s registered I/O read addresses %04x to %04x", name, base, end);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
builtinRegisterIOWriteHandlerRange(void *thisPtr, ioWriteHandler_t callback,
|
|
|
|
unsigned base, unsigned end, const char *name, Bit8u mask)
|
|
|
|
{
|
|
|
|
int ret;
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_ASSERT(mask<8);
|
2004-01-15 05:08:37 +03:00
|
|
|
ret = bx_devices.register_io_write_handler_range (thisPtr, callback, base, end, name, mask);
|
|
|
|
pluginlog->ldebug("plugin %s registered I/O write addresses %04x to %04x", name, base, end);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
builtinUnregisterIOReadHandlerRange(void *thisPtr, ioReadHandler_t callback,
|
|
|
|
unsigned begin, unsigned end, Bit8u mask)
|
|
|
|
{
|
|
|
|
int ret;
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_ASSERT(mask<8);
|
2004-01-15 05:08:37 +03:00
|
|
|
ret = bx_devices.unregister_io_read_handler_range (thisPtr, callback, begin, end, mask);
|
|
|
|
pluginlog->ldebug("plugin unregistered I/O read addresses %04x to %04x", begin, end);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
builtinUnregisterIOWriteHandlerRange(void *thisPtr, ioWriteHandler_t callback,
|
|
|
|
unsigned begin, unsigned end, Bit8u mask)
|
|
|
|
{
|
|
|
|
int ret;
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_ASSERT(mask<8);
|
2004-01-15 05:08:37 +03:00
|
|
|
ret = bx_devices.unregister_io_write_handler_range (thisPtr, callback, begin, end, mask);
|
|
|
|
pluginlog->ldebug("plugin unregistered I/O write addresses %04x to %04x", begin, end);
|
|
|
|
return ret;
|
2002-10-25 01:07:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
builtinRegisterDefaultIOReadHandler(void *thisPtr, ioReadHandler_t callback,
|
2003-07-31 16:04:48 +04:00
|
|
|
const char *name, Bit8u mask)
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_ASSERT(mask<8);
|
2003-07-31 16:04:48 +04:00
|
|
|
bx_devices.register_default_io_read_handler (thisPtr, callback, name, mask);
|
2002-10-25 01:07:56 +04:00
|
|
|
pluginlog->ldebug("plugin %s registered default I/O read ", name);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
builtinRegisterDefaultIOWriteHandler(void *thisPtr, ioWriteHandler_t callback,
|
2003-07-31 16:04:48 +04:00
|
|
|
const char *name, Bit8u mask)
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_ASSERT(mask<8);
|
2003-07-31 16:04:48 +04:00
|
|
|
bx_devices.register_default_io_write_handler (thisPtr, callback, name, mask);
|
2002-10-25 01:07:56 +04:00
|
|
|
pluginlog->ldebug("plugin %s registered default I/O write ", name);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
builtinRegisterTimer(void *this_ptr, void (*funct)(void *),
|
2008-02-06 01:57:43 +03:00
|
|
|
Bit32u useconds, bx_bool continuous,
|
2004-01-20 00:43:50 +03:00
|
|
|
bx_bool active, const char* name)
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
|
|
|
int id = bx_pc_system.register_timer (this_ptr, funct, useconds, continuous, active, name);
|
|
|
|
pluginlog->ldebug("plugin %s registered timer %d", name, id);
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2002-10-25 15:44:41 +04:00
|
|
|
builtinActivateTimer(unsigned id, Bit32u usec, bx_bool continuous)
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
|
|
|
bx_pc_system.activate_timer (id, usec, continuous);
|
|
|
|
pluginlog->ldebug("plugin activated timer %d", id);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if BX_PLUGINS
|
|
|
|
/************************************************************************/
|
|
|
|
/* Plugin initialization / deinitialization */
|
|
|
|
/************************************************************************/
|
|
|
|
|
2008-02-16 01:05:43 +03:00
|
|
|
void plugin_init_one(plugin_t *plugin)
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
2008-02-16 01:05:43 +03:00
|
|
|
/* initialize the plugin */
|
2017-01-28 12:52:09 +03:00
|
|
|
if (plugin->plugin_init(plugin, plugin->type))
|
2008-02-16 01:05:43 +03:00
|
|
|
{
|
|
|
|
pluginlog->info("Plugin initialization failed for %s", plugin->name);
|
|
|
|
plugin_abort();
|
|
|
|
}
|
2008-02-06 01:57:43 +03:00
|
|
|
|
2008-02-16 01:05:43 +03:00
|
|
|
plugin->initialized = 1;
|
2002-10-25 01:07:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-09-10 13:13:47 +04:00
|
|
|
plugin_t *plugin_unload(plugin_t *plugin)
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
2008-02-16 01:05:43 +03:00
|
|
|
plugin_t *dead_plug;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2008-02-16 01:05:43 +03:00
|
|
|
if (plugin->initialized)
|
|
|
|
plugin->plugin_fini();
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2013-12-30 00:04:16 +04:00
|
|
|
#if defined(WIN32)
|
2011-06-15 21:24:32 +04:00
|
|
|
FreeLibrary(plugin->handle);
|
|
|
|
#else
|
2008-02-16 01:05:43 +03:00
|
|
|
lt_dlclose(plugin->handle);
|
2011-06-15 21:24:32 +04:00
|
|
|
#endif
|
2008-02-16 01:05:43 +03:00
|
|
|
delete [] plugin->name;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2008-02-16 01:05:43 +03:00
|
|
|
dead_plug = plugin;
|
|
|
|
plugin = plugin->next;
|
2016-12-05 21:47:16 +03:00
|
|
|
delete dead_plug;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2008-02-16 01:05:43 +03:00
|
|
|
return plugin;
|
2002-10-25 01:07:56 +04:00
|
|
|
}
|
|
|
|
|
2017-01-13 21:09:51 +03:00
|
|
|
void plugin_load(char *name, plugintype_t type)
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
2009-01-01 15:06:31 +03:00
|
|
|
plugin_t *plugin, *temp;
|
2013-12-30 00:04:16 +04:00
|
|
|
#if defined(WIN32)
|
2013-11-16 15:24:51 +04:00
|
|
|
char dll_path_list[MAX_PATH];
|
2013-11-15 23:14:31 +04:00
|
|
|
#endif
|
2009-01-01 15:06:31 +03:00
|
|
|
|
|
|
|
if (plugins != NULL) {
|
|
|
|
temp = plugins;
|
|
|
|
|
|
|
|
while (temp != NULL) {
|
|
|
|
if (!strcmp(name, temp->name)) {
|
|
|
|
BX_PANIC(("plugin '%s' already loaded", name));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
temp = temp->next;
|
|
|
|
}
|
|
|
|
}
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2016-12-05 21:47:16 +03:00
|
|
|
plugin = new plugin_t;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2008-02-16 01:05:43 +03:00
|
|
|
plugin->type = type;
|
|
|
|
plugin->name = name;
|
|
|
|
plugin->initialized = 0;
|
|
|
|
|
2013-11-16 15:24:51 +04:00
|
|
|
char plugin_filename[BX_PATHNAME_LEN], tmpname[BX_PATHNAME_LEN];
|
2017-02-20 21:21:19 +03:00
|
|
|
if (type != PLUGTYPE_SOUND) {
|
|
|
|
sprintf(tmpname, PLUGIN_FILENAME_FORMAT, name);
|
|
|
|
} else {
|
|
|
|
sprintf(tmpname, SOUND_PLUGIN_FILENAME_FORMAT, name);
|
|
|
|
}
|
2013-11-16 15:24:51 +04:00
|
|
|
sprintf(plugin_filename, "%s%s", PLUGIN_PATH, tmpname);
|
2008-02-16 01:05:43 +03:00
|
|
|
|
|
|
|
// Set context so that any devices that the plugin registers will
|
|
|
|
// be able to see which plugin created them. The registration will
|
|
|
|
// be called from either dlopen (global constructors) or plugin_init.
|
|
|
|
BX_ASSERT(current_plugin_context == NULL);
|
|
|
|
current_plugin_context = plugin;
|
2013-12-30 00:04:16 +04:00
|
|
|
#if defined(WIN32)
|
2013-11-16 15:24:51 +04:00
|
|
|
char *ptr;
|
2011-06-15 21:24:32 +04:00
|
|
|
plugin->handle = LoadLibrary(plugin_filename);
|
2013-11-15 23:14:31 +04:00
|
|
|
if (!plugin->handle) {
|
2013-11-16 15:24:51 +04:00
|
|
|
if (GetEnvironmentVariable("LTDL_LIBRARY_PATH", dll_path_list, MAX_PATH)) {
|
|
|
|
ptr = strtok(dll_path_list, ";");
|
|
|
|
while ((ptr) && !plugin->handle) {
|
|
|
|
sprintf(plugin_filename, "%s\\%s", ptr, tmpname);
|
|
|
|
plugin->handle = LoadLibrary(plugin_filename);
|
|
|
|
ptr = strtok(NULL, ";");
|
|
|
|
}
|
2013-11-15 23:14:31 +04:00
|
|
|
}
|
|
|
|
}
|
2011-06-15 21:24:32 +04:00
|
|
|
BX_INFO(("DLL handle is %p", plugin->handle));
|
2013-11-15 23:14:31 +04:00
|
|
|
if (!plugin->handle) {
|
2011-06-15 21:24:32 +04:00
|
|
|
current_plugin_context = NULL;
|
2017-02-20 21:21:19 +03:00
|
|
|
BX_PANIC(("LoadLibrary failed for module '%s' (%s): error=%d", name,
|
|
|
|
plugin_filename, GetLastError()));
|
2016-12-05 21:47:16 +03:00
|
|
|
delete plugin;
|
2011-06-15 21:24:32 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
#else
|
2013-11-16 15:24:51 +04:00
|
|
|
plugin->handle = lt_dlopen(plugin_filename);
|
2008-02-16 01:05:43 +03:00
|
|
|
BX_INFO(("lt_dlhandle is %p", plugin->handle));
|
2013-11-16 15:24:51 +04:00
|
|
|
if (!plugin->handle) {
|
2008-02-16 01:05:43 +03:00
|
|
|
current_plugin_context = NULL;
|
2017-02-20 21:21:19 +03:00
|
|
|
BX_PANIC(("dlopen failed for module '%s' (%s): %s", name, plugin_filename,
|
|
|
|
lt_dlerror()));
|
2016-12-05 21:47:16 +03:00
|
|
|
delete plugin;
|
2008-02-16 01:05:43 +03:00
|
|
|
return;
|
|
|
|
}
|
2011-06-15 21:24:32 +04:00
|
|
|
#endif
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2017-02-18 19:28:04 +03:00
|
|
|
if (type == PLUGTYPE_GUI) {
|
|
|
|
sprintf(tmpname, GUI_PLUGIN_INIT_FMT_STRING, name);
|
2017-02-20 21:21:19 +03:00
|
|
|
} else if (type == PLUGTYPE_SOUND) {
|
|
|
|
sprintf(tmpname, SOUND_PLUGIN_INIT_FMT_STRING, name);
|
2017-02-18 19:28:04 +03:00
|
|
|
} else if (type != PLUGTYPE_USER) {
|
2013-11-16 15:24:51 +04:00
|
|
|
sprintf(tmpname, PLUGIN_INIT_FMT_STRING, name);
|
2009-01-01 15:06:31 +03:00
|
|
|
} else {
|
2013-11-16 15:24:51 +04:00
|
|
|
sprintf(tmpname, PLUGIN_INIT_FMT_STRING, "user");
|
2009-01-01 15:06:31 +03:00
|
|
|
}
|
2013-12-30 00:04:16 +04:00
|
|
|
#if defined(WIN32)
|
2013-11-16 15:24:51 +04:00
|
|
|
plugin->plugin_init = (plugin_init_t) GetProcAddress(plugin->handle, tmpname);
|
2011-06-15 21:24:32 +04:00
|
|
|
if (plugin->plugin_init == NULL) {
|
|
|
|
pluginlog->panic("could not find plugin_init: error=%d", GetLastError());
|
2013-11-16 15:24:51 +04:00
|
|
|
plugin_abort();
|
2011-06-15 21:24:32 +04:00
|
|
|
}
|
|
|
|
#else
|
2013-11-16 15:24:51 +04:00
|
|
|
plugin->plugin_init = (plugin_init_t) lt_dlsym(plugin->handle, tmpname);
|
2008-02-16 01:05:43 +03:00
|
|
|
if (plugin->plugin_init == NULL) {
|
2013-11-16 15:24:51 +04:00
|
|
|
pluginlog->panic("could not find plugin_init: %s", lt_dlerror());
|
|
|
|
plugin_abort();
|
2008-02-16 01:05:43 +03:00
|
|
|
}
|
2011-06-15 21:24:32 +04:00
|
|
|
#endif
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2017-02-18 19:28:04 +03:00
|
|
|
if (type == PLUGTYPE_GUI) {
|
|
|
|
sprintf(tmpname, GUI_PLUGIN_FINI_FMT_STRING, name);
|
2017-02-20 21:21:19 +03:00
|
|
|
} else if (type == PLUGTYPE_SOUND) {
|
|
|
|
sprintf(tmpname, SOUND_PLUGIN_FINI_FMT_STRING, name);
|
2017-02-18 19:28:04 +03:00
|
|
|
} else if (type != PLUGTYPE_USER) {
|
2013-11-16 15:24:51 +04:00
|
|
|
sprintf(tmpname, PLUGIN_FINI_FMT_STRING, name);
|
2009-01-01 15:06:31 +03:00
|
|
|
} else {
|
2013-11-16 15:24:51 +04:00
|
|
|
sprintf(tmpname, PLUGIN_FINI_FMT_STRING, "user");
|
2009-01-01 15:06:31 +03:00
|
|
|
}
|
2013-12-30 00:04:16 +04:00
|
|
|
#if defined(WIN32)
|
2013-11-16 15:24:51 +04:00
|
|
|
plugin->plugin_fini = (plugin_fini_t) GetProcAddress(plugin->handle, tmpname);
|
2011-06-15 21:24:32 +04:00
|
|
|
if (plugin->plugin_fini == NULL) {
|
|
|
|
pluginlog->panic("could not find plugin_fini: error=%d", GetLastError());
|
2013-11-16 15:24:51 +04:00
|
|
|
plugin_abort();
|
2011-06-15 21:24:32 +04:00
|
|
|
}
|
|
|
|
#else
|
2013-11-16 15:24:51 +04:00
|
|
|
plugin->plugin_fini = (plugin_fini_t) lt_dlsym(plugin->handle, tmpname);
|
2009-01-01 15:06:31 +03:00
|
|
|
if (plugin->plugin_fini == NULL) {
|
2013-11-16 15:24:51 +04:00
|
|
|
pluginlog->panic("could not find plugin_fini: %s", lt_dlerror());
|
2008-02-16 01:05:43 +03:00
|
|
|
plugin_abort();
|
|
|
|
}
|
2011-06-15 21:24:32 +04:00
|
|
|
#endif
|
2008-02-16 01:05:43 +03:00
|
|
|
pluginlog->info("loaded plugin %s",plugin_filename);
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2008-02-16 01:05:43 +03:00
|
|
|
/* Insert plugin at the _end_ of the plugin linked list. */
|
|
|
|
plugin->next = NULL;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2013-11-16 15:24:51 +04:00
|
|
|
if (!plugins) {
|
2008-02-16 01:05:43 +03:00
|
|
|
/* Empty list, this become the first entry. */
|
|
|
|
plugins = plugin;
|
2013-11-16 15:24:51 +04:00
|
|
|
} else {
|
2008-02-16 01:05:43 +03:00
|
|
|
/* Non-empty list. Add to end. */
|
2009-01-01 15:06:31 +03:00
|
|
|
temp = plugins;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2008-02-16 01:05:43 +03:00
|
|
|
while (temp->next)
|
|
|
|
temp = temp->next;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2008-02-16 01:05:43 +03:00
|
|
|
temp->next = plugin;
|
|
|
|
}
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2008-02-16 01:05:43 +03:00
|
|
|
plugin_init_one(plugin);
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2008-02-16 01:05:43 +03:00
|
|
|
// check that context didn't change. This should only happen if we
|
|
|
|
// need a reentrant plugin_load.
|
|
|
|
BX_ASSERT(current_plugin_context == plugin);
|
|
|
|
current_plugin_context = NULL;
|
2002-10-25 01:07:56 +04:00
|
|
|
}
|
|
|
|
|
2006-09-10 13:13:47 +04:00
|
|
|
void plugin_abort(void)
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
2008-02-16 01:05:43 +03:00
|
|
|
pluginlog->panic("plugin load aborted");
|
2002-10-25 01:07:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* end of #if BX_PLUGINS */
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
/* Plugin system: initialisation of plugins entry points */
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
|
|
void
|
|
|
|
plugin_startup(void)
|
|
|
|
{
|
|
|
|
pluginRegisterIRQ = builtinRegisterIRQ;
|
|
|
|
pluginUnregisterIRQ = builtinUnregisterIRQ;
|
|
|
|
|
|
|
|
pluginSetHRQHackCallback = builtinSetHRQHackCallback;
|
|
|
|
pluginSetHRQ = builtinSetHRQ;
|
2008-02-06 01:57:43 +03:00
|
|
|
|
2002-10-25 01:07:56 +04:00
|
|
|
pluginRegisterIOReadHandler = builtinRegisterIOReadHandler;
|
|
|
|
pluginRegisterIOWriteHandler = builtinRegisterIOWriteHandler;
|
2008-02-06 01:57:43 +03:00
|
|
|
|
2004-01-15 05:08:37 +03:00
|
|
|
pluginUnregisterIOReadHandler = builtinUnregisterIOReadHandler;
|
|
|
|
pluginUnregisterIOWriteHandler = builtinUnregisterIOWriteHandler;
|
2008-02-06 01:57:43 +03:00
|
|
|
|
2004-01-15 05:08:37 +03:00
|
|
|
pluginRegisterIOReadHandlerRange = builtinRegisterIOReadHandlerRange;
|
|
|
|
pluginRegisterIOWriteHandlerRange = builtinRegisterIOWriteHandlerRange;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2004-01-15 05:08:37 +03:00
|
|
|
pluginUnregisterIOReadHandlerRange = builtinUnregisterIOReadHandlerRange;
|
|
|
|
pluginUnregisterIOWriteHandlerRange = builtinUnregisterIOWriteHandlerRange;
|
2008-02-06 01:57:43 +03:00
|
|
|
|
2002-10-25 01:07:56 +04:00
|
|
|
pluginRegisterDefaultIOReadHandler = builtinRegisterDefaultIOReadHandler;
|
|
|
|
pluginRegisterDefaultIOWriteHandler = builtinRegisterDefaultIOWriteHandler;
|
|
|
|
|
|
|
|
pluginRegisterTimer = builtinRegisterTimer;
|
|
|
|
pluginActivateTimer = builtinActivateTimer;
|
|
|
|
|
2003-07-11 00:26:05 +04:00
|
|
|
pluginlog = new logfunctions();
|
2013-12-29 14:41:11 +04:00
|
|
|
pluginlog->put("PLUGIN");
|
2013-12-30 00:04:16 +04:00
|
|
|
#if BX_PLUGINS && !defined(WIN32)
|
2013-11-16 15:24:51 +04:00
|
|
|
int status = lt_dlinit();
|
2002-10-25 01:07:56 +04:00
|
|
|
if (status != 0) {
|
2013-11-16 15:24:51 +04:00
|
|
|
BX_ERROR(("initialization error in ltdl library (for loading plugins)"));
|
|
|
|
BX_PANIC(("error message was: %s", lt_dlerror()));
|
2002-10-25 01:07:56 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
/* Plugin system: Device registration */
|
|
|
|
/************************************************************************/
|
|
|
|
|
2007-10-25 03:29:40 +04:00
|
|
|
void pluginRegisterDeviceDevmodel(plugin_t *plugin, plugintype_t type, bx_devmodel_c *devmodel, const char *name)
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
2016-12-05 21:47:16 +03:00
|
|
|
device_t **devlist;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2016-12-05 21:47:16 +03:00
|
|
|
device_t *device = new device_t;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2008-02-16 01:05:43 +03:00
|
|
|
device->name = name;
|
|
|
|
BX_ASSERT(devmodel != NULL);
|
|
|
|
device->devmodel = devmodel;
|
|
|
|
device->plugin = plugin; // this can be NULL
|
|
|
|
device->next = NULL;
|
2012-01-13 21:04:47 +04:00
|
|
|
device->plugtype = type;
|
2008-02-16 01:05:43 +03:00
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case PLUGTYPE_CORE:
|
2012-01-13 21:04:47 +04:00
|
|
|
devlist = &core_devices;
|
|
|
|
break;
|
2012-01-10 21:45:18 +04:00
|
|
|
case PLUGTYPE_STANDARD:
|
2008-02-16 01:05:43 +03:00
|
|
|
case PLUGTYPE_OPTIONAL:
|
|
|
|
case PLUGTYPE_USER:
|
|
|
|
default:
|
2012-01-13 21:04:47 +04:00
|
|
|
devlist = &devices;
|
2008-02-16 01:05:43 +03:00
|
|
|
break;
|
|
|
|
}
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2012-01-13 21:04:47 +04:00
|
|
|
if (!*devlist) {
|
2008-02-16 01:05:43 +03:00
|
|
|
/* Empty list, this become the first entry. */
|
2012-01-13 21:04:47 +04:00
|
|
|
*devlist = device;
|
|
|
|
} else {
|
2008-02-16 01:05:43 +03:00
|
|
|
/* Non-empty list. Add to end. */
|
2012-01-13 21:04:47 +04:00
|
|
|
device_t *temp = *devlist;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2008-02-16 01:05:43 +03:00
|
|
|
while (temp->next)
|
|
|
|
temp = temp->next;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2008-02-16 01:05:43 +03:00
|
|
|
temp->next = device;
|
|
|
|
}
|
2002-10-25 01:07:56 +04:00
|
|
|
}
|
|
|
|
|
2009-01-05 00:46:20 +03:00
|
|
|
/************************************************************************/
|
|
|
|
/* Plugin system: Remove registered plugin device */
|
|
|
|
/************************************************************************/
|
|
|
|
|
2011-12-23 16:01:58 +04:00
|
|
|
void pluginUnregisterDeviceDevmodel(const char *name)
|
2009-01-05 00:46:20 +03:00
|
|
|
{
|
|
|
|
device_t *device, *prev = NULL;
|
|
|
|
|
|
|
|
for (device = devices; device; device = device->next) {
|
2011-12-23 16:01:58 +04:00
|
|
|
if (!strcmp(name, device->name)) {
|
2009-01-05 00:46:20 +03:00
|
|
|
if (prev == NULL) {
|
|
|
|
devices = device->next;
|
|
|
|
} else {
|
|
|
|
prev->next = device->next;
|
|
|
|
}
|
2016-12-05 21:47:16 +03:00
|
|
|
delete device;
|
2009-01-05 00:46:20 +03:00
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
prev = device;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-25 01:07:56 +04:00
|
|
|
/************************************************************************/
|
|
|
|
/* Plugin system: Check if a plugin is loaded */
|
|
|
|
/************************************************************************/
|
|
|
|
|
2011-12-23 16:01:58 +04:00
|
|
|
bx_bool pluginDevicePresent(const char *name)
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
2008-02-16 01:05:43 +03:00
|
|
|
device_t *device;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2008-02-16 01:05:43 +03:00
|
|
|
for (device = devices; device; device = device->next)
|
|
|
|
{
|
2011-12-23 16:01:58 +04:00
|
|
|
if (!strcmp(name, device->name)) return 1;
|
2008-02-16 01:05:43 +03:00
|
|
|
}
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2011-12-23 16:01:58 +04:00
|
|
|
return 0;
|
2002-10-25 01:07:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#if BX_PLUGINS
|
|
|
|
/************************************************************************/
|
|
|
|
/* Plugin system: Load one plugin */
|
|
|
|
/************************************************************************/
|
|
|
|
|
2009-01-05 00:46:20 +03:00
|
|
|
int bx_load_plugin(const char *name, plugintype_t type)
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
|
|
|
char *namecopy = new char[1+strlen(name)];
|
2006-09-10 13:13:47 +04:00
|
|
|
strcpy(namecopy, name);
|
2017-01-13 21:09:51 +03:00
|
|
|
plugin_load(namecopy, type);
|
2011-12-23 16:01:58 +04:00
|
|
|
return 1;
|
2002-10-25 01:07:56 +04:00
|
|
|
}
|
2006-09-10 13:13:47 +04:00
|
|
|
|
2009-01-05 00:46:20 +03:00
|
|
|
void bx_unload_plugin(const char *name, bx_bool devflag)
|
2006-09-10 13:13:47 +04:00
|
|
|
{
|
|
|
|
plugin_t *plugin, *prev = NULL;
|
|
|
|
|
|
|
|
for (plugin = plugins; plugin; plugin = plugin->next) {
|
|
|
|
if (!strcmp(plugin->name, name)) {
|
2009-01-05 00:46:20 +03:00
|
|
|
if (devflag) {
|
2011-12-23 16:01:58 +04:00
|
|
|
pluginUnregisterDeviceDevmodel(plugin->name);
|
2009-01-05 00:46:20 +03:00
|
|
|
}
|
2006-09-10 13:13:47 +04:00
|
|
|
plugin = plugin_unload(plugin);
|
|
|
|
if (prev == NULL) {
|
|
|
|
plugins = plugin;
|
|
|
|
} else {
|
|
|
|
prev->next = plugin;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
prev = plugin;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-25 01:07:56 +04:00
|
|
|
#endif /* end of #if BX_PLUGINS */
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/* Plugin system: Execute init function of all registered plugin-devices */
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
void bx_init_plugins()
|
|
|
|
{
|
2008-02-16 01:05:43 +03:00
|
|
|
device_t *device;
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2012-01-13 21:04:47 +04:00
|
|
|
for (device = core_devices; device; device = device->next) {
|
|
|
|
pluginlog->info("init_dev of '%s' plugin device by virtual method",device->name);
|
|
|
|
device->devmodel->init();
|
|
|
|
}
|
2009-01-05 00:46:20 +03:00
|
|
|
for (device = devices; device; device = device->next) {
|
2012-01-10 21:45:18 +04:00
|
|
|
if (device->plugtype == PLUGTYPE_STANDARD) {
|
2009-01-05 00:46:20 +03:00
|
|
|
pluginlog->info("init_dev of '%s' plugin device by virtual method",device->name);
|
|
|
|
device->devmodel->init();
|
|
|
|
}
|
2008-02-16 01:05:43 +03:00
|
|
|
}
|
2009-01-05 00:46:20 +03:00
|
|
|
for (device = devices; device; device = device->next) {
|
2012-01-10 21:45:18 +04:00
|
|
|
if (device->plugtype == PLUGTYPE_OPTIONAL) {
|
2009-01-05 00:46:20 +03:00
|
|
|
pluginlog->info("init_dev of '%s' plugin device by virtual method",device->name);
|
|
|
|
device->devmodel->init();
|
|
|
|
}
|
|
|
|
}
|
2012-01-10 21:45:18 +04:00
|
|
|
#if BX_PLUGINS
|
2009-01-05 00:46:20 +03:00
|
|
|
for (device = devices; device; device = device->next) {
|
2012-01-10 21:45:18 +04:00
|
|
|
if (device->plugtype == PLUGTYPE_USER) {
|
|
|
|
pluginlog->info("init_dev of '%s' plugin device by virtual method",device->name);
|
|
|
|
device->devmodel->init();
|
|
|
|
}
|
2008-02-16 01:05:43 +03:00
|
|
|
}
|
2009-01-05 00:46:20 +03:00
|
|
|
#endif
|
2002-10-25 01:07:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************/
|
|
|
|
/* Plugin system: Execute reset function of all registered plugin-devices */
|
|
|
|
/**************************************************************************/
|
|
|
|
|
|
|
|
void bx_reset_plugins(unsigned signal)
|
|
|
|
{
|
2008-02-16 01:05:43 +03:00
|
|
|
device_t *device;
|
2009-01-05 00:46:20 +03:00
|
|
|
|
2012-01-13 21:04:47 +04:00
|
|
|
for (device = core_devices; device; device = device->next) {
|
|
|
|
pluginlog->info("reset of '%s' plugin device by virtual method",device->name);
|
|
|
|
device->devmodel->reset(signal);
|
|
|
|
}
|
2009-01-05 00:46:20 +03:00
|
|
|
for (device = devices; device; device = device->next) {
|
2012-01-10 21:45:18 +04:00
|
|
|
if (device->plugtype == PLUGTYPE_STANDARD) {
|
2009-01-05 00:46:20 +03:00
|
|
|
pluginlog->info("reset of '%s' plugin device by virtual method",device->name);
|
|
|
|
device->devmodel->reset(signal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (device = devices; device; device = device->next) {
|
2012-01-10 21:45:18 +04:00
|
|
|
if (device->plugtype == PLUGTYPE_OPTIONAL) {
|
2009-01-05 00:46:20 +03:00
|
|
|
pluginlog->info("reset of '%s' plugin device by virtual method",device->name);
|
|
|
|
device->devmodel->reset(signal);
|
|
|
|
}
|
|
|
|
}
|
2012-01-10 21:45:18 +04:00
|
|
|
#if BX_PLUGINS
|
2009-01-05 00:46:20 +03:00
|
|
|
for (device = devices; device; device = device->next) {
|
2012-01-10 21:45:18 +04:00
|
|
|
if (device->plugtype == PLUGTYPE_USER) {
|
|
|
|
pluginlog->info("reset of '%s' plugin device by virtual method",device->name);
|
|
|
|
device->devmodel->reset(signal);
|
|
|
|
}
|
2008-02-16 01:05:43 +03:00
|
|
|
}
|
2009-01-05 00:46:20 +03:00
|
|
|
#endif
|
2002-10-25 01:07:56 +04:00
|
|
|
}
|
2004-08-11 15:09:01 +04:00
|
|
|
|
2006-09-10 13:13:47 +04:00
|
|
|
/*******************************************************/
|
|
|
|
/* Plugin system: Unload all registered plugin-devices */
|
|
|
|
/*******************************************************/
|
|
|
|
|
|
|
|
void bx_unload_plugins()
|
|
|
|
{
|
|
|
|
device_t *device, *next;
|
|
|
|
|
|
|
|
device = devices;
|
2006-09-12 17:05:07 +04:00
|
|
|
while (device != NULL) {
|
2006-09-10 13:13:47 +04:00
|
|
|
if (device->plugin != NULL) {
|
|
|
|
#if BX_PLUGINS
|
2009-01-05 00:46:20 +03:00
|
|
|
bx_unload_plugin(device->name, 0);
|
2006-09-10 13:13:47 +04:00
|
|
|
#endif
|
|
|
|
} else {
|
2011-12-23 16:01:58 +04:00
|
|
|
#if !BX_PLUGINS
|
2011-12-25 12:52:34 +04:00
|
|
|
if (!bx_unload_opt_plugin(device->name, 0)) {
|
2011-12-23 16:01:58 +04:00
|
|
|
delete device->devmodel;
|
|
|
|
}
|
|
|
|
#endif
|
2006-09-10 13:13:47 +04:00
|
|
|
}
|
|
|
|
next = device->next;
|
2016-12-05 21:47:16 +03:00
|
|
|
delete device;
|
2006-09-10 13:13:47 +04:00
|
|
|
device = next;
|
2008-02-16 01:05:43 +03:00
|
|
|
}
|
2006-09-10 13:13:47 +04:00
|
|
|
devices = NULL;
|
|
|
|
}
|
|
|
|
|
2012-02-12 12:37:42 +04:00
|
|
|
void bx_unload_core_plugins()
|
|
|
|
{
|
|
|
|
device_t *device, *next;
|
|
|
|
|
|
|
|
device = core_devices;
|
|
|
|
while (device != NULL) {
|
|
|
|
if (device->plugin != NULL) {
|
|
|
|
#if BX_PLUGINS
|
|
|
|
bx_unload_plugin(device->name, 0);
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
delete device->devmodel;
|
|
|
|
}
|
|
|
|
next = device->next;
|
2016-12-05 21:47:16 +03:00
|
|
|
delete device;
|
2012-02-12 12:37:42 +04:00
|
|
|
device = next;
|
|
|
|
}
|
|
|
|
core_devices = NULL;
|
|
|
|
}
|
|
|
|
|
2006-04-15 21:03:59 +04:00
|
|
|
/**************************************************************************/
|
|
|
|
/* Plugin system: Register device state of all registered plugin-devices */
|
|
|
|
/**************************************************************************/
|
|
|
|
|
|
|
|
void bx_plugins_register_state()
|
|
|
|
{
|
2008-02-16 01:05:43 +03:00
|
|
|
device_t *device;
|
2009-01-05 00:46:20 +03:00
|
|
|
|
2012-01-13 21:04:47 +04:00
|
|
|
for (device = core_devices; device; device = device->next) {
|
|
|
|
pluginlog->info("register state of '%s' plugin device by virtual method",device->name);
|
|
|
|
device->devmodel->register_state();
|
|
|
|
}
|
2009-01-05 00:46:20 +03:00
|
|
|
for (device = devices; device; device = device->next) {
|
2008-02-16 01:05:43 +03:00
|
|
|
pluginlog->info("register state of '%s' plugin device by virtual method",device->name);
|
|
|
|
device->devmodel->register_state();
|
|
|
|
}
|
2006-04-15 21:03:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************/
|
|
|
|
/* Plugin system: Execute code after restoring state of all plugin devices */
|
|
|
|
/***************************************************************************/
|
|
|
|
|
|
|
|
void bx_plugins_after_restore_state()
|
|
|
|
{
|
2008-02-16 01:05:43 +03:00
|
|
|
device_t *device;
|
2009-01-05 00:46:20 +03:00
|
|
|
|
2012-01-13 21:04:47 +04:00
|
|
|
for (device = core_devices; device; device = device->next) {
|
|
|
|
device->devmodel->after_restore_state();
|
|
|
|
}
|
2009-01-05 00:46:20 +03:00
|
|
|
for (device = devices; device; device = device->next) {
|
2012-01-10 21:45:18 +04:00
|
|
|
if (device->plugtype == PLUGTYPE_STANDARD) {
|
2009-01-05 00:46:20 +03:00
|
|
|
device->devmodel->after_restore_state();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (device = devices; device; device = device->next) {
|
2012-01-10 21:45:18 +04:00
|
|
|
if (device->plugtype == PLUGTYPE_OPTIONAL) {
|
2009-01-05 00:46:20 +03:00
|
|
|
device->devmodel->after_restore_state();
|
|
|
|
}
|
|
|
|
}
|
2012-01-10 21:45:18 +04:00
|
|
|
#if BX_PLUGINS
|
2009-01-05 00:46:20 +03:00
|
|
|
for (device = devices; device; device = device->next) {
|
2012-01-10 21:45:18 +04:00
|
|
|
if (device->plugtype == PLUGTYPE_USER) {
|
|
|
|
device->devmodel->after_restore_state();
|
|
|
|
}
|
2008-02-16 01:05:43 +03:00
|
|
|
}
|
2009-01-05 00:46:20 +03:00
|
|
|
#endif
|
2006-04-15 21:03:59 +04:00
|
|
|
}
|
|
|
|
|
2011-12-22 14:35:49 +04:00
|
|
|
#if !BX_PLUGINS
|
|
|
|
|
2017-02-18 19:28:04 +03:00
|
|
|
// special code for loading gui & optional plugins when plugins are turned off
|
2011-12-22 14:35:49 +04:00
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
const char *name;
|
|
|
|
plugin_init_t plugin_init;
|
2011-12-23 16:01:58 +04:00
|
|
|
plugin_fini_t plugin_fini;
|
|
|
|
bx_bool status;
|
2011-12-22 14:35:49 +04:00
|
|
|
} builtin_plugin_t;
|
|
|
|
|
2017-02-18 19:28:04 +03:00
|
|
|
#define BUILTIN_GUI_PLUGIN_ENTRY(mod) {#mod, lib##mod##_gui_plugin_init, lib##mod##_gui_plugin_fini, 0}
|
2011-12-22 14:35:49 +04:00
|
|
|
|
2017-02-18 19:28:04 +03:00
|
|
|
static builtin_plugin_t builtin_gui_plugins[] = {
|
2017-01-13 00:39:04 +03:00
|
|
|
#if BX_WITH_AMIGAOS
|
2017-02-18 19:28:04 +03:00
|
|
|
BUILTIN_GUI_PLUGIN_ENTRY(amigaos),
|
2017-01-13 00:39:04 +03:00
|
|
|
#endif
|
|
|
|
#if BX_WITH_CARBON
|
2017-02-18 19:28:04 +03:00
|
|
|
BUILTIN_GUI_PLUGIN_ENTRY(carbon),
|
2017-01-13 00:39:04 +03:00
|
|
|
#endif
|
|
|
|
#if BX_WITH_MACOS
|
2017-02-18 19:28:04 +03:00
|
|
|
BUILTIN_GUI_PLUGIN_ENTRY(macos),
|
2017-01-13 00:39:04 +03:00
|
|
|
#endif
|
|
|
|
#if BX_WITH_NOGUI
|
2017-02-18 19:28:04 +03:00
|
|
|
BUILTIN_GUI_PLUGIN_ENTRY(nogui),
|
2017-01-13 00:39:04 +03:00
|
|
|
#endif
|
|
|
|
#if BX_WITH_RFB
|
2017-02-18 19:28:04 +03:00
|
|
|
BUILTIN_GUI_PLUGIN_ENTRY(rfb),
|
2017-01-13 00:39:04 +03:00
|
|
|
#endif
|
|
|
|
#if BX_WITH_SDL
|
2017-02-18 19:28:04 +03:00
|
|
|
BUILTIN_GUI_PLUGIN_ENTRY(sdl),
|
2017-01-13 00:39:04 +03:00
|
|
|
#endif
|
|
|
|
#if BX_WITH_SDL2
|
2017-02-18 19:28:04 +03:00
|
|
|
BUILTIN_GUI_PLUGIN_ENTRY(sdl2),
|
2017-01-13 00:39:04 +03:00
|
|
|
#endif
|
|
|
|
#if BX_WITH_SVGA
|
2017-02-18 19:28:04 +03:00
|
|
|
BUILTIN_GUI_PLUGIN_ENTRY(svga),
|
2017-01-13 00:39:04 +03:00
|
|
|
#endif
|
|
|
|
#if BX_WITH_TERM
|
2017-02-18 19:28:04 +03:00
|
|
|
BUILTIN_GUI_PLUGIN_ENTRY(term),
|
2017-01-13 00:39:04 +03:00
|
|
|
#endif
|
|
|
|
#if BX_WITH_VNCSRV
|
2017-02-18 19:28:04 +03:00
|
|
|
BUILTIN_GUI_PLUGIN_ENTRY(vncsrv),
|
2017-01-13 00:39:04 +03:00
|
|
|
#endif
|
|
|
|
#if BX_WITH_WIN32
|
2017-02-18 19:28:04 +03:00
|
|
|
BUILTIN_GUI_PLUGIN_ENTRY(win32),
|
2017-01-13 00:39:04 +03:00
|
|
|
#endif
|
2017-02-18 19:56:19 +03:00
|
|
|
#if BX_WITH_WX
|
|
|
|
BUILTIN_GUI_PLUGIN_ENTRY(wx),
|
|
|
|
#endif
|
2017-01-13 00:39:04 +03:00
|
|
|
#if BX_WITH_X11
|
2017-02-18 19:28:04 +03:00
|
|
|
BUILTIN_GUI_PLUGIN_ENTRY(x),
|
2017-01-13 00:39:04 +03:00
|
|
|
#endif
|
2017-02-18 19:28:04 +03:00
|
|
|
{"NULL", NULL, NULL, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
int bx_load_gui_plugin(const char *name)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
while (strcmp(builtin_gui_plugins[i].name, "NULL")) {
|
|
|
|
if (!strcmp(name, builtin_gui_plugins[i].name)) {
|
|
|
|
if (builtin_gui_plugins[i].status == 0) {
|
|
|
|
builtin_gui_plugins[i].plugin_init(NULL, PLUGTYPE_GUI);
|
|
|
|
builtin_gui_plugins[i].status = 1;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
};
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define BUILTIN_PLUGIN_ENTRY(mod) {#mod, lib##mod##_LTX_plugin_init, lib##mod##_LTX_plugin_fini, 0}
|
|
|
|
|
|
|
|
static builtin_plugin_t builtin_opt_plugins[] = {
|
|
|
|
BUILTIN_PLUGIN_ENTRY(unmapped),
|
|
|
|
BUILTIN_PLUGIN_ENTRY(biosdev),
|
|
|
|
BUILTIN_PLUGIN_ENTRY(speaker),
|
|
|
|
BUILTIN_PLUGIN_ENTRY(extfpuirq),
|
|
|
|
BUILTIN_PLUGIN_ENTRY(parallel),
|
|
|
|
BUILTIN_PLUGIN_ENTRY(serial),
|
2017-01-13 00:39:04 +03:00
|
|
|
#if BX_SUPPORT_BUSMOUSE
|
|
|
|
BUILTIN_PLUGIN_ENTRY(busmouse),
|
|
|
|
#endif
|
2012-01-12 22:03:20 +04:00
|
|
|
#if BX_SUPPORT_E1000
|
|
|
|
BUILTIN_PLUGIN_ENTRY(e1000),
|
|
|
|
#endif
|
|
|
|
#if BX_SUPPORT_ES1370
|
|
|
|
BUILTIN_PLUGIN_ENTRY(es1370),
|
|
|
|
#endif
|
2011-12-22 14:35:49 +04:00
|
|
|
#if BX_SUPPORT_GAMEPORT
|
|
|
|
BUILTIN_PLUGIN_ENTRY(gameport),
|
|
|
|
#endif
|
|
|
|
#if BX_SUPPORT_IODEBUG
|
|
|
|
BUILTIN_PLUGIN_ENTRY(iodebug),
|
|
|
|
#endif
|
2012-01-12 22:03:20 +04:00
|
|
|
#if BX_SUPPORT_NE2K
|
|
|
|
BUILTIN_PLUGIN_ENTRY(ne2k),
|
2012-01-07 18:14:53 +04:00
|
|
|
#endif
|
2012-01-09 21:15:03 +04:00
|
|
|
#if BX_SUPPORT_PCIDEV
|
|
|
|
BUILTIN_PLUGIN_ENTRY(pcidev),
|
|
|
|
#endif
|
|
|
|
#if BX_SUPPORT_PCIPNIC
|
|
|
|
BUILTIN_PLUGIN_ENTRY(pcipnic),
|
|
|
|
#endif
|
2012-01-12 22:03:20 +04:00
|
|
|
#if BX_SUPPORT_SB16
|
|
|
|
BUILTIN_PLUGIN_ENTRY(sb16),
|
|
|
|
#endif
|
2015-12-06 23:03:42 +03:00
|
|
|
#if BX_SUPPORT_USB_UHCI
|
|
|
|
BUILTIN_PLUGIN_ENTRY(usb_uhci),
|
|
|
|
#endif
|
2012-01-08 16:43:46 +04:00
|
|
|
#if BX_SUPPORT_USB_OHCI
|
|
|
|
BUILTIN_PLUGIN_ENTRY(usb_ohci),
|
|
|
|
#endif
|
2015-12-06 23:03:42 +03:00
|
|
|
#if BX_SUPPORT_USB_EHCI
|
|
|
|
BUILTIN_PLUGIN_ENTRY(usb_ehci),
|
2012-01-08 16:43:46 +04:00
|
|
|
#endif
|
2012-01-07 18:14:53 +04:00
|
|
|
#if BX_SUPPORT_USB_XHCI
|
|
|
|
BUILTIN_PLUGIN_ENTRY(usb_xhci),
|
2012-09-15 01:50:50 +04:00
|
|
|
#endif
|
|
|
|
#if BX_SUPPORT_VOODOO
|
|
|
|
BUILTIN_PLUGIN_ENTRY(voodoo),
|
2011-12-22 14:35:49 +04:00
|
|
|
#endif
|
2011-12-23 16:01:58 +04:00
|
|
|
{"NULL", NULL, NULL, 0}
|
2011-12-22 14:35:49 +04:00
|
|
|
};
|
|
|
|
|
2011-12-23 16:01:58 +04:00
|
|
|
int bx_load_opt_plugin(const char *name)
|
2011-12-22 14:35:49 +04:00
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
while (strcmp(builtin_opt_plugins[i].name, "NULL")) {
|
|
|
|
if (!strcmp(name, builtin_opt_plugins[i].name)) {
|
2011-12-23 16:01:58 +04:00
|
|
|
if (builtin_opt_plugins[i].status == 0) {
|
2017-01-28 12:52:09 +03:00
|
|
|
builtin_opt_plugins[i].plugin_init(NULL, PLUGTYPE_OPTIONAL);
|
2011-12-23 16:01:58 +04:00
|
|
|
builtin_opt_plugins[i].status = 1;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
};
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-12-25 12:52:34 +04:00
|
|
|
int bx_unload_opt_plugin(const char *name, bx_bool devflag)
|
2011-12-23 16:01:58 +04:00
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
while (strcmp(builtin_opt_plugins[i].name, "NULL")) {
|
|
|
|
if (!strcmp(name, builtin_opt_plugins[i].name)) {
|
|
|
|
if (builtin_opt_plugins[i].status == 1) {
|
2011-12-25 12:52:34 +04:00
|
|
|
if (devflag) {
|
|
|
|
pluginUnregisterDeviceDevmodel(builtin_opt_plugins[i].name);
|
|
|
|
}
|
2011-12-23 16:01:58 +04:00
|
|
|
builtin_opt_plugins[i].plugin_fini();
|
|
|
|
builtin_opt_plugins[i].status = 0;
|
|
|
|
}
|
|
|
|
return 1;
|
2011-12-22 14:35:49 +04:00
|
|
|
}
|
|
|
|
i++;
|
|
|
|
};
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-02-22 00:12:17 +03:00
|
|
|
#if BX_SUPPORT_SOUNDLOW
|
|
|
|
|
2017-02-20 21:21:19 +03:00
|
|
|
#define BUILTIN_SOUND_PLUGIN_ENTRY(mod) {#mod, lib##mod##_sound_plugin_init, lib##mod##_sound_plugin_fini, 0}
|
|
|
|
|
|
|
|
static builtin_plugin_t builtin_sound_plugins[] = {
|
|
|
|
#if BX_HAVE_SOUND_ALSA
|
|
|
|
BUILTIN_SOUND_PLUGIN_ENTRY(alsa),
|
|
|
|
#endif
|
|
|
|
#if BX_HAVE_SOUND_OSS
|
|
|
|
BUILTIN_SOUND_PLUGIN_ENTRY(oss),
|
|
|
|
#endif
|
|
|
|
#if BX_HAVE_SOUND_OSX
|
|
|
|
BUILTIN_SOUND_PLUGIN_ENTRY(osx),
|
|
|
|
#endif
|
|
|
|
#if BX_HAVE_SOUND_SDL
|
|
|
|
BUILTIN_SOUND_PLUGIN_ENTRY(sdl),
|
|
|
|
#endif
|
|
|
|
#if BX_HAVE_SOUND_WIN
|
|
|
|
BUILTIN_SOUND_PLUGIN_ENTRY(win),
|
|
|
|
#endif
|
|
|
|
BUILTIN_SOUND_PLUGIN_ENTRY(file),
|
|
|
|
{"NULL", NULL, NULL, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
int bx_load_sound_plugin(const char *name)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
while (strcmp(builtin_sound_plugins[i].name, "NULL")) {
|
|
|
|
if (!strcmp(name, builtin_sound_plugins[i].name)) {
|
|
|
|
if (builtin_sound_plugins[i].status == 0) {
|
|
|
|
builtin_sound_plugins[i].plugin_init(NULL, PLUGTYPE_SOUND);
|
|
|
|
builtin_sound_plugins[i].status = 1;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
};
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int bx_unload_sound_plugin(const char *name)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
while (strcmp(builtin_sound_plugins[i].name, "NULL")) {
|
|
|
|
if (!strcmp(name, builtin_sound_plugins[i].name)) {
|
|
|
|
if (builtin_sound_plugins[i].status == 1) {
|
|
|
|
builtin_sound_plugins[i].plugin_fini();
|
|
|
|
builtin_sound_plugins[i].status = 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
};
|
|
|
|
return 0;
|
|
|
|
}
|
2017-02-22 00:12:17 +03:00
|
|
|
#endif
|
2017-02-20 21:21:19 +03:00
|
|
|
|
2011-12-22 14:35:49 +04:00
|
|
|
#endif
|
|
|
|
|
2004-08-11 15:09:01 +04:00
|
|
|
}
|