- support for serial port modes added. The mode defines what to do with the

data written to the port and where to get the data read from it. Available
  modes are 'null' (no input/output), 'file' (output to a file specified as
  the 'dev' parameter), 'term' (serial terminal) and 'raw' (use the real serial
  port - under construction for win32).
- descriptions for serial and parallel options in bochsrc sample updated
This commit is contained in:
Volker Ruppert 2004-07-28 19:36:42 +00:00
parent 158ba92f2e
commit f1a0f56d55
5 changed files with 295 additions and 160 deletions

View File

@ -370,21 +370,29 @@ debug: action=ignore
debugger_log: -
#=======================================================================
# COM1:
# This defines a serial port (UART type 16550A). You can specify a device
# to use as com1. This can be a real serial line, or a pty. To use a pty
# (under X/Unix), create two windows (xterms, usually). One of them will
# COM1, COM2, COM3, COM4:
# This defines a serial port (UART type 16550A). In the 'term' you can specify
# a device to use as com1. This can be a real serial line, or a pty. To use
# a pty (under X/Unix), create two windows (xterms, usually). One of them will
# run bochs, and the other will act as com1. Find out the tty the com1
# window using the `tty' command, and use that as the `dev' parameter.
# Then do `sleep 1000000' in the com1 window to keep the shell from
# messing with things, and run bochs in the other window. Serial I/O to
# com1 (port 0x3f8) will all go to the other window.
# Other serial modes are 'null' (no input/output), 'file' (output to a file
# specified as the 'dev' parameter) and 'raw' (use the real serial port - under
# construction for win32).
#
# Examples:
# com1: enabled=1, mode=null
# com2: enabled=1, mode=file, dev=serial.out
# com3: enabled=1, mode=raw, dev=com1
#=======================================================================
#com1: enabled=1, dev=/dev/ttyp9
#com1: enabled=1, mode=term, dev=/dev/ttyp9
#=======================================================================
# PARPORT1:
# PARPORT1, PARPORT2:
# This defines a parallel (printer) port. When turned on and an output file is
# defined the emulated printer port sends characters printed by the guest OS
# into the output file. On some platforms a device filename can be used to
@ -393,7 +401,7 @@ debugger_log: -
#
# Examples:
# parport1: enabled=1, file="parport.out"
# parport1: enabled=1, file="/dev/lp0"
# parport2: enabled=1, file="/dev/lp0"
# parport1: enabled=0
#=======================================================================
parport1: enabled=1, file="parport.out"

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: config.cc,v 1.7 2004-07-18 17:18:19 vruppert Exp $
// $Id: config.cc,v 1.8 2004-07-28 19:36:42 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2002 MandrakeSoft S.A.
@ -843,6 +843,14 @@ void bx_init_options ()
*par_ser_ptr++ = bx_options.par[i].Ooutfile;
}
static char *serial_mode_list[] = {
"null",
"file",
"term",
"raw",
NULL
};
// serial ports
for (i=0; i<BX_N_SERIAL_PORTS; i++) {
// options for COM port
@ -853,6 +861,15 @@ void bx_init_options ()
strdup(name),
strdup(descr),
(i==0)?1 : 0); // only enable the first by default
sprintf (name, "I/O mode of the serial device for COM%d", i+1);
sprintf (descr, "The mode can be one these: 'null', 'file', 'term', 'raw'");
bx_options.com[i].Omode = new bx_param_enum_c (
BXP_COMx_MODE(i+1),
strdup(name),
strdup(descr),
serial_mode_list,
0,
0);
sprintf (name, "Pathname of the serial device for COM%d", i+1);
sprintf (descr, "The path can be a real serial device or a pty (X/Unix only)");
bx_options.com[i].Odev = new bx_param_filename_c (
@ -860,11 +877,13 @@ void bx_init_options ()
strdup(name),
strdup(descr),
"", BX_PATHNAME_LEN);
deplist = new bx_list_c (BXP_NULL, 1);
deplist = new bx_list_c (BXP_NULL, 2);
deplist->add (bx_options.com[i].Omode);
deplist->add (bx_options.com[i].Odev);
bx_options.com[i].Oenabled->set_dependent_list (deplist);
// add to menu
*par_ser_ptr++ = bx_options.com[i].Oenabled;
*par_ser_ptr++ = bx_options.com[i].Omode;
*par_ser_ptr++ = bx_options.com[i].Odev;
}
@ -1688,6 +1707,7 @@ void bx_reset_options ()
// standard ports
for (i=0; i<BX_N_SERIAL_PORTS; i++) {
bx_options.com[i].Oenabled->reset();
bx_options.com[i].Omode->reset();
bx_options.com[i].Odev->reset();
}
for (i=0; i<BX_N_PARALLEL_PORTS; i++) {
@ -2480,6 +2500,11 @@ parse_line_formatted(char *context, int num_params, char *params[])
if (!strncmp(params[i], "enabled=", 8)) {
bx_options.com[0].Oenabled->set (atol(&params[i][8]));
}
else if (!strncmp(params[i], "mode=", 5)) {
if (!bx_options.com[0].Omode->set_by_name (strdup(&params[i][5])))
PARSE_ERR(("%s: serial port mode '%s' not available", context, strdup(&params[i][5])));
bx_options.com[0].Oenabled->set (1);
}
else if (!strncmp(params[i], "dev=", 4)) {
bx_options.com[0].Odev->set (&params[i][4]);
bx_options.com[0].Oenabled->set (1);
@ -2494,6 +2519,11 @@ parse_line_formatted(char *context, int num_params, char *params[])
if (!strncmp(params[i], "enabled=", 8)) {
bx_options.com[1].Oenabled->set (atol(&params[i][8]));
}
else if (!strncmp(params[i], "mode=", 5)) {
if (!bx_options.com[1].Omode->set_by_name (strdup(&params[i][5])))
PARSE_ERR(("%s: serial port mode '%s' not available", context, strdup(&params[i][5])));
bx_options.com[1].Oenabled->set (1);
}
else if (!strncmp(params[i], "dev=", 4)) {
bx_options.com[1].Odev->set (&params[i][4]);
bx_options.com[1].Oenabled->set (1);
@ -2508,6 +2538,11 @@ parse_line_formatted(char *context, int num_params, char *params[])
if (!strncmp(params[i], "enabled=", 8)) {
bx_options.com[2].Oenabled->set (atol(&params[i][8]));
}
else if (!strncmp(params[i], "mode=", 5)) {
if (!bx_options.com[2].Omode->set_by_name (strdup(&params[i][5])))
PARSE_ERR(("%s: serial port mode '%s' not available", context, strdup(&params[i][5])));
bx_options.com[2].Oenabled->set (1);
}
else if (!strncmp(params[i], "dev=", 4)) {
bx_options.com[2].Odev->set (&params[i][4]);
bx_options.com[2].Oenabled->set (1);
@ -2522,6 +2557,11 @@ parse_line_formatted(char *context, int num_params, char *params[])
if (!strncmp(params[i], "enabled=", 8)) {
bx_options.com[3].Oenabled->set (atol(&params[i][8]));
}
else if (!strncmp(params[i], "mode=", 5)) {
if (!bx_options.com[3].Omode->set_by_name (strdup(&params[i][5])))
PARSE_ERR(("%s: serial port mode '%s' not available", context, strdup(&params[i][5])));
bx_options.com[3].Oenabled->set (1);
}
else if (!strncmp(params[i], "dev=", 4)) {
bx_options.com[3].Odev->set (&params[i][4]);
bx_options.com[3].Oenabled->set (1);
@ -3436,6 +3476,7 @@ bx_write_serial_options (FILE *fp, bx_serial_options *opt, int n)
{
fprintf (fp, "com%d: enabled=%d", n, opt->Oenabled->get ());
if (opt->Oenabled->get ()) {
fprintf (fp, ", mode=\"%s\"", opt->Omode->get_choice(opt->Omode->get()));
fprintf (fp, ", dev=\"%s\"", opt->Odev->getptr ());
}
fprintf (fp, "\n");

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: siminterface.h,v 1.122 2004-07-09 21:40:48 vruppert Exp $
// $Id: siminterface.h,v 1.123 2004-07-28 19:36:42 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
// Before I can describe what this file is for, I have to make the
@ -314,14 +314,18 @@ typedef enum {
BXP_ATA3_SLAVE_JOURNAL,
#define BXP_ATAx_DEVICE_JOURNAL(i, s) (BXP_ATA0_MASTER_JOURNAL + (2*(i)) + (s))
#define BXP_PARAMS_PER_SERIAL_PORT 2
#define BXP_PARAMS_PER_SERIAL_PORT 3
BXP_COM1_ENABLED,
BXP_COM1_MODE,
BXP_COM1_PATH,
BXP_COM2_ENABLED,
BXP_COM2_MODE,
BXP_COM2_PATH,
BXP_COM3_ENABLED,
BXP_COM3_MODE,
BXP_COM3_PATH,
BXP_COM4_ENABLED,
BXP_COM4_MODE,
BXP_COM4_PATH,
#define BXP_PARAMS_PER_USB_HUB 3
BXP_USB1_ENABLED,
@ -492,6 +496,8 @@ typedef enum {
// use x=1,2,3,4
#define BXP_COMx_ENABLED(x) \
(bx_id)(BXP_COM1_ENABLED + (((x)-1)*BXP_PARAMS_PER_SERIAL_PORT))
#define BXP_COMx_MODE(x) \
(bx_id)(BXP_COM1_MODE + (((x)-1)*BXP_PARAMS_PER_SERIAL_PORT))
#define BXP_COMx_PATH(x) \
(bx_id)(BXP_COM1_PATH + (((x)-1)*BXP_PARAMS_PER_SERIAL_PORT))
@ -1310,6 +1316,7 @@ typedef struct {
typedef struct {
bx_param_bool_c *Oenabled;
bx_param_enum_c *Omode;
bx_param_string_c *Odev;
} bx_serial_options;

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: serial.cc,v 1.54 2004-06-19 15:20:14 sshwarts Exp $
// $Id: serial.cc,v 1.55 2004-07-28 19:36:42 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2004 MandrakeSoft S.A.
@ -73,13 +73,24 @@ bx_serial_c::~bx_serial_c(void)
{
for (int i=0; i<BX_SERIAL_MAXDEV; i++) {
if (bx_options.com[i].Oenabled->get ()) {
#if USE_RAW_SERIAL
delete [] BX_SER_THIS s[i].raw;
#elif defined(SERIAL_ENABLE)
if (s[i].tty_id >= 0) {
tcsetattr(s[i].tty_id, TCSAFLUSH, &s[i].term_orig);
}
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)
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;
}
}
}
}
@ -194,38 +205,66 @@ bx_serial_c::init(void)
DEV_register_ioread_handler(this, read_handler, addr, name, 1);
DEV_register_iowrite_handler(this, write_handler, addr, name, 1);
}
#if USE_RAW_SERIAL
BX_SER_THIS s[i].raw = new serial_raw(bx_options.com[i].Odev->getptr ());
#elif defined(SERIAL_ENABLE)
if (strlen(bx_options.com[i].Odev->getptr ()) > 0) {
BX_SER_THIS s[i].tty_id = open(bx_options.com[i].Odev->getptr (), O_RDWR|O_NONBLOCK,600);
if (BX_SER_THIS s[i].tty_id < 0)
BX_PANIC(("open of com%d (%s) failed\n", i+1, bx_options.com[i].Odev->getptr ()));
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);
bcopy((caddr_t) &BX_SER_THIS s[i].term_orig, (caddr_t) &BX_SER_THIS s[i].term_new, sizeof(struct termios));
cfmakeraw(&BX_SER_THIS s[i].term_new);
BX_SER_THIS s[i].term_new.c_oflag |= OPOST | ONLCR; // Enable NL to CR-NL translation
BX_SER_THIS s[i].io_mode = BX_SER_MODE_NULL;
char *mode = bx_options.com[i].Omode->get_choice(bx_options.com[i].Omode->get());
if (!strcmp(mode, "file")) {
if (strlen(bx_options.com[i].Odev->getptr ()) > 0) {
BX_SER_THIS s[i].output = fopen(bx_options.com[i].Odev->getptr (), "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)
if (strlen(bx_options.com[i].Odev->getptr ()) > 0) {
BX_SER_THIS s[i].tty_id = open(bx_options.com[i].Odev->getptr (), O_RDWR|O_NONBLOCK,600);
if (BX_SER_THIS s[i].tty_id < 0) {
BX_PANIC(("open of com%d (%s) failed\n", i+1, bx_options.com[i].Odev->getptr ()));
} 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);
bcopy((caddr_t) &BX_SER_THIS s[i].term_orig, (caddr_t) &BX_SER_THIS s[i].term_new, sizeof(struct termios));
cfmakeraw(&BX_SER_THIS s[i].term_new);
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;
// 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;
// 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);
}
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(bx_options.com[i].Odev->getptr ());
BX_SER_THIS s[i].io_mode = BX_SER_MODE_RAW;
#else
BX_PANIC(("raw serial support not present"));
#endif
} else if (strcmp(mode, "null")) {
BX_PANIC(("unknown serial i/o 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));
}
}
@ -446,24 +485,26 @@ bx_serial_c::read(Bit32u address, unsigned io_len)
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;
}
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) |
@ -696,29 +737,30 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
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;
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);
}
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;
@ -744,19 +786,23 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
(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);
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_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);
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;
@ -766,28 +812,34 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
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);
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
}
#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);
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);
}
mcr_changed = 1;
if (BX_SER_THIS s[port].line_cntl.break_cntl) {
BX_SER_THIS s[port].raw->set_break(0);
}
#endif
}
}
}
@ -818,17 +870,19 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
}
raise_interrupt(port, BX_SER_INT_MODSTAT);
} else {
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);
}
#else
/* set these to 0 for the time being */
BX_SER_THIS s[port].modem_status.cts = 0;
BX_SER_THIS s[port].modem_status.dsr = 0;
BX_SER_THIS s[port].modem_status.ri = 0;
BX_SER_THIS s[port].modem_status.dcd = 0;
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;
@ -930,16 +984,27 @@ bx_serial_c::tx_timer(void)
if (BX_SER_THIS s[port].modem_cntl.local_loopback) {
rx_fifo_enq(port, BX_SER_THIS s[port].tsrbuffer);
} else {
#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);
#elif 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);
}
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;
}
}
BX_SER_THIS s[port].line_status.tsr_empty = 1;
@ -984,6 +1049,7 @@ bx_serial_c::rx_timer(void)
#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) {
@ -998,67 +1064,73 @@ bx_serial_c::rx_timer(void)
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;
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);
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)) {
if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) {
#if USE_RAW_SERIAL
bx_bool rdy;
int data;
if ((rdy = BX_SER_THIS s[port].raw->ready_receive())) {
data = BX_SER_THIS s[port].raw->receive();
if (data < 0 ) {
rdy = 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;
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 (rdy) {
chbuf = data;
#elif 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));
#else
if (0) {
if (data_ready) {
chbuf = data;
}
#endif
} else if (BX_SER_THIS s[port].io_mode == 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
}
if (data_ready) {
if (!BX_SER_THIS s[port].modem_cntl.local_loopback) {
rx_fifo_enq(port, chbuf);
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: serial.h,v 1.18 2004-01-18 11:58:07 vruppert Exp $
// $Id: serial.h,v 1.19 2004-07-28 19:36:42 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2004 MandrakeSoft S.A.
@ -66,6 +66,11 @@ extern "C" {
#define BX_SER_MSR 6
#define BX_SER_SCR 7
#define BX_SER_MODE_NULL 0
#define BX_SER_MODE_FILE 1
#define BX_SER_MODE_TERM 2
#define BX_SER_MODE_RAW 3
enum {
BX_SER_INT_IER,
BX_SER_INT_RXDATA,
@ -101,7 +106,9 @@ typedef struct {
int rx_timer_index;
int fifo_timer_index;
int io_mode;
int tty_id;
FILE *output;
#if USE_RAW_SERIAL
serial_raw* raw;