- MCR bit 3 (OUT2) controls the serial interrupt generation, but has no effect

on the IIR (only depends on the IER).
- IER write code rewritten. The "THR empty" interrupt will be generated immediately
  after enabling this interrupt reason.
This commit is contained in:
Volker Ruppert 2003-10-28 18:40:00 +00:00
parent 78e2cc110d
commit fbba69380b
2 changed files with 60 additions and 58 deletions

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: serial.cc,v 1.37 2003-10-24 11:16:25 danielg4 Exp $ // $Id: serial.cc,v 1.38 2003-10-28 18:40:00 vruppert Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2002 MandrakeSoft S.A. // Copyright (C) 2002 MandrakeSoft S.A.
@ -159,7 +159,6 @@ bx_serial_c::init(void)
BX_SER_THIS s[i].ls_ipending = 0; BX_SER_THIS s[i].ls_ipending = 0;
BX_SER_THIS s[i].ms_ipending = 0; BX_SER_THIS s[i].ms_ipending = 0;
BX_SER_THIS s[i].rx_ipending = 0; BX_SER_THIS s[i].rx_ipending = 0;
BX_SER_THIS s[i].tx_ipending = 0;
BX_SER_THIS s[i].ls_interrupt = 0; BX_SER_THIS s[i].ls_interrupt = 0;
BX_SER_THIS s[i].ms_interrupt = 0; BX_SER_THIS s[i].ms_interrupt = 0;
BX_SER_THIS s[i].rx_interrupt = 0; BX_SER_THIS s[i].rx_interrupt = 0;
@ -337,7 +336,6 @@ bx_serial_c::read(Bit32u address, unsigned io_len)
} }
BX_SER_THIS s[0].tx_interrupt = 0; BX_SER_THIS s[0].tx_interrupt = 0;
BX_SER_THIS s[0].tx_ipending = 0;
val = BX_SER_THIS s[0].int_ident.ipending | val = BX_SER_THIS s[0].int_ident.ipending |
(BX_SER_THIS s[0].int_ident.int_ID << 1) | (BX_SER_THIS s[0].int_ident.int_ID << 1) |
@ -442,6 +440,7 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
UNUSED(this_ptr); UNUSED(this_ptr);
#endif // !BX_USE_SER_SMF #endif // !BX_USE_SER_SMF
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 gen_int = 0; bx_bool gen_int = 0;
/* SERIAL PORT 1 */ /* SERIAL PORT 1 */
@ -469,12 +468,10 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
if (BX_SER_THIS s[0].line_status.tsr_empty) { if (BX_SER_THIS s[0].line_status.tsr_empty) {
BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].thrbuffer; BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].thrbuffer;
BX_SER_THIS s[0].line_status.tsr_empty = 0; BX_SER_THIS s[0].line_status.tsr_empty = 0;
if (BX_SER_THIS s[0].modem_cntl.out2) { if (BX_SER_THIS s[0].int_enable.txhold_enable) {
if (BX_SER_THIS s[0].int_enable.txhold_enable) { BX_SER_THIS s[0].tx_interrupt = 1;
BX_SER_THIS s[0].tx_interrupt = 1; if (BX_SER_THIS s[0].modem_cntl.out2) {
DEV_pic_raise_irq(4); DEV_pic_raise_irq(4);
} else {
BX_SER_THIS s[0].tx_ipending = 1;
} }
} }
bx_pc_system.activate_timer(BX_SER_THIS s[0].tx_timer_index, bx_pc_system.activate_timer(BX_SER_THIS s[0].tx_timer_index,
@ -490,7 +487,6 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
DEV_pic_lower_irq(4); DEV_pic_lower_irq(4);
} }
BX_SER_THIS s[0].tx_interrupt = 0; BX_SER_THIS s[0].tx_interrupt = 0;
BX_SER_THIS s[0].tx_ipending = 0;
} }
} else { } else {
BX_ERROR(("write to tx hold register when not empty")); BX_ERROR(("write to tx hold register when not empty"));
@ -511,35 +507,47 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
#endif // USE_RAW_SERIAL #endif // USE_RAW_SERIAL
} }
} else { } else {
BX_SER_THIS s[0].int_enable.rxdata_enable = value & 0x01; new_rx_ien = value & 0x01;
BX_SER_THIS s[0].int_enable.txhold_enable = (value & 0x02) >> 1; new_tx_ien = (value & 0x02) >> 1;
BX_SER_THIS s[0].int_enable.rxlstat_enable = (value & 0x04) >> 2; new_ls_ien = (value & 0x04) >> 2;
BX_SER_THIS s[0].int_enable.modstat_enable = (value & 0x08) >> 3; new_ms_ien = (value & 0x08) >> 3;
if ((BX_SER_THIS s[0].ms_ipending == 1) && if (new_ms_ien != BX_SER_THIS s[0].int_enable.modstat_enable) {
(BX_SER_THIS s[0].int_enable.modstat_enable == 1)) { BX_SER_THIS s[0].int_enable.modstat_enable = new_ms_ien;
BX_SER_THIS s[0].ms_interrupt = 1; if ((BX_SER_THIS s[0].ms_ipending == 1) &&
BX_SER_THIS s[0].ms_ipending = 0; (BX_SER_THIS s[0].int_enable.modstat_enable == 1)) {
gen_int = 1; BX_SER_THIS s[0].ms_interrupt = 1;
BX_SER_THIS s[0].ms_ipending = 0;
gen_int = 1;
}
} }
if ((BX_SER_THIS s[0].tx_ipending == 1) && if (new_tx_ien != BX_SER_THIS s[0].int_enable.txhold_enable) {
(BX_SER_THIS s[0].int_enable.txhold_enable == 1)) { BX_SER_THIS s[0].int_enable.txhold_enable = new_tx_ien;
BX_SER_THIS s[0].tx_interrupt = 1; if (BX_SER_THIS s[0].int_enable.txhold_enable == 1) {
BX_SER_THIS s[0].tx_ipending = 0; BX_SER_THIS s[0].tx_interrupt = BX_SER_THIS s[0].line_status.thr_empty;
gen_int = 1; if (BX_SER_THIS s[0].tx_interrupt) gen_int = 1;
} else {
BX_SER_THIS s[0].tx_interrupt = 0;
}
} }
if ((BX_SER_THIS s[0].rx_ipending == 1) && if (new_rx_ien != BX_SER_THIS s[0].int_enable.rxdata_enable) {
(BX_SER_THIS s[0].int_enable.rxdata_enable == 1)) { BX_SER_THIS s[0].int_enable.rxdata_enable = new_rx_ien;
BX_SER_THIS s[0].rx_interrupt = 1; if ((BX_SER_THIS s[0].rx_ipending == 1) &&
BX_SER_THIS s[0].rx_ipending = 0; (BX_SER_THIS s[0].int_enable.rxdata_enable == 1)) {
gen_int = 1; BX_SER_THIS s[0].rx_interrupt = 1;
if ((BX_SER_THIS s[0].ls_ipending == 1) && BX_SER_THIS s[0].rx_ipending = 0;
(BX_SER_THIS s[0].int_enable.rxlstat_enable == 1)) { gen_int = 1;
BX_SER_THIS s[0].ls_interrupt = 1; }
BX_SER_THIS s[0].ls_ipending = 0;
gen_int = 1;
} }
if (new_ls_ien != BX_SER_THIS s[0].int_enable.rxlstat_enable) {
BX_SER_THIS s[0].int_enable.rxlstat_enable = new_ls_ien;
if ((BX_SER_THIS s[0].ls_ipending == 1) &&
(BX_SER_THIS s[0].int_enable.rxlstat_enable == 1)) {
BX_SER_THIS s[0].ls_interrupt = 1;
BX_SER_THIS s[0].ls_ipending = 0;
gen_int = 1;
}
} }
if (gen_int == 1) if ((gen_int == 1) && BX_SER_THIS s[0].modem_cntl.out2)
DEV_pic_raise_irq(4); DEV_pic_raise_irq(4);
} }
break; break;
@ -691,19 +699,17 @@ bx_serial_c::tx_timer(void)
BX_SER_THIS s[0].line_status.overrun_error = 1; BX_SER_THIS s[0].line_status.overrun_error = 1;
BX_SER_THIS s[0].rxbuffer = BX_SER_THIS s[0].tsrbuffer; BX_SER_THIS s[0].rxbuffer = BX_SER_THIS s[0].tsrbuffer;
BX_SER_THIS s[0].line_status.rxdata_ready = 1; BX_SER_THIS s[0].line_status.rxdata_ready = 1;
if (BX_SER_THIS s[0].modem_cntl.out2) { if (BX_SER_THIS s[0].int_enable.rxdata_enable) {
if (BX_SER_THIS s[0].int_enable.rxdata_enable) { gen_int = 1;
gen_int = 1; BX_SER_THIS s[0].rx_interrupt = 1;
BX_SER_THIS s[0].rx_interrupt = 1; } else {
} else { BX_SER_THIS s[0].rx_ipending = 1;
BX_SER_THIS s[0].rx_ipending = 1; }
} if (BX_SER_THIS s[0].int_enable.rxlstat_enable) {
if (BX_SER_THIS s[0].int_enable.rxlstat_enable) { gen_int = 1;
gen_int = 1; BX_SER_THIS s[0].ls_interrupt = 1;
BX_SER_THIS s[0].ls_interrupt = 1; } else {
} else { BX_SER_THIS s[0].ls_ipending = 1;
BX_SER_THIS s[0].ls_ipending = 1;
}
} }
} else { } else {
#if USE_RAW_SERIAL #if USE_RAW_SERIAL
@ -720,13 +726,9 @@ bx_serial_c::tx_timer(void)
if (!BX_SER_THIS s[0].line_status.thr_empty) { if (!BX_SER_THIS s[0].line_status.thr_empty) {
BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].thrbuffer; BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].thrbuffer;
BX_SER_THIS s[0].line_status.thr_empty = 1; BX_SER_THIS s[0].line_status.thr_empty = 1;
if (BX_SER_THIS s[0].modem_cntl.out2) { if (BX_SER_THIS s[0].int_enable.txhold_enable) {
if (BX_SER_THIS s[0].int_enable.txhold_enable) { gen_int = 1;
gen_int = 1; BX_SER_THIS s[0].tx_interrupt = 1;
BX_SER_THIS s[0].tx_interrupt = 1;
} else {
BX_SER_THIS s[0].tx_ipending = 1;
}
} }
bx_pc_system.activate_timer(BX_SER_THIS s[0].tx_timer_index, bx_pc_system.activate_timer(BX_SER_THIS s[0].tx_timer_index,
(int) (1000000.0 / BX_SER_THIS s[0].baudrate * (int) (1000000.0 / BX_SER_THIS s[0].baudrate *
@ -736,7 +738,7 @@ bx_serial_c::tx_timer(void)
BX_SER_THIS s[0].line_status.tsr_empty = 1; BX_SER_THIS s[0].line_status.tsr_empty = 1;
} }
if (gen_int) { if ((gen_int == 1) && BX_SER_THIS s[0].modem_cntl.out2) {
DEV_pic_raise_irq(4); DEV_pic_raise_irq(4);
} }
} }
@ -803,7 +805,8 @@ bx_serial_c::rx_timer(void)
BX_SER_THIS s[0].line_status.rxdata_ready = 1; BX_SER_THIS s[0].line_status.rxdata_ready = 1;
if (BX_SER_THIS s[0].int_enable.rxdata_enable) { if (BX_SER_THIS s[0].int_enable.rxdata_enable) {
BX_SER_THIS s[0].rx_interrupt = 1; BX_SER_THIS s[0].rx_interrupt = 1;
DEV_pic_raise_irq(4); if (BX_SER_THIS s[0].modem_cntl.out2)
DEV_pic_raise_irq(4);
} else { } else {
BX_SER_THIS s[0].rx_ipending = 1; BX_SER_THIS s[0].rx_ipending = 1;
} }

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// $Id: serial.h,v 1.10 2003-09-14 20:16:25 vruppert Exp $ // $Id: serial.h,v 1.11 2003-10-28 18:40:00 vruppert Exp $
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2002 MandrakeSoft S.A. // Copyright (C) 2002 MandrakeSoft S.A.
@ -60,7 +60,6 @@ typedef struct {
bx_bool ls_ipending; bx_bool ls_ipending;
bx_bool ms_ipending; bx_bool ms_ipending;
bx_bool rx_ipending; bx_bool rx_ipending;
bx_bool tx_ipending;
int baudrate; int baudrate;
int tx_timer_index; int tx_timer_index;