{% extends "sega.html" %}
{% macro nameTable(name, guid=None) %}
<h3>Device registrations</h3>
<table>
    <tr>
        <td>Device Name</td>
        <td>{% if name %}<code>\Device\{{ name }}</code>{% endif %}</td>
    </tr>
    <tr>
        <td>Linked To</td>
        <td>{% if name %}<code>\DosDevices\{{name}}</code> (<code>\\.\{{name}}</code>){% endif %}</td>
    </tr>
    <tr>
        <td>Device GUID</td>
        <td>{% if guid %}<code>{{ "{" }}{{ guid }}{{ "}" }}</code>{% endif %}</td>
    </tr>
</table>
{% endmacro %}
{% block title %}Drivers{% endblock %}
{% block body %}
<h1>Drivers</h1>
{{ generate_toc()|safe }}

<p>Ring* systems makes use of a number of (mostly) bespoke drivers, listed below:</p>
<ul>
    <li><code>geminifs.sys</code></li>
    <li><code>kbfilter.sys</code></li>
    <li><code>columba.sys</code></li>
    <li><code>mxcmos.sys</code></li>
    <li><code>mxhwreset.sys</code></li>
    <li><code>mxjvs.sys</code></li>
    <li><code>mxparallel.sys</code></li>
    <li><code>mxsmbus.sys</code></li>
    <li><code>mxsram.sys</code></li>
    <li><code>mxsram_pci_isa_bridge.sys</code></li>
    <li><code>mxsram_pcmcia.sys</code></li>
    <li><code>mxsuperio.sys</code></li>
    <li><code>mxusbdevice.sys</code></li>
</ul>

<!-- Notes for table generation:

    Device Name: `IoCreateDevice` third argument
    Symlink Name: `IoCreateSymbolicLink` first argument
    Username Name:
    Device GUID: `IoRegisterDeviceInterface` second argument

    Major functions:
        00: Create
        01: Create named pipe
        02: Close
        03: Read
        04: Write
        05: Query info
        06: Set info
        07: Query EA
        08: Set EA
        09: Flush buffers
        0a: Query vol info
        0b: Set vol info
        0c: Dir ctrl
        0d: FS ctrl
        0e: Device ctrl
        0f: Internal device ctrl
        10: Shutdown
        11: Lock ctrl
        12: Cleanup
        13: Create mailslot
        14: Query security
        15: Set security
        16: Power
        17: System ctrl
        18: Device change
        19: Query quota
        1a: Set quota
        1b: PNP

    Ports used:
        *_PORT_*
-->

<h2 id="kbfilter">kbfilter</h2>
<p>kbfilter is a service responsible for blocking keyboard input.</p>

<p>The driver can be disabled by setting <code>FilterEnable</code> at
    <code>HKLM\System\CurrentControlSet\Services\kbfilter\Parameters</code> to <code>0</code>.</p>

<h2 id="geminifs">geminifs</h2>
<p>GeminiFS is a custom filesystem driver used by the games to construct the <code>X:</code> mountpoint.</p>

<h2 id="columba">columba</h2>
<p>Columba is a driver used to fetch DMI information about the current system.</p>
{{ nameTable("columba") }}
<h3>IO control codes</h3>
<table>
    <thead>
        <tr>
            <td>IOCTL Code</td>
            <td>#define</td>
            <td>Bytes in</td>
            <td>Bytes out</td>
            <td>Meaning</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>0x9c406104</code></td>
            <td><code>{{ ioctl("0x9c406104") }}</code></td>
            <td></td>
            <td></td>
            <td>Read the DMI at a given offset</td>
        </tr>
    </tbody>
</table>

<h2 id="mxcmos">mxcmos</h2>
<p>mxcmos is unknown currently</p>

<h2 id="mxhwreset">mxhwreset</h2>
<p>This driver is used exclusively to power cycle the PC.</p>
{{ nameTable("mxhwreset") }}
<h3>IO control codes</h3>
<table>
    <thead>
        <tr>
            <td>IOCTL Code</td>
            <td>#define</td>
            <td>Bytes in</td>
            <td>Bytes out</td>
            <td>Meaning</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>0x9c402000</code></td>
            <td><code>{{ ioctl("0x9c402000") }}</code></td>
            <td>0</td>
            <td>0</td>
            <td>Writes <code>0xE</code> to PORT <code>0xCF9</code>, causing a power cycle.</td>
        </tr>
    </tbody>
</table>


<h2 id="mxjvs">mxjvs</h2>
<p>mxjvs is the driver used to communicate with the JVS IO board connected to the Ring* PC via the JVS USB port.</p>
{{ nameTable("mxjvs") }}
<h3>IO control codes</h3>
<table>
    <thead>
        <tr>
            <td>IOCTL Code</td>
            <td>#define</td>
            <td>Bytes in</td>
            <td>Bytes out</td>
            <td>Meaning</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>0x9c402000</code></td>
            <td><code>{{ ioctl("0x9c402000") }}</code></td>
            <td><em>variable</em></td>
            <td><em>variable</em></td>
            <td>Exchange JVS packets with the JVS IO board</td>
        </tr>
    </tbody>
