diff options
Diffstat (limited to 'hw/net/e1000x_common.c')
| -rw-r--r-- | hw/net/e1000x_common.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/hw/net/e1000x_common.c b/hw/net/e1000x_common.c index e6387dde53..c497923806 100644 --- a/hw/net/e1000x_common.c +++ b/hw/net/e1000x_common.c @@ -267,3 +267,28 @@ e1000x_read_tx_ctx_descr(struct e1000_context_desc *d, props->tcp = (op & E1000_TXD_CMD_TCP) ? 1 : 0; props->tse = (op & E1000_TXD_CMD_TSE) ? 1 : 0; } + +void e1000x_timestamp(uint32_t *mac, int64_t timadj, size_t lo, size_t hi) +{ + int64_t ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint32_t timinca = mac[TIMINCA]; + uint32_t incvalue = timinca & E1000_TIMINCA_INCVALUE_MASK; + uint32_t incperiod = MAX(timinca >> E1000_TIMINCA_INCPERIOD_SHIFT, 1); + int64_t timestamp = timadj + muldiv64(ns, incvalue, incperiod * 16); + + mac[lo] = timestamp & 0xffffffff; + mac[hi] = timestamp >> 32; +} + +void e1000x_set_timinca(uint32_t *mac, int64_t *timadj, uint32_t val) +{ + int64_t ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + uint32_t old_val = mac[TIMINCA]; + uint32_t old_incvalue = old_val & E1000_TIMINCA_INCVALUE_MASK; + uint32_t old_incperiod = MAX(old_val >> E1000_TIMINCA_INCPERIOD_SHIFT, 1); + uint32_t incvalue = val & E1000_TIMINCA_INCVALUE_MASK; + uint32_t incperiod = MAX(val >> E1000_TIMINCA_INCPERIOD_SHIFT, 1); + + mac[TIMINCA] = val; + *timadj += (muldiv64(ns, incvalue, incperiod) - muldiv64(ns, old_incvalue, old_incperiod)) / 16; +} |