]> git.proxmox.com Git - mirror_qemu.git/blob - pc-bios/s390-ccw/cio.c
Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request' into...
[mirror_qemu.git] / pc-bios / s390-ccw / cio.c
1 /*
2 * S390 Channel I/O
3 *
4 * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
5 * Copyright (c) 2019 IBM Corp.
6 *
7 * Author(s): Jason J. Herne <jjherne@us.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or (at
10 * your option) any later version. See the COPYING file in the top-level
11 * directory.
12 */
13
14 #include "libc.h"
15 #include "s390-ccw.h"
16 #include "s390-arch.h"
17 #include "helper.h"
18 #include "cio.h"
19
20 static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
21
22 static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb);
23
24 int enable_mss_facility(void)
25 {
26 int ret;
27 ChscAreaSda *sda_area = (ChscAreaSda *) chsc_page;
28
29 memset(sda_area, 0, PAGE_SIZE);
30 sda_area->request.length = 0x0400;
31 sda_area->request.code = 0x0031;
32 sda_area->operation_code = 0x2;
33
34 ret = chsc(sda_area);
35 if ((ret == 0) && (sda_area->response.code == 0x0001)) {
36 return 0;
37 }
38 return -EIO;
39 }
40
41 void enable_subchannel(SubChannelId schid)
42 {
43 Schib schib;
44
45 stsch_err(schid, &schib);
46 schib.pmcw.ena = 1;
47 msch(schid, &schib);
48 }
49
50 uint16_t cu_type(SubChannelId schid)
51 {
52 Ccw1 sense_id_ccw;
53 SenseId sense_data;
54
55 sense_id_ccw.cmd_code = CCW_CMD_SENSE_ID;
56 sense_id_ccw.cda = ptr2u32(&sense_data);
57 sense_id_ccw.count = sizeof(sense_data);
58 sense_id_ccw.flags |= CCW_FLAG_SLI;
59
60 if (do_cio(schid, CU_TYPE_UNKNOWN, ptr2u32(&sense_id_ccw), CCW_FMT1)) {
61 panic("Failed to run SenseID CCw\n");
62 }
63
64 return sense_data.cu_type;
65 }
66
67 int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data,
68 uint16_t data_size)
69 {
70 Ccw1 senseCcw;
71 Irb irb;
72
73 senseCcw.cmd_code = CCW_CMD_BASIC_SENSE;
74 senseCcw.cda = ptr2u32(sense_data);
75 senseCcw.count = data_size;
76
77 return __do_cio(schid, ptr2u32(&senseCcw), CCW_FMT1, &irb);
78 }
79
80 static bool irb_error(Irb *irb)
81 {
82 if (irb->scsw.cstat) {
83 return true;
84 }
85 return irb->scsw.dstat != (SCSW_DSTAT_DEVEND | SCSW_DSTAT_CHEND);
86 }
87
88 static void print_eckd_dasd_sense_data(SenseDataEckdDasd *sd)
89 {
90 char msgline[512];
91
92 if (sd->config_info & 0x8000) {
93 sclp_print("Eckd Dasd Sense Data (fmt 24-bytes):\n");
94 } else {
95 sclp_print("Eckd Dasd Sense Data (fmt 32-bytes):\n");
96 }
97
98 strcat(msgline, " Sense Condition Flags :");
99 if (sd->common_status & SNS_STAT0_CMD_REJECT) {
100 strcat(msgline, " [Cmd-Reject]");
101 }
102 if (sd->common_status & SNS_STAT0_INTERVENTION_REQ) {
103 strcat(msgline, " [Intervention-Required]");
104 }
105 if (sd->common_status & SNS_STAT0_BUS_OUT_CHECK) {
106 strcat(msgline, " [Bus-Out-Parity-Check]");
107 }
108 if (sd->common_status & SNS_STAT0_EQUIPMENT_CHECK) {
109 strcat(msgline, " [Equipment-Check]");
110 }
111 if (sd->common_status & SNS_STAT0_DATA_CHECK) {
112 strcat(msgline, " [Data-Check]");
113 }
114 if (sd->common_status & SNS_STAT0_OVERRUN) {
115 strcat(msgline, " [Overrun]");
116 }
117 if (sd->common_status & SNS_STAT0_INCOMPL_DOMAIN) {
118 strcat(msgline, " [Incomplete-Domain]");
119 }
120
121 if (sd->status[0] & SNS_STAT1_PERM_ERR) {
122 strcat(msgline, " [Permanent-Error]");
123 }
124 if (sd->status[0] & SNS_STAT1_INV_TRACK_FORMAT) {
125 strcat(msgline, " [Invalid-Track-Fmt]");
126 }
127 if (sd->status[0] & SNS_STAT1_EOC) {
128 strcat(msgline, " [End-of-Cyl]");
129 }
130 if (sd->status[0] & SNS_STAT1_MESSAGE_TO_OPER) {
131 strcat(msgline, " [Operator-Msg]");
132 }
133 if (sd->status[0] & SNS_STAT1_NO_REC_FOUND) {
134 strcat(msgline, " [No-Record-Found]");
135 }
136 if (sd->status[0] & SNS_STAT1_FILE_PROTECTED) {
137 strcat(msgline, " [File-Protected]");
138 }
139 if (sd->status[0] & SNS_STAT1_WRITE_INHIBITED) {
140 strcat(msgline, " [Write-Inhibited]");
141 }
142 if (sd->status[0] & SNS_STAT1_IMPRECISE_END) {
143 strcat(msgline, " [Imprecise-Ending]");
144 }
145
146 if (sd->status[1] & SNS_STAT2_REQ_INH_WRITE) {
147 strcat(msgline, " [Req-Inhibit-Write]");
148 }
149 if (sd->status[1] & SNS_STAT2_CORRECTABLE) {
150 strcat(msgline, " [Correctable-Data-Check]");
151 }
152 if (sd->status[1] & SNS_STAT2_FIRST_LOG_ERR) {
153 strcat(msgline, " [First-Error-Log]");
154 }
155 if (sd->status[1] & SNS_STAT2_ENV_DATA_PRESENT) {
156 strcat(msgline, " [Env-Data-Present]");
157 }
158 if (sd->status[1] & SNS_STAT2_IMPRECISE_END) {
159 strcat(msgline, " [Imprecise-End]");
160 }
161 strcat(msgline, "\n");
162 sclp_print(msgline);
163
164 print_int(" Residual Count =", sd->res_count);
165 print_int(" Phys Drive ID =", sd->phys_drive_id);
166 print_int(" low cyl address =", sd->low_cyl_addr);
167 print_int(" head addr & hi cyl =", sd->head_high_cyl_addr);
168 print_int(" format/message =", sd->fmt_msg);
169 print_int(" fmt-dependent[0-7] =", sd->fmt_dependent_info[0]);
170 print_int(" fmt-dependent[8-15]=", sd->fmt_dependent_info[1]);
171 print_int(" prog action code =", sd->program_action_code);
172 print_int(" Configuration info =", sd->config_info);
173 print_int(" mcode / hi-cyl =", sd->mcode_hicyl);
174 print_int(" cyl & head addr [0]=", sd->cyl_head_addr[0]);
175 print_int(" cyl & head addr [1]=", sd->cyl_head_addr[1]);
176 print_int(" cyl & head addr [2]=", sd->cyl_head_addr[2]);
177 }
178
179 static void print_irb_err(Irb *irb)
180 {
181 uint64_t this_ccw = *(uint64_t *)u32toptr(irb->scsw.cpa);
182 uint64_t prev_ccw = *(uint64_t *)u32toptr(irb->scsw.cpa - 8);
183 char msgline[256];
184
185 sclp_print("Interrupt Response Block Data:\n");
186
187 strcat(msgline, " Function Ctrl :");
188 if (irb->scsw.ctrl & SCSW_FCTL_START_FUNC) {
189 strcat(msgline, " [Start]");
190 }
191 if (irb->scsw.ctrl & SCSW_FCTL_HALT_FUNC) {
192 strcat(msgline, " [Halt]");
193 }
194 if (irb->scsw.ctrl & SCSW_FCTL_CLEAR_FUNC) {
195 strcat(msgline, " [Clear]");
196 }
197 strcat(msgline, "\n");
198 sclp_print(msgline);
199
200 msgline[0] = '\0';
201 strcat(msgline, " Activity Ctrl :");
202 if (irb->scsw.ctrl & SCSW_ACTL_RESUME_PEND) {
203 strcat(msgline, " [Resume-Pending]");
204 }
205 if (irb->scsw.ctrl & SCSW_ACTL_START_PEND) {
206 strcat(msgline, " [Start-Pending]");
207 }
208 if (irb->scsw.ctrl & SCSW_ACTL_HALT_PEND) {
209 strcat(msgline, " [Halt-Pending]");
210 }
211 if (irb->scsw.ctrl & SCSW_ACTL_CLEAR_PEND) {
212 strcat(msgline, " [Clear-Pending]");
213 }
214 if (irb->scsw.ctrl & SCSW_ACTL_CH_ACTIVE) {
215 strcat(msgline, " [Channel-Active]");
216 }
217 if (irb->scsw.ctrl & SCSW_ACTL_DEV_ACTIVE) {
218 strcat(msgline, " [Device-Active]");
219 }
220 if (irb->scsw.ctrl & SCSW_ACTL_SUSPENDED) {
221 strcat(msgline, " [Suspended]");
222 }
223 strcat(msgline, "\n");
224 sclp_print(msgline);
225
226 msgline[0] = '\0';
227 strcat(msgline, " Status Ctrl :");
228 if (irb->scsw.ctrl & SCSW_SCTL_ALERT) {
229 strcat(msgline, " [Alert]");
230 }
231 if (irb->scsw.ctrl & SCSW_SCTL_INTERMED) {
232 strcat(msgline, " [Intermediate]");
233 }
234 if (irb->scsw.ctrl & SCSW_SCTL_PRIMARY) {
235 strcat(msgline, " [Primary]");
236 }
237 if (irb->scsw.ctrl & SCSW_SCTL_SECONDARY) {
238 strcat(msgline, " [Secondary]");
239 }
240 if (irb->scsw.ctrl & SCSW_SCTL_STATUS_PEND) {
241 strcat(msgline, " [Status-Pending]");
242 }
243
244 strcat(msgline, "\n");
245 sclp_print(msgline);
246
247 msgline[0] = '\0';
248 strcat(msgline, " Device Status :");
249 if (irb->scsw.dstat & SCSW_DSTAT_ATTN) {
250 strcat(msgline, " [Attention]");
251 }
252 if (irb->scsw.dstat & SCSW_DSTAT_STATMOD) {
253 strcat(msgline, " [Status-Modifier]");
254 }
255 if (irb->scsw.dstat & SCSW_DSTAT_CUEND) {
256 strcat(msgline, " [Ctrl-Unit-End]");
257 }
258 if (irb->scsw.dstat & SCSW_DSTAT_BUSY) {
259 strcat(msgline, " [Busy]");
260 }
261 if (irb->scsw.dstat & SCSW_DSTAT_CHEND) {
262 strcat(msgline, " [Channel-End]");
263 }
264 if (irb->scsw.dstat & SCSW_DSTAT_DEVEND) {
265 strcat(msgline, " [Device-End]");
266 }
267 if (irb->scsw.dstat & SCSW_DSTAT_UCHK) {
268 strcat(msgline, " [Unit-Check]");
269 }
270 if (irb->scsw.dstat & SCSW_DSTAT_UEXCP) {
271 strcat(msgline, " [Unit-Exception]");
272 }
273 strcat(msgline, "\n");
274 sclp_print(msgline);
275
276 msgline[0] = '\0';
277 strcat(msgline, " Channel Status :");
278 if (irb->scsw.cstat & SCSW_CSTAT_PCINT) {
279 strcat(msgline, " [Program-Ctrl-Interruption]");
280 }
281 if (irb->scsw.cstat & SCSW_CSTAT_BADLEN) {
282 strcat(msgline, " [Incorrect-Length]");
283 }
284 if (irb->scsw.cstat & SCSW_CSTAT_PROGCHK) {
285 strcat(msgline, " [Program-Check]");
286 }
287 if (irb->scsw.cstat & SCSW_CSTAT_PROTCHK) {
288 strcat(msgline, " [Protection-Check]");
289 }
290 if (irb->scsw.cstat & SCSW_CSTAT_CHDCHK) {
291 strcat(msgline, " [Channel-Data-Check]");
292 }
293 if (irb->scsw.cstat & SCSW_CSTAT_CHCCHK) {
294 strcat(msgline, " [Channel-Ctrl-Check]");
295 }
296 if (irb->scsw.cstat & SCSW_CSTAT_ICCHK) {
297 strcat(msgline, " [Interface-Ctrl-Check]");
298 }
299 if (irb->scsw.cstat & SCSW_CSTAT_CHAINCHK) {
300 strcat(msgline, " [Chaining-Check]");
301 }
302 strcat(msgline, "\n");
303 sclp_print(msgline);
304
305 print_int(" cpa=", irb->scsw.cpa);
306 print_int(" prev_ccw=", prev_ccw);
307 print_int(" this_ccw=", this_ccw);
308 }
309
310 /*
311 * Handles executing ssch, tsch and returns the irb obtained from tsch.
312 * Returns 0 on success, -1 if unexpected status pending and we need to retry,
313 * otherwise returns condition code from ssch/tsch for error cases.
314 */
315 static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb)
316 {
317 CmdOrb orb = {};
318 int rc;
319
320 IPL_assert(fmt == 0 || fmt == 1, "Invalid ccw format");
321
322 /* ccw_addr must be <= 24 bits and point to at least one whole ccw. */
323 if (fmt == 0) {
324 IPL_assert(ccw_addr <= 0xFFFFFF - 8, "Invalid ccw address");
325 }
326
327 orb.fmt = fmt;
328 orb.pfch = 1; /* QEMU's cio implementation requires prefetch */
329 orb.c64 = 1; /* QEMU's cio implementation requires 64-bit idaws */
330 orb.lpm = 0xFF; /* All paths allowed */
331 orb.cpa = ccw_addr;
332
333 rc = ssch(schid, &orb);
334 if (rc == 1 || rc == 2) {
335 /* Subchannel status pending or busy. Eat status and ask for retry. */
336 tsch(schid, irb);
337 return -1;
338 }
339 if (rc) {
340 print_int("ssch failed with cc=", rc);
341 return rc;
342 }
343
344 consume_io_int();
345
346 /* collect status */
347 rc = tsch(schid, irb);
348 if (rc) {
349 print_int("tsch failed with cc=", rc);
350 }
351
352 return rc;
353 }
354
355 /*
356 * Executes a channel program at a given subchannel. The request to run the
357 * channel program is sent to the subchannel, we then wait for the interrupt
358 * signaling completion of the I/O operation(s) performed by the channel
359 * program. Lastly we verify that the i/o operation completed without error and
360 * that the interrupt we received was for the subchannel used to run the
361 * channel program.
362 *
363 * Note: This function assumes it is running in an environment where no other
364 * cpus are generating or receiving I/O interrupts. So either run it in a
365 * single-cpu environment or make sure all other cpus are not doing I/O and
366 * have I/O interrupts masked off. We also assume that only one device is
367 * active (generating i/o interrupts).
368 *
369 * Returns non-zero on error.
370 */
371 int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt)
372 {
373 Irb irb = {};
374 SenseDataEckdDasd sd;
375 int rc, retries = 0;
376
377 while (true) {
378 rc = __do_cio(schid, ccw_addr, fmt, &irb);
379
380 if (rc == -1) {
381 retries++;
382 continue;
383 }
384 if (rc) {
385 /* ssch/tsch error. Message already reported by __do_cio */
386 break;
387 }
388
389 if (!irb_error(&irb)) {
390 break;
391 }
392
393 /*
394 * Unexpected unit check, or interface-control-check. Use sense to
395 * clear (unit check only) then retry.
396 */
397 if ((unit_check(&irb) || iface_ctrl_check(&irb)) && retries <= 2) {
398 if (unit_check(&irb)) {
399 basic_sense(schid, cutype, &sd, sizeof(sd));
400 }
401 retries++;
402 continue;
403 }
404
405 sclp_print("cio device error\n");
406 print_int(" ssid ", schid.ssid);
407 print_int(" cssid ", schid.cssid);
408 print_int(" sch_no", schid.sch_no);
409 print_int(" ctrl-unit type", cutype);
410 sclp_print("\n");
411 print_irb_err(&irb);
412 if (cutype == CU_TYPE_DASD_3990 || cutype == CU_TYPE_DASD_2107 ||
413 cutype == CU_TYPE_UNKNOWN) {
414 if (!basic_sense(schid, cutype, &sd, sizeof(sd))) {
415 print_eckd_dasd_sense_data(&sd);
416 }
417 }
418 rc = -1;
419 break;
420 }
421
422 return rc;
423 }