qemu/hw/ssi/remote-port-ssi-slave.c
<<
>>
Prefs
   1/*
   2 * QEMU remote port SSI slave. Write transactions recieved from the remote port
   3 * are sent over an SSI bus.
   4 *
   5 * Copyright (c) 2013 Xilinx Inc
   6 * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com>
   7 *
   8 * This code is licensed under the GNU GPL.
   9 */
  10
  11#include "qemu/osdep.h"
  12#include "sysemu/sysemu.h"
  13#include "qemu/log.h"
  14#include "qapi/qmp/qerror.h"
  15#include "hw/qdev.h"
  16#include "qapi/error.h"
  17#include "hw/ssi/ssi.h"
  18
  19#include "hw/remote-port-proto.h"
  20#include "hw/remote-port-device.h"
  21
  22#define TYPE_REMOTE_PORT_SSI_SLAVE "remote-port-ssi-slave"
  23#define REMOTE_PORT_SSI_SLAVE(obj) \
  24        OBJECT_CHECK(RemotePortSSISlave, (obj), \
  25                     TYPE_REMOTE_PORT_SSI_SLAVE)
  26
  27typedef struct RemotePortSSISlave {
  28    /* private */
  29    DeviceState parent;
  30    /* public */
  31    struct RemotePort *rp;
  32    SSIBus *ssib;
  33
  34    uint16_t num_ssi_devs;
  35} RemotePortSSISlave;
  36
  37static void rp_ssi_slave_write(RemotePortDevice *rpd, struct rp_pkt *pkt)
  38{
  39    RemotePortSSISlave *s = REMOTE_PORT_SSI_SLAVE(rpd);
  40    /* FIXME: be less hardcoded */
  41    size_t pktlen = sizeof(struct rp_pkt_busaccess) + 4;
  42    size_t enclen;
  43    int64_t delay;
  44    uint32_t data, *data_p;
  45    RemotePortDynPkt rsp;
  46
  47    data_p = (uint32_t *)(pkt + 1);
  48    data = be32_to_cpu(*data_p);
  49
  50    assert(!(pkt->hdr.flags & RP_PKT_FLAGS_response));
  51
  52    memset(&rsp, 0, sizeof(rsp));
  53    rp_dpkt_alloc(&rsp, pktlen);
  54
  55    data = ssi_transfer(s->ssib, data);
  56    data_p = (uint32_t *)(rsp.pkt + 1);
  57    *data_p = cpu_to_be32(data);
  58    /* delay here could be set to the annotated cost of doing issuing
  59       these accesses. QEMU doesn't support this kind of annotations
  60       at the moment. So we just clear the delay.  */
  61    delay = 0;
  62
  63    enclen = rp_encode_read_resp(
  64                    pkt->hdr.id, pkt->hdr.dev, &rsp.pkt->busaccess,
  65                    pkt->busaccess.timestamp + delay,
  66                    0,
  67                    pkt->busaccess.addr,
  68                    pkt->busaccess.attributes,
  69                    pkt->busaccess.len,
  70                    pkt->busaccess.width,
  71                    pkt->busaccess.stream_width);
  72    /* FIXME */
  73    assert(enclen == pktlen);
  74
  75    rp_write(s->rp, (void *)rsp.pkt, pktlen);
  76}
  77
  78static void rp_ssi_slave_realize(DeviceState *dev, Error **errp)
  79{
  80    RemotePortSSISlave *s = REMOTE_PORT_SSI_SLAVE(dev);
  81
  82    s->ssib = ssi_create_bus(dev, "ssib");
  83}
  84
  85static void rp_ssi_slave_init(Object *obj)
  86{
  87    RemotePortSSISlave *rpms = REMOTE_PORT_SSI_SLAVE(obj);
  88
  89    object_property_add_link(obj, "rp-adaptor0", "remote-port",
  90                             (Object **)&rpms->rp,
  91                             qdev_prop_allow_set_link_before_realize,
  92                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
  93                             &error_abort);
  94}
  95
  96static Property rp_properties[] = {
  97     DEFINE_PROP_UINT16("num-ssi-devs", RemotePortSSISlave, num_ssi_devs, 1),
  98     DEFINE_PROP_END_OF_LIST(),
  99};
 100
 101static void rp_ssi_slave_class_init(ObjectClass *oc, void *data)
 102{
 103    RemotePortDeviceClass *rpdc = REMOTE_PORT_DEVICE_CLASS(oc);
 104    DeviceClass *dc = DEVICE_CLASS(oc);
 105
 106    rpdc->ops[RP_CMD_write] = rp_ssi_slave_write;
 107    dc->realize = rp_ssi_slave_realize;
 108    dc->props = rp_properties;
 109}
 110
 111static const TypeInfo rp_info = {
 112    .name          = TYPE_REMOTE_PORT_SSI_SLAVE,
 113    .parent        = TYPE_DEVICE,
 114    .instance_size = sizeof(RemotePortSSISlave),
 115    .instance_init = rp_ssi_slave_init,
 116    .class_init    = rp_ssi_slave_class_init,
 117    .interfaces    = (InterfaceInfo[]) {
 118        { TYPE_REMOTE_PORT_DEVICE },
 119        { },
 120    },
 121};
 122
 123static void rp_register_types(void)
 124{
 125    type_register_static(&rp_info);
 126}
 127
 128type_init(rp_register_types)
 129