diff --git a/src/chipset/intel_420ex.c b/src/chipset/intel_420ex.c index 03720b668..4d810f65b 100644 --- a/src/chipset/intel_420ex.c +++ b/src/chipset/intel_420ex.c @@ -522,7 +522,7 @@ i420ex_speed_changed(void *priv) if (te) timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC); - te = timer_is_enabled(&dev->fast_off_timer); + te = timer_is_on(&dev->fast_off_timer); timer_stop(&dev->fast_off_timer); if (te) diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index add421b96..4066abe31 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -1541,10 +1541,10 @@ piix_speed_changed(void *priv) if (!dev) return; - int te = timer_is_enabled(&dev->fast_off_timer); + int to = timer_is_on(&dev->fast_off_timer); timer_stop(&dev->fast_off_timer); - if (te) + if (to) timer_on_auto(&dev->fast_off_timer, ((double) cpu_fast_off_val + 1) * dev->fast_off_period); } diff --git a/src/chipset/intel_sio.c b/src/chipset/intel_sio.c index 0f32eb4c8..03a292da8 100644 --- a/src/chipset/intel_sio.c +++ b/src/chipset/intel_sio.c @@ -497,7 +497,7 @@ sio_speed_changed(void *priv) timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC); if (dev->id == 0x03) { - te = timer_is_enabled(&dev->fast_off_timer); + te = timer_is_on(&dev->fast_off_timer); timer_stop(&dev->fast_off_timer); if (te) diff --git a/src/cpu/386.c b/src/cpu/386.c index fb42a222f..20b67ff89 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -369,7 +369,7 @@ exec386_2386(int cycs) } if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) - timer_process_inline(); + timer_process(); #ifdef USE_GDBSTUB if (gdbstub_instruction()) diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index a31704c1b..ab01d28b8 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -256,7 +256,7 @@ update_tsc(void) if (cycdiff > 0) { if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) - timer_process_inline(); + timer_process(); } } @@ -782,7 +782,7 @@ exec386_dynarec(int cycs) if (cycdiff > 0) { if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) - timer_process_inline(); + timer_process(); } # ifdef USE_GDBSTUB @@ -943,7 +943,7 @@ exec386(int cycs) } if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc)) - timer_process_inline(); + timer_process(); #ifdef USE_GDBSTUB if (gdbstub_instruction()) diff --git a/src/device/serial.c b/src/device/serial.c index 5dd5d8420..da34fd212 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -363,7 +363,7 @@ serial_update_speed(serial_t *dev) if (dev->transmit_enabled & 3) timer_on_auto(&dev->transmit_timer, dev->transmit_period); - if (timer_is_enabled(&dev->timeout_timer)) + if (timer_is_on(&dev->timeout_timer)) timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period); } diff --git a/src/include/86box/timer.h b/src/include/86box/timer.h index 586e3d2fe..45b648151 100644 --- a/src/include/86box/timer.h +++ b/src/include/86box/timer.h @@ -122,7 +122,7 @@ timer_is_enabled(pc_timer_t *timer) static __inline int timer_is_on(pc_timer_t *timer) { - return ((timer->flags & TIMER_ENABLED) && (timer->period > 0.0)); + return ((timer->flags & TIMER_SPLIT) && (timer->flags & TIMER_ENABLED)); } /*Return integer timestamp of timer*/ @@ -184,45 +184,8 @@ timer_set_p(pc_timer_t *timer, void *priv) /* The API for big timer periods starts here. */ extern void timer_stop(pc_timer_t *timer); -extern void timer_advance_ex(pc_timer_t *timer, int start); -extern void timer_on(pc_timer_t *timer, double period, int start); extern void timer_on_auto(pc_timer_t *timer, double period); -extern void timer_remove_head(void); - -extern pc_timer_t *timer_head; -extern int timer_inited; - -static __inline void -timer_process_inline(void) -{ - pc_timer_t *timer; - - if (!timer_head) - return; - - while (1) { - timer = timer_head; - - if (!TIMER_LESS_THAN_VAL(timer, (uint32_t) tsc)) - break; - - timer_head = timer->next; - if (timer_head) - timer_head->prev = NULL; - - timer->next = timer->prev = NULL; - timer->flags &= ~TIMER_ENABLED; - - if (timer->flags & TIMER_SPLIT) - timer_advance_ex(timer, 0); /* We're splitting a > 1 s period into multiple <= 1 s periods. */ - else if (timer->callback != NULL) /* Make sure it's no NULL, so that we can have a NULL callback when no operation is needed. */ - timer->callback(timer->priv); - } - - timer_target = timer_head->ts.ts32.integer; -} - #ifdef __cplusplus } #endif diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 8b0ae3c0c..c4bec884d 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -639,7 +639,8 @@ ncr_write(uint16_t port, uint8_t val, void *priv) } } else { /*Don't stop the timer until it finishes the transfer*/ - if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { + if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) && + !timer_is_on(&ncr_dev->timer)) { ncr_log("Continuing DMA mode\n"); ncr_timer_on(ncr_dev, ncr, 0); } @@ -671,7 +672,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv) if (dev->buffer_length > 0) { memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length)); - ncr_log("DMA send timer start, enabled? = %i\n", timer_is_enabled(&ncr_dev->timer)); + ncr_log("DMA send timer start, enabled? = %i\n", timer_is_on(&ncr_dev->timer)); ncr_dev->t128.block_count = dev->buffer_length >> 9; ncr_dev->t128.block_loaded = 1; @@ -679,7 +680,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv) ncr_dev->t128.status |= 0x04; } } else { - if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { + if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer)) { memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length)); ncr_log("DMA send timer on\n"); @@ -693,7 +694,8 @@ ncr_write(uint16_t port, uint8_t val, void *priv) /*a Read 6/10 has occurred, start the timer when the block count is loaded*/ ncr->dma_mode = DMA_INITIATOR_RECEIVE; if (ncr_dev->type == 3) { - ncr_log("DMA receive timer start, enabled? = %i, cdb[0] = %02x, buflen = %i\n", timer_is_enabled(&ncr_dev->timer), ncr->command[0], dev->buffer_length); + ncr_log("DMA receive timer start, enabled? = %i, cdb[0] = %02x, buflen = %i\n", + timer_is_on(&ncr_dev->timer), ncr->command[0], dev->buffer_length); if (dev->buffer_length > 0) { memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length)); @@ -709,7 +711,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv) timer_on_auto(&ncr_dev->timer, 0.02); } } else { - if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { + if ((ncr->mode & MODE_DMA) && !timer_is_on(&ncr_dev->timer)) { memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length)); ncr_log("DMA receive timer start\n"); diff --git a/src/scsi/scsi_spock.c b/src/scsi/scsi_spock.c index 3b9f5108c..d70afca76 100644 --- a/src/scsi/scsi_spock.c +++ b/src/scsi/scsi_spock.c @@ -1055,7 +1055,7 @@ spock_callback(void *priv) spock_process_scsi(scsi, scb); period = 0.2 * ((double) scsi->temp_period); - timer_on(&scsi->callback_timer, (scsi->media_period + period + 10.0), 0); + timer_on_auto(&scsi->callback_timer, (scsi->media_period + period + 10.0)); spock_log("Temporary period: %lf us (%" PRIi64 " periods)\n", scsi->callback_timer.period, scsi->temp_period); } diff --git a/src/scsi/scsi_x54x.c b/src/scsi/scsi_x54x.c index 96088e200..dc3fdfac3 100644 --- a/src/scsi/scsi_x54x.c +++ b/src/scsi/scsi_x54x.c @@ -1293,7 +1293,7 @@ x54x_cmd_callback(void *priv) } period = (1000000.0 / dev->ha_bps) * ((double) dev->temp_period); - timer_on(&dev->timer, dev->media_period + period + 10.0, 0); + timer_on_auto(&dev->timer, dev->media_period + period + 10.0); #if 0 x54x_log("Temporary period: %lf us (%" PRIi64 " periods)\n", dev->timer.period, dev->temp_period); #endif diff --git a/src/timer.c b/src/timer.c index 90ee3ca49..e45fc4398 100644 --- a/src/timer.c +++ b/src/timer.c @@ -15,10 +15,13 @@ pc_timer_t *timer_head = NULL; /* Are we initialized? */ int timer_inited = 0; +static void timer_advance_ex(pc_timer_t *timer); + void timer_enable(pc_timer_t *timer) { pc_timer_t *timer_node = timer_head; + int ret = 0; if (!timer_inited || (timer == NULL)) return; @@ -29,59 +32,63 @@ timer_enable(pc_timer_t *timer) if (timer->next || timer->prev) fatal("timer_enable - timer->next\n"); - timer->flags |= TIMER_ENABLED; - /*List currently empty - add to head*/ if (!timer_head) { timer_head = timer; timer->next = timer->prev = NULL; timer_target = timer_head->ts.ts32.integer; - return; - } - - if (TIMER_LESS_THAN(timer, timer_head)) { + ret = 1; + } else if (TIMER_LESS_THAN(timer, timer_head)) { timer->next = timer_head; timer->prev = NULL; timer_head->prev = timer; timer_head = timer; timer_target = timer_head->ts.ts32.integer; - return; - } - - if (!timer_head->next) { + ret = 1; + } else if (!timer_head->next) { timer_head->next = timer; timer->prev = timer_head; - return; + ret = 1; } - pc_timer_t *prev = timer_head; - timer_node = timer_head->next; + if (ret == 0) { + pc_timer_t *prev = timer_head; + timer_node = timer_head->next; - while (1) { - /*Timer expires before timer_node. Add to list in front of timer_node*/ - if (TIMER_LESS_THAN(timer, timer_node)) { - timer->next = timer_node; - timer->prev = prev; - timer_node->prev = timer; - prev->next = timer; - return; + while (1) { + /*Timer expires before timer_node. Add to list in front of timer_node*/ + if (TIMER_LESS_THAN(timer, timer_node)) { + timer->next = timer_node; + timer->prev = prev; + timer_node->prev = timer; + prev->next = timer; + ret = 1; + break; + } + + /*timer_node is last in the list. Add timer to end of list*/ + if (!timer_node->next) { + timer_node->next = timer; + timer->prev = timer_node; + ret = 1; + break; + } + + prev = timer_node; + timer_node = timer_node->next; } - - /*timer_node is last in the list. Add timer to end of list*/ - if (!timer_node->next) { - timer_node->next = timer; - timer->prev = timer_node; - return; - } - - prev = timer_node; - timer_node = timer_node->next; } + + /* Do not mark it as enabled if it has failed every single condition. */ + if (ret == 1) + timer->flags |= TIMER_ENABLED; } void timer_disable(pc_timer_t *timer) { + pc_timer_t *cur, *temp; + if (!timer_inited || (timer == NULL) || !(timer->flags & TIMER_ENABLED)) return; @@ -120,13 +127,15 @@ timer_process(void) timer->next = timer->prev = NULL; timer->flags &= ~TIMER_ENABLED; + timer->flags |= TIMER_PROCESS; if (timer->flags & TIMER_SPLIT) - timer_advance_ex(timer, 0); /* We're splitting a > 1 s period into multiple <= 1 s periods. */ - else if (timer->callback != NULL) {/* Make sure it's no NULL, so that we can have a NULL callback when no operation is needed. */ - timer->flags |= TIMER_PROCESS; + timer_advance_ex(timer); /* We're splitting a > 1 s period into + multiple <= 1 s periods. */ + else if (timer->callback != NULL) /* Make sure it's not NULL, so that we can + have a NULL callback when no operation + is needed. */ timer->callback(timer->priv); - timer->flags &= ~TIMER_PROCESS; - } + timer->flags &= ~TIMER_PROCESS; } timer_target = timer_head->ts.ts32.integer; @@ -182,60 +191,47 @@ timer_stop(pc_timer_t *timer) return; timer->period = 0.0; - timer_disable(timer); + if (timer_is_enabled(timer)) + timer_disable(timer); timer->flags &= ~TIMER_SPLIT; } static void -timer_do_period(pc_timer_t *timer, uint64_t period, int start) +timer_do_period(pc_timer_t *timer, uint64_t period) { - if (!timer_inited || (timer == NULL)) - return; - - if (start) - timer_set_delay_u64(timer, period); - else + if (timer->flags & TIMER_PROCESS) timer_advance_u64(timer, period); + else + timer_set_delay_u64(timer, period); } -void -timer_advance_ex(pc_timer_t *timer, int start) +static void +timer_advance_ex(pc_timer_t *timer) { - if (!timer_inited || (timer == NULL)) - return; + double dusec = ((double) TIMER_USEC); + double period; - if (timer->period > MAX_USEC) { - timer_do_period(timer, MAX_USEC64 * TIMER_USEC, start); - timer->period -= MAX_USEC; - timer->flags |= TIMER_SPLIT; - } else { - if (timer->period > 0.0) - timer_do_period(timer, (uint64_t) (timer->period * ((double) TIMER_USEC)), start); - else - timer_disable(timer); - timer->period = 0.0; + period = (timer->period > MAX_USEC) ? MAX_USEC64 : timer->period; + + if (timer->period > 0.0) { + timer_do_period(timer, (uint64_t) (period * dusec)); + timer->period -= period; + timer->flags = (timer->flags & ~TIMER_SPLIT) | ((timer->period > MAX_USEC) ? TIMER_SPLIT : 0); + } else if (timer_is_enabled(timer)) { + timer_disable(timer); timer->flags &= ~TIMER_SPLIT; } } -void -timer_on(pc_timer_t *timer, double period, int start) -{ - if (!timer_inited || (timer == NULL)) - return; - - timer->period = period; - timer_advance_ex(timer, start); -} - void timer_on_auto(pc_timer_t *timer, double period) { if (!timer_inited || (timer == NULL)) return; - if (period > 0.0) - timer_on(timer, period, !(timer->flags & TIMER_PROCESS) && (timer->period <= 0.0)); - else + if (period > 0.0) { + timer->period = period; + timer_advance_ex(timer); + } else if (timer_is_on(timer)) timer_stop(timer); }