- serial FIFO support (UART type 16550A) implemented
This commit is contained in:
parent
8d963231d3
commit
6866ca21d6
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: serial.cc,v 1.40 2003-10-31 17:23:56 vruppert Exp $
|
||||
// $Id: serial.cc,v 1.41 2003-11-09 00:14:43 vruppert Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
||||
@ -25,12 +25,11 @@
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
// Peter Grehan (grehan@iprg.nokia.com) coded most of this
|
||||
// serial emulation. Here's some notes from his implementation:
|
||||
|
||||
// Implement a single 16450, and allow terminal input/output to stdout
|
||||
// on some platforms. 16550/16550a/16552 should be easy: just add code
|
||||
// to handle a FIFO. I only did what was needed to get console output.
|
||||
// Peter Grehan (grehan@iprg.nokia.com) coded the original version of this
|
||||
// serial emulation. He implemented a single 8250, and allow terminal
|
||||
// input/output to stdout on FreeBSD.
|
||||
// The current version emulates a single 16550A with FIFO. Terminal
|
||||
// input/output now works on some more platforms.
|
||||
|
||||
|
||||
// Define BX_PLUGGABLE in files that can be compiled into plugins. For
|
||||
@ -94,6 +93,7 @@ bx_serial_c::bx_serial_c(void)
|
||||
for (int i=0; i<BX_SERIAL_MAXDEV; i++) {
|
||||
s[i].tx_timer_index = BX_NULL_TIMER_HANDLE;
|
||||
s[i].rx_timer_index = BX_NULL_TIMER_HANDLE;
|
||||
s[i].fifo_timer_index = BX_NULL_TIMER_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,10 +167,12 @@ bx_serial_c::init(void)
|
||||
BX_SER_THIS s[i].ls_ipending = 0;
|
||||
BX_SER_THIS s[i].ms_ipending = 0;
|
||||
BX_SER_THIS s[i].rx_ipending = 0;
|
||||
BX_SER_THIS s[i].fifo_ipending = 0;
|
||||
BX_SER_THIS s[i].ls_interrupt = 0;
|
||||
BX_SER_THIS s[i].ms_interrupt = 0;
|
||||
BX_SER_THIS s[i].rx_interrupt = 0;
|
||||
BX_SER_THIS s[i].tx_interrupt = 0;
|
||||
BX_SER_THIS s[i].fifo_interrupt = 0;
|
||||
|
||||
if (BX_SER_THIS s[i].tx_timer_index == BX_NULL_TIMER_HANDLE) {
|
||||
BX_SER_THIS s[i].tx_timer_index =
|
||||
@ -183,6 +185,11 @@ bx_serial_c::init(void)
|
||||
bx_pc_system.register_timer(this, rx_timer_handler, 0,
|
||||
0,0, "serial.rx"); // one-shot, inactive
|
||||
}
|
||||
if (BX_SER_THIS s[i].fifo_timer_index == BX_NULL_TIMER_HANDLE) {
|
||||
BX_SER_THIS s[i].fifo_timer_index =
|
||||
bx_pc_system.register_timer(this, fifo_timer_handler, 0,
|
||||
0,0, "serial.fifo"); // one-shot, inactive
|
||||
}
|
||||
BX_SER_THIS s[i].rx_pollstate = BX_SER_RXIDLE;
|
||||
|
||||
/* int enable: b0000 0000 */
|
||||
@ -194,14 +201,12 @@ bx_serial_c::init(void)
|
||||
/* int ID: b0000 0001 */
|
||||
BX_SER_THIS s[i].int_ident.ipending = 1;
|
||||
BX_SER_THIS s[i].int_ident.int_ID = 0;
|
||||
BX_SER_THIS s[i].int_ident.fifo_enabled = 0;
|
||||
|
||||
/* FIFO control: b0000 0000 */
|
||||
BX_SER_THIS s[i].fifo_cntl.enable = 0;
|
||||
BX_SER_THIS s[i].fifo_cntl.rxreset = 0;
|
||||
BX_SER_THIS s[i].fifo_cntl.txreset = 0;
|
||||
BX_SER_THIS s[i].fifo_cntl.dmamode = 0;
|
||||
BX_SER_THIS s[i].fifo_cntl.rxtrigger = 0;
|
||||
BX_SER_THIS s[i].rx_fifo_end = 0;
|
||||
BX_SER_THIS s[i].tx_fifo_end = 0;
|
||||
|
||||
/* Line Control reg: b0000 0000 */
|
||||
BX_SER_THIS s[i].line_cntl.wordlen_sel = 0;
|
||||
@ -267,7 +272,8 @@ bx_serial_c::lower_interrupt(Bit8u port)
|
||||
if ((BX_SER_THIS s[port].rx_interrupt == 0) &&
|
||||
(BX_SER_THIS s[port].tx_interrupt == 0) &&
|
||||
(BX_SER_THIS s[port].ls_interrupt == 0) &&
|
||||
(BX_SER_THIS s[port].ms_interrupt == 0)) {
|
||||
(BX_SER_THIS s[port].ms_interrupt == 0) &&
|
||||
(BX_SER_THIS s[port].fifo_interrupt == 0)) {
|
||||
DEV_pic_lower_irq(BX_SER_THIS s[port].IRQ);
|
||||
}
|
||||
}
|
||||
@ -311,6 +317,14 @@ bx_serial_c::raise_interrupt(Bit8u port, int type)
|
||||
gen_int = 1;
|
||||
}
|
||||
break;
|
||||
case BX_SER_INT_FIFO:
|
||||
if (BX_SER_THIS s[port].int_enable.rxdata_enable) {
|
||||
BX_SER_THIS s[port].fifo_interrupt = 1;
|
||||
gen_int = 1;
|
||||
} else {
|
||||
BX_SER_THIS s[port].fifo_ipending = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (gen_int && BX_SER_THIS s[port].modem_cntl.out2) {
|
||||
DEV_pic_raise_irq(BX_SER_THIS s[port].IRQ);
|
||||
@ -348,11 +362,27 @@ bx_serial_c::read(Bit32u address, unsigned io_len)
|
||||
if (BX_SER_THIS s[0].line_cntl.dlab) {
|
||||
val = BX_SER_THIS s[0].divisor_lsb;
|
||||
} else {
|
||||
val = BX_SER_THIS s[0].rxbuffer;
|
||||
BX_SER_THIS s[0].line_status.rxdata_ready = 0;
|
||||
BX_SER_THIS s[0].rx_interrupt = 0;
|
||||
BX_SER_THIS s[0].rx_ipending = 0;
|
||||
lower_interrupt(0);
|
||||
if (BX_SER_THIS s[0].fifo_cntl.enable) {
|
||||
val = BX_SER_THIS s[0].rx_fifo[0];
|
||||
if (BX_SER_THIS s[0].rx_fifo_end > 0) {
|
||||
memcpy(&BX_SER_THIS s[0].rx_fifo[0], &BX_SER_THIS s[0].rx_fifo[1], 15);
|
||||
BX_SER_THIS s[0].rx_fifo_end--;
|
||||
}
|
||||
if (BX_SER_THIS s[0].rx_fifo_end == 0) {
|
||||
BX_SER_THIS s[0].line_status.rxdata_ready = 0;
|
||||
BX_SER_THIS s[0].rx_interrupt = 0;
|
||||
BX_SER_THIS s[0].rx_ipending = 0;
|
||||
BX_SER_THIS s[0].fifo_interrupt = 0;
|
||||
BX_SER_THIS s[0].fifo_ipending = 0;
|
||||
lower_interrupt(0);
|
||||
}
|
||||
} else {
|
||||
val = BX_SER_THIS s[0].rxbuffer;
|
||||
BX_SER_THIS s[0].line_status.rxdata_ready = 0;
|
||||
BX_SER_THIS s[0].rx_interrupt = 0;
|
||||
BX_SER_THIS s[0].rx_ipending = 0;
|
||||
lower_interrupt(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -374,6 +404,9 @@ bx_serial_c::read(Bit32u address, unsigned io_len)
|
||||
if (BX_SER_THIS s[0].ls_interrupt) {
|
||||
BX_SER_THIS s[0].int_ident.int_ID = 0x3;
|
||||
BX_SER_THIS s[0].int_ident.ipending = 0;
|
||||
} else if (BX_SER_THIS s[0].fifo_interrupt) {
|
||||
BX_SER_THIS s[0].int_ident.int_ID = 0x6;
|
||||
BX_SER_THIS s[0].int_ident.ipending = 0;
|
||||
} else if (BX_SER_THIS s[0].rx_interrupt) {
|
||||
BX_SER_THIS s[0].int_ident.int_ID = 0x2;
|
||||
BX_SER_THIS s[0].int_ident.ipending = 0;
|
||||
@ -392,7 +425,7 @@ bx_serial_c::read(Bit32u address, unsigned io_len)
|
||||
|
||||
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.fifo_enabled << 6);
|
||||
(BX_SER_THIS s[0].fifo_cntl.enable ? 0xc0 : 0x00);
|
||||
break;
|
||||
|
||||
case 0x03FB: /* Line control register */
|
||||
@ -505,11 +538,23 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
||||
#endif // USE_RAW_SERIAL
|
||||
}
|
||||
} else {
|
||||
Bit8u bitmask = 0xff >> (3 - BX_SER_THIS s[0].line_cntl.wordlen_sel);
|
||||
if (BX_SER_THIS s[0].line_status.thr_empty) {
|
||||
Bit8u bitmask = 0xff >> (3 - BX_SER_THIS s[0].line_cntl.wordlen_sel);
|
||||
BX_SER_THIS s[0].thrbuffer = value & bitmask;
|
||||
if (BX_SER_THIS s[0].fifo_cntl.enable) {
|
||||
BX_SER_THIS s[0].tx_fifo[BX_SER_THIS s[0].tx_fifo_end++] = value & bitmask;
|
||||
} else {
|
||||
BX_SER_THIS s[0].thrbuffer = value & bitmask;
|
||||
}
|
||||
BX_SER_THIS s[0].line_status.thr_empty = 0;
|
||||
if (BX_SER_THIS s[0].line_status.tsr_empty) {
|
||||
BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].thrbuffer;
|
||||
if (BX_SER_THIS s[0].fifo_cntl.enable) {
|
||||
BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].tx_fifo[0];
|
||||
memcpy(&BX_SER_THIS s[0].tx_fifo[0], &BX_SER_THIS s[0].tx_fifo[1], 15);
|
||||
BX_SER_THIS s[0].line_status.thr_empty = (--BX_SER_THIS s[0].tx_fifo_end == 0);
|
||||
} else {
|
||||
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.tsr_empty = 0;
|
||||
raise_interrupt(0, BX_SER_INT_TXHOLD);
|
||||
bx_pc_system.activate_timer(BX_SER_THIS s[0].tx_timer_index,
|
||||
@ -517,12 +562,19 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
||||
(BX_SER_THIS s[0].line_cntl.wordlen_sel + 5)),
|
||||
0); /* not continuous */
|
||||
} else {
|
||||
BX_SER_THIS s[0].line_status.thr_empty = 0;
|
||||
BX_SER_THIS s[0].tx_interrupt = 0;
|
||||
lower_interrupt(0);
|
||||
}
|
||||
} else {
|
||||
BX_ERROR(("write to tx hold register when not empty"));
|
||||
if (BX_SER_THIS s[0].fifo_cntl.enable) {
|
||||
if (BX_SER_THIS s[0].tx_fifo_end < 16) {
|
||||
BX_SER_THIS s[0].tx_fifo[BX_SER_THIS s[0].tx_fifo_end++] = value & bitmask;
|
||||
} else {
|
||||
BX_ERROR(("com1: transmit FIFO overflow"));
|
||||
}
|
||||
} else {
|
||||
BX_ERROR(("write to tx hold register when not empty"));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -573,6 +625,11 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
||||
if (new_rx_ien != BX_SER_THIS s[0].int_enable.rxdata_enable) {
|
||||
BX_SER_THIS s[0].int_enable.rxdata_enable = new_rx_ien;
|
||||
if (BX_SER_THIS s[0].int_enable.rxdata_enable == 1) {
|
||||
if (BX_SER_THIS s[0].fifo_ipending == 1) {
|
||||
BX_SER_THIS s[0].fifo_interrupt = 1;
|
||||
BX_SER_THIS s[0].fifo_ipending = 0;
|
||||
gen_int = 1;
|
||||
}
|
||||
if (BX_SER_THIS s[0].rx_ipending == 1) {
|
||||
BX_SER_THIS s[0].rx_interrupt = 1;
|
||||
BX_SER_THIS s[0].rx_ipending = 0;
|
||||
@ -584,6 +641,11 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
||||
BX_SER_THIS s[0].rx_ipending = 1;
|
||||
lower_interrupt(0);
|
||||
}
|
||||
if (BX_SER_THIS s[0].fifo_interrupt == 1) {
|
||||
BX_SER_THIS s[0].fifo_interrupt = 0;
|
||||
BX_SER_THIS s[0].fifo_ipending = 1;
|
||||
lower_interrupt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (new_ls_ien != BX_SER_THIS s[0].int_enable.rxlstat_enable) {
|
||||
@ -607,7 +669,19 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
||||
break;
|
||||
|
||||
case 0x03FA: /* FIFO control register */
|
||||
/* Ignore until FIFO mode is supported... */
|
||||
if (!BX_SER_THIS s[0].fifo_cntl.enable && (value & 0x01)) {
|
||||
BX_INFO(("FIFO enabled"));
|
||||
BX_SER_THIS s[0].rx_fifo_end = 0;
|
||||
BX_SER_THIS s[0].tx_fifo_end = 0;
|
||||
}
|
||||
BX_SER_THIS s[0].fifo_cntl.enable = value & 0x01;
|
||||
if (value & 0x02) {
|
||||
BX_SER_THIS s[0].rx_fifo_end = 0;
|
||||
}
|
||||
if (value & 0x04) {
|
||||
BX_SER_THIS s[0].tx_fifo_end = 0;
|
||||
}
|
||||
BX_SER_THIS s[0].fifo_cntl.rxtrigger = (value & 0xc0) >> 6;
|
||||
break;
|
||||
|
||||
case 0x03FB: /* Line control register */
|
||||
@ -730,6 +804,56 @@ bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bx_serial_c::rx_fifo_enq(Bit8u port, Bit8u data)
|
||||
{
|
||||
bx_bool gen_int = 0;
|
||||
|
||||
if (BX_SER_THIS s[port].fifo_cntl.enable) {
|
||||
if (BX_SER_THIS s[port].rx_fifo_end == 16) {
|
||||
BX_ERROR(("com%d: receive FIFO overflow", port + 1));
|
||||
BX_SER_THIS s[port].line_status.overrun_error = 1;
|
||||
raise_interrupt(port, BX_SER_INT_RXLSTAT);
|
||||
} else {
|
||||
BX_SER_THIS s[port].rx_fifo[BX_SER_THIS s[0].rx_fifo_end++] = data;
|
||||
switch (BX_SER_THIS s[port].fifo_cntl.rxtrigger) {
|
||||
case 1:
|
||||
if (BX_SER_THIS s[0].rx_fifo_end == 4) gen_int = 1;
|
||||
break;
|
||||
case 2:
|
||||
if (BX_SER_THIS s[0].rx_fifo_end == 8) gen_int = 1;
|
||||
break;
|
||||
case 3:
|
||||
if (BX_SER_THIS s[0].rx_fifo_end == 14) gen_int = 1;
|
||||
break;
|
||||
default:
|
||||
gen_int = 1;
|
||||
}
|
||||
if (gen_int) {
|
||||
bx_pc_system.deactivate_timer(BX_SER_THIS s[0].fifo_timer_index);
|
||||
BX_SER_THIS s[port].line_status.rxdata_ready = 1;
|
||||
raise_interrupt(port, BX_SER_INT_RXDATA);
|
||||
} else {
|
||||
bx_pc_system.activate_timer(BX_SER_THIS s[0].fifo_timer_index,
|
||||
(int) (1000000.0 / BX_SER_THIS s[0].baudrate *
|
||||
(BX_SER_THIS s[0].line_cntl.wordlen_sel + 5) * 16),
|
||||
0); /* not continuous */
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (BX_SER_THIS s[port].line_status.rxdata_ready == 1) {
|
||||
BX_ERROR(("com%d: overrun error", port + 1));
|
||||
BX_SER_THIS s[port].line_status.overrun_error = 1;
|
||||
raise_interrupt(port, BX_SER_INT_RXLSTAT);
|
||||
}
|
||||
BX_SER_THIS s[port].rxbuffer = data;
|
||||
BX_SER_THIS s[port].line_status.rxdata_ready = 1;
|
||||
raise_interrupt(port, BX_SER_INT_RXDATA);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bx_serial_c::tx_timer_handler(void *this_ptr)
|
||||
{
|
||||
@ -742,14 +866,10 @@ bx_serial_c::tx_timer_handler(void *this_ptr)
|
||||
void
|
||||
bx_serial_c::tx_timer(void)
|
||||
{
|
||||
bx_bool gen_int = 0;
|
||||
|
||||
if (BX_SER_THIS s[0].modem_cntl.local_loopback) {
|
||||
if (BX_SER_THIS s[0].line_status.rxdata_ready == 1) {
|
||||
BX_SER_THIS s[0].line_status.overrun_error = 1;
|
||||
raise_interrupt(0, BX_SER_INT_RXLSTAT);
|
||||
}
|
||||
BX_SER_THIS s[0].rxbuffer = BX_SER_THIS s[0].tsrbuffer;
|
||||
BX_SER_THIS s[0].line_status.rxdata_ready = 1;
|
||||
raise_interrupt(0, BX_SER_INT_RXDATA);
|
||||
rx_fifo_enq(0, BX_SER_THIS s[0].tsrbuffer);
|
||||
} else {
|
||||
#if USE_RAW_SERIAL
|
||||
if (!BX_SER_THIS raw->ready_transmit())
|
||||
@ -762,16 +882,26 @@ bx_serial_c::tx_timer(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!BX_SER_THIS s[0].line_status.thr_empty) {
|
||||
BX_SER_THIS s[0].line_status.tsr_empty = 1;
|
||||
if (BX_SER_THIS s[0].fifo_cntl.enable && (BX_SER_THIS s[0].tx_fifo_end > 0)) {
|
||||
BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].tx_fifo[0];
|
||||
BX_SER_THIS s[0].line_status.tsr_empty = 0;
|
||||
memcpy(&BX_SER_THIS s[0].tx_fifo[0], &BX_SER_THIS s[0].tx_fifo[1], 15);
|
||||
gen_int = (--BX_SER_THIS s[0].tx_fifo_end == 0);
|
||||
} else 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].line_status.thr_empty = 1;
|
||||
raise_interrupt(0, BX_SER_INT_TXHOLD);
|
||||
BX_SER_THIS s[0].line_status.tsr_empty = 0;
|
||||
gen_int = 1;
|
||||
}
|
||||
if (!BX_SER_THIS s[0].line_status.tsr_empty) {
|
||||
if (gen_int) {
|
||||
BX_SER_THIS s[0].line_status.thr_empty = 1;
|
||||
raise_interrupt(0, BX_SER_INT_TXHOLD);
|
||||
}
|
||||
bx_pc_system.activate_timer(BX_SER_THIS s[0].tx_timer_index,
|
||||
(int) (1000000.0 / BX_SER_THIS s[0].baudrate *
|
||||
(BX_SER_THIS s[0].line_cntl.wordlen_sel + 5)),
|
||||
0); /* not continuous */
|
||||
} else {
|
||||
BX_SER_THIS s[0].line_status.tsr_empty = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -810,7 +940,8 @@ bx_serial_c::rx_timer(void)
|
||||
FD_ZERO(&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[0].line_status.rxdata_ready == 0) ||
|
||||
(BX_SER_THIS s[0].fifo_cntl.enable)) {
|
||||
#if USE_RAW_SERIAL
|
||||
bx_bool rdy;
|
||||
uint16 data;
|
||||
@ -832,16 +963,12 @@ bx_serial_c::rx_timer(void)
|
||||
if (0) {
|
||||
#endif
|
||||
if (!BX_SER_THIS s[0].modem_cntl.local_loopback) {
|
||||
if (BX_SER_THIS s[0].line_status.rxdata_ready == 1) {
|
||||
BX_SER_THIS s[0].line_status.overrun_error = 1;
|
||||
raise_interrupt(0, BX_SER_INT_RXLSTAT);
|
||||
}
|
||||
BX_SER_THIS s[0].rxbuffer = chbuf;
|
||||
BX_SER_THIS s[0].line_status.rxdata_ready = 1;
|
||||
raise_interrupt(0, BX_SER_INT_RXDATA);
|
||||
rx_fifo_enq(0, chbuf);
|
||||
}
|
||||
} else {
|
||||
bdrate = (int) (1000000.0 / 100000); // Poll frequency is 100ms
|
||||
if (!BX_SER_THIS s[0].fifo_cntl.enable) {
|
||||
bdrate = (int) (1000000.0 / 100000); // Poll frequency is 100ms
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Poll at 4x baud rate to see if the next-char can
|
||||
@ -855,3 +982,20 @@ bx_serial_c::rx_timer(void)
|
||||
(int) (1000000.0 / bdrate),
|
||||
0); /* not continuous */
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bx_serial_c::fifo_timer_handler(void *this_ptr)
|
||||
{
|
||||
bx_serial_c *class_ptr = (bx_serial_c *) this_ptr;
|
||||
|
||||
class_ptr->fifo_timer();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bx_serial_c::fifo_timer(void)
|
||||
{
|
||||
BX_SER_THIS s[0].line_status.rxdata_ready = 1;
|
||||
raise_interrupt(0, BX_SER_INT_FIFO);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// $Id: serial.h,v 1.13 2003-10-31 17:23:56 vruppert Exp $
|
||||
// $Id: serial.h,v 1.14 2003-11-09 00:14:43 vruppert Exp $
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2002 MandrakeSoft S.A.
|
||||
@ -54,6 +54,7 @@ enum {
|
||||
BX_SER_INT_TXHOLD,
|
||||
BX_SER_INT_RXLSTAT,
|
||||
BX_SER_INT_MODSTAT,
|
||||
BX_SER_INT_FIFO
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@ -64,17 +65,23 @@ typedef struct {
|
||||
bx_bool ms_interrupt;
|
||||
bx_bool rx_interrupt;
|
||||
bx_bool tx_interrupt;
|
||||
bx_bool fifo_interrupt;
|
||||
bx_bool ls_ipending;
|
||||
bx_bool ms_ipending;
|
||||
bx_bool rx_ipending;
|
||||
bx_bool fifo_ipending;
|
||||
|
||||
Bit8u IRQ;
|
||||
|
||||
Bit8u rx_fifo_end;
|
||||
Bit8u tx_fifo_end;
|
||||
|
||||
int baudrate;
|
||||
int tx_timer_index;
|
||||
|
||||
int rx_pollstate;
|
||||
int rx_timer_index;
|
||||
int fifo_timer_index;
|
||||
|
||||
#define RX_CB_SIZE 80
|
||||
int rx_cb_start;
|
||||
@ -97,14 +104,10 @@ typedef struct {
|
||||
struct {
|
||||
bx_bool ipending; /* 0=interrupt pending */
|
||||
Bit8u int_ID; /* 3-bit interrupt ID */
|
||||
Bit8u fifo_enabled; /* 2-bit, set to b11 when FCR0 enabled */
|
||||
} int_ident;
|
||||
/* FIFO Control Register (w/o) */
|
||||
struct {
|
||||
bx_bool enable; /* 1=enable tx and rx FIFOs */
|
||||
bx_bool rxreset; /* 1=clear rx fifo. self-clearing */
|
||||
bx_bool txreset; /* 1=clear tx fifo. self-clearing */
|
||||
bx_bool dmamode; /* 1=DMA mode 1 (unused on PC ?) */
|
||||
Bit8u rxtrigger; /* 2-bit code for rx fifo trigger level */
|
||||
} fifo_cntl;
|
||||
/* Line Control Register (r/w) */
|
||||
@ -150,6 +153,8 @@ typedef struct {
|
||||
|
||||
Bit8u scratch; /* Scratch Register (r/w) */
|
||||
Bit8u tsrbuffer; /* transmit shift register (internal) */
|
||||
Bit8u rx_fifo[16]; /* receive FIFO (internal) */
|
||||
Bit8u tx_fifo[16]; /* transmit FIFO (internal) */
|
||||
Bit8u divisor_lsb; /* Divisor latch, least-sig. byte */
|
||||
Bit8u divisor_msb; /* Divisor latch, most-sig. byte */
|
||||
} bx_serial_t;
|
||||
@ -172,12 +177,17 @@ private:
|
||||
static void lower_interrupt(Bit8u port);
|
||||
static void raise_interrupt(Bit8u port, int type);
|
||||
|
||||
static void rx_fifo_enq(Bit8u port, Bit8u data);
|
||||
|
||||
static void tx_timer_handler(void *);
|
||||
BX_SER_SMF void tx_timer(void);
|
||||
|
||||
static void rx_timer_handler(void *);
|
||||
BX_SER_SMF void rx_timer(void);
|
||||
|
||||
static void fifo_timer_handler(void *);
|
||||
BX_SER_SMF void fifo_timer(void);
|
||||
|
||||
static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
|
||||
static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
|
||||
#if !BX_USE_SER_SMF
|
||||
|
Loading…
x
Reference in New Issue
Block a user