Import of all sources.
This commit is contained in:
374
src/bugger.c
Normal file
374
src/bugger.c
Normal file
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* VARCem Virtual Archaelogical Computer EMulator.
|
||||
* An emulator of (mostly) x86-based PC systems and devices,
|
||||
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
|
||||
* spanning the era between 1981 and 1995.
|
||||
*
|
||||
* This file is part of the VARCem Project.
|
||||
*
|
||||
* Implementation of the ISA Bus (de)Bugger expansion card
|
||||
* sold as a DIY kit in the late 1980's in The Netherlands.
|
||||
* This card was a assemble-yourself 8bit ISA addon card for
|
||||
* PC and AT systems that had several tools to aid in low-
|
||||
* level debugging (mostly for faulty BIOSes, bootloaders
|
||||
* and system kernels...)
|
||||
*
|
||||
* The standard version had a total of 16 LEDs (8 RED, plus
|
||||
* 8 GREEN), two 7-segment displays and one 8-position DIP
|
||||
* switch block on board for use as debugging tools.
|
||||
*
|
||||
* The "Plus" version, added an extra 2 7-segment displays,
|
||||
* as well as a very simple RS-232 serial interface that
|
||||
* could be used as a mini-console terminal.
|
||||
*
|
||||
* Two I/O ports were used; one for control, at offset 0 in
|
||||
* I/O space, and one for data, at offset 1 in I/O space.
|
||||
* Both registers could be read from and written to. Although
|
||||
* the author has a vague memory of a DIP switch to set the
|
||||
* board's I/O address, comments in old software seems to
|
||||
* indicate that it was actually fixed to 0x7A (and 0x7B.)
|
||||
*
|
||||
* A READ on the data register always returned the actual
|
||||
* state of the DIP switch. Writing data to the LEDs was done
|
||||
* in two steps.. first, the block number (RED or GREEN) was
|
||||
* written to the CTRL register, and then the actual LED data
|
||||
* was written to the DATA register. Likewise, data for the
|
||||
* 7-segment displays was written.
|
||||
*
|
||||
* The serial port was a bit different, and its operation is
|
||||
* not verified, but two extra bits in the control register
|
||||
* were used to set up parameters, and also the actual data
|
||||
* input and output.
|
||||
*
|
||||
* TODO: Still have to implement the RS232 Serial Port Parameters
|
||||
* configuration register (CTRL_SPCFG bit set) but have to
|
||||
* remember that stuff first...
|
||||
*
|
||||
* Version: @(#)bugger.c 1.0.1 2018/02/14
|
||||
*
|
||||
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with
|
||||
* or without modification, are permitted provided that the
|
||||
* following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the entire
|
||||
* above notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names
|
||||
* of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "emu.h"
|
||||
#include "io.h"
|
||||
#include "device.h"
|
||||
#include "plat.h"
|
||||
#include "ui.h"
|
||||
#include "bugger.h"
|
||||
|
||||
|
||||
/* BugBugger registers. */
|
||||
#define BUG_CTRL 0
|
||||
# define CTRL_RLED 0x00 /* write to the RED LED block */
|
||||
# define CTRL_GLED 0x01 /* write to the GREEN LED block */
|
||||
# define CTRL_SEG1 0x02 /* write to the RIGHT 7SEG displays */
|
||||
# define CTRL_SEG2 0x04 /* write to the LEFT 7SEG displays */
|
||||
# define CTRL_SPORT 0x20 /* enable the serial port */
|
||||
# define CTRL_SPCFG 0x40 /* set up the serial port */
|
||||
# define CTRL_INIT 0x80 /* enable and reset the card */
|
||||
# define CTRL_RESET 0xff /* this resets the board */
|
||||
#define BUG_DATA 1
|
||||
|
||||
|
||||
static uint8_t bug_ctrl, /* control register */
|
||||
bug_data, /* data register */
|
||||
bug_ledr, bug_ledg, /* RED and GREEN LEDs */
|
||||
bug_seg1, bug_seg2, /* LEFT and RIGHT 7SEG displays */
|
||||
bug_spcfg; /* serial port configuration */
|
||||
# define FIFO_LEN 256
|
||||
static uint8_t bug_buff[FIFO_LEN], /* serial port data buffer */
|
||||
*bug_bptr;
|
||||
# define UISTR_LEN 24
|
||||
static char bug_str[UISTR_LEN]; /* UI output string */
|
||||
|
||||
|
||||
extern void ui_sb_bugui(char *__str);
|
||||
|
||||
|
||||
/* Update the system's UI with the actual Bugger status. */
|
||||
static void
|
||||
bug_setui(void)
|
||||
{
|
||||
/* Format all current info in a string. */
|
||||
sprintf(bug_str, "%02X:%02X %c%c%c%c%c%c%c%c-%c%c%c%c%c%c%c%c",
|
||||
bug_seg2, bug_seg1,
|
||||
(bug_ledg&0x80)?'G':'g', (bug_ledg&0x40)?'G':'g',
|
||||
(bug_ledg&0x20)?'G':'g', (bug_ledg&0x10)?'G':'g',
|
||||
(bug_ledg&0x08)?'G':'g', (bug_ledg&0x04)?'G':'g',
|
||||
(bug_ledg&0x02)?'G':'g', (bug_ledg&0x01)?'G':'g',
|
||||
(bug_ledr&0x80)?'R':'r', (bug_ledr&0x40)?'R':'r',
|
||||
(bug_ledr&0x20)?'R':'r', (bug_ledr&0x10)?'R':'r',
|
||||
(bug_ledr&0x08)?'R':'r', (bug_ledr&0x04)?'R':'r',
|
||||
(bug_ledr&0x02)?'R':'r', (bug_ledr&0x01)?'R':'r');
|
||||
|
||||
/* Send formatted string to the UI. */
|
||||
ui_sb_bugui(bug_str);
|
||||
}
|
||||
|
||||
|
||||
/* Flush the serial port. */
|
||||
static void
|
||||
bug_spflsh(void)
|
||||
{
|
||||
*bug_bptr = '\0';
|
||||
pclog("BUGGER- serial port [%s]\n", bug_buff);
|
||||
bug_bptr = bug_buff;
|
||||
}
|
||||
|
||||
|
||||
/* Handle a write to the Serial Port Data register. */
|
||||
static void
|
||||
bug_wsport(uint8_t val)
|
||||
{
|
||||
uint8_t old = bug_ctrl;
|
||||
|
||||
/* Clear the SPORT bit to indicate we are busy. */
|
||||
bug_ctrl &= ~CTRL_SPORT;
|
||||
|
||||
/* Delay while processing byte.. */
|
||||
if (bug_bptr == &bug_buff[FIFO_LEN-1]) {
|
||||
/* Buffer full, gotta flush. */
|
||||
bug_spflsh();
|
||||
}
|
||||
|
||||
/* Write (store) the byte. */
|
||||
*bug_bptr++ = val;
|
||||
|
||||
/* Restore the SPORT bit. */
|
||||
bug_ctrl |= (old & CTRL_SPORT);
|
||||
|
||||
pclog("BUGGER- sport %02x\n", val);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a write to the Serial Port Configuration register. */
|
||||
static void
|
||||
bug_wspcfg(uint8_t val)
|
||||
{
|
||||
bug_spcfg = val;
|
||||
|
||||
pclog("BUGGER- spcfg %02x\n", bug_spcfg);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a write to the control register. */
|
||||
static void
|
||||
bug_wctrl(uint8_t val)
|
||||
{
|
||||
if (val == CTRL_RESET) {
|
||||
/* User wants us to reset. */
|
||||
bug_ctrl = CTRL_INIT;
|
||||
bug_spcfg = 0x00;
|
||||
bug_bptr = NULL;
|
||||
} else {
|
||||
/* If turning off the serial port, flush it. */
|
||||
if ((bug_ctrl & CTRL_SPORT) && !(val & CTRL_SPORT))
|
||||
bug_spflsh();
|
||||
|
||||
/* FIXME: did they do this using an XOR of operation bits? --FvK */
|
||||
|
||||
if (val & CTRL_SPCFG) {
|
||||
/* User wants to configure the serial port. */
|
||||
bug_ctrl &= ~(CTRL_SPORT|CTRL_SEG2|CTRL_SEG1|CTRL_GLED);
|
||||
bug_ctrl |= CTRL_SPCFG;
|
||||
} else if (val & CTRL_SPORT) {
|
||||
/* User wants to talk to the serial port. */
|
||||
bug_ctrl &= ~(CTRL_SPCFG|CTRL_SEG2|CTRL_SEG1|CTRL_GLED);
|
||||
bug_ctrl |= CTRL_SPORT;
|
||||
if (bug_bptr == NULL)
|
||||
bug_bptr = bug_buff;
|
||||
} else if (val & CTRL_SEG2) {
|
||||
/* User selected SEG2 (LEFT, Plus only) for output. */
|
||||
bug_ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG1|CTRL_GLED);
|
||||
bug_ctrl |= CTRL_SEG2;
|
||||
} else if (val & CTRL_SEG1) {
|
||||
/* User selected SEG1 (RIGHT) for output. */
|
||||
bug_ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG2|CTRL_GLED);
|
||||
bug_ctrl |= CTRL_SEG1;
|
||||
} else if (val & CTRL_GLED) {
|
||||
/* User selected the GREEN LEDs for output. */
|
||||
bug_ctrl &= ~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG2|CTRL_SEG1);
|
||||
bug_ctrl |= CTRL_GLED;
|
||||
} else {
|
||||
/* User selected the RED LEDs for output. */
|
||||
bug_ctrl &=
|
||||
~(CTRL_SPCFG|CTRL_SPORT|CTRL_SEG2|CTRL_SEG1|CTRL_GLED);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the UI with active settings. */
|
||||
pclog("BUGGER- ctrl %02x\n", bug_ctrl);
|
||||
bug_setui();
|
||||
}
|
||||
|
||||
|
||||
/* Handle a write to the data register. */
|
||||
static void
|
||||
bug_wdata(uint8_t val)
|
||||
{
|
||||
bug_data = val;
|
||||
|
||||
if (bug_ctrl & CTRL_SPCFG)
|
||||
bug_wspcfg(val);
|
||||
else if (bug_ctrl & CTRL_SPORT)
|
||||
bug_wsport(val);
|
||||
else {
|
||||
if (bug_ctrl & CTRL_SEG2)
|
||||
bug_seg2 = val;
|
||||
else if (bug_ctrl & CTRL_SEG1)
|
||||
bug_seg1 = val;
|
||||
else if (bug_ctrl & CTRL_GLED)
|
||||
bug_ledg = val;
|
||||
else
|
||||
bug_ledr = val;
|
||||
|
||||
pclog("BUGGER- data %02x\n", bug_data);
|
||||
}
|
||||
|
||||
/* Update the UI with active settings. */
|
||||
bug_setui();
|
||||
}
|
||||
|
||||
|
||||
/* Reset the ISA BusBugger controller. */
|
||||
static void
|
||||
bug_reset(void)
|
||||
{
|
||||
/* Clear the data register. */
|
||||
bug_data = 0x00;
|
||||
|
||||
/* Clear the RED and GREEN LEDs. */
|
||||
bug_ledr = 0x00; bug_ledg = 0x00;
|
||||
|
||||
/* Clear both 7SEG displays. */
|
||||
bug_seg1 = 0x00; bug_seg2 = 0x00;
|
||||
|
||||
/* Reset the control register (updates UI.) */
|
||||
bug_wctrl(CTRL_RESET);
|
||||
}
|
||||
|
||||
|
||||
/* Handle a WRITE operation to one of our registers. */
|
||||
static void
|
||||
bug_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
switch (port-BUGGER_ADDR) {
|
||||
case BUG_CTRL: /* control register */
|
||||
if (val == CTRL_RESET) {
|
||||
/* Perform a full reset. */
|
||||
bug_reset();
|
||||
} else if (bug_ctrl & CTRL_INIT) {
|
||||
/* Only allow writes if initialized. */
|
||||
bug_wctrl(val);
|
||||
}
|
||||
break;
|
||||
|
||||
case BUG_DATA: /* data register */
|
||||
if (bug_ctrl & CTRL_INIT) {
|
||||
bug_wdata(val);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle a READ operation from one of our registers. */
|
||||
static uint8_t
|
||||
bug_read(uint16_t port, void *priv)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if (bug_ctrl & CTRL_INIT) switch (port-BUGGER_ADDR) {
|
||||
case BUG_CTRL: /* control register */
|
||||
ret = bug_ctrl;
|
||||
break;
|
||||
|
||||
case BUG_DATA: /* data register */
|
||||
if (bug_ctrl & CTRL_SPCFG) {
|
||||
ret = bug_spcfg;
|
||||
} else if (bug_ctrl & CTRL_SPORT) {
|
||||
ret = 0x00; /* input not supported */
|
||||
} else {
|
||||
/* Just read the DIP switch. */
|
||||
ret = bug_data;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the ISA BusBugger emulator. */
|
||||
static void *
|
||||
bug_init(device_t *info)
|
||||
{
|
||||
pclog("%s, I/O=%04x\n", info->name, BUGGER_ADDR);
|
||||
|
||||
/* Initialize local registers. */
|
||||
bug_reset();
|
||||
|
||||
io_sethandler(BUGGER_ADDR, BUGGER_ADDRLEN,
|
||||
bug_read, NULL, NULL, bug_write, NULL, NULL, NULL);
|
||||
|
||||
/* Just so its not NULL. */
|
||||
return(info);
|
||||
}
|
||||
|
||||
|
||||
/* Remove the ISA BusBugger emulator from the system. */
|
||||
static void
|
||||
bug_close(UNUSED(void *priv))
|
||||
{
|
||||
io_removehandler(BUGGER_ADDR, BUGGER_ADDRLEN,
|
||||
bug_read, NULL, NULL, bug_write, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
device_t bugger_device = {
|
||||
"ISA/PCI Bus Bugger",
|
||||
DEVICE_ISA | DEVICE_AT,
|
||||
0,
|
||||
bug_init, bug_close, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
Reference in New Issue
Block a user