summaryrefslogtreecommitdiffstats
path: root/hw/s390x/css.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/s390x/css.c')
-rw-r--r--hw/s390x/css.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index c29068b..c02f5bc 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -60,10 +60,72 @@ typedef struct ChannelSubSys {
CssImage *css[MAX_CSSID + 1];
uint8_t default_cssid;
QTAILQ_HEAD(, IoAdapter) io_adapters;
+ QTAILQ_HEAD(, IndAddr) indicator_addresses;
} ChannelSubSys;
static ChannelSubSys *channel_subsys;
+IndAddr *get_indicator(hwaddr ind_addr, int len)
+{
+ IndAddr *indicator;
+
+ QTAILQ_FOREACH(indicator, &channel_subsys->indicator_addresses, sibling) {
+ if (indicator->addr == ind_addr) {
+ indicator->refcnt++;
+ return indicator;
+ }
+ }
+ indicator = g_new0(IndAddr, 1);
+ indicator->addr = ind_addr;
+ indicator->len = len;
+ indicator->refcnt = 1;
+ QTAILQ_INSERT_TAIL(&channel_subsys->indicator_addresses,
+ indicator, sibling);
+ return indicator;
+}
+
+static int s390_io_adapter_map(AdapterInfo *adapter, uint64_t map_addr,
+ bool do_map)
+{
+ S390FLICState *fs = s390_get_flic();
+ S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
+
+ return fsc->io_adapter_map(fs, adapter->adapter_id, map_addr, do_map);
+}
+
+void release_indicator(AdapterInfo *adapter, IndAddr *indicator)
+{
+ assert(indicator->refcnt > 0);
+ indicator->refcnt--;
+ if (indicator->refcnt > 0) {
+ return;
+ }
+ QTAILQ_REMOVE(&channel_subsys->indicator_addresses, indicator, sibling);
+ if (indicator->map) {
+ s390_io_adapter_map(adapter, indicator->map, false);
+ }
+ g_free(indicator);
+}
+
+int map_indicator(AdapterInfo *adapter, IndAddr *indicator)
+{
+ int ret;
+
+ if (indicator->map) {
+ return 0; /* already mapped is not an error */
+ }
+ indicator->map = indicator->addr;
+ ret = s390_io_adapter_map(adapter, indicator->map, true);
+ if ((ret != 0) && (ret != -ENOSYS)) {
+ goto out_err;
+ }
+ return 0;
+
+out_err:
+ indicator->map = 0;
+ return ret;
+}
+
int css_create_css_image(uint8_t cssid, bool default_image)
{
trace_css_new_image(cssid, default_image ? "(default)" : "");
@@ -1524,6 +1586,7 @@ static void css_init(void)
channel_subsys->crws_lost = false;
channel_subsys->chnmon_active = false;
QTAILQ_INIT(&channel_subsys->io_adapters);
+ QTAILQ_INIT(&channel_subsys->indicator_addresses);
}
machine_init(css_init);
OpenPOWER on IntegriCloud