Bochs/bochs/iodev/serial.cc

1628 lines
62 KiB
C++
Raw Normal View History

/////////////////////////////////////////////////////////////////////////
2011-01-15 01:15:37 +03:00
// $Id: serial.cc,v 1.94 2011-01-14 22:15:37 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
2009-12-04 22:50:29 +03:00
// Copyright (C) 2004-2009 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
/////////////////////////////////////////////////////////////////////////
// Peter Grehan (grehan@iprg.nokia.com) coded the original version of this
// serial emulation. He implemented a single 8250, and allow terminal
// input/output to stdout on FreeBSD.
// The current version emulates up to 4 UART 16550A with FIFO. Terminal
// input/output now works on some more platforms.
Add plugin support to Bochs by merging all the changes from the BRANCH_PLUGINS branch! Authors: Bryce Denney Christophe Bothamy Kevin Lawton (we grabbed a lot of plugin code from plex86) Testing help from: Volker Ruppert Don Becker (Psyon) Jeremy Parsons (Br'fin) The change log is too long to paste in here. To read the change log, do cvs log patches/patch.final-from-BRANCH_PLUGINS.gz All the changes and a detailed description are contained in a patch called patch.final-from-BRANCH_PLUGINS.gz. To look at the complete patch, do cvs upd -r1.1 patches/patch.final-from-BRANCH_PLUGINS.gz Then you will have a local copy of the patch, which you can gunzip and play with however you want. Modified Files: .bochsrc Makefile.in aclocal.m4 bochs.h config.h.in configure configure.in gdbstub.cc logio.cc main.cc pc_system.cc pc_system.h state_file.h bios/Makefile.in bios/rombios.c cpu/Makefile.in cpu/access.cc cpu/apic.cc cpu/arith16.cc cpu/arith32.cc cpu/arith8.cc cpu/cpu.cc cpu/cpu.h cpu/ctrl_xfer32.cc cpu/exception.cc cpu/fetchdecode.cc cpu/fetchdecode64.cc cpu/flag_ctrl.cc cpu/flag_ctrl_pro.cc cpu/init.cc cpu/io.cc cpu/logical16.cc cpu/logical32.cc cpu/logical8.cc cpu/paging.cc cpu/proc_ctrl.cc cpu/protect_ctrl.cc cpu/segment_ctrl_pro.cc cpu/shift16.cc cpu/shift32.cc cpu/stack64.cc cpu/string.cc cpu/tasking.cc debug/Makefile.in debug/dbg_main.cc disasm/Makefile.in doc/docbook/user/user.dbk dynamic/Makefile.in fpu/Makefile.in gui/Makefile.in gui/amigaos.cc gui/beos.cc gui/carbon.cc gui/control.cc gui/control.h gui/gui.cc gui/gui.h gui/keymap.cc gui/keymap.h gui/macintosh.cc gui/nogui.cc gui/rfb.cc gui/sdl.cc gui/sdlkeys.h gui/siminterface.cc gui/siminterface.h gui/term.cc gui/win32.cc gui/wx.cc gui/wxdialog.cc gui/wxdialog.h gui/wxmain.cc gui/wxmain.h gui/x.cc gui/keymaps/sdl-pc-de.map gui/keymaps/sdl-pc-us.map gui/keymaps/x11-pc-de.map instrument/example0/instrument.h instrument/example1/instrument.h instrument/stubs/instrument.cc instrument/stubs/instrument.h iodev/Makefile.in iodev/biosdev.cc iodev/biosdev.h iodev/cdrom.cc iodev/cmos.cc iodev/cmos.h iodev/devices.cc iodev/dma.cc iodev/dma.h iodev/eth_fbsd.cc iodev/eth_linux.cc iodev/eth_null.cc iodev/eth_tap.cc iodev/floppy.cc iodev/floppy.h iodev/guest2host.cc iodev/guest2host.h iodev/harddrv.cc iodev/harddrv.h iodev/iodebug.cc iodev/iodebug.h iodev/iodev.h iodev/keyboard.cc iodev/keyboard.h iodev/ne2k.cc iodev/ne2k.h iodev/parallel.cc iodev/parallel.h iodev/pci.cc iodev/pci.h iodev/pci2isa.cc iodev/pci2isa.h iodev/pic.cc iodev/pic.h iodev/pit.cc iodev/pit.h iodev/pit_wrap.cc iodev/pit_wrap.h iodev/sb16.cc iodev/sb16.h iodev/scancodes.cc iodev/scancodes.h iodev/serial.cc iodev/serial.h iodev/slowdown_timer.cc iodev/slowdown_timer.h iodev/unmapped.cc iodev/unmapped.h iodev/vga.cc iodev/vga.h memory/Makefile.in memory/memory.cc memory/memory.h memory/misc_mem.cc misc/bximage.c misc/niclist.c Added Files: README-plugins extplugin.h ltdl.c ltdl.h ltdlconf.h.in ltmain.sh plugin.cc plugin.h
2002-10-25 01:07:56 +04:00
// Define BX_PLUGGABLE in files that can be compiled into plugins. For
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
Add plugin support to Bochs by merging all the changes from the BRANCH_PLUGINS branch! Authors: Bryce Denney Christophe Bothamy Kevin Lawton (we grabbed a lot of plugin code from plex86) Testing help from: Volker Ruppert Don Becker (Psyon) Jeremy Parsons (Br'fin) The change log is too long to paste in here. To read the change log, do cvs log patches/patch.final-from-BRANCH_PLUGINS.gz All the changes and a detailed description are contained in a patch called patch.final-from-BRANCH_PLUGINS.gz. To look at the complete patch, do cvs upd -r1.1 patches/patch.final-from-BRANCH_PLUGINS.gz Then you will have a local copy of the patch, which you can gunzip and play with however you want. Modified Files: .bochsrc Makefile.in aclocal.m4 bochs.h config.h.in configure configure.in gdbstub.cc logio.cc main.cc pc_system.cc pc_system.h state_file.h bios/Makefile.in bios/rombios.c cpu/Makefile.in cpu/access.cc cpu/apic.cc cpu/arith16.cc cpu/arith32.cc cpu/arith8.cc cpu/cpu.cc cpu/cpu.h cpu/ctrl_xfer32.cc cpu/exception.cc cpu/fetchdecode.cc cpu/fetchdecode64.cc cpu/flag_ctrl.cc cpu/flag_ctrl_pro.cc cpu/init.cc cpu/io.cc cpu/logical16.cc cpu/logical32.cc cpu/logical8.cc cpu/paging.cc cpu/proc_ctrl.cc cpu/protect_ctrl.cc cpu/segment_ctrl_pro.cc cpu/shift16.cc cpu/shift32.cc cpu/stack64.cc cpu/string.cc cpu/tasking.cc debug/Makefile.in debug/dbg_main.cc disasm/Makefile.in doc/docbook/user/user.dbk dynamic/Makefile.in fpu/Makefile.in gui/Makefile.in gui/amigaos.cc gui/beos.cc gui/carbon.cc gui/control.cc gui/control.h gui/gui.cc gui/gui.h gui/keymap.cc gui/keymap.h gui/macintosh.cc gui/nogui.cc gui/rfb.cc gui/sdl.cc gui/sdlkeys.h gui/siminterface.cc gui/siminterface.h gui/term.cc gui/win32.cc gui/wx.cc gui/wxdialog.cc gui/wxdialog.h gui/wxmain.cc gui/wxmain.h gui/x.cc gui/keymaps/sdl-pc-de.map gui/keymaps/sdl-pc-us.map gui/keymaps/x11-pc-de.map instrument/example0/instrument.h instrument/example1/instrument.h instrument/stubs/instrument.cc instrument/stubs/instrument.h iodev/Makefile.in iodev/biosdev.cc iodev/biosdev.h iodev/cdrom.cc iodev/cmos.cc iodev/cmos.h iodev/devices.cc iodev/dma.cc iodev/dma.h iodev/eth_fbsd.cc iodev/eth_linux.cc iodev/eth_null.cc iodev/eth_tap.cc iodev/floppy.cc iodev/floppy.h iodev/guest2host.cc iodev/guest2host.h iodev/harddrv.cc iodev/harddrv.h iodev/iodebug.cc iodev/iodebug.h iodev/iodev.h iodev/keyboard.cc iodev/keyboard.h iodev/ne2k.cc iodev/ne2k.h iodev/parallel.cc iodev/parallel.h iodev/pci.cc iodev/pci.h iodev/pci2isa.cc iodev/pci2isa.h iodev/pic.cc iodev/pic.h iodev/pit.cc iodev/pit.h iodev/pit_wrap.cc iodev/pit_wrap.h iodev/sb16.cc iodev/sb16.h iodev/scancodes.cc iodev/scancodes.h iodev/serial.cc iodev/serial.h iodev/slowdown_timer.cc iodev/slowdown_timer.h iodev/unmapped.cc iodev/unmapped.h iodev/vga.cc iodev/vga.h memory/Makefile.in memory/memory.cc memory/memory.h memory/misc_mem.cc misc/bximage.c misc/niclist.c Added Files: README-plugins extplugin.h ltdl.c ltdl.h ltdlconf.h.in ltmain.sh plugin.cc plugin.h
2002-10-25 01:07:56 +04:00
// is used to know when we are exporting symbols and when we are importing.
#define BX_PLUGGABLE
#ifndef WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define closesocket(s) close(s)
typedef int SOCKET;
#endif
Add plugin support to Bochs by merging all the changes from the BRANCH_PLUGINS branch! Authors: Bryce Denney Christophe Bothamy Kevin Lawton (we grabbed a lot of plugin code from plex86) Testing help from: Volker Ruppert Don Becker (Psyon) Jeremy Parsons (Br'fin) The change log is too long to paste in here. To read the change log, do cvs log patches/patch.final-from-BRANCH_PLUGINS.gz All the changes and a detailed description are contained in a patch called patch.final-from-BRANCH_PLUGINS.gz. To look at the complete patch, do cvs upd -r1.1 patches/patch.final-from-BRANCH_PLUGINS.gz Then you will have a local copy of the patch, which you can gunzip and play with however you want. Modified Files: .bochsrc Makefile.in aclocal.m4 bochs.h config.h.in configure configure.in gdbstub.cc logio.cc main.cc pc_system.cc pc_system.h state_file.h bios/Makefile.in bios/rombios.c cpu/Makefile.in cpu/access.cc cpu/apic.cc cpu/arith16.cc cpu/arith32.cc cpu/arith8.cc cpu/cpu.cc cpu/cpu.h cpu/ctrl_xfer32.cc cpu/exception.cc cpu/fetchdecode.cc cpu/fetchdecode64.cc cpu/flag_ctrl.cc cpu/flag_ctrl_pro.cc cpu/init.cc cpu/io.cc cpu/logical16.cc cpu/logical32.cc cpu/logical8.cc cpu/paging.cc cpu/proc_ctrl.cc cpu/protect_ctrl.cc cpu/segment_ctrl_pro.cc cpu/shift16.cc cpu/shift32.cc cpu/stack64.cc cpu/string.cc cpu/tasking.cc debug/Makefile.in debug/dbg_main.cc disasm/Makefile.in doc/docbook/user/user.dbk dynamic/Makefile.in fpu/Makefile.in gui/Makefile.in gui/amigaos.cc gui/beos.cc gui/carbon.cc gui/control.cc gui/control.h gui/gui.cc gui/gui.h gui/keymap.cc gui/keymap.h gui/macintosh.cc gui/nogui.cc gui/rfb.cc gui/sdl.cc gui/sdlkeys.h gui/siminterface.cc gui/siminterface.h gui/term.cc gui/win32.cc gui/wx.cc gui/wxdialog.cc gui/wxdialog.h gui/wxmain.cc gui/wxmain.h gui/x.cc gui/keymaps/sdl-pc-de.map gui/keymaps/sdl-pc-us.map gui/keymaps/x11-pc-de.map instrument/example0/instrument.h instrument/example1/instrument.h instrument/stubs/instrument.cc instrument/stubs/instrument.h iodev/Makefile.in iodev/biosdev.cc iodev/biosdev.h iodev/cdrom.cc iodev/cmos.cc iodev/cmos.h iodev/devices.cc iodev/dma.cc iodev/dma.h iodev/eth_fbsd.cc iodev/eth_linux.cc iodev/eth_null.cc iodev/eth_tap.cc iodev/floppy.cc iodev/floppy.h iodev/guest2host.cc iodev/guest2host.h iodev/harddrv.cc iodev/harddrv.h iodev/iodebug.cc iodev/iodebug.h iodev/iodev.h iodev/keyboard.cc iodev/keyboard.h iodev/ne2k.cc iodev/ne2k.h iodev/parallel.cc iodev/parallel.h iodev/pci.cc iodev/pci.h iodev/pci2isa.cc iodev/pci2isa.h iodev/pic.cc iodev/pic.h iodev/pit.cc iodev/pit.h iodev/pit_wrap.cc iodev/pit_wrap.h iodev/sb16.cc iodev/sb16.h iodev/scancodes.cc iodev/scancodes.h iodev/serial.cc iodev/serial.h iodev/slowdown_timer.cc iodev/slowdown_timer.h iodev/unmapped.cc iodev/unmapped.h iodev/vga.cc iodev/vga.h memory/Makefile.in memory/memory.cc memory/memory.h memory/misc_mem.cc misc/bximage.c misc/niclist.c Added Files: README-plugins extplugin.h ltdl.c ltdl.h ltdlconf.h.in ltmain.sh plugin.cc plugin.h
2002-10-25 01:07:56 +04:00
#include "iodev.h"
#include "serial.h"
2011-01-15 01:15:37 +03:00
#if defined(WIN32) && !defined(FILE_FLAG_FIRST_PIPE_INSTANCE)
#define FILE_FLAG_FIRST_PIPE_INSTANCE 0
#endif
#if USE_RAW_SERIAL
#include "serial_raw.h"
2011-01-15 01:15:37 +03:00
#endif
Add plugin support to Bochs by merging all the changes from the BRANCH_PLUGINS branch! Authors: Bryce Denney Christophe Bothamy Kevin Lawton (we grabbed a lot of plugin code from plex86) Testing help from: Volker Ruppert Don Becker (Psyon) Jeremy Parsons (Br'fin) The change log is too long to paste in here. To read the change log, do cvs log patches/patch.final-from-BRANCH_PLUGINS.gz All the changes and a detailed description are contained in a patch called patch.final-from-BRANCH_PLUGINS.gz. To look at the complete patch, do cvs upd -r1.1 patches/patch.final-from-BRANCH_PLUGINS.gz Then you will have a local copy of the patch, which you can gunzip and play with however you want. Modified Files: .bochsrc Makefile.in aclocal.m4 bochs.h config.h.in configure configure.in gdbstub.cc logio.cc main.cc pc_system.cc pc_system.h state_file.h bios/Makefile.in bios/rombios.c cpu/Makefile.in cpu/access.cc cpu/apic.cc cpu/arith16.cc cpu/arith32.cc cpu/arith8.cc cpu/cpu.cc cpu/cpu.h cpu/ctrl_xfer32.cc cpu/exception.cc cpu/fetchdecode.cc cpu/fetchdecode64.cc cpu/flag_ctrl.cc cpu/flag_ctrl_pro.cc cpu/init.cc cpu/io.cc cpu/logical16.cc cpu/logical32.cc cpu/logical8.cc cpu/paging.cc cpu/proc_ctrl.cc cpu/protect_ctrl.cc cpu/segment_ctrl_pro.cc cpu/shift16.cc cpu/shift32.cc cpu/stack64.cc cpu/string.cc cpu/tasking.cc debug/Makefile.in debug/dbg_main.cc disasm/Makefile.in doc/docbook/user/user.dbk dynamic/Makefile.in fpu/Makefile.in gui/Makefile.in gui/amigaos.cc gui/beos.cc gui/carbon.cc gui/control.cc gui/control.h gui/gui.cc gui/gui.h gui/keymap.cc gui/keymap.h gui/macintosh.cc gui/nogui.cc gui/rfb.cc gui/sdl.cc gui/sdlkeys.h gui/siminterface.cc gui/siminterface.h gui/term.cc gui/win32.cc gui/wx.cc gui/wxdialog.cc gui/wxdialog.h gui/wxmain.cc gui/wxmain.h gui/x.cc gui/keymaps/sdl-pc-de.map gui/keymaps/sdl-pc-us.map gui/keymaps/x11-pc-de.map instrument/example0/instrument.h instrument/example1/instrument.h instrument/stubs/instrument.cc instrument/stubs/instrument.h iodev/Makefile.in iodev/biosdev.cc iodev/biosdev.h iodev/cdrom.cc iodev/cmos.cc iodev/cmos.h iodev/devices.cc iodev/dma.cc iodev/dma.h iodev/eth_fbsd.cc iodev/eth_linux.cc iodev/eth_null.cc iodev/eth_tap.cc iodev/floppy.cc iodev/floppy.h iodev/guest2host.cc iodev/guest2host.h iodev/harddrv.cc iodev/harddrv.h iodev/iodebug.cc iodev/iodebug.h iodev/iodev.h iodev/keyboard.cc iodev/keyboard.h iodev/ne2k.cc iodev/ne2k.h iodev/parallel.cc iodev/parallel.h iodev/pci.cc iodev/pci.h iodev/pci2isa.cc iodev/pci2isa.h iodev/pic.cc iodev/pic.h iodev/pit.cc iodev/pit.h iodev/pit_wrap.cc iodev/pit_wrap.h iodev/sb16.cc iodev/sb16.h iodev/scancodes.cc iodev/scancodes.h iodev/serial.cc iodev/serial.h iodev/slowdown_timer.cc iodev/slowdown_timer.h iodev/unmapped.cc iodev/unmapped.h iodev/vga.cc iodev/vga.h memory/Makefile.in memory/memory.cc memory/memory.h memory/misc_mem.cc misc/bximage.c misc/niclist.c Added Files: README-plugins extplugin.h ltdl.c ltdl.h ltdlconf.h.in ltmain.sh plugin.cc plugin.h
2002-10-25 01:07:56 +04:00
#define LOG_THIS theSerialDevice->
Add plugin support to Bochs by merging all the changes from the BRANCH_PLUGINS branch! Authors: Bryce Denney Christophe Bothamy Kevin Lawton (we grabbed a lot of plugin code from plex86) Testing help from: Volker Ruppert Don Becker (Psyon) Jeremy Parsons (Br'fin) The change log is too long to paste in here. To read the change log, do cvs log patches/patch.final-from-BRANCH_PLUGINS.gz All the changes and a detailed description are contained in a patch called patch.final-from-BRANCH_PLUGINS.gz. To look at the complete patch, do cvs upd -r1.1 patches/patch.final-from-BRANCH_PLUGINS.gz Then you will have a local copy of the patch, which you can gunzip and play with however you want. Modified Files: .bochsrc Makefile.in aclocal.m4 bochs.h config.h.in configure configure.in gdbstub.cc logio.cc main.cc pc_system.cc pc_system.h state_file.h bios/Makefile.in bios/rombios.c cpu/Makefile.in cpu/access.cc cpu/apic.cc cpu/arith16.cc cpu/arith32.cc cpu/arith8.cc cpu/cpu.cc cpu/cpu.h cpu/ctrl_xfer32.cc cpu/exception.cc cpu/fetchdecode.cc cpu/fetchdecode64.cc cpu/flag_ctrl.cc cpu/flag_ctrl_pro.cc cpu/init.cc cpu/io.cc cpu/logical16.cc cpu/logical32.cc cpu/logical8.cc cpu/paging.cc cpu/proc_ctrl.cc cpu/protect_ctrl.cc cpu/segment_ctrl_pro.cc cpu/shift16.cc cpu/shift32.cc cpu/stack64.cc cpu/string.cc cpu/tasking.cc debug/Makefile.in debug/dbg_main.cc disasm/Makefile.in doc/docbook/user/user.dbk dynamic/Makefile.in fpu/Makefile.in gui/Makefile.in gui/amigaos.cc gui/beos.cc gui/carbon.cc gui/control.cc gui/control.h gui/gui.cc gui/gui.h gui/keymap.cc gui/keymap.h gui/macintosh.cc gui/nogui.cc gui/rfb.cc gui/sdl.cc gui/sdlkeys.h gui/siminterface.cc gui/siminterface.h gui/term.cc gui/win32.cc gui/wx.cc gui/wxdialog.cc gui/wxdialog.h gui/wxmain.cc gui/wxmain.h gui/x.cc gui/keymaps/sdl-pc-de.map gui/keymaps/sdl-pc-us.map gui/keymaps/x11-pc-de.map instrument/example0/instrument.h instrument/example1/instrument.h instrument/stubs/instrument.cc instrument/stubs/instrument.h iodev/Makefile.in iodev/biosdev.cc iodev/biosdev.h iodev/cdrom.cc iodev/cmos.cc iodev/cmos.h iodev/devices.cc iodev/dma.cc iodev/dma.h iodev/eth_fbsd.cc iodev/eth_linux.cc iodev/eth_null.cc iodev/eth_tap.cc iodev/floppy.cc iodev/floppy.h iodev/guest2host.cc iodev/guest2host.h iodev/harddrv.cc iodev/harddrv.h iodev/iodebug.cc iodev/iodebug.h iodev/iodev.h iodev/keyboard.cc iodev/keyboard.h iodev/ne2k.cc iodev/ne2k.h iodev/parallel.cc iodev/parallel.h iodev/pci.cc iodev/pci.h iodev/pci2isa.cc iodev/pci2isa.h iodev/pic.cc iodev/pic.h iodev/pit.cc iodev/pit.h iodev/pit_wrap.cc iodev/pit_wrap.h iodev/sb16.cc iodev/sb16.h iodev/scancodes.cc iodev/scancodes.h iodev/serial.cc iodev/serial.h iodev/slowdown_timer.cc iodev/slowdown_timer.h iodev/unmapped.cc iodev/unmapped.h iodev/vga.cc iodev/vga.h memory/Makefile.in memory/memory.cc memory/memory.h memory/misc_mem.cc misc/bximage.c misc/niclist.c Added Files: README-plugins extplugin.h ltdl.c ltdl.h ltdlconf.h.in ltmain.sh plugin.cc plugin.h
2002-10-25 01:07:56 +04:00
bx_serial_c *theSerialDevice = NULL;
int libserial_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
Add plugin support to Bochs by merging all the changes from the BRANCH_PLUGINS branch! Authors: Bryce Denney Christophe Bothamy Kevin Lawton (we grabbed a lot of plugin code from plex86) Testing help from: Volker Ruppert Don Becker (Psyon) Jeremy Parsons (Br'fin) The change log is too long to paste in here. To read the change log, do cvs log patches/patch.final-from-BRANCH_PLUGINS.gz All the changes and a detailed description are contained in a patch called patch.final-from-BRANCH_PLUGINS.gz. To look at the complete patch, do cvs upd -r1.1 patches/patch.final-from-BRANCH_PLUGINS.gz Then you will have a local copy of the patch, which you can gunzip and play with however you want. Modified Files: .bochsrc Makefile.in aclocal.m4 bochs.h config.h.in configure configure.in gdbstub.cc logio.cc main.cc pc_system.cc pc_system.h state_file.h bios/Makefile.in bios/rombios.c cpu/Makefile.in cpu/access.cc cpu/apic.cc cpu/arith16.cc cpu/arith32.cc cpu/arith8.cc cpu/cpu.cc cpu/cpu.h cpu/ctrl_xfer32.cc cpu/exception.cc cpu/fetchdecode.cc cpu/fetchdecode64.cc cpu/flag_ctrl.cc cpu/flag_ctrl_pro.cc cpu/init.cc cpu/io.cc cpu/logical16.cc cpu/logical32.cc cpu/logical8.cc cpu/paging.cc cpu/proc_ctrl.cc cpu/protect_ctrl.cc cpu/segment_ctrl_pro.cc cpu/shift16.cc cpu/shift32.cc cpu/stack64.cc cpu/string.cc cpu/tasking.cc debug/Makefile.in debug/dbg_main.cc disasm/Makefile.in doc/docbook/user/user.dbk dynamic/Makefile.in fpu/Makefile.in gui/Makefile.in gui/amigaos.cc gui/beos.cc gui/carbon.cc gui/control.cc gui/control.h gui/gui.cc gui/gui.h gui/keymap.cc gui/keymap.h gui/macintosh.cc gui/nogui.cc gui/rfb.cc gui/sdl.cc gui/sdlkeys.h gui/siminterface.cc gui/siminterface.h gui/term.cc gui/win32.cc gui/wx.cc gui/wxdialog.cc gui/wxdialog.h gui/wxmain.cc gui/wxmain.h gui/x.cc gui/keymaps/sdl-pc-de.map gui/keymaps/sdl-pc-us.map gui/keymaps/x11-pc-de.map instrument/example0/instrument.h instrument/example1/instrument.h instrument/stubs/instrument.cc instrument/stubs/instrument.h iodev/Makefile.in iodev/biosdev.cc iodev/biosdev.h iodev/cdrom.cc iodev/cmos.cc iodev/cmos.h iodev/devices.cc iodev/dma.cc iodev/dma.h iodev/eth_fbsd.cc iodev/eth_linux.cc iodev/eth_null.cc iodev/eth_tap.cc iodev/floppy.cc iodev/floppy.h iodev/guest2host.cc iodev/guest2host.h iodev/harddrv.cc iodev/harddrv.h iodev/iodebug.cc iodev/iodebug.h iodev/iodev.h iodev/keyboard.cc iodev/keyboard.h iodev/ne2k.cc iodev/ne2k.h iodev/parallel.cc iodev/parallel.h iodev/pci.cc iodev/pci.h iodev/pci2isa.cc iodev/pci2isa.h iodev/pic.cc iodev/pic.h iodev/pit.cc iodev/pit.h iodev/pit_wrap.cc iodev/pit_wrap.h iodev/sb16.cc iodev/sb16.h iodev/scancodes.cc iodev/scancodes.h iodev/serial.cc iodev/serial.h iodev/slowdown_timer.cc iodev/slowdown_timer.h iodev/unmapped.cc iodev/unmapped.h iodev/vga.cc iodev/vga.h memory/Makefile.in memory/memory.cc memory/memory.h memory/misc_mem.cc misc/bximage.c misc/niclist.c Added Files: README-plugins extplugin.h ltdl.c ltdl.h ltdlconf.h.in ltmain.sh plugin.cc plugin.h
2002-10-25 01:07:56 +04:00
{
theSerialDevice = new bx_serial_c();
Add plugin support to Bochs by merging all the changes from the BRANCH_PLUGINS branch! Authors: Bryce Denney Christophe Bothamy Kevin Lawton (we grabbed a lot of plugin code from plex86) Testing help from: Volker Ruppert Don Becker (Psyon) Jeremy Parsons (Br'fin) The change log is too long to paste in here. To read the change log, do cvs log patches/patch.final-from-BRANCH_PLUGINS.gz All the changes and a detailed description are contained in a patch called patch.final-from-BRANCH_PLUGINS.gz. To look at the complete patch, do cvs upd -r1.1 patches/patch.final-from-BRANCH_PLUGINS.gz Then you will have a local copy of the patch, which you can gunzip and play with however you want. Modified Files: .bochsrc Makefile.in aclocal.m4 bochs.h config.h.in configure configure.in gdbstub.cc logio.cc main.cc pc_system.cc pc_system.h state_file.h bios/Makefile.in bios/rombios.c cpu/Makefile.in cpu/access.cc cpu/apic.cc cpu/arith16.cc cpu/arith32.cc cpu/arith8.cc cpu/cpu.cc cpu/cpu.h cpu/ctrl_xfer32.cc cpu/exception.cc cpu/fetchdecode.cc cpu/fetchdecode64.cc cpu/flag_ctrl.cc cpu/flag_ctrl_pro.cc cpu/init.cc cpu/io.cc cpu/logical16.cc cpu/logical32.cc cpu/logical8.cc cpu/paging.cc cpu/proc_ctrl.cc cpu/protect_ctrl.cc cpu/segment_ctrl_pro.cc cpu/shift16.cc cpu/shift32.cc cpu/stack64.cc cpu/string.cc cpu/tasking.cc debug/Makefile.in debug/dbg_main.cc disasm/Makefile.in doc/docbook/user/user.dbk dynamic/Makefile.in fpu/Makefile.in gui/Makefile.in gui/amigaos.cc gui/beos.cc gui/carbon.cc gui/control.cc gui/control.h gui/gui.cc gui/gui.h gui/keymap.cc gui/keymap.h gui/macintosh.cc gui/nogui.cc gui/rfb.cc gui/sdl.cc gui/sdlkeys.h gui/siminterface.cc gui/siminterface.h gui/term.cc gui/win32.cc gui/wx.cc gui/wxdialog.cc gui/wxdialog.h gui/wxmain.cc gui/wxmain.h gui/x.cc gui/keymaps/sdl-pc-de.map gui/keymaps/sdl-pc-us.map gui/keymaps/x11-pc-de.map instrument/example0/instrument.h instrument/example1/instrument.h instrument/stubs/instrument.cc instrument/stubs/instrument.h iodev/Makefile.in iodev/biosdev.cc iodev/biosdev.h iodev/cdrom.cc iodev/cmos.cc iodev/cmos.h iodev/devices.cc iodev/dma.cc iodev/dma.h iodev/eth_fbsd.cc iodev/eth_linux.cc iodev/eth_null.cc iodev/eth_tap.cc iodev/floppy.cc iodev/floppy.h iodev/guest2host.cc iodev/guest2host.h iodev/harddrv.cc iodev/harddrv.h iodev/iodebug.cc iodev/iodebug.h iodev/iodev.h iodev/keyboard.cc iodev/keyboard.h iodev/ne2k.cc iodev/ne2k.h iodev/parallel.cc iodev/parallel.h iodev/pci.cc iodev/pci.h iodev/pci2isa.cc iodev/pci2isa.h iodev/pic.cc iodev/pic.h iodev/pit.cc iodev/pit.h iodev/pit_wrap.cc iodev/pit_wrap.h iodev/sb16.cc iodev/sb16.h iodev/scancodes.cc iodev/scancodes.h iodev/serial.cc iodev/serial.h iodev/slowdown_timer.cc iodev/slowdown_timer.h iodev/unmapped.cc iodev/unmapped.h iodev/vga.cc iodev/vga.h memory/Makefile.in memory/memory.cc memory/memory.h memory/misc_mem.cc misc/bximage.c misc/niclist.c Added Files: README-plugins extplugin.h ltdl.c ltdl.h ltdlconf.h.in ltmain.sh plugin.cc plugin.h
2002-10-25 01:07:56 +04:00
BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theSerialDevice, BX_PLUGIN_SERIAL);
return(0); // Success
}
void libserial_LTX_plugin_fini(void)
Add plugin support to Bochs by merging all the changes from the BRANCH_PLUGINS branch! Authors: Bryce Denney Christophe Bothamy Kevin Lawton (we grabbed a lot of plugin code from plex86) Testing help from: Volker Ruppert Don Becker (Psyon) Jeremy Parsons (Br'fin) The change log is too long to paste in here. To read the change log, do cvs log patches/patch.final-from-BRANCH_PLUGINS.gz All the changes and a detailed description are contained in a patch called patch.final-from-BRANCH_PLUGINS.gz. To look at the complete patch, do cvs upd -r1.1 patches/patch.final-from-BRANCH_PLUGINS.gz Then you will have a local copy of the patch, which you can gunzip and play with however you want. Modified Files: .bochsrc Makefile.in aclocal.m4 bochs.h config.h.in configure configure.in gdbstub.cc logio.cc main.cc pc_system.cc pc_system.h state_file.h bios/Makefile.in bios/rombios.c cpu/Makefile.in cpu/access.cc cpu/apic.cc cpu/arith16.cc cpu/arith32.cc cpu/arith8.cc cpu/cpu.cc cpu/cpu.h cpu/ctrl_xfer32.cc cpu/exception.cc cpu/fetchdecode.cc cpu/fetchdecode64.cc cpu/flag_ctrl.cc cpu/flag_ctrl_pro.cc cpu/init.cc cpu/io.cc cpu/logical16.cc cpu/logical32.cc cpu/logical8.cc cpu/paging.cc cpu/proc_ctrl.cc cpu/protect_ctrl.cc cpu/segment_ctrl_pro.cc cpu/shift16.cc cpu/shift32.cc cpu/stack64.cc cpu/string.cc cpu/tasking.cc debug/Makefile.in debug/dbg_main.cc disasm/Makefile.in doc/docbook/user/user.dbk dynamic/Makefile.in fpu/Makefile.in gui/Makefile.in gui/amigaos.cc gui/beos.cc gui/carbon.cc gui/control.cc gui/control.h gui/gui.cc gui/gui.h gui/keymap.cc gui/keymap.h gui/macintosh.cc gui/nogui.cc gui/rfb.cc gui/sdl.cc gui/sdlkeys.h gui/siminterface.cc gui/siminterface.h gui/term.cc gui/win32.cc gui/wx.cc gui/wxdialog.cc gui/wxdialog.h gui/wxmain.cc gui/wxmain.h gui/x.cc gui/keymaps/sdl-pc-de.map gui/keymaps/sdl-pc-us.map gui/keymaps/x11-pc-de.map instrument/example0/instrument.h instrument/example1/instrument.h instrument/stubs/instrument.cc instrument/stubs/instrument.h iodev/Makefile.in iodev/biosdev.cc iodev/biosdev.h iodev/cdrom.cc iodev/cmos.cc iodev/cmos.h iodev/devices.cc iodev/dma.cc iodev/dma.h iodev/eth_fbsd.cc iodev/eth_linux.cc iodev/eth_null.cc iodev/eth_tap.cc iodev/floppy.cc iodev/floppy.h iodev/guest2host.cc iodev/guest2host.h iodev/harddrv.cc iodev/harddrv.h iodev/iodebug.cc iodev/iodebug.h iodev/iodev.h iodev/keyboard.cc iodev/keyboard.h iodev/ne2k.cc iodev/ne2k.h iodev/parallel.cc iodev/parallel.h iodev/pci.cc iodev/pci.h iodev/pci2isa.cc iodev/pci2isa.h iodev/pic.cc iodev/pic.h iodev/pit.cc iodev/pit.h iodev/pit_wrap.cc iodev/pit_wrap.h iodev/sb16.cc iodev/sb16.h iodev/scancodes.cc iodev/scancodes.h iodev/serial.cc iodev/serial.h iodev/slowdown_timer.cc iodev/slowdown_timer.h iodev/unmapped.cc iodev/unmapped.h iodev/vga.cc iodev/vga.h memory/Makefile.in memory/memory.cc memory/memory.h memory/misc_mem.cc misc/bximage.c misc/niclist.c Added Files: README-plugins extplugin.h ltdl.c ltdl.h ltdlconf.h.in ltmain.sh plugin.cc plugin.h
2002-10-25 01:07:56 +04:00
{
delete theSerialDevice;
Add plugin support to Bochs by merging all the changes from the BRANCH_PLUGINS branch! Authors: Bryce Denney Christophe Bothamy Kevin Lawton (we grabbed a lot of plugin code from plex86) Testing help from: Volker Ruppert Don Becker (Psyon) Jeremy Parsons (Br'fin) The change log is too long to paste in here. To read the change log, do cvs log patches/patch.final-from-BRANCH_PLUGINS.gz All the changes and a detailed description are contained in a patch called patch.final-from-BRANCH_PLUGINS.gz. To look at the complete patch, do cvs upd -r1.1 patches/patch.final-from-BRANCH_PLUGINS.gz Then you will have a local copy of the patch, which you can gunzip and play with however you want. Modified Files: .bochsrc Makefile.in aclocal.m4 bochs.h config.h.in configure configure.in gdbstub.cc logio.cc main.cc pc_system.cc pc_system.h state_file.h bios/Makefile.in bios/rombios.c cpu/Makefile.in cpu/access.cc cpu/apic.cc cpu/arith16.cc cpu/arith32.cc cpu/arith8.cc cpu/cpu.cc cpu/cpu.h cpu/ctrl_xfer32.cc cpu/exception.cc cpu/fetchdecode.cc cpu/fetchdecode64.cc cpu/flag_ctrl.cc cpu/flag_ctrl_pro.cc cpu/init.cc cpu/io.cc cpu/logical16.cc cpu/logical32.cc cpu/logical8.cc cpu/paging.cc cpu/proc_ctrl.cc cpu/protect_ctrl.cc cpu/segment_ctrl_pro.cc cpu/shift16.cc cpu/shift32.cc cpu/stack64.cc cpu/string.cc cpu/tasking.cc debug/Makefile.in debug/dbg_main.cc disasm/Makefile.in doc/docbook/user/user.dbk dynamic/Makefile.in fpu/Makefile.in gui/Makefile.in gui/amigaos.cc gui/beos.cc gui/carbon.cc gui/control.cc gui/control.h gui/gui.cc gui/gui.h gui/keymap.cc gui/keymap.h gui/macintosh.cc gui/nogui.cc gui/rfb.cc gui/sdl.cc gui/sdlkeys.h gui/siminterface.cc gui/siminterface.h gui/term.cc gui/win32.cc gui/wx.cc gui/wxdialog.cc gui/wxdialog.h gui/wxmain.cc gui/wxmain.h gui/x.cc gui/keymaps/sdl-pc-de.map gui/keymaps/sdl-pc-us.map gui/keymaps/x11-pc-de.map instrument/example0/instrument.h instrument/example1/instrument.h instrument/stubs/instrument.cc instrument/stubs/instrument.h iodev/Makefile.in iodev/biosdev.cc iodev/biosdev.h iodev/cdrom.cc iodev/cmos.cc iodev/cmos.h iodev/devices.cc iodev/dma.cc iodev/dma.h iodev/eth_fbsd.cc iodev/eth_linux.cc iodev/eth_null.cc iodev/eth_tap.cc iodev/floppy.cc iodev/floppy.h iodev/guest2host.cc iodev/guest2host.h iodev/harddrv.cc iodev/harddrv.h iodev/iodebug.cc iodev/iodebug.h iodev/iodev.h iodev/keyboard.cc iodev/keyboard.h iodev/ne2k.cc iodev/ne2k.h iodev/parallel.cc iodev/parallel.h iodev/pci.cc iodev/pci.h iodev/pci2isa.cc iodev/pci2isa.h iodev/pic.cc iodev/pic.h iodev/pit.cc iodev/pit.h iodev/pit_wrap.cc iodev/pit_wrap.h iodev/sb16.cc iodev/sb16.h iodev/scancodes.cc iodev/scancodes.h iodev/serial.cc iodev/serial.h iodev/slowdown_timer.cc iodev/slowdown_timer.h iodev/unmapped.cc iodev/unmapped.h iodev/vga.cc iodev/vga.h memory/Makefile.in memory/memory.cc memory/memory.h memory/misc_mem.cc misc/bximage.c misc/niclist.c Added Files: README-plugins extplugin.h ltdl.c ltdl.h ltdlconf.h.in ltmain.sh plugin.cc plugin.h
2002-10-25 01:07:56 +04:00
}
bx_serial_c::bx_serial_c(void)
{
2001-06-27 23:16:01 +04:00
put("SER");
for (int i=0; i<BX_SERIAL_MAXDEV; i++) {
s[i].io_mode = BX_SER_MODE_NULL;
s[i].tty_id = -1;
s[i].tx_timer_index = BX_NULL_TIMER_HANDLE;
s[i].rx_timer_index = BX_NULL_TIMER_HANDLE;
s[i].fifo_timer_index = BX_NULL_TIMER_HANDLE;
}
}
bx_serial_c::~bx_serial_c(void)
{
char pname[20];
bx_list_c *base;
for (int i=0; i<BX_SERIAL_MAXDEV; i++) {
sprintf(pname, "ports.serial.%d", i+1);
base = (bx_list_c*) SIM->get_param(pname);
if (SIM->get_param_bool("enabled", base)->get()) {
switch (BX_SER_THIS s[i].io_mode) {
case BX_SER_MODE_FILE:
if (BX_SER_THIS s[i].output != NULL)
fclose(BX_SER_THIS s[i].output);
break;
case BX_SER_MODE_TERM:
#if defined(SERIAL_ENABLE) && !defined(WIN32)
if (s[i].tty_id >= 0) {
tcsetattr(s[i].tty_id, TCSAFLUSH, &s[i].term_orig);
}
#endif
break;
case BX_SER_MODE_RAW:
#if USE_RAW_SERIAL
delete [] BX_SER_THIS s[i].raw;
#endif
break;
case BX_SER_MODE_SOCKET:
if (BX_SER_THIS s[i].socket_id >= 0) closesocket(BX_SER_THIS s[i].socket_id);
break;
case BX_SER_MODE_PIPE:
#ifdef WIN32
if (BX_SER_THIS s[i].pipe)
CloseHandle(BX_SER_THIS s[i].pipe);
#endif
break;
}
}
}
BX_DEBUG(("Exit"));
}
void
Add plugin support to Bochs by merging all the changes from the BRANCH_PLUGINS branch! Authors: Bryce Denney Christophe Bothamy Kevin Lawton (we grabbed a lot of plugin code from plex86) Testing help from: Volker Ruppert Don Becker (Psyon) Jeremy Parsons (Br'fin) The change log is too long to paste in here. To read the change log, do cvs log patches/patch.final-from-BRANCH_PLUGINS.gz All the changes and a detailed description are contained in a patch called patch.final-from-BRANCH_PLUGINS.gz. To look at the complete patch, do cvs upd -r1.1 patches/patch.final-from-BRANCH_PLUGINS.gz Then you will have a local copy of the patch, which you can gunzip and play with however you want. Modified Files: .bochsrc Makefile.in aclocal.m4 bochs.h config.h.in configure configure.in gdbstub.cc logio.cc main.cc pc_system.cc pc_system.h state_file.h bios/Makefile.in bios/rombios.c cpu/Makefile.in cpu/access.cc cpu/apic.cc cpu/arith16.cc cpu/arith32.cc cpu/arith8.cc cpu/cpu.cc cpu/cpu.h cpu/ctrl_xfer32.cc cpu/exception.cc cpu/fetchdecode.cc cpu/fetchdecode64.cc cpu/flag_ctrl.cc cpu/flag_ctrl_pro.cc cpu/init.cc cpu/io.cc cpu/logical16.cc cpu/logical32.cc cpu/logical8.cc cpu/paging.cc cpu/proc_ctrl.cc cpu/protect_ctrl.cc cpu/segment_ctrl_pro.cc cpu/shift16.cc cpu/shift32.cc cpu/stack64.cc cpu/string.cc cpu/tasking.cc debug/Makefile.in debug/dbg_main.cc disasm/Makefile.in doc/docbook/user/user.dbk dynamic/Makefile.in fpu/Makefile.in gui/Makefile.in gui/amigaos.cc gui/beos.cc gui/carbon.cc gui/control.cc gui/control.h gui/gui.cc gui/gui.h gui/keymap.cc gui/keymap.h gui/macintosh.cc gui/nogui.cc gui/rfb.cc gui/sdl.cc gui/sdlkeys.h gui/siminterface.cc gui/siminterface.h gui/term.cc gui/win32.cc gui/wx.cc gui/wxdialog.cc gui/wxdialog.h gui/wxmain.cc gui/wxmain.h gui/x.cc gui/keymaps/sdl-pc-de.map gui/keymaps/sdl-pc-us.map gui/keymaps/x11-pc-de.map instrument/example0/instrument.h instrument/example1/instrument.h instrument/stubs/instrument.cc instrument/stubs/instrument.h iodev/Makefile.in iodev/biosdev.cc iodev/biosdev.h iodev/cdrom.cc iodev/cmos.cc iodev/cmos.h iodev/devices.cc iodev/dma.cc iodev/dma.h iodev/eth_fbsd.cc iodev/eth_linux.cc iodev/eth_null.cc iodev/eth_tap.cc iodev/floppy.cc iodev/floppy.h iodev/guest2host.cc iodev/guest2host.h iodev/harddrv.cc iodev/harddrv.h iodev/iodebug.cc iodev/iodebug.h iodev/iodev.h iodev/keyboard.cc iodev/keyboard.h iodev/ne2k.cc iodev/ne2k.h iodev/parallel.cc iodev/parallel.h iodev/pci.cc iodev/pci.h iodev/pci2isa.cc iodev/pci2isa.h iodev/pic.cc iodev/pic.h iodev/pit.cc iodev/pit.h iodev/pit_wrap.cc iodev/pit_wrap.h iodev/sb16.cc iodev/sb16.h iodev/scancodes.cc iodev/scancodes.h iodev/serial.cc iodev/serial.h iodev/slowdown_timer.cc iodev/slowdown_timer.h iodev/unmapped.cc iodev/unmapped.h iodev/vga.cc iodev/vga.h memory/Makefile.in memory/memory.cc memory/memory.h memory/misc_mem.cc misc/bximage.c misc/niclist.c Added Files: README-plugins extplugin.h ltdl.c ltdl.h ltdlconf.h.in ltmain.sh plugin.cc plugin.h
2002-10-25 01:07:56 +04:00
bx_serial_c::init(void)
{
Bit16u ports[BX_SERIAL_MAXDEV] = {0x03f8, 0x02f8, 0x03e8, 0x02e8};
char name[16], pname[20];
bx_list_c *base;
unsigned i;
BX_SER_THIS detect_mouse = 0;
BX_SER_THIS mouse_port = -1;
BX_SER_THIS mouse_type = BX_MOUSE_TYPE_NONE;
BX_SER_THIS mouse_internal_buffer.num_elements = 0;
for (i=0; i<BX_MOUSE_BUFF_SIZE; i++)
BX_SER_THIS mouse_internal_buffer.buffer[i] = 0;
BX_SER_THIS mouse_internal_buffer.head = 0;
BX_SER_THIS mouse_delayed_dx = 0;
BX_SER_THIS mouse_delayed_dy = 0;
/*
* Put the UART registers into their RESET state
*/
for (i=0; i<BX_N_SERIAL_PORTS; i++) {
sprintf(pname, "ports.serial.%d", i+1);
base = (bx_list_c*) SIM->get_param(pname);
if (SIM->get_param_bool("enabled", base)->get()) {
sprintf(name, "Serial Port %d", i + 1);
/* serial interrupt */
BX_SER_THIS s[i].IRQ = 4 - (i & 1);
if (i < 2) {
DEV_register_irq(BX_SER_THIS s[i].IRQ, name);
}
/* internal state */
BX_SER_THIS s[i].ls_ipending = 0;
BX_SER_THIS s[i].ms_ipending = 0;
BX_SER_THIS s[i].rx_ipending = 0;
BX_SER_THIS s[i].fifo_ipending = 0;
BX_SER_THIS s[i].ls_interrupt = 0;
BX_SER_THIS s[i].ms_interrupt = 0;
BX_SER_THIS s[i].rx_interrupt = 0;
BX_SER_THIS s[i].tx_interrupt = 0;
BX_SER_THIS s[i].fifo_interrupt = 0;
if (BX_SER_THIS s[i].tx_timer_index == BX_NULL_TIMER_HANDLE) {
BX_SER_THIS s[i].tx_timer_index =
bx_pc_system.register_timer(this, tx_timer_handler, 0,
0,0, "serial.tx"); // one-shot, inactive
}
if (BX_SER_THIS s[i].rx_timer_index == BX_NULL_TIMER_HANDLE) {
BX_SER_THIS s[i].rx_timer_index =
bx_pc_system.register_timer(this, rx_timer_handler, 0,
0,0, "serial.rx"); // one-shot, inactive
}
if (BX_SER_THIS s[i].fifo_timer_index == BX_NULL_TIMER_HANDLE) {
BX_SER_THIS s[i].fifo_timer_index =
bx_pc_system.register_timer(this, fifo_timer_handler, 0,
0,0, "serial.fifo"); // one-shot, inactive
}
BX_SER_THIS s[i].rx_pollstate = BX_SER_RXIDLE;
/* int enable: b0000 0000 */
BX_SER_THIS s[i].int_enable.rxdata_enable = 0;
BX_SER_THIS s[i].int_enable.txhold_enable = 0;
BX_SER_THIS s[i].int_enable.rxlstat_enable = 0;
BX_SER_THIS s[i].int_enable.modstat_enable = 0;
/* int ID: b0000 0001 */
BX_SER_THIS s[i].int_ident.ipending = 1;
BX_SER_THIS s[i].int_ident.int_ID = 0;
/* FIFO control: b0000 0000 */
BX_SER_THIS s[i].fifo_cntl.enable = 0;
BX_SER_THIS s[i].fifo_cntl.rxtrigger = 0;
BX_SER_THIS s[i].rx_fifo_end = 0;
BX_SER_THIS s[i].tx_fifo_end = 0;
/* Line Control reg: b0000 0000 */
BX_SER_THIS s[i].line_cntl.wordlen_sel = 0;
BX_SER_THIS s[i].line_cntl.stopbits = 0;
BX_SER_THIS s[i].line_cntl.parity_enable = 0;
BX_SER_THIS s[i].line_cntl.evenparity_sel = 0;
BX_SER_THIS s[i].line_cntl.stick_parity = 0;
BX_SER_THIS s[i].line_cntl.break_cntl = 0;
BX_SER_THIS s[i].line_cntl.dlab = 0;
/* Modem Control reg: b0000 0000 */
BX_SER_THIS s[i].modem_cntl.dtr = 0;
BX_SER_THIS s[i].modem_cntl.rts = 0;
BX_SER_THIS s[i].modem_cntl.out1 = 0;
BX_SER_THIS s[i].modem_cntl.out2 = 0;
BX_SER_THIS s[i].modem_cntl.local_loopback = 0;
/* Line Status register: b0110 0000 */
BX_SER_THIS s[i].line_status.rxdata_ready = 0;
BX_SER_THIS s[i].line_status.overrun_error = 0;
BX_SER_THIS s[i].line_status.parity_error = 0;
BX_SER_THIS s[i].line_status.framing_error = 0;
BX_SER_THIS s[i].line_status.break_int = 0;
BX_SER_THIS s[i].line_status.thr_empty = 1;
BX_SER_THIS s[i].line_status.tsr_empty = 1;
BX_SER_THIS s[i].line_status.fifo_error = 0;
/* Modem Status register: bXXXX 0000 */
BX_SER_THIS s[i].modem_status.delta_cts = 0;
BX_SER_THIS s[i].modem_status.delta_dsr = 0;
BX_SER_THIS s[i].modem_status.ri_trailedge = 0;
BX_SER_THIS s[i].modem_status.delta_dcd = 0;
BX_SER_THIS s[i].modem_status.cts = 0;
BX_SER_THIS s[i].modem_status.dsr = 0;
BX_SER_THIS s[i].modem_status.ri = 0;
BX_SER_THIS s[i].modem_status.dcd = 0;
BX_SER_THIS s[i].scratch = 0; /* scratch register */
BX_SER_THIS s[i].divisor_lsb = 1; /* divisor-lsb register */
BX_SER_THIS s[i].divisor_msb = 0; /* divisor-msb register */
BX_SER_THIS s[i].baudrate = 115200;
for (unsigned addr=ports[i]; addr<(unsigned)(ports[i]+8); addr++) {
BX_DEBUG(("com%d initialize register for read/write: 0x%04x",i+1, addr));
DEV_register_ioread_handler(this, read_handler, addr, name, 1);
DEV_register_iowrite_handler(this, write_handler, addr, name, 1);
}
BX_SER_THIS s[i].io_mode = BX_SER_MODE_NULL;
2007-10-25 03:17:42 +04:00
const char *mode = SIM->get_param_enum("mode", base)->get_selected();
const char *dev = SIM->get_param_string("dev", base)->getptr();
if (!strcmp(mode, "file")) {
if (strlen(dev) > 0) {
BX_SER_THIS s[i].output = fopen(dev, "wb");
if (BX_SER_THIS s[i].output)
BX_SER_THIS s[i].io_mode = BX_SER_MODE_FILE;
}
} else if (!strcmp(mode, "term")) {
#if defined(SERIAL_ENABLE) && !defined(WIN32)
if (strlen(dev) > 0) {
BX_SER_THIS s[i].tty_id = open(dev, O_RDWR|O_NONBLOCK,600);
if (BX_SER_THIS s[i].tty_id < 0) {
BX_PANIC(("open of com%d (%s) failed", i+1, dev));
} else {
BX_SER_THIS s[i].io_mode = BX_SER_MODE_TERM;
BX_DEBUG(("com%d tty_id: %d", i+1, BX_SER_THIS s[i].tty_id));
tcgetattr(BX_SER_THIS s[i].tty_id, &BX_SER_THIS s[i].term_orig);
memcpy(&BX_SER_THIS s[i].term_orig, &BX_SER_THIS s[i].term_new, sizeof(struct termios));
BX_SER_THIS s[i].term_new.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
BX_SER_THIS s[i].term_new.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
BX_SER_THIS s[i].term_new.c_cflag &= ~(CSIZE|PARENB);
BX_SER_THIS s[i].term_new.c_cflag |= CS8;
BX_SER_THIS s[i].term_new.c_oflag |= OPOST | ONLCR; // Enable NL to CR-NL translation
#ifndef TRUE_CTLC
// ctl-C will exit Bochs, or trap to the debugger
BX_SER_THIS s[i].term_new.c_iflag &= ~IGNBRK;
BX_SER_THIS s[i].term_new.c_iflag |= BRKINT;
BX_SER_THIS s[i].term_new.c_lflag |= ISIG;
#else
// ctl-C will be delivered to the serial port
BX_SER_THIS s[i].term_new.c_iflag |= IGNBRK;
BX_SER_THIS s[i].term_new.c_iflag &= ~BRKINT;
#endif /* !def TRUE_CTLC */
BX_SER_THIS s[i].term_new.c_iflag = 0;
BX_SER_THIS s[i].term_new.c_oflag = 0;
BX_SER_THIS s[i].term_new.c_cflag = CS8|CREAD|CLOCAL;
BX_SER_THIS s[i].term_new.c_lflag = 0;
BX_SER_THIS s[i].term_new.c_cc[VMIN] = 1;
BX_SER_THIS s[i].term_new.c_cc[VTIME] = 0;
//BX_SER_THIS s[i].term_new.c_iflag |= IXOFF;
tcsetattr(BX_SER_THIS s[i].tty_id, TCSAFLUSH, &BX_SER_THIS s[i].term_new);
}
}
#else
BX_PANIC(("serial terminal support not available"));
#endif /* def SERIAL_ENABLE */
} else if (!strcmp(mode, "raw")) {
#if USE_RAW_SERIAL
BX_SER_THIS s[i].raw = new serial_raw(dev);
BX_SER_THIS s[i].io_mode = BX_SER_MODE_RAW;
#else
BX_PANIC(("raw serial support not present"));
#endif
} else if (!strcmp(mode, "mouse")) {
BX_SER_THIS s[i].io_mode = BX_SER_MODE_MOUSE;
BX_SER_THIS mouse_port = i;
BX_SER_THIS mouse_type = SIM->get_param_enum(BXPN_MOUSE_TYPE)->get();
} else if (!strncmp(mode, "socket", 6)) {
BX_SER_THIS s[i].io_mode = BX_SER_MODE_SOCKET;
struct sockaddr_in sin;
struct hostent *hp;
char host[BX_PATHNAME_LEN];
int port;
2010-11-23 17:59:36 +03:00
SOCKET socket;
bx_bool server = !strcmp(mode, "socket-server");
#if defined(WIN32)
static bx_bool winsock_init = false;
if (!winsock_init) {
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 0);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
BX_PANIC(("WSAStartup failed"));
winsock_init = true;
}
#endif
strcpy(host, dev);
char *substr = strtok(host, ":");
substr = strtok(NULL, ":");
if (!substr) {
BX_PANIC(("com%d: inet address is wrong (%s)", i+1, dev));
}
port = atoi(substr);
hp = gethostbyname(host);
if (!hp) {
BX_PANIC(("com%d: gethostbyname failed (%s)", i+1, host));
}
memset ((char*) &sin, 0, sizeof (sin));
#if BX_HAVE_SOCKADDR_IN_SIN_LEN
sin.sin_len = sizeof sin;
#endif
memcpy ((char*) &(sin.sin_addr), hp->h_addr, hp->h_length);
sin.sin_family = hp->h_addrtype;
sin.sin_port = htons (port);
socket = ::socket (AF_INET, SOCK_STREAM, 0);
if (socket < 0)
BX_PANIC(("com%d: socket() failed",i+1));
// server mode
if (server) {
if (::bind (socket, (sockaddr *) &sin, sizeof (sin)) < 0 ||
::listen (socket, SOMAXCONN) < 0) {
closesocket(socket);
2010-11-23 17:59:36 +03:00
socket = (SOCKET) -1;
BX_PANIC(("com%d: bind() or listen() failed (host:%s, port:%d)",i+1, host, port));
}
else {
BX_INFO(("com%d: waiting for client to connect (host:%s, port:%d)",i+1, host, port));
2010-11-23 17:59:36 +03:00
SOCKET client;
if ((client = ::accept (socket, NULL, 0)) < 0)
BX_PANIC(("com%d: accept() failed (host:%s, port:%d)",i+1, host, port));
closesocket(socket);
socket = client;
}
}
// client mode
else if (::connect (socket, (sockaddr *) &sin, sizeof (sin)) < 0) {
closesocket(socket);
2010-11-23 17:59:36 +03:00
socket = (SOCKET) -1;
BX_INFO(("com%d: connect() failed (host:%s, port:%d)",i+1, host, port));
}
BX_SER_THIS s[i].socket_id = socket;
if (socket > 0)
BX_INFO(("com%d - inet %s - socket_id: %d, ip:%s, port:%d",
i+1, server ? "server" : "client", socket, host, port));
} else if (!strncmp(mode, "pipe", 4)) {
if (strlen(dev) > 0) {
#ifdef WIN32
2008-12-21 11:56:26 +03:00
bx_bool server = !strcmp(mode, "pipe-server");
HANDLE pipe;
BX_SER_THIS s[i].io_mode = BX_SER_MODE_PIPE;
// server mode
if (server) {
pipe = CreateNamedPipe( dev,
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1, 4096, 4096, 0, NULL);
if (pipe == INVALID_HANDLE_VALUE)
BX_PANIC(("com%d: CreateNamedPipe(%s) failed", i+1, dev));
BX_INFO(("com%d: waiting for client to connect to %s", i+1, dev));
if (!ConnectNamedPipe(pipe, NULL) && GetLastError() != ERROR_PIPE_CONNECTED)
{
CloseHandle(pipe);
pipe = INVALID_HANDLE_VALUE;
BX_PANIC(("com%d: ConnectNamedPipe(%s) failed", i+1, dev));
}
}
// client mode
else {
pipe = CreateFile( dev,
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (pipe == INVALID_HANDLE_VALUE)
BX_INFO(("com%d: failed to open pipe %s", i+1, dev));
}
if (pipe != INVALID_HANDLE_VALUE)
BX_SER_THIS s[i].pipe = pipe;
#else
BX_PANIC(("support for serial mode '%s' not available", mode));
#endif
}
} else if (strcmp(mode, "null")) {
BX_PANIC(("unknown serial i/o mode '%s'", mode));
}
// simulate device connected
if (BX_SER_THIS s[i].io_mode != BX_SER_MODE_RAW) {
BX_SER_THIS s[i].modem_status.cts = 1;
BX_SER_THIS s[i].modem_status.dsr = 1;
}
BX_INFO(("com%d at 0x%04x irq %d", i+1, ports[i], BX_SER_THIS s[i].IRQ));
}
}
if ((BX_SER_THIS mouse_type == BX_MOUSE_TYPE_SERIAL) ||
(BX_SER_THIS mouse_type == BX_MOUSE_TYPE_SERIAL_WHEEL) ||
(BX_SER_THIS mouse_type == BX_MOUSE_TYPE_SERIAL_MSYS)) {
DEV_register_default_mouse(this, mouse_enq_static, NULL);
}
}
2006-05-27 19:54:49 +04:00
void bx_serial_c::reset(unsigned type)
{
}
2006-05-27 19:54:49 +04:00
void bx_serial_c::register_state(void)
{
unsigned i, j;
char name[6];
bx_list_c *port;
bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "serial", "Serial Port State", 9);
2006-05-27 19:54:49 +04:00
for (i=0; i<BX_N_SERIAL_PORTS; i++) {
sprintf(name, "%d", i);
port = new bx_list_c(list, name, 28);
2006-05-27 19:54:49 +04:00
new bx_shadow_bool_c(port, "ls_interrupt", &BX_SER_THIS s[i].ls_interrupt);
new bx_shadow_bool_c(port, "ms_interrupt", &BX_SER_THIS s[i].ms_interrupt);
new bx_shadow_bool_c(port, "rx_interrupt", &BX_SER_THIS s[i].rx_interrupt);
new bx_shadow_bool_c(port, "tx_interrupt", &BX_SER_THIS s[i].tx_interrupt);
new bx_shadow_bool_c(port, "fifo_interrupt", &BX_SER_THIS s[i].fifo_interrupt);
new bx_shadow_bool_c(port, "ls_ipending", &BX_SER_THIS s[i].ls_ipending);
new bx_shadow_bool_c(port, "ms_ipending", &BX_SER_THIS s[i].ms_ipending);
new bx_shadow_bool_c(port, "rx_ipending", &BX_SER_THIS s[i].rx_ipending);
new bx_shadow_bool_c(port, "fifo_ipending", &BX_SER_THIS s[i].fifo_ipending);
new bx_shadow_num_c(port, "rx_fifo_end", &BX_SER_THIS s[i].rx_fifo_end);
new bx_shadow_num_c(port, "tx_fifo_end", &BX_SER_THIS s[i].tx_fifo_end);
new bx_shadow_num_c(port, "baudrate", &BX_SER_THIS s[i].baudrate);
new bx_shadow_num_c(port, "rx_pollstate", &BX_SER_THIS s[i].rx_pollstate);
new bx_shadow_num_c(port, "rxbuffer", &BX_SER_THIS s[i].rxbuffer, BASE_HEX);
new bx_shadow_num_c(port, "thrbuffer", &BX_SER_THIS s[i].thrbuffer, BASE_HEX);
bx_list_c *int_en = new bx_list_c(port, "int_enable", 4);
2006-05-27 19:54:49 +04:00
new bx_shadow_bool_c(int_en, "rxdata_enable", &BX_SER_THIS s[i].int_enable.rxdata_enable);
new bx_shadow_bool_c(int_en, "txhold_enable", &BX_SER_THIS s[i].int_enable.txhold_enable);
new bx_shadow_bool_c(int_en, "rxlstat_enable", &BX_SER_THIS s[i].int_enable.rxlstat_enable);
new bx_shadow_bool_c(int_en, "modstat_enable", &BX_SER_THIS s[i].int_enable.modstat_enable);
bx_list_c *int_id = new bx_list_c(port, "int_ident", 2);
2006-05-27 19:54:49 +04:00
new bx_shadow_bool_c(int_id, "ipending", &BX_SER_THIS s[i].int_ident.ipending);
new bx_shadow_num_c(int_id, "int_ID", &BX_SER_THIS s[i].int_ident.int_ID, BASE_HEX);
bx_list_c *fifo = new bx_list_c(port, "fifo_cntl", 2);
2006-05-27 19:54:49 +04:00
new bx_shadow_bool_c(fifo, "enable", &BX_SER_THIS s[i].fifo_cntl.enable);
new bx_shadow_num_c(fifo, "rxtrigger", &BX_SER_THIS s[i].fifo_cntl.rxtrigger, BASE_HEX);
bx_list_c *lcntl = new bx_list_c(port, "line_cntl", 7);
new bx_shadow_num_c(lcntl, "wordlen_sel", &BX_SER_THIS s[i].line_cntl.wordlen_sel, BASE_HEX);
new bx_shadow_bool_c(lcntl, "stopbits", &BX_SER_THIS s[i].line_cntl.stopbits);
new bx_shadow_bool_c(lcntl, "parity_enable", &BX_SER_THIS s[i].line_cntl.parity_enable);
new bx_shadow_bool_c(lcntl, "evenparity_sel", &BX_SER_THIS s[i].line_cntl.evenparity_sel);
new bx_shadow_bool_c(lcntl, "stick_parity", &BX_SER_THIS s[i].line_cntl.stick_parity);
new bx_shadow_bool_c(lcntl, "break_cntl", &BX_SER_THIS s[i].line_cntl.break_cntl);
new bx_shadow_bool_c(lcntl, "dlab", &BX_SER_THIS s[i].line_cntl.dlab);
bx_list_c *mcntl = new bx_list_c(port, "modem_cntl", 5);
2006-05-27 19:54:49 +04:00
new bx_shadow_bool_c(mcntl, "dtr", &BX_SER_THIS s[i].modem_cntl.dtr);
new bx_shadow_bool_c(mcntl, "rts", &BX_SER_THIS s[i].modem_cntl.rts);
new bx_shadow_bool_c(mcntl, "out1", &BX_SER_THIS s[i].modem_cntl.out1);
new bx_shadow_bool_c(mcntl, "out2", &BX_SER_THIS s[i].modem_cntl.out2);
new bx_shadow_bool_c(mcntl, "local_loopback", &BX_SER_THIS s[i].modem_cntl.local_loopback);
bx_list_c *lstatus = new bx_list_c(port, "line_status", 8);
new bx_shadow_bool_c(lstatus, "rxdata_ready", &BX_SER_THIS s[i].line_status.rxdata_ready);
new bx_shadow_bool_c(lstatus, "overrun_error", &BX_SER_THIS s[i].line_status.overrun_error);
new bx_shadow_bool_c(lstatus, "parity_error", &BX_SER_THIS s[i].line_status.parity_error);
new bx_shadow_bool_c(lstatus, "framing_error", &BX_SER_THIS s[i].line_status.framing_error);
new bx_shadow_bool_c(lstatus, "break_int", &BX_SER_THIS s[i].line_status.break_int);
new bx_shadow_bool_c(lstatus, "thr_empty", &BX_SER_THIS s[i].line_status.thr_empty);
new bx_shadow_bool_c(lstatus, "tsr_empty", &BX_SER_THIS s[i].line_status.tsr_empty);
new bx_shadow_bool_c(lstatus, "fifo_error", &BX_SER_THIS s[i].line_status.fifo_error);
bx_list_c *mstatus = new bx_list_c(port, "modem_status", 8);
new bx_shadow_bool_c(mstatus, "delta_cts", &BX_SER_THIS s[i].modem_status.delta_cts);
new bx_shadow_bool_c(mstatus, "delta_dsr", &BX_SER_THIS s[i].modem_status.delta_dsr);
new bx_shadow_bool_c(mstatus, "ri_trailedge", &BX_SER_THIS s[i].modem_status.ri_trailedge);
new bx_shadow_bool_c(mstatus, "delta_dcd", &BX_SER_THIS s[i].modem_status.delta_dcd);
new bx_shadow_bool_c(mstatus, "cts", &BX_SER_THIS s[i].modem_status.cts);
new bx_shadow_bool_c(mstatus, "dsr", &BX_SER_THIS s[i].modem_status.dsr);
new bx_shadow_bool_c(mstatus, "ri", &BX_SER_THIS s[i].modem_status.ri);
new bx_shadow_bool_c(mstatus, "dcd", &BX_SER_THIS s[i].modem_status.dcd);
new bx_shadow_num_c(port, "scratch", &BX_SER_THIS s[i].scratch, BASE_HEX);
new bx_shadow_num_c(port, "tsrbuffer", &BX_SER_THIS s[i].tsrbuffer, BASE_HEX);
bx_list_c *rxfifo = new bx_list_c(port, "rx_fifo", 16);
for (j=0; j<16; j++) {
sprintf(name, "0x%02x", j);
new bx_shadow_num_c(rxfifo, name, &BX_SER_THIS s[i].rx_fifo[j], BASE_HEX);
2006-05-27 19:54:49 +04:00
}
bx_list_c *txfifo = new bx_list_c(port, "tx_fifo", 16);
for (j=0; j<16; j++) {
sprintf(name, "0x%02x", j);
new bx_shadow_num_c(txfifo, name, &BX_SER_THIS s[i].tx_fifo[j], BASE_HEX);
2006-05-27 19:54:49 +04:00
}
new bx_shadow_num_c(port, "divisor_lsb", &BX_SER_THIS s[i].divisor_lsb, BASE_HEX);
new bx_shadow_num_c(port, "divisor_msb", &BX_SER_THIS s[i].divisor_msb, BASE_HEX);
}
new bx_shadow_num_c(list, "detect_mouse", &BX_SER_THIS detect_mouse);
new bx_shadow_num_c(list, "mouse_delayed_dx", &BX_SER_THIS mouse_delayed_dx);
new bx_shadow_num_c(list, "mouse_delayed_dy", &BX_SER_THIS mouse_delayed_dy);
new bx_shadow_num_c(list, "mouse_delayed_dz", &BX_SER_THIS mouse_delayed_dz);
bx_list_c *mousebuf = new bx_list_c(list, "mouse_internal_buffer", 3);
2006-05-27 19:54:49 +04:00
new bx_shadow_num_c(mousebuf, "num_elements", &BX_SER_THIS mouse_internal_buffer.num_elements);
bx_list_c *buffer = new bx_list_c(mousebuf, "buffer", BX_MOUSE_BUFF_SIZE);
for (i=0; i<BX_MOUSE_BUFF_SIZE; i++) {
sprintf(name, "0x%02x", i);
new bx_shadow_num_c(buffer, name, &BX_SER_THIS mouse_internal_buffer.buffer[i], BASE_HEX);
2006-05-27 19:54:49 +04:00
}
new bx_shadow_num_c(mousebuf, "head", &BX_SER_THIS mouse_internal_buffer.head);
}
void bx_serial_c::lower_interrupt(Bit8u port)
{
/* If there are no more ints pending, clear the irq */
if ((BX_SER_THIS s[port].rx_interrupt == 0) &&
(BX_SER_THIS s[port].tx_interrupt == 0) &&
(BX_SER_THIS s[port].ls_interrupt == 0) &&
(BX_SER_THIS s[port].ms_interrupt == 0) &&
(BX_SER_THIS s[port].fifo_interrupt == 0)) {
DEV_pic_lower_irq(BX_SER_THIS s[port].IRQ);
}
}
void
bx_serial_c::raise_interrupt(Bit8u port, int type)
{
bx_bool gen_int = 0;
switch (type) {
case BX_SER_INT_IER: /* IER has changed */
gen_int = 1;
break;
case BX_SER_INT_RXDATA:
if (BX_SER_THIS s[port].int_enable.rxdata_enable) {
BX_SER_THIS s[port].rx_interrupt = 1;
gen_int = 1;
} else {
BX_SER_THIS s[port].rx_ipending = 1;
}
break;
case BX_SER_INT_TXHOLD:
if (BX_SER_THIS s[port].int_enable.txhold_enable) {
BX_SER_THIS s[port].tx_interrupt = 1;
gen_int = 1;
}
break;
case BX_SER_INT_RXLSTAT:
if (BX_SER_THIS s[port].int_enable.rxlstat_enable) {
BX_SER_THIS s[port].ls_interrupt = 1;
gen_int = 1;
} else {
BX_SER_THIS s[port].ls_ipending = 1;
}
break;
case BX_SER_INT_MODSTAT:
if ((BX_SER_THIS s[port].ms_ipending == 1) &&
(BX_SER_THIS s[port].int_enable.modstat_enable == 1)) {
BX_SER_THIS s[port].ms_interrupt = 1;
BX_SER_THIS s[port].ms_ipending = 0;
gen_int = 1;
}
break;
case BX_SER_INT_FIFO:
if (BX_SER_THIS s[port].int_enable.rxdata_enable) {
BX_SER_THIS s[port].fifo_interrupt = 1;
gen_int = 1;
} else {
BX_SER_THIS s[port].fifo_ipending = 1;
}
break;
}
if (gen_int && BX_SER_THIS s[port].modem_cntl.out2) {
DEV_pic_raise_irq(BX_SER_THIS s[port].IRQ);
}
}
// static IO port read callback handler
// redirects to non-static class handler to avoid virtual functions
Bit32u bx_serial_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
{
#if !BX_USE_SER_SMF
bx_serial_c *class_ptr = (bx_serial_c *) this_ptr;
return class_ptr->read(address, io_len);
}
Bit32u bx_serial_c::read(Bit32u address, unsigned io_len)
{
#else
UNUSED(this_ptr);
#endif // !BX_USE_SER_SMF
bx_bool prev_cts, prev_dsr, prev_ri, prev_dcd;
Bit8u offset, val;
Bit8u port = 0;
offset = address & 0x07;
switch (address & 0x03f8) {
case 0x03f8: port = 0; break;
case 0x02f8: port = 1; break;
case 0x03e8: port = 2; break;
case 0x02e8: port = 3; break;
}
switch (offset) {
case BX_SER_RBR: /* receive buffer, or divisor latch LSB if DLAB set */
if (BX_SER_THIS s[port].line_cntl.dlab) {
val = BX_SER_THIS s[port].divisor_lsb;
} else {
if (BX_SER_THIS s[port].fifo_cntl.enable) {
val = BX_SER_THIS s[port].rx_fifo[0];
if (BX_SER_THIS s[port].rx_fifo_end > 0) {
memcpy(&BX_SER_THIS s[port].rx_fifo[0], &BX_SER_THIS s[port].rx_fifo[1], 15);
BX_SER_THIS s[port].rx_fifo_end--;
}
if (BX_SER_THIS s[port].rx_fifo_end == 0) {
BX_SER_THIS s[port].line_status.rxdata_ready = 0;
BX_SER_THIS s[port].rx_interrupt = 0;
BX_SER_THIS s[port].rx_ipending = 0;
BX_SER_THIS s[port].fifo_interrupt = 0;
BX_SER_THIS s[port].fifo_ipending = 0;
lower_interrupt(port);
}
} else {
val = BX_SER_THIS s[port].rxbuffer;
BX_SER_THIS s[port].line_status.rxdata_ready = 0;
BX_SER_THIS s[port].rx_interrupt = 0;
BX_SER_THIS s[port].rx_ipending = 0;
lower_interrupt(port);
}
}
break;
case BX_SER_IER: /* interrupt enable register, or div. latch MSB */
if (BX_SER_THIS s[port].line_cntl.dlab) {
val = BX_SER_THIS s[port].divisor_msb;
} else {
val = BX_SER_THIS s[port].int_enable.rxdata_enable |
(BX_SER_THIS s[port].int_enable.txhold_enable << 1) |
(BX_SER_THIS s[port].int_enable.rxlstat_enable << 2) |
(BX_SER_THIS s[port].int_enable.modstat_enable << 3);
}
break;
case BX_SER_IIR: /* interrupt ID register */
/*
* Set the interrupt ID based on interrupt source
*/
if (BX_SER_THIS s[port].ls_interrupt) {
BX_SER_THIS s[port].int_ident.int_ID = 0x3;
BX_SER_THIS s[port].int_ident.ipending = 0;
} else if (BX_SER_THIS s[port].fifo_interrupt) {
BX_SER_THIS s[port].int_ident.int_ID = 0x6;
BX_SER_THIS s[port].int_ident.ipending = 0;
} else if (BX_SER_THIS s[port].rx_interrupt) {
BX_SER_THIS s[port].int_ident.int_ID = 0x2;
BX_SER_THIS s[port].int_ident.ipending = 0;
} else if (BX_SER_THIS s[port].tx_interrupt) {
BX_SER_THIS s[port].int_ident.int_ID = 0x1;
BX_SER_THIS s[port].int_ident.ipending = 0;
} else if (BX_SER_THIS s[port].ms_interrupt) {
BX_SER_THIS s[port].int_ident.int_ID = 0x0;
BX_SER_THIS s[port].int_ident.ipending = 0;
} else {
BX_SER_THIS s[port].int_ident.int_ID = 0x0;
BX_SER_THIS s[port].int_ident.ipending = 1;
}
BX_SER_THIS s[port].tx_interrupt = 0;
lower_interrupt(port);
val = BX_SER_THIS s[port].int_ident.ipending |
(BX_SER_THIS s[port].int_ident.int_ID << 1) |
(BX_SER_THIS s[port].fifo_cntl.enable ? 0xc0 : 0x00);
break;
case BX_SER_LCR: /* Line control register */
val = BX_SER_THIS s[port].line_cntl.wordlen_sel |
(BX_SER_THIS s[port].line_cntl.stopbits << 2) |
(BX_SER_THIS s[port].line_cntl.parity_enable << 3) |
(BX_SER_THIS s[port].line_cntl.evenparity_sel << 4) |
(BX_SER_THIS s[port].line_cntl.stick_parity << 5) |
(BX_SER_THIS s[port].line_cntl.break_cntl << 6) |
(BX_SER_THIS s[port].line_cntl.dlab << 7);
break;
case BX_SER_MCR: /* MODEM control register */
val = BX_SER_THIS s[port].modem_cntl.dtr |
(BX_SER_THIS s[port].modem_cntl.rts << 1) |
(BX_SER_THIS s[port].modem_cntl.out1 << 2) |
(BX_SER_THIS s[port].modem_cntl.out2 << 3) |
(BX_SER_THIS s[port].modem_cntl.local_loopback << 4);
break;
case BX_SER_LSR: /* Line status register */
val = BX_SER_THIS s[port].line_status.rxdata_ready |
(BX_SER_THIS s[port].line_status.overrun_error << 1) |
(BX_SER_THIS s[port].line_status.parity_error << 2) |
(BX_SER_THIS s[port].line_status.framing_error << 3) |
(BX_SER_THIS s[port].line_status.break_int << 4) |
(BX_SER_THIS s[port].line_status.thr_empty << 5) |
(BX_SER_THIS s[port].line_status.tsr_empty << 6) |
(BX_SER_THIS s[port].line_status.fifo_error << 7);
BX_SER_THIS s[port].line_status.overrun_error = 0;
BX_SER_THIS s[port].line_status.framing_error = 0;
BX_SER_THIS s[port].line_status.break_int = 0;
BX_SER_THIS s[port].ls_interrupt = 0;
BX_SER_THIS s[port].ls_ipending = 0;
lower_interrupt(port);
break;
case BX_SER_MSR: /* MODEM status register */
prev_cts = BX_SER_THIS s[port].modem_status.cts;
prev_dsr = BX_SER_THIS s[port].modem_status.dsr;
prev_ri = BX_SER_THIS s[port].modem_status.ri;
prev_dcd = BX_SER_THIS s[port].modem_status.dcd;
if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) {
#if USE_RAW_SERIAL
val = BX_SER_THIS s[port].raw->get_modem_status();
BX_SER_THIS s[port].modem_status.cts = (val & 0x10) >> 4;
BX_SER_THIS s[port].modem_status.dsr = (val & 0x20) >> 5;
BX_SER_THIS s[port].modem_status.ri = (val & 0x40) >> 6;
BX_SER_THIS s[port].modem_status.dcd = (val & 0x80) >> 7;
if (BX_SER_THIS s[port].modem_status.cts != prev_cts) {
BX_SER_THIS s[port].modem_status.delta_cts = 1;
}
if (BX_SER_THIS s[port].modem_status.dsr != prev_dsr) {
BX_SER_THIS s[port].modem_status.delta_dsr = 1;
}
if ((BX_SER_THIS s[port].modem_status.ri == 0) && (prev_ri == 1))
BX_SER_THIS s[port].modem_status.ri_trailedge = 1;
if (BX_SER_THIS s[port].modem_status.dcd != prev_dcd) {
BX_SER_THIS s[port].modem_status.delta_dcd = 1;
}
#endif
}
val = BX_SER_THIS s[port].modem_status.delta_cts |
(BX_SER_THIS s[port].modem_status.delta_dsr << 1) |
(BX_SER_THIS s[port].modem_status.ri_trailedge << 2) |
(BX_SER_THIS s[port].modem_status.delta_dcd << 3) |
(BX_SER_THIS s[port].modem_status.cts << 4) |
(BX_SER_THIS s[port].modem_status.dsr << 5) |
(BX_SER_THIS s[port].modem_status.ri << 6) |
(BX_SER_THIS s[port].modem_status.dcd << 7);
BX_SER_THIS s[port].modem_status.delta_cts = 0;
BX_SER_THIS s[port].modem_status.delta_dsr = 0;
BX_SER_THIS s[port].modem_status.ri_trailedge = 0;
BX_SER_THIS s[port].modem_status.delta_dcd = 0;
BX_SER_THIS s[port].ms_interrupt = 0;
BX_SER_THIS s[port].ms_ipending = 0;
lower_interrupt(port);
break;
case BX_SER_SCR: /* scratch register */
val = BX_SER_THIS s[port].scratch;
break;
default:
val = 0; // keep compiler happy
BX_PANIC(("unsupported io read from address=0x%04x!", address));
break;
}
BX_DEBUG(("com%d register read from address: 0x%04x = 0x%02x", port+1, address, val));
return(val);
}
// static IO port write callback handler
// redirects to non-static class handler to avoid virtual functions
2001-06-19 21:52:46 +04:00
void
bx_serial_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
{
#if !BX_USE_SER_SMF
bx_serial_c *class_ptr = (bx_serial_c *) this_ptr;
class_ptr->write(address, value, io_len);
}
2001-06-19 21:52:46 +04:00
void
bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
{
#else
UNUSED(this_ptr);
#endif // !BX_USE_SER_SMF
- Apply patch.replace-Boolean rev 1.3. Every "Boolean" is now changed to a "bx_bool" which is always defined as Bit32u on all platforms. In Carbon specific code, Boolean is still used because the Carbon header files define it to unsigned char. - this fixes bug [ 623152 ] MacOSX: Triple Exception Booting win95. The bug was that some code in Bochs depends on Boolean to be a 32 bit value. (This should be fixed, but I don't know all the places where it needs to be fixed yet.) Because Carbon defined Boolean as an unsigned char, Bochs just followed along and used the unsigned char definition to avoid compile problems. This exposed the dependency on 32 bit Boolean on MacOS X only and led to major simulation problems, that could only be reproduced and debugged on that platform. - On the mailing list we debated whether to make all Booleans into "bool" or our own type. I chose bx_bool for several reasons. 1. Unlike C++'s bool, we can guarantee that bx_bool is the same size on all platforms, which makes it much less likely to have more platform-specific simulation differences in the future. (I spent hours on a borrowed MacOSX machine chasing bug 618388 before discovering that different sized Booleans were the problem, and I don't want to repeat that.) 2. We still have at least one dependency on 32 bit Booleans which must be fixed some time, but I don't want to risk introducing new bugs into the simulation just before the 2.0 release. Modified Files: bochs.h config.h.in gdbstub.cc logio.cc main.cc pc_system.cc pc_system.h plugin.cc plugin.h bios/rombios.c cpu/apic.cc cpu/arith16.cc cpu/arith32.cc cpu/arith64.cc cpu/arith8.cc cpu/cpu.cc cpu/cpu.h cpu/ctrl_xfer16.cc cpu/ctrl_xfer32.cc cpu/ctrl_xfer64.cc cpu/data_xfer16.cc cpu/data_xfer32.cc cpu/data_xfer64.cc cpu/debugstuff.cc cpu/exception.cc cpu/fetchdecode.cc cpu/flag_ctrl_pro.cc cpu/init.cc cpu/io_pro.cc cpu/lazy_flags.cc cpu/lazy_flags.h cpu/mult16.cc cpu/mult32.cc cpu/mult64.cc cpu/mult8.cc cpu/paging.cc cpu/proc_ctrl.cc cpu/segment_ctrl_pro.cc cpu/stack_pro.cc cpu/tasking.cc debug/dbg_main.cc debug/debug.h debug/sim2.cc disasm/dis_decode.cc disasm/disasm.h doc/docbook/Makefile docs-html/cosimulation.html fpu/wmFPUemu_glue.cc gui/amigaos.cc gui/beos.cc gui/carbon.cc gui/gui.cc gui/gui.h gui/keymap.cc gui/keymap.h gui/macintosh.cc gui/nogui.cc gui/rfb.cc gui/sdl.cc gui/siminterface.cc gui/siminterface.h gui/term.cc gui/win32.cc gui/wx.cc gui/wxmain.cc gui/wxmain.h gui/x.cc instrument/example0/instrument.cc instrument/example0/instrument.h instrument/example1/instrument.cc instrument/example1/instrument.h instrument/stubs/instrument.cc instrument/stubs/instrument.h iodev/cdrom.cc iodev/cdrom.h iodev/cdrom_osx.cc iodev/cmos.cc iodev/devices.cc iodev/dma.cc iodev/dma.h iodev/eth_arpback.cc iodev/eth_packetmaker.cc iodev/eth_packetmaker.h iodev/floppy.cc iodev/floppy.h iodev/guest2host.h iodev/harddrv.cc iodev/harddrv.h iodev/ioapic.cc iodev/ioapic.h iodev/iodebug.cc iodev/iodev.h iodev/keyboard.cc iodev/keyboard.h iodev/ne2k.h iodev/parallel.h iodev/pci.cc iodev/pci.h iodev/pic.h iodev/pit.cc iodev/pit.h iodev/pit_wrap.cc iodev/pit_wrap.h iodev/sb16.cc iodev/sb16.h iodev/serial.cc iodev/serial.h iodev/vga.cc iodev/vga.h memory/memory.h memory/misc_mem.cc
2002-10-25 15:44:41 +04:00
bx_bool prev_cts, prev_dsr, prev_ri, prev_dcd;
bx_bool new_b0, new_b1, new_b2, new_b3;
bx_bool new_b4, new_b5, new_b6, new_b7;
- Apply patch.replace-Boolean rev 1.3. Every "Boolean" is now changed to a "bx_bool" which is always defined as Bit32u on all platforms. In Carbon specific code, Boolean is still used because the Carbon header files define it to unsigned char. - this fixes bug [ 623152 ] MacOSX: Triple Exception Booting win95. The bug was that some code in Bochs depends on Boolean to be a 32 bit value. (This should be fixed, but I don't know all the places where it needs to be fixed yet.) Because Carbon defined Boolean as an unsigned char, Bochs just followed along and used the unsigned char definition to avoid compile problems. This exposed the dependency on 32 bit Boolean on MacOS X only and led to major simulation problems, that could only be reproduced and debugged on that platform. - On the mailing list we debated whether to make all Booleans into "bool" or our own type. I chose bx_bool for several reasons. 1. Unlike C++'s bool, we can guarantee that bx_bool is the same size on all platforms, which makes it much less likely to have more platform-specific simulation differences in the future. (I spent hours on a borrowed MacOSX machine chasing bug 618388 before discovering that different sized Booleans were the problem, and I don't want to repeat that.) 2. We still have at least one dependency on 32 bit Booleans which must be fixed some time, but I don't want to risk introducing new bugs into the simulation just before the 2.0 release. Modified Files: bochs.h config.h.in gdbstub.cc logio.cc main.cc pc_system.cc pc_system.h plugin.cc plugin.h bios/rombios.c cpu/apic.cc cpu/arith16.cc cpu/arith32.cc cpu/arith64.cc cpu/arith8.cc cpu/cpu.cc cpu/cpu.h cpu/ctrl_xfer16.cc cpu/ctrl_xfer32.cc cpu/ctrl_xfer64.cc cpu/data_xfer16.cc cpu/data_xfer32.cc cpu/data_xfer64.cc cpu/debugstuff.cc cpu/exception.cc cpu/fetchdecode.cc cpu/flag_ctrl_pro.cc cpu/init.cc cpu/io_pro.cc cpu/lazy_flags.cc cpu/lazy_flags.h cpu/mult16.cc cpu/mult32.cc cpu/mult64.cc cpu/mult8.cc cpu/paging.cc cpu/proc_ctrl.cc cpu/segment_ctrl_pro.cc cpu/stack_pro.cc cpu/tasking.cc debug/dbg_main.cc debug/debug.h debug/sim2.cc disasm/dis_decode.cc disasm/disasm.h doc/docbook/Makefile docs-html/cosimulation.html fpu/wmFPUemu_glue.cc gui/amigaos.cc gui/beos.cc gui/carbon.cc gui/gui.cc gui/gui.h gui/keymap.cc gui/keymap.h gui/macintosh.cc gui/nogui.cc gui/rfb.cc gui/sdl.cc gui/siminterface.cc gui/siminterface.h gui/term.cc gui/win32.cc gui/wx.cc gui/wxmain.cc gui/wxmain.h gui/x.cc instrument/example0/instrument.cc instrument/example0/instrument.h instrument/example1/instrument.cc instrument/example1/instrument.h instrument/stubs/instrument.cc instrument/stubs/instrument.h iodev/cdrom.cc iodev/cdrom.h iodev/cdrom_osx.cc iodev/cmos.cc iodev/devices.cc iodev/dma.cc iodev/dma.h iodev/eth_arpback.cc iodev/eth_packetmaker.cc iodev/eth_packetmaker.h iodev/floppy.cc iodev/floppy.h iodev/guest2host.h iodev/harddrv.cc iodev/harddrv.h iodev/ioapic.cc iodev/ioapic.h iodev/iodebug.cc iodev/iodev.h iodev/keyboard.cc iodev/keyboard.h iodev/ne2k.h iodev/parallel.h iodev/pci.cc iodev/pci.h iodev/pic.h iodev/pit.cc iodev/pit.h iodev/pit_wrap.cc iodev/pit_wrap.h iodev/sb16.cc iodev/sb16.h iodev/serial.cc iodev/serial.h iodev/vga.cc iodev/vga.h memory/memory.h memory/misc_mem.cc
2002-10-25 15:44:41 +04:00
bx_bool gen_int = 0;
Bit8u offset, new_wordlen;
#if USE_RAW_SERIAL
bx_bool mcr_changed = 0;
Bit8u p_mode;
#endif
Bit8u port = 0;
offset = address & 0x07;
switch (address & 0x03f8) {
case 0x03f8: port = 0; break;
case 0x02f8: port = 1; break;
case 0x03e8: port = 2; break;
case 0x02e8: port = 3; break;
}
BX_DEBUG(("com%d register write to address: 0x%04x = 0x%02x", port+1, address, value));
new_b0 = value & 0x01;
new_b1 = (value & 0x02) >> 1;
new_b2 = (value & 0x04) >> 2;
new_b3 = (value & 0x08) >> 3;
new_b4 = (value & 0x10) >> 4;
new_b5 = (value & 0x20) >> 5;
new_b6 = (value & 0x40) >> 6;
new_b7 = (value & 0x80) >> 7;
switch (offset) {
case BX_SER_THR: /* transmit buffer, or divisor latch LSB if DLAB set */
if (BX_SER_THIS s[port].line_cntl.dlab) {
BX_SER_THIS s[port].divisor_lsb = value;
if ((value != 0) || (BX_SER_THIS s[port].divisor_msb != 0)) {
BX_SER_THIS s[port].baudrate = (int) (BX_PC_CLOCK_XTL /
(16 * ((BX_SER_THIS s[port].divisor_msb << 8) |
BX_SER_THIS s[port].divisor_lsb)));
}
} else {
Bit8u bitmask = 0xff >> (3 - BX_SER_THIS s[port].line_cntl.wordlen_sel);
if (BX_SER_THIS s[port].line_status.thr_empty) {
if (BX_SER_THIS s[port].fifo_cntl.enable) {
BX_SER_THIS s[port].tx_fifo[BX_SER_THIS s[port].tx_fifo_end++] = value & bitmask;
} else {
BX_SER_THIS s[port].thrbuffer = value & bitmask;
}
BX_SER_THIS s[port].line_status.thr_empty = 0;
if (BX_SER_THIS s[port].line_status.tsr_empty) {
if (BX_SER_THIS s[port].fifo_cntl.enable) {
BX_SER_THIS s[port].tsrbuffer = BX_SER_THIS s[port].tx_fifo[0];
memcpy(&BX_SER_THIS s[port].tx_fifo[0], &BX_SER_THIS s[port].tx_fifo[1], 15);
BX_SER_THIS s[port].line_status.thr_empty = (--BX_SER_THIS s[port].tx_fifo_end == 0);
} else {
BX_SER_THIS s[port].tsrbuffer = BX_SER_THIS s[port].thrbuffer;
BX_SER_THIS s[port].line_status.thr_empty = 1;
}
BX_SER_THIS s[port].line_status.tsr_empty = 0;
raise_interrupt(port, BX_SER_INT_TXHOLD);
bx_pc_system.activate_timer(BX_SER_THIS s[port].tx_timer_index,
(int) (1000000.0 / BX_SER_THIS s[port].baudrate *
(BX_SER_THIS s[port].line_cntl.wordlen_sel + 5)),
0); /* not continuous */
} else {
BX_SER_THIS s[port].tx_interrupt = 0;
lower_interrupt(port);
}
} else {
if (BX_SER_THIS s[port].fifo_cntl.enable) {
if (BX_SER_THIS s[port].tx_fifo_end < 16) {
BX_SER_THIS s[port].tx_fifo[BX_SER_THIS s[port].tx_fifo_end++] = value & bitmask;
} else {
BX_ERROR(("com%d: transmit FIFO overflow", port+1));
}
} else {
BX_ERROR(("com%d: write to tx hold register when not empty", port+1));
}
}
}
break;
case BX_SER_IER: /* interrupt enable register, or div. latch MSB */
if (BX_SER_THIS s[port].line_cntl.dlab) {
BX_SER_THIS s[port].divisor_msb = value;
if ((value != 0) || (BX_SER_THIS s[port].divisor_lsb != 0)) {
BX_SER_THIS s[port].baudrate = (int) (BX_PC_CLOCK_XTL /
(16 * ((BX_SER_THIS s[port].divisor_msb << 8) |
BX_SER_THIS s[port].divisor_lsb)));
}
} else {
if (new_b3 != BX_SER_THIS s[port].int_enable.modstat_enable) {
BX_SER_THIS s[port].int_enable.modstat_enable = new_b3;
if (BX_SER_THIS s[port].int_enable.modstat_enable == 1) {
if (BX_SER_THIS s[port].ms_ipending == 1) {
BX_SER_THIS s[port].ms_interrupt = 1;
BX_SER_THIS s[port].ms_ipending = 0;
gen_int = 1;
}
} else {
if (BX_SER_THIS s[port].ms_interrupt == 1) {
BX_SER_THIS s[port].ms_interrupt = 0;
BX_SER_THIS s[port].ms_ipending = 1;
lower_interrupt(port);
}
}
}
if (new_b1 != BX_SER_THIS s[port].int_enable.txhold_enable) {
BX_SER_THIS s[port].int_enable.txhold_enable = new_b1;
if (BX_SER_THIS s[port].int_enable.txhold_enable == 1) {
BX_SER_THIS s[port].tx_interrupt = BX_SER_THIS s[port].line_status.thr_empty;
if (BX_SER_THIS s[port].tx_interrupt) gen_int = 1;
} else {
BX_SER_THIS s[port].tx_interrupt = 0;
lower_interrupt(port);
}
}
if (new_b0 != BX_SER_THIS s[port].int_enable.rxdata_enable) {
BX_SER_THIS s[port].int_enable.rxdata_enable = new_b0;
if (BX_SER_THIS s[port].int_enable.rxdata_enable == 1) {
if (BX_SER_THIS s[port].fifo_ipending == 1) {
BX_SER_THIS s[port].fifo_interrupt = 1;
BX_SER_THIS s[port].fifo_ipending = 0;
gen_int = 1;
}
if (BX_SER_THIS s[port].rx_ipending == 1) {
BX_SER_THIS s[port].rx_interrupt = 1;
BX_SER_THIS s[port].rx_ipending = 0;
gen_int = 1;
}
} else {
if (BX_SER_THIS s[port].rx_interrupt == 1) {
BX_SER_THIS s[port].rx_interrupt = 0;
BX_SER_THIS s[port].rx_ipending = 1;
lower_interrupt(port);
}
if (BX_SER_THIS s[port].fifo_interrupt == 1) {
BX_SER_THIS s[port].fifo_interrupt = 0;
BX_SER_THIS s[port].fifo_ipending = 1;
lower_interrupt(port);
}
}
}
if (new_b2 != BX_SER_THIS s[port].int_enable.rxlstat_enable) {
BX_SER_THIS s[port].int_enable.rxlstat_enable = new_b2;
if (BX_SER_THIS s[port].int_enable.rxlstat_enable == 1) {
if (BX_SER_THIS s[port].ls_ipending == 1) {
BX_SER_THIS s[port].ls_interrupt = 1;
BX_SER_THIS s[port].ls_ipending = 0;
gen_int = 1;
}
} else {
if (BX_SER_THIS s[port].ls_interrupt == 1) {
BX_SER_THIS s[port].ls_interrupt = 0;
BX_SER_THIS s[port].ls_ipending = 1;
lower_interrupt(port);
}
}
}
if (gen_int) raise_interrupt(port, BX_SER_INT_IER);
}
break;
case BX_SER_FCR: /* FIFO control register */
if (new_b0 && !BX_SER_THIS s[port].fifo_cntl.enable) {
BX_INFO(("com%d: FIFO enabled", port+1));
BX_SER_THIS s[port].rx_fifo_end = 0;
BX_SER_THIS s[port].tx_fifo_end = 0;
}
BX_SER_THIS s[port].fifo_cntl.enable = new_b0;
if (new_b1) {
BX_SER_THIS s[port].rx_fifo_end = 0;
}
if (new_b2) {
BX_SER_THIS s[port].tx_fifo_end = 0;
}
BX_SER_THIS s[port].fifo_cntl.rxtrigger = (value & 0xc0) >> 6;
break;
case BX_SER_LCR: /* Line control register */
new_wordlen = value & 0x03;
if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) {
#if USE_RAW_SERIAL
if (BX_SER_THIS s[port].line_cntl.wordlen_sel != new_wordlen) {
BX_SER_THIS s[port].raw->set_data_bits(new_wordlen + 5);
}
if (new_b2 != BX_SER_THIS s[port].line_cntl.stopbits) {
BX_SER_THIS s[port].raw->set_stop_bits(new_b2 ? 2 : 1);
}
if ((new_b3 != BX_SER_THIS s[port].line_cntl.parity_enable) ||
(new_b4 != BX_SER_THIS s[port].line_cntl.evenparity_sel) ||
(new_b5 != BX_SER_THIS s[port].line_cntl.stick_parity)) {
if (new_b3 == 0) {
p_mode = P_NONE;
} else {
p_mode = ((value & 0x30) >> 4) + 1;
}
BX_SER_THIS s[port].raw->set_parity_mode(p_mode);
}
if ((new_b6 != BX_SER_THIS s[port].line_cntl.break_cntl) &&
(!BX_SER_THIS s[port].modem_cntl.local_loopback)) {
BX_SER_THIS s[port].raw->set_break(new_b6);
}
#endif // USE_RAW_SERIAL
}
BX_SER_THIS s[port].line_cntl.wordlen_sel = new_wordlen;
/* These are ignored, but set them up so they can be read back */
BX_SER_THIS s[port].line_cntl.stopbits = new_b2;
BX_SER_THIS s[port].line_cntl.parity_enable = new_b3;
BX_SER_THIS s[port].line_cntl.evenparity_sel = new_b4;
BX_SER_THIS s[port].line_cntl.stick_parity = new_b5;
BX_SER_THIS s[port].line_cntl.break_cntl = new_b6;
if (BX_SER_THIS s[port].modem_cntl.local_loopback &&
BX_SER_THIS s[port].line_cntl.break_cntl) {
BX_SER_THIS s[port].line_status.break_int = 1;
BX_SER_THIS s[port].line_status.framing_error = 1;
rx_fifo_enq(port, 0x00);
}
/* used when doing future writes */
if (!new_b7 && BX_SER_THIS s[port].line_cntl.dlab) {
// Start the receive polling process if not already started
// and there is a valid baudrate.
if (BX_SER_THIS s[port].rx_pollstate == BX_SER_RXIDLE &&
BX_SER_THIS s[port].baudrate != 0) {
BX_SER_THIS s[port].rx_pollstate = BX_SER_RXPOLL;
bx_pc_system.activate_timer(BX_SER_THIS s[port].rx_timer_index,
(int) (1000000.0 / BX_SER_THIS s[port].baudrate *
(BX_SER_THIS s[port].line_cntl.wordlen_sel + 5)),
0); /* not continuous */
}
if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) {
#if USE_RAW_SERIAL
BX_SER_THIS s[port].raw->set_baudrate(BX_SER_THIS s[port].baudrate);
#endif // USE_RAW_SERIAL
}
BX_DEBUG(("com%d: baud rate set - %d", port+1, BX_SER_THIS s[port].baudrate));
}
BX_SER_THIS s[port].line_cntl.dlab = new_b7;
break;
case BX_SER_MCR: /* MODEM control register */
if ((BX_SER_THIS s[port].io_mode == BX_SER_MODE_MOUSE) &&
((BX_SER_THIS s[port].line_cntl.wordlen_sel == 2) ||
(BX_SER_THIS s[port].line_cntl.wordlen_sel == 3))) {
if (new_b0 && !new_b1) BX_SER_THIS detect_mouse = 1;
if (new_b0 && new_b1 && (BX_SER_THIS detect_mouse == 1)) BX_SER_THIS detect_mouse = 2;
}
if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) {
#if USE_RAW_SERIAL
mcr_changed = (BX_SER_THIS s[port].modem_cntl.dtr != new_b0) |
(BX_SER_THIS s[port].modem_cntl.rts != new_b1);
#endif
}
BX_SER_THIS s[port].modem_cntl.dtr = new_b0;
BX_SER_THIS s[port].modem_cntl.rts = new_b1;
BX_SER_THIS s[port].modem_cntl.out1 = new_b2;
BX_SER_THIS s[port].modem_cntl.out2 = new_b3;
if (new_b4 != BX_SER_THIS s[port].modem_cntl.local_loopback) {
BX_SER_THIS s[port].modem_cntl.local_loopback = new_b4;
if (BX_SER_THIS s[port].modem_cntl.local_loopback) {
/* transition to loopback mode */
if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) {
#if USE_RAW_SERIAL
if (BX_SER_THIS s[port].modem_cntl.dtr ||
BX_SER_THIS s[port].modem_cntl.rts) {
BX_SER_THIS s[port].raw->set_modem_control(0);
}
#endif
}
if (BX_SER_THIS s[port].line_cntl.break_cntl) {
if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) {
#if USE_RAW_SERIAL
BX_SER_THIS s[port].raw->set_break(0);
#endif
}
BX_SER_THIS s[port].line_status.break_int = 1;
BX_SER_THIS s[port].line_status.framing_error = 1;
rx_fifo_enq(port, 0x00);
}
} else {
/* transition to normal mode */
if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) {
#if USE_RAW_SERIAL
mcr_changed = 1;
if (BX_SER_THIS s[port].line_cntl.break_cntl) {
BX_SER_THIS s[port].raw->set_break(0);
}
#endif
}
}
}
if (BX_SER_THIS s[port].modem_cntl.local_loopback) {
prev_cts = BX_SER_THIS s[port].modem_status.cts;
prev_dsr = BX_SER_THIS s[port].modem_status.dsr;
prev_ri = BX_SER_THIS s[port].modem_status.ri;
prev_dcd = BX_SER_THIS s[port].modem_status.dcd;
BX_SER_THIS s[port].modem_status.cts = BX_SER_THIS s[port].modem_cntl.rts;
BX_SER_THIS s[port].modem_status.dsr = BX_SER_THIS s[port].modem_cntl.dtr;
BX_SER_THIS s[port].modem_status.ri = BX_SER_THIS s[port].modem_cntl.out1;
BX_SER_THIS s[port].modem_status.dcd = BX_SER_THIS s[port].modem_cntl.out2;
if (BX_SER_THIS s[port].modem_status.cts != prev_cts) {
BX_SER_THIS s[port].modem_status.delta_cts = 1;
BX_SER_THIS s[port].ms_ipending = 1;
}
if (BX_SER_THIS s[port].modem_status.dsr != prev_dsr) {
BX_SER_THIS s[port].modem_status.delta_dsr = 1;
BX_SER_THIS s[port].ms_ipending = 1;
}
if (BX_SER_THIS s[port].modem_status.ri != prev_ri)
BX_SER_THIS s[port].ms_ipending = 1;
if ((BX_SER_THIS s[port].modem_status.ri == 0) && (prev_ri == 1))
BX_SER_THIS s[port].modem_status.ri_trailedge = 1;
if (BX_SER_THIS s[port].modem_status.dcd != prev_dcd) {
BX_SER_THIS s[port].modem_status.delta_dcd = 1;
BX_SER_THIS s[port].ms_ipending = 1;
}
raise_interrupt(port, BX_SER_INT_MODSTAT);
} else {
if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_MOUSE) {
if (BX_SER_THIS detect_mouse == 2) {
if ((BX_SER_THIS mouse_type == BX_MOUSE_TYPE_SERIAL) ||
(BX_SER_THIS mouse_type == BX_MOUSE_TYPE_SERIAL_MSYS)) {
BX_SER_THIS mouse_internal_buffer.head = 0;
BX_SER_THIS mouse_internal_buffer.num_elements = 1;
BX_SER_THIS mouse_internal_buffer.buffer[0] = 'M';
} else if (BX_SER_THIS mouse_type == BX_MOUSE_TYPE_SERIAL_WHEEL) {
BX_SER_THIS mouse_internal_buffer.head = 0;
BX_SER_THIS mouse_internal_buffer.num_elements = 6;
BX_SER_THIS mouse_internal_buffer.buffer[0] = 'M';
BX_SER_THIS mouse_internal_buffer.buffer[1] = 'Z';
BX_SER_THIS mouse_internal_buffer.buffer[2] = '@';
BX_SER_THIS mouse_internal_buffer.buffer[3] = '\0';
BX_SER_THIS mouse_internal_buffer.buffer[4] = '\0';
BX_SER_THIS mouse_internal_buffer.buffer[5] = '\0';
}
BX_SER_THIS detect_mouse = 0;
}
}
if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) {
#if USE_RAW_SERIAL
if (mcr_changed) {
BX_SER_THIS s[port].raw->set_modem_control(value & 0x03);
}
#endif
} else {
/* simulate device connected */
BX_SER_THIS s[port].modem_status.cts = 1;
BX_SER_THIS s[port].modem_status.dsr = 1;
BX_SER_THIS s[port].modem_status.ri = 0;
BX_SER_THIS s[port].modem_status.dcd = 0;
}
}
break;
case BX_SER_LSR: /* Line status register */
BX_ERROR(("com%d: write to line status register ignored", port+1));
break;
case BX_SER_MSR: /* MODEM status register */
BX_ERROR(("com%d: write to MODEM status register ignored", port+1));
break;
case BX_SER_SCR: /* scratch register */
BX_SER_THIS s[port].scratch = value;
break;
default:
BX_PANIC(("unsupported io write to address=0x%04x, value = 0x%02x!",
(unsigned) address, (unsigned) value));
break;
}
}
void
bx_serial_c::rx_fifo_enq(Bit8u port, Bit8u data)
{
bx_bool gen_int = 0;
if (BX_SER_THIS s[port].fifo_cntl.enable) {
if (BX_SER_THIS s[port].rx_fifo_end == 16) {
BX_ERROR(("com%d: receive FIFO overflow", port+1));
BX_SER_THIS s[port].line_status.overrun_error = 1;
raise_interrupt(port, BX_SER_INT_RXLSTAT);
} else {
BX_SER_THIS s[port].rx_fifo[BX_SER_THIS s[port].rx_fifo_end++] = data;
switch (BX_SER_THIS s[port].fifo_cntl.rxtrigger) {
case 1:
if (BX_SER_THIS s[port].rx_fifo_end == 4) gen_int = 1;
break;
case 2:
if (BX_SER_THIS s[port].rx_fifo_end == 8) gen_int = 1;
break;
case 3:
if (BX_SER_THIS s[port].rx_fifo_end == 14) gen_int = 1;
break;
default:
gen_int = 1;
}
if (gen_int) {
bx_pc_system.deactivate_timer(BX_SER_THIS s[port].fifo_timer_index);
BX_SER_THIS s[port].line_status.rxdata_ready = 1;
raise_interrupt(port, BX_SER_INT_RXDATA);
} else {
bx_pc_system.activate_timer(BX_SER_THIS s[port].fifo_timer_index,
(int) (1000000.0 / BX_SER_THIS s[port].baudrate *
(BX_SER_THIS s[port].line_cntl.wordlen_sel + 5) * 16),
0); /* not continuous */
}
}
} else {
if (BX_SER_THIS s[port].line_status.rxdata_ready == 1) {
BX_ERROR(("com%d: overrun error", port+1));
BX_SER_THIS s[port].line_status.overrun_error = 1;
raise_interrupt(port, BX_SER_INT_RXLSTAT);
}
BX_SER_THIS s[port].rxbuffer = data;
BX_SER_THIS s[port].line_status.rxdata_ready = 1;
raise_interrupt(port, BX_SER_INT_RXDATA);
}
}
void
bx_serial_c::tx_timer_handler(void *this_ptr)
{
bx_serial_c *class_ptr = (bx_serial_c *) this_ptr;
class_ptr->tx_timer();
}
void
bx_serial_c::tx_timer(void)
{
bx_bool gen_int = 0;
Bit8u port = 0;
int timer_id;
timer_id = bx_pc_system.triggeredTimerID();
if (timer_id == BX_SER_THIS s[0].tx_timer_index) {
port = 0;
} else if (timer_id == BX_SER_THIS s[1].tx_timer_index) {
port = 1;
} else if (timer_id == BX_SER_THIS s[2].tx_timer_index) {
port = 2;
} else if (timer_id == BX_SER_THIS s[3].tx_timer_index) {
port = 3;
}
if (BX_SER_THIS s[port].modem_cntl.local_loopback) {
rx_fifo_enq(port, BX_SER_THIS s[port].tsrbuffer);
} else {
switch (BX_SER_THIS s[port].io_mode) {
case BX_SER_MODE_FILE:
fputc(BX_SER_THIS s[port].tsrbuffer, BX_SER_THIS s[port].output);
fflush(BX_SER_THIS s[port].output);
break;
case BX_SER_MODE_TERM:
#if defined(SERIAL_ENABLE)
BX_DEBUG(("com%d: write: '%c'", port+1, BX_SER_THIS s[port].tsrbuffer));
if (BX_SER_THIS s[port].tty_id >= 0) {
write(BX_SER_THIS s[port].tty_id, (bx_ptr_t) & BX_SER_THIS s[port].tsrbuffer, 1);
}
#endif
break;
case BX_SER_MODE_RAW:
#if USE_RAW_SERIAL
if (!BX_SER_THIS s[port].raw->ready_transmit())
BX_PANIC(("com%d: not ready to transmit", port+1));
BX_SER_THIS s[port].raw->transmit(BX_SER_THIS s[port].tsrbuffer);
#endif
break;
case BX_SER_MODE_MOUSE:
BX_INFO(("com%d: write to mouse ignored: 0x%02x", port+1, BX_SER_THIS s[port].tsrbuffer));
break;
case BX_SER_MODE_SOCKET:
if (BX_SER_THIS s[port].socket_id >= 0) {
#ifdef WIN32
BX_INFO(("attempting to write win32 : %c", BX_SER_THIS s[port].tsrbuffer));
::send(BX_SER_THIS s[port].socket_id,
(const char*) & BX_SER_THIS s[port].tsrbuffer, 1, 0);
#else
::write(BX_SER_THIS s[port].socket_id,
(bx_ptr_t) & BX_SER_THIS s[port].tsrbuffer, 1);
#endif
}
case BX_SER_MODE_PIPE:
#ifdef WIN32
if (BX_SER_THIS s[port].pipe) {
DWORD written;
WriteFile(BX_SER_THIS s[port].pipe, (bx_ptr_t)& BX_SER_THIS s[port].tsrbuffer, 1, &written, NULL);
}
#endif
break;
}
}
BX_SER_THIS s[port].line_status.tsr_empty = 1;
if (BX_SER_THIS s[port].fifo_cntl.enable && (BX_SER_THIS s[port].tx_fifo_end > 0)) {
BX_SER_THIS s[port].tsrbuffer = BX_SER_THIS s[port].tx_fifo[0];
BX_SER_THIS s[port].line_status.tsr_empty = 0;
memcpy(&BX_SER_THIS s[port].tx_fifo[0], &BX_SER_THIS s[port].tx_fifo[1], 15);
gen_int = (--BX_SER_THIS s[port].tx_fifo_end == 0);
} else if (!BX_SER_THIS s[port].line_status.thr_empty) {
BX_SER_THIS s[port].tsrbuffer = BX_SER_THIS s[port].thrbuffer;
BX_SER_THIS s[port].line_status.tsr_empty = 0;
gen_int = 1;
}
if (!BX_SER_THIS s[port].line_status.tsr_empty) {
if (gen_int) {
BX_SER_THIS s[port].line_status.thr_empty = 1;
raise_interrupt(port, BX_SER_INT_TXHOLD);
}
bx_pc_system.activate_timer(BX_SER_THIS s[port].tx_timer_index,
(int) (1000000.0 / BX_SER_THIS s[port].baudrate *
(BX_SER_THIS s[port].line_cntl.wordlen_sel + 5)),
0); /* not continuous */
}
}
void
bx_serial_c::rx_timer_handler(void *this_ptr)
{
bx_serial_c *class_ptr = (bx_serial_c *) this_ptr;
class_ptr->rx_timer();
}
void
bx_serial_c::rx_timer(void)
{
#if BX_HAVE_SELECT && defined(SERIAL_ENABLE)
struct timeval tval;
fd_set fds;
#endif
Bit8u port = 0;
int timer_id;
bx_bool data_ready = 0;
timer_id = bx_pc_system.triggeredTimerID();
if (timer_id == BX_SER_THIS s[0].rx_timer_index) {
port = 0;
} else if (timer_id == BX_SER_THIS s[1].rx_timer_index) {
port = 1;
} else if (timer_id == BX_SER_THIS s[2].rx_timer_index) {
port = 2;
} else if (timer_id == BX_SER_THIS s[3].rx_timer_index) {
port = 3;
}
int bdrate = BX_SER_THIS s[port].baudrate / (BX_SER_THIS s[port].line_cntl.wordlen_sel + 5);
unsigned char chbuf = 0;
if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_TERM) {
#if BX_HAVE_SELECT && defined(SERIAL_ENABLE)
tval.tv_sec = 0;
tval.tv_usec = 0;
// MacOS: I'm not sure what to do with this, since I don't know
// what an fd_set is or what FD_SET() or select() do. They aren't
// declared in the CodeWarrior standard library headers. I'm just
// leaving it commented out for the moment.
FD_ZERO(&fds);
if (BX_SER_THIS s[port].tty_id >= 0) FD_SET(BX_SER_THIS s[port].tty_id, &fds);
#endif
}
if ((BX_SER_THIS s[port].line_status.rxdata_ready == 0) ||
(BX_SER_THIS s[port].fifo_cntl.enable)) {
switch (BX_SER_THIS s[port].io_mode) {
case BX_SER_MODE_SOCKET:
2008-08-22 11:58:20 +04:00
#if BX_HAVE_SELECT && defined(SERIAL_ENABLE)
if (BX_SER_THIS s[port].line_status.rxdata_ready == 0) {
tval.tv_sec = 0;
tval.tv_usec = 0;
FD_ZERO(&fds);
2010-11-23 17:59:36 +03:00
SOCKET socketid = BX_SER_THIS s[port].socket_id;
if (socketid >= 0) FD_SET(socketid, &fds);
if ((socketid >= 0) && (select(socketid+1, &fds, NULL, NULL, &tval) == 1)) {
#ifdef WIN32
(void) ::recv(socketid, (char*) &chbuf, 1, 0);
#else
(void) read(socketid, &chbuf, 1);
#endif
BX_INFO((" -- COM %d : read byte [%d]", port+1, chbuf));
data_ready = 1;
}
}
#endif
break;
case BX_SER_MODE_RAW:
#if USE_RAW_SERIAL
int data;
if ((data_ready = BX_SER_THIS s[port].raw->ready_receive())) {
data = BX_SER_THIS s[port].raw->receive();
if (data < 0) {
data_ready = 0;
switch (data) {
case RAW_EVENT_BREAK:
BX_SER_THIS s[port].line_status.break_int = 1;
raise_interrupt(port, BX_SER_INT_RXLSTAT);
break;
case RAW_EVENT_FRAME:
BX_SER_THIS s[port].line_status.framing_error = 1;
raise_interrupt(port, BX_SER_INT_RXLSTAT);
break;
case RAW_EVENT_OVERRUN:
BX_SER_THIS s[port].line_status.overrun_error = 1;
raise_interrupt(port, BX_SER_INT_RXLSTAT);
break;
case RAW_EVENT_PARITY:
BX_SER_THIS s[port].line_status.parity_error = 1;
raise_interrupt(port, BX_SER_INT_RXLSTAT);
break;
case RAW_EVENT_CTS_ON:
case RAW_EVENT_CTS_OFF:
case RAW_EVENT_DSR_ON:
case RAW_EVENT_DSR_OFF:
case RAW_EVENT_RING_ON:
case RAW_EVENT_RING_OFF:
case RAW_EVENT_RLSD_ON:
case RAW_EVENT_RLSD_OFF:
raise_interrupt(port, BX_SER_INT_MODSTAT);
break;
}
}
}
if (data_ready) {
chbuf = data;
}
#endif
break;
case BX_SER_MODE_TERM:
#if BX_HAVE_SELECT && defined(SERIAL_ENABLE)
if ((BX_SER_THIS s[port].tty_id >= 0) && (select(BX_SER_THIS s[port].tty_id + 1, &fds, NULL, NULL, &tval) == 1)) {
(void) read(BX_SER_THIS s[port].tty_id, &chbuf, 1);
BX_DEBUG(("com%d: read: '%c'", port+1, chbuf));
data_ready = 1;
}
#endif
break;
case BX_SER_MODE_MOUSE:
if (BX_SER_THIS mouse_internal_buffer.num_elements > 0) {
chbuf = BX_SER_THIS mouse_internal_buffer.buffer[BX_SER_THIS mouse_internal_buffer.head];
BX_SER_THIS mouse_internal_buffer.head = (BX_SER_THIS mouse_internal_buffer.head + 1) %
BX_MOUSE_BUFF_SIZE;
BX_SER_THIS mouse_internal_buffer.num_elements--;
data_ready = 1;
}
break;
case BX_SER_MODE_PIPE:
#ifdef WIN32
DWORD avail = 0;
if (BX_SER_THIS s[port].pipe &&
PeekNamedPipe(BX_SER_THIS s[port].pipe, NULL, 0, NULL, &avail, NULL) &&
avail > 0) {
ReadFile(BX_SER_THIS s[port].pipe, &chbuf, 1, &avail, NULL);
data_ready = 1;
}
#endif
break;
}
if (data_ready) {
if (!BX_SER_THIS s[port].modem_cntl.local_loopback) {
rx_fifo_enq(port, chbuf);
}
} else {
if (!BX_SER_THIS s[port].fifo_cntl.enable) {
bdrate = (int) (1000000.0 / 100000); // Poll frequency is 100ms
}
}
} else {
// Poll at 4x baud rate to see if the next-char can
// be read
bdrate *= 4;
}
bx_pc_system.activate_timer(BX_SER_THIS s[port].rx_timer_index,
(int) (1000000.0 / bdrate),
0); /* not continuous */
}
void
bx_serial_c::fifo_timer_handler(void *this_ptr)
{
bx_serial_c *class_ptr = (bx_serial_c *) this_ptr;
class_ptr->fifo_timer();
}
void
bx_serial_c::fifo_timer(void)
{
Bit8u port = 0;
int timer_id;
timer_id = bx_pc_system.triggeredTimerID();
if (timer_id == BX_SER_THIS s[0].fifo_timer_index) {
port = 0;
} else if (timer_id == BX_SER_THIS s[1].fifo_timer_index) {
port = 1;
} else if (timer_id == BX_SER_THIS s[2].fifo_timer_index) {
port = 2;
} else if (timer_id == BX_SER_THIS s[3].fifo_timer_index) {
port = 3;
}
BX_SER_THIS s[port].line_status.rxdata_ready = 1;
raise_interrupt(port, BX_SER_INT_FIFO);
}
void bx_serial_c::mouse_enq_static(void *dev, int delta_x, int delta_y, int delta_z, unsigned button_state)
{
((bx_serial_c*)dev)->mouse_enq(delta_x, delta_y, delta_z, button_state);
}
void bx_serial_c::mouse_enq(int delta_x, int delta_y, int delta_z, unsigned button_state)
{
2008-06-18 20:33:44 +04:00
Bit8u b1, b2, b3, mouse_data[5];
int bytes, tail;
if (BX_SER_THIS mouse_port == -1) {
BX_ERROR(("mouse not connected to a serial port"));
return;
}
// if the DTR and RTS lines aren't up, the mouse doesn't have any power to send packets.
if (!BX_SER_THIS s[BX_SER_THIS mouse_port].modem_cntl.dtr || !BX_SER_THIS s[BX_SER_THIS mouse_port].modem_cntl.rts)
return;
// scale down the motion
if ((delta_x < -1) || (delta_x > 1))
delta_x /= 2;
if ((delta_y < -1) || (delta_y > 1))
delta_y /= 2;
if(delta_x>127) delta_x=127;
if(delta_y>127) delta_y=127;
if(delta_x<-128) delta_x=-128;
if(delta_y<-128) delta_y=-128;
BX_SER_THIS mouse_delayed_dx+=delta_x;
BX_SER_THIS mouse_delayed_dy-=delta_y;
BX_SER_THIS mouse_delayed_dz =delta_z;
if ((BX_SER_THIS mouse_internal_buffer.num_elements + 4) >= BX_MOUSE_BUFF_SIZE) {
return; /* buffer doesn't have the space */
}
if (BX_SER_THIS mouse_delayed_dx > 127) {
delta_x = 127;
BX_SER_THIS mouse_delayed_dx -= 127;
} else if (BX_SER_THIS mouse_delayed_dx < -128) {
delta_x = -128;
BX_SER_THIS mouse_delayed_dx += 128;
} else {
delta_x = BX_SER_THIS mouse_delayed_dx;
BX_SER_THIS mouse_delayed_dx = 0;
}
if (BX_SER_THIS mouse_delayed_dy > 127) {
delta_y = 127;
BX_SER_THIS mouse_delayed_dy -= 127;
} else if (BX_SER_THIS mouse_delayed_dy < -128) {
delta_y = -128;
BX_SER_THIS mouse_delayed_dy += 128;
} else {
delta_y = BX_SER_THIS mouse_delayed_dy;
BX_SER_THIS mouse_delayed_dy = 0;
}
if (BX_SER_THIS mouse_type != BX_MOUSE_TYPE_SERIAL_MSYS) {
b1 = (Bit8u) delta_x;
b2 = (Bit8u) delta_y;
b3 = (Bit8u) -((Bit8s) delta_z);
mouse_data[0] = 0x40 | ((b1 & 0xc0) >> 6) | ((b2 & 0xc0) >> 4);
mouse_data[0] |= ((button_state & 0x01) << 5) | ((button_state & 0x02) << 3);
mouse_data[1] = b1 & 0x3f;
mouse_data[2] = b2 & 0x3f;
mouse_data[3] = b3 & 0x0f;
mouse_data[3] |= ((button_state & 0x04) << 2);
bytes = 3;
if (BX_SER_THIS mouse_type == BX_MOUSE_TYPE_SERIAL_WHEEL) bytes = 4;
} else {
b1 = (Bit8u) (delta_x / 2);
b2 = (Bit8u) -((Bit8s) (delta_y / 2));
mouse_data[0] = 0x80 | ((~button_state & 0x01) << 2);
mouse_data[0] |= ((~button_state & 0x06) >> 1);
mouse_data[1] = b1;
mouse_data[2] = b2;
mouse_data[3] = 0;
mouse_data[4] = 0;
bytes = 5;
}
/* enqueue mouse data in multibyte internal mouse buffer */
for (int i = 0; i < bytes; i++) {
tail = (BX_SER_THIS mouse_internal_buffer.head + BX_SER_THIS mouse_internal_buffer.num_elements) %
BX_MOUSE_BUFF_SIZE;
BX_SER_THIS mouse_internal_buffer.buffer[tail] = mouse_data[i];
BX_SER_THIS mouse_internal_buffer.num_elements++;
}
}