</table>
<h3>Extra values used, currently unknown</h3>
<ul>
    <li><code>\Device\Serial3</code></li>
    <li><code>{86e0d1e0-8089-11d0-9ce4-08003e301f73}</code></li>
</ul>

<h2 id="mxparallel">mxparallel</h2>
<p>mxparallel is a wrapper driver for the parallel port used to communicate with the keychip</p>
{{ nameTable("mxparallel") }}
<h3>IO control codes</h3>
<table>
    <thead>
        <tr>
            <td>IOCTL Code</td>
            <td>#define</td>
            <td>Bytes in</td>
            <td>Bytes out</td>
            <td>Meaning</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>0x9c40a000</code></td>
            <td><code>{{ ioctl("0x9c40a000") }}</code></td>
            <td></td>
            <td></td>
            <td>Write data</td>
        </tr>
        <tr>
            <td><code>0x9c406004</code></td>
            <td><code>{{ ioctl("0x9c406004") }}</code></td>
            <td></td>
            <td></td>
            <td>Read data</td>
        </tr>
        <tr>
            <td><code>0x9c40a008</code></td>
            <td><code>{{ ioctl("0x9c40a008") }}</code></td>
            <td></td>
            <td></td>
            <td>Write status</td>
        </tr>
        <tr>
            <td><code>0x9c40600c</code></td>
            <td><code>{{ ioctl("0x9c40600c") }}</code></td>
            <td></td>
            <td></td>
            <td>Read status</td>
        </tr>
        <tr>
            <td><code>0x9c40a010</code></td>
            <td><code>{{ ioctl("0x9c40a010") }}</code></td>
            <td></td>
            <td></td>
            <td>Write control</td>
        </tr>
        <tr>
            <td><code>0x9c406014</code></td>
            <td><code>{{ ioctl("0x9c406014") }}</code></td>
            <td></td>
            <td></td>
            <td>Read control</td>
        </tr>
        <tr>
            <td><code>0x9c40a018</code></td>
            <td><code>{{ ioctl("0x9c40a018") }}</code></td>
            <td></td>
            <td></td>
            <td>Write flags</td>
        </tr>
        <tr>
            <td><code>0x9c40601c</code></td>
            <td><code>{{ ioctl("0x9c40601c") }}</code></td>
            <td></td>
            <td></td>
            <td>Read flags</td>
        </tr>
    </tbody>
</table>
<h3>Ports used</h3>
<ul>
    <li><code>\Device\ParallelPort0</code></li>
</ul>

<h2 id="mxsmbus">mxsmbus</h2>
<p>This driver communicates with the system message bus chip on the motherboard. This driver appears to be a slightly
    modified reference driver from Intel. The exact chipset used varies depending on the system:</p>
<table>
    <tr>
        <td>RingWide</td>
        <td>Intel(R) 82801G(ICH7 Family)SMBus Controller</td>
    </tr>
    <tr>
        <td>RingEdge</td>
        <td>Intel(R) ICH9 SMBus Controller</td>
    </tr>
    <tr>
        <td>RingEdge 2</td>
        <td>Intel(R) 5 Series/3400 Series Chipset Family SMBus Controller</td>
    </tr>
</table>
<p>Devices currently confirmed to be located on the system message bus:</p>
<table>
    <thead>
        <tr>
            <td>Address</td>
            <td>Device</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>0x20</code></td>
            <td>PCA9535; used for DIP switches</td>
        </tr>
        <tr>
            <td><code>0x30</code></td>
            <td></td>
        </tr>
        <tr>
            <td><code>0x55</code></td>
            <td></td>
        </tr>
        <tr>
            <td><code>0x57</code></td>
            <td>EEPROM</td>
        </tr>
    </tbody>
</table>
{{ nameTable(None, "5c49e1fe-3fec-4b8d-a4b5-76be7025d842") }}
<h3>IO control codes</h3>
<table>
    <thead>
        <tr>
            <td>IOCTL Code</td>
            <td>#define</td>
            <td>Bytes in</td>
            <td>Bytes out</td>
            <td>Meaning</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>0x9c406000</code></td>
            <td><code>{{ ioctl("0x9c406000") }}</code></td>
            <td>0</td>
            <td>4</td>
            <td>Not totally understood, but appears to retrieve the port number</td>
        </tr>
        <tr>
            <td><code>0x9c402004</code></td>
            <td><code>{{ ioctl("0x9c402004") }}</code></td>
            <td>25<sub>h</sub></td>
            <td>25<sub>h</sub></td>
            <td>Exchange data over the smbus</td>
        </tr>
        <tr>
            <td><code>0x9c406008</code></td>
            <td><code>{{ ioctl("0x9c406008") }}</code></td>
            <td>0</td>
            <td>4</td>
            <td>Retrieve the driver version</td>
        </tr>
        <tr>
            <td><code>0x9c40200c</code></td>
            <td><code>{{ ioctl("0x9c40200c") }}</code></td>
            <td>27<sub>h</sub></td>
            <td>27<sub>h</sub></td>
            <td>Exchange data with an I2C device over the smbus</td>
        </tr>
    </tbody>
