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