xref: /openbmc/linux/tools/firewire/decode-fcp.c (revision 9f6d3c4b76314c40c866a935d78c80fd284768bd)
1*9f6d3c4bSStefan Richter #include <stdlib.h>
2*9f6d3c4bSStefan Richter #include <stdio.h>
3*9f6d3c4bSStefan Richter #include "list.h"
4*9f6d3c4bSStefan Richter #include "nosy-dump.h"
5*9f6d3c4bSStefan Richter 
6*9f6d3c4bSStefan Richter #define CSR_FCP_COMMAND			0xfffff0000b00ull
7*9f6d3c4bSStefan Richter #define CSR_FCP_RESPONSE		0xfffff0000d00ull
8*9f6d3c4bSStefan Richter 
9*9f6d3c4bSStefan Richter static const char * const ctype_names[16] = {
10*9f6d3c4bSStefan Richter     "control",
11*9f6d3c4bSStefan Richter     "status",
12*9f6d3c4bSStefan Richter     "specific inquiry",
13*9f6d3c4bSStefan Richter     "notify",
14*9f6d3c4bSStefan Richter     "general inquiry",
15*9f6d3c4bSStefan Richter     "(reserved 0x05)",
16*9f6d3c4bSStefan Richter     "(reserved 0x06)",
17*9f6d3c4bSStefan Richter     "(reserved 0x07)",
18*9f6d3c4bSStefan Richter     "not implemented",
19*9f6d3c4bSStefan Richter     "accepted",
20*9f6d3c4bSStefan Richter     "rejected",
21*9f6d3c4bSStefan Richter     "in transition",
22*9f6d3c4bSStefan Richter     "stable",
23*9f6d3c4bSStefan Richter     "changed",
24*9f6d3c4bSStefan Richter     "(reserved 0x0e)",
25*9f6d3c4bSStefan Richter     "interim"
26*9f6d3c4bSStefan Richter };
27*9f6d3c4bSStefan Richter 
28*9f6d3c4bSStefan Richter static const char * const subunit_type_names[32] = {
29*9f6d3c4bSStefan Richter     "monitor",
30*9f6d3c4bSStefan Richter     "audio",
31*9f6d3c4bSStefan Richter     "printer",
32*9f6d3c4bSStefan Richter     "disc",
33*9f6d3c4bSStefan Richter     "tape recorder/player",
34*9f6d3c4bSStefan Richter     "tuner",
35*9f6d3c4bSStefan Richter     "ca",
36*9f6d3c4bSStefan Richter     "camera",
37*9f6d3c4bSStefan Richter     "(reserved 0x08)",
38*9f6d3c4bSStefan Richter     "panel",
39*9f6d3c4bSStefan Richter     "bulletin board",
40*9f6d3c4bSStefan Richter     "camera storage",
41*9f6d3c4bSStefan Richter     "(reserved 0x0c)",
42*9f6d3c4bSStefan Richter     "(reserved 0x0d)",
43*9f6d3c4bSStefan Richter     "(reserved 0x0e)",
44*9f6d3c4bSStefan Richter     "(reserved 0x0f)",
45*9f6d3c4bSStefan Richter     "(reserved 0x10)",
46*9f6d3c4bSStefan Richter     "(reserved 0x11)",
47*9f6d3c4bSStefan Richter     "(reserved 0x12)",
48*9f6d3c4bSStefan Richter     "(reserved 0x13)",
49*9f6d3c4bSStefan Richter     "(reserved 0x14)",
50*9f6d3c4bSStefan Richter     "(reserved 0x15)",
51*9f6d3c4bSStefan Richter     "(reserved 0x16)",
52*9f6d3c4bSStefan Richter     "(reserved 0x17)",
53*9f6d3c4bSStefan Richter     "(reserved 0x18)",
54*9f6d3c4bSStefan Richter     "(reserved 0x19)",
55*9f6d3c4bSStefan Richter     "(reserved 0x1a)",
56*9f6d3c4bSStefan Richter     "(reserved 0x1b)",
57*9f6d3c4bSStefan Richter     "vendor unique",
58*9f6d3c4bSStefan Richter     "all subunit types",
59*9f6d3c4bSStefan Richter     "subunit_type extended to next byte",
60*9f6d3c4bSStefan Richter     "unit"
61*9f6d3c4bSStefan Richter };
62*9f6d3c4bSStefan Richter 
63*9f6d3c4bSStefan Richter struct avc_enum {
64*9f6d3c4bSStefan Richter     int value;
65*9f6d3c4bSStefan Richter     const char *name;
66*9f6d3c4bSStefan Richter };
67*9f6d3c4bSStefan Richter 
68*9f6d3c4bSStefan Richter struct avc_field {
69*9f6d3c4bSStefan Richter   const char *name;	/* Short name for field. */
70*9f6d3c4bSStefan Richter   int offset;		/* Location of field, specified in bits.
71*9f6d3c4bSStefan Richter 			 * Negative means from end of packet */
72*9f6d3c4bSStefan Richter   int width;		/* Width of field, 0 means use data_length. */
73*9f6d3c4bSStefan Richter   struct avc_enum *names;
74*9f6d3c4bSStefan Richter };
75*9f6d3c4bSStefan Richter 
76*9f6d3c4bSStefan Richter struct avc_opcode_info {
77*9f6d3c4bSStefan Richter     const char *name;
78*9f6d3c4bSStefan Richter     struct avc_field fields[8];
79*9f6d3c4bSStefan Richter };
80*9f6d3c4bSStefan Richter 
81*9f6d3c4bSStefan Richter struct avc_enum power_field_names[] = {
82*9f6d3c4bSStefan Richter     { 0x70, "on" },
83*9f6d3c4bSStefan Richter     { 0x60, "off" },
84*9f6d3c4bSStefan Richter     { }
85*9f6d3c4bSStefan Richter };
86*9f6d3c4bSStefan Richter 
87*9f6d3c4bSStefan Richter static const struct avc_opcode_info opcode_info[256] = {
88*9f6d3c4bSStefan Richter 
89*9f6d3c4bSStefan Richter     /* TA Document 1999026
90*9f6d3c4bSStefan Richter      * AV/C Digital Interface Command Set General Specification
91*9f6d3c4bSStefan Richter      * Version 4.0 */
92*9f6d3c4bSStefan Richter     [0xb2] =
93*9f6d3c4bSStefan Richter     { "power", {
94*9f6d3c4bSStefan Richter 	    { "state", 0, 8, power_field_names }
95*9f6d3c4bSStefan Richter 	}
96*9f6d3c4bSStefan Richter     },
97*9f6d3c4bSStefan Richter     [0x30] =
98*9f6d3c4bSStefan Richter     { "unit info", {
99*9f6d3c4bSStefan Richter 	    { "foo", 0, 8 },
100*9f6d3c4bSStefan Richter 	    { "unit_type", 8, 5 },
101*9f6d3c4bSStefan Richter 	    { "unit", 13, 3 },
102*9f6d3c4bSStefan Richter 	    { "company id", 16, 24 },
103*9f6d3c4bSStefan Richter 	}
104*9f6d3c4bSStefan Richter     },
105*9f6d3c4bSStefan Richter     [0x31] = { "subunit info" },
106*9f6d3c4bSStefan Richter     [0x01] = { "reserve" },
107*9f6d3c4bSStefan Richter     [0xb0] = { "version" },
108*9f6d3c4bSStefan Richter     [0x00] = { "vendor dependent" },
109*9f6d3c4bSStefan Richter 
110*9f6d3c4bSStefan Richter     [0x02] = { "plug info" },
111*9f6d3c4bSStefan Richter     [0x12] = { "channel usage" },
112*9f6d3c4bSStefan Richter     [0x24] = { "connect" },
113*9f6d3c4bSStefan Richter     [0x20] = { "connect av" },
114*9f6d3c4bSStefan Richter     [0x22] = { "connections" },
115*9f6d3c4bSStefan Richter     [0x11] = { "digital input" },
116*9f6d3c4bSStefan Richter     [0x10] = { "digital output" },
117*9f6d3c4bSStefan Richter     [0x25] = { "disconnect" },
118*9f6d3c4bSStefan Richter     [0x21] = { "disconnect av" },
119*9f6d3c4bSStefan Richter     [0x19] = { "input plug signal format" },
120*9f6d3c4bSStefan Richter     [0x18] = { "output plug signal format" },
121*9f6d3c4bSStefan Richter     [0x1f] = { "general bus setup" },
122*9f6d3c4bSStefan Richter 
123*9f6d3c4bSStefan Richter     /* TA Document 1999025
124*9f6d3c4bSStefan Richter      * AV/C Descriptor Mechanism Specification Version 1.0 */
125*9f6d3c4bSStefan Richter     [0x0c] = { "create descriptor" },
126*9f6d3c4bSStefan Richter     [0x08] = { "open descriptor" },
127*9f6d3c4bSStefan Richter     [0x09] = { "read descriptor" },
128*9f6d3c4bSStefan Richter     [0x0a] = { "write descriptor" },
129*9f6d3c4bSStefan Richter     [0x05] = { "open info block" },
130*9f6d3c4bSStefan Richter     [0x06] = { "read info block" },
131*9f6d3c4bSStefan Richter     [0x07] = { "write info block" },
132*9f6d3c4bSStefan Richter     [0x0b] = { "search descriptor" },
133*9f6d3c4bSStefan Richter     [0x0d] = { "object number select" },
134*9f6d3c4bSStefan Richter 
135*9f6d3c4bSStefan Richter     /* TA Document 1999015
136*9f6d3c4bSStefan Richter      * AV/C Command Set for Rate Control of Isochronous Data Flow 1.0 */
137*9f6d3c4bSStefan Richter     [0xb3] = { "rate", {
138*9f6d3c4bSStefan Richter 	    { "subfunction", 0, 8 },
139*9f6d3c4bSStefan Richter 	    { "result", 8, 8 },
140*9f6d3c4bSStefan Richter 	    { "plug_type", 16, 8 },
141*9f6d3c4bSStefan Richter 	    { "plug_id", 16, 8 },
142*9f6d3c4bSStefan Richter 	}
143*9f6d3c4bSStefan Richter     },
144*9f6d3c4bSStefan Richter 
145*9f6d3c4bSStefan Richter     /* TA Document 1999008
146*9f6d3c4bSStefan Richter      * AV/C Audio Subunit Specification 1.0 */
147*9f6d3c4bSStefan Richter     [0xb8] = { "function block" },
148*9f6d3c4bSStefan Richter 
149*9f6d3c4bSStefan Richter     /* TA Document 2001001
150*9f6d3c4bSStefan Richter      * AV/C Panel Subunit Specification 1.1 */
151*9f6d3c4bSStefan Richter     [0x7d] = { "gui update" },
152*9f6d3c4bSStefan Richter     [0x7e] = { "push gui data" },
153*9f6d3c4bSStefan Richter     [0x7f] = { "user action" },
154*9f6d3c4bSStefan Richter     [0x7c] = { "pass through" },
155*9f6d3c4bSStefan Richter 
156*9f6d3c4bSStefan Richter     /* */
157*9f6d3c4bSStefan Richter     [0x26] = { "asynchronous connection" },
158*9f6d3c4bSStefan Richter };
159*9f6d3c4bSStefan Richter 
160*9f6d3c4bSStefan Richter struct avc_frame {
161*9f6d3c4bSStefan Richter     unsigned int operand0 : 8;
162*9f6d3c4bSStefan Richter     unsigned int opcode : 8;
163*9f6d3c4bSStefan Richter     unsigned int subunit_id : 3;
164*9f6d3c4bSStefan Richter     unsigned int subunit_type : 5;
165*9f6d3c4bSStefan Richter     unsigned int ctype : 4;
166*9f6d3c4bSStefan Richter     unsigned int cts : 4;
167*9f6d3c4bSStefan Richter };
168*9f6d3c4bSStefan Richter 
169*9f6d3c4bSStefan Richter static void
170*9f6d3c4bSStefan Richter decode_avc(struct link_transaction *t)
171*9f6d3c4bSStefan Richter {
172*9f6d3c4bSStefan Richter     struct avc_frame *frame = (struct avc_frame *) t->request->packet.write_block.data;
173*9f6d3c4bSStefan Richter     const struct avc_opcode_info *info;
174*9f6d3c4bSStefan Richter     const char *name;
175*9f6d3c4bSStefan Richter     char buffer[32];
176*9f6d3c4bSStefan Richter     int i;
177*9f6d3c4bSStefan Richter 
178*9f6d3c4bSStefan Richter     info = &opcode_info[frame->opcode];
179*9f6d3c4bSStefan Richter     if (info->name == NULL) {
180*9f6d3c4bSStefan Richter 	snprintf(buffer, sizeof buffer, "(unknown opcode 0x%02x)", frame->opcode);
181*9f6d3c4bSStefan Richter 	name = buffer;
182*9f6d3c4bSStefan Richter     } else {
183*9f6d3c4bSStefan Richter 	name = info->name;
184*9f6d3c4bSStefan Richter     }
185*9f6d3c4bSStefan Richter 
186*9f6d3c4bSStefan Richter     printf("av/c %s, subunit_type=%s, subunit_id=%d, opcode=%s",
187*9f6d3c4bSStefan Richter 	   ctype_names[frame->ctype], subunit_type_names[frame->subunit_type],
188*9f6d3c4bSStefan Richter 	   frame->subunit_id, name);
189*9f6d3c4bSStefan Richter 
190*9f6d3c4bSStefan Richter     for (i = 0; info->fields[i].name != NULL; i++) {
191*9f6d3c4bSStefan Richter 	printf(", %s", info->fields[i].name);
192*9f6d3c4bSStefan Richter     }
193*9f6d3c4bSStefan Richter 
194*9f6d3c4bSStefan Richter     printf("\n");
195*9f6d3c4bSStefan Richter }
196*9f6d3c4bSStefan Richter 
197*9f6d3c4bSStefan Richter 
198*9f6d3c4bSStefan Richter int
199*9f6d3c4bSStefan Richter decode_fcp(struct link_transaction *t)
200*9f6d3c4bSStefan Richter {
201*9f6d3c4bSStefan Richter     struct avc_frame *frame = (struct avc_frame *) t->request->packet.write_block.data;
202*9f6d3c4bSStefan Richter     unsigned long long offset;
203*9f6d3c4bSStefan Richter 
204*9f6d3c4bSStefan Richter     offset = ((unsigned long long) t->request->packet.common.offset_high << 32) |
205*9f6d3c4bSStefan Richter 	t->request->packet.common.offset_low;
206*9f6d3c4bSStefan Richter 
207*9f6d3c4bSStefan Richter     if (t->request->packet.common.tcode != TCODE_WRITE_BLOCK)
208*9f6d3c4bSStefan Richter 	return 0;
209*9f6d3c4bSStefan Richter 
210*9f6d3c4bSStefan Richter     if (offset == CSR_FCP_COMMAND || offset == CSR_FCP_RESPONSE) {
211*9f6d3c4bSStefan Richter 	switch (frame->cts) {
212*9f6d3c4bSStefan Richter 	case 0x00:
213*9f6d3c4bSStefan Richter 	    decode_avc(t);
214*9f6d3c4bSStefan Richter 	    break;
215*9f6d3c4bSStefan Richter 	case 0x01:
216*9f6d3c4bSStefan Richter 	    printf("cal fcp frame (cts=0x01)\n");
217*9f6d3c4bSStefan Richter 	    break;
218*9f6d3c4bSStefan Richter 	case 0x02:
219*9f6d3c4bSStefan Richter 	    printf("ehs fcp frame (cts=0x02)\n");
220*9f6d3c4bSStefan Richter 	    break;
221*9f6d3c4bSStefan Richter 	case 0x03:
222*9f6d3c4bSStefan Richter 	    printf("havi fcp frame (cts=0x03)\n");
223*9f6d3c4bSStefan Richter 	    break;
224*9f6d3c4bSStefan Richter 	case 0x0e:
225*9f6d3c4bSStefan Richter 	    printf("vendor specific fcp frame (cts=0x0e)\n");
226*9f6d3c4bSStefan Richter 	    break;
227*9f6d3c4bSStefan Richter 	case 0x0f:
228*9f6d3c4bSStefan Richter 	    printf("extended cts\n");
229*9f6d3c4bSStefan Richter 	    break;
230*9f6d3c4bSStefan Richter 	default:
231*9f6d3c4bSStefan Richter 	    printf("reserved fcp frame (ctx=0x%02x)\n", frame->cts);
232*9f6d3c4bSStefan Richter 	    break;
233*9f6d3c4bSStefan Richter 	}
234*9f6d3c4bSStefan Richter 	return 1;
235*9f6d3c4bSStefan Richter     }
236*9f6d3c4bSStefan Richter 
237*9f6d3c4bSStefan Richter     return 0;
238*9f6d3c4bSStefan Richter }
239*9f6d3c4bSStefan Richter 
240