aboutsummaryrefslogtreecommitdiff
path: root/include/hw/ppc/spapr_vio.h
blob: e87f8e6f59648db689a7894b0b1150244259c250 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#ifndef HW_SPAPR_VIO_H
#define HW_SPAPR_VIO_H

/*
 * QEMU sPAPR VIO bus definitions
 *
 * Copyright (c) 2010 David Gibson, IBM Corporation <david@gibson.dropbear.id.au>
 * Based on the s390 virtio bus definitions:
 * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */

#include "hw/ppc/spapr.h"
#include "sysemu/dma.h"
#include "hw/irq.h"
#include "qom/object.h"

#define TYPE_VIO_SPAPR_DEVICE "vio-spapr-device"
OBJECT_DECLARE_TYPE(SpaprVioDevice, SpaprVioDeviceClass,
                    VIO_SPAPR_DEVICE)

#define TYPE_SPAPR_VIO_BUS "spapr-vio-bus"
OBJECT_DECLARE_SIMPLE_TYPE(SpaprVioBus, SPAPR_VIO_BUS)

#define TYPE_SPAPR_VIO_BRIDGE "spapr-vio-bridge"

typedef struct SpaprVioCrq {
    uint64_t qladdr;
    uint32_t qsize;
    uint32_t qnext;
    int(*SendFunc)(struct SpaprVioDevice *vdev, uint8_t *crq);
} SpaprVioCrq;


struct SpaprVioDeviceClass {
    DeviceClass parent_class;

    const char *dt_name, *dt_type, *dt_compatible;
    target_ulong signal_mask;
    uint32_t rtce_window_size;
    void (*realize)(SpaprVioDevice *dev, Error **errp);
    void (*reset)(SpaprVioDevice *dev);
    int (*devnode)(SpaprVioDevice *dev, void *fdt, int node_off);
    const char *(*get_dt_compatible)(SpaprVioDevice *dev);
};

struct SpaprVioDevice {
    DeviceState qdev;
    uint32_t reg;
    uint32_t irq;
    uint64_t signal_state;
    SpaprVioCrq crq;
    AddressSpace as;
    MemoryRegion mrroot;
    MemoryRegion mrbypass;
    SpaprTceTable *tcet;
};

#define DEFINE_SPAPR_PROPERTIES(type, field)           \
        DEFINE_PROP_UINT32("reg", type, field.reg, -1)

struct SpaprVioBus {
    BusState bus;
    uint32_t next_reg;
};

SpaprVioBus *spapr_vio_bus_init(void);
SpaprVioDevice *spapr_vio_find_by_reg(SpaprVioBus *bus, uint32_t reg);
void spapr_dt_vdevice(SpaprVioBus *bus, void *fdt);
gchar *spapr_vio_stdout_path(SpaprVioBus *bus);

static inline void spapr_vio_irq_pulse(SpaprVioDevice *dev)
{
    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());

    qemu_irq_pulse(spapr_qirq(spapr, dev->irq));
}

static inline bool spapr_vio_dma_valid(SpaprVioDevice *dev, uint64_t taddr,
                                       uint32_t size, DMADirection dir)
{
    return dma_memory_valid(&dev->as, taddr, size, dir, MEMTXATTRS_UNSPECIFIED);
}

static inline int spapr_vio_dma_read(SpaprVioDevice *dev, uint64_t taddr,
                                     void *buf, uint32_t size)
{
    return (dma_memory_read(&dev->as, taddr,
                            buf, size, MEMTXATTRS_UNSPECIFIED) != 0) ?
        H_DEST_PARM : H_SUCCESS;
}

static inline int spapr_vio_dma_write(SpaprVioDevice *dev, uint64_t taddr,
                                      const void *buf, uint32_t size)
{
    return (dma_memory_write(&dev->as, taddr,
                             buf, size, MEMTXATTRS_UNSPECIFIED) != 0) ?
        H_DEST_PARM : H_SUCCESS;
}

static inline int spapr_vio_dma_set(SpaprVioDevice *dev, uint64_t taddr,
                                    uint8_t c, uint32_t size)
{
    return (dma_memory_set(&dev->as, taddr,
                           c, size, MEMTXATTRS_UNSPECIFIED) != 0) ?
        H_DEST_PARM : H_SUCCESS;
}

#define vio_stb(_dev, _addr, _val) \
        (stb_dma(&(_dev)->as, (_addr), (_val), MEMTXATTRS_UNSPECIFIED))
#define vio_sth(_dev, _addr, _val) \
        (stw_be_dma(&(_dev)->as, (_addr), (_val), MEMTXATTRS_UNSPECIFIED))
#define vio_stl(_dev, _addr, _val) \
        (stl_be_dma(&(_dev)->as, (_addr), (_val), MEMTXATTRS_UNSPECIFIED))
#define vio_stq(_dev, _addr, _val) \
        (stq_be_dma(&(_dev)->as, (_addr), (_val), MEMTXATTRS_UNSPECIFIED))
#define vio_ldq(_dev, _addr) (ldq_be_dma(&(_dev)->as, (_addr)))

int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq);

SpaprVioDevice *vty_lookup(SpaprMachineState *spapr, target_ulong reg);
void vty_putchars(SpaprVioDevice *sdev, uint8_t *buf, int len);
void spapr_vty_create(SpaprVioBus *bus, Chardev *chardev);
void spapr_vlan_create(SpaprVioBus *bus, NICInfo *nd);
void spapr_vscsi_create(SpaprVioBus *bus);

SpaprVioDevice *spapr_vty_get_default(SpaprVioBus *bus);

extern const VMStateDescription vmstate_spapr_vio;

#define VMSTATE_SPAPR_VIO(_f, _s) \
    VMSTATE_STRUCT(_f, _s, 0, vmstate_spapr_vio, SpaprVioDevice)

void spapr_vio_set_bypass(SpaprVioDevice *dev, bool bypass);

#endif /* HW_SPAPR_VIO_H */