- serial read/write and timer handlers prepared for 4 ports
- new function triggeredTimerID() returns the active ID in timer handler
This commit is contained in:
parent
63e4f9d270
commit
8b640bface
@ -1,8 +1,8 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// $Id: serial.cc,v 1.41 2003-11-09 00:14:43 vruppert Exp $
|
// $Id: serial.cc,v 1.42 2004-01-17 15:51:09 vruppert Exp $
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
// Copyright (C) 2004 MandrakeSoft S.A.
|
||||||
//
|
//
|
||||||
// MandrakeSoft S.A.
|
// MandrakeSoft S.A.
|
||||||
// 43, rue d'Aboukir
|
// 43, rue d'Aboukir
|
||||||
@ -350,144 +350,149 @@ bx_serial_c::read(Bit32u address, unsigned io_len)
|
|||||||
#else
|
#else
|
||||||
UNUSED(this_ptr);
|
UNUSED(this_ptr);
|
||||||
#endif // !BX_USE_SER_SMF
|
#endif // !BX_USE_SER_SMF
|
||||||
//UNUSED(address);
|
Bit8u offset, val;
|
||||||
Bit8u val;
|
Bit8u port = 0;
|
||||||
|
|
||||||
/* SERIAL PORT 1 */
|
BX_DEBUG(("register read from address 0x%04x - ", address));
|
||||||
|
|
||||||
BX_DEBUG(("register read from address 0x%04x - ", (unsigned) address));
|
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 (address) {
|
switch (offset) {
|
||||||
case 0x03F8: /* receive buffer, or divisor latch LSB if DLAB set */
|
case BX_SER_RBR: /* receive buffer, or divisor latch LSB if DLAB set */
|
||||||
if (BX_SER_THIS s[0].line_cntl.dlab) {
|
if (BX_SER_THIS s[port].line_cntl.dlab) {
|
||||||
val = BX_SER_THIS s[0].divisor_lsb;
|
val = BX_SER_THIS s[port].divisor_lsb;
|
||||||
} else {
|
} else {
|
||||||
if (BX_SER_THIS s[0].fifo_cntl.enable) {
|
if (BX_SER_THIS s[port].fifo_cntl.enable) {
|
||||||
val = BX_SER_THIS s[0].rx_fifo[0];
|
val = BX_SER_THIS s[port].rx_fifo[0];
|
||||||
if (BX_SER_THIS s[0].rx_fifo_end > 0) {
|
if (BX_SER_THIS s[port].rx_fifo_end > 0) {
|
||||||
memcpy(&BX_SER_THIS s[0].rx_fifo[0], &BX_SER_THIS s[0].rx_fifo[1], 15);
|
memcpy(&BX_SER_THIS s[port].rx_fifo[0], &BX_SER_THIS s[port].rx_fifo[1], 15);
|
||||||
BX_SER_THIS s[0].rx_fifo_end--;
|
BX_SER_THIS s[port].rx_fifo_end--;
|
||||||
}
|
}
|
||||||
if (BX_SER_THIS s[0].rx_fifo_end == 0) {
|
if (BX_SER_THIS s[port].rx_fifo_end == 0) {
|
||||||
BX_SER_THIS s[0].line_status.rxdata_ready = 0;
|
BX_SER_THIS s[port].line_status.rxdata_ready = 0;
|
||||||
BX_SER_THIS s[0].rx_interrupt = 0;
|
BX_SER_THIS s[port].rx_interrupt = 0;
|
||||||
BX_SER_THIS s[0].rx_ipending = 0;
|
BX_SER_THIS s[port].rx_ipending = 0;
|
||||||
BX_SER_THIS s[0].fifo_interrupt = 0;
|
BX_SER_THIS s[port].fifo_interrupt = 0;
|
||||||
BX_SER_THIS s[0].fifo_ipending = 0;
|
BX_SER_THIS s[port].fifo_ipending = 0;
|
||||||
lower_interrupt(0);
|
lower_interrupt(port);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val = BX_SER_THIS s[0].rxbuffer;
|
val = BX_SER_THIS s[port].rxbuffer;
|
||||||
BX_SER_THIS s[0].line_status.rxdata_ready = 0;
|
BX_SER_THIS s[port].line_status.rxdata_ready = 0;
|
||||||
BX_SER_THIS s[0].rx_interrupt = 0;
|
BX_SER_THIS s[port].rx_interrupt = 0;
|
||||||
BX_SER_THIS s[0].rx_ipending = 0;
|
BX_SER_THIS s[port].rx_ipending = 0;
|
||||||
lower_interrupt(0);
|
lower_interrupt(port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03F9: /* interrupt enable register, or div. latch MSB */
|
case BX_SER_IER: /* interrupt enable register, or div. latch MSB */
|
||||||
if (BX_SER_THIS s[0].line_cntl.dlab) {
|
if (BX_SER_THIS s[port].line_cntl.dlab) {
|
||||||
val = BX_SER_THIS s[0].divisor_msb;
|
val = BX_SER_THIS s[port].divisor_msb;
|
||||||
} else {
|
} else {
|
||||||
val = BX_SER_THIS s[0].int_enable.rxdata_enable |
|
val = BX_SER_THIS s[port].int_enable.rxdata_enable |
|
||||||
(BX_SER_THIS s[0].int_enable.txhold_enable << 1) |
|
(BX_SER_THIS s[port].int_enable.txhold_enable << 1) |
|
||||||
(BX_SER_THIS s[0].int_enable.rxlstat_enable << 2) |
|
(BX_SER_THIS s[port].int_enable.rxlstat_enable << 2) |
|
||||||
(BX_SER_THIS s[0].int_enable.modstat_enable << 3);
|
(BX_SER_THIS s[port].int_enable.modstat_enable << 3);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03FA: /* interrupt ID register */
|
case BX_SER_IIR: /* interrupt ID register */
|
||||||
/*
|
/*
|
||||||
* Set the interrupt ID based on interrupt source
|
* Set the interrupt ID based on interrupt source
|
||||||
*/
|
*/
|
||||||
if (BX_SER_THIS s[0].ls_interrupt) {
|
if (BX_SER_THIS s[port].ls_interrupt) {
|
||||||
BX_SER_THIS s[0].int_ident.int_ID = 0x3;
|
BX_SER_THIS s[port].int_ident.int_ID = 0x3;
|
||||||
BX_SER_THIS s[0].int_ident.ipending = 0;
|
BX_SER_THIS s[port].int_ident.ipending = 0;
|
||||||
} else if (BX_SER_THIS s[0].fifo_interrupt) {
|
} else if (BX_SER_THIS s[port].fifo_interrupt) {
|
||||||
BX_SER_THIS s[0].int_ident.int_ID = 0x6;
|
BX_SER_THIS s[port].int_ident.int_ID = 0x6;
|
||||||
BX_SER_THIS s[0].int_ident.ipending = 0;
|
BX_SER_THIS s[port].int_ident.ipending = 0;
|
||||||
} else if (BX_SER_THIS s[0].rx_interrupt) {
|
} else if (BX_SER_THIS s[port].rx_interrupt) {
|
||||||
BX_SER_THIS s[0].int_ident.int_ID = 0x2;
|
BX_SER_THIS s[port].int_ident.int_ID = 0x2;
|
||||||
BX_SER_THIS s[0].int_ident.ipending = 0;
|
BX_SER_THIS s[port].int_ident.ipending = 0;
|
||||||
} else if (BX_SER_THIS s[0].tx_interrupt) {
|
} else if (BX_SER_THIS s[port].tx_interrupt) {
|
||||||
BX_SER_THIS s[0].int_ident.int_ID = 0x1;
|
BX_SER_THIS s[port].int_ident.int_ID = 0x1;
|
||||||
BX_SER_THIS s[0].int_ident.ipending = 0;
|
BX_SER_THIS s[port].int_ident.ipending = 0;
|
||||||
} else if (BX_SER_THIS s[0].ms_interrupt) {
|
} else if (BX_SER_THIS s[port].ms_interrupt) {
|
||||||
BX_SER_THIS s[0].int_ident.int_ID = 0x0;
|
BX_SER_THIS s[port].int_ident.int_ID = 0x0;
|
||||||
BX_SER_THIS s[0].int_ident.ipending = 0;
|
BX_SER_THIS s[port].int_ident.ipending = 0;
|
||||||
} else {
|
} else {
|
||||||
BX_SER_THIS s[0].int_ident.int_ID = 0x0;
|
BX_SER_THIS s[port].int_ident.int_ID = 0x0;
|
||||||
BX_SER_THIS s[0].int_ident.ipending = 1;
|
BX_SER_THIS s[port].int_ident.ipending = 1;
|
||||||
}
|
}
|
||||||
BX_SER_THIS s[0].tx_interrupt = 0;
|
BX_SER_THIS s[port].tx_interrupt = 0;
|
||||||
lower_interrupt(0);
|
lower_interrupt(port);
|
||||||
|
|
||||||
val = BX_SER_THIS s[0].int_ident.ipending |
|
val = BX_SER_THIS s[port].int_ident.ipending |
|
||||||
(BX_SER_THIS s[0].int_ident.int_ID << 1) |
|
(BX_SER_THIS s[port].int_ident.int_ID << 1) |
|
||||||
(BX_SER_THIS s[0].fifo_cntl.enable ? 0xc0 : 0x00);
|
(BX_SER_THIS s[port].fifo_cntl.enable ? 0xc0 : 0x00);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03FB: /* Line control register */
|
case BX_SER_LCR: /* Line control register */
|
||||||
val = BX_SER_THIS s[0].line_cntl.wordlen_sel |
|
val = BX_SER_THIS s[port].line_cntl.wordlen_sel |
|
||||||
(BX_SER_THIS s[0].line_cntl.stopbits << 2) |
|
(BX_SER_THIS s[port].line_cntl.stopbits << 2) |
|
||||||
(BX_SER_THIS s[0].line_cntl.parity_enable << 3) |
|
(BX_SER_THIS s[port].line_cntl.parity_enable << 3) |
|
||||||
(BX_SER_THIS s[0].line_cntl.evenparity_sel << 4) |
|
(BX_SER_THIS s[port].line_cntl.evenparity_sel << 4) |
|
||||||
(BX_SER_THIS s[0].line_cntl.stick_parity << 5) |
|
(BX_SER_THIS s[port].line_cntl.stick_parity << 5) |
|
||||||
(BX_SER_THIS s[0].line_cntl.break_cntl << 6) |
|
(BX_SER_THIS s[port].line_cntl.break_cntl << 6) |
|
||||||
(BX_SER_THIS s[0].line_cntl.dlab << 7);
|
(BX_SER_THIS s[port].line_cntl.dlab << 7);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03FC: /* MODEM control register */
|
case BX_SER_MCR: /* MODEM control register */
|
||||||
val = BX_SER_THIS s[0].modem_cntl.dtr |
|
val = BX_SER_THIS s[port].modem_cntl.dtr |
|
||||||
(BX_SER_THIS s[0].modem_cntl.rts << 1) |
|
(BX_SER_THIS s[port].modem_cntl.rts << 1) |
|
||||||
(BX_SER_THIS s[0].modem_cntl.out1 << 2) |
|
(BX_SER_THIS s[port].modem_cntl.out1 << 2) |
|
||||||
(BX_SER_THIS s[0].modem_cntl.out2 << 3) |
|
(BX_SER_THIS s[port].modem_cntl.out2 << 3) |
|
||||||
(BX_SER_THIS s[0].modem_cntl.local_loopback << 4);
|
(BX_SER_THIS s[port].modem_cntl.local_loopback << 4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03FD: /* Line status register */
|
case BX_SER_LSR: /* Line status register */
|
||||||
val = BX_SER_THIS s[0].line_status.rxdata_ready |
|
val = BX_SER_THIS s[port].line_status.rxdata_ready |
|
||||||
(BX_SER_THIS s[0].line_status.overrun_error << 1) |
|
(BX_SER_THIS s[port].line_status.overrun_error << 1) |
|
||||||
(BX_SER_THIS s[0].line_status.parity_error << 2) |
|
(BX_SER_THIS s[port].line_status.parity_error << 2) |
|
||||||
(BX_SER_THIS s[0].line_status.framing_error << 3) |
|
(BX_SER_THIS s[port].line_status.framing_error << 3) |
|
||||||
(BX_SER_THIS s[0].line_status.break_int << 4) |
|
(BX_SER_THIS s[port].line_status.break_int << 4) |
|
||||||
(BX_SER_THIS s[0].line_status.thr_empty << 5) |
|
(BX_SER_THIS s[port].line_status.thr_empty << 5) |
|
||||||
(BX_SER_THIS s[0].line_status.tsr_empty << 6) |
|
(BX_SER_THIS s[port].line_status.tsr_empty << 6) |
|
||||||
(BX_SER_THIS s[0].line_status.fifo_error << 7);
|
(BX_SER_THIS s[port].line_status.fifo_error << 7);
|
||||||
BX_SER_THIS s[0].line_status.overrun_error = 0;
|
BX_SER_THIS s[port].line_status.overrun_error = 0;
|
||||||
BX_SER_THIS s[0].line_status.break_int = 0;
|
BX_SER_THIS s[port].line_status.break_int = 0;
|
||||||
BX_SER_THIS s[0].ls_interrupt = 0;
|
BX_SER_THIS s[port].ls_interrupt = 0;
|
||||||
BX_SER_THIS s[0].ls_ipending = 0;
|
BX_SER_THIS s[port].ls_ipending = 0;
|
||||||
lower_interrupt(0);
|
lower_interrupt(port);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03FE: /* MODEM status register */
|
case BX_SER_MSR: /* MODEM status register */
|
||||||
val = BX_SER_THIS s[0].modem_status.delta_cts |
|
val = BX_SER_THIS s[port].modem_status.delta_cts |
|
||||||
(BX_SER_THIS s[0].modem_status.delta_dsr << 1) |
|
(BX_SER_THIS s[port].modem_status.delta_dsr << 1) |
|
||||||
(BX_SER_THIS s[0].modem_status.ri_trailedge << 2) |
|
(BX_SER_THIS s[port].modem_status.ri_trailedge << 2) |
|
||||||
(BX_SER_THIS s[0].modem_status.delta_dcd << 3) |
|
(BX_SER_THIS s[port].modem_status.delta_dcd << 3) |
|
||||||
(BX_SER_THIS s[0].modem_status.cts << 4) |
|
(BX_SER_THIS s[port].modem_status.cts << 4) |
|
||||||
(BX_SER_THIS s[0].modem_status.dsr << 5) |
|
(BX_SER_THIS s[port].modem_status.dsr << 5) |
|
||||||
(BX_SER_THIS s[0].modem_status.ri << 6) |
|
(BX_SER_THIS s[port].modem_status.ri << 6) |
|
||||||
(BX_SER_THIS s[0].modem_status.dcd << 7);
|
(BX_SER_THIS s[port].modem_status.dcd << 7);
|
||||||
BX_SER_THIS s[0].modem_status.delta_cts = 0;
|
BX_SER_THIS s[port].modem_status.delta_cts = 0;
|
||||||
BX_SER_THIS s[0].modem_status.delta_dsr = 0;
|
BX_SER_THIS s[port].modem_status.delta_dsr = 0;
|
||||||
BX_SER_THIS s[0].modem_status.ri_trailedge = 0;
|
BX_SER_THIS s[port].modem_status.ri_trailedge = 0;
|
||||||
BX_SER_THIS s[0].modem_status.delta_dcd = 0;
|
BX_SER_THIS s[port].modem_status.delta_dcd = 0;
|
||||||
BX_SER_THIS s[0].ms_interrupt = 0;
|
BX_SER_THIS s[port].ms_interrupt = 0;
|
||||||
BX_SER_THIS s[0].ms_ipending = 0;
|
BX_SER_THIS s[port].ms_ipending = 0;
|
||||||
lower_interrupt(0);
|
lower_interrupt(port);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03FF: /* scratch register */
|
case BX_SER_SCR: /* scratch register */
|
||||||
val = BX_SER_THIS s[0].scratch;
|
val = BX_SER_THIS s[port].scratch;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
val = 0; // keep compiler happy
|
val = 0; // keep compiler happy
|
||||||
BX_PANIC(("unsupported io read from address=0x%04x!",
|
BX_PANIC(("unsupported io read from address=0x%04x!", address));
|
||||||
(unsigned) address));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,57 +523,64 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
|||||||
bx_bool prev_cts, prev_dsr, prev_ri, prev_dcd;
|
bx_bool prev_cts, prev_dsr, prev_ri, prev_dcd;
|
||||||
bx_bool new_rx_ien, new_tx_ien, new_ls_ien, new_ms_ien;
|
bx_bool new_rx_ien, new_tx_ien, new_ls_ien, new_ms_ien;
|
||||||
bx_bool gen_int = 0;
|
bx_bool gen_int = 0;
|
||||||
|
Bit8u offset;
|
||||||
|
Bit8u port = 0;
|
||||||
|
|
||||||
/* SERIAL PORT 1 */
|
BX_DEBUG(("write to address: 0x%04x = 0x%02x", address, value));
|
||||||
|
|
||||||
BX_DEBUG(("write to address: 0x%04x = 0x%02x",
|
offset = address & 0x07;
|
||||||
(unsigned) address, (unsigned) value));
|
switch (address & 0x03f8) {
|
||||||
|
case 0x03f8: port = 0; break;
|
||||||
|
case 0x02f8: port = 1; break;
|
||||||
|
case 0x03e8: port = 2; break;
|
||||||
|
case 0x02e8: port = 3; break;
|
||||||
|
}
|
||||||
|
|
||||||
switch (address) {
|
switch (offset) {
|
||||||
case 0x03F8: /* transmit buffer, or divisor latch LSB if DLAB set */
|
case BX_SER_THR: /* transmit buffer, or divisor latch LSB if DLAB set */
|
||||||
if (BX_SER_THIS s[0].line_cntl.dlab) {
|
if (BX_SER_THIS s[port].line_cntl.dlab) {
|
||||||
BX_SER_THIS s[0].divisor_lsb = value;
|
BX_SER_THIS s[port].divisor_lsb = value;
|
||||||
|
|
||||||
if ((value != 0) || (BX_SER_THIS s[0].divisor_msb != 0)) {
|
if ((value != 0) || (BX_SER_THIS s[port].divisor_msb != 0)) {
|
||||||
BX_SER_THIS s[0].baudrate = (int) (BX_PC_CLOCK_XTL /
|
BX_SER_THIS s[port].baudrate = (int) (BX_PC_CLOCK_XTL /
|
||||||
(16 * ((BX_SER_THIS s[0].divisor_msb << 8) |
|
(16 * ((BX_SER_THIS s[port].divisor_msb << 8) |
|
||||||
BX_SER_THIS s[0].divisor_lsb)));
|
BX_SER_THIS s[port].divisor_lsb)));
|
||||||
#if USE_RAW_SERIAL
|
#if USE_RAW_SERIAL
|
||||||
BX_SER_THIS raw->set_baudrate(BX_SER_THIS s[0].baudrate);
|
BX_SER_THIS raw->set_baudrate(BX_SER_THIS s[port].baudrate);
|
||||||
#endif // USE_RAW_SERIAL
|
#endif // USE_RAW_SERIAL
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Bit8u bitmask = 0xff >> (3 - BX_SER_THIS s[0].line_cntl.wordlen_sel);
|
Bit8u bitmask = 0xff >> (3 - BX_SER_THIS s[port].line_cntl.wordlen_sel);
|
||||||
if (BX_SER_THIS s[0].line_status.thr_empty) {
|
if (BX_SER_THIS s[port].line_status.thr_empty) {
|
||||||
if (BX_SER_THIS s[0].fifo_cntl.enable) {
|
if (BX_SER_THIS s[port].fifo_cntl.enable) {
|
||||||
BX_SER_THIS s[0].tx_fifo[BX_SER_THIS s[0].tx_fifo_end++] = value & bitmask;
|
BX_SER_THIS s[port].tx_fifo[BX_SER_THIS s[port].tx_fifo_end++] = value & bitmask;
|
||||||
} else {
|
} else {
|
||||||
BX_SER_THIS s[0].thrbuffer = value & bitmask;
|
BX_SER_THIS s[port].thrbuffer = value & bitmask;
|
||||||
}
|
}
|
||||||
BX_SER_THIS s[0].line_status.thr_empty = 0;
|
BX_SER_THIS s[port].line_status.thr_empty = 0;
|
||||||
if (BX_SER_THIS s[0].line_status.tsr_empty) {
|
if (BX_SER_THIS s[port].line_status.tsr_empty) {
|
||||||
if (BX_SER_THIS s[0].fifo_cntl.enable) {
|
if (BX_SER_THIS s[port].fifo_cntl.enable) {
|
||||||
BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].tx_fifo[0];
|
BX_SER_THIS s[port].tsrbuffer = BX_SER_THIS s[port].tx_fifo[0];
|
||||||
memcpy(&BX_SER_THIS s[0].tx_fifo[0], &BX_SER_THIS s[0].tx_fifo[1], 15);
|
memcpy(&BX_SER_THIS s[port].tx_fifo[0], &BX_SER_THIS s[port].tx_fifo[1], 15);
|
||||||
BX_SER_THIS s[0].line_status.thr_empty = (--BX_SER_THIS s[0].tx_fifo_end == 0);
|
BX_SER_THIS s[port].line_status.thr_empty = (--BX_SER_THIS s[port].tx_fifo_end == 0);
|
||||||
} else {
|
} else {
|
||||||
BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].thrbuffer;
|
BX_SER_THIS s[port].tsrbuffer = BX_SER_THIS s[port].thrbuffer;
|
||||||
BX_SER_THIS s[0].line_status.thr_empty = 1;
|
BX_SER_THIS s[port].line_status.thr_empty = 1;
|
||||||
}
|
}
|
||||||
BX_SER_THIS s[0].line_status.tsr_empty = 0;
|
BX_SER_THIS s[port].line_status.tsr_empty = 0;
|
||||||
raise_interrupt(0, BX_SER_INT_TXHOLD);
|
raise_interrupt(port, BX_SER_INT_TXHOLD);
|
||||||
bx_pc_system.activate_timer(BX_SER_THIS s[0].tx_timer_index,
|
bx_pc_system.activate_timer(BX_SER_THIS s[port].tx_timer_index,
|
||||||
(int) (1000000.0 / BX_SER_THIS s[0].baudrate *
|
(int) (1000000.0 / BX_SER_THIS s[port].baudrate *
|
||||||
(BX_SER_THIS s[0].line_cntl.wordlen_sel + 5)),
|
(BX_SER_THIS s[port].line_cntl.wordlen_sel + 5)),
|
||||||
0); /* not continuous */
|
0); /* not continuous */
|
||||||
} else {
|
} else {
|
||||||
BX_SER_THIS s[0].tx_interrupt = 0;
|
BX_SER_THIS s[port].tx_interrupt = 0;
|
||||||
lower_interrupt(0);
|
lower_interrupt(port);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (BX_SER_THIS s[0].fifo_cntl.enable) {
|
if (BX_SER_THIS s[port].fifo_cntl.enable) {
|
||||||
if (BX_SER_THIS s[0].tx_fifo_end < 16) {
|
if (BX_SER_THIS s[port].tx_fifo_end < 16) {
|
||||||
BX_SER_THIS s[0].tx_fifo[BX_SER_THIS s[0].tx_fifo_end++] = value & bitmask;
|
BX_SER_THIS s[port].tx_fifo[BX_SER_THIS s[port].tx_fifo_end++] = value & bitmask;
|
||||||
} else {
|
} else {
|
||||||
BX_ERROR(("com1: transmit FIFO overflow"));
|
BX_ERROR(("com1: transmit FIFO overflow"));
|
||||||
}
|
}
|
||||||
@ -579,16 +591,16 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03F9: /* interrupt enable register, or div. latch MSB */
|
case BX_SER_IER: /* interrupt enable register, or div. latch MSB */
|
||||||
if (BX_SER_THIS s[0].line_cntl.dlab) {
|
if (BX_SER_THIS s[port].line_cntl.dlab) {
|
||||||
BX_SER_THIS s[0].divisor_msb = value;
|
BX_SER_THIS s[port].divisor_msb = value;
|
||||||
|
|
||||||
if ((value != 0) || (BX_SER_THIS s[0].divisor_lsb != 0)) {
|
if ((value != 0) || (BX_SER_THIS s[port].divisor_lsb != 0)) {
|
||||||
BX_SER_THIS s[0].baudrate = (int) (BX_PC_CLOCK_XTL /
|
BX_SER_THIS s[port].baudrate = (int) (BX_PC_CLOCK_XTL /
|
||||||
(16 * ((BX_SER_THIS s[0].divisor_msb << 8) |
|
(16 * ((BX_SER_THIS s[port].divisor_msb << 8) |
|
||||||
BX_SER_THIS s[0].divisor_lsb)));
|
BX_SER_THIS s[port].divisor_lsb)));
|
||||||
#if USE_RAW_SERIAL
|
#if USE_RAW_SERIAL
|
||||||
BX_SER_THIS raw->set_baudrate(BX_SER_THIS s[0].baudrate);
|
BX_SER_THIS raw->set_baudrate(BX_SER_THIS s[port].baudrate);
|
||||||
#endif // USE_RAW_SERIAL
|
#endif // USE_RAW_SERIAL
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -596,95 +608,95 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
|||||||
new_tx_ien = (value & 0x02) >> 1;
|
new_tx_ien = (value & 0x02) >> 1;
|
||||||
new_ls_ien = (value & 0x04) >> 2;
|
new_ls_ien = (value & 0x04) >> 2;
|
||||||
new_ms_ien = (value & 0x08) >> 3;
|
new_ms_ien = (value & 0x08) >> 3;
|
||||||
if (new_ms_ien != BX_SER_THIS s[0].int_enable.modstat_enable) {
|
if (new_ms_ien != BX_SER_THIS s[port].int_enable.modstat_enable) {
|
||||||
BX_SER_THIS s[0].int_enable.modstat_enable = new_ms_ien;
|
BX_SER_THIS s[port].int_enable.modstat_enable = new_ms_ien;
|
||||||
if (BX_SER_THIS s[0].int_enable.modstat_enable == 1) {
|
if (BX_SER_THIS s[port].int_enable.modstat_enable == 1) {
|
||||||
if (BX_SER_THIS s[0].ms_ipending == 1) {
|
if (BX_SER_THIS s[port].ms_ipending == 1) {
|
||||||
BX_SER_THIS s[0].ms_interrupt = 1;
|
BX_SER_THIS s[port].ms_interrupt = 1;
|
||||||
BX_SER_THIS s[0].ms_ipending = 0;
|
BX_SER_THIS s[port].ms_ipending = 0;
|
||||||
gen_int = 1;
|
gen_int = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (BX_SER_THIS s[0].ms_interrupt == 1) {
|
if (BX_SER_THIS s[port].ms_interrupt == 1) {
|
||||||
BX_SER_THIS s[0].ms_interrupt = 0;
|
BX_SER_THIS s[port].ms_interrupt = 0;
|
||||||
BX_SER_THIS s[0].ms_ipending = 1;
|
BX_SER_THIS s[port].ms_ipending = 1;
|
||||||
lower_interrupt(0);
|
lower_interrupt(port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (new_tx_ien != BX_SER_THIS s[0].int_enable.txhold_enable) {
|
if (new_tx_ien != BX_SER_THIS s[port].int_enable.txhold_enable) {
|
||||||
BX_SER_THIS s[0].int_enable.txhold_enable = new_tx_ien;
|
BX_SER_THIS s[port].int_enable.txhold_enable = new_tx_ien;
|
||||||
if (BX_SER_THIS s[0].int_enable.txhold_enable == 1) {
|
if (BX_SER_THIS s[port].int_enable.txhold_enable == 1) {
|
||||||
BX_SER_THIS s[0].tx_interrupt = BX_SER_THIS s[0].line_status.thr_empty;
|
BX_SER_THIS s[port].tx_interrupt = BX_SER_THIS s[port].line_status.thr_empty;
|
||||||
if (BX_SER_THIS s[0].tx_interrupt) gen_int = 1;
|
if (BX_SER_THIS s[port].tx_interrupt) gen_int = 1;
|
||||||
} else {
|
} else {
|
||||||
BX_SER_THIS s[0].tx_interrupt = 0;
|
BX_SER_THIS s[port].tx_interrupt = 0;
|
||||||
lower_interrupt(0);
|
lower_interrupt(port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (new_rx_ien != BX_SER_THIS s[0].int_enable.rxdata_enable) {
|
if (new_rx_ien != BX_SER_THIS s[port].int_enable.rxdata_enable) {
|
||||||
BX_SER_THIS s[0].int_enable.rxdata_enable = new_rx_ien;
|
BX_SER_THIS s[port].int_enable.rxdata_enable = new_rx_ien;
|
||||||
if (BX_SER_THIS s[0].int_enable.rxdata_enable == 1) {
|
if (BX_SER_THIS s[port].int_enable.rxdata_enable == 1) {
|
||||||
if (BX_SER_THIS s[0].fifo_ipending == 1) {
|
if (BX_SER_THIS s[port].fifo_ipending == 1) {
|
||||||
BX_SER_THIS s[0].fifo_interrupt = 1;
|
BX_SER_THIS s[port].fifo_interrupt = 1;
|
||||||
BX_SER_THIS s[0].fifo_ipending = 0;
|
BX_SER_THIS s[port].fifo_ipending = 0;
|
||||||
gen_int = 1;
|
gen_int = 1;
|
||||||
}
|
}
|
||||||
if (BX_SER_THIS s[0].rx_ipending == 1) {
|
if (BX_SER_THIS s[port].rx_ipending == 1) {
|
||||||
BX_SER_THIS s[0].rx_interrupt = 1;
|
BX_SER_THIS s[port].rx_interrupt = 1;
|
||||||
BX_SER_THIS s[0].rx_ipending = 0;
|
BX_SER_THIS s[port].rx_ipending = 0;
|
||||||
gen_int = 1;
|
gen_int = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (BX_SER_THIS s[0].rx_interrupt == 1) {
|
if (BX_SER_THIS s[port].rx_interrupt == 1) {
|
||||||
BX_SER_THIS s[0].rx_interrupt = 0;
|
BX_SER_THIS s[port].rx_interrupt = 0;
|
||||||
BX_SER_THIS s[0].rx_ipending = 1;
|
BX_SER_THIS s[port].rx_ipending = 1;
|
||||||
lower_interrupt(0);
|
lower_interrupt(port);
|
||||||
}
|
}
|
||||||
if (BX_SER_THIS s[0].fifo_interrupt == 1) {
|
if (BX_SER_THIS s[port].fifo_interrupt == 1) {
|
||||||
BX_SER_THIS s[0].fifo_interrupt = 0;
|
BX_SER_THIS s[port].fifo_interrupt = 0;
|
||||||
BX_SER_THIS s[0].fifo_ipending = 1;
|
BX_SER_THIS s[port].fifo_ipending = 1;
|
||||||
lower_interrupt(0);
|
lower_interrupt(port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (new_ls_ien != BX_SER_THIS s[0].int_enable.rxlstat_enable) {
|
if (new_ls_ien != BX_SER_THIS s[port].int_enable.rxlstat_enable) {
|
||||||
BX_SER_THIS s[0].int_enable.rxlstat_enable = new_ls_ien;
|
BX_SER_THIS s[port].int_enable.rxlstat_enable = new_ls_ien;
|
||||||
if (BX_SER_THIS s[0].int_enable.rxlstat_enable == 1) {
|
if (BX_SER_THIS s[port].int_enable.rxlstat_enable == 1) {
|
||||||
if (BX_SER_THIS s[0].ls_ipending == 1) {
|
if (BX_SER_THIS s[port].ls_ipending == 1) {
|
||||||
BX_SER_THIS s[0].ls_interrupt = 1;
|
BX_SER_THIS s[port].ls_interrupt = 1;
|
||||||
BX_SER_THIS s[0].ls_ipending = 0;
|
BX_SER_THIS s[port].ls_ipending = 0;
|
||||||
gen_int = 1;
|
gen_int = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (BX_SER_THIS s[0].ls_interrupt == 1) {
|
if (BX_SER_THIS s[port].ls_interrupt == 1) {
|
||||||
BX_SER_THIS s[0].ls_interrupt = 0;
|
BX_SER_THIS s[port].ls_interrupt = 0;
|
||||||
BX_SER_THIS s[0].ls_ipending = 1;
|
BX_SER_THIS s[port].ls_ipending = 1;
|
||||||
lower_interrupt(0);
|
lower_interrupt(port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (gen_int) raise_interrupt(0, BX_SER_INT_IER);
|
if (gen_int) raise_interrupt(port, BX_SER_INT_IER);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03FA: /* FIFO control register */
|
case BX_SER_FCR: /* FIFO control register */
|
||||||
if (!BX_SER_THIS s[0].fifo_cntl.enable && (value & 0x01)) {
|
if (!BX_SER_THIS s[port].fifo_cntl.enable && (value & 0x01)) {
|
||||||
BX_INFO(("FIFO enabled"));
|
BX_INFO(("FIFO enabled"));
|
||||||
BX_SER_THIS s[0].rx_fifo_end = 0;
|
BX_SER_THIS s[port].rx_fifo_end = 0;
|
||||||
BX_SER_THIS s[0].tx_fifo_end = 0;
|
BX_SER_THIS s[port].tx_fifo_end = 0;
|
||||||
}
|
}
|
||||||
BX_SER_THIS s[0].fifo_cntl.enable = value & 0x01;
|
BX_SER_THIS s[port].fifo_cntl.enable = value & 0x01;
|
||||||
if (value & 0x02) {
|
if (value & 0x02) {
|
||||||
BX_SER_THIS s[0].rx_fifo_end = 0;
|
BX_SER_THIS s[port].rx_fifo_end = 0;
|
||||||
}
|
}
|
||||||
if (value & 0x04) {
|
if (value & 0x04) {
|
||||||
BX_SER_THIS s[0].tx_fifo_end = 0;
|
BX_SER_THIS s[port].tx_fifo_end = 0;
|
||||||
}
|
}
|
||||||
BX_SER_THIS s[0].fifo_cntl.rxtrigger = (value & 0xc0) >> 6;
|
BX_SER_THIS s[port].fifo_cntl.rxtrigger = (value & 0xc0) >> 6;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03FB: /* Line control register */
|
case BX_SER_LCR: /* Line control register */
|
||||||
#if !USE_RAW_SERIAL
|
#if !USE_RAW_SERIAL
|
||||||
if ((value & 0x3) != 0x3) {
|
if ((value & 0x3) != 0x3) {
|
||||||
/* ignore this: this is set by FreeBSD when the console
|
/* ignore this: this is set by FreeBSD when the console
|
||||||
@ -692,109 +704,109 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
|||||||
}
|
}
|
||||||
#endif // !USE_RAW_SERIAL
|
#endif // !USE_RAW_SERIAL
|
||||||
#if USE_RAW_SERIAL
|
#if USE_RAW_SERIAL
|
||||||
if (BX_SER_THIS s[0].line_cntl.wordlen_sel != (value & 0x3)) {
|
if (BX_SER_THIS s[port].line_cntl.wordlen_sel != (value & 0x3)) {
|
||||||
BX_SER_THIS raw->set_data_bits((value & 0x3) + 5);
|
BX_SER_THIS raw->set_data_bits((value & 0x3) + 5);
|
||||||
}
|
}
|
||||||
if (BX_SER_THIS s[0].line_cntl.stopbits != (value & 0x4) >> 2) {
|
if (BX_SER_THIS s[port].line_cntl.stopbits != (value & 0x4) >> 2) {
|
||||||
BX_SER_THIS raw->set_stop_bits((value & 0x4 >> 2) ? 2 : 1);
|
BX_SER_THIS raw->set_stop_bits((value & 0x4 >> 2) ? 2 : 1);
|
||||||
}
|
}
|
||||||
if (BX_SER_THIS s[0].line_cntl.parity_enable != (value & 0x8) >> 3 ||
|
if (BX_SER_THIS s[port].line_cntl.parity_enable != (value & 0x8) >> 3 ||
|
||||||
BX_SER_THIS s[0].line_cntl.evenparity_sel != (value & 0x10) >> 4 ||
|
BX_SER_THIS s[port].line_cntl.evenparity_sel != (value & 0x10) >> 4 ||
|
||||||
BX_SER_THIS s[0].line_cntl.stick_parity != (value & 0x20) >> 5) {
|
BX_SER_THIS s[port].line_cntl.stick_parity != (value & 0x20) >> 5) {
|
||||||
if (((value & 0x20) >> 5) &&
|
if (((value & 0x20) >> 5) &&
|
||||||
((value & 0x8) >> 3))
|
((value & 0x8) >> 3))
|
||||||
BX_PANIC(("sticky parity set and parity enabled"));
|
BX_PANIC(("sticky parity set and parity enabled"));
|
||||||
BX_SER_THIS raw->set_parity_mode(((value & 0x8) >> 3),
|
BX_SER_THIS raw->set_parity_mode(((value & 0x8) >> 3),
|
||||||
((value & 0x10) >> 4) ? P_EVEN : P_ODD);
|
((value & 0x10) >> 4) ? P_EVEN : P_ODD);
|
||||||
}
|
}
|
||||||
if (BX_SER_THIS s[0].line_cntl.break_cntl && !((value & 0x40) >> 6)) {
|
if (BX_SER_THIS s[port].line_cntl.break_cntl && !((value & 0x40) >> 6)) {
|
||||||
BX_SER_THIS raw->transmit(C_BREAK);
|
BX_SER_THIS raw->transmit(C_BREAK);
|
||||||
}
|
}
|
||||||
#endif // USE_RAW_SERIAL
|
#endif // USE_RAW_SERIAL
|
||||||
|
|
||||||
BX_SER_THIS s[0].line_cntl.wordlen_sel = value & 0x3;
|
BX_SER_THIS s[port].line_cntl.wordlen_sel = value & 0x3;
|
||||||
/* These are ignored, but set them up so they can be read back */
|
/* These are ignored, but set them up so they can be read back */
|
||||||
BX_SER_THIS s[0].line_cntl.stopbits = (value & 0x4) >> 2;
|
BX_SER_THIS s[port].line_cntl.stopbits = (value & 0x4) >> 2;
|
||||||
BX_SER_THIS s[0].line_cntl.parity_enable = (value & 0x8) >> 3;
|
BX_SER_THIS s[port].line_cntl.parity_enable = (value & 0x8) >> 3;
|
||||||
BX_SER_THIS s[0].line_cntl.evenparity_sel = (value & 0x10) >> 4;
|
BX_SER_THIS s[port].line_cntl.evenparity_sel = (value & 0x10) >> 4;
|
||||||
BX_SER_THIS s[0].line_cntl.stick_parity = (value & 0x20) >> 5;
|
BX_SER_THIS s[port].line_cntl.stick_parity = (value & 0x20) >> 5;
|
||||||
BX_SER_THIS s[0].line_cntl.break_cntl = (value & 0x40) >> 6;
|
BX_SER_THIS s[port].line_cntl.break_cntl = (value & 0x40) >> 6;
|
||||||
/* used when doing future writes */
|
/* used when doing future writes */
|
||||||
if (BX_SER_THIS s[0].line_cntl.dlab &&
|
if (BX_SER_THIS s[port].line_cntl.dlab &&
|
||||||
!((value & 0x80) >> 7)) {
|
!((value & 0x80) >> 7)) {
|
||||||
// Start the receive polling process if not already started
|
// Start the receive polling process if not already started
|
||||||
// and there is a valid baudrate.
|
// and there is a valid baudrate.
|
||||||
if (BX_SER_THIS s[0].rx_pollstate == BX_SER_RXIDLE &&
|
if (BX_SER_THIS s[port].rx_pollstate == BX_SER_RXIDLE &&
|
||||||
BX_SER_THIS s[0].baudrate != 0) {
|
BX_SER_THIS s[port].baudrate != 0) {
|
||||||
BX_SER_THIS s[0].rx_pollstate = BX_SER_RXPOLL;
|
BX_SER_THIS s[port].rx_pollstate = BX_SER_RXPOLL;
|
||||||
bx_pc_system.activate_timer(BX_SER_THIS s[0].rx_timer_index,
|
bx_pc_system.activate_timer(BX_SER_THIS s[port].rx_timer_index,
|
||||||
(int) (1000000.0 / BX_SER_THIS s[0].baudrate *
|
(int) (1000000.0 / BX_SER_THIS s[port].baudrate *
|
||||||
(BX_SER_THIS s[0].line_cntl.wordlen_sel + 5)),
|
(BX_SER_THIS s[port].line_cntl.wordlen_sel + 5)),
|
||||||
0); /* not continuous */
|
0); /* not continuous */
|
||||||
}
|
}
|
||||||
BX_DEBUG(("baud rate set - %d", BX_SER_THIS s[0].baudrate));
|
BX_DEBUG(("baud rate set - %d", BX_SER_THIS s[port].baudrate));
|
||||||
}
|
}
|
||||||
BX_SER_THIS s[0].line_cntl.dlab = (value & 0x80) >> 7;
|
BX_SER_THIS s[port].line_cntl.dlab = (value & 0x80) >> 7;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03FC: /* MODEM control register */
|
case BX_SER_MCR: /* MODEM control register */
|
||||||
if ((value & 0x01) == 0) {
|
if ((value & 0x01) == 0) {
|
||||||
#if USE_RAW_SERIAL
|
#if USE_RAW_SERIAL
|
||||||
BX_SER_THIS raw->send_hangup();
|
BX_SER_THIS raw->send_hangup();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BX_SER_THIS s[0].modem_cntl.dtr = value & 0x01;
|
BX_SER_THIS s[port].modem_cntl.dtr = value & 0x01;
|
||||||
BX_SER_THIS s[0].modem_cntl.rts = (value & 0x02) >> 1;
|
BX_SER_THIS s[port].modem_cntl.rts = (value & 0x02) >> 1;
|
||||||
BX_SER_THIS s[0].modem_cntl.out1 = (value & 0x04) >> 2;
|
BX_SER_THIS s[port].modem_cntl.out1 = (value & 0x04) >> 2;
|
||||||
BX_SER_THIS s[0].modem_cntl.out2 = (value & 0x08) >> 3;
|
BX_SER_THIS s[port].modem_cntl.out2 = (value & 0x08) >> 3;
|
||||||
BX_SER_THIS s[0].modem_cntl.local_loopback = (value & 0x10) >> 4;
|
BX_SER_THIS s[port].modem_cntl.local_loopback = (value & 0x10) >> 4;
|
||||||
|
|
||||||
if (BX_SER_THIS s[0].modem_cntl.local_loopback) {
|
if (BX_SER_THIS s[port].modem_cntl.local_loopback) {
|
||||||
prev_cts = BX_SER_THIS s[0].modem_status.cts;
|
prev_cts = BX_SER_THIS s[port].modem_status.cts;
|
||||||
prev_dsr = BX_SER_THIS s[0].modem_status.dsr;
|
prev_dsr = BX_SER_THIS s[port].modem_status.dsr;
|
||||||
prev_ri = BX_SER_THIS s[0].modem_status.ri;
|
prev_ri = BX_SER_THIS s[port].modem_status.ri;
|
||||||
prev_dcd = BX_SER_THIS s[0].modem_status.dcd;
|
prev_dcd = BX_SER_THIS s[port].modem_status.dcd;
|
||||||
BX_SER_THIS s[0].modem_status.cts = BX_SER_THIS s[0].modem_cntl.rts;
|
BX_SER_THIS s[port].modem_status.cts = BX_SER_THIS s[port].modem_cntl.rts;
|
||||||
BX_SER_THIS s[0].modem_status.dsr = BX_SER_THIS s[0].modem_cntl.dtr;
|
BX_SER_THIS s[port].modem_status.dsr = BX_SER_THIS s[port].modem_cntl.dtr;
|
||||||
BX_SER_THIS s[0].modem_status.ri = BX_SER_THIS s[0].modem_cntl.out1;
|
BX_SER_THIS s[port].modem_status.ri = BX_SER_THIS s[port].modem_cntl.out1;
|
||||||
BX_SER_THIS s[0].modem_status.dcd = BX_SER_THIS s[0].modem_cntl.out2;
|
BX_SER_THIS s[port].modem_status.dcd = BX_SER_THIS s[port].modem_cntl.out2;
|
||||||
if (BX_SER_THIS s[0].modem_status.cts != prev_cts) {
|
if (BX_SER_THIS s[port].modem_status.cts != prev_cts) {
|
||||||
BX_SER_THIS s[0].modem_status.delta_cts = 1;
|
BX_SER_THIS s[port].modem_status.delta_cts = 1;
|
||||||
BX_SER_THIS s[0].ms_ipending = 1;
|
BX_SER_THIS s[port].ms_ipending = 1;
|
||||||
}
|
}
|
||||||
if (BX_SER_THIS s[0].modem_status.dsr != prev_dsr) {
|
if (BX_SER_THIS s[port].modem_status.dsr != prev_dsr) {
|
||||||
BX_SER_THIS s[0].modem_status.delta_dsr = 1;
|
BX_SER_THIS s[port].modem_status.delta_dsr = 1;
|
||||||
BX_SER_THIS s[0].ms_ipending = 1;
|
BX_SER_THIS s[port].ms_ipending = 1;
|
||||||
}
|
}
|
||||||
if (BX_SER_THIS s[0].modem_status.ri != prev_ri)
|
if (BX_SER_THIS s[port].modem_status.ri != prev_ri)
|
||||||
BX_SER_THIS s[0].ms_ipending = 1;
|
BX_SER_THIS s[port].ms_ipending = 1;
|
||||||
if ((BX_SER_THIS s[0].modem_status.ri == 0) && (prev_ri == 1))
|
if ((BX_SER_THIS s[port].modem_status.ri == 0) && (prev_ri == 1))
|
||||||
BX_SER_THIS s[0].modem_status.ri_trailedge = 1;
|
BX_SER_THIS s[port].modem_status.ri_trailedge = 1;
|
||||||
if (BX_SER_THIS s[0].modem_status.dcd != prev_dcd) {
|
if (BX_SER_THIS s[port].modem_status.dcd != prev_dcd) {
|
||||||
BX_SER_THIS s[0].modem_status.delta_dcd = 1;
|
BX_SER_THIS s[port].modem_status.delta_dcd = 1;
|
||||||
BX_SER_THIS s[0].ms_ipending = 1;
|
BX_SER_THIS s[port].ms_ipending = 1;
|
||||||
}
|
}
|
||||||
raise_interrupt(0, BX_SER_INT_MODSTAT);
|
raise_interrupt(port, BX_SER_INT_MODSTAT);
|
||||||
} else {
|
} else {
|
||||||
/* set these to 0 for the time being */
|
/* set these to 0 for the time being */
|
||||||
BX_SER_THIS s[0].modem_status.cts = 0;
|
BX_SER_THIS s[port].modem_status.cts = 0;
|
||||||
BX_SER_THIS s[0].modem_status.dsr = 0;
|
BX_SER_THIS s[port].modem_status.dsr = 0;
|
||||||
BX_SER_THIS s[0].modem_status.ri = 0;
|
BX_SER_THIS s[port].modem_status.ri = 0;
|
||||||
BX_SER_THIS s[0].modem_status.dcd = 0;
|
BX_SER_THIS s[port].modem_status.dcd = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03FD: /* Line status register */
|
case BX_SER_LSR: /* Line status register */
|
||||||
BX_ERROR(("write to line status register ignored"));
|
BX_ERROR(("write to line status register ignored"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03FE: /* MODEM status register */
|
case BX_SER_MSR: /* MODEM status register */
|
||||||
BX_ERROR(("write to MODEM status register ignored"));
|
BX_ERROR(("write to MODEM status register ignored"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03FF: /* scratch register */
|
case BX_SER_SCR: /* scratch register */
|
||||||
BX_SER_THIS s[0].scratch = value;
|
BX_SER_THIS s[port].scratch = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -816,28 +828,28 @@ bx_serial_c::rx_fifo_enq(Bit8u port, Bit8u data)
|
|||||||
BX_SER_THIS s[port].line_status.overrun_error = 1;
|
BX_SER_THIS s[port].line_status.overrun_error = 1;
|
||||||
raise_interrupt(port, BX_SER_INT_RXLSTAT);
|
raise_interrupt(port, BX_SER_INT_RXLSTAT);
|
||||||
} else {
|
} else {
|
||||||
BX_SER_THIS s[port].rx_fifo[BX_SER_THIS s[0].rx_fifo_end++] = data;
|
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) {
|
switch (BX_SER_THIS s[port].fifo_cntl.rxtrigger) {
|
||||||
case 1:
|
case 1:
|
||||||
if (BX_SER_THIS s[0].rx_fifo_end == 4) gen_int = 1;
|
if (BX_SER_THIS s[port].rx_fifo_end == 4) gen_int = 1;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (BX_SER_THIS s[0].rx_fifo_end == 8) gen_int = 1;
|
if (BX_SER_THIS s[port].rx_fifo_end == 8) gen_int = 1;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (BX_SER_THIS s[0].rx_fifo_end == 14) gen_int = 1;
|
if (BX_SER_THIS s[port].rx_fifo_end == 14) gen_int = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
gen_int = 1;
|
gen_int = 1;
|
||||||
}
|
}
|
||||||
if (gen_int) {
|
if (gen_int) {
|
||||||
bx_pc_system.deactivate_timer(BX_SER_THIS s[0].fifo_timer_index);
|
bx_pc_system.deactivate_timer(BX_SER_THIS s[port].fifo_timer_index);
|
||||||
BX_SER_THIS s[port].line_status.rxdata_ready = 1;
|
BX_SER_THIS s[port].line_status.rxdata_ready = 1;
|
||||||
raise_interrupt(port, BX_SER_INT_RXDATA);
|
raise_interrupt(port, BX_SER_INT_RXDATA);
|
||||||
} else {
|
} else {
|
||||||
bx_pc_system.activate_timer(BX_SER_THIS s[0].fifo_timer_index,
|
bx_pc_system.activate_timer(BX_SER_THIS s[port].fifo_timer_index,
|
||||||
(int) (1000000.0 / BX_SER_THIS s[0].baudrate *
|
(int) (1000000.0 / BX_SER_THIS s[port].baudrate *
|
||||||
(BX_SER_THIS s[0].line_cntl.wordlen_sel + 5) * 16),
|
(BX_SER_THIS s[port].line_cntl.wordlen_sel + 5) * 16),
|
||||||
0); /* not continuous */
|
0); /* not continuous */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -867,40 +879,53 @@ void
|
|||||||
bx_serial_c::tx_timer(void)
|
bx_serial_c::tx_timer(void)
|
||||||
{
|
{
|
||||||
bx_bool gen_int = 0;
|
bx_bool gen_int = 0;
|
||||||
|
Bit8u port = 0;
|
||||||
|
int timer_id;
|
||||||
|
|
||||||
if (BX_SER_THIS s[0].modem_cntl.local_loopback) {
|
timer_id = bx_pc_system.triggeredTimerID();
|
||||||
rx_fifo_enq(0, BX_SER_THIS s[0].tsrbuffer);
|
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;
|
||||||
|
}
|
||||||
|
BX_INFO(("tx_timer: port = %d", port));
|
||||||
|
if (BX_SER_THIS s[port].modem_cntl.local_loopback) {
|
||||||
|
rx_fifo_enq(0, BX_SER_THIS s[port].tsrbuffer);
|
||||||
} else {
|
} else {
|
||||||
#if USE_RAW_SERIAL
|
#if USE_RAW_SERIAL
|
||||||
if (!BX_SER_THIS raw->ready_transmit())
|
if (!BX_SER_THIS raw->ready_transmit())
|
||||||
BX_PANIC(("Not ready to transmit"));
|
BX_PANIC(("Not ready to transmit"));
|
||||||
BX_SER_THIS raw->transmit(BX_SER_THIS s[0].tsrbuffer);
|
BX_SER_THIS raw->transmit(BX_SER_THIS s[port].tsrbuffer);
|
||||||
#endif
|
#endif
|
||||||
#if defined(SERIAL_ENABLE)
|
#if defined(SERIAL_ENABLE)
|
||||||
BX_DEBUG(("write: '%c'", BX_SER_THIS s[0].tsrbuffer));
|
BX_DEBUG(("write: '%c'", BX_SER_THIS s[port].tsrbuffer));
|
||||||
if (tty_id >= 0) write(tty_id, (bx_ptr_t) & BX_SER_THIS s[0].tsrbuffer, 1);
|
if (tty_id >= 0) write(tty_id, (bx_ptr_t) & BX_SER_THIS s[port].tsrbuffer, 1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BX_SER_THIS s[0].line_status.tsr_empty = 1;
|
BX_SER_THIS s[port].line_status.tsr_empty = 1;
|
||||||
if (BX_SER_THIS s[0].fifo_cntl.enable && (BX_SER_THIS s[0].tx_fifo_end > 0)) {
|
if (BX_SER_THIS s[port].fifo_cntl.enable && (BX_SER_THIS s[port].tx_fifo_end > 0)) {
|
||||||
BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].tx_fifo[0];
|
BX_SER_THIS s[port].tsrbuffer = BX_SER_THIS s[port].tx_fifo[0];
|
||||||
BX_SER_THIS s[0].line_status.tsr_empty = 0;
|
BX_SER_THIS s[port].line_status.tsr_empty = 0;
|
||||||
memcpy(&BX_SER_THIS s[0].tx_fifo[0], &BX_SER_THIS s[0].tx_fifo[1], 15);
|
memcpy(&BX_SER_THIS s[port].tx_fifo[0], &BX_SER_THIS s[port].tx_fifo[1], 15);
|
||||||
gen_int = (--BX_SER_THIS s[0].tx_fifo_end == 0);
|
gen_int = (--BX_SER_THIS s[port].tx_fifo_end == 0);
|
||||||
} else if (!BX_SER_THIS s[0].line_status.thr_empty) {
|
} else if (!BX_SER_THIS s[port].line_status.thr_empty) {
|
||||||
BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].thrbuffer;
|
BX_SER_THIS s[port].tsrbuffer = BX_SER_THIS s[port].thrbuffer;
|
||||||
BX_SER_THIS s[0].line_status.tsr_empty = 0;
|
BX_SER_THIS s[port].line_status.tsr_empty = 0;
|
||||||
gen_int = 1;
|
gen_int = 1;
|
||||||
}
|
}
|
||||||
if (!BX_SER_THIS s[0].line_status.tsr_empty) {
|
if (!BX_SER_THIS s[port].line_status.tsr_empty) {
|
||||||
if (gen_int) {
|
if (gen_int) {
|
||||||
BX_SER_THIS s[0].line_status.thr_empty = 1;
|
BX_SER_THIS s[port].line_status.thr_empty = 1;
|
||||||
raise_interrupt(0, BX_SER_INT_TXHOLD);
|
raise_interrupt(port, BX_SER_INT_TXHOLD);
|
||||||
}
|
}
|
||||||
bx_pc_system.activate_timer(BX_SER_THIS s[0].tx_timer_index,
|
bx_pc_system.activate_timer(BX_SER_THIS s[port].tx_timer_index,
|
||||||
(int) (1000000.0 / BX_SER_THIS s[0].baudrate *
|
(int) (1000000.0 / BX_SER_THIS s[port].baudrate *
|
||||||
(BX_SER_THIS s[0].line_cntl.wordlen_sel + 5)),
|
(BX_SER_THIS s[port].line_cntl.wordlen_sel + 5)),
|
||||||
0); /* not continuous */
|
0); /* not continuous */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -924,7 +949,20 @@ bx_serial_c::rx_timer(void)
|
|||||||
fd_set fds;
|
fd_set fds;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
int bdrate = BX_SER_THIS s[0].baudrate / (BX_SER_THIS s[0].line_cntl.wordlen_sel + 5);
|
Bit8u port = 0;
|
||||||
|
int timer_id;
|
||||||
|
|
||||||
|
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;
|
unsigned char chbuf = 0;
|
||||||
|
|
||||||
#if BX_HAVE_SELECT
|
#if BX_HAVE_SELECT
|
||||||
@ -940,8 +978,8 @@ bx_serial_c::rx_timer(void)
|
|||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
if (tty_id >= 0) FD_SET(tty_id, &fds);
|
if (tty_id >= 0) FD_SET(tty_id, &fds);
|
||||||
|
|
||||||
if ((BX_SER_THIS s[0].line_status.rxdata_ready == 0) ||
|
if ((BX_SER_THIS s[port].line_status.rxdata_ready == 0) ||
|
||||||
(BX_SER_THIS s[0].fifo_cntl.enable)) {
|
(BX_SER_THIS s[port].fifo_cntl.enable)) {
|
||||||
#if USE_RAW_SERIAL
|
#if USE_RAW_SERIAL
|
||||||
bx_bool rdy;
|
bx_bool rdy;
|
||||||
uint16 data;
|
uint16 data;
|
||||||
@ -949,7 +987,7 @@ bx_serial_c::rx_timer(void)
|
|||||||
data = BX_SER_THIS raw->receive();
|
data = BX_SER_THIS raw->receive();
|
||||||
if (data == C_BREAK) {
|
if (data == C_BREAK) {
|
||||||
BX_DEBUG(("got BREAK"));
|
BX_DEBUG(("got BREAK"));
|
||||||
BX_SER_THIS s[0].line_status.break_int = 1;
|
BX_SER_THIS s[port].line_status.break_int = 1;
|
||||||
rdy = 0;
|
rdy = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -962,11 +1000,11 @@ bx_serial_c::rx_timer(void)
|
|||||||
#else
|
#else
|
||||||
if (0) {
|
if (0) {
|
||||||
#endif
|
#endif
|
||||||
if (!BX_SER_THIS s[0].modem_cntl.local_loopback) {
|
if (!BX_SER_THIS s[port].modem_cntl.local_loopback) {
|
||||||
rx_fifo_enq(0, chbuf);
|
rx_fifo_enq(0, chbuf);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!BX_SER_THIS s[0].fifo_cntl.enable) {
|
if (!BX_SER_THIS s[port].fifo_cntl.enable) {
|
||||||
bdrate = (int) (1000000.0 / 100000); // Poll frequency is 100ms
|
bdrate = (int) (1000000.0 / 100000); // Poll frequency is 100ms
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -978,7 +1016,7 @@ bx_serial_c::rx_timer(void)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bx_pc_system.activate_timer(BX_SER_THIS s[0].rx_timer_index,
|
bx_pc_system.activate_timer(BX_SER_THIS s[port].rx_timer_index,
|
||||||
(int) (1000000.0 / bdrate),
|
(int) (1000000.0 / bdrate),
|
||||||
0); /* not continuous */
|
0); /* not continuous */
|
||||||
}
|
}
|
||||||
@ -996,6 +1034,19 @@ bx_serial_c::fifo_timer_handler(void *this_ptr)
|
|||||||
void
|
void
|
||||||
bx_serial_c::fifo_timer(void)
|
bx_serial_c::fifo_timer(void)
|
||||||
{
|
{
|
||||||
BX_SER_THIS s[0].line_status.rxdata_ready = 1;
|
Bit8u port = 0;
|
||||||
raise_interrupt(0, BX_SER_INT_FIFO);
|
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);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// $Id: serial.h,v 1.15 2003-11-16 08:21:10 vruppert Exp $
|
// $Id: serial.h,v 1.16 2004-01-17 15:51:09 vruppert Exp $
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
// Copyright (C) 2004 MandrakeSoft S.A.
|
||||||
//
|
//
|
||||||
// MandrakeSoft S.A.
|
// MandrakeSoft S.A.
|
||||||
// 43, rue d'Aboukir
|
// 43, rue d'Aboukir
|
||||||
@ -48,6 +48,17 @@
|
|||||||
#define BX_SER_RXPOLL 1
|
#define BX_SER_RXPOLL 1
|
||||||
#define BX_SER_RXWAIT 2
|
#define BX_SER_RXWAIT 2
|
||||||
|
|
||||||
|
#define BX_SER_THR 0
|
||||||
|
#define BX_SER_RBR 0
|
||||||
|
#define BX_SER_IER 1
|
||||||
|
#define BX_SER_IIR 2
|
||||||
|
#define BX_SER_FCR 2
|
||||||
|
#define BX_SER_LCR 3
|
||||||
|
#define BX_SER_MCR 4
|
||||||
|
#define BX_SER_LSR 5
|
||||||
|
#define BX_SER_MSR 6
|
||||||
|
#define BX_SER_SCR 7
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
BX_SER_INT_IER,
|
BX_SER_INT_IER,
|
||||||
BX_SER_INT_RXDATA,
|
BX_SER_INT_RXDATA,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// $Id: pc_system.cc,v 1.34 2003-06-07 19:16:51 vruppert Exp $
|
// $Id: pc_system.cc,v 1.35 2004-01-17 15:51:08 vruppert Exp $
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
// Copyright (C) 2002 MandrakeSoft S.A.
|
||||||
@ -78,6 +78,7 @@ bx_pc_system_c::bx_pc_system_c(void)
|
|||||||
currCountdown = NullTimerInterval;
|
currCountdown = NullTimerInterval;
|
||||||
currCountdownPeriod = NullTimerInterval;
|
currCountdownPeriod = NullTimerInterval;
|
||||||
numTimers = 1; // So far, only the nullTimer.
|
numTimers = 1; // So far, only the nullTimer.
|
||||||
|
triggeredTimer = 0;
|
||||||
lastTimeUsec = 0;
|
lastTimeUsec = 0;
|
||||||
usecSinceLast = 0;
|
usecSinceLast = 0;
|
||||||
}
|
}
|
||||||
@ -372,7 +373,9 @@ bx_pc_system_c::countdownEvent(void)
|
|||||||
// Call requested timer function. It may request a different
|
// Call requested timer function. It may request a different
|
||||||
// timer period or deactivate etc.
|
// timer period or deactivate etc.
|
||||||
if (triggered[i]) {
|
if (triggered[i]) {
|
||||||
|
triggeredTimer = i;
|
||||||
timer[i].funct(timer[i].this_ptr);
|
timer[i].funct(timer[i].this_ptr);
|
||||||
|
triggeredTimer = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// $Id: pc_system.h,v 1.25 2003-03-02 23:59:08 cbothamy Exp $
|
// $Id: pc_system.h,v 1.26 2004-01-17 15:51:08 vruppert Exp $
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
// Copyright (C) 2004 MandrakeSoft S.A.
|
||||||
//
|
//
|
||||||
// MandrakeSoft S.A.
|
// MandrakeSoft S.A.
|
||||||
// 43, rue d'Aboukir
|
// 43, rue d'Aboukir
|
||||||
@ -67,6 +67,7 @@ private:
|
|||||||
} timer[BX_MAX_TIMERS];
|
} timer[BX_MAX_TIMERS];
|
||||||
|
|
||||||
unsigned numTimers; // Number of currently allocated timers.
|
unsigned numTimers; // Number of currently allocated timers.
|
||||||
|
unsigned triggeredTimer; // ID of the actually triggered timer.
|
||||||
Bit32u currCountdown; // Current countdown ticks value (decrements to 0).
|
Bit32u currCountdown; // Current countdown ticks value (decrements to 0).
|
||||||
Bit32u currCountdownPeriod; // Length of current countdown period.
|
Bit32u currCountdownPeriod; // Length of current countdown period.
|
||||||
Bit64u ticksTotal; // Num ticks total since start of emulator execution.
|
Bit64u ticksTotal; // Num ticks total since start of emulator execution.
|
||||||
@ -105,6 +106,9 @@ public:
|
|||||||
void activate_timer( unsigned timer_index, Bit32u useconds,
|
void activate_timer( unsigned timer_index, Bit32u useconds,
|
||||||
bx_bool continuous );
|
bx_bool continuous );
|
||||||
void deactivate_timer( unsigned timer_index );
|
void deactivate_timer( unsigned timer_index );
|
||||||
|
unsigned triggeredTimerID(void) {
|
||||||
|
return triggeredTimer;
|
||||||
|
}
|
||||||
static BX_CPP_INLINE void tick1(void) {
|
static BX_CPP_INLINE void tick1(void) {
|
||||||
#if BX_SHOW_IPS
|
#if BX_SHOW_IPS
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user