qemu

Форк
0
/
3270-ccw.c 
181 строка · 4.5 Кб
1
/*
2
 * Emulated ccw-attached 3270 implementation
3
 *
4
 * Copyright 2017 IBM Corp.
5
 * Author(s): Yang Chen <bjcyang@linux.vnet.ibm.com>
6
 *            Jing Liu <liujbjl@linux.vnet.ibm.com>
7
 *
8
 * This work is licensed under the terms of the GNU GPL, version 2 or (at
9
 * your option) any later version. See the COPYING file in the top-level
10
 * directory.
11
 */
12

13
#include "qemu/osdep.h"
14
#include "qapi/error.h"
15
#include "qemu/module.h"
16
#include "hw/s390x/css.h"
17
#include "hw/s390x/css-bridge.h"
18
#include "hw/qdev-properties.h"
19
#include "hw/s390x/3270-ccw.h"
20

21
/* Handle READ ccw commands from guest */
22
static int handle_payload_3270_read(EmulatedCcw3270Device *dev, CCW1 *ccw)
23
{
24
    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
25
    CcwDevice *ccw_dev = CCW_DEVICE(dev);
26
    int len;
27

28
    if (!ccw->cda) {
29
        return -EFAULT;
30
    }
31

32
    len = ck->read_payload_3270(dev);
33
    if (len < 0) {
34
        return len;
35
    }
36
    ccw_dev->sch->curr_status.scsw.count = ccw->count - len;
37

38
    return 0;
39
}
40

41
/* Handle WRITE ccw commands to write data to client */
42
static int handle_payload_3270_write(EmulatedCcw3270Device *dev, CCW1 *ccw)
43
{
44
    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
45
    CcwDevice *ccw_dev = CCW_DEVICE(dev);
46
    int len;
47

48
    if (!ccw->cda) {
49
        return -EFAULT;
50
    }
51

52
    len = ck->write_payload_3270(dev, ccw->cmd_code);
53

54
    if (len <= 0) {
55
        return len ? len : -EIO;
56
    }
57

58
    ccw_dev->sch->curr_status.scsw.count = ccw->count - len;
59
    return 0;
60
}
61

62
static int emulated_ccw_3270_cb(SubchDev *sch, CCW1 ccw)
63
{
64
    int rc = 0;
65
    EmulatedCcw3270Device *dev = sch->driver_data;
66

67
    switch (ccw.cmd_code) {
68
    case TC_WRITESF:
69
    case TC_WRITE:
70
    case TC_EWRITE:
71
    case TC_EWRITEA:
72
        rc = handle_payload_3270_write(dev, &ccw);
73
        break;
74
    case TC_RDBUF:
75
    case TC_READMOD:
76
        rc = handle_payload_3270_read(dev, &ccw);
77
        break;
78
    default:
79
        rc = -ENOSYS;
80
        break;
81
    }
82

83
    if (rc == -EIO) {
84
        /* I/O error, specific devices generate specific conditions */
85
        SCHIB *schib = &sch->curr_status;
86

87
        sch->curr_status.scsw.dstat = SCSW_DSTAT_UNIT_CHECK;
88
        sch->sense_data[0] = 0x40;    /* intervention-req */
89
        schib->scsw.ctrl &= ~SCSW_ACTL_START_PEND;
90
        schib->scsw.ctrl &= ~SCSW_CTRL_MASK_STCTL;
91
        schib->scsw.ctrl |= SCSW_STCTL_PRIMARY | SCSW_STCTL_SECONDARY |
92
                   SCSW_STCTL_ALERT | SCSW_STCTL_STATUS_PEND;
93
    }
94

95
    return rc;
96
}
97

98
static void emulated_ccw_3270_realize(DeviceState *ds, Error **errp)
99
{
100
    uint16_t chpid;
101
    EmulatedCcw3270Device *dev = EMULATED_CCW_3270(ds);
102
    EmulatedCcw3270Class *ck = EMULATED_CCW_3270_GET_CLASS(dev);
103
    CcwDevice *cdev = CCW_DEVICE(ds);
104
    CCWDeviceClass *cdk = CCW_DEVICE_GET_CLASS(cdev);
105
    SubchDev *sch;
106
    Error *err = NULL;
107

108
    sch = css_create_sch(cdev->devno, errp);
109
    if (!sch) {
110
        return;
111
    }
112

113
    if (!ck->init) {
114
        goto out_err;
115
    }
116

117
    sch->driver_data = dev;
118
    cdev->sch = sch;
119
    chpid = css_find_free_chpid(sch->cssid);
120

121
    if (chpid > MAX_CHPID) {
122
        error_setg(&err, "No available chpid to use.");
123
        goto out_err;
124
    }
125

126
    sch->id.reserved = 0xff;
127
    sch->id.cu_type = EMULATED_CCW_3270_CU_TYPE;
128
    css_sch_build_virtual_schib(sch, (uint8_t)chpid,
129
                                EMULATED_CCW_3270_CHPID_TYPE);
130
    sch->do_subchannel_work = do_subchannel_work_virtual;
131
    sch->ccw_cb = emulated_ccw_3270_cb;
132
    sch->irb_cb = build_irb_virtual;
133

134
    ck->init(dev, &err);
135
    if (err) {
136
        goto out_err;
137
    }
138

139
    cdk->realize(cdev, &err);
140
    if (err) {
141
        goto out_err;
142
    }
143

144
    return;
145

146
out_err:
147
    error_propagate(errp, err);
148
    css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
149
    cdev->sch = NULL;
150
    g_free(sch);
151
}
152

153
static Property emulated_ccw_3270_properties[] = {
154
    DEFINE_PROP_END_OF_LIST(),
155
};
156

157
static void emulated_ccw_3270_class_init(ObjectClass *klass, void *data)
158
{
159
    DeviceClass *dc = DEVICE_CLASS(klass);
160

161
    device_class_set_props(dc, emulated_ccw_3270_properties);
162
    dc->realize = emulated_ccw_3270_realize;
163
    dc->hotpluggable = false;
164
    set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
165
}
166

167
static const TypeInfo emulated_ccw_3270_info = {
168
    .name = TYPE_EMULATED_CCW_3270,
169
    .parent = TYPE_CCW_DEVICE,
170
    .instance_size = sizeof(EmulatedCcw3270Device),
171
    .class_init = emulated_ccw_3270_class_init,
172
    .class_size = sizeof(EmulatedCcw3270Class),
173
    .abstract = true,
174
};
175

176
static void emulated_ccw_register(void)
177
{
178
    type_register_static(&emulated_ccw_3270_info);
179
}
180

181
type_init(emulated_ccw_register)
182

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.