Some additions in the plugins section and fixes/updates in other sections.

Removed obsolete README-plugins file.
This commit is contained in:
Volker Ruppert 2021-03-07 17:10:20 +00:00
parent a2cf072751
commit 8cf09f8545
2 changed files with 85 additions and 404 deletions

View File

@ -1,357 +0,0 @@
README-plugins
This is the README file that came from the CVS branch called BRANCH_PLUGINS.
It's not intended to be user documentation for plugins. It's more like a
bunch of to-do lists that the developers used to coordinate their efforts
while working on plugins. At the bottom are some miscellaneous notes by the
plugin developers and some references to useful usenet articles.
-------------------------------------------------------------------------
BRANCH_PLUGINS
The branch is called BRANCH_PLUGINS. There is a normal tag called
BRANCH_PLUGINS_BASE that marks the point where the branch began. The
base marker will help at merge time.
This branch is a place to experiment with Bochs plugins. Bryce created
the branch on October 4, 2002, and he and Christophe began working on
Bochs plugins.
We started from Bryce's patch.plugins3, which was a patch from December 2001
that copied in some of the plugin architecture from plex86. Here are the
comments from that patch:
> Patch name: patch.plugins3
> Author: Bryce Denney
> Date: Wed Dec 12 17:56:11 EST 2001
>
> This patch replaces the Bochs keyboard with a slightly modified version
> of the plex86 keyboard device, which is implemented as a plugin. This
> is sort of a proof of concept, rather than anything that I'm about to
> check in. It uses GNU libtool to compile the plex86 keyboard code into
> a shared library, and installs that shared library in
> /tmp/bochslib/libplex-keyboard.so. Then the new code in plugin.cc (which
> is adapted from the plex86 plugin code) loads the libplex-keyboard library
> during initialization and installs the plex86 keyboard instead of the
> bochs keyboard.
>
> I chose the keyboard because it takes about 2 seconds to test that it's
> basically working, and because the bochs and plex86 implementations hadn't
> changed very much since they split.
>
> If you look at plex-keyboard.cc and plex-keyboard.h, it is fundamentally the
> same as the current plex86 code. I have changed lots of names from bx_* to
> plex_* just to reduce confusion and mayhem when I was compiling with both
> kbd implementations. I didn't change anything except to get it to compile.
Christophe had made a plugins5 patch, so he checked it in, with these
changes:
- plex86 keyboard device was marged with Bochs keyboard, as a plugin
- plugin.cc was cleaned up
- a device registration mechanism was set up
- the biosdev and unmapped devices were plugin-ized
TO DO:
- (LATER) some plugins, such as the GUI, PIT, SB, and NE2000, have several different
possible implementations. In this case, all implementations should be
children of a single stub class. The stub's methods produce errors or
panics if they are called, depending on the importance of the device.
There is always one instance of the stub class lying around, which will be
used if none of the implementation plugins is loaded. Either an optional
plugin or a user plugin can fill in these slots.
- platform specific issues
- (LATER) make sure LTDL works on VC++. It doesn't and won't without
significant work. Maybe it's easier to support VC++ with ifdefs in
plugin.cc rather than using ltdl at all. This will have to wait.
- (DONE) nmake build: we must use lib.exe, not $(LIBTOOL) $(CXX) stuff
- configure script work
- LTDL has a feature called dlpreload which sort of emulates dlopen
by linking all the modules statically and then emulating dlopen calls.
I don't see any value in this for plugins. If the platform cannot
support dlopen or some equivalent, let the configure script crash and
tell the user to configure without plugins instead.
- (DONE) to support plugins on MacOSX, the user must install dlcompat.
Otherwise libtool's configure script will discover that no dlopen() or
equivalent function is found, and it will not be able to build/load
plugins. The configure script should bomb in this case, with an error
that says where to find dlcompat. dlcompat IS installed on SF compile
farm in /sw/include and /sw/lib.
- Understand/resolve simulation differences between CVS head and
BRANCH_PLUGINS. Simulation is slightly different.
- compare four versions
- BRANCH_PLUGINS with --enable-plugins
- BRANCH_PLUGINS without --enable-plugins
- BRANCH_PLUGINS_BASE
- CVS head
- these differences seem to be explained by a few things:
1. devices are initialized in a different order, so they are assigned
different timer id. For any events that occur at the same tick, the
timer handlers would get called in a different order. I believe I
have fixed the order of timer registration so that it matches, and
that cleaned up some simulation differences.
2. bx_gui->handle_events is now called from iodev/devices.cc instead of
from iodev/keyboard.cc.
3. bx_keyb_c::periodic() used to be called directly from devices.cc
but now the keyboard registers its own timer
- I have never seen any problems caused by the sim differences, but they
make me nervous. -Bryce
- (LATER) convert remaining devices
- (LATER) maybe the implementation class for each plugin device should go into
the .cc file instead of the header file. If all their methods are called
through the stub class virtual functions, and no external file has access to
the real non-stub class, then maybe there is no point in letting anybody
else see the real class at all? (If you do use the class you will get
undefined symbols when you compile for plugins anyway.) For the hard drive,
we could put bx_hard_drive_stub_c in harddrv.h, and any constants or types
that external files might need, and then put the real class, bx_hard_drive_c,
at the top of harddrv.cc.
- (LATER) eventually we need to clarify the connection between plugins and
devices. At the moment, each plugin creates exactly one device, but it does
not have to work that way.
- it would be more correct to mark the devices as core, optional, etc. than
to use a type field in the plugin struct. The reason that the type
(core,optional,user) is currently passed into the PLUG_load_plugin macro
and placed in the plugin struct instead of letting the device code decide
is: devices.cc is responsible for initting and resetting devices, so I
wanted devices.cc to decide whether the device would be managed by the
plugin infrastructure (init_all, reset_all) or not. This is not that
important yet, but when Volker wants to write a plugin with multiple
devices, we will need to sort it out.
- (LATER) make a way for users to replace a core plugin with one of their
choice.
- (LATER) implement user plugins. These are plugins that Bochs does not know
anything about at compile time. The user asks Bochs to load a plugin using
just its filename. It loads the plugin and registers any bx_params that
the user can configure, and either the text config interface or the
wxWindows interface can display this param list as a menu or dialog.
Then at simulation start time, we call init() on the user device and
it can be used like any other device.
- (LATER) make plugin CPU???
DONE:
- applied patch.plugins5
- updated makefile dependencies now that plugin.h is in there
- all guis converted to plugins
- 8 I/O devices are converted to plugins
- make the Makefile use libtool to build dynamic libraries
- use libtool's ltdl library to open and read dynamic libraries, since it
has cross platform support
- the Boolean/bx_bool thing will be resolved in the main branch. I have
made patch.replace-Boolean.gz which I will apply later, after the
plugins branch has been merged. This become more urgent because it
caused bug #623152 MacOSX: Triple Exception Booting win95
- take a look at the code generated by calls to virtual functions, to
check if there's huge overhead that I don't know about.
Answer: I don't believe there is that much extra overhead. If you call
a nonvirtual function, it must push all the args onto the stack, then
push the THIS pointer, then call the method using a known constant address.
With a virtual function, you push all the args onto the stack, then push
the THIS pointer, then do one extra memory reference to THIS+constant to read
the pointer to the virtual method, and call it. This is just what I
expected to find--no strange and magicial code was inserted by the
compiler in this case.
- wxWindows configuration interface and display works fine as a plugin now
- selection of config interface is controlled by the bochsrc line
"config_interface: NAME" and the parameter bx_options.Osel_config.
- selection of display library is controlled by the bochsrc line
"display_library: NAME" and the parameter bx_options.Osel_displaylib.
- renamed vga_library to display_library (Christophe's suggestion)
- add --with-all-libs option, which attempts to detect all the display
libraries that Bochs can compile with. You can use this with or without
plugins, compile with multiple guis in the same binary, and select between
them at runtime. If the detection fails, you can always write a bunch
of --with-PACKAGE options yourself.
- load plugins as they are needed, in main.cc and iodev/devices.cc.
- plugins are loaded using a macro PLUG_load_plugin(plugin_name, plugin_type).
When plugins are enabled, this macro calls bx_load_plugin() in plugin.cc,
which loads the plugin with lt_dlopen and calls its plugin_init method.
When plugins are disabled, the code is already linked into the binary so
the macro calls the plugin_init method directly.
- The plugin_init method for plugin ABC is called libABC_LTX_plugin_init()
and the same prefix is added before the plugin_fini method. This "name
mangling" makes the symbols unique so that they can all be linked
statically into the binary when plugins are turned off. This turned out
to be a very useful thing!
- The choice of lib*_LTX_* is not random... The libtool LTDL library
automatically searches for symbols of the form lib<module>_LTX_<symbol>
before looking for <symbol>. Libtool recommends making global symbols in
every plugin unique in some way, and in fact on MacOSX the dynamic linker
will not allow two libs to be linked in that both have plugin_init symbols,
so this sort of mangling is required.
- how do we know what plugins should be available when we start Bochs?
- we have core plugins, optional plugins, and user plugins.
- (V2.0) core plugin: These are so fundamental that Bochs won't even
initialize without them, for example the CMOS. The user can substitute
his own equivalent plugin to replace the CMOS, but he cannot say "Don't
load the CMOS at all." Core plugin devices are initialized and reset
explictly by code in iodev/devices.cc, since the initialization order for
some of them is critical. They are currently NOT added to the device
list in pluginRegisterDevice and pluginRegisterDeviceDevmodel, so that
the plugin system does not call init() and reset(). If a core plugin
cannot be found, Bochs will panic.
In the bochsrc we can provide a way for the user to REPLACE a core plugin
with a different plugin that implements the same C++ interface, but there
is no way to ask bochs to NOT load a core plugin. I'm not sure how to
configure the replacement plugin--this may have to be added later.
Bochsrc line:
replace_core_plugin: old=pic, new=mypic
- (V2.0) optional plugin: These can be loaded or not without affecting
Bochs's ability to start up and simulate. Initialization and reset for
all optional plugins are handled by bx_init_plugins() and
bx_reset_plugins(), which are now called from bx_devices_c::init() and
bx_devices_c::reset(). Bochs knows how to configure optional plugins at
compile time, and they are loaded only if the configuration settings
enables the device. Examples: serial, parallel, ne2k. See the call to
is_serial_enabled() in iodev/devices.cc. There are some plugins that you
wouldn't ever want to leave out, like vga. Maybe the term "optional" is
not clear and I need to think of a better name. Bochs will panic if an
optional plugin cannot be found. If the plugin was compiled, then
it should be available at runtime too!
- (NOT DONE) user plugin: These are plugins that Bochs does not know
anything about at compile time. The user asks Bochs to load a plugin
using just its filename. It loads the plugin and (somehow) gets
information about what settings the user can configure. The settings are
adjusted by either bochsrc lines or the user interface, and then the
device can be used. I'm missing some details here because I haven't
thought through it all the way. User plugins may not be supported until
after v2.0.
- list of plugins sorted into categories
- core plugins: unmapped, biosdev, cmos, dma, pic, vga
- optional: floppy, harddrv, keyboard, serial, parallel
- user: none yet
- clarify relationship of plugin and device
- a plugin is a shared object that you load that has a plugin_init() and
plugin_fini() function inside. The plugin_init() can create any number of
"devices" and register them. Devices are added to a global list so that we
can do operations on every registered device.
- There is (now) a pointer from each device to the plugin that created it.
- Devices created by core plugins are called core devices. These will not be
added to the device list because they are managed by existing code in
devices.cc and elsewhere. Instead of referring to them by their device_t
structure, we will use a global pointer to them, similar to the
bx_devices.pluginKeyboard pointer. (Alternative: maybe we should add
them to device list anyway, but exclude them in init_all and reset_all
functions.)
- MACOSX PLUGINS WORK! to support plugins on MacOSX, we must ensure that no
plugins have any global symbol names in common, including plugin_init! An
easy solution to this is to say that all plugin functions which can be
looked up with dlsym must follow a pattern like "%s_BXPLUG_%s", where the
first %s is the module name and the second is the plain symbol name, e.g.
pic_BXPLUG_plugin_init. Symbols that are used internally can be declared
static (file scope only).
- SOLARIS PLUGINS WORK! to support plugins on Solaris, we must not rely on
the use of global object constructors. In fact every global variable in a
module MUST BE set to a compile-time constant. We must declare object
pointers as globals, not actual objects.
- WIN32 PLUGINS WORK! to support plugins on win32, I added the
BOCHSAPI macro which expands to __declspec(dllexport) in the nonplugin
code and __declspec(dllimport) in the plugin code. Some makefile hacks
were required too. A few differences between win32 and other platforms:
- use semicolon to separate path names in LTDL_LIBRARY_PATH
- every path name in LTDL_LIBRARY_PATH should start with a drive letter,
for example: c:/cygwin/home/bryce/plugins.
- how do we locate plugins on the disk?
- make install copies the plugins into ${prefix}/lib
- if people install into a standard location, no action may be needed (?)
- we can tell people to set the LTDL_LIBRARY_PATH variable.
- if necessary we can implement a bochsrc command like
plugin_search_directory: /path/to/libs
which would call lt_dlsetsearchpath() to add the path to LTDL's list of
directories it will search.
- change log for BRANCH_PLUGINS is in patches/patch.plugins. It is
pretty complete now.
-----------------------------------------------
random notes:
class heirarchy:
logfunctions
- bx_devmodel_c
- bx_keyb_stub_c
- bx_keyb_c
bx_devmodel_c is an abstract class that defines standard functions that all
devices should define, like init and reset. Each method is defined as empty
in bx_devmodel_c so that child classes can choose to implement them or not.
bx_keyb_stub_c declares the methods that code outside the keyboard would need
to call, such as mouse_motion, gen_scancode, etc. It declares these methods
virtual, and provides a minimal definition for each that just does a panic. A
global variable pluginKeyboard initially points to an instance of
bx_keyb_stub_c so that if you forget/fail to load the load the keyboard plugin,
you will see these panics when the methods are called.
bx_keyb_c is the real keyboard code. In its constructor, it changes
pluginKeyboard to point to "this". This is equivalent to installing all
the plugin callbacks associated with the keyboard. It also works in
nonplugin code, which is a plus.
hard drive read_handler. Right now the read_handler
is a static method so it must get its object pointer from somewhere.
1) It can get it from global variable bx_hard_drive
2) The hard drive object can be passed in to it
We've always used #2, so every device has methods that look like this:
static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsi
If/when we switch over to using virtual methods, there will no longer be
any problem finding the this pointer. If we go that route, the this_ptr
can be eliminated. For now, we must use the this_ptr. Otherwise we could
never support more than one device of a given type.
------------------------------------------
References
From: Tero Pulkkinen (p150650@zori.cs.tut.fi)
Subject: Re: undefined reference to `pm virtual table'
Newsgroups: gnu.g++.help
Date: 1996/11/15
> The compile goes off OK, but I get this error at link time:
> pm.o(.text+0xa8): undefined reference to `pm virtual table'
This error comes from that the compiler didnt make virtual function
table for object even though there's implemented functions that use
objects of that type(constructor for example). Probably your pm-class
has all implemented member functions *inline* and you still have
(pure) virtual functions inside the class.
The creation point of virtual function table usually (dunno if g++ does that)
is at position of first seen noninline function body of that class.
Now if every of your function is inline, there's no place where compiler
could make virtual function table.
Fix is to move body of for example constructor(any member is fine) to the .cc
file instead of keeping it in .h-file and linking that .o file to your
executable.
Other sollution is to remove *all* implementations of functions from header
file. If all functions of a class are pure virtual, there's no need for
virtual function table. (Constructor must set pointer to virtual function
table to the object, so, if you have constructor, you'll need virtual
function table too, even in abstract classes...)
> Can someone help me? Thanks in advance.
Hope this helps....

