1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Channel subsystem structures dumping 4 * 5 * Copyright (c) 2020 IBM Corp. 6 * 7 * Authors: 8 * Pierre Morel <pmorel@linux.ibm.com> 9 * 10 * Description: 11 * Provides the dumping functions for various structures used by subchannels: 12 * - ORB : Operation request block, describes the I/O operation and points to 13 * a CCW chain 14 * - CCW : Channel Command Word, describes the command, data and flow control 15 * - IRB : Interuption response Block, describes the result of an operation; 16 * holds a SCSW and model-dependent data. 17 * - SCHIB: SubCHannel Information Block composed of: 18 * - SCSW: SubChannel Status Word, status of the channel. 19 * - PMCW: Path Management Control Word 20 * You need the QEMU ccw-pong device in QEMU to answer the I/O transfers. 21 */ 22 23 #include <libcflat.h> 24 #include <stdint.h> 25 #include <string.h> 26 27 #include <css.h> 28 29 /* 30 * Try to have a more human representation of the SCSW flags: 31 * each letter in the two strings represents the first 32 * letter of the associated bit in the flag fields. 33 */ 34 static const char *scsw_str = "kkkkslccfpixuzen"; 35 static const char *scsw_str2 = "1SHCrshcsdsAIPSs"; 36 static char scsw_line[64] = {}; 37 38 char *dump_scsw_flags(uint32_t f) 39 { 40 int i; 41 42 for (i = 0; i < 16; i++) { 43 if ((f << i) & 0x80000000) 44 scsw_line[i] = scsw_str[i]; 45 else 46 scsw_line[i] = '_'; 47 } 48 scsw_line[i] = ' '; 49 for (; i < 32; i++) { 50 if ((f << i) & 0x80000000) 51 scsw_line[i + 1] = scsw_str2[i - 16]; 52 else 53 scsw_line[i + 1] = '_'; 54 } 55 return scsw_line; 56 } 57 58 /* 59 * Try to have a more human representation of the PMCW flags 60 * each letter in the string represents the first 61 * letter of the associated bit in the flag fields. 62 */ 63 static const char *pmcw_str = "11iii111ellmmdtv"; 64 static char pcmw_line[32] = {}; 65 char *dump_pmcw_flags(uint16_t f) 66 { 67 int i; 68 69 for (i = 0; i < 16; i++) { 70 if ((f << i) & 0x8000) 71 pcmw_line[i] = pmcw_str[i]; 72 else 73 pcmw_line[i] = '_'; 74 } 75 return pcmw_line; 76 } 77 78 void dump_scsw(struct scsw *s) 79 { 80 dump_scsw_flags(s->ctrl); 81 printf("scsw->flags: %s\n", scsw_line); 82 printf("scsw->addr : %08x\n", s->ccw_addr); 83 printf("scsw->devs : %02x\n", s->dev_stat); 84 printf("scsw->schs : %02x\n", s->sch_stat); 85 printf("scsw->count: %04x\n", s->count); 86 } 87 88 void dump_irb(struct irb *irbp) 89 { 90 int i; 91 uint32_t *p = (uint32_t *)irbp; 92 93 dump_scsw(&irbp->scsw); 94 for (i = 0; i < sizeof(*irbp)/sizeof(*p); i++, p++) 95 printf("irb[%02x] : %08x\n", i, *p); 96 } 97 98 void dump_pmcw(struct pmcw *p) 99 { 100 int i; 101 102 printf("pmcw->intparm : %08x\n", p->intparm); 103 printf("pmcw->flags : %04x\n", p->flags); 104 dump_pmcw_flags(p->flags); 105 printf("pmcw->devnum : %04x\n", p->devnum); 106 printf("pmcw->lpm : %02x\n", p->lpm); 107 printf("pmcw->pnom : %02x\n", p->pnom); 108 printf("pmcw->lpum : %02x\n", p->lpum); 109 printf("pmcw->pim : %02x\n", p->pim); 110 printf("pmcw->mbi : %04x\n", p->mbi); 111 printf("pmcw->pom : %02x\n", p->pom); 112 printf("pmcw->pam : %02x\n", p->pam); 113 printf("pmcw->mbi : %04x\n", p->mbi); 114 for (i = 0; i < 8; i++) 115 printf("pmcw->chpid[%d]: %02x\n", i, p->chpid[i]); 116 printf("pmcw->flags2 : %08x\n", p->flags2); 117 } 118 119 void dump_schib(struct schib *sch) 120 { 121 struct pmcw *p = &sch->pmcw; 122 struct scsw *s = &sch->scsw; 123 124 printf("--SCHIB--\n"); 125 dump_pmcw(p); 126 dump_scsw(s); 127 } 128 129 struct ccw1 *dump_ccw(struct ccw1 *cp) 130 { 131 printf("CCW: code: %02x flags: %02x count: %04x data: %08x\n", cp->code, 132 cp->flags, cp->count, cp->data_address); 133 134 if (cp->code == CCW_C_TIC) 135 return (struct ccw1 *)(long)cp->data_address; 136 137 return (cp->flags & CCW_F_CC) ? cp + 1 : NULL; 138 } 139 140 void dump_orb(struct orb *op) 141 { 142 struct ccw1 *cp; 143 144 printf("ORB: intparm : %08x\n", op->intparm); 145 printf("ORB: ctrl : %08x\n", op->ctrl); 146 printf("ORB: prio : %08x\n", op->prio); 147 cp = (struct ccw1 *)(long) (op->cpa); 148 while (cp) 149 cp = dump_ccw(cp); 150 } 151