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#include "qemu/osdep.h"
31#include "hw/sysbus.h"
32#include "qapi/error.h"
33#include "qemu/log.h"
34
35#include "qemu/bitops.h"
36#include "qapi/qmp/qerror.h"
37#include "hw/misc/sss.h"
38
39void sss_notify_all(SSSBase *s)
40{
41 int remote;
42
43 for (remote = 0; remote < s->num_remotes; ++remote) {
44 if (s->notifys[remote]) {
45 s->notifys[remote](s->notify_opaques[remote]);
46 s->notifys[remote] = NULL;
47 }
48 }
49}
50
51static inline int
52sss_lookup_rx_remote(SSSBase *s, SSSStream *ss)
53{
54 int ret;
55
56 for (ret = 0; ret < s->num_remotes; ++ret) {
57 if (ss == &s->rx_devs[ret]) {
58 break;
59 }
60 }
61 return ret;
62}
63
64static inline int
65sss_lookup_tx_remote(SSSBase *s, int rx_remote)
66{
67 uint32_t enc;
68 if (rx_remote == NOT_REMOTE(s)) {
69 return NOT_REMOTE(s);
70 }
71
72 int ret;
73
74 for (ret = 0; ret < NOT_REMOTE(s); ++ret) {
75 if (s->r_sss_shifts[ret] == -1) {
76
77 continue;
78 }
79
80 enc = s->get_sss_regfield(s, ret);
81 if (s->r_sss_encodings[rx_remote] == enc) {
82 break;
83 }
84 }
85 return (s->sss_population[ret] & (1 << rx_remote)) ?
86 ret : NOT_REMOTE(s);
87}
88
89static bool
90sss_stream_can_push(StreamSlave *obj, StreamCanPushNotifyFn notify,
91 void *notify_opaque)
92{
93 SSSStream *ss = SSS_STREAM(obj);
94 SSSBase *s = SSS_BASE(ss->sss);
95 int rx = sss_lookup_rx_remote(s, ss);
96 int tx = sss_lookup_tx_remote(s, rx);
97
98 if (tx != NOT_REMOTE(s) && s->tx_devs[tx] &&
99 stream_can_push(s->tx_devs[tx], notify, notify_opaque)) {
100 return true;
101 }
102
103 s->notifys[rx] = notify;
104 s->notify_opaques[rx] = notify_opaque;
105 return false;
106}
107
108
109
110static size_t sss_stream_push(StreamSlave *obj, uint8_t *buf,
111 size_t len, uint32_t attr)
112{
113 SSSStream *ss = SSS_STREAM(obj);
114 SSSBase *s = SSS_BASE(ss->sss);
115 int rx = sss_lookup_rx_remote(s, ss);
116 int tx = sss_lookup_tx_remote(s, rx);
117
118 return (tx != NOT_REMOTE(s)) ?
119 stream_push(s->tx_devs[tx], buf, len, attr) : 0;
120}
121
122
123
124
125
126static void sss_stream_class_init(ObjectClass *klass, void *data)
127{
128 StreamSlaveClass *ssc = STREAM_SLAVE_CLASS(klass);
129
130 ssc->push = sss_stream_push;
131 ssc->can_push = sss_stream_can_push;
132}
133
134static const TypeInfo sss_info = {
135 .name = TYPE_SSS_BASE,
136 .parent = TYPE_SYS_BUS_DEVICE,
137 .instance_size = sizeof(SSSBase),
138};
139
140static const TypeInfo sss_stream_info = {
141 .name = TYPE_SSS_STREAM,
142 .parent = TYPE_DEVICE,
143 .instance_size = sizeof(SSSStream),
144 .class_init = sss_stream_class_init,
145 .interfaces = (InterfaceInfo[]) {
146 { TYPE_STREAM_SLAVE },
147 { }
148 }
149};
150
151static void sss_register_types(void)
152{
153 type_register_static(&sss_info);
154 type_register_static(&sss_stream_info);
155}
156
157type_init(sss_register_types)
158