diff --git a/bochs/.bochsrc b/bochs/.bochsrc index a0583f87c..8defbfc3f 100644 --- a/bochs/.bochsrc +++ b/bochs/.bochsrc @@ -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" diff --git a/bochs/config.cc b/bochs/config.cc index f5377ab61..8265e62d3 100755 --- a/bochs/config.cc +++ b/bochs/config.cc @@ -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; iadd (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; ireset(); + bx_options.com[i].Omode->reset(); bx_options.com[i].Odev->reset(); } for (i=0; iset (1); + } else if (!strncmp(params[i], "dev=", 4)) { bx_options.com[0].Odev->set (¶ms[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(¶ms[i][8])); } + else if (!strncmp(params[i], "mode=", 5)) { + if (!bx_options.com[1].Omode->set_by_name (strdup(¶ms[i][5]))) + PARSE_ERR(("%s: serial port mode '%s' not available", context, strdup(¶ms[i][5]))); + bx_options.com[1].Oenabled->set (1); + } else if (!strncmp(params[i], "dev=", 4)) { bx_options.com[1].Odev->set (¶ms[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(¶ms[i][8])); } + else if (!strncmp(params[i], "mode=", 5)) { + if (!bx_options.com[2].Omode->set_by_name (strdup(¶ms[i][5]))) + PARSE_ERR(("%s: serial port mode '%s' not available", context, strdup(¶ms[i][5]))); + bx_options.com[2].Oenabled->set (1); + } else if (!strncmp(params[i], "dev=", 4)) { bx_options.com[2].Odev->set (¶ms[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(¶ms[i][8])); } + else if (!strncmp(params[i], "mode=", 5)) { + if (!bx_options.com[3].Omode->set_by_name (strdup(¶ms[i][5]))) + PARSE_ERR(("%s: serial port mode '%s' not available", context, strdup(¶ms[i][5]))); + bx_options.com[3].Oenabled->set (1); + } else if (!strncmp(params[i], "dev=", 4)) { bx_options.com[3].Odev->set (¶ms[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"); diff --git a/bochs/gui/siminterface.h b/bochs/gui/siminterface.h index cfc6b1a64..ed18817a5 100644 --- a/bochs/gui/siminterface.h +++ b/bochs/gui/siminterface.h @@ -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; diff --git a/bochs/iodev/serial.cc b/bochs/iodev/serial.cc index 7f83ab1b9..8e27378e3 100644 --- a/bochs/iodev/serial.cc +++ b/bochs/iodev/serial.cc @@ -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; iget ()) { -#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); } diff --git a/bochs/iodev/serial.h b/bochs/iodev/serial.h index 25e62cf73..d0f108cbe 100644 --- a/bochs/iodev/serial.h +++ b/bochs/iodev/serial.h @@ -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;