2 * Emulated ccw-attached 3270 implementation
4 * Copyright 2017 IBM Corp.
5 * Author(s): Yang Chen <bjcyang@linux.vnet.ibm.com>
6 * Jing Liu <liujbjl@linux.vnet.ibm.com>
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
12 #include "qemu/osdep.h"
13 #include "qapi/error.h"
14 #include "qemu/module.h"
16 #include "hw/s390x/css.h"
17 #include "hw/s390x/css-bridge.h"
18 #include "hw/s390x/3270-ccw.h"
20 /* Handle READ ccw commands from guest */
21 static int handle_payload_3270_read(EmulatedCcw3270Device
*dev
, CCW1
*ccw
)
23 EmulatedCcw3270Class
*ck
= EMULATED_CCW_3270_GET_CLASS(dev
);
24 CcwDevice
*ccw_dev
= CCW_DEVICE(dev
);
31 len
= ck
->read_payload_3270(dev
, ccw
->cda
, ccw
->count
);
32 ccw_dev
->sch
->curr_status
.scsw
.count
= ccw
->count
- len
;
37 /* Handle WRITE ccw commands to write data to client */
38 static int handle_payload_3270_write(EmulatedCcw3270Device
*dev
, CCW1
*ccw
)
40 EmulatedCcw3270Class
*ck
= EMULATED_CCW_3270_GET_CLASS(dev
);
41 CcwDevice
*ccw_dev
= CCW_DEVICE(dev
);
48 len
= ck
->write_payload_3270(dev
, ccw
->cmd_code
, ccw
->cda
, ccw
->count
);
54 ccw_dev
->sch
->curr_status
.scsw
.count
= ccw
->count
- len
;
58 static int emulated_ccw_3270_cb(SubchDev
*sch
, CCW1 ccw
)
61 EmulatedCcw3270Device
*dev
= sch
->driver_data
;
63 switch (ccw
.cmd_code
) {
68 rc
= handle_payload_3270_write(dev
, &ccw
);
72 rc
= handle_payload_3270_read(dev
, &ccw
);
80 /* I/O error, specific devices generate specific conditions */
81 SCSW
*s
= &sch
->curr_status
.scsw
;
83 sch
->curr_status
.scsw
.dstat
= SCSW_DSTAT_UNIT_CHECK
;
84 sch
->sense_data
[0] = 0x40; /* intervention-req */
85 s
->ctrl
&= ~SCSW_ACTL_START_PEND
;
86 s
->ctrl
&= ~SCSW_CTRL_MASK_STCTL
;
87 s
->ctrl
|= SCSW_STCTL_PRIMARY
| SCSW_STCTL_SECONDARY
|
88 SCSW_STCTL_ALERT
| SCSW_STCTL_STATUS_PEND
;
94 static void emulated_ccw_3270_realize(DeviceState
*ds
, Error
**errp
)
97 EmulatedCcw3270Device
*dev
= EMULATED_CCW_3270(ds
);
98 EmulatedCcw3270Class
*ck
= EMULATED_CCW_3270_GET_CLASS(dev
);
99 CcwDevice
*cdev
= CCW_DEVICE(ds
);
100 CCWDeviceClass
*cdk
= CCW_DEVICE_GET_CLASS(cdev
);
101 DeviceState
*parent
= DEVICE(cdev
);
102 BusState
*qbus
= qdev_get_parent_bus(parent
);
103 VirtualCssBus
*cbus
= VIRTUAL_CSS_BUS(qbus
);
107 sch
= css_create_sch(cdev
->devno
, true, cbus
->squash_mcss
, errp
);
116 sch
->driver_data
= dev
;
118 chpid
= css_find_free_chpid(sch
->cssid
);
120 if (chpid
> MAX_CHPID
) {
121 error_setg(&err
, "No available chpid to use.");
125 sch
->id
.reserved
= 0xff;
126 sch
->id
.cu_type
= EMULATED_CCW_3270_CU_TYPE
;
127 css_sch_build_virtual_schib(sch
, (uint8_t)chpid
,
128 EMULATED_CCW_3270_CHPID_TYPE
);
129 sch
->do_subchannel_work
= do_subchannel_work_virtual
;
130 sch
->ccw_cb
= emulated_ccw_3270_cb
;
137 cdk
->realize(cdev
, &err
);
145 error_propagate(errp
, err
);
146 css_subch_assign(sch
->cssid
, sch
->ssid
, sch
->schid
, sch
->devno
, NULL
);
151 static Property emulated_ccw_3270_properties
[] = {
152 DEFINE_PROP_END_OF_LIST(),
155 static void emulated_ccw_3270_class_init(ObjectClass
*klass
, void *data
)
157 DeviceClass
*dc
= DEVICE_CLASS(klass
);
159 dc
->props
= emulated_ccw_3270_properties
;
160 dc
->bus_type
= TYPE_VIRTUAL_CSS_BUS
;
161 dc
->realize
= emulated_ccw_3270_realize
;
162 dc
->hotpluggable
= false;
165 static const TypeInfo emulated_ccw_3270_info
= {
166 .name
= TYPE_EMULATED_CCW_3270
,
167 .parent
= TYPE_CCW_DEVICE
,
168 .instance_size
= sizeof(EmulatedCcw3270Device
),
169 .class_init
= emulated_ccw_3270_class_init
,
170 .class_size
= sizeof(EmulatedCcw3270Class
),
174 static void emulated_ccw_register(void)
176 type_register_static(&emulated_ccw_3270_info
);
179 type_init(emulated_ccw_register
)