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
dump_scsw_flags(uint32_t f)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] = {};
dump_pmcw_flags(uint16_t f)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
dump_scsw(struct scsw * s)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
dump_irb(struct irb * irbp)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
dump_pmcw(struct pmcw * p)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
dump_schib(struct schib * sch)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
dump_ccw(struct ccw1 * cp)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
dump_orb(struct orb * op)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