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