</table>
<h3>Ports used</h3>
<p>Unsure</p>

<h2 id="mxsram">mxsram</h2>
<p>The on-board SRAM. This device driver also supports reading and writing like a file.</p>
{{ nameTable("mxsram") }}
<h3>IO control codes</h3>
<table>
    <thead>
        <tr>
            <td>IOCTL Code</td>
            <td>#define</td>
            <td>Bytes in</td>
            <td>Bytes out</td>
            <td>Meaning</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>0x70000</code></td>
            <td><code>IOCTL_DISK_GET_DRIVE_GEOMETRY</code></td>
            <td>0</td>
            <td>18<sub>h</sub></td>
            <td></td>
        </tr>
        <tr>
            <td><code>0x7405c</code></td>
            <td><code>IOCTL_DISK_GET_LENGTH_INFO</code></td>
            <td>0</td>
            <td>8</td>
            <td></td>
        </tr>
        <tr>
            <td><code>0x9c406000</code></td>
            <td><code>{{ ioctl("0x9c406000") }}</code></td>
            <td></td>
            <td></td>
            <td>Ping</td>
        </tr>
        <tr>
            <td><code>0x9c406004</code></td>
            <td><code>{{ ioctl("0x9c406004") }}</code></td>
            <td></td>
            <td></td>
            <td>Get sector size</td>
        </tr>
        <tr>
            <td><code>0x9c406008</code></td>
            <td><code>{{ ioctl("0x9c406008") }}</code></td>
            <td></td>
            <td></td>
            <td>Get version</td>
        </tr>
    </tbody>
</table>
<h3>Ports used</h3>
<ul>
    <li><code>\Device\memcard0</code></li>
</ul>

<h2 id="mxsram_pci_isa_bridge">mxsram_pci_isa_bridge</h2>
<p>mxsram_pci_isa_bridge is unknown currently</p>

<h2 id="mxsram_pcmcia">mxsram_pcmcia</h2>
<p>mxsram_pcmcia is unknown currently</p>

<h2 id="mxsuperio">mxsuperio</h2>
<p>This driver communicates with some additional on-board devices. Notably EEPROM and the W83791D hardware monitor.</p>
{{ nameTable("mxsuperio") }}
<h3>IO control codes</h3>
<table>
    <thead>
        <tr>
            <td>IOCTL Code</td>
            <td>#define</td>
            <td>Bytes in</td>
            <td>Bytes out</td>
            <td>Meaning</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>0x9c406000</code></td>
            <td><code>{{ ioctl("0x9c406000") }}</code></td>
            <td></td>
            <td></td>
            <td>Ping</td>
        </tr>
        <tr>
            <td><code>0x9c402004</code></td>
            <td><code>{{ ioctl("0x9c402004") }}</code></td>
            <td></td>
            <td></td>
            <td>Read</td>
        </tr>
        <tr>
            <td><code>0x9c40a008</code></td>
            <td><code>{{ ioctl("0x9c40a008") }}</code></td>
            <td></td>
            <td></td>
            <td>Write</td>
        </tr>
        <tr>
            <td><code>0x9c40200c</code></td>
            <td><code>{{ ioctl("0x9c40200c") }}</code></td>
            <td></td>
            <td></td>
            <td>Hardware monitor Read</td>
        </tr>
        <tr>
            <td><code>0x9c40a010</code></td>
            <td><code>{{ ioctl("0x9c40a010") }}</code></td>
            <td></td>
            <td></td>
            <td>Hardware monitor write</td>
        </tr>
    </tbody>
</table>
<h3>Ports used</h3>
<ul>
    <li><code></code></li>
</ul>

<h2 id="mxusbdevice">mxusbdevice</h2>
<p>Monitors connected devices to the system, and when a device connects matching the
    <code>GUID_DEVINTERFACE_USB_DEVICE</code> class (<code>{a5dcbf10-6530-11d2-901f-00c04fb951ed}</code>) it checks the
    VID and PID. If it matches a pair it has been instructed to scan for, it increments the count and informs the
    caller.
</p>
{{ nameTable("mxusbdevice") }}
<h3>IO control codes</h3>
<table>
    <thead>
        <tr>
            <td>IOCTL Code</td>
            <td>#define</td>
            <td>Bytes in</td>
            <td>Bytes out</td>
            <td>Meaning</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>0x9c402000</code></td>
            <td><code>{{ ioctl("0x9c402000") }}</code></td>
            <td>8</td>
            <td>0</td>
            <td>Equeue a new query. <code>{ uint insertion_count, wchar_t vid; wchar_t pid }<code> is currently my best guess regarding the structure of the payload.</td>
        </tr>
    </tbody>
</table>

{% endblock %}