diff --git a/src/86box.h b/src/86box.h index e9fa19a25..a85123e48 100644 --- a/src/86box.h +++ b/src/86box.h @@ -8,7 +8,7 @@ * * Main include file for the application. * - * Version: @(#)86box.h 1.0.30 2019/10/23 + * Version: @(#)86box.h 1.0.31 2019/10/31 * * Authors: Miran Grca, *f Fred N. van Kempen, @@ -30,8 +30,8 @@ #define EMU_NAME "86Box" #define EMU_NAME_W L"86Box" #ifdef RELEASE_BUILD -#define EMU_VERSION "2.02" -#define EMU_VERSION_W L"2.02" +#define EMU_VERSION "2.03" +#define EMU_VERSION_W L"2.03" #else #define EMU_VERSION "2.10" #define EMU_VERSION_W L"2.10" diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index ffa6a8a0c..bf712bcc8 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -10,13 +10,13 @@ * word 0 - base address * word 1 - bits 1-15 = byte count, bit 31 = end of transfer * - * Version: @(#)hdc_ide_sff8038i.c 1.0.0 2019/05/12 + * Version: @(#)hdc_ide_sff8038i.c 1.0.1 2019/10/30 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -371,12 +371,12 @@ sff_bus_master_set_irq(int channel, void *priv) channel &= 0x01; if (dev->status & 0x04) { if (channel && pci_use_mirq(0)) - pci_set_mirq(0); + pci_set_mirq(0, 0); else picint(1 << (14 + channel)); } else { if ((channel & 1) && pci_use_mirq(0)) - pci_clear_mirq(0); + pci_clear_mirq(0, 0); else picintc(1 << (14 + channel)); } diff --git a/src/keyboard.h b/src/keyboard.h index 607136757..78cd50a86 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -8,7 +8,7 @@ * * Definitions for the keyboard interface. * - * Version: @(#)keyboard.h 1.0.18 2019/03/05 + * Version: @(#)keyboard.h 1.0.19 2019/10/30 * * Authors: Sarah Walker, * Miran Grca, @@ -103,6 +103,7 @@ extern void keyboard_at_adddata_mouse(uint8_t val); extern void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val,void *), void *); extern uint8_t keyboard_at_get_mouse_scan(void); extern void keyboard_at_set_mouse_scan(uint8_t val); +extern void keyboard_at_reset(void); #ifdef __cplusplus } diff --git a/src/keyboard_at.c b/src/keyboard_at.c index dfe28a53b..34b8cbcd5 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -8,7 +8,7 @@ * * Intel 8042 (AT keyboard controller) emulation. * - * Version: @(#)keyboard_at.c 1.0.43 2019/03/05 + * Version: @(#)keyboard_at.c 1.0.44 2019/10/30 * * Authors: Sarah Walker, * Miran Grca, @@ -2298,6 +2298,15 @@ kbd_reset(void *priv) } +/* Reset the AT keyboard - this is needed for the PCI TRC and is done + until a better solution is found. */ +void +keyboard_at_reset(void) +{ + kbd_reset(SavedKbd); +} + + static void kbd_close(void *priv) { diff --git a/src/mouse_serial.c b/src/mouse_serial.c index f2038c368..c96a7598d 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -10,7 +10,7 @@ * * TODO: Add the Genius Serial Mouse. * - * Version: @(#)mouse_serial.c 1.0.28 2019/03/23 + * Version: @(#)mouse_serial.c 1.0.29 2019/10/31 * * Author: Fred N. van Kempen, */ @@ -112,10 +112,7 @@ sermouse_timer_on(mouse_t *dev, double period, int report) enabled = &dev->command_enabled; } - if (*enabled) - timer_advance_u64(timer, (uint64_t) (period * (double)TIMER_USEC)); - else - timer_set_delay_u64(timer, (uint64_t) (period * (double)TIMER_USEC)); + timer_on_auto(timer, period); *enabled = 1; } @@ -175,7 +172,7 @@ sermouse_callback(struct serial_s *serial, void *priv) if (dev->id[0] != 'H') dev->format = 7; dev->transmit_period = sermouse_transmit_period(dev, 1200, -1); - timer_disable(&dev->command_timer); + timer_stop(&dev->command_timer); sub_cycles(ISA_CYCLES(8)); #ifdef USE_NEW_DYNAREC sermouse_timer_on(dev, 5000.0, 0); @@ -367,7 +364,7 @@ sermouse_command_pos_check(mouse_t *dev, int len) if (++dev->command_pos == len) sermouse_command_phase_idle(dev); else - timer_advance_u64(&dev->command_timer, (uint64_t) (dev->transmit_period * (double)TIMER_USEC)); + timer_on_auto(&dev->command_timer, dev->transmit_period); } @@ -434,6 +431,8 @@ sermouse_update_data(mouse_t *dev) dev->lastb = dev->oldb; + mouse_serial_log("sermouse_update_data(): ret = %i\n", ret); + return ret; } @@ -585,8 +584,6 @@ ltsermouse_prompt_mode(mouse_t *dev, int prompt) dev->status &= 0xBF; if (prompt) dev->status |= 0x40; - /* timer_disable(&dev->report_timer); - dev->report_enabled = 0; */ } @@ -595,7 +592,7 @@ ltsermouse_command_phase(mouse_t *dev, int phase) { dev->command_pos = 0; dev->command_phase = phase; - timer_disable(&dev->command_timer); + timer_stop(&dev->command_timer); sermouse_timer_on(dev, dev->transmit_period, 0); } @@ -604,7 +601,7 @@ static void ltsermouse_set_report_period(mouse_t *dev, int rps) { dev->report_period = sermouse_transmit_period(dev, 9600, rps); - timer_disable(&dev->report_timer); + timer_stop(&dev->report_timer); sermouse_timer_on(dev, dev->report_period, 1); ltsermouse_prompt_mode(dev, 0); dev->report_phase = REPORT_PHASE_PREPARE; @@ -681,7 +678,7 @@ ltsermouse_write(struct serial_s *serial, void *priv, uint8_t data) case 0x4F: ltsermouse_prompt_mode(dev, 0); dev->report_period = 0; - timer_disable(&dev->report_timer); + timer_stop(&dev->report_timer); dev->report_phase = REPORT_PHASE_PREPARE; sermouse_report_timer((void *) dev); break; @@ -726,7 +723,7 @@ sermouse_speed_changed(void *priv) mouse_t *dev = (mouse_t *)priv; if (dev->report_enabled) { - timer_disable(&dev->report_timer); + timer_stop(&dev->report_timer); if (dev->report_phase == REPORT_PHASE_TRANSMIT) sermouse_timer_on(dev, dev->transmit_period, 1); else @@ -734,7 +731,7 @@ sermouse_speed_changed(void *priv) } if (dev->command_enabled) { - timer_disable(&dev->command_timer); + timer_stop(&dev->command_timer); sermouse_timer_on(dev, dev->transmit_period, 0); } } diff --git a/src/pci.c b/src/pci.c index ccfc4d312..1e27becdf 100644 --- a/src/pci.c +++ b/src/pci.c @@ -8,15 +8,15 @@ * * Implementation the PCI bus. * - * Version: @(#)pci.c 1.0.1 2018/11/05 + * Version: @(#)pci.c 1.0.3 2019/10/30 * * Authors: Miran Grca, * Fred N. van Kempen, * Sarah Walker, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2019 Sarah Walker. */ #include #include @@ -321,10 +321,9 @@ pci_use_mirq(uint8_t mirq) void -pci_set_mirq(uint8_t mirq) +pci_set_mirq(uint8_t mirq, int level) { uint8_t irq_line = 0; - uint8_t level = 0; if (! pci_mirqs[mirq].enabled) { pci_log("pci_set_mirq(%02X): MIRQ0 disabled\n", mirq); @@ -339,20 +338,21 @@ pci_set_mirq(uint8_t mirq) irq_line = pci_mirqs[mirq].irq_line; pci_log("pci_set_mirq(%02X): Using IRQ %i\n", mirq, irq_line); - if (pci_irq_is_level(irq_line) && - (pci_irq_hold[irq_line] & (1ULL << (0x1E + mirq)))) { + if (level && (pci_irq_hold[irq_line] & (1ULL << (0x1E + mirq)))) { /* IRQ already held, do nothing. */ pci_log("pci_set_mirq(%02X): MIRQ is already holding the IRQ\n", mirq); return; } pci_log("pci_set_mirq(%02X): MIRQ not yet holding the IRQ\n", mirq); - level = pci_irq_is_level(irq_line); if (!level || !pci_irq_hold[irq_line]) { pci_log("pci_set_mirq(%02X): Issuing %s-triggered IRQ (%sheld)\n", mirq, level ? "level" : "edge", pci_irq_hold[irq_line] ? "" : "not "); /* Only raise the interrupt if it's edge-triggered or level-triggered and not yet being held. */ - picintlevel(1 << irq_line); + if (level) + picintlevel(1 << irq_line); + else + picint(1 << irq_line); } else if (level && pci_irq_hold[irq_line]) { pci_log("pci_set_mirq(%02X): IRQ line already being held\n", mirq); } @@ -376,7 +376,6 @@ pci_set_irq(uint8_t card, uint8_t pci_int) uint8_t irq_line = 0; uint8_t level = 0; - if (! last_pci_card) { pci_log("pci_set_irq(%02X, %02X): No PCI slots (how are we even here?!)\n", card, pci_int); return; @@ -418,9 +417,9 @@ pci_set_irq(uint8_t card, uint8_t pci_int) pci_log("pci_set_irq(%02X, %02X): Card not yet holding the IRQ\n", card, pci_int); if (pci_type & PCI_NO_IRQ_STEERING) - level = 0; + level = 0; /* PCI without IRQ steering - IRQ always edge. */ else - level = pci_irq_is_level(irq_line); + level = 1; /* PCI with IRQ steering - IRQ always level per the Intel datasheets. */ if (!level || !pci_irq_hold[irq_line]) { pci_log("pci_set_irq(%02X, %02X): Issuing %s-triggered IRQ (%sheld)\n", card, pci_int, level ? "level" : "edge", pci_irq_hold[irq_line] ? "" : "not "); @@ -444,10 +443,9 @@ pci_set_irq(uint8_t card, uint8_t pci_int) void -pci_clear_mirq(uint8_t mirq) +pci_clear_mirq(uint8_t mirq, int level) { uint8_t irq_line = 0; - uint8_t level = 0; if (mirq > 1) { pci_log("pci_clear_mirq(%02X): Invalid MIRQ\n", mirq); @@ -467,14 +465,12 @@ pci_clear_mirq(uint8_t mirq) irq_line = pci_mirqs[mirq].irq_line; pci_log("pci_clear_mirq(%02X): Using IRQ %i\n", mirq, irq_line); - if (pci_irq_is_level(irq_line) && - !(pci_irq_hold[irq_line] & (1ULL << (0x1E + mirq)))) { + if (level && !(pci_irq_hold[irq_line] & (1ULL << (0x1E + mirq)))) { /* IRQ not held, do nothing. */ pci_log("pci_clear_mirq(%02X): MIRQ is not holding the IRQ\n", mirq); return; } - level = pci_irq_is_level(irq_line); if (level) { pci_log("pci_clear_mirq(%02X): Releasing this MIRQ's hold on the IRQ\n", mirq); pci_irq_hold[irq_line] &= ~(1 << (0x1E + mirq)); @@ -543,9 +539,9 @@ pci_clear_irq(uint8_t card, uint8_t pci_int) } if (pci_type & PCI_NO_IRQ_STEERING) - level = 0; + level = 0; /* PCI without IRQ steering - IRQ always edge. */ else - level = pci_irq_is_level(irq_line); + level = 1; /* PCI with IRQ steering - IRQ always level per the Intel datasheets. */ if (level) { pci_log("pci_clear_irq(%02X, %02X): Releasing this card's hold on the IRQ\n", card, pci_int); pci_irq_hold[irq_line] &= ~(1 << card); @@ -624,6 +620,7 @@ trc_reset(uint8_t val) flushmmucache(); pci_reset(); + keyboard_at_reset(); } resetx86(); diff --git a/src/pci.h b/src/pci.h index 4476a970c..be7347757 100644 --- a/src/pci.h +++ b/src/pci.h @@ -8,15 +8,15 @@ * * Definitions for the PCI handler module. * - * Version: @(#)pci.h 1.0.0 2018/10/21 + * Version: @(#)pci.h 1.0.1 2019/10/30 * * Authors: Miran Grca, * Fred N. van Kempen, * Sarah Walker, * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2019 Sarah Walker. */ #ifndef EMU_PCI_H # define EMU_PCI_H @@ -76,9 +76,9 @@ extern uint8_t pci_use_mirq(uint8_t mirq); extern int pci_irq_is_level(int irq); -extern void pci_set_mirq(uint8_t mirq); +extern void pci_set_mirq(uint8_t mirq, int level); extern void pci_set_irq(uint8_t card, uint8_t pci_int); -extern void pci_clear_mirq(uint8_t mirq); +extern void pci_clear_mirq(uint8_t mirq, int level); extern void pci_clear_irq(uint8_t card, uint8_t pci_int); extern void pci_reset(void); diff --git a/src/serial.c b/src/serial.c index 6761c04d3..51297a64b 100644 --- a/src/serial.c +++ b/src/serial.c @@ -8,7 +8,9 @@ * * NS8250/16450/16550 UART emulation. * - * Version: @(#)serial.h 1.0.11 2019/10/11 + * Now passes all the AMIDIAG tests. + * + * Version: @(#)serial.h 1.0.13 2019/10/31 * * Author: Sarah Walker, * Miran Grca, @@ -42,7 +44,8 @@ enum SERIAL_INT_LSR = 1, SERIAL_INT_RECEIVE = 2, SERIAL_INT_TRANSMIT = 4, - SERIAL_INT_MSR = 8 + SERIAL_INT_MSR = 8, + SERIAL_INT_TIMEOUT = 16 }; @@ -77,8 +80,8 @@ serial_reset_port(serial_t *dev) dev->iir = dev->ier = dev->lcr = dev->fcr = 0; dev->fifo_enabled = 0; dev->xmit_fifo_pos = dev->rcvr_fifo_pos = 0; + dev->rcvr_fifo_full = 0; dev->baud_cycles = 0; - dev->bytes_transmitted = 0; memset(dev->xmit_fifo, 0, 16); memset(dev->rcvr_fifo, 0, 14); } @@ -107,6 +110,10 @@ serial_update_ints(serial_t *dev) /* Line status interrupt */ stat = 1; dev->iir = 6; + } else if ((dev->ier & 1) && (dev->int_status & SERIAL_INT_TIMEOUT)) { + /* Received data available */ + stat = 1; + dev->iir = 0x0c; } else if ((dev->ier & 1) && (dev->int_status & SERIAL_INT_RECEIVE)) { /* Received data available */ stat = 1; @@ -131,42 +138,136 @@ serial_update_ints(serial_t *dev) } -void -serial_write_fifo(serial_t *dev, uint8_t dat) +static void +serial_clear_timeout(serial_t *dev) { - serial_log("serial_write_fifo(%08X, %02X, %i)\n", dev, dat, (dev->type >= SERIAL_NS16550) && dev->fifo_enabled); + /* Disable timeout timer and clear timeout condition. */ + timer_disable(&dev->timeout_timer); + dev->int_status &= ~SERIAL_INT_TIMEOUT; + serial_update_ints(dev); +} + + +static void +write_fifo(serial_t *dev, uint8_t dat) +{ + serial_log("write_fifo(%08X, %02X, %i, %i)\n", dev, dat, (dev->type >= SERIAL_NS16550) && dev->fifo_enabled, dev->rcvr_fifo_pos & 0x0f); if ((dev->type >= SERIAL_NS16550) && dev->fifo_enabled) { /* FIFO mode. */ - dev->rcvr_fifo[dev->rcvr_fifo_pos++] = dat; - dev->rcvr_fifo_pos %= dev->rcvr_fifo_len; + timer_disable(&dev->timeout_timer); + /* Indicate overrun. */ + if (dev->rcvr_fifo_full) + dev->lsr |= 0x02; + else + dev->rcvr_fifo[dev->rcvr_fifo_pos] = dat; dev->lsr &= 0xfe; - dev->lsr |= (!dev->rcvr_fifo_pos); dev->int_status &= ~SERIAL_INT_RECEIVE; - if (!dev->rcvr_fifo_pos) { + if (dev->rcvr_fifo_pos == (dev->rcvr_fifo_len - 1)) { + dev->lsr |= 0x01; dev->int_status |= SERIAL_INT_RECEIVE; - serial_update_ints(dev); } + if (dev->rcvr_fifo_pos < 15) + dev->rcvr_fifo_pos++; + else + dev->rcvr_fifo_full = 1; + serial_update_ints(dev); + timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); } else { /* Non-FIFO mode. */ + /* Indicate overrun. */ + if (dev->lsr & 0x01) + dev->lsr |= 0x02; dev->dat = dat; - dev->lsr |= 1; + dev->lsr |= 0x01; dev->int_status |= SERIAL_INT_RECEIVE; serial_update_ints(dev); } } +void +serial_write_fifo(serial_t *dev, uint8_t dat) +{ + serial_log("serial_write_fifo(%08X, %02X, %i, %i)\n", dev, dat, (dev->type >= SERIAL_NS16550) && dev->fifo_enabled, dev->rcvr_fifo_pos & 0x0f); + + if (!(dev->mctrl & 0x10)) + write_fifo(dev, dat); +} + + void serial_transmit(serial_t *dev, uint8_t val) { if (dev->mctrl & 0x10) - serial_write_fifo(dev, val); + write_fifo(dev, val); else if (dev->sd->dev_write) dev->sd->dev_write(dev, dev->sd->priv, val); } +static void +serial_move_to_txsr(serial_t *dev) +{ + int i = 0; + + if (dev->fifo_enabled) { + dev->txsr = dev->xmit_fifo[0]; + if (dev->xmit_fifo_pos > 0) { + /* Move the entire fifo forward by one byte. */ + for (i = 1; i < 16; i++) + dev->xmit_fifo[i - 1] = dev->xmit_fifo[i]; + /* Decrease FIFO position. */ + dev->xmit_fifo_pos--; + } + } else { + dev->txsr = dev->thr; + dev->thr = 0; + } + + dev->lsr &= ~0x40; + serial_log("serial_move_to_txsr(): FIFO %sabled, FIFO pos = %i\n", dev->fifo_enabled ? "en" : "dis", dev->xmit_fifo_pos & 0x0f); + + if (!dev->fifo_enabled || (dev->xmit_fifo_pos == 0x0)) { + /* Update interrupts to signal THRE and that TXSR is no longer empty. */ + dev->lsr |= 0x20; + dev->int_status |= SERIAL_INT_TRANSMIT; + serial_update_ints(dev); + } + if (dev->transmit_enabled & 2) + dev->baud_cycles++; + else + dev->baud_cycles = 0; /* If not moving while transmitting, reset BAUDOUT cycle count. */ + if (!dev->fifo_enabled || (dev->xmit_fifo_pos == 0x0)) + dev->transmit_enabled &= ~1; /* Stop moving. */ + dev->transmit_enabled |= 2; /* Start transmitting. */ +} + + +static void +serial_process_txsr(serial_t *dev) +{ + serial_log("serial_process_txsr(): FIFO %sabled\n", dev->fifo_enabled ? "en" : "dis"); + serial_transmit(dev, dev->txsr); + dev->txsr = 0; + /* Reset BAUDOUT cycle count. */ + dev->baud_cycles = 0; + /* If FIFO is enabled and there are bytes left to transmit, + continue with the FIFO, otherwise stop. */ + if (dev->fifo_enabled && (dev->xmit_fifo_pos != 0x0)) + dev->transmit_enabled |= 1; + else { + /* Both FIFO/THR and TXSR are empty. */ + /* If bit 5 is set, also set bit 6 to mark both THR and shift register as empty. */ + if (dev->lsr & 0x20) + dev->lsr |= 0x40; + dev->transmit_enabled &= ~2; + } + dev->int_status &= ~SERIAL_INT_TRANSMIT; + serial_update_ints(dev); +} + + /* Transmit_enable flags: Bit 0 = Do move if set; Bit 1 = Do transmit if set. */ @@ -176,73 +277,63 @@ serial_transmit_timer(void *priv) serial_t *dev = (serial_t *) priv; int delay = 8; /* STOP to THRE delay is 8 BAUDOUT cycles. */ - if ((dev->transmit_enabled & 1) && (dev->transmit_enabled & 2)) - delay = dev->data_bits; /* Delay by less if already transmitting. */ + if (dev->transmit_enabled & 3) { + if ((dev->transmit_enabled & 1) && (dev->transmit_enabled & 2)) + delay = dev->data_bits; /* Delay by less if already transmitting. */ - if ((dev->baud_cycles == delay) && (dev->transmit_enabled & 1)) { - /* We have processed (data bits) BAUDOUT cycles. */ - if (dev->fifo_enabled) { - dev->txsr = dev->xmit_fifo[dev->xmit_fifo_pos]; - dev->xmit_fifo[dev->xmit_fifo_pos++] = 0; - } else { - dev->txsr = dev->thr; - dev->thr = 0; - } - - dev->bytes_transmitted++; - - if (!dev->fifo_enabled || (dev->xmit_fifo_pos == 16)) { - /* Update interrupts to signal THRE. */ - dev->xmit_fifo_pos = 0; - dev->lsr |= 0x20; - dev->int_status |= SERIAL_INT_TRANSMIT; - serial_update_ints(dev); - } - if (dev->transmit_enabled & 2) - dev->baud_cycles++; - else - dev->baud_cycles = 0; /* If not moving while transmitting, reset BAUDOUT cycle count. */ - dev->transmit_enabled &= ~1; /* Stop moving. */ - dev->transmit_enabled |= 2; /* Start transmitting. */ - timer_advance_u64(&dev->transmit_timer, (uint64_t) (dev->transmit_period * (double)TIMER_USEC)); - } else if ((dev->baud_cycles == dev->bits) && (dev->transmit_enabled & 2)) { - /* We have processed (total bits) BAUDOUT cycles, transmit the byte. */ - serial_transmit(dev, dev->txsr); - dev->txsr = 0; - /* Reset BAUDOUT cycle count. */ - dev->baud_cycles = 0; - /* If FIFO is enabled and there are bytes left to transmit, - continue with the FIFO, otherwise stop. */ - if (dev->fifo_enabled && (dev->bytes_transmitted == 16)) { - dev->transmit_enabled |= 1; - timer_advance_u64(&dev->transmit_timer, (uint64_t) (dev->transmit_period * (double)TIMER_USEC)); - } else { - /* Both FIFO/THR and TXSR are empty. */ - /* If bit 5 is set, also set bit 6 to mark both THR and shift register as empty. */ - if (dev->lsr & 0x20) - dev->lsr |= 0x40; - dev->transmit_enabled &= ~2; - dev->bytes_transmitted = 0; - } - dev->int_status &= ~SERIAL_INT_TRANSMIT; - serial_update_ints(dev); - } else if (dev->transmit_enabled & 3) { dev->baud_cycles++; - timer_advance_u64(&dev->transmit_timer, (uint64_t) (dev->transmit_period * (double)TIMER_USEC)); + + /* We have processed (total bits) BAUDOUT cycles, transmit the byte. */ + if ((dev->baud_cycles == dev->bits) && (dev->transmit_enabled & 2)) + serial_process_txsr(dev); + + /* We have processed (data bits) BAUDOUT cycles. */ + if ((dev->baud_cycles == delay) && (dev->transmit_enabled & 1)) + serial_move_to_txsr(dev); + + if (dev->transmit_enabled & 3) + timer_on_auto(&dev->transmit_timer, dev->transmit_period); } else { dev->baud_cycles = 0; - dev->bytes_transmitted = 0; + return; } } +static void +serial_timeout_timer(void *priv) +{ + serial_t *dev = (serial_t *) priv; + +#ifdef ENABLE_SERIAL_LOG + serial_log("serial_timeout_timer()\n"); +#endif + + dev->lsr |= 0x01; + dev->int_status |= SERIAL_INT_TIMEOUT; + serial_update_ints(dev); +} + + static void serial_update_speed(serial_t *dev) { - if (dev->transmit_enabled & 3) { - timer_disable(&dev->transmit_timer); - timer_set_delay_u64(&dev->transmit_timer, (uint64_t) (dev->transmit_period * (double)TIMER_USEC)); - } + if (dev->transmit_enabled & 3) + timer_on_auto(&dev->transmit_timer, dev->transmit_period); + + if (timer_is_enabled(&dev->timeout_timer)) + timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); +} + + +static void +serial_reset_fifo(serial_t *dev) +{ + dev->lsr = (dev->lsr & 0xfe) | 0x60; + dev->int_status = (dev->int_status & ~SERIAL_INT_RECEIVE) | SERIAL_INT_TRANSMIT; + serial_update_ints(dev); + dev->xmit_fifo_pos = dev->rcvr_fifo_pos = 0; + dev->rcvr_fifo_full = 0; } @@ -270,23 +361,14 @@ serial_write(uint16_t addr, uint8_t val, void *p) dev->int_status &= ~SERIAL_INT_TRANSMIT; serial_update_ints(dev); - if ((dev->type >= SERIAL_NS16550) && dev->fifo_enabled) { - /* FIFO mode. */ + if ((dev->type >= SERIAL_NS16550) && dev->fifo_enabled && (dev->xmit_fifo_pos < 16)) { + /* FIFO mode, begin transmitting. */ + timer_on_auto(&dev->transmit_timer, dev->transmit_period); + dev->transmit_enabled |= 1; /* Start moving. */ dev->xmit_fifo[dev->xmit_fifo_pos++] = val; - dev->xmit_fifo_pos &= 0x0f; - - if (dev->xmit_fifo_pos == 0) { - /* FIFO full, begin transmitting. */ - timer_disable(&dev->transmit_timer); - timer_set_delay_u64(&dev->transmit_timer, (uint64_t) (dev->transmit_period * (double)TIMER_USEC)); - dev->bytes_transmitted = 0; - dev->transmit_enabled |= 1; /* Start moving. */ - } } else { /* Non-FIFO mode, begin transmitting. */ - dev->bytes_transmitted = 0; - timer_disable(&dev->transmit_timer); - timer_set_delay_u64(&dev->transmit_timer, (uint64_t) (dev->transmit_period * (double)TIMER_USEC)); + timer_on_auto(&dev->transmit_timer, dev->transmit_period); dev->transmit_enabled |= 1; /* Start moving. */ dev->thr = val; } @@ -298,25 +380,29 @@ serial_write(uint16_t addr, uint8_t val, void *p) serial_update_speed(dev); return; } + if ((val & 2) && (dev->lsr & 0x20)) + dev->int_status |= SERIAL_INT_TRANSMIT; dev->ier = val & 0xf; serial_update_ints(dev); break; case 2: if (dev->type >= SERIAL_NS16550) { - if ((val ^ dev->fcr) & 0x04) - dev->lsr |= 0x60; + if ((val ^ dev->fcr) & 0x01) + serial_reset_fifo(dev); dev->fcr = val & 0xf9; dev->fifo_enabled = val & 0x01; if (!dev->fifo_enabled) { memset(dev->rcvr_fifo, 0, 14); memset(dev->xmit_fifo, 0, 16); - dev->rcvr_fifo_pos = dev->xmit_fifo_pos = 0; + dev->xmit_fifo_pos = dev->rcvr_fifo_pos = 0; + dev->rcvr_fifo_full = 0; dev->rcvr_fifo_len = 1; break; } if (val & 0x02) { memset(dev->rcvr_fifo, 0, 14); dev->rcvr_fifo_pos = 0; + dev->rcvr_fifo_full = 0; } if (val & 0x04) { memset(dev->xmit_fifo, 0, 16); @@ -336,6 +422,7 @@ serial_write(uint16_t addr, uint8_t val, void *p) dev->rcvr_fifo_len = 14; break; } + serial_log("FIFO now %sabled, receive FIFO length = %i\n", dev->fifo_enabled ? "en" : "dis", dev->rcvr_fifo_len); } break; case 3: @@ -361,6 +448,10 @@ serial_write(uint16_t addr, uint8_t val, void *p) if (dev->sd->rcr_callback) dev->sd->rcr_callback(dev, dev->sd->priv); } + if (!(val & 8) && (dev->mctrl & 8)) + picintc(1 << dev->irq); + if ((val ^ dev->mctrl) & 0x10) + serial_reset_fifo(dev); dev->mctrl = val; if (val & 0x10) { new_msr = (val & 0x0c) << 4; @@ -379,6 +470,7 @@ serial_write(uint16_t addr, uint8_t val, void *p) dev->msr = new_msr; dev->xmit_fifo_pos = dev->rcvr_fifo_pos = 0; + dev->rcvr_fifo_full = 0; } break; case 5: @@ -409,7 +501,7 @@ uint8_t serial_read(uint16_t addr, void *p) { serial_t *dev = (serial_t *)p; - uint8_t ret = 0; + uint8_t i, ret = 0; sub_cycles(ISA_CYCLES(8)); @@ -422,22 +514,23 @@ serial_read(uint16_t addr, void *p) if ((dev->type >= SERIAL_NS16550) && dev->fifo_enabled) { /* FIFO mode. */ - if (dev->mctrl & 0x10) { - ret = dev->xmit_fifo[dev->xmit_fifo_pos++]; - dev->xmit_fifo_pos %= 16; - if (!dev->xmit_fifo_pos) { - dev->lsr &= 0xfe; - dev->int_status &= ~SERIAL_INT_RECEIVE; - serial_update_ints(dev); - } + + serial_clear_timeout(dev); + + ret = dev->rcvr_fifo[0]; + dev->rcvr_fifo_full = 0; + if (dev->rcvr_fifo_pos > 0) { + for (i = 1; i < 16; i++) + dev->rcvr_fifo[i - 1] = dev->rcvr_fifo[i]; + serial_log("FIFO position %i: read %02X, next %02X\n", dev->rcvr_fifo_pos, ret, dev->rcvr_fifo[0]); + dev->rcvr_fifo_pos--; + /* At least one byte remains to be read, start the timeout + timer so that a timeout is indicated in case of no read. */ + timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); } else { - ret = dev->rcvr_fifo[dev->rcvr_fifo_pos++]; - dev->rcvr_fifo_pos %= dev->rcvr_fifo_len; - if (!dev->rcvr_fifo_pos) { - dev->lsr &= 0xfe; - dev->int_status &= ~SERIAL_INT_RECEIVE; - serial_update_ints(dev); - } + dev->lsr &= 0xfe; + dev->int_status &= ~SERIAL_INT_RECEIVE; + serial_update_ints(dev); } } else { ret = dev->dat; @@ -585,6 +678,7 @@ serial_init(const device_t *info) dev->fcr = 0x06; serial_transmit_period(dev); timer_add(&dev->transmit_timer, serial_transmit_timer, dev, 0); + timer_add(&dev->timeout_timer, serial_timeout_timer, dev, 0); } next_inst++; diff --git a/src/serial.h b/src/serial.h index 2cfca14cd..73238c87b 100644 --- a/src/serial.h +++ b/src/serial.h @@ -8,7 +8,7 @@ * * Definitions for the NS8250/16450/16550 UART emulation. * - * Version: @(#)serial.h 1.0.11 2019/10/11 + * Version: @(#)serial.h 1.0.12 2019/10/31 * * Author: Sarah Walker, * Miran Grca, @@ -44,14 +44,15 @@ typedef struct serial_s dat, int_status, scratch, fcr, irq, type, inst, transmit_enabled, fifo_enabled, rcvr_fifo_len, bits, data_bits, - baud_cycles, bytes_transmitted, txsr, pad; + baud_cycles, rcvr_fifo_full, txsr, pad; uint16_t dlab, base_address; - uint8_t rcvr_fifo_pos, rcvr_fifo[14]; - uint8_t xmit_fifo_pos, xmit_fifo[16]; + uint8_t rcvr_fifo_pos, xmit_fifo_pos, + pad0, pad1, + rcvr_fifo[16], xmit_fifo[16]; - pc_timer_t transmit_timer; + pc_timer_t transmit_timer, timeout_timer; double transmit_period; struct serial_device_s *sd; diff --git a/src/sound/snd_dbopl.cc b/src/sound/snd_dbopl.cc index e2a0e079b..2ccc9e56c 100644 --- a/src/sound/snd_dbopl.cc +++ b/src/sound/snd_dbopl.cc @@ -153,7 +153,7 @@ uint8_t opl_read(int nr, uint16_t addr) void opl2_update(int nr, int16_t *buffer, int samples) { int c; - Bit32s buffer_32[SOUNDBUFLEN]; + Bit32s buffer_32[samples]; if (opl_type) { @@ -171,7 +171,7 @@ void opl2_update(int nr, int16_t *buffer, int samples) void opl3_update(int nr, int16_t *buffer, int samples) { int c; - Bit32s buffer_32[SOUNDBUFLEN*2]; + Bit32s buffer_32[samples*2]; if (opl_type) { diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index b8fd1b868..c0d0d0b03 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -8,13 +8,13 @@ * * S3 emulation. * - * Version: @(#)vid_s3.c 1.0.26 2019/01/12 + * Version: @(#)vid_s3.c 1.0.27 2019/10/30 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. */ #include #include @@ -2379,23 +2379,6 @@ int s3_data_len(s3_t *s3) return 4; } -void s3_data_swap(s3_t *s3) -{ - uint8_t i, temp_array[4]; - uint8_t c = s3_data_len(s3); - - for (i = 0; i < 4; i++) - temp_array[i] = s3->accel.pix_trans[i]; - - if (s3_data_len(s3) < 2) - return; - - if (s3->accel.cmd & 0x1000) { - for (i = 0; i < c; i++) - s3->accel.pix_trans[i] = temp_array[i ^ (c - 1)]; - } -} - void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3) { svga_t *svga = &s3->svga; @@ -2645,7 +2628,17 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r && s3->accel.cy >= clip_t && s3->accel.cy <= clip_b) { - switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) + if (s3_cpu_dest(s3) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x00)) + mix_dat = mix_mask; /* Mix data = forced to foreground register. */ + else if (s3_cpu_dest(s3) && vram_mask) { + /* Mix data = current video memory value. */ + READ_SRC(s3->accel.dest + s3->accel.cx, mix_dat); + mix_dat = mix_dat ? mix_mask : 0; + } + + if (s3_cpu_dest(s3)) { + READ_SRC(s3->accel.dest + s3->accel.cx, src_dat); + } else switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = s3->accel.bkgd_color; break; case 1: src_dat = s3->accel.frgd_color; break; @@ -2657,11 +2650,11 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { - if (s3_cpu_dest(s3)) { - READ_SRC(s3->accel.dest + s3->accel.cx, src_dat); + if (s3_cpu_dest(s3)) dest_dat = 0xffffffff; - } else + else { READ_DST(s3->accel.dest + s3->accel.cx, dest_dat); + } MIX @@ -2700,28 +2693,22 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat s3->accel.sy--; if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) { - if (s3_cpu_dest(s3)) { + if (s3_cpu_dest(s3)) s3->data_available = 1; - s3_data_swap(s3); - } return; } if (s3->accel.sy < 0) { s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; - if (s3_cpu_dest(s3)) { + if (s3_cpu_dest(s3)) s3->data_available = 1; - s3_data_swap(s3); - } return; } } - if (s3_cpu_dest(s3) && s3->data_available) { - s3_data_swap(s3); + if (s3_cpu_dest(s3) && s3->data_available) return; - } } break; diff --git a/src/win/86Box.rc b/src/win/86Box.rc index e02942cf5..59c80990f 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -8,7 +8,7 @@ * * Application resource script for Windows. * - * Version: @(#)86Box.rc 1.0.49 2019/10/23 + * Version: @(#)86Box.rc 1.0.50 2019/10/31 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -225,7 +225,7 @@ BEGIN DEFPUSHBUTTON "OK",IDOK,129,94,71,12 ICON 100,IDC_ABOUT_ICON,7,7,20,20 #ifdef RELEASE_BUILD - LTEXT "86Box v2.02 - An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, MoochMcGee, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2. See LICENSE for more information.", + LTEXT "86Box v2.03 - An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, MoochMcGee, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2. See LICENSE for more information.", IDC_ABOUT_ICON,54,7,146,73 #else LTEXT "86Box v2.10 - An emulator of old computers\n\nAuthors: Sarah Walker, Miran Grca, Fred N. van Kempen (waltje), SA1988, MoochMcGee, reenigne, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2. See LICENSE for more information.", @@ -980,8 +980,8 @@ END VS_VERSION_INFO VERSIONINFO #ifdef RELEASE_BUILD - FILEVERSION 2,2,0,0 - PRODUCTVERSION 2,2,0,0 + FILEVERSION 2,3,0,0 + PRODUCTVERSION 2,3,0,0 #else FILEVERSION 2,10,0,0 PRODUCTVERSION 2,10,0,0 @@ -1004,7 +1004,7 @@ BEGIN VALUE "CompanyName", "IRC #SoftHistory\0" VALUE "FileDescription", "86Box - an emulator for X86-based systems\0" #ifdef RELEASE_BUILD - VALUE "FileVersion", "2.02\0" + VALUE "FileVersion", "2.03\0" #else VALUE "FileVersion", "2.10\0" #endif @@ -1015,7 +1015,7 @@ BEGIN VALUE "PrivateBuild", "\0" VALUE "ProductName", "86Box Emulator\0" #ifdef RELEASE_BUILD - VALUE "ProductVersion", "2.02\0" + VALUE "ProductVersion", "2.03\0" #else VALUE "ProductVersion", "2.10\0" #endif