qemu/include/hw/remote-port-proto.h
<<
>>
Prefs
   1/*
   2 * QEMU remote port protocol parts.
   3 *
   4 * Copyright (c) 2013 Xilinx Inc
   5 * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a copy
   8 * of this software and associated documentation files (the "Software"), to deal
   9 * in the Software without restriction, including without limitation the rights
  10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 * copies of the Software, and to permit persons to whom the Software is
  12 * furnished to do so, subject to the following conditions:
  13 *
  14 * The above copyright notice and this permission notice shall be included in
  15 * all copies or substantial portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 * THE SOFTWARE.
  24 */
  25#ifndef REMOTE_PORT_PROTO_H__
  26#define REMOTE_PORT_PROTO_H__
  27
  28#include <stdbool.h>
  29#include <string.h>
  30
  31/*
  32 * Remote-Port (RP) is an inter-simulator protocol. It assumes a reliable
  33 * point to point communcation with the remote simulation environment.
  34 *
  35 * Setup
  36 * In the SETUP phase a mandatory HELLO packet is exchanged with optional
  37 * CFG packets following. HELLO packets are useful to ensure that both
  38 * sides are speaking the same protocol and using compatible versions.
  39 *
  40 * CFG packets are used to negotiate configuration options. At the moment
  41 * these remain unimplemented.
  42 *
  43 * Once the session is up, communication can start through various other
  44 * commands. The list can be found further down this document.
  45 * Commands are carried over RP packets. Every RP packet contains a header
  46 * with length, flags and an ID to track potential responses.
  47 * The header is followed by a packet specific payload. You'll find the
  48 * details of the various commands packet layouts here. Some commands can
  49 * carry data/blobs in their payload.
  50 */
  51
  52
  53#define RP_VERSION_MAJOR 4
  54#define RP_VERSION_MINOR 0
  55
  56#if defined(_WIN32) && defined(__MINGW32__)
  57/* mingw GCC has a bug with packed attributes.  */
  58#define PACKED __attribute__ ((gcc_struct, packed))
  59#else
  60#define PACKED __attribute__ ((packed))
  61#endif
  62
  63/* Could be auto generated.  */
  64enum rp_cmd {
  65    RP_CMD_nop         = 0,
  66    RP_CMD_hello       = 1,
  67    RP_CMD_cfg         = 2,
  68    RP_CMD_read        = 3,
  69    RP_CMD_write       = 4,
  70    RP_CMD_interrupt   = 5,
  71    RP_CMD_sync        = 6,
  72    RP_CMD_max         = 6
  73};
  74
  75enum {
  76    RP_OPT_quantum = 0,
  77};
  78
  79struct rp_cfg_state {
  80    uint64_t quantum;
  81};
  82
  83enum {
  84    RP_PKT_FLAGS_optional      = 1 << 0,
  85    RP_PKT_FLAGS_response      = 1 << 1,
  86};
  87
  88struct rp_pkt_hdr {
  89    uint32_t cmd;
  90    uint32_t len;
  91    uint32_t id;
  92    uint32_t flags;
  93    uint32_t dev;
  94} PACKED;
  95
  96struct rp_pkt_cfg {
  97    struct rp_pkt_hdr hdr;
  98    uint32_t opt;
  99    uint8_t set;
 100} PACKED;
 101
 102struct rp_version {
 103    uint16_t major;
 104    uint16_t minor;
 105} PACKED;
 106
 107struct rp_pkt_hello {
 108    struct rp_pkt_hdr hdr;
 109    struct rp_version version;
 110} PACKED;
 111
 112
 113enum {
 114    RP_BUS_ATTR_EOP        =  (1 << 0),
 115    RP_BUS_ATTR_SECURE     =  (1 << 1),
 116};
 117
 118struct rp_pkt_busaccess {
 119    struct rp_pkt_hdr hdr;
 120    uint64_t timestamp;
 121    uint64_t attributes;
 122    uint64_t addr;
 123
 124    /* Length in bytes.  */
 125    uint32_t len;
 126
 127    /* Width of each beat in bytes. Set to zero for unknown (let the remote
 128       side choose).  */
 129    uint32_t width;
 130
 131    /* Width of streaming, must be a multiple of width.
 132       addr should repeat itself around this width. Set to same as len
 133       for incremental (normal) accesses.  In bytes.  */
 134    uint32_t stream_width;
 135
 136    /* Implementation specific source or master-id.  */
 137    uint16_t master_id;
 138} PACKED;
 139
 140struct rp_pkt_interrupt {
 141    struct rp_pkt_hdr hdr;
 142    uint64_t timestamp;
 143    uint64_t vector;
 144    uint32_t line;
 145    uint8_t val;
 146} PACKED;
 147
 148struct rp_pkt_sync {
 149    struct rp_pkt_hdr hdr;
 150    uint64_t timestamp;
 151} PACKED;
 152
 153struct rp_pkt {
 154    union {
 155        struct rp_pkt_hdr hdr;
 156        struct rp_pkt_hello hello;
 157        struct rp_pkt_busaccess busaccess;
 158        struct rp_pkt_interrupt interrupt;
 159        struct rp_pkt_sync sync;
 160    };
 161};
 162
 163struct rp_peer_state {
 164    void *opaque;
 165
 166    struct rp_pkt pkt;
 167    bool hdr_used;
 168
 169    struct rp_version version;
 170
 171    /* Used to normalize our clk.  */
 172    int64_t clk_base;
 173
 174    struct rp_cfg_state local_cfg;
 175    struct rp_cfg_state peer_cfg;
 176};
 177
 178const char *rp_cmd_to_string(enum rp_cmd cmd);
 179int rp_decode_hdr(struct rp_pkt *pkt);
 180int rp_decode_payload(struct rp_pkt *pkt);
 181
 182void rp_encode_hdr(struct rp_pkt_hdr *hdr,
 183                   uint32_t cmd, uint32_t id, uint32_t dev, uint32_t len,
 184                   uint32_t flags);
 185
 186size_t rp_encode_hello(uint32_t id, uint32_t dev, struct rp_pkt_hello *pkt,
 187                       uint16_t version_major, uint16_t version_minor);
 188
 189static inline void *rp_busaccess_dataptr(struct rp_pkt_busaccess *pkt)
 190{
 191    /* Right after the packet.  */
 192    return pkt + 1;
 193}
 194
 195size_t rp_encode_read(uint32_t id, uint32_t dev,
 196                      struct rp_pkt_busaccess *pkt,
 197                      int64_t clk, uint16_t master_id,
 198                      uint64_t addr, uint32_t attr, uint32_t size,
 199                      uint32_t width, uint32_t stream_width);
 200
 201size_t rp_encode_read_resp(uint32_t id, uint32_t dev,
 202                           struct rp_pkt_busaccess *pkt,
 203                           int64_t clk, uint16_t master_id,
 204                           uint64_t addr, uint32_t attr, uint32_t size,
 205                           uint32_t width, uint32_t stream_width);
 206
 207size_t rp_encode_write(uint32_t id, uint32_t dev,
 208                       struct rp_pkt_busaccess *pkt,
 209                       int64_t clk, uint16_t master_id,
 210                       uint64_t addr, uint32_t attr, uint32_t size,
 211                       uint32_t width, uint32_t stream_width);
 212
 213size_t rp_encode_write_resp(uint32_t id, uint32_t dev,
 214                       struct rp_pkt_busaccess *pkt,
 215                       int64_t clk, uint16_t master_id,
 216                       uint64_t addr, uint32_t attr, uint32_t size,
 217                       uint32_t width, uint32_t stream_width);
 218
 219size_t rp_encode_interrupt(uint32_t id, uint32_t dev,
 220                           struct rp_pkt_interrupt *pkt,
 221                           int64_t clk,
 222                           uint32_t line, uint64_t vector, uint8_t val);
 223
 224size_t rp_encode_sync(uint32_t id, uint32_t dev,
 225                      struct rp_pkt_sync *pkt,
 226                      int64_t clk);
 227
 228size_t rp_encode_sync_resp(uint32_t id, uint32_t dev,
 229                           struct rp_pkt_sync *pkt,
 230                           int64_t clk);
 231
 232/* Dynamically resizable remote port pkt.  */
 233
 234typedef struct RemotePortDynPkt {
 235    struct rp_pkt *pkt;
 236    size_t size;
 237} RemotePortDynPkt;
 238
 239/*
 240 * Make sure dpkt is allocated and has enough room.
 241 */
 242
 243void rp_dpkt_alloc(RemotePortDynPkt *dpkt, size_t size);
 244
 245void rp_dpkt_swap(RemotePortDynPkt *a, RemotePortDynPkt *b);
 246
 247/*
 248 * Check if the dpkt is valid. Used for debugging purposes.
 249 */
 250
 251bool rp_dpkt_is_valid(RemotePortDynPkt *dpkt);
 252
 253/*
 254 * Invalidate the dpkt. Used for debugging purposes.
 255 */
 256
 257void rp_dpkt_invalidate(RemotePortDynPkt *dpkt);
 258
 259void rp_dpkt_free(RemotePortDynPkt *dpkt);
 260
 261#endif
 262