qemu/include/hw/virtio/virtio-access.h
<<
>>
Prefs
   1/*
   2 * Virtio Accessor Support: In case your target can change endian.
   3 *
   4 * Copyright IBM, Corp. 2013
   5 *
   6 * Authors:
   7 *  Rusty Russell   <rusty@au.ibm.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation, either version 2 of the License, or
  12 * (at your option) any later version.
  13 *
  14 */
  15#ifndef _QEMU_VIRTIO_ACCESS_H
  16#define _QEMU_VIRTIO_ACCESS_H
  17#include "hw/virtio/virtio.h"
  18#include "exec/address-spaces.h"
  19
  20static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
  21{
  22    if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
  23        /* Devices conforming to VIRTIO 1.0 or later are always LE. */
  24        return false;
  25    }
  26#if defined(TARGET_IS_BIENDIAN)
  27    return virtio_is_big_endian(vdev);
  28#elif defined(TARGET_WORDS_BIGENDIAN)
  29    return true;
  30#else
  31    return false;
  32#endif
  33}
  34
  35static inline bool virtio_legacy_is_cross_endian(VirtIODevice *vdev)
  36{
  37#ifdef TARGET_IS_BIENDIAN
  38#ifdef HOST_WORDS_BIGENDIAN
  39    return !virtio_is_big_endian(vdev);
  40#else
  41    return virtio_is_big_endian(vdev);
  42#endif
  43#else
  44    return false;
  45#endif
  46}
  47
  48static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa)
  49{
  50    if (virtio_access_is_big_endian(vdev)) {
  51        return lduw_be_phys(&address_space_memory, pa);
  52    }
  53    return lduw_le_phys(&address_space_memory, pa);
  54}
  55
  56static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa)
  57{
  58    if (virtio_access_is_big_endian(vdev)) {
  59        return ldl_be_phys(&address_space_memory, pa);
  60    }
  61    return ldl_le_phys(&address_space_memory, pa);
  62}
  63
  64static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa)
  65{
  66    if (virtio_access_is_big_endian(vdev)) {
  67        return ldq_be_phys(&address_space_memory, pa);
  68    }
  69    return ldq_le_phys(&address_space_memory, pa);
  70}
  71
  72static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa,
  73                                   uint16_t value)
  74{
  75    if (virtio_access_is_big_endian(vdev)) {
  76        stw_be_phys(&address_space_memory, pa, value);
  77    } else {
  78        stw_le_phys(&address_space_memory, pa, value);
  79    }
  80}
  81
  82static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa,
  83                                   uint32_t value)
  84{
  85    if (virtio_access_is_big_endian(vdev)) {
  86        stl_be_phys(&address_space_memory, pa, value);
  87    } else {
  88        stl_le_phys(&address_space_memory, pa, value);
  89    }
  90}
  91
  92static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v)
  93{
  94    if (virtio_access_is_big_endian(vdev)) {
  95        stw_be_p(ptr, v);
  96    } else {
  97        stw_le_p(ptr, v);
  98    }
  99}
 100
 101static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v)
 102{
 103    if (virtio_access_is_big_endian(vdev)) {
 104        stl_be_p(ptr, v);
 105    } else {
 106        stl_le_p(ptr, v);
 107    }
 108}
 109
 110static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v)
 111{
 112    if (virtio_access_is_big_endian(vdev)) {
 113        stq_be_p(ptr, v);
 114    } else {
 115        stq_le_p(ptr, v);
 116    }
 117}
 118
 119static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr)
 120{
 121    if (virtio_access_is_big_endian(vdev)) {
 122        return lduw_be_p(ptr);
 123    } else {
 124        return lduw_le_p(ptr);
 125    }
 126}
 127
 128static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr)
 129{
 130    if (virtio_access_is_big_endian(vdev)) {
 131        return ldl_be_p(ptr);
 132    } else {
 133        return ldl_le_p(ptr);
 134    }
 135}
 136
 137static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr)
 138{
 139    if (virtio_access_is_big_endian(vdev)) {
 140        return ldq_be_p(ptr);
 141    } else {
 142        return ldq_le_p(ptr);
 143    }
 144}
 145
 146static inline bool virtio_needs_swap(VirtIODevice *vdev)
 147{
 148#ifdef HOST_WORDS_BIGENDIAN
 149    return virtio_access_is_big_endian(vdev) ? false : true;
 150#else
 151    return virtio_access_is_big_endian(vdev) ? true : false;
 152#endif
 153}
 154
 155static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s)
 156{
 157#ifdef HOST_WORDS_BIGENDIAN
 158    return virtio_access_is_big_endian(vdev) ? s : bswap16(s);
 159#else
 160    return virtio_access_is_big_endian(vdev) ? bswap16(s) : s;
 161#endif
 162}
 163
 164static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s)
 165{
 166    *s = virtio_tswap16(vdev, *s);
 167}
 168
 169static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s)
 170{
 171#ifdef HOST_WORDS_BIGENDIAN
 172    return virtio_access_is_big_endian(vdev) ? s : bswap32(s);
 173#else
 174    return virtio_access_is_big_endian(vdev) ? bswap32(s) : s;
 175#endif
 176}
 177
 178static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s)
 179{
 180    *s = virtio_tswap32(vdev, *s);
 181}
 182
 183static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s)
 184{
 185#ifdef HOST_WORDS_BIGENDIAN
 186    return virtio_access_is_big_endian(vdev) ? s : bswap64(s);
 187#else
 188    return virtio_access_is_big_endian(vdev) ? bswap64(s) : s;
 189#endif
 190}
 191
 192static inline void virtio_tswap64s(VirtIODevice *vdev, uint64_t *s)
 193{
 194    *s = virtio_tswap64(vdev, *s);
 195}
 196#endif /* _QEMU_VIRTIO_ACCESS_H */
 197