View File

@ -288,12 +288,12 @@ behind the programmer's back. More explicitness would be a big win.
C++ methods have an invisible parameter called the this pointer - otherwise the
method wouldn't know which object to operate on. In many cases in Bochs, there
will only ever be one object - so this flexibility is unnecessary. There is a
hack that can be enabled by #defining BX_USE_CPU_SMF to 1 in <filename>config.h
</filename> that makes most methods static, which means they have a "special
relationship" with the class they are declared in but apart from that are
normal C functions with no hidden parameters. Of course they still need access
to the internals of an object, so the single object of their class has a globally
visible name that these functions use. It is all hidden with macros.
hack that can be enabled by defining e.g. <option>BX_USE_PIC_SMF</option> to 1
in <filename>config.h</filename> that makes most methods static, which means
they have a "special relationship" with the class they are declared in but apart
from that are normal C functions with no hidden parameters. Of course they still
need access t/o the internals of an object, so the single object of their class has
a globally visible name that these functions use. It is all hidden with macros.
</para>
<para>
Declaration of a class, from iodev/pic.h:
@ -366,29 +366,20 @@ of bugs just waiting to happen. Some classes use BX_SMF, others have their own
version of the macro, like BX_PIC_SMF above.
</para>
</section>
<section id="cpu-mem-objects"><title>CPU und memory objects in UP/SMP configurations</title>
<section id="cpu-objects"><title>CPU objects in UP/SMP configurations</title>
<para>
The CPU class is a special case of the above: if Bochs is simulating a uni-
processor machine then there is obviously only one bx_cpu_c object and the
static methods trick can be used. If, on the other hand, Bochs is simulating an
smp machine then we can't use the trick. The same seems to be true for memory:
for some reason, we have a memory object for each CPU object. This might become
relevant for NUMA machines, but they are not all that common -- and even the
existing IA-32 NUMA machines bend over backwards to hide that fact: it should
only be visible in slightly worse timing for non-local memory and non-local
peripherals. Other than that, the memory map and device map presented to each
CPU will be identical.
SMP machine then we can't use the trick.
</para>
<para>
In a UP configuration, the CPU object is declared as bx_cpu. In an SMP
configuration it will be an array of pointers to CPU objects (bx_cpu_array[]).
For memory that would be bx_mem and bx_mem_array[], respectively.
Each CPU object contains a pointer to its associated memory object.
Access of a CPU object often goes through the BX_CPU(x) macro, which either
ignores the parameter and evaluates to &amp;bx_cpu, or evaluates to bx_cpu_array
[n], so the result will always be a pointer. The same goes for BX_MEM(x).
If static methods are used then BX_CPU_THIS_PTR evaluates to BX_CPU(0)->. Ugly,
isn't it?
[n], so the result will always be a pointer. If static methods are used then
BX_CPU_THIS_PTR evaluates to BX_CPU(0)->. Ugly, isn't it?
</para>
</section>
<section id="siminterface"><title>The simulator interface</title>
@ -409,7 +400,7 @@ done using the <command>SIM</command> object:
The event handling supports both synchronous and asynchronous types. In case of
a synchronous event, the sender waits until the receiver has processed the
event (finally setting return code). Asynchronous events are simply added to the
event queue and fetched from it later when the receiver processes event. The
event queue and fetched from it later when the receiver processes events. The
event handling is important if a multithreaded implementation of gui and config
interface like wxWidgets is used. An example for the event handling is the
procedure after pressing the "snapshot" tool bar button:
@ -917,7 +908,7 @@ All devices models located on or connected to the Bochs "mainboard" are based on
the <emphasis>bx_devmodel_c</emphasis> class. It is defined in <filename>iodev.h</filename>
and it has been introduced along with the plugin interface. That's why the
device registration code is still located in <filename>plugin.cc</filename>, but
it is present independent from the <emphasis>--enable-plugins</emphasis> switch.
it is present independent from the <option>--enable-plugins</option> switch.
Some code in <filename>devices.cc</filename> uses the device registration to
initialize or reset all devices. It also calls required methods of the save/restore
feature. If the debugger is present, a device can resister a method to dump it's
@ -3015,14 +3006,15 @@ several files need to be modified (configure script, makefile, some headers)
and the complete build process must be performed. As an alternative, Bochs
can be compiled as an executable file containing the core funtionality and a
number of loadable modules providing device emulation, display library (gui)
features or drivers for some features. On Windows platforms such a module is
called DLL, others platforms like Linux call it shared library. Bochs uses the
environment variable LTDL_LIBARY_PATH to search for plugins. To build Bochs in
this mode, the configure option <option>--enable-plugins</option> must be used.
In this mode it is possible to add externally developed extensions
(AKA "user plugins"). Rebuilding the whole project is not necessary in that
case. Basically these Bochs facilities are currently supported by the plugin
interface:
capabilities or drivers for some other features. On Windows platforms such a
module is called DLL, other platforms like Linux call it shared library and use
<command>libtool</command> to create it. Bochs uses the environment variable
LTDL_LIBARY_PATH to search for plugins. To build Bochs in this mode, the
configure option <option>--enable-plugins</option> must be used. In this mode
it is possible to add externally developed extensions (AKA "user plugins") that
can be detected at startup. Rebuilding the whole project is not necessary in
that case. Basically these Bochs facilities are currently supported by the
plugin interface:
<itemizedlist>
<listitem><para>i/o device</para></listitem>
<listitem><para>pluggable USB device</para></listitem>
@ -3036,20 +3028,64 @@ interface:
<section><title>Plugin file names</title>
<para>
The plugin interface expects a special file name format that depends on the
plugin type and platform. On Linux and other platforms using "libtool" the
plugin file for the CMOS device has this name:
plugin type and platform. On Linux and other platforms using
<command>libtool</command>-based compilation the plugin file for the CMOS
device gets this name:
<screen>
libbx_cmos.so
</screen>
On Windows platforms the output file is a DLL and the name is slightly different:
On Windows platforms (Cygwin, MinGW/MSYS, MSVC) the output file is a DLL and
the name is slightly different:
<screen>
bx_cmos.dll
</screen>
The names of device plugins are created from the base name of source files like
the example above. Networking module names traditionally start with <emphasis>"eth_"</emphasis>
and sound driver names start with <emphasis>"sound"</emphasis>. For gui and disk
image format modules an extension has been added to the base name (<emphasis>"_gui"</emphasis>
/ <emphasis>"_img"</emphasis>).
the example above. For other module types the naming is similar, but with some
extensions. This table shows how the names of some existing modules are created:
<table>
<title>Plugin file naming</title>
<tgroup cols="5">
<thead>
<row>
<entry>Type</entry>
<entry>Module name</entry>
<entry>Source file name</entry>
<entry>Libtool file name</entry>
<entry>DLL file name</entry>
</row>
</thead>
<tbody>
<row>
<entry>Display library</entry>
<entry>sdl2</entry>
<entry>sdl2.cc</entry>
<entry>libbx_sdl2_gui.so</entry>
<entry>bx_sdl2_gui.dll</entry>
</row>
<row>
<entry>Disk image module</entry>
<entry>vbox</entry>
<entry>vbox.cc</entry>
<entry>libbx_vbox_img.so</entry>
<entry>bx_vbox_img.dll</entry>
</row>
<row>
<entry>Networking module</entry>
<entry>slirp</entry>
<entry>eth_slirp.cc</entry>
<entry>libbx_eth_slirp.so</entry>
<entry>bx_eth_slirp.dll</entry>
</row>
<row>
<entry>Lowlevel sound driver</entry>
<entry>file</entry>
<entry>soundfile.cc</entry>
<entry>libbx_soundfile.so</entry>
<entry>bx_soundfile.dll</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
</section>
<section><title>Plugin types</title>
@ -3062,7 +3098,7 @@ list of plugin types defined in <filename>extplugin.h</filename> with some
description:
<table>
<title>Plugin types</title>
<tgroup cols="3">
<tgroup cols="5">
<thead>
<row>
<entry>Type</entry>
@ -3146,8 +3182,9 @@ description:
Each plugin has an entry function that is called during plugin detection, after
loading and before unloading the modules. For compatiblity with the "monolithic"
Bochs compilation each plugin must have a unique name. When plugins are disabled,
the macros for loading / unloading the plugin directly call the plugin entry
function. The entry function can be called with these mode arguments:
the macros / functions for loading / unloading the plugin directly call the
plugin entry function. The entry function can be called with these mode
arguments:
<itemizedlist>
<listitem><para>PLUGIN_PROBE returns the plugin type as defined above (mandatory for all plugins)</para></listitem>
<listitem><para>PLUGIN_FLAGS returns flags associated with the plugin</para></listitem>
@ -3156,13 +3193,14 @@ function. The entry function can be called with these mode arguments:
</itemizedlist>
At Bochs startup, but before initializing the config options, it searches the
plugin paths for modules with the correct file name format and the expected
entry function name. Each valid plugin is temporarily loaded and then the plugin
type and flags are read. The plugin interface builds up a database with all
information for loading detected modules later on demand. A plugin can return
multiple types, but it can only be loaded with one of it (currently on used by
the "voodoo" plugin). The flags can be used to indicate specific capabilities
of the plugin (currently on used for device plugins that can be connected to a
PCI slot). For unimplemented modes the entry function needs to return 0.
entry function name. Each valid plugin is temporarily loaded to read the plugin
type and flags by calling the entry function with the corresponding mode. The
plugin interface builds up a database with all information for loading detected
modules later on demand. A plugin can return multiple types, but it can only be
loaded with one of it (currently on used by the "voodoo" plugin). The flags can
be used to indicate specific capabilities of the plugin (currently on used for
device plugins that can be connected to a PCI slot). For unimplemented calling
modes the entry function must return 0.
</para>
<para>
To simplify the naming of the plugin entry function some macros have been
@ -3174,7 +3212,7 @@ plugins on platforms other than Windows:
</screen>
Please see <filename>plugin.h</filename> for all supported definitions of the
entry function. The example below shows the plugin-related section
of the "unmapped" device.
of the "unmapped" device source file.
<screen>
// Define BX_PLUGGABLE in files that can be compiled into plugins. For
// platforms that require a special tag on exported symbols, BX_PLUGGABLE