static void aspeed_timer_expire(void *opaque) { AspeedTimer *t = opaque; bool interrupt = false; uint32_t ticks; if (!timer_enabled(t)) { return; } ticks = calculate_ticks(t, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); if (!ticks) { interrupt = timer_overflow_interrupt(t) || !t->match[0] || !t->match[1]; } else if (ticks <= MIN(t->match[0], t->match[1])) { interrupt = true; } else if (ticks <= MAX(t->match[0], t->match[1])) { interrupt = true; } if (interrupt) { t->level = !t->level; qemu_set_irq(t->irq, t->level); } aspeed_timer_mod(t); }
static int calculate_log_ticks (double min, double max, double distance, TICKS * ticks) { int k = 0 ; /* Number of ticks we have placed in "ticks" array */ double underpinning ; /* Largest power of ten that is <= min */ /* If the interval is less than a decade, just apply the same ** numbering-choosing scheme as used with linear axis, with the ** ticks positioned logarithmically. */ if (max / min < 10.0) return calculate_ticks (min, max, distance, 2, ticks) ; /* If the range is greater than 1 to 1000000, it will generate more than ** 19 ticks. Better to fail explicitly than to overflow. */ if (max / min > 1000000) { printf ("Error: Frequency range is too great for logarithmic scale.\n") ; exit (1) ; } ; /* First hack: label the powers of ten. */ /* Find largest power of ten that is <= minimum value */ underpinning = pow (10.0, floor (log10 (min))) ; /* Go powering up by 10 from there, numbering as we go. */ k = add_log_ticks (min, max, distance, ticks, k, underpinning, true) ; /* Do we have enough numbers? If so, add numberless ticks at 2 and 5 */ if (k >= TARGET_DIVISIONS + 1) /* Number of labels is n.of divisions + 1 */ { k = add_log_ticks (min, max, distance, ticks, k, underpinning * 2.0, false) ; k = add_log_ticks (min, max, distance, ticks, k, underpinning * 5.0, false) ; } else { int i ; /* Not enough numbers: add numbered ticks at 2 and 5 and * unnumbered ticks at all the rest */ for (i = 2 ; i <= 9 ; i++) k = add_log_ticks (min, max, distance, ticks, k, underpinning * (1.0 * i), i == 2 || i == 5) ; } ; /* Greatest possible number of ticks calculation: ** The worst case is when the else clause adds 8 ticks with the maximal ** number of divisions, which is when k == TARGET_DIVISIONS, 3, ** for example 100, 1000, 10000. ** The else clause adds another 8 ticks inside each division as well as ** up to 8 ticks after the last number (from 20000 to 90000) ** and 8 before to the first (from 20 to 90 in the example). ** Maximum possible ticks is 3+8+8+8+8=35 */ return k ; } /* calculate_log_ticks */
static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg, uint32_t value) { AspeedTimer *t; uint32_t old_reload; trace_aspeed_timer_set_value(timer, reg, value); t = &s->timers[timer]; switch (reg) { case TIMER_REG_RELOAD: old_reload = t->reload; t->reload = value; /* If the reload value was not previously set, or zero, and * the current value is valid, try to start the timer if it is * enabled. */ if (old_reload || !t->reload) { break; } case TIMER_REG_STATUS: if (timer_enabled(t)) { uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); int64_t delta = (int64_t) value - (int64_t) calculate_ticks(t, now); uint32_t rate = calculate_rate(t); t->start += muldiv64(delta, NANOSECONDS_PER_SECOND, rate); aspeed_timer_mod(t); } break; case TIMER_REG_MATCH_FIRST: case TIMER_REG_MATCH_SECOND: t->match[reg - 2] = value; if (timer_enabled(t)) { aspeed_timer_mod(t); } break; default: qemu_log_mask(LOG_UNIMP, "%s: Programming error: unexpected reg: %d\n", __func__, reg); break; } }
static void render_heat_border (cairo_surface_t * surface, double magfloor, const RECT *r) { const char *decibels = "dB" ; char text [512] ; cairo_t * cr ; cairo_text_extents_t extents ; TICKS ticks ; int k, tick_count ; cr = cairo_create (surface) ; cairo_set_source_rgb (cr, 1.0, 1.0, 1.0) ; cairo_set_line_width (cr, BORDER_LINE_WIDTH) ; /* Border around actual spectrogram. */ cairo_rectangle (cr, r->left, r->top, r->width, r->height) ; cairo_stroke (cr) ; cairo_select_font_face (cr, font_family, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL) ; cairo_set_font_size (cr, 1.0 * NORMAL_FONT_SIZE) ; cairo_text_extents (cr, decibels, &extents) ; cairo_move_to (cr, r->left + (r->width - extents.width) / 2, r->top - 5) ; cairo_show_text (cr, decibels) ; tick_count = calculate_ticks (0.0, fabs (magfloor), r->height, false, &ticks) ; for (k = 0 ; k < tick_count ; k++) { x_line (cr, r->left + r->width, r->top + ticks.distance [k], TICK_LEN) ; if (JUST_A_TICK (ticks, k)) continue ; str_print_value (text, sizeof (text), -1.0 * ticks.value [k], ticks.decimal_places_to_print) ; cairo_text_extents (cr, text, &extents) ; cairo_move_to (cr, r->left + r->width + 2 * TICK_LEN, r->top + ticks.distance [k] + extents.height / 4.5) ; cairo_show_text (cr, text) ; } ; cairo_destroy (cr) ; } /* render_heat_border */
static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg) { uint64_t value; switch (reg) { case TIMER_REG_STATUS: value = calculate_ticks(t, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); break; case TIMER_REG_RELOAD: value = t->reload; break; case TIMER_REG_MATCH_FIRST: case TIMER_REG_MATCH_SECOND: value = t->match[reg - 2]; break; default: qemu_log_mask(LOG_UNIMP, "%s: Programming error: unexpected reg: %d\n", __func__, reg); value = 0; break; } return value; }
static void render_spect_border (cairo_surface_t * surface, const char * filename, double left, double width, double seconds, double top, double height, double min_freq, double max_freq, bool log_freq) { char text [512] ; cairo_t * cr ; cairo_text_extents_t extents ; cairo_matrix_t matrix ; TICKS ticks ; int k, tick_count ; cr = cairo_create (surface) ; cairo_set_source_rgb (cr, 1.0, 1.0, 1.0) ; cairo_set_line_width (cr, BORDER_LINE_WIDTH) ; /* Print title. */ cairo_select_font_face (cr, font_family, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL) ; cairo_set_font_size (cr, 1.0 * TITLE_FONT_SIZE) ; snprintf (text, sizeof (text), "Spectrogram: %s", filename) ; cairo_text_extents (cr, text, &extents) ; cairo_move_to (cr, left + 2, top - extents.height / 2) ; cairo_show_text (cr, text) ; /* Print labels. */ cairo_select_font_face (cr, font_family, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL) ; cairo_set_font_size (cr, 1.0 * NORMAL_FONT_SIZE) ; /* Border around actual spectrogram. */ cairo_rectangle (cr, left, top, width, height) ; /* Put ticks on Time axis */ tick_count = calculate_ticks (0.0, seconds, width, false, &ticks) ; for (k = 0 ; k < tick_count ; k++) { y_line (cr, left + ticks.distance [k], top + height, TICK_LEN) ; if (JUST_A_TICK (ticks, k)) continue ; str_print_value (text, sizeof (text), ticks.value [k], ticks.decimal_places_to_print) ; cairo_text_extents (cr, text, &extents) ; cairo_move_to (cr, left + ticks.distance [k] - extents.width / 2, top + height + 8 + extents.height) ; cairo_show_text (cr, text) ; } ; /* Put ticks on Frequency axis */ tick_count = calculate_ticks (min_freq, max_freq, height, log_freq, &ticks) ; for (k = 0 ; k < tick_count ; k++) { x_line (cr, left + width, top + height - ticks.distance [k], TICK_LEN) ; if (JUST_A_TICK (ticks, k)) continue ; str_print_value (text, sizeof (text), ticks.value [k], ticks.decimal_places_to_print) ; cairo_text_extents (cr, text, &extents) ; cairo_move_to (cr, left + width + 12, top + height - ticks.distance [k] + extents.height / 4.5) ; cairo_show_text (cr, text) ; } ; cairo_set_font_size (cr, 1.0 * NORMAL_FONT_SIZE) ; /* Label X axis. */ snprintf (text, sizeof (text), "Time (secs)") ; cairo_text_extents (cr, text, &extents) ; cairo_move_to (cr, left + (width - extents.width) / 2, cairo_image_surface_get_height (surface) - 8) ; cairo_show_text (cr, text) ; /* Label Y axis (rotated). */ snprintf (text, sizeof (text), "Frequency (Hz)") ; cairo_text_extents (cr, text, &extents) ; cairo_get_font_matrix (cr, &matrix) ; cairo_matrix_rotate (&matrix, -0.5 * M_PI) ; cairo_set_font_matrix (cr, &matrix) ; cairo_move_to (cr, cairo_image_surface_get_width (surface) - 12, top + (height + extents.width) / 2) ; cairo_show_text (cr, text) ; cairo_destroy (cr) ; } /* render_spect_border */