mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 01:25:33 -07:00
Merge remote-tracking branch 'upstream/master' into qt-wacom-serial
This commit is contained in:
108
.ci/build.sh
108
.ci/build.sh
@@ -26,7 +26,6 @@
|
||||
# - Packaging the Ghostscript DLL requires 32-bit and/or 64-bit Ghostscript on Program Files
|
||||
# - Packaging the FluidSynth DLL requires it to be at /home/86Box/dll32/libfluidsynth.dll
|
||||
# and/or /home/86Box/dll64/libfluidsynth64.dll (for 32-bit and 64-bit builds respectively)
|
||||
# - Packaging the Discord DLL requires wget (MSYS should come with it)
|
||||
# - For Linux builds:
|
||||
# - Only Debian and derivatives are supported
|
||||
# - dpkg and apt-get are called through sudo to manage dependencies; make sure those
|
||||
@@ -284,7 +283,7 @@ then
|
||||
then
|
||||
# Update keyring as well, since the package signing keys sometimes change.
|
||||
echo [-] Updating package databases and keyring
|
||||
yes | pacman -Sy --needed msys2-keyring
|
||||
pacman -Sy --needed --noconfirm msys2-keyring
|
||||
|
||||
# Save build tag to skip pacman sync/keyring later.
|
||||
save_buildtag pacmansync
|
||||
@@ -292,100 +291,29 @@ then
|
||||
echo [-] Not updating package databases and keyring again
|
||||
fi
|
||||
|
||||
# Query installed packages.
|
||||
pacman -Qe > "$cache_dir/pacman.txt"
|
||||
|
||||
# Download the specified versions of architecture-specific dependencies.
|
||||
echo -n [-] Downloading dependencies:
|
||||
pkg_dir="/var/cache/pacman/pkg"
|
||||
repo_base="https://repo.msys2.org/mingw/$(echo $MSYSTEM | tr '[:upper:]' '[:lower:]')"
|
||||
cat .ci/dependencies_msys.txt | tr -d '\r' > "$cache_dir/deps.txt"
|
||||
pkgs=""
|
||||
while IFS=" " read pkg version
|
||||
do
|
||||
prefixed_pkg="$MINGW_PACKAGE_PREFIX-$pkg"
|
||||
installed_version=$(grep -E "^$prefixed_pkg " "$cache_dir/pacman.txt" | cut -d " " -f 2)
|
||||
if [ "$installed_version" != "$version" ] # installed_version will be empty if not installed
|
||||
then
|
||||
echo -n " [$pkg"
|
||||
|
||||
# Download package if not already present in the local cache.
|
||||
pkg_tar="$prefixed_pkg-$version-any.pkg.tar"
|
||||
if [ -s "$pkg_dir/$pkg_tar.xz" ]
|
||||
then
|
||||
pkg_fn="$pkg_tar.xz"
|
||||
pkg_dest="$pkg_dir/$pkg_fn"
|
||||
else
|
||||
pkg_fn="$pkg_tar.zst"
|
||||
pkg_dest="$pkg_dir/$pkg_fn"
|
||||
if [ ! -s "$pkg_dest" ]
|
||||
then
|
||||
if ! wget -qO "$pkg_dest" "$repo_base/$pkg_fn"
|
||||
then
|
||||
rm -f "$pkg_dest"
|
||||
pkg_fn="$pkg_tar.xz"
|
||||
pkg_dest="$pkg_dir/$pkg_fn"
|
||||
wget -qO "$pkg_dest" "$repo_base/$pkg_fn" || rm -f "$pkg_dest"
|
||||
fi
|
||||
if [ -s "$pkg_dest" ]
|
||||
then
|
||||
wget -qO "$pkg_dest.sig" "$repo_base/$pkg_fn.sig" || rm -f "$pkg_dest.sig"
|
||||
[ ! -s "$pkg_dest.sig" ] && rm -f "$pkg_dest.sig"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if the cached package is valid.
|
||||
if [ -s "$pkg_dest" ]
|
||||
then
|
||||
# Add cached zst package.
|
||||
pkgs="$pkgs $pkg_fn"
|
||||
else
|
||||
# Not valid, remove if it exists.
|
||||
rm -f "$pkg_dest" "$pkg_dest.sig"
|
||||
echo -n " FAIL"
|
||||
fi
|
||||
echo -n "]"
|
||||
fi
|
||||
done < "$cache_dir/deps.txt"
|
||||
[ -z "$pkgs" ] && echo -n ' none required'
|
||||
echo
|
||||
|
||||
# Install the downloaded architecture-specific dependencies.
|
||||
echo [-] Installing dependencies through pacman
|
||||
if [ -n "$pkgs" ]
|
||||
then
|
||||
pushd "$pkg_dir"
|
||||
yes | pacman -U --needed $pkgs
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
# Install packages individually if installing them all together failed.
|
||||
for pkg in $pkgs
|
||||
do
|
||||
yes | pacman -U --needed "$pkg"
|
||||
done
|
||||
fi
|
||||
popd
|
||||
|
||||
# Query installed packages again.
|
||||
pacman -Qe > "$cache_dir/pacman.txt"
|
||||
fi
|
||||
|
||||
# Install the latest versions for any missing packages (if the specified version couldn't be installed).
|
||||
# Establish general dependencies.
|
||||
pkgs="git"
|
||||
while IFS=" " read pkg version
|
||||
|
||||
# Gather installed architecture-specific packages for updating.
|
||||
# This prevents outdated shared libraries, unmet dependencies
|
||||
# and potentially other issues caused by the fact pacman doesn't
|
||||
# update a package's dependencies unless explicitly told to.
|
||||
pkgs="$pkgs $(pacman -Quq | grep -E "^$MINGW_PACKAGE_PREFIX-")"
|
||||
|
||||
# Establish architecture-specific dependencies.
|
||||
while read pkg rest
|
||||
do
|
||||
prefixed_pkg="$MINGW_PACKAGE_PREFIX-$pkg"
|
||||
grep -qE "^$prefixed_pkg " "$cache_dir/pacman.txt" || pkgs="$pkgs $prefixed_pkg"
|
||||
done < "$cache_dir/deps.txt"
|
||||
rm -f "$cache_dir/pacman.txt" "$cache_dir/deps.txt"
|
||||
yes | pacman -S --needed $pkgs
|
||||
if [ $? -ne 0 ]
|
||||
pkgs="$pkgs $MINGW_PACKAGE_PREFIX-$(echo "$pkg" | tr -d '\r')" # CR removal required
|
||||
done < .ci/dependencies_msys.txt
|
||||
|
||||
# Install or update dependencies.
|
||||
echo [-] Installing dependencies through pacman
|
||||
if ! pacman -S --needed --noconfirm $pkgs
|
||||
then
|
||||
# Install packages individually if installing them all together failed.
|
||||
for pkg in $pkgs
|
||||
do
|
||||
yes | pacman -S --needed "$pkg"
|
||||
pacman -S --needed --noconfirm "$pkg"
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,24 +1,12 @@
|
||||
zlib 1.2.11-9
|
||||
binutils 2.37-4
|
||||
headers-git 9.0.0.6357.eac8c38c1-1
|
||||
crt-git 9.0.0.6357.eac8c38c1-2
|
||||
libwinpthread-git 9.0.0.6357.eac8c38c1-1
|
||||
winpthreads-git 9.0.0.6357.eac8c38c1-1
|
||||
winstorecompat-git 9.0.0.6357.eac8c38c1-1
|
||||
gcc-libs 11.2.0-4
|
||||
gcc-ada 11.2.0-4
|
||||
gcc-fortran 11.2.0-4
|
||||
gcc-libgfortran 11.2.0-4
|
||||
gcc-objc 11.2.0-4
|
||||
gcc 11.2.0-4
|
||||
libgccjit 11.2.0-4
|
||||
tools-git 9.0.0.6357.eac8c38c1-1
|
||||
ninja 1.10.2-3
|
||||
pkgconf 1.8.0-2
|
||||
openal 1.21.1-3
|
||||
libpng 1.6.37-6
|
||||
freetype 2.11.1-1
|
||||
SDL2 2.0.18-2
|
||||
rtmidi 4.0.0-1
|
||||
cmake 3.22.1-1
|
||||
qt5-static 5.15.2-4
|
||||
ninja
|
||||
cmake
|
||||
gcc
|
||||
pkgconf
|
||||
openal
|
||||
freetype
|
||||
SDL2
|
||||
zlib
|
||||
libpng
|
||||
rtmidi
|
||||
qt5-static
|
||||
qt5-translations
|
||||
|
||||
@@ -19,11 +19,14 @@
|
||||
* Copyright 2017-2020 Fred N. van Kempen.
|
||||
* Copyright 2021 Laci bá'
|
||||
* Copyright 2021 dob205
|
||||
* Copyright 2021 Andreas J. Reichel.
|
||||
* Copyright 2021-2022 Jasmine Iwanek.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
@@ -68,6 +71,7 @@
|
||||
#include <86box/isartc.h>
|
||||
#include <86box/lpt.h>
|
||||
#include <86box/serial.h>
|
||||
#include <86box/serial_passthrough.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/mouse.h>
|
||||
#include <86box/gameport.h>
|
||||
@@ -162,6 +166,7 @@ int video_filter_method = 1; /* (C) video */
|
||||
int video_vsync = 0; /* (C) video */
|
||||
int video_framerate = -1; /* (C) video */
|
||||
char video_shader[512] = { '\0' }; /* (C) video */
|
||||
bool serial_passthrough_enabled[SERIAL_MAX] = { 0, 0, 0, 0 }; /* (C) activation and kind of pass-through for serial ports */
|
||||
int bugger_enabled = 0; /* (C) enable ISAbugger */
|
||||
int postcard_enabled = 0; /* (C) enable POST card */
|
||||
int isamem_type[ISAMEM_MAX] = { 0, 0, 0, 0 }; /* (C) enable ISA mem cards */
|
||||
@@ -1038,6 +1043,7 @@ pc_reset_hard_init(void)
|
||||
|
||||
/* Reset and reconfigure the serial ports. */
|
||||
serial_standalone_init();
|
||||
serial_passthrough_init();
|
||||
|
||||
/* Reset and reconfigure the Sound Card layer. */
|
||||
sound_card_reset();
|
||||
|
||||
@@ -851,9 +851,28 @@ pipc_sb_handlers(pipc_t *dev, uint8_t modem)
|
||||
|
||||
if (dev->ac97_regs[0][0x42] & 0x04) {
|
||||
io_sethandler(0x388, 4, pipc_fm_read, NULL, NULL, pipc_fm_write, NULL, NULL, dev);
|
||||
#ifndef VIA_PIPC_FM_EMULATION
|
||||
dev->sb->opl_enabled = 1;
|
||||
} else {
|
||||
dev->sb->opl_enabled = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pipc_sb_get_buffer(int32_t *buffer, int len, void *priv)
|
||||
{
|
||||
pipc_t *dev = (pipc_t *) priv;
|
||||
|
||||
/* Poll SB audio only if the legacy block is enabled. */
|
||||
#ifdef VIA_PIPC_FM_EMULATION
|
||||
if (dev->ac97_regs[0][0x42] & 0x01)
|
||||
#else
|
||||
if (dev->ac97_regs[0][0x42] & 0x05)
|
||||
#endif
|
||||
sb_get_buffer_sbpro(buffer, len, dev->sb);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
pipc_read(int func, int addr, void *priv)
|
||||
{
|
||||
@@ -1599,10 +1618,7 @@ pipc_init(const device_t *info)
|
||||
ac97_via_set_slot(dev->ac97, dev->slot, PCI_INTC);
|
||||
|
||||
dev->sb = device_add_inst(&sb_pro_compat_device, 2);
|
||||
#ifndef VIA_PIPC_FM_EMULATION
|
||||
dev->sb->opl_enabled = 1;
|
||||
#endif
|
||||
sound_add_handler(sb_get_buffer_sbpro, dev->sb);
|
||||
sound_add_handler(pipc_sb_get_buffer, dev);
|
||||
|
||||
dev->gameport = gameport_add(&gameport_sio_device);
|
||||
|
||||
|
||||
19
src/config.c
19
src/config.c
@@ -20,6 +20,8 @@
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
* Copyright 2018-2019 David Hrdlička.
|
||||
* Copyright 2021 Andreas J. Reichel.
|
||||
* Copyright 2021-2022 Jasmine Iwanek.
|
||||
*
|
||||
* NOTE: Forcing config files to be in Unicode encoding breaks
|
||||
* it on Windows XP, and possibly also Vista. Use the
|
||||
@@ -54,6 +56,8 @@
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/gameport.h>
|
||||
#include <86box/serial.h>
|
||||
#include <86box/serial_passthrough.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/mouse.h>
|
||||
#include <86box/thread.h>
|
||||
@@ -81,6 +85,7 @@ static ini_t config;
|
||||
static int backwards_compat = 0;
|
||||
static int backwards_compat2 = 0;
|
||||
|
||||
#define ENABLE_CONFIG_LOG 1
|
||||
#ifdef ENABLE_CONFIG_LOG
|
||||
int config_do_log = ENABLE_CONFIG_LOG;
|
||||
|
||||
@@ -836,6 +841,8 @@ load_ports(void)
|
||||
char temp[512];
|
||||
int c, d;
|
||||
|
||||
memset(temp, 0, sizeof(temp));
|
||||
|
||||
for (c = 0; c < SERIAL_MAX; c++) {
|
||||
sprintf(temp, "serial%d_enabled", c + 1);
|
||||
com_ports[c].enabled = !!ini_section_get_int(cat, temp, (c >= 2) ? 0 : 1);
|
||||
@@ -845,6 +852,12 @@ load_ports(void)
|
||||
p = (char *) ini_section_get_string(cat, temp, "none");
|
||||
com_ports[c].device = com_device_get_from_internal_name(p);
|
||||
*/
|
||||
|
||||
sprintf(temp, "serial%d_passthrough_enabled", c + 1);
|
||||
serial_passthrough_enabled[c] = !!ini_section_get_int(cat, temp, 0);
|
||||
|
||||
if (serial_passthrough_enabled[c])
|
||||
config_log("Serial Port %d: passthrough enabled.\n\n", c+1);
|
||||
}
|
||||
|
||||
for (c = 0; c < PARALLEL_MAX; c++) {
|
||||
@@ -2466,6 +2479,12 @@ save_ports(void)
|
||||
ini_section_set_string(cat, temp,
|
||||
(char *) com_device_get_internal_name(com_ports[c].device));
|
||||
*/
|
||||
|
||||
if (com_ports[c].enabled)
|
||||
if (serial_passthrough_enabled[c]) {
|
||||
sprintf(temp, "serial%d_passthrough_enabled", c + 1);
|
||||
ini_section_set_int(cat, temp, 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (c = 0; c < PARALLEL_MAX; c++) {
|
||||
|
||||
13
src/device.c
13
src/device.c
@@ -18,6 +18,8 @@
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
* Copyright 2008-2019 Sarah Walker.
|
||||
* Copyright 2021 Andreas J. Reichel.
|
||||
* Copyright 2021-2022 Jasmine Iwanek.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -91,6 +93,7 @@ device_set_context(device_context_t *c, const device_t *d, int inst)
|
||||
|
||||
memset(c, 0, sizeof(device_context_t));
|
||||
c->dev = d;
|
||||
c->instance = inst;
|
||||
if (inst) {
|
||||
sprintf(c->name, "%s #%i", d->name, inst);
|
||||
|
||||
@@ -556,6 +559,12 @@ device_force_redraw(void)
|
||||
}
|
||||
}
|
||||
|
||||
const int
|
||||
device_get_instance(void)
|
||||
{
|
||||
return device_current.instance;
|
||||
}
|
||||
|
||||
const char *
|
||||
device_get_config_string(const char *s)
|
||||
{
|
||||
@@ -748,7 +757,7 @@ device_is_valid(const device_t *device, int m)
|
||||
int
|
||||
machine_get_config_int(char *s)
|
||||
{
|
||||
const device_t *d = machine_getdevice(machine);
|
||||
const device_t *d = machine_get_device(machine);
|
||||
const device_config_t *c;
|
||||
|
||||
if (d == NULL)
|
||||
@@ -768,7 +777,7 @@ machine_get_config_int(char *s)
|
||||
char *
|
||||
machine_get_config_string(char *s)
|
||||
{
|
||||
const device_t *d = machine_getdevice(machine);
|
||||
const device_t *d = machine_get_device(machine);
|
||||
const device_config_t *c;
|
||||
|
||||
if (d == NULL)
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
#
|
||||
# Copyright 2020-2021 David Hrdlička.
|
||||
# Copyright 2021 Andreas J. Reichel.
|
||||
# Copyright 2021-2022 Jasmine Iwanek.
|
||||
#
|
||||
|
||||
add_library(dev OBJECT bugger.c cassette.c cartridge.c hasp.c hwm.c hwm_lm75.c hwm_lm78.c hwm_gl518sm.c
|
||||
@@ -18,7 +20,7 @@ add_library(dev OBJECT bugger.c cassette.c cartridge.c hasp.c hwm.c hwm_lm75.c h
|
||||
postcard.c serial.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c
|
||||
smbus_piix4.c smbus_ali7101.c keyboard.c keyboard_xt.c keyboard_at.c
|
||||
mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c phoenix_486_jumper.c
|
||||
mouse_wacom_tablet.c)
|
||||
mouse_wacom_tablet.c serial_passthrough.c)
|
||||
|
||||
if(ISAMEM_RAMPAGE)
|
||||
target_compile_definitions(dev PRIVATE USE_ISAMEM_RAMPAGE)
|
||||
|
||||
@@ -191,6 +191,12 @@ ps2_write(uint8_t val, void *priv)
|
||||
keyboard_at_adddata_mouse(dev->sample_rate);
|
||||
break;
|
||||
|
||||
case 0xea: /* set stream */
|
||||
dev->flags &= ~FLAG_CTRLDAT;
|
||||
mouse_scan = 1;
|
||||
keyboard_at_adddata_mouse(0xfa); /* ACK for command byte */
|
||||
break;
|
||||
|
||||
case 0xeb: /* Get mouse data */
|
||||
keyboard_at_adddata_mouse(0xfa);
|
||||
|
||||
|
||||
@@ -93,6 +93,8 @@ serial_transmit_period(serial_t *dev)
|
||||
|
||||
/* Bit period based on DLAB. */
|
||||
dev->transmit_period = (16000000.0 * ddlab) / dev->clock_src;
|
||||
if (dev->sd && dev->sd->transmit_period_callback)
|
||||
dev->sd->transmit_period_callback(dev, dev->sd->priv, dev->transmit_period);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -161,7 +163,7 @@ write_fifo(serial_t *dev, uint8_t dat)
|
||||
dev->lsr |= 0x01;
|
||||
dev->int_status |= SERIAL_INT_RECEIVE;
|
||||
}
|
||||
if (dev->rcvr_fifo_pos < 15)
|
||||
if (dev->rcvr_fifo_pos < (dev->rcvr_fifo_len - 1))
|
||||
dev->rcvr_fifo_pos++;
|
||||
else
|
||||
dev->rcvr_fifo_full = 1;
|
||||
@@ -175,6 +177,8 @@ write_fifo(serial_t *dev, uint8_t dat)
|
||||
dev->dat = dat;
|
||||
dev->lsr |= 0x01;
|
||||
dev->int_status |= SERIAL_INT_RECEIVE;
|
||||
if (dev->lsr & 0x02)
|
||||
dev->int_status |= SERIAL_INT_LSR;
|
||||
serial_update_ints(dev);
|
||||
}
|
||||
}
|
||||
@@ -311,6 +315,22 @@ serial_timeout_timer(void *priv)
|
||||
serial_update_ints(dev);
|
||||
}
|
||||
|
||||
void
|
||||
serial_device_timeout(void *priv)
|
||||
{
|
||||
serial_t *dev = (serial_t *) priv;
|
||||
|
||||
#ifdef ENABLE_SERIAL_LOG
|
||||
serial_log("serial_device_timeout()\n");
|
||||
#endif
|
||||
|
||||
if (!dev->fifo_enabled) {
|
||||
dev->lsr |= 0x10;
|
||||
dev->int_status |= SERIAL_INT_LSR;
|
||||
serial_update_ints(dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
serial_update_speed(serial_t *dev)
|
||||
{
|
||||
@@ -331,6 +351,63 @@ serial_reset_fifo(serial_t *dev)
|
||||
dev->rcvr_fifo_full = 0;
|
||||
}
|
||||
|
||||
void
|
||||
serial_set_dsr(serial_t *dev, uint8_t enabled)
|
||||
{
|
||||
if (dev->mctrl & 0x10)
|
||||
return;
|
||||
|
||||
dev->msr &= ~0x2;
|
||||
dev->msr |= !!((dev->msr & 0x20) ^ (enabled << 5)) << 1;
|
||||
dev->msr &= ~0x20;
|
||||
dev->msr |= (!!enabled) << 5;
|
||||
dev->msr_set &= ~0x20;
|
||||
dev->msr_set |= (!!enabled) << 5;
|
||||
|
||||
if (dev->msr & 0x2) {
|
||||
dev->int_status |= SERIAL_INT_MSR;
|
||||
serial_update_ints(dev);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
serial_set_cts(serial_t *dev, uint8_t enabled)
|
||||
{
|
||||
if (dev->mctrl & 0x10)
|
||||
return;
|
||||
|
||||
dev->msr &= ~0x1;
|
||||
dev->msr |= !!((dev->msr & 0x10) ^ (enabled << 4));
|
||||
dev->msr &= ~0x10;
|
||||
dev->msr |= (!!enabled) << 4;
|
||||
dev->msr_set &= ~0x10;
|
||||
dev->msr_set |= (!!enabled) << 4;
|
||||
|
||||
if (dev->msr & 0x1) {
|
||||
dev->int_status |= SERIAL_INT_MSR;
|
||||
serial_update_ints(dev);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
serial_set_dcd(serial_t *dev, uint8_t enabled)
|
||||
{
|
||||
if (dev->mctrl & 0x10)
|
||||
return;
|
||||
|
||||
dev->msr &= ~0x8;
|
||||
dev->msr |= !!((dev->msr & 0x80) ^ (enabled << 7));
|
||||
dev->msr &= ~0x80;
|
||||
dev->msr |= (!!enabled) << 7;
|
||||
dev->msr_set &= ~0x80;
|
||||
dev->msr_set |= (!!enabled) << 7;
|
||||
|
||||
if (dev->msr & 0x8) {
|
||||
dev->int_status |= SERIAL_INT_MSR;
|
||||
serial_update_ints(dev);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
serial_set_clock_src(serial_t *dev, double clock_src)
|
||||
{
|
||||
@@ -431,7 +508,7 @@ serial_write(uint16_t addr, uint8_t val, void *p)
|
||||
case 3:
|
||||
old = dev->lcr;
|
||||
dev->lcr = val;
|
||||
if ((old ^ val) & 0x0f) {
|
||||
if ((old ^ val) & 0x3f) {
|
||||
/* Data bits + start bit. */
|
||||
dev->bits = ((dev->lcr & 0x03) + 5) + 1;
|
||||
/* Stop bits. */
|
||||
@@ -444,11 +521,14 @@ serial_write(uint16_t addr, uint8_t val, void *p)
|
||||
|
||||
serial_transmit_period(dev);
|
||||
serial_update_speed(dev);
|
||||
|
||||
if (dev->sd && dev->sd->lcr_callback)
|
||||
dev->sd->lcr_callback(dev, dev->sd->priv, dev->lcr);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if ((val & 2) && !(dev->mctrl & 2)) {
|
||||
if (dev->sd->rcr_callback)
|
||||
if (dev->sd && dev->sd->rcr_callback)
|
||||
dev->sd->rcr_callback(dev, dev->sd->priv);
|
||||
}
|
||||
if (!(val & 8) && (dev->mctrl & 8))
|
||||
@@ -487,7 +567,7 @@ serial_write(uint16_t addr, uint8_t val, void *p)
|
||||
serial_update_ints(dev);
|
||||
break;
|
||||
case 6:
|
||||
dev->msr = val;
|
||||
dev->msr = (val & 0xF0) | (dev->msr & 0x0F);
|
||||
if (dev->msr & 0x0f)
|
||||
dev->int_status |= SERIAL_INT_MSR;
|
||||
serial_update_ints(dev);
|
||||
@@ -521,11 +601,15 @@ serial_read(uint16_t addr, void *p)
|
||||
|
||||
ret = dev->rcvr_fifo[0];
|
||||
dev->rcvr_fifo_full = 0;
|
||||
|
||||
for (i = 1; i < 16; i++)
|
||||
dev->rcvr_fifo[i - 1] = dev->rcvr_fifo[i];
|
||||
|
||||
dev->rcvr_fifo_pos--;
|
||||
|
||||
if (dev->rcvr_fifo_pos > 0) {
|
||||
for (i = 1; i < 16; i++)
|
||||
dev->rcvr_fifo[i - 1] = dev->rcvr_fifo[i];
|
||||
serial_log("FIFO position %i: read %02X, next %02X\n", dev->rcvr_fifo_pos, ret, dev->rcvr_fifo[0]);
|
||||
dev->rcvr_fifo_pos--;
|
||||
|
||||
/* At least one byte remains to be read, start the timeout
|
||||
timer so that a timeout is indicated in case of no read. */
|
||||
timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period);
|
||||
@@ -571,7 +655,7 @@ serial_read(uint16_t addr, void *p)
|
||||
serial_update_ints(dev);
|
||||
break;
|
||||
case 6:
|
||||
ret = dev->msr;
|
||||
ret = dev->msr | dev->msr_set;
|
||||
dev->msr &= ~0x0f;
|
||||
dev->int_status &= ~SERIAL_INT_MSR;
|
||||
serial_update_ints(dev);
|
||||
@@ -630,9 +714,30 @@ serial_attach(int port,
|
||||
{
|
||||
serial_device_t *sd = &serial_devices[port];
|
||||
|
||||
sd->rcr_callback = rcr_callback;
|
||||
sd->dev_write = dev_write;
|
||||
sd->priv = priv;
|
||||
sd->rcr_callback = rcr_callback;
|
||||
sd->dev_write = dev_write;
|
||||
sd->transmit_period_callback = NULL;
|
||||
sd->lcr_callback = NULL;
|
||||
sd->priv = priv;
|
||||
|
||||
return sd->serial;
|
||||
}
|
||||
|
||||
serial_t *
|
||||
serial_attach_ex(int port,
|
||||
void (*rcr_callback)(struct serial_s *serial, void *p),
|
||||
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data),
|
||||
void (*transmit_period_callback)(struct serial_s *serial, void *p, double transmit_period),
|
||||
void (*lcr_callback)(struct serial_s *serial, void *p, uint8_t data_bits),
|
||||
void *priv)
|
||||
{
|
||||
serial_device_t *sd = &serial_devices[port];
|
||||
|
||||
sd->rcr_callback = rcr_callback;
|
||||
sd->dev_write = dev_write;
|
||||
sd->transmit_period_callback = transmit_period_callback;
|
||||
sd->lcr_callback = lcr_callback;
|
||||
sd->priv = priv;
|
||||
|
||||
return sd->serial;
|
||||
}
|
||||
|
||||
357
src/device/serial_passthrough.c
Normal file
357
src/device/serial_passthrough.c
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of Serial passthrough device.
|
||||
*
|
||||
*
|
||||
* Authors: Andreas J. Reichel <webmaster@6th-dimension.com>,
|
||||
* Jasmine Iwanek <jasmine@iwanek.co.uk>
|
||||
*
|
||||
* Copyright 2021 Andreas J. Reichel.
|
||||
* Copyright 2021-2022 Jasmine Iwanek.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/serial.h>
|
||||
#include <86box/serial_passthrough.h>
|
||||
#include <86box/plat_serial_passthrough.h>
|
||||
|
||||
#define ENABLE_SERIAL_PASSTHROUGH_LOG 1
|
||||
#ifdef ENABLE_SERIAL_PASSTHROUGH_LOG
|
||||
int serial_passthrough_do_log = ENABLE_SERIAL_PASSTHROUGH_LOG;
|
||||
|
||||
static void
|
||||
serial_passthrough_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (serial_passthrough_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define serial_passthrough_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
void
|
||||
serial_passthrough_init(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
for (c = 0; c < SERIAL_MAX; c++) {
|
||||
if (serial_passthrough_enabled[c]) {
|
||||
/* Instance n for COM n */
|
||||
device_add_inst(&serial_passthrough_device, c + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
serial_passthrough_timers_off(serial_passthrough_t *dev)
|
||||
{
|
||||
timer_stop(&dev->host_to_serial_timer);
|
||||
}
|
||||
|
||||
static void
|
||||
serial_passthrough_write(serial_t *s, void *priv, uint8_t val)
|
||||
{
|
||||
plat_serpt_write(priv, val);
|
||||
}
|
||||
|
||||
static void
|
||||
host_to_serial_cb(void *priv)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *) priv;
|
||||
|
||||
uint8_t byte;
|
||||
|
||||
/* write_fifo has no failure indication, but if we write to fast, the host
|
||||
* can never fetch the bytes in time, so check if the fifo is full if in
|
||||
* fifo mode or if lsr has bit 0 set if not in fifo mode */
|
||||
if ((dev->serial->type >= SERIAL_16550) && dev->serial->fifo_enabled) {
|
||||
if (dev->serial->rcvr_fifo_full) {
|
||||
goto no_write_to_machine;
|
||||
}
|
||||
} else {
|
||||
if (dev->serial->lsr & 1) {
|
||||
goto no_write_to_machine;
|
||||
}
|
||||
}
|
||||
if (plat_serpt_read(dev, &byte)) {
|
||||
// printf("got byte %02X\n", byte);
|
||||
serial_write_fifo(dev->serial, byte);
|
||||
// serial_set_dsr(dev->serial, 1);
|
||||
}
|
||||
no_write_to_machine:
|
||||
// serial_device_timeout(dev->serial);
|
||||
timer_on_auto(&dev->host_to_serial_timer, (1000000.0 / dev->baudrate) * (double) dev->bits);
|
||||
}
|
||||
|
||||
static void
|
||||
serial_passthrough_rcr_cb(struct serial_s *serial, void *priv)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *) priv;
|
||||
|
||||
timer_stop(&dev->host_to_serial_timer);
|
||||
/* FIXME: do something to dev->baudrate */
|
||||
timer_on_auto(&dev->host_to_serial_timer, (1000000.0 / dev->baudrate) * (double) dev->bits);
|
||||
// serial_clear_fifo(dev->serial);
|
||||
}
|
||||
|
||||
static void
|
||||
serial_passthrough_speed_changed(void *priv)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *) priv;
|
||||
|
||||
timer_stop(&dev->host_to_serial_timer);
|
||||
/* FIXME: do something to dev->baudrate */
|
||||
timer_on_auto(&dev->host_to_serial_timer, (1000000.0 / dev->baudrate) * (double) dev->bits);
|
||||
// serial_clear_fifo(dev->serial);
|
||||
}
|
||||
|
||||
static void
|
||||
serial_passthrough_dev_close(void *priv)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *) priv;
|
||||
|
||||
/* Detach passthrough device from COM port */
|
||||
if (dev && dev->serial && dev->serial->sd)
|
||||
memset(dev->serial->sd, 0, sizeof(serial_device_t));
|
||||
|
||||
plat_serpt_close(dev);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
void
|
||||
serial_passthrough_transmit_period(serial_t *serial, void *p, double transmit_period)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||
|
||||
if (dev->mode != SERPT_MODE_HOSTSER)
|
||||
return;
|
||||
dev->baudrate = 1000000.0 / (transmit_period);
|
||||
|
||||
serial_passthrough_speed_changed(p);
|
||||
plat_serpt_set_params(dev);
|
||||
}
|
||||
|
||||
void
|
||||
serial_passthrough_lcr_callback(serial_t *serial, void *p, uint8_t lcr)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||
|
||||
if (dev->mode != SERPT_MODE_HOSTSER)
|
||||
return;
|
||||
dev->bits = serial->bits;
|
||||
dev->data_bits = ((lcr & 0x03) + 5);
|
||||
serial_passthrough_speed_changed(p);
|
||||
plat_serpt_set_params(dev);
|
||||
}
|
||||
|
||||
/* Initialize the device for use by the user. */
|
||||
static void *
|
||||
serial_passthrough_dev_init(const device_t *info)
|
||||
{
|
||||
serial_passthrough_t *dev;
|
||||
|
||||
dev = (serial_passthrough_t *) malloc(sizeof(serial_passthrough_t));
|
||||
memset(dev, 0, sizeof(serial_passthrough_t));
|
||||
dev->mode = device_get_config_int("mode");
|
||||
|
||||
dev->port = device_get_instance() - 1;
|
||||
dev->baudrate = device_get_config_int("baudrate");
|
||||
dev->data_bits = device_get_config_int("data_bits");
|
||||
|
||||
/* Attach passthrough device to a COM port */
|
||||
dev->serial = serial_attach_ex(dev->port, serial_passthrough_rcr_cb,
|
||||
serial_passthrough_write, serial_passthrough_transmit_period, serial_passthrough_lcr_callback, dev);
|
||||
|
||||
strncpy(dev->host_serial_path, device_get_config_string("host_serial_path"), 1024);
|
||||
|
||||
serial_passthrough_log("%s: port=COM%d\n", info->name, dev->port + 1);
|
||||
serial_passthrough_log("%s: baud=%f\n", info->name, dev->baudrate);
|
||||
serial_passthrough_log("%s: mode=%s\n", info->name, serpt_mode_names[dev->mode]);
|
||||
|
||||
if (plat_serpt_open_device(dev)) {
|
||||
serial_passthrough_log("%s: not running\n", info->name);
|
||||
return NULL;
|
||||
}
|
||||
serial_passthrough_log("%s: running\n", info->name);
|
||||
|
||||
memset(&dev->host_to_serial_timer, 0, sizeof(pc_timer_t));
|
||||
timer_add(&dev->host_to_serial_timer, host_to_serial_cb, dev, 1);
|
||||
serial_set_cts(dev->serial, 1);
|
||||
serial_set_dsr(dev->serial, 1);
|
||||
serial_set_dcd(dev->serial, 1);
|
||||
|
||||
/* 1 start bit + data bits + stop bits (no parity assumed) */
|
||||
dev->bits = 1 + device_get_config_int("data_bits") + device_get_config_int("stop_bits");
|
||||
|
||||
/* Return our private data to the I/O layer. */
|
||||
return dev;
|
||||
}
|
||||
|
||||
const char *serpt_mode_names[SERPT_MODES_MAX] = {
|
||||
[SERPT_MODE_VCON] = "vcon",
|
||||
[SERPT_MODE_TCPSRV] = "tcpsrv",
|
||||
[SERPT_MODE_TCPCLNT] = "tcpclnt",
|
||||
[SERPT_MODE_HOSTSER] = "hostser",
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
static const device_config_t serial_passthrough_config[] = {
|
||||
{
|
||||
.name = "mode",
|
||||
.description = "Passthrough Mode",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = "",
|
||||
.default_int = 0,
|
||||
.file_filter = "",
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
#ifdef _WIN32
|
||||
{
|
||||
.description = "Named Pipe (Server)",
|
||||
.value = SERPT_MODE_VCON
|
||||
},
|
||||
#if 0 /* TODO */
|
||||
{
|
||||
.description = "Named Pipe (Client)",
|
||||
.value = SERPT_MODE_VCON
|
||||
},
|
||||
#endif
|
||||
#else
|
||||
{
|
||||
.description = "Pseudo Terminal/Virtual Console",
|
||||
.value = SERPT_MODE_VCON
|
||||
},
|
||||
#endif
|
||||
#if 0 /* TODO */
|
||||
{
|
||||
.description = "TCP Server",
|
||||
.value = SERPT_MODE_TCPSRV
|
||||
},
|
||||
{
|
||||
.description = "TCP Client",
|
||||
.value = SERPT_MODE_TCPCLNT
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.description = "Host Serial Passthrough",
|
||||
.value = SERPT_MODE_HOSTSER
|
||||
},
|
||||
{
|
||||
.description = ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
.name = "host_serial_path",
|
||||
.description = "Host Serial Device",
|
||||
.type = CONFIG_SERPORT,
|
||||
.default_string = "",
|
||||
.file_filter = NULL,
|
||||
.spinner = {},
|
||||
.selection = {}
|
||||
},
|
||||
{
|
||||
.name = "data_bits",
|
||||
.description = "Data bits",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = "8",
|
||||
.default_int = 8,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
#if 0 /* Mentioned by WFW 3.1x, not supported, atleast on Linux */
|
||||
{ .description = "4", .value = 4 },
|
||||
#endif
|
||||
{ .description = "5", .value = 5 },
|
||||
{ .description = "6", .value = 6 },
|
||||
{ .description = "7", .value = 7 },
|
||||
{ .description = "8", .value = 8 }
|
||||
}
|
||||
},
|
||||
{
|
||||
.name = "stop_bits",
|
||||
.description = "Stop bits",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = "1",
|
||||
.default_int = 1,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "1", .value = 1 },
|
||||
#if 0
|
||||
{ .description = "1.5", .value = 1.5 },
|
||||
#endif
|
||||
{ .description = "2", .value = 2 }
|
||||
}
|
||||
},
|
||||
{
|
||||
.name = "baudrate",
|
||||
.description = "Baud Rate of Passthrough",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = "",
|
||||
.default_int = 115200,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
#if 0
|
||||
{ .description = "256000", .value = 256000 },
|
||||
{ .description = "128000", .value = 128000 },
|
||||
#endif
|
||||
{ .description = "115200", .value = 115200 },
|
||||
{ .description = "57600", .value = 57600 },
|
||||
{ .description = "56000", .value = 56000 },
|
||||
{ .description = "38400", .value = 38400 },
|
||||
{ .description = "19200", .value = 19200 },
|
||||
{ .description = "14400", .value = 14400 },
|
||||
{ .description = "9600", .value = 9600 },
|
||||
{ .description = "7200", .value = 7200 },
|
||||
{ .description = "4800", .value = 4800 },
|
||||
{ .description = "2400", .value = 2400 },
|
||||
{ .description = "1800", .value = 1800 },
|
||||
{ .description = "1200", .value = 1200 },
|
||||
{ .description = "600", .value = 600 },
|
||||
{ .description = "300", .value = 300 },
|
||||
{ .description = "150", .value = 150 },
|
||||
#if 0
|
||||
{ .description = "134.5", .value = 134.5 },
|
||||
#endif
|
||||
{ .description = "110", .value = 110 },
|
||||
{ .description = "75", .value = 75 }
|
||||
}
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
const device_t serial_passthrough_device = {
|
||||
.name = "Serial Passthrough Device",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = serial_passthrough_dev_init,
|
||||
.close = serial_passthrough_dev_close,
|
||||
.reset = NULL,
|
||||
{ .poll = NULL },
|
||||
.speed_changed = serial_passthrough_speed_changed,
|
||||
.force_redraw = NULL,
|
||||
.config = serial_passthrough_config
|
||||
};
|
||||
@@ -60,7 +60,7 @@ enum {
|
||||
CDROM_BUS_USB
|
||||
};
|
||||
|
||||
#define KNOWN_CDROM_DRIVE_TYPES 30
|
||||
#define KNOWN_CDROM_DRIVE_TYPES 35
|
||||
#define BUS_TYPE_ALL 0
|
||||
#define BUS_TYPE_IDE 1
|
||||
#define BUS_TYPE_SCSI 2
|
||||
@@ -75,36 +75,41 @@ static const struct
|
||||
const int bus_type;
|
||||
} cdrom_drive_types[] =
|
||||
{
|
||||
{ "86BOX", "CD-ROM", "1.00", "(ATAPI/SCSI) 86BOX CD-ROM 1.00", "86BOX_CD-ROM_1.00", BUS_TYPE_ALL},
|
||||
{ "AZT", "CDA46802I", "1.15", "(ATAPI) AZT CDA46802I 1.15", "AZT_CDA46802I_1.15", BUS_TYPE_IDE},
|
||||
{ "BTC", "CD-ROM BCD36XH", "U1.0", "(ATAPI) BTC CD-ROM BCD36XH U1.0", "BTC_CD-ROM_BCD36XH_U1.0", BUS_TYPE_IDE},
|
||||
{ "GOLDSTAR", "CRD-8160B", "3.14", "(ATAPI) GOLDSTAR CRD-8160B 3.14", "GOLDSTAR_CRD-8160B_3.14", BUS_TYPE_IDE},
|
||||
{ "HITACHI", "CDR-8130", "0020", "(ATAPI) HITACHI CDR-8130 0020", "HITACHI_CDR-8130_0020", BUS_TYPE_IDE},
|
||||
{ "KENWOOD", "CD-ROM UCR-421", "208E", "(ATAPI) KENWOOD CD-ROM UCR-421 208E", "KENWOOD_CD-ROM_UCR-421_208E", BUS_TYPE_IDE},
|
||||
{ "MATSHITA", "CD-ROM CR-587", "7S13", "(ATAPI) MATSHITA CD-ROM CR-587 7S13", "MATSHITA_CD-ROM_CR-587_7S13", BUS_TYPE_IDE},
|
||||
{ "MATSHITA", "CD-ROM CR-588", "LS15", "(ATAPI) MATSHITA CD-ROM CR-588 LS15", "MATSHITA_CD-ROM_CR-588_LS15", BUS_TYPE_IDE},
|
||||
{ "MITSUMI", "CRMC-FX4820T", "D02A", "(ATAPI) MITSUMI CRMC-FX4820T D02A", "MITSUMI_CRMC-FX4820T_D02A", BUS_TYPE_IDE},
|
||||
{ "NEC", "CD-ROM DRIVE:260", "1.00", "(ATAPI) NEC CD-ROM DRIVE:260 1.00", "NEC_CD-ROM_DRIVE260_1.00", BUS_TYPE_IDE},
|
||||
{ "NEC", "CD-ROM DRIVE:260", "1.01", "(ATAPI) NEC CD-ROM DRIVE:260 1.01", "NEC_CD-ROM_DRIVE260_1.01", BUS_TYPE_IDE},
|
||||
{ "NEC", "CDR-1300A", "1.05", "(ATAPI) NEC CDR-1300A 1.05", "NEC_CDR-1300A_1.05", BUS_TYPE_IDE},
|
||||
{ "PHILIPS", "CD-ROM PCA403CD", "U31P", "(ATAPI) PHILIPS CD-ROM PCA403CD U31P", "PHILIPS_CD-ROM_PCA403CD_U31P", BUS_TYPE_IDE},
|
||||
{ "SONY", "CD-ROM CDU76", "1.0i", "(ATAPI) SONY CD-ROM CDU76 1.0i", "SONY_CD-ROM_CDU76_1.0i", BUS_TYPE_IDE},
|
||||
{ "SONY", "CD-ROM CDU311", "3.0h", "(ATAPI) SONY CD-ROM CDU311 3.0h", "SONY_CD-ROM_CDU311_3.0h", BUS_TYPE_IDE},
|
||||
{ "TOSHIBA", "CD-ROM XM-5702B", "TA70", "(ATAPI) TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE},
|
||||
{ "CHINON", "CD-ROM CDS-431", "H42 ", "(SCSI) CHINON CD-ROM CDS-431 H42", "CHINON_CD-ROM_CDS-431_H42", BUS_TYPE_SCSI},
|
||||
{ "DEC", "RRD45 (C) DEC", "0436", "(SCSI) DEC RRD45 0436", "DEC_RRD45_0436", BUS_TYPE_SCSI},
|
||||
{ "MATSHITA", "CD-ROM CR-501", "1.0b", "(SCSI) MATSHITA CD-ROM CR-501 1.0b", "MATSHITA_CD-ROM_CR-501_1.0b", BUS_TYPE_SCSI},
|
||||
{ "NEC", "CD-ROM DRIVE:74", "1.00", "(SCSI) NEC CD-ROM DRIVE:74 1.00", "NEC_CD-ROM_DRIVE74_1.00", BUS_TYPE_SCSI},
|
||||
{ "NEC", "CD-ROM DRIVE:464", "1.05", "(SCSI) NEC CD-ROM DRIVE:464 1.05", "NEC_CD-ROM_DRIVE464_1.05", BUS_TYPE_SCSI},
|
||||
{ "SONY", "CD-ROM CDU-541", "1.0i", "(SCSI) SONY CD-ROM CDU-541 1.0i", "SONY_CD-ROM_CDU-541_1.0i", BUS_TYPE_SCSI},
|
||||
{ "SONY", "CD-ROM CDU-76S", "1.00", "(SCSI) SONY CD-ROM CDU-76S 1.00", "SONY_CD-ROM_CDU-76S_1.00", BUS_TYPE_SCSI},
|
||||
{ "PHILIPS", "CDD2600", "1.07", "(SCSI) PHILIPS CDD2600 1.07", "PHILIPS_CDD2600_1.07", BUS_TYPE_SCSI},
|
||||
{ "PIONEER", "CD-ROM DRM-604X", "2403", "(SCSI) PIONEER CD-ROM DRM-604X 2403", "PIONEER_CD-ROM_DRM-604X_2403", BUS_TYPE_SCSI},
|
||||
{ "PLEXTOR", "CD-ROM PX-32TS", "1.03", "(SCSI) PLEXTOR CD-ROM PX-32TS 1.03", "PLEXTOR_CD-ROM_PX-32TS_1.03", BUS_TYPE_SCSI},
|
||||
{ "TEAC", "CD-R55S", "1.0R", "(SCSI) TEAC CD-R55S 1.0R", "TEAC_CD-R55S_1.0R", BUS_TYPE_SCSI},
|
||||
{ "TOSHIBA", "CD-ROM DRIVE:XM", "3433", "(SCSI) TOSHIBA CD-ROM DRIVE:XM 3433", "TOSHIBA_CD-ROM_DRIVEXM_3433", BUS_TYPE_SCSI},
|
||||
{ "TOSHIBA", "CD-ROM XM-3301TA", "0272", "(SCSI) TOSHIBA CD-ROM XM-3301TA 0272", "TOSHIBA_CD-ROM_XM-3301TA_0272", BUS_TYPE_SCSI},
|
||||
{ "TOSHIBA", "CD-ROM XM-5701TA", "3136", "(SCSI) TOSHIBA CD-ROM XM-5701TA 3136", "TOSHIBA_CD-ROM_XM-5701TA_3136", BUS_TYPE_SCSI},
|
||||
{ "86BOX", "CD-ROM", "1.00", "(ATAPI/SCSI) 86BOX CD-ROM 1.00", "86BOX_CD-ROM_1.00", BUS_TYPE_ALL}, /*1*/
|
||||
{ "AZT", "CDA46802I", "1.15", "(ATAPI) AZT CDA46802I 1.15", "AZT_CDA46802I_1.15", BUS_TYPE_IDE}, /*2*/
|
||||
{ "BTC", "CD-ROM BCD36XH", "U1.0", "(ATAPI) BTC CD-ROM BCD36XH U1.0", "BTC_CD-ROM_BCD36XH_U1.0", BUS_TYPE_IDE}, /*3*/
|
||||
{ "GOLDSTAR", "CRD-8160B", "3.14", "(ATAPI) GOLDSTAR CRD-8160B 3.14", "GOLDSTAR_CRD-8160B_3.14", BUS_TYPE_IDE}, /*4*/
|
||||
{ "HITACHI", "CDR-8130", "0020", "(ATAPI) HITACHI CDR-8130 0020", "HITACHI_CDR-8130_0020", BUS_TYPE_IDE}, /*5*/
|
||||
{ "KENWOOD", "CD-ROM UCR-421", "208E", "(ATAPI) KENWOOD CD-ROM UCR-421 208E", "KENWOOD_CD-ROM_UCR-421_208E", BUS_TYPE_IDE}, /*6*/
|
||||
{ "MATSHITA", "CD-ROM CR-587", "7S13", "(ATAPI) MATSHITA CD-ROM CR-587 7S13", "MATSHITA_CD-ROM_CR-587_7S13", BUS_TYPE_IDE}, /*7*/
|
||||
{ "MATSHITA", "CD-ROM CR-588", "LS15", "(ATAPI) MATSHITA CD-ROM CR-588 LS15", "MATSHITA_CD-ROM_CR-588_LS15", BUS_TYPE_IDE}, /*8*/
|
||||
{ "MATSHITA", "CR-571", "1.0e", "(ATAPI) MATSHITA CR-571 1.0e", "MATSHITA_CR-571_1.0e", BUS_TYPE_IDE}, /*9*/
|
||||
{ "MATSHITA", "CR-572", "1.0j", "(ATAPI) MATSHITA CR-572 1.0j", "MATSHITA_CR-572_1.0j", BUS_TYPE_IDE}, /*10*/
|
||||
{ "MITSUMI", "CRMC-FX4820T", "D02A", "(ATAPI) MITSUMI CRMC-FX4820T D02A", "MITSUMI_CRMC-FX4820T_D02A", BUS_TYPE_IDE}, /*11*/
|
||||
{ "NEC", "CD-ROM DRIVE:260", "1.00", "(ATAPI) NEC CD-ROM DRIVE:260 1.00", "NEC_CD-ROM_DRIVE260_1.00", BUS_TYPE_IDE}, /*12*/
|
||||
{ "NEC", "CD-ROM DRIVE:260", "1.01", "(ATAPI) NEC CD-ROM DRIVE:260 1.01", "NEC_CD-ROM_DRIVE260_1.01", BUS_TYPE_IDE}, /*13*/
|
||||
{ "NEC", "CD-ROM DRIVE:273", "4.20", "(ATAPI) NEC CD-ROM DRIVE:273 4.20", "NEC_CD-ROM_DRIVE273_4.20", BUS_TYPE_IDE}, /*14*/
|
||||
{ "NEC", "CD-ROM DRIVE:280", "1.05", "(ATAPI) NEC CD-ROM DRIVE:280 1.05", "NEC_CD-ROM_DRIVE280_1.05", BUS_TYPE_IDE}, /*15*/
|
||||
{ "NEC", "CD-ROM DRIVE:280", "3.08", "(ATAPI) NEC CD-ROM DRIVE:280 3.08", "NEC_CD-ROM_DRIVE280_3.08", BUS_TYPE_IDE}, /*16*/
|
||||
{ "PHILIPS", "CD-ROM PCA403CD", "U31P", "(ATAPI) PHILIPS CD-ROM PCA403CD U31P", "PHILIPS_CD-ROM_PCA403CD_U31P", BUS_TYPE_IDE}, /*17*/
|
||||
{ "SONY", "CD-ROM CDU76", "1.0i", "(ATAPI) SONY CD-ROM CDU76 1.0i", "SONY_CD-ROM_CDU76_1.0i", BUS_TYPE_IDE}, /*18*/
|
||||
{ "SONY", "CD-ROM CDU311", "3.0h", "(ATAPI) SONY CD-ROM CDU311 3.0h", "SONY_CD-ROM_CDU311_3.0h", BUS_TYPE_IDE}, /*19*/
|
||||
{ "TOSHIBA", "CD-ROM XM-5302TA", "0305", "(ATAPI) TOSHIBA CD-ROM XM-5302TA 0305", "TOSHIBA_CD-ROM_XM-5302TA_0305", BUS_TYPE_IDE}, /*20*/
|
||||
{ "TOSHIBA", "CD-ROM XM-5702B", "TA70", "(ATAPI) TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE}, /*21*/
|
||||
{ "CHINON", "CD-ROM CDS-431", "H42 ", "(SCSI) CHINON CD-ROM CDS-431 H42", "CHINON_CD-ROM_CDS-431_H42", BUS_TYPE_SCSI}, /*22*/
|
||||
{ "DEC", "RRD45 (C) DEC", "0436", "(SCSI) DEC RRD45 0436", "DEC_RRD45_0436", BUS_TYPE_SCSI}, /*23*/
|
||||
{ "MATSHITA", "CD-ROM CR-501", "1.0b", "(SCSI) MATSHITA CD-ROM CR-501 1.0b", "MATSHITA_CD-ROM_CR-501_1.0b", BUS_TYPE_SCSI}, /*24*/
|
||||
{ "NEC", "CD-ROM DRIVE:74", "1.00", "(SCSI) NEC CD-ROM DRIVE:74 1.00", "NEC_CD-ROM_DRIVE74_1.00", BUS_TYPE_SCSI}, /*25*/
|
||||
{ "NEC", "CD-ROM DRIVE:464", "1.05", "(SCSI) NEC CD-ROM DRIVE:464 1.05", "NEC_CD-ROM_DRIVE464_1.05", BUS_TYPE_SCSI}, /*26*/
|
||||
{ "SONY", "CD-ROM CDU-541", "1.0i", "(SCSI) SONY CD-ROM CDU-541 1.0i", "SONY_CD-ROM_CDU-541_1.0i", BUS_TYPE_SCSI}, /*27*/
|
||||
{ "SONY", "CD-ROM CDU-76S", "1.00", "(SCSI) SONY CD-ROM CDU-76S 1.00", "SONY_CD-ROM_CDU-76S_1.00", BUS_TYPE_SCSI}, /*28*/
|
||||
{ "PHILIPS", "CDD2600", "1.07", "(SCSI) PHILIPS CDD2600 1.07", "PHILIPS_CDD2600_1.07", BUS_TYPE_SCSI}, /*29*/
|
||||
{ "PIONEER", "CD-ROM DRM-604X", "2403", "(SCSI) PIONEER CD-ROM DRM-604X 2403", "PIONEER_CD-ROM_DRM-604X_2403", BUS_TYPE_SCSI}, /*30*/
|
||||
{ "PLEXTOR", "CD-ROM PX-32TS", "1.03", "(SCSI) PLEXTOR CD-ROM PX-32TS 1.03", "PLEXTOR_CD-ROM_PX-32TS_1.03", BUS_TYPE_SCSI}, /*31*/
|
||||
{ "TEAC", "CD-R55S", "1.0R", "(SCSI) TEAC CD-R55S 1.0R", "TEAC_CD-R55S_1.0R", BUS_TYPE_SCSI}, /*32*/
|
||||
{ "TOSHIBA", "CD-ROM DRIVE:XM", "3433", "(SCSI) TOSHIBA CD-ROM DRIVE:XM 3433", "TOSHIBA_CD-ROM_DRIVEXM_3433", BUS_TYPE_SCSI}, /*33*/
|
||||
{ "TOSHIBA", "CD-ROM XM-3301TA", "0272", "(SCSI) TOSHIBA CD-ROM XM-3301TA 0272", "TOSHIBA_CD-ROM_XM-3301TA_0272", BUS_TYPE_SCSI}, /*34*/
|
||||
{ "TOSHIBA", "CD-ROM XM-5701TA", "3136", "(SCSI) TOSHIBA CD-ROM XM-5701TA 3136", "TOSHIBA_CD-ROM_XM-5701TA_3136", BUS_TYPE_SCSI}, /*35*/
|
||||
{ "", "", "", "", "", -1},
|
||||
};
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
* Copyright 2008-2019 Sarah Walker.
|
||||
* Copyright 2021 Andreas J. Reichel.
|
||||
* Copyright 2021-2022 Jasmine Iwanek.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -52,6 +54,7 @@
|
||||
#define CONFIG_MAC 9
|
||||
#define CONFIG_MIDI_IN 10
|
||||
#define CONFIG_BIOS 11
|
||||
#define CONFIG_SERPORT 12
|
||||
|
||||
enum {
|
||||
DEVICE_PCJR = 2, /* requires an IBM PCjr */
|
||||
@@ -107,7 +110,7 @@ typedef struct {
|
||||
int default_int;
|
||||
const char *file_filter;
|
||||
const device_config_spinner_t spinner;
|
||||
const device_config_selection_t selection[16];
|
||||
const device_config_selection_t selection[32];
|
||||
const device_config_bios_t bios[32];
|
||||
} device_config_t;
|
||||
|
||||
@@ -134,6 +137,7 @@ typedef struct _device_ {
|
||||
typedef struct {
|
||||
const device_t *dev;
|
||||
char name[2048];
|
||||
int instance;
|
||||
} device_context_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -178,6 +182,7 @@ extern void device_set_config_hex16(const char *s, int val);
|
||||
extern void device_set_config_hex20(const char *s, int val);
|
||||
extern void device_set_config_mac(const char *s, int val);
|
||||
extern const char *device_get_config_string(const char *name);
|
||||
extern const int device_get_instance(void);
|
||||
#define device_get_config_bios device_get_config_string
|
||||
|
||||
extern char *device_get_internal_name(const device_t *d);
|
||||
|
||||
@@ -39,8 +39,6 @@ typedef struct {
|
||||
#define RSHIFT_OFF 0x105
|
||||
|
||||
/* KBC #define's */
|
||||
#define KBC_UNKNOWN 0x0000 /* As yet unknown keyboard */
|
||||
|
||||
/* IBM-style controllers */
|
||||
#define KBC_IBM_PC_XT 0x0000 /* IBM PC/XT */
|
||||
#define KBC_IBM_PCJR 0x0001 /* IBM PCjr */
|
||||
|
||||
@@ -288,7 +288,11 @@ typedef struct _machine_ {
|
||||
const machine_memory_t ram;
|
||||
int ram_granularity;
|
||||
int nvrmask;
|
||||
uint16_t kbc;
|
||||
#ifdef EMU_DEVICE_H
|
||||
const device_t *kbc_device;
|
||||
#else
|
||||
void *kbc_device;
|
||||
#endif /* EMU_DEVICE_H */
|
||||
/* Bits:
|
||||
7-0 Set bits are forced set on P1 (no forced set = 0x00);
|
||||
15-8 Clear bits are forced clear on P1 (no foced clear = 0xff). */
|
||||
@@ -297,11 +301,15 @@ typedef struct _machine_ {
|
||||
uint32_t gpio_acpi;
|
||||
#ifdef EMU_DEVICE_H
|
||||
const device_t *device;
|
||||
const device_t *fdc_device;
|
||||
const device_t *sio_device;
|
||||
const device_t *vid_device;
|
||||
const device_t *snd_device;
|
||||
const device_t *net_device;
|
||||
#else
|
||||
void *device;
|
||||
void *fdc_device;
|
||||
void *sio_device;
|
||||
void *vid_device;
|
||||
void *snd_device;
|
||||
void *net_device;
|
||||
@@ -324,10 +332,13 @@ extern char *machine_get_internal_name(void);
|
||||
extern int machine_get_machine_from_internal_name(char *s);
|
||||
extern void machine_init(void);
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t *machine_getdevice(int m);
|
||||
extern const device_t *machine_getviddevice(int m);
|
||||
extern const device_t *machine_getsnddevice(int m);
|
||||
extern const device_t *machine_getnetdevice(int m);
|
||||
extern const device_t *machine_get_kbc_device(int m);
|
||||
extern const device_t *machine_get_device(int m);
|
||||
extern const device_t *machine_get_fdc_device(int m);
|
||||
extern const device_t *machine_get_sio_device(int m);
|
||||
extern const device_t *machine_get_vid_device(int m);
|
||||
extern const device_t *machine_get_snd_device(int m);
|
||||
extern const device_t *machine_get_net_device(int m);
|
||||
#endif
|
||||
extern char *machine_get_internal_name_ex(int m);
|
||||
extern int machine_get_nvrmask(int m);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef EMU_PCI_DUMMY_H
|
||||
#define EMU_PCI_DUMMY_H
|
||||
|
||||
extern void pci_dummy_init(void);
|
||||
extern void pci_dummy_init(int min_slot, int max_slot, int nb_slot, int sb_slot);
|
||||
|
||||
#endif /*EMU_PCI_DUMMY_H*/
|
||||
|
||||
38
src/include/86box/plat_serial_passthrough.h
Normal file
38
src/include/86box/plat_serial_passthrough.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Definitions for platform specific serial to host passthrough.
|
||||
*
|
||||
*
|
||||
* Authors: Andreas J. Reichel <webmaster@6th-dimension.com>,
|
||||
* Jasmine Iwanek <jasmine@iwanek.co.uk>
|
||||
*
|
||||
* Copyright 2021 Andreas J. Reichel.
|
||||
* Copyright 2021-2022 Jasmine Iwanek.
|
||||
*/
|
||||
|
||||
#ifndef PLAT_SERIAL_PASSTHROUGH_H
|
||||
#define PLAT_SERIAL_PASSTHROUGH_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void plat_serpt_write(void *p, uint8_t data);
|
||||
extern int plat_serpt_read(void *p, uint8_t *data);
|
||||
extern int plat_serpt_open_device(void *p);
|
||||
extern void plat_serpt_close(void *p);
|
||||
extern void plat_serpt_set_params(void *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -247,6 +247,10 @@
|
||||
#define IDC_CHECK_PARALLEL2 1089
|
||||
#define IDC_CHECK_PARALLEL3 1090
|
||||
#define IDC_CHECK_PARALLEL4 1091
|
||||
#define IDC_CHECK_SERIAL_PASS1 1092
|
||||
#define IDC_CHECK_SERIAL_PASS2 1093
|
||||
#define IDC_CHECK_SERIAL_PASS3 1094
|
||||
#define IDC_CHECK_SERIAL_PASS4 1095
|
||||
|
||||
#define IDC_OTHER_PERIPH 1110 /* storage controllers config */
|
||||
#define IDC_COMBO_HDC 1111
|
||||
@@ -364,6 +368,10 @@
|
||||
#define IDC_CONFIGURE_NET4 1321
|
||||
#define IDC_CONFIGURE_MIDI_OUT 1322
|
||||
#define IDC_CONFIGURE_MIDI_IN 1323
|
||||
#define IDC_CONFIGURE_SERIAL_PASS1 1324
|
||||
#define IDC_CONFIGURE_SERIAL_PASS2 1325
|
||||
#define IDC_CONFIGURE_SERIAL_PASS3 1326
|
||||
#define IDC_CONFIGURE_SERIAL_PASS4 1327
|
||||
#define IDC_JOY1 1330
|
||||
#define IDC_JOY2 1331
|
||||
#define IDC_JOY3 1332
|
||||
|
||||
@@ -53,7 +53,7 @@ typedef struct serial_s {
|
||||
dat, int_status, scratch, fcr,
|
||||
irq, type, inst, transmit_enabled,
|
||||
fifo_enabled, rcvr_fifo_len, bits, data_bits,
|
||||
baud_cycles, rcvr_fifo_full, txsr, pad;
|
||||
baud_cycles, rcvr_fifo_full, txsr, pad, msr_set;
|
||||
|
||||
uint16_t dlab, base_address;
|
||||
|
||||
@@ -70,6 +70,8 @@ typedef struct serial_s {
|
||||
typedef struct serial_device_s {
|
||||
void (*rcr_callback)(struct serial_s *serial, void *p);
|
||||
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data);
|
||||
void (*lcr_callback)(struct serial_s *serial, void *p, uint8_t lcr);
|
||||
void (*transmit_period_callback)(struct serial_s *serial, void *p, double transmit_period);
|
||||
void *priv;
|
||||
serial_t *serial;
|
||||
} serial_device_t;
|
||||
@@ -84,6 +86,12 @@ extern serial_t *serial_attach(int port,
|
||||
void (*rcr_callback)(struct serial_s *serial, void *p),
|
||||
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data),
|
||||
void *priv);
|
||||
extern serial_t *serial_attach_ex(int port,
|
||||
void (*rcr_callback)(struct serial_s *serial, void *p),
|
||||
void (*dev_write)(struct serial_s *serial, void *p, uint8_t data),
|
||||
void (*transmit_period_callback)(struct serial_s *serial, void *p, double transmit_period),
|
||||
void (*lcr_callback)(struct serial_s *serial, void *p, uint8_t data_bits),
|
||||
void *priv);
|
||||
extern void serial_remove(serial_t *dev);
|
||||
extern void serial_set_type(serial_t *dev, int type);
|
||||
extern void serial_setup(serial_t *dev, uint16_t addr, uint8_t irq);
|
||||
@@ -93,6 +101,11 @@ extern void serial_set_next_inst(int ni);
|
||||
extern void serial_standalone_init(void);
|
||||
extern void serial_set_clock_src(serial_t *dev, double clock_src);
|
||||
extern void serial_reset_port(serial_t *dev);
|
||||
extern void serial_device_timeout(void *priv);
|
||||
|
||||
extern void serial_set_cts(serial_t *dev, uint8_t enabled);
|
||||
extern void serial_set_dsr(serial_t *dev, uint8_t enabled);
|
||||
extern void serial_set_dcd(serial_t *dev, uint8_t enabled);
|
||||
|
||||
extern const device_t ns8250_device;
|
||||
extern const device_t ns8250_pcjr_device;
|
||||
|
||||
61
src/include/86box/serial_passthrough.h
Normal file
61
src/include/86box/serial_passthrough.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Definition of Serial passthrough device.
|
||||
*
|
||||
*
|
||||
* Authors: Andreas J. Reichel <webmaster@6th-dimension.com>,
|
||||
* Jasmine Iwanek <jasmine@iwanek.co.uk>
|
||||
*
|
||||
* Copyright 2021 Andreas J. Reichel.
|
||||
* Copyright 2021-2022 Jasmine Iwanek.
|
||||
*/
|
||||
|
||||
#ifndef SERIAL_PASSTHROUGH_H
|
||||
#define SERIAL_PASSTHROUGH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/serial.h>
|
||||
|
||||
enum serial_passthrough_mode {
|
||||
SERPT_MODE_VCON, /*Named Pipe (Server) / Pseudo Terminal/Virtual Console */
|
||||
SERPT_MODE_TCPSRV, /* TCP Server (TODO) */
|
||||
SERPT_MODE_TCPCLNT, /* TCP Client (TODO) */
|
||||
SERPT_MODE_HOSTSER, /* Host Serial Passthrough */
|
||||
SERPT_MODES_MAX,
|
||||
};
|
||||
|
||||
extern const char *serpt_mode_names[SERPT_MODES_MAX];
|
||||
|
||||
typedef struct serial_passthrough_s {
|
||||
enum serial_passthrough_mode mode;
|
||||
pc_timer_t host_to_serial_timer;
|
||||
pc_timer_t serial_to_host_timer;
|
||||
serial_t *serial;
|
||||
double baudrate;
|
||||
uint8_t bits, data_bits;
|
||||
uint8_t port;
|
||||
uint8_t data;
|
||||
char slave_pt[32]; /* used for pseudo term name of slave side */
|
||||
intptr_t master_fd; /* file desc for master pseudo terminal or
|
||||
* socket or alike */
|
||||
char host_serial_path[1024]; /* Path to TTY/host serial port on the host */
|
||||
void *backend_priv; /* Private platform backend data */
|
||||
} serial_passthrough_t;
|
||||
|
||||
extern bool serial_passthrough_enabled[SERIAL_MAX];
|
||||
extern const device_t serial_passthrough_device;
|
||||
|
||||
extern void serial_passthrough_init(void);
|
||||
|
||||
#endif
|
||||
@@ -17,7 +17,7 @@
|
||||
#define WIN_OPENGL_H
|
||||
|
||||
#define UNICODE
|
||||
#include <Windows.h>
|
||||
#include <windows.h>
|
||||
|
||||
extern int opengl_init(HWND hwnd);
|
||||
extern int opengl_pause(void);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#define _DISCORD_GAME_SDK_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#include <windows.h>
|
||||
#include <dxgi.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ int
|
||||
machine_available(int m)
|
||||
{
|
||||
int ret;
|
||||
device_t *d = (device_t *) machine_getdevice(m);
|
||||
device_t *d = (device_t *) machine_get_device(m);
|
||||
|
||||
bios_only = 1;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
258
src/pci_dummy.c
258
src/pci_dummy.c
@@ -1,58 +1,68 @@
|
||||
/* This can also serve as a sample PCI device. */
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/pci_dummy.h>
|
||||
|
||||
static uint8_t pci_regs[256];
|
||||
typedef struct
|
||||
{
|
||||
uint8_t pci_regs[256];
|
||||
|
||||
static bar_t pci_bar[2];
|
||||
bar_t pci_bar[2];
|
||||
|
||||
static uint8_t interrupt_on = 0x00;
|
||||
static uint8_t card = 0;
|
||||
uint8_t card, interrupt_on;
|
||||
} pci_dummy_t;
|
||||
|
||||
static void
|
||||
pci_dummy_interrupt(int set)
|
||||
pci_dummy_interrupt(int set, pci_dummy_t *dev)
|
||||
{
|
||||
if (set) {
|
||||
pci_set_irq(card, pci_regs[0x3D]);
|
||||
} else {
|
||||
pci_clear_irq(card, pci_regs[0x3D]);
|
||||
}
|
||||
if (set)
|
||||
pci_set_irq(dev->card, PCI_INTA);
|
||||
else
|
||||
pci_clear_irq(dev->card, PCI_INTA);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
pci_dummy_read(uint16_t Port, void *p)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
pci_dummy_t *dev = (pci_dummy_t *) p;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (Port & 0x20) {
|
||||
case 0x00:
|
||||
return 0x1A;
|
||||
ret = 0x1a;
|
||||
break;
|
||||
case 0x01:
|
||||
return 0x07;
|
||||
ret = 0x07;
|
||||
break;
|
||||
case 0x02:
|
||||
return 0x0B;
|
||||
ret = 0x0b;
|
||||
break;
|
||||
case 0x03:
|
||||
return 0xAB;
|
||||
ret = 0xab;
|
||||
break;
|
||||
case 0x04:
|
||||
return pci_regs[0x3C];
|
||||
ret = dev->pci_regs[0x3c];
|
||||
break;
|
||||
case 0x05:
|
||||
return pci_regs[0x3D];
|
||||
ret = dev->pci_regs[0x3d];
|
||||
break;
|
||||
case 0x06:
|
||||
ret = interrupt_on;
|
||||
if (interrupt_on) {
|
||||
pci_dummy_interrupt(0);
|
||||
interrupt_on = 0;
|
||||
ret = dev->interrupt_on;
|
||||
if (dev->interrupt_on) {
|
||||
pci_dummy_interrupt(0, dev);
|
||||
dev->interrupt_on = 0;
|
||||
}
|
||||
return ret;
|
||||
default:
|
||||
return 0x00;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
@@ -70,15 +80,15 @@ pci_dummy_readl(uint16_t Port, void *p)
|
||||
static void
|
||||
pci_dummy_write(uint16_t Port, uint8_t Val, void *p)
|
||||
{
|
||||
pci_dummy_t *dev = (pci_dummy_t *) p;
|
||||
|
||||
switch (Port & 0x20) {
|
||||
case 0x06:
|
||||
if (!interrupt_on) {
|
||||
interrupt_on = 1;
|
||||
pci_dummy_interrupt(1);
|
||||
if (!dev->interrupt_on) {
|
||||
dev->interrupt_on = 1;
|
||||
pci_dummy_interrupt(1, dev);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,143 +105,179 @@ pci_dummy_writel(uint16_t Port, uint32_t Val, void *p)
|
||||
}
|
||||
|
||||
static void
|
||||
pci_dummy_io_remove(void)
|
||||
pci_dummy_io_remove(pci_dummy_t *dev)
|
||||
{
|
||||
io_removehandler(pci_bar[0].addr, 0x0020, pci_dummy_read, pci_dummy_readw, pci_dummy_readl, pci_dummy_write, pci_dummy_writew, pci_dummy_writel, NULL);
|
||||
io_removehandler(dev->pci_bar[0].addr, 0x0020, pci_dummy_read, pci_dummy_readw, pci_dummy_readl, pci_dummy_write, pci_dummy_writew, pci_dummy_writel, dev);
|
||||
}
|
||||
|
||||
static void
|
||||
pci_dummy_io_set(void)
|
||||
pci_dummy_io_set(pci_dummy_t *dev)
|
||||
{
|
||||
io_sethandler(pci_bar[0].addr, 0x0020, pci_dummy_read, pci_dummy_readw, pci_dummy_readl, pci_dummy_write, pci_dummy_writew, pci_dummy_writel, NULL);
|
||||
io_sethandler(dev->pci_bar[0].addr, 0x0020, pci_dummy_read, pci_dummy_readw, pci_dummy_readl, pci_dummy_write, pci_dummy_writew, pci_dummy_writel, dev);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
pci_dummy_pci_read(int func, int addr, void *priv)
|
||||
{
|
||||
pclog("AB0B:071A: PCI_Read(%d, %04x)\n", func, addr);
|
||||
pci_dummy_t *dev = (pci_dummy_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (addr) {
|
||||
case 0x00:
|
||||
return 0x1A;
|
||||
case 0x01:
|
||||
return 0x07;
|
||||
if (func == 0x00) switch (addr) {
|
||||
case 0x00: case 0x2c:
|
||||
ret = 0x1a;
|
||||
break;
|
||||
case 0x01: case 0x2d:
|
||||
ret = 0x07;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
return 0x0B;
|
||||
case 0x03:
|
||||
return 0xAB;
|
||||
case 0x02: case 0x2e:
|
||||
ret = 0x0b;
|
||||
break;
|
||||
case 0x03: case 0x2f:
|
||||
ret = 0xab;
|
||||
break;
|
||||
|
||||
case 0x04: /* PCI_COMMAND_LO */
|
||||
case 0x05: /* PCI_COMMAND_HI */
|
||||
return pci_regs[addr];
|
||||
|
||||
case 0x06: /* PCI_STATUS_LO */
|
||||
case 0x07: /* PCI_STATUS_HI */
|
||||
return pci_regs[addr];
|
||||
case 0x0a: case 0x0b:
|
||||
case 0x3c: /* PCI_ILR */
|
||||
ret = dev->pci_regs[addr];
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
return 0x00;
|
||||
|
||||
case 0x0A:
|
||||
return pci_regs[addr];
|
||||
|
||||
case 0x0B:
|
||||
return pci_regs[addr];
|
||||
case 0x08: /* Techncially, revision, but we return the card (slot) here. */
|
||||
ret = dev->card;
|
||||
break;
|
||||
|
||||
case 0x10: /* PCI_BAR 7:5 */
|
||||
return (pci_bar[0].addr_regs[0] & 0xe0) | 0x01;
|
||||
ret = (dev->pci_bar[0].addr_regs[0] & 0xe0) | 0x01;
|
||||
break;
|
||||
case 0x11: /* PCI_BAR 15:8 */
|
||||
return pci_bar[0].addr_regs[1];
|
||||
case 0x12: /* PCI_BAR 23:16 */
|
||||
return pci_bar[0].addr_regs[2];
|
||||
case 0x13: /* PCI_BAR 31:24 */
|
||||
return pci_bar[0].addr_regs[3];
|
||||
ret = dev->pci_bar[0].addr_regs[1];
|
||||
break;
|
||||
|
||||
case 0x2C:
|
||||
return 0x1A;
|
||||
case 0x2D:
|
||||
return 0x07;
|
||||
|
||||
case 0x2E:
|
||||
return 0x0B;
|
||||
case 0x2F:
|
||||
return 0xAB;
|
||||
|
||||
case 0x3C: /* PCI_ILR */
|
||||
return pci_regs[addr];
|
||||
|
||||
case 0x3D: /* PCI_IPR */
|
||||
return pci_regs[addr];
|
||||
case 0x3d: /* PCI_IPR */
|
||||
ret = PCI_INTA;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0x00;
|
||||
ret = 0x00;
|
||||
break;
|
||||
}
|
||||
|
||||
// pclog("AB0B:071A: PCI_Read(%d, %04X) = %02X\n", func, addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
pci_dummy_pci_write(int func, int addr, uint8_t val, void *priv)
|
||||
{
|
||||
pci_dummy_t *dev = (pci_dummy_t *) priv;
|
||||
uint8_t valxor;
|
||||
|
||||
pclog("AB0B:071A: PCI_Write(%d, %04x, %02x)\n", func, addr, val);
|
||||
// pclog("AB0B:071A: PCI_Write(%d, %04X, %02X)\n", func, addr, val);
|
||||
|
||||
switch (addr) {
|
||||
if (func == 0x00) switch (addr) {
|
||||
case 0x04: /* PCI_COMMAND_LO */
|
||||
valxor = (val & 0x03) ^ pci_regs[addr];
|
||||
valxor = (val & 0x03) ^ dev->pci_regs[addr];
|
||||
if (valxor & PCI_COMMAND_IO) {
|
||||
pci_dummy_io_remove();
|
||||
if (((pci_bar[0].addr & 0xffe0) != 0) && (val & PCI_COMMAND_IO)) {
|
||||
pci_dummy_io_set();
|
||||
}
|
||||
pci_dummy_io_remove(dev);
|
||||
if ((dev->pci_bar[0].addr != 0) && (val & PCI_COMMAND_IO))
|
||||
pci_dummy_io_set(dev);
|
||||
}
|
||||
pci_regs[addr] = val & 0x03;
|
||||
dev->pci_regs[addr] = val & 0x03;
|
||||
break;
|
||||
|
||||
case 0x10: /* PCI_BAR */
|
||||
val &= 0xe0; /* 0xe0 acc to RTL DS */
|
||||
val |= 0x01; /* re-enable IOIN bit */
|
||||
/*FALLTHROUGH*/
|
||||
|
||||
case 0x11: /* PCI_BAR */
|
||||
case 0x12: /* PCI_BAR */
|
||||
case 0x13: /* PCI_BAR */
|
||||
/* Remove old I/O. */
|
||||
pci_dummy_io_remove();
|
||||
pci_dummy_io_remove(dev);
|
||||
|
||||
/* Set new I/O as per PCI request. */
|
||||
pci_bar[0].addr_regs[addr & 3] = val;
|
||||
dev->pci_bar[0].addr_regs[addr & 3] = val;
|
||||
|
||||
/* Then let's calculate the new I/O base. */
|
||||
pci_bar[0].addr &= 0xffe0;
|
||||
dev->pci_bar[0].addr &= 0xffe0;
|
||||
|
||||
/* Log the new base. */
|
||||
pclog("AB0B:071A: PCI: new I/O base is %04X\n", pci_bar[0].addr);
|
||||
// pclog("AB0B:071A: PCI: new I/O base is %04X\n", dev->pci_bar[0].addr);
|
||||
|
||||
/* We're done, so get out of the here. */
|
||||
if (pci_regs[4] & PCI_COMMAND_IO) {
|
||||
if ((pci_bar[0].addr) != 0) {
|
||||
pci_dummy_io_set();
|
||||
}
|
||||
if (dev->pci_regs[4] & PCI_COMMAND_IO) {
|
||||
if ((dev->pci_bar[0].addr) != 0)
|
||||
pci_dummy_io_set(dev);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3C: /* PCI_ILR */
|
||||
pclog("AB0B:071A: IRQ now: %i\n", val);
|
||||
pci_regs[addr] = val;
|
||||
case 0x3c: /* PCI_ILR */
|
||||
pclog("AB0B:071A Device %02X: IRQ now: %i\n", dev->card, val);
|
||||
dev->pci_regs[addr] = val;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pci_dummy_init(void)
|
||||
static void
|
||||
pci_dummy_reset(void *priv)
|
||||
{
|
||||
card = pci_add_card(PCI_ADD_NORMAL, pci_dummy_pci_read, pci_dummy_pci_write, NULL);
|
||||
pci_dummy_t *dev = (pci_dummy_t *) priv;
|
||||
|
||||
pci_bar[0].addr_regs[0] = 0x01;
|
||||
pci_regs[0x04] = 0x03;
|
||||
/* Lower the IRQ. */
|
||||
pci_dummy_interrupt(0, dev);
|
||||
|
||||
pci_regs[0x3D] = PCI_INTD;
|
||||
/* Disable I/O and memory accesses. */
|
||||
pci_dummy_pci_write(0x00, 0x04, 0x00, dev);
|
||||
|
||||
/* Zero all the registers. */
|
||||
memset(dev, 0x00, sizeof(pci_dummy_t));
|
||||
}
|
||||
|
||||
static void
|
||||
pci_dummy_close(void *priv)
|
||||
{
|
||||
pci_dummy_t *dev = (pci_dummy_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void *
|
||||
pci_dummy_card_init(const device_t *info)
|
||||
{
|
||||
pci_dummy_t *dev = (pci_dummy_t *) calloc(1, sizeof(pci_dummy_t));
|
||||
|
||||
dev->card = pci_add_card(PCI_ADD_NORMAL, pci_dummy_pci_read, pci_dummy_pci_write, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t pci_dummy_device = {
|
||||
.name = "Dummy Device (PCI)",
|
||||
.internal_name = "pci_dummy",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = 0,
|
||||
.init = pci_dummy_card_init,
|
||||
.close = pci_dummy_close,
|
||||
.reset = pci_dummy_reset,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
void
|
||||
pci_dummy_init(int min_slot, int max_slot, int nb_slot, int sb_slot)
|
||||
{
|
||||
int i = 0, j = 1;
|
||||
|
||||
for (i = min_slot; i <= max_slot; i++) {
|
||||
if ((i != nb_slot) && (i != sb_slot)) {
|
||||
pci_register_slot(i, PCI_CARD_NORMAL, 1, 3, 2, 4);
|
||||
device_add_inst(&pci_dummy_device, j);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,6 +221,12 @@ if(WIN32 AND NOT MINGW)
|
||||
target_sources(plat PRIVATE ../win/win_opendir.c)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
target_sources(plat PRIVATE ../win/win_serial_passthrough.c)
|
||||
else()
|
||||
target_sources(plat PRIVATE ../unix/unix_serial_passthrough.c)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
target_sources(ui PRIVATE macos_event_filter.mm)
|
||||
if(MOLTENVK)
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include <QCheckBox>
|
||||
#include <QFrame>
|
||||
#include <QLabel>
|
||||
#include <QDir>
|
||||
#include <QSettings>
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
@@ -40,6 +42,10 @@ extern "C" {
|
||||
|
||||
#include "qt_filefield.hpp"
|
||||
#include "qt_models_common.hpp"
|
||||
#ifdef Q_OS_LINUX
|
||||
# include <sys/stat.h>
|
||||
# include <sys/sysmacros.h>
|
||||
#endif
|
||||
|
||||
DeviceConfig::DeviceConfig(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
@@ -53,6 +59,40 @@ DeviceConfig::~DeviceConfig()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
static QStringList
|
||||
EnumerateSerialDevices()
|
||||
{
|
||||
QStringList serialDevices, ttyEntries;
|
||||
QByteArray devstr(1024, 0);
|
||||
#ifdef Q_OS_LINUX
|
||||
QDir class_dir("/sys/class/tty/");
|
||||
QDir dev_dir("/dev/");
|
||||
ttyEntries = class_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::System, QDir::SortFlag::Name);
|
||||
for (int i = 0; i < ttyEntries.size(); i++) {
|
||||
if (class_dir.exists(ttyEntries[i] + "/device/driver/") && dev_dir.exists(ttyEntries[i])
|
||||
&& QFileInfo(dev_dir.canonicalPath() + '/' + ttyEntries[i]).isReadable()
|
||||
&& QFileInfo(dev_dir.canonicalPath() + '/' + ttyEntries[i]).isWritable()) {
|
||||
serialDevices.push_back("/dev/" + ttyEntries[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef Q_OS_WINDOWS
|
||||
QSettings comPorts("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM", QSettings::NativeFormat, nullptr);
|
||||
for (int i = 0; i < comPorts.childKeys().length(); i++) {
|
||||
serialDevices.push_back(QString("\\\\.\\") + comPorts.value(comPorts.childKeys()[i]).toString());
|
||||
}
|
||||
#endif
|
||||
#ifdef Q_OS_MACOS
|
||||
QDir dev_dir("/dev/");
|
||||
dev_dir.setNameFilters({ "tty.*", "cu.*" });
|
||||
QDir::Filters serial_dev_flags = QDir::Files | QDir::NoSymLinks | QDir::Readable | QDir::Writable | QDir::NoDotAndDotDot | QDir::System;
|
||||
for (const auto &device : dev_dir.entryInfoList(serial_dev_flags, QDir::SortFlag::Name)) {
|
||||
serialDevices.push_back(device.canonicalFilePath());
|
||||
}
|
||||
#endif
|
||||
return serialDevices;
|
||||
}
|
||||
|
||||
void
|
||||
DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *settings)
|
||||
{
|
||||
@@ -205,6 +245,27 @@ DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *se
|
||||
dc.ui->formLayout->addRow(config->description, fileField);
|
||||
break;
|
||||
}
|
||||
case CONFIG_SERPORT:
|
||||
{
|
||||
auto *cbox = new QComboBox();
|
||||
cbox->setObjectName(config->name);
|
||||
auto *model = cbox->model();
|
||||
int currentIndex = 0;
|
||||
auto serialDevices = EnumerateSerialDevices();
|
||||
char *selected = config_get_string(device_context.name, const_cast<char *>(config->name), const_cast<char *>(config->default_string));
|
||||
|
||||
Models::AddEntry(model, "None", -1);
|
||||
for (int i = 0; i < serialDevices.size(); i++) {
|
||||
int row = Models::AddEntry(model, serialDevices[i], i);
|
||||
if (selected == serialDevices[i]) {
|
||||
currentIndex = row;
|
||||
}
|
||||
}
|
||||
|
||||
dc.ui->formLayout->addRow(config->description, cbox);
|
||||
cbox->setCurrentIndex(currentIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
++config;
|
||||
}
|
||||
@@ -236,6 +297,15 @@ DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *se
|
||||
config_set_string(device_context.name, const_cast<char *>(config->name), const_cast<char *>(config->bios[idx].internal_name));
|
||||
break;
|
||||
}
|
||||
case CONFIG_SERPORT:
|
||||
{
|
||||
auto *cbox = dc.findChild<QComboBox *>(config->name);
|
||||
auto path = cbox->currentText().toUtf8();
|
||||
if (path == "None")
|
||||
path = "";
|
||||
config_set_string(device_context.name, const_cast<char *>(config->name), path);
|
||||
break;
|
||||
}
|
||||
case CONFIG_HEX16:
|
||||
{
|
||||
auto *cbox = dc.findChild<QComboBox *>(config->name);
|
||||
|
||||
@@ -43,7 +43,7 @@ Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin)
|
||||
# include "qt_winrawinputfilter.hpp"
|
||||
# include "qt_winmanagerfilter.hpp"
|
||||
# include <86box/win.h>
|
||||
# include <Shobjidl.h>
|
||||
# include <shobjidl.h>
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
@@ -169,7 +169,7 @@ SettingsMachine::on_comboBoxMachine_currentIndexChanged(int index)
|
||||
}
|
||||
|
||||
int machineId = ui->comboBoxMachine->currentData().toInt();
|
||||
const auto *device = machine_getdevice(machineId);
|
||||
const auto *device = machine_get_device(machineId);
|
||||
ui->pushButtonConfigure->setEnabled((device != nullptr) && (device->config != nullptr));
|
||||
|
||||
auto *modelCpu = ui->comboBoxCPU->model();
|
||||
@@ -304,6 +304,6 @@ SettingsMachine::on_pushButtonConfigure_clicked()
|
||||
{
|
||||
// deviceconfig_inst_open
|
||||
int machineId = ui->comboBoxMachine->currentData().toInt();
|
||||
const auto *device = machine_getdevice(machineId);
|
||||
const auto *device = machine_get_device(machineId);
|
||||
DeviceConfig::ConfigureDevice(device, 0, qobject_cast<Settings *>(Settings::settings));
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ extern "C" {
|
||||
#include <86box/machine.h>
|
||||
#include <86box/lpt.h>
|
||||
#include <86box/serial.h>
|
||||
#include <86box/serial_passthrough.h>
|
||||
}
|
||||
|
||||
#include "qt_deviceconfig.hpp"
|
||||
@@ -66,6 +67,15 @@ SettingsPorts::SettingsPorts(QWidget *parent)
|
||||
auto *checkBox = findChild<QCheckBox *>(QString("checkBoxSerial%1").arg(i + 1));
|
||||
checkBox->setChecked(com_ports[i].enabled > 0);
|
||||
}
|
||||
|
||||
ui->checkBoxSerialPassThru1->setChecked(serial_passthrough_enabled[0]);
|
||||
ui->pushButtonSerialPassThru1->setEnabled(serial_passthrough_enabled[0]);
|
||||
ui->checkBoxSerialPassThru2->setChecked(serial_passthrough_enabled[1]);
|
||||
ui->pushButtonSerialPassThru2->setEnabled(serial_passthrough_enabled[1]);
|
||||
ui->checkBoxSerialPassThru3->setChecked(serial_passthrough_enabled[2]);
|
||||
ui->pushButtonSerialPassThru3->setEnabled(serial_passthrough_enabled[2]);
|
||||
ui->checkBoxSerialPassThru4->setChecked(serial_passthrough_enabled[3]);
|
||||
ui->pushButtonSerialPassThru4->setEnabled(serial_passthrough_enabled[3]);
|
||||
}
|
||||
|
||||
SettingsPorts::~SettingsPorts()
|
||||
@@ -87,6 +97,11 @@ SettingsPorts::save()
|
||||
auto *checkBox = findChild<QCheckBox *>(QString("checkBoxSerial%1").arg(i + 1));
|
||||
com_ports[i].enabled = checkBox->isChecked() ? 1 : 0;
|
||||
}
|
||||
|
||||
serial_passthrough_enabled[0] = ui->checkBoxSerialPassThru1->isChecked();
|
||||
serial_passthrough_enabled[1] = ui->checkBoxSerialPassThru2->isChecked();
|
||||
serial_passthrough_enabled[2] = ui->checkBoxSerialPassThru3->isChecked();
|
||||
serial_passthrough_enabled[3] = ui->checkBoxSerialPassThru4->isChecked();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -112,3 +127,51 @@ SettingsPorts::on_checkBoxParallel4_stateChanged(int state)
|
||||
{
|
||||
ui->comboBoxLpt4->setEnabled(state == Qt::Checked);
|
||||
}
|
||||
|
||||
void
|
||||
SettingsPorts::on_pushButtonSerialPassThru1_clicked()
|
||||
{
|
||||
DeviceConfig::ConfigureDevice(&serial_passthrough_device, 1, qobject_cast<Settings *>(Settings::settings));
|
||||
}
|
||||
|
||||
void
|
||||
SettingsPorts::on_pushButtonSerialPassThru2_clicked()
|
||||
{
|
||||
DeviceConfig::ConfigureDevice(&serial_passthrough_device, 2, qobject_cast<Settings *>(Settings::settings));
|
||||
}
|
||||
|
||||
void
|
||||
SettingsPorts::on_pushButtonSerialPassThru3_clicked()
|
||||
{
|
||||
DeviceConfig::ConfigureDevice(&serial_passthrough_device, 3, qobject_cast<Settings *>(Settings::settings));
|
||||
}
|
||||
|
||||
void
|
||||
SettingsPorts::on_pushButtonSerialPassThru4_clicked()
|
||||
{
|
||||
DeviceConfig::ConfigureDevice(&serial_passthrough_device, 4, qobject_cast<Settings *>(Settings::settings));
|
||||
}
|
||||
|
||||
void
|
||||
SettingsPorts::on_checkBoxSerialPassThru1_clicked(bool checked)
|
||||
{
|
||||
ui->pushButtonSerialPassThru1->setEnabled(checked);
|
||||
}
|
||||
|
||||
void
|
||||
SettingsPorts::on_checkBoxSerialPassThru2_clicked(bool checked)
|
||||
{
|
||||
ui->pushButtonSerialPassThru2->setEnabled(checked);
|
||||
}
|
||||
|
||||
void
|
||||
SettingsPorts::on_checkBoxSerialPassThru3_clicked(bool checked)
|
||||
{
|
||||
ui->pushButtonSerialPassThru3->setEnabled(checked);
|
||||
}
|
||||
|
||||
void
|
||||
SettingsPorts::on_checkBoxSerialPassThru4_clicked(bool checked)
|
||||
{
|
||||
ui->pushButtonSerialPassThru4->setEnabled(checked);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,30 @@ public:
|
||||
~SettingsPorts();
|
||||
|
||||
void save();
|
||||
private slots:
|
||||
void on_checkBoxSerialPassThru4_clicked(bool checked);
|
||||
|
||||
private slots:
|
||||
void on_checkBoxSerialPassThru3_clicked(bool checked);
|
||||
|
||||
private slots:
|
||||
void on_checkBoxSerialPassThru2_clicked(bool checked);
|
||||
|
||||
private slots:
|
||||
void on_pushButtonSerialPassThru4_clicked();
|
||||
|
||||
private slots:
|
||||
void on_pushButtonSerialPassThru3_clicked();
|
||||
|
||||
private slots:
|
||||
void on_pushButtonSerialPassThru2_clicked();
|
||||
|
||||
private slots:
|
||||
void on_pushButtonSerialPassThru1_clicked();
|
||||
|
||||
private slots:
|
||||
void on_checkBoxSerialPassThru1_clicked(bool checked);
|
||||
|
||||
private slots:
|
||||
void on_checkBoxParallel3_stateChanged(int arg1);
|
||||
void on_checkBoxParallel2_stateChanged(int arg1);
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
@@ -26,7 +26,7 @@
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
@@ -70,29 +70,8 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerial1">
|
||||
<property name="text">
|
||||
<string>Serial port 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="checkBoxParallel1">
|
||||
<property name="text">
|
||||
<string>Parallel port 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerial2">
|
||||
<property name="text">
|
||||
<string>Serial port 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="checkBoxParallel2">
|
||||
<property name="text">
|
||||
@@ -100,13 +79,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerial3">
|
||||
<property name="text">
|
||||
<string>Serial port 3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="checkBoxParallel3">
|
||||
<property name="text">
|
||||
@@ -114,10 +86,17 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerial4">
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerial3">
|
||||
<property name="text">
|
||||
<string>Serial port 4</string>
|
||||
<string>Serial port 3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerial1">
|
||||
<property name="text">
|
||||
<string>Serial port 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -128,20 +107,117 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerial2">
|
||||
<property name="text">
|
||||
<string>Serial port 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="checkBoxParallel1">
|
||||
<property name="text">
|
||||
<string>Parallel port 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerial4">
|
||||
<property name="text">
|
||||
<string>Serial port 4</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<item row="3" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
<item row="4" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerialPassThru3">
|
||||
<property name="text">
|
||||
<string>Serial port passthrough 3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="pushButtonSerialPassThru1">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerialPassThru1">
|
||||
<property name="text">
|
||||
<string>Serial port passthrough 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerialPassThru2">
|
||||
<property name="text">
|
||||
<string>Serial port passthrough 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerialPassThru4">
|
||||
<property name="text">
|
||||
<string>Serial port passthrough 4</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="pushButtonSerialPassThru2">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="pushButtonSerialPassThru3">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="pushButtonSerialPassThru4">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include "qt_winmanagerfilter.hpp"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <windows.h>
|
||||
#include <86box/win.h>
|
||||
|
||||
bool
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
#include <QMenuBar>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/mouse.h>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include <QAbstractNativeEventFilter>
|
||||
#include <QByteArray>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
@@ -81,9 +81,17 @@ xinput2_get_xtest_pointer()
|
||||
{
|
||||
/* The XTEST pointer events injected by VNC servers to move the cursor always report
|
||||
absolute coordinates, despite XTEST declaring relative axes (related: SDL issue 1836).
|
||||
This looks for the XTEST pointer so that we can assume it's absolute as a workaround. */
|
||||
This looks for the XTEST pointer so that we can assume it's absolute as a workaround.
|
||||
|
||||
TigerVNC publishes both the XTEST pointer and a TigerVNC pointer, but actual
|
||||
RawMotion events are published using the TigerVNC pointer */
|
||||
int devs;
|
||||
XIDeviceInfo *info = XIQueryDevice(disp, XIAllDevices, &devs), *dev;
|
||||
for (int i = 0; i < devs; i++) {
|
||||
dev = &info[i];
|
||||
if ((dev->use == XISlavePointer) && !strcmp(dev->name, "TigerVNC pointer"))
|
||||
return dev->deviceid;
|
||||
}
|
||||
for (int i = 0; i < devs; i++) {
|
||||
dev = &info[i];
|
||||
if ((dev->use == XISlavePointer) && !strcmp(dev->name, "Virtual core XTEST pointer"))
|
||||
|
||||
@@ -3519,15 +3519,30 @@ scsi_cdrom_identify(ide_t *ide, int ide_has_dma)
|
||||
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "SONY_CD-ROM_CDU311_3.0h"))) {
|
||||
ide_padstr((char *) (ide->buffer + 23), "3.0h ", 8); /* Firmware */
|
||||
ide_padstr((char *) (ide->buffer + 27), "SONY CD-ROM CDU311 ", 40); /* Model */
|
||||
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "NEC_CDR-1300A_1.05"))) {
|
||||
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "NEC_CD-ROM_DRIVE280_1.05"))) {
|
||||
ide_padstr((char *) (ide->buffer + 23), "1.05 ", 8); /* Firmware */
|
||||
ide_padstr((char *) (ide->buffer + 27), "NEC CDR-1300A ", 40); /* Model */
|
||||
ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:280 ", 40); /* Model */
|
||||
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "NEC_CD-ROM_DRIVE280_3.08"))) {
|
||||
ide_padstr((char *) (ide->buffer + 23), "3.08 ", 8); /* Firmware */
|
||||
ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:280 ", 40); /* Model */
|
||||
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "NEC_CD-ROM_DRIVE273_4.20"))) {
|
||||
ide_padstr((char *) (ide->buffer + 23), "4.20 ", 8); /* Firmware */
|
||||
ide_padstr((char *) (ide->buffer + 27), "NEC CD-ROM DRIVE:273 ", 40); /* Model */
|
||||
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "TOSHIBA_CD-ROM_XM-5302TA_0305"))) {
|
||||
ide_padstr((char *) (ide->buffer + 23), "0305 ", 8); /* Firmware */
|
||||
ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-5302TA ", 40); /* Model */
|
||||
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "TOSHIBA_CD-ROM_XM-5702B_TA70"))) {
|
||||
ide_padstr((char *) (ide->buffer + 23), "TA70 ", 8); /* Firmware */
|
||||
ide_padstr((char *) (ide->buffer + 27), "TOSHIBA CD-ROM XM-5702B ", 40); /* Model */
|
||||
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "GOLDSTAR_CRD-8160B_3.14"))) {
|
||||
ide_padstr((char *) (ide->buffer + 23), "3.14 ", 8); /* Firmware */
|
||||
ide_padstr((char *) (ide->buffer + 27), "GOLDSTAR CRD-8160B ", 40); /* Model */
|
||||
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "MATSHITA_CR-571_1.0e"))) {
|
||||
ide_padstr((char *) (ide->buffer + 23), "1.0e ", 8); /* Firmware */
|
||||
ide_padstr((char *) (ide->buffer + 27), "MATSHITA CR-571 ", 40); /* Model */
|
||||
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "MATSHITA_CR-572_1.0j"))) {
|
||||
ide_padstr((char *) (ide->buffer + 23), "1.0j ", 8); /* Firmware */
|
||||
ide_padstr((char *) (ide->buffer + 27), "MATSHITA CR-572 ", 40); /* Model */
|
||||
} else if ((!strcmp(cdrom_drive_types[dev->drv->type].internal_name, "MATSHITA_CD-ROM_CR-587_7S13"))) {
|
||||
ide_padstr((char *) (ide->buffer + 23), "7S13 ", 8); /* Firmware */
|
||||
ide_padstr((char *) (ide->buffer + 27), "MATSHITA CD-ROM CR-587 ", 40); /* Model */
|
||||
|
||||
@@ -13,9 +13,11 @@
|
||||
#
|
||||
# Copyright 2021 Cacodemon345.
|
||||
# Copyright 2021 David Hrdlička.
|
||||
# Copyright 2021 Andreas J. Reichel.
|
||||
# Copyright 2021-2022 Jasmine Iwanek.
|
||||
#
|
||||
|
||||
add_library(plat OBJECT unix.c)
|
||||
add_library(plat OBJECT unix.c unix_serial_passthrough.c)
|
||||
|
||||
if (NOT CPPTHREADS)
|
||||
target_sources(plat PRIVATE unix_thread.c)
|
||||
|
||||
314
src/unix/unix_serial_passthrough.c
Normal file
314
src/unix/unix_serial_passthrough.c
Normal file
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Definitions for platform specific serial to host passthrough
|
||||
*
|
||||
*
|
||||
* Authors: Andreas J. Reichel <webmaster@6th-dimension.com>,
|
||||
* Jasmine Iwanek <jasmine@iwanek.co.uk>
|
||||
*
|
||||
* Copyright 2021 Andreas J. Reichel.
|
||||
* Copyright 2021-2022 Jasmine Iwanek.
|
||||
*/
|
||||
|
||||
#ifndef __APPLE__
|
||||
# define _XOPEN_SOURCE 500
|
||||
# define _DEFAULT_SOURCE 1
|
||||
# define _BSD_SOURCE 1
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include <86box/86box.h>
|
||||
#include <86box/log.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/serial_passthrough.h>
|
||||
#include <86box/plat_serial_passthrough.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define LOG_PREFIX "serial_passthrough: "
|
||||
|
||||
int
|
||||
plat_serpt_read(void *p, uint8_t *data)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||
int res;
|
||||
struct timeval tv;
|
||||
fd_set rdfds;
|
||||
|
||||
switch (dev->mode) {
|
||||
case SERPT_MODE_VCON:
|
||||
case SERPT_MODE_HOSTSER:
|
||||
FD_ZERO(&rdfds);
|
||||
FD_SET(dev->master_fd, &rdfds);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
res = select(dev->master_fd + 1, &rdfds, NULL, NULL, &tv);
|
||||
if (res <= 0 || !FD_ISSET(dev->master_fd, &rdfds)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (read(dev->master_fd, data, 1) > 0) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
plat_serpt_close(void *p)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||
|
||||
if (dev->mode == SERPT_MODE_HOSTSER) {
|
||||
tcsetattr(dev->master_fd, TCSANOW, (struct termios *) dev->backend_priv);
|
||||
free(dev->backend_priv);
|
||||
}
|
||||
close(dev->master_fd);
|
||||
}
|
||||
|
||||
static void
|
||||
plat_serpt_write_vcon(serial_passthrough_t *dev, uint8_t data)
|
||||
{
|
||||
/* fd_set wrfds;
|
||||
* int res;
|
||||
*/
|
||||
|
||||
/* We cannot use select here, this would block the hypervisor! */
|
||||
/* FD_ZERO(&wrfds);
|
||||
FD_SET(ctx->master_fd, &wrfds);
|
||||
|
||||
res = select(ctx->master_fd + 1, NULL, &wrfds, NULL, NULL);
|
||||
|
||||
if (res <= 0) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
/* just write it out */
|
||||
if (dev->mode == SERPT_MODE_HOSTSER) {
|
||||
int res = 0;
|
||||
do {
|
||||
res = write(dev->master_fd, &data, 1);
|
||||
} while (res == 0 || (res == -1 && (errno == EAGAIN || res == EWOULDBLOCK)));
|
||||
} else
|
||||
write(dev->master_fd, &data, 1);
|
||||
}
|
||||
|
||||
void
|
||||
plat_serpt_set_params(void *p)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||
|
||||
if (dev->mode == SERPT_MODE_HOSTSER) {
|
||||
struct termios term_attr;
|
||||
tcgetattr(dev->master_fd, &term_attr);
|
||||
#define BAUDRATE_RANGE(baud_rate, min, max, val) \
|
||||
if (baud_rate >= min && baud_rate < max) { \
|
||||
cfsetispeed(&term_attr, val); \
|
||||
cfsetospeed(&term_attr, val); \
|
||||
}
|
||||
|
||||
BAUDRATE_RANGE(dev->baudrate, 50, 75, B50);
|
||||
BAUDRATE_RANGE(dev->baudrate, 75, 110, B75);
|
||||
BAUDRATE_RANGE(dev->baudrate, 110, 134, B110);
|
||||
BAUDRATE_RANGE(dev->baudrate, 134, 150, B134);
|
||||
BAUDRATE_RANGE(dev->baudrate, 150, 200, B150);
|
||||
BAUDRATE_RANGE(dev->baudrate, 200, 300, B200);
|
||||
BAUDRATE_RANGE(dev->baudrate, 300, 600, B300);
|
||||
BAUDRATE_RANGE(dev->baudrate, 600, 1200, B600);
|
||||
BAUDRATE_RANGE(dev->baudrate, 1200, 1800, B1200);
|
||||
BAUDRATE_RANGE(dev->baudrate, 1800, 2400, B1800);
|
||||
BAUDRATE_RANGE(dev->baudrate, 2400, 4800, B2400);
|
||||
BAUDRATE_RANGE(dev->baudrate, 4800, 9600, B4800);
|
||||
BAUDRATE_RANGE(dev->baudrate, 9600, 19200, B9600);
|
||||
BAUDRATE_RANGE(dev->baudrate, 19200, 38400, B19200);
|
||||
BAUDRATE_RANGE(dev->baudrate, 38400, 57600, B38400);
|
||||
BAUDRATE_RANGE(dev->baudrate, 57600, 115200, B57600);
|
||||
BAUDRATE_RANGE(dev->baudrate, 115200, 0xFFFFFFFF, B115200);
|
||||
|
||||
term_attr.c_cflag &= CSIZE;
|
||||
switch (dev->data_bits) {
|
||||
case 8:
|
||||
default:
|
||||
term_attr.c_cflag |= CS8;
|
||||
break;
|
||||
case 7:
|
||||
term_attr.c_cflag |= CS7;
|
||||
break;
|
||||
case 6:
|
||||
term_attr.c_cflag |= CS6;
|
||||
break;
|
||||
case 5:
|
||||
term_attr.c_cflag |= CS5;
|
||||
break;
|
||||
}
|
||||
term_attr.c_cflag &= CSTOPB;
|
||||
if (dev->serial->lcr & 0x04)
|
||||
term_attr.c_cflag |= CSTOPB;
|
||||
#ifdef __APPLE__
|
||||
term_attr.c_cflag &= PARENB | PARODD;
|
||||
#else
|
||||
term_attr.c_cflag &= PARENB | PARODD | CMSPAR;
|
||||
#endif
|
||||
if (dev->serial->lcr & 0x08) {
|
||||
term_attr.c_cflag |= PARENB;
|
||||
if (!(dev->serial->lcr & 0x10))
|
||||
term_attr.c_cflag |= PARODD;
|
||||
#ifndef __APPLE__
|
||||
if ((dev->serial->lcr & 0x20))
|
||||
term_attr.c_cflag |= CMSPAR;
|
||||
#endif
|
||||
}
|
||||
tcsetattr(dev->master_fd, TCSANOW, &term_attr);
|
||||
#undef BAUDRATE_RANGE
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
plat_serpt_write(void *p, uint8_t data)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||
|
||||
switch (dev->mode) {
|
||||
case SERPT_MODE_VCON:
|
||||
case SERPT_MODE_HOSTSER:
|
||||
plat_serpt_write_vcon(dev, data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
open_pseudo_terminal(serial_passthrough_t *dev)
|
||||
{
|
||||
int master_fd = open("/dev/ptmx", O_RDWR | O_NONBLOCK);
|
||||
char *ptname;
|
||||
struct termios term_attr_raw;
|
||||
|
||||
if (!master_fd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get name of slave device */
|
||||
if (!(ptname = ptsname(master_fd))) {
|
||||
pclog(LOG_PREFIX "could not get name of slave pseudo terminal");
|
||||
close(master_fd);
|
||||
return 0;
|
||||
}
|
||||
memset(dev->slave_pt, 0, sizeof(dev->slave_pt));
|
||||
strncpy(dev->slave_pt, ptname, sizeof(dev->slave_pt) - 1);
|
||||
|
||||
fprintf(stderr, LOG_PREFIX "Slave side is %s\n", dev->slave_pt);
|
||||
|
||||
if (grantpt(master_fd)) {
|
||||
pclog(LOG_PREFIX "error in grantpt()\n");
|
||||
close(master_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (unlockpt(master_fd)) {
|
||||
pclog(LOG_PREFIX "error in unlockpt()\n");
|
||||
close(master_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tcgetattr(master_fd, &term_attr_raw);
|
||||
cfmakeraw(&term_attr_raw);
|
||||
tcsetattr(master_fd, TCSANOW, &term_attr_raw);
|
||||
|
||||
dev->master_fd = master_fd;
|
||||
|
||||
return master_fd;
|
||||
}
|
||||
|
||||
static int
|
||||
open_host_serial_port(serial_passthrough_t *dev)
|
||||
{
|
||||
struct termios *term_attr = NULL;
|
||||
struct termios term_attr_raw = {};
|
||||
int fd = open(dev->host_serial_path, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||
if (fd == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!isatty(fd)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
term_attr = calloc(1, sizeof(struct termios));
|
||||
if (!term_attr) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tcgetattr(fd, term_attr) == -1) {
|
||||
free(term_attr);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
term_attr_raw = *term_attr;
|
||||
/* "Raw" mode. */
|
||||
cfmakeraw(&term_attr_raw);
|
||||
term_attr_raw.c_cflag &= CSIZE;
|
||||
switch (dev->data_bits) {
|
||||
case 8:
|
||||
default:
|
||||
term_attr_raw.c_cflag |= CS8;
|
||||
break;
|
||||
case 7:
|
||||
term_attr_raw.c_cflag |= CS7;
|
||||
break;
|
||||
case 6:
|
||||
term_attr_raw.c_cflag |= CS6;
|
||||
break;
|
||||
case 5:
|
||||
term_attr_raw.c_cflag |= CS5;
|
||||
break;
|
||||
}
|
||||
tcsetattr(fd, TCSANOW, &term_attr_raw);
|
||||
dev->backend_priv = term_attr;
|
||||
dev->master_fd = fd;
|
||||
pclog(LOG_PREFIX "Opened host TTY/serial port %s\n", dev->host_serial_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
plat_serpt_open_device(void *p)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||
|
||||
switch (dev->mode) {
|
||||
case SERPT_MODE_VCON:
|
||||
if (!open_pseudo_terminal(dev)) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case SERPT_MODE_HOSTSER:
|
||||
if (!open_host_serial_port(dev)) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -10,13 +10,14 @@
|
||||
#
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
#
|
||||
# Copyright 2020-2021 David Hrdlička.
|
||||
# Copyright 2020,2021 David Hrdlička.
|
||||
# Copyright 2021-2022 Jasmine Iwanek.
|
||||
#
|
||||
|
||||
enable_language(RC)
|
||||
|
||||
add_library(plat OBJECT win.c win_dynld.c win_cdrom.c win_keyboard.c
|
||||
win_mouse.c)
|
||||
win_mouse.c win_serial_passthrough.c)
|
||||
|
||||
add_library(ui OBJECT win_ui.c win_icon.c win_stbar.c win_sdl.c win_dialog.c win_about.c
|
||||
win_settings.c win_devconf.c win_snd_gain.c win_specify_dim.c win_new_floppy.c
|
||||
|
||||
@@ -76,6 +76,9 @@ ifeq ($(DEV_BUILD), y)
|
||||
ifndef PAS16
|
||||
PAS16 := y
|
||||
endif
|
||||
ifndef PCI_DUMMY
|
||||
PCI_DUMMY := y
|
||||
endif
|
||||
ifndef SIO_DETECT
|
||||
SIO_DETECT := y
|
||||
endif
|
||||
@@ -137,6 +140,9 @@ else
|
||||
ifndef PAS16
|
||||
PAS16 := n
|
||||
endif
|
||||
ifndef PCI_DUMMY
|
||||
PCI_DUMMY := n
|
||||
endif
|
||||
ifndef SIO_DETECT
|
||||
SIO_DETECT := n
|
||||
endif
|
||||
@@ -476,6 +482,11 @@ ifeq ($(DEV_BRANCH), y)
|
||||
DEVBROBJ += snd_pas16.o
|
||||
endif
|
||||
|
||||
ifeq ($(PCI_DUMMY), y)
|
||||
OPTS += -DUSE_PCI_DUMMY
|
||||
DEVBROBJ += pci_dummy.o
|
||||
endif
|
||||
|
||||
ifeq ($(SIO_DETECT), y)
|
||||
OPTS += -DUSE_SIO_DETECT
|
||||
DEVBROBJ += sio_detect.o
|
||||
@@ -586,7 +597,7 @@ DEVOBJ := bugger.o cartridge.o cassette.o hasp.o hwm.o hwm_lm75.o hwm_lm78.o hwm
|
||||
mouse_bus.o \
|
||||
mouse_serial.o mouse_ps2.o \
|
||||
mouse_wacom_tablet.o \
|
||||
phoenix_486_jumper.o
|
||||
phoenix_486_jumper.o serial_passthrough.o
|
||||
|
||||
SIOOBJ := sio_acc3221.o sio_ali5123.o \
|
||||
sio_f82c710.o sio_82091aa.o sio_fdc37c6xx.o \
|
||||
@@ -739,7 +750,7 @@ VOODOOOBJ := vid_voodoo.o vid_voodoo_banshee.o \
|
||||
PLATOBJ := win.o \
|
||||
win_dynld.o \
|
||||
win_cdrom.o win_keyboard.o \
|
||||
win_mouse.o
|
||||
win_mouse.o win_serial_passthrough.o
|
||||
|
||||
UIOBJ := win_ui.o win_icon.o win_stbar.o discord.o \
|
||||
win_sdl.o win_opengl.o win_opengl_glslp.o glad.o \
|
||||
@@ -772,13 +783,19 @@ ifdef EXOBJ
|
||||
OBJ += $(EXOBJ)
|
||||
endif
|
||||
|
||||
ifeq ($(LOG), y)
|
||||
MWIN := -lcomdlg32
|
||||
else
|
||||
MWIN := -mwindows
|
||||
endif
|
||||
|
||||
ifeq ($(OPENAL), y)
|
||||
LIBS := -mwindows -lopenal -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lws2_32
|
||||
LIBS := $(MWIN) -lopenal -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lws2_32
|
||||
else
|
||||
ifeq ($(FAUDIO), y)
|
||||
LIBS := -mwindows -lfaudio -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lws2_32
|
||||
LIBS := $(MWIN) -lfaudio -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lws2_32
|
||||
else
|
||||
LIBS := -mwindows -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lws2_32
|
||||
LIBS := $(MWIN) -lcomctl32 -lSDL2 -limagehlp -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -lws2_32
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "Povolit port LPT2"
|
||||
#define STR_PARALLEL3 "Povolit port LPT3"
|
||||
#define STR_PARALLEL4 "Povolit port LPT4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "Řadič disku:"
|
||||
#define STR_FDC "Disketový řadič:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "Parallelport 2"
|
||||
#define STR_PARALLEL3 "Parallelport 3"
|
||||
#define STR_PARALLEL4 "Parallelport 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "HDD-Controller:"
|
||||
#define STR_FDC "FD-Controller:"
|
||||
|
||||
@@ -453,54 +453,78 @@ BEGIN
|
||||
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
|
||||
LTEXT STR_LPT2, IDT_LPT2,
|
||||
CFG_HMARGIN, 28, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT
|
||||
CFG_HMARGIN, 24, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT
|
||||
COMBOBOX IDC_COMBO_LPT2,
|
||||
CFG_COMBO_BOX_LEFT, 26, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT,
|
||||
CFG_COMBO_BOX_LEFT, 22, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT,
|
||||
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
|
||||
LTEXT STR_LPT3, IDT_LPT3,
|
||||
CFG_HMARGIN, 47, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT
|
||||
CFG_HMARGIN, 39, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT
|
||||
COMBOBOX IDC_COMBO_LPT3,
|
||||
CFG_COMBO_BOX_LEFT, 45, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT,
|
||||
CFG_COMBO_BOX_LEFT, 37, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT,
|
||||
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
|
||||
LTEXT STR_LPT4, IDT_LPT4,
|
||||
CFG_HMARGIN, 66, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT
|
||||
CFG_HMARGIN, 54, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT
|
||||
COMBOBOX IDC_COMBO_LPT4,
|
||||
CFG_COMBO_BOX_LEFT, 64, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT,
|
||||
CFG_COMBO_BOX_LEFT, 52, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT,
|
||||
CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
|
||||
CONTROL STR_SERIAL1, IDC_CHECK_SERIAL1,
|
||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
CFG_HMARGIN, 83, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
CFG_HMARGIN, 71, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
|
||||
CONTROL STR_SERIAL2, IDC_CHECK_SERIAL2,
|
||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
CFG_HMARGIN, 102, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
CFG_HMARGIN, 86, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
|
||||
CONTROL STR_SERIAL3, IDC_CHECK_SERIAL3,
|
||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
CFG_HMARGIN, 121, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
CFG_HMARGIN, 101, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
|
||||
CONTROL STR_SERIAL4, IDC_CHECK_SERIAL4,
|
||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
CFG_HMARGIN, 140, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
CFG_HMARGIN, 116, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
|
||||
CONTROL STR_PARALLEL1, IDC_CHECK_PARALLEL1,
|
||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
167, 83, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
167, 71, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
|
||||
CONTROL STR_PARALLEL2, IDC_CHECK_PARALLEL2,
|
||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
167, 102, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
167, 86, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
|
||||
CONTROL STR_PARALLEL3, IDC_CHECK_PARALLEL3,
|
||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
167, 121, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
167, 101, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
|
||||
CONTROL STR_PARALLEL4, IDC_CHECK_PARALLEL4,
|
||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
167, 140, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
167, 116, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
|
||||
CONTROL STR_SERIAL_PASS1, IDC_CHECK_SERIAL_PASS1,
|
||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
CFG_HMARGIN, 134, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SERIAL_PASS1,
|
||||
CFG_COMBO_BTN_LEFT, 131, CFG_BTN_WIDTH, CFG_BTN_HEIGHT
|
||||
|
||||
CONTROL STR_SERIAL_PASS2, IDC_CHECK_SERIAL_PASS2,
|
||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
CFG_HMARGIN, 150, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SERIAL_PASS2,
|
||||
CFG_COMBO_BTN_LEFT, 147, CFG_BTN_WIDTH, CFG_BTN_HEIGHT
|
||||
|
||||
CONTROL STR_SERIAL_PASS3, IDC_CHECK_SERIAL_PASS3,
|
||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
CFG_HMARGIN, 165, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SERIAL_PASS3,
|
||||
CFG_COMBO_BTN_LEFT, 162, CFG_BTN_WIDTH, CFG_BTN_HEIGHT
|
||||
|
||||
CONTROL STR_SERIAL_PASS4, IDC_CHECK_SERIAL_PASS4,
|
||||
"Button", BS_AUTOCHECKBOX | WS_TABSTOP,
|
||||
CFG_HMARGIN, 180, CFG_CHECKBOX_PRI_WIDTH, CFG_CHECKBOX_HEIGHT
|
||||
PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_SERIAL_PASS4,
|
||||
CFG_COMBO_BTN_LEFT, 177, CFG_BTN_WIDTH, CFG_BTN_HEIGHT
|
||||
END
|
||||
|
||||
DLG_CFG_STORAGE DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT
|
||||
@@ -996,6 +1020,10 @@ END
|
||||
#undef STR_PARALLEL2
|
||||
#undef STR_PARALLEL3
|
||||
#undef STR_PARALLEL4
|
||||
#undef STR_SERIAL_PASS1
|
||||
#undef STR_SERIAL_PASS2
|
||||
#undef STR_SERIAL_PASS3
|
||||
#undef STR_SERIAL_PASS4
|
||||
|
||||
#undef STR_HDC
|
||||
#undef STR_FDC
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "Parallel port 2"
|
||||
#define STR_PARALLEL3 "Parallel port 3"
|
||||
#define STR_PARALLEL4 "Parallel port 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "HD Controller:"
|
||||
#define STR_FDC "FD Controller:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "Parallel port 2"
|
||||
#define STR_PARALLEL3 "Parallel port 3"
|
||||
#define STR_PARALLEL4 "Parallel port 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "HD Controller:"
|
||||
#define STR_FDC "FD Controller:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "Puerto paralelo 2"
|
||||
#define STR_PARALLEL3 "Puerto paralelo 3"
|
||||
#define STR_PARALLEL4 "Puerto paralelo 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "Controladora HD:"
|
||||
#define STR_FDC "Controladora FD:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "Rinnakkaisportti 2"
|
||||
#define STR_PARALLEL3 "Rinnakkaisportti 3"
|
||||
#define STR_PARALLEL4 "Rinnakkaisportti 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "Kiintolevyohjain:"
|
||||
#define STR_FDC "Levykeohjain:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "Port parallèle 2"
|
||||
#define STR_PARALLEL3 "Port parallèle 3"
|
||||
#define STR_PARALLEL4 "Port parallèle 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "Contrôleur HD:"
|
||||
#define STR_FDC "Contrôleur FD:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "Paralelna vrata 2"
|
||||
#define STR_PARALLEL3 "Paralelna vrata 3"
|
||||
#define STR_PARALLEL4 "Paralelna vrata 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "Kontroler tvrdog diska:"
|
||||
#define STR_FDC "Kontroler diskete:"
|
||||
|
||||
@@ -333,6 +333,10 @@ END
|
||||
#define STR_PARALLEL2 "Párhuzamos port 2"
|
||||
#define STR_PARALLEL3 "Párhuzamos port 3"
|
||||
#define STR_PARALLEL4 "Párhuzamos port 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "Merevl.-vezérlő:"
|
||||
#define STR_FDC "Floppy-vezérlő:"
|
||||
|
||||
@@ -329,6 +329,10 @@ END
|
||||
#define STR_PARALLEL2 "Porta parallela 2"
|
||||
#define STR_PARALLEL3 "Porta parallela 3"
|
||||
#define STR_PARALLEL4 "Porta parallela 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "Controller HD:"
|
||||
#define STR_FDC "Controller FD:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "パラレルポート2"
|
||||
#define STR_PARALLEL3 "パラレルポート3"
|
||||
#define STR_PARALLEL4 "パラレルポート4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "HDコントローラー:"
|
||||
#define STR_FDC "FDコントローラー:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "병렬 포트 2"
|
||||
#define STR_PARALLEL3 "병렬 포트 3"
|
||||
#define STR_PARALLEL4 "병렬 포트 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "HD 컨트롤러:"
|
||||
#define STR_FDC "FD 컨트롤러:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "Port równoległy 2"
|
||||
#define STR_PARALLEL3 "Port równoległy 3"
|
||||
#define STR_PARALLEL4 "Port równoległy 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "Kontroler dysku twardego:"
|
||||
#define STR_FDC "Kontroler dyskietek:"
|
||||
|
||||
@@ -331,6 +331,10 @@ END
|
||||
#define STR_PARALLEL2 "Porta paralela 2"
|
||||
#define STR_PARALLEL3 "Porta paralela 3"
|
||||
#define STR_PARALLEL4 "Porta paralela 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "Controlador HD:"
|
||||
#define STR_FDC "Controlador FD:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "Porta paralela 2"
|
||||
#define STR_PARALLEL3 "Porta paralela 3"
|
||||
#define STR_PARALLEL4 "Porta paralela 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "Controlador HD:"
|
||||
#define STR_FDC "Controlador FD:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "Параллельный порт LPT2"
|
||||
#define STR_PARALLEL3 "Параллельный порт LPT3"
|
||||
#define STR_PARALLEL4 "Параллельный порт LPT4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "Контроллер HD:"
|
||||
#define STR_FDC "Контроллер FD:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "Paralelna vrata 2"
|
||||
#define STR_PARALLEL3 "Paralelna vrata 3"
|
||||
#define STR_PARALLEL4 "Paralelna vrata 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "Krmilnik trdega diska:"
|
||||
#define STR_FDC "Krmilnik disketnika:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "Paralel port 2"
|
||||
#define STR_PARALLEL3 "Paralel port 3"
|
||||
#define STR_PARALLEL4 "Paralel port 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "HD Kontrolcüsü:"
|
||||
#define STR_FDC "FD Kontrolcüsü:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "Паралельний порт LPT2"
|
||||
#define STR_PARALLEL3 "Паралельний порт LPT3"
|
||||
#define STR_PARALLEL4 "Паралельний порт LPT4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "Контролер HD:"
|
||||
#define STR_FDC "Контролер FD:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "并口 2"
|
||||
#define STR_PARALLEL3 "并口 3"
|
||||
#define STR_PARALLEL4 "并口 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "硬盘控制器:"
|
||||
#define STR_FDC "软盘控制器:"
|
||||
|
||||
@@ -328,6 +328,10 @@ END
|
||||
#define STR_PARALLEL2 "並列埠 2"
|
||||
#define STR_PARALLEL3 "並列埠 3"
|
||||
#define STR_PARALLEL4 "並列埠 4"
|
||||
#define STR_SERIAL_PASS1 "Serial port passthrough 1"
|
||||
#define STR_SERIAL_PASS2 "Serial port passthrough 2"
|
||||
#define STR_SERIAL_PASS3 "Serial port passthrough 3"
|
||||
#define STR_SERIAL_PASS4 "Serial port passthrough 4"
|
||||
|
||||
#define STR_HDC "硬碟控制器:"
|
||||
#define STR_FDC "軟碟控制器:"
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#define UNICODE
|
||||
#include <Windows.h>
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_syswm.h>
|
||||
|
||||
223
src/win/win_serial_passthrough.c
Normal file
223
src/win/win_serial_passthrough.c
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Definitions for platform specific serial to host passthrough
|
||||
*
|
||||
*
|
||||
* Authors: Andreas J. Reichel <webmaster@6th-dimension.com>,
|
||||
* Jasmine Iwanek <jasmine@iwanek.co.uk>
|
||||
*
|
||||
* Copyright 2021 Andreas J. Reichel
|
||||
* Copyright 2021-2022 Jasmine Iwanek
|
||||
*/
|
||||
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <86box/86box.h>
|
||||
#include <86box/log.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/serial_passthrough.h>
|
||||
#include <86box/plat_serial_passthrough.h>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define LOG_PREFIX "serial_passthrough: "
|
||||
|
||||
void
|
||||
plat_serpt_close(void *p)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||
|
||||
// fclose(dev->master_fd);
|
||||
FlushFileBuffers((HANDLE) dev->master_fd);
|
||||
if (dev->mode == SERPT_MODE_VCON)
|
||||
DisconnectNamedPipe((HANDLE) dev->master_fd);
|
||||
if (dev->mode == SERPT_MODE_HOSTSER) {
|
||||
SetCommState((HANDLE)dev->master_fd, (DCB*)dev->backend_priv);
|
||||
free(dev->backend_priv);
|
||||
}
|
||||
CloseHandle((HANDLE) dev->master_fd);
|
||||
}
|
||||
|
||||
static void
|
||||
plat_serpt_write_vcon(serial_passthrough_t *dev, uint8_t data)
|
||||
{
|
||||
/* fd_set wrfds;
|
||||
* int res;
|
||||
*/
|
||||
|
||||
/* We cannot use select here, this would block the hypervisor! */
|
||||
/* FD_ZERO(&wrfds);
|
||||
FD_SET(ctx->master_fd, &wrfds);
|
||||
|
||||
res = select(ctx->master_fd + 1, NULL, &wrfds, NULL, NULL);
|
||||
|
||||
if (res <= 0) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
/* just write it out */
|
||||
// fwrite(dev->master_fd, &data, 1);
|
||||
DWORD bytesWritten = 0;
|
||||
WriteFile((HANDLE) dev->master_fd, &data, 1, &bytesWritten, NULL);
|
||||
if (bytesWritten == 0) {
|
||||
fatal("serial_passthrough: WriteFile pipe write-buffer full!");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
plat_serpt_set_params(void *p)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *)p;
|
||||
|
||||
if (dev->mode == SERPT_MODE_HOSTSER) {
|
||||
DCB serialattr = {};
|
||||
GetCommState((HANDLE)dev->master_fd, &serialattr);
|
||||
#define BAUDRATE_RANGE(baud_rate, min, max) if (baud_rate >= min && baud_rate < max) { serialattr.BaudRate = min; }
|
||||
|
||||
BAUDRATE_RANGE(dev->baudrate, 110, 300);
|
||||
BAUDRATE_RANGE(dev->baudrate, 300, 600);
|
||||
BAUDRATE_RANGE(dev->baudrate, 600, 1200);
|
||||
BAUDRATE_RANGE(dev->baudrate, 1200, 2400);
|
||||
BAUDRATE_RANGE(dev->baudrate, 2400, 4800);
|
||||
BAUDRATE_RANGE(dev->baudrate, 4800, 9600);
|
||||
BAUDRATE_RANGE(dev->baudrate, 9600, 14400);
|
||||
BAUDRATE_RANGE(dev->baudrate, 14400, 19200);
|
||||
BAUDRATE_RANGE(dev->baudrate, 19200, 38400);
|
||||
BAUDRATE_RANGE(dev->baudrate, 38400, 57600);
|
||||
BAUDRATE_RANGE(dev->baudrate, 57600, 115200);
|
||||
BAUDRATE_RANGE(dev->baudrate, 115200, 0xFFFFFFFF);
|
||||
|
||||
serialattr.ByteSize = dev->data_bits;
|
||||
serialattr.StopBits = (dev->serial->lcr & 0x04) ? TWOSTOPBITS : ONESTOPBIT;
|
||||
if (!(dev->serial->lcr & 0x08)) {
|
||||
serialattr.fParity = 0;
|
||||
serialattr.Parity = NOPARITY;
|
||||
} else {
|
||||
serialattr.fParity = 1;
|
||||
if (dev->serial->lcr & 0x20) {
|
||||
serialattr.Parity = (MARKPARITY) + !!(dev->serial->lcr & 0x10);
|
||||
} else {
|
||||
serialattr.Parity = (ODDPARITY) + !!(dev->serial->lcr & 0x10);
|
||||
}
|
||||
}
|
||||
|
||||
SetCommState((HANDLE)dev->master_fd, &serialattr);
|
||||
#undef BAUDRATE_RANGE
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
plat_serpt_write(void *p, uint8_t data)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||
|
||||
switch (dev->mode) {
|
||||
case SERPT_MODE_VCON:
|
||||
case SERPT_MODE_HOSTSER:
|
||||
plat_serpt_write_vcon(dev, data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
plat_serpt_read_vcon(serial_passthrough_t *dev, uint8_t *data)
|
||||
{
|
||||
DWORD bytesRead = 0;
|
||||
ReadFile((HANDLE) dev->master_fd, data, 1, &bytesRead, NULL);
|
||||
return !!bytesRead;
|
||||
}
|
||||
|
||||
int
|
||||
plat_serpt_read(void *p, uint8_t *data)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||
int res = 0;
|
||||
|
||||
switch (dev->mode) {
|
||||
case SERPT_MODE_VCON:
|
||||
case SERPT_MODE_HOSTSER:
|
||||
res = plat_serpt_read_vcon(dev, data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
open_pseudo_terminal(serial_passthrough_t *dev)
|
||||
{
|
||||
char ascii_pipe_name[1024] = { 0 };
|
||||
snprintf(ascii_pipe_name, sizeof(ascii_pipe_name), "\\\\.\\pipe\\86Box\\%s", vm_name);
|
||||
dev->master_fd = (intptr_t) CreateNamedPipeA(ascii_pipe_name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_NOWAIT, 32, 65536, 65536, NMPWAIT_USE_DEFAULT_WAIT, NULL);
|
||||
if (dev->master_fd == (intptr_t) INVALID_HANDLE_VALUE) {
|
||||
return 0;
|
||||
}
|
||||
pclog("Named Pipe @ %s\n", ascii_pipe_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
open_host_serial_port(serial_passthrough_t *dev)
|
||||
{
|
||||
COMMTIMEOUTS timeouts = {
|
||||
.ReadIntervalTimeout = MAXDWORD,
|
||||
.ReadTotalTimeoutConstant = 0,
|
||||
.ReadTotalTimeoutMultiplier = 0,
|
||||
.WriteTotalTimeoutMultiplier = 0,
|
||||
.WriteTotalTimeoutConstant = 1000
|
||||
};
|
||||
DCB* serialattr = calloc(1, sizeof(DCB));
|
||||
if (!serialattr) return 0;
|
||||
dev->master_fd = (intptr_t) CreateFileA(dev->host_serial_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (dev->master_fd == (intptr_t) INVALID_HANDLE_VALUE) {
|
||||
free(serialattr);
|
||||
return 0;
|
||||
}
|
||||
if (!SetCommTimeouts((HANDLE) dev->master_fd, &timeouts)) {
|
||||
pclog(LOG_PREFIX "error setting COM port timeouts.\n");
|
||||
CloseHandle((HANDLE) dev->master_fd);
|
||||
free(serialattr);
|
||||
return 0;
|
||||
}
|
||||
GetCommState((HANDLE)dev->master_fd, serialattr);
|
||||
dev->backend_priv = serialattr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
plat_serpt_open_device(void *p)
|
||||
{
|
||||
serial_passthrough_t *dev = (serial_passthrough_t *) p;
|
||||
|
||||
switch (dev->mode) {
|
||||
case SERPT_MODE_VCON:
|
||||
if (open_pseudo_terminal(dev)) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case SERPT_MODE_HOSTSER:
|
||||
if (open_host_serial_port(dev)) {
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -71,6 +71,7 @@
|
||||
#include <86box/plat.h>
|
||||
#include <86box/ui.h>
|
||||
#include <86box/win.h>
|
||||
#include <86box/serial_passthrough.h>
|
||||
#include "../disk/minivhd/minivhd.h"
|
||||
#include "../disk/minivhd/minivhd_util.h"
|
||||
|
||||
@@ -111,6 +112,7 @@ static char temp_pcap_dev[NET_CARD_MAX][128];
|
||||
/* Ports category */
|
||||
static int temp_lpt_devices[PARALLEL_MAX];
|
||||
static int temp_serial[SERIAL_MAX], temp_lpt[PARALLEL_MAX];
|
||||
static int temp_serial_passthrough_enabled[SERIAL_MAX];
|
||||
|
||||
/* Other peripherals category */
|
||||
static int temp_fdc_card, temp_hdc, temp_ide_ter, temp_ide_qua, temp_cassette;
|
||||
@@ -358,11 +360,13 @@ win_settings_init(void)
|
||||
|
||||
/* Ports category */
|
||||
for (i = 0; i < PARALLEL_MAX; i++) {
|
||||
temp_lpt_devices[i] = lpt_ports[i].device;
|
||||
temp_lpt[i] = lpt_ports[i].enabled;
|
||||
temp_lpt_devices[i] = lpt_ports[i].device;
|
||||
temp_lpt[i] = lpt_ports[i].enabled;
|
||||
}
|
||||
for (i = 0; i < SERIAL_MAX; i++) {
|
||||
temp_serial[i] = com_ports[i].enabled;
|
||||
temp_serial_passthrough_enabled[i] = serial_passthrough_enabled[i];
|
||||
}
|
||||
for (i = 0; i < SERIAL_MAX; i++)
|
||||
temp_serial[i] = com_ports[i].enabled;
|
||||
|
||||
/* Storage devices category */
|
||||
for (i = 0; i < SCSI_BUS_MAX; i++)
|
||||
@@ -484,8 +488,10 @@ win_settings_changed(void)
|
||||
i = i || (temp_lpt_devices[j] != lpt_ports[j].device);
|
||||
i = i || (temp_lpt[j] != lpt_ports[j].enabled);
|
||||
}
|
||||
for (j = 0; j < SERIAL_MAX; j++)
|
||||
for (j = 0; j < SERIAL_MAX; j++) {
|
||||
i = i || (temp_serial[j] != com_ports[j].enabled);
|
||||
i = i || (temp_serial_passthrough_enabled[i] != serial_passthrough_enabled[i]);
|
||||
}
|
||||
|
||||
/* Storage devices category */
|
||||
for (j = 0; j < SCSI_BUS_MAX; j++)
|
||||
@@ -578,8 +584,10 @@ win_settings_save(void)
|
||||
lpt_ports[i].device = temp_lpt_devices[i];
|
||||
lpt_ports[i].enabled = temp_lpt[i];
|
||||
}
|
||||
for (i = 0; i < SERIAL_MAX; i++)
|
||||
for (i = 0; i < SERIAL_MAX; i++) {
|
||||
com_ports[i].enabled = temp_serial[i];
|
||||
serial_passthrough_enabled[i] = temp_serial_passthrough_enabled[i];
|
||||
}
|
||||
|
||||
/* Storage devices category */
|
||||
for (i = 0; i < SCSI_BUS_MAX; i++)
|
||||
@@ -755,7 +763,7 @@ win_settings_machine_recalc_machine(HWND hdlg)
|
||||
|
||||
lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR));
|
||||
|
||||
d = (device_t *) machine_getdevice(temp_machine);
|
||||
d = (device_t *) machine_get_device(temp_machine);
|
||||
settings_enable_window(hdlg, IDC_CONFIGURE_MACHINE, d && d->config);
|
||||
|
||||
settings_reset_content(hdlg, IDC_COMBO_CPU_TYPE);
|
||||
@@ -987,7 +995,7 @@ win_settings_machine_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
break;
|
||||
case IDC_CONFIGURE_MACHINE:
|
||||
temp_machine = listtomachine[settings_get_cur_sel(hdlg, IDC_COMBO_MACHINE)];
|
||||
temp_deviceconfig |= deviceconfig_open(hdlg, (void *) machine_getdevice(temp_machine));
|
||||
temp_deviceconfig |= deviceconfig_open(hdlg, (void *) machine_get_device(temp_machine));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1764,8 +1772,10 @@ win_settings_ports_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
settings_enable_window(hdlg, IDC_COMBO_LPT1 + i, temp_lpt[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < SERIAL_MAX; i++)
|
||||
for (i = 0; i < SERIAL_MAX; i++) {
|
||||
settings_set_check(hdlg, IDC_CHECK_SERIAL1 + i, temp_serial[i]);
|
||||
settings_set_check(hdlg, IDC_CHECK_SERIAL_PASS1 + i, temp_serial_passthrough_enabled[i]);
|
||||
}
|
||||
|
||||
free(lptsTemp);
|
||||
|
||||
@@ -1790,8 +1800,10 @@ win_settings_ports_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
temp_lpt[i] = settings_get_check(hdlg, IDC_CHECK_PARALLEL1 + i);
|
||||
}
|
||||
|
||||
for (i = 0; i < SERIAL_MAX; i++)
|
||||
for (i = 0; i < SERIAL_MAX; i++) {
|
||||
temp_serial[i] = settings_get_check(hdlg, IDC_CHECK_SERIAL1 + i);
|
||||
temp_serial_passthrough_enabled[i] = settings_get_check(hdlg, IDC_CHECK_SERIAL_PASS1 + i);
|
||||
}
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <Windows.h>
|
||||
#include <CommCtrl.h>
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/resource.h>
|
||||
|
||||
Reference in New Issue
Block a user