Skip to content

Commit 242719f

Browse files
committed
Kernel/xHCI: Add optional TRB logging
1 parent 3fcdaeb commit 242719f

File tree

5 files changed

+331
-0
lines changed

5 files changed

+331
-0
lines changed

Kernel/Bus/USB/xHCI/DataStructures.cpp

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
* SPDX-License-Identifier: BSD-2-Clause
66
*/
77

8+
#include <AK/StringBuilder.h>
89
#include <AK/StringView.h>
910
#include <Kernel/Bus/USB/xHCI/DataStructures.h>
11+
#include <Kernel/Memory/PhysicalAddress.h>
1012

1113
namespace Kernel::USB::xHCI {
1214

@@ -164,4 +166,293 @@ StringView enum_to_string(TransferRequestBlock::TRBType trb_type)
164166
}
165167
}
166168

169+
void TransferRequestBlock::dump(StringView prefix) const
170+
{
171+
auto print_line = [prefix]<typename... Parameters>(CheckedFormatString<Parameters...>&& fmt, Parameters const&... parameters) {
172+
AK::StringBuilder builder;
173+
174+
builder.append(prefix);
175+
176+
AK::VariadicFormatParams<AK::AllowDebugOnlyFormatters::Yes, Parameters...> variadic_format_params { parameters... };
177+
AK::vformat(builder, fmt.view(), variadic_format_params).release_value_but_fixme_should_propagate_errors();
178+
179+
dbgln("{}", builder.string_view());
180+
};
181+
182+
switch (generic.transfer_request_block_type) {
183+
using enum TransferRequestBlock::TRBType;
184+
185+
case Normal: {
186+
auto data_buffer = PhysicalAddress { normal.data_buffer_pointer_low | static_cast<u64>(normal.data_buffer_pointer_high) << 32 };
187+
print_line("Data Buffer: {}", data_buffer);
188+
print_line("TRB Transfer Length: {:#x}", normal.transfer_request_block_transfer_length);
189+
print_line("TD Size: {:#x}", normal.transfer_descriptor_size);
190+
print_line("Interrupter Target: {:#x}", normal.interrupter_target);
191+
print_line("Cycle bit: {}", normal.cycle_bit);
192+
print_line("Evaluate Next TRB: {}", normal.evaluate_next_transfer_request_block);
193+
print_line("Interrupt-on Short Packet: {}", normal.interrupt_on_short_packet);
194+
print_line("No Snoop: {}", normal.no_snoop);
195+
print_line("Chain bit: {}", normal.chain_bit);
196+
print_line("Interrupt On Completion: {}", normal.interrupt_on_completion);
197+
print_line("Immediate Data: {}", normal.immediate_data);
198+
print_line("Block Event Interrupt: {}", normal.block_event_interrupt);
199+
break;
200+
}
201+
case Setup_Stage:
202+
print_line("bmRequestType: {:#x}", setup_stage.request_type);
203+
print_line("bRequest: {:#x}", setup_stage.request);
204+
print_line("wValue: {:#x}", setup_stage.value);
205+
print_line("wIndex: {:#x}", setup_stage.index);
206+
print_line("wLength: {:#x}", setup_stage.length);
207+
print_line("TRB Transfer Length: {:#x}", setup_stage.transfer_request_block_transfer_length);
208+
print_line("Interrupter Target: {:#x}", setup_stage.interrupter_target);
209+
print_line("Cycle bit: {}", setup_stage.cycle_bit);
210+
print_line("Interrupt On Completion: {}", setup_stage.interrupt_on_completion);
211+
print_line("Immediate Data: {}", setup_stage.immediate_data);
212+
print_line("Transfer Type: {:#x}", to_underlying(setup_stage.transfer_type));
213+
break;
214+
case Data_Stage: {
215+
auto data_buffer = PhysicalAddress { data_stage.data_buffer_low | static_cast<u64>(data_stage.data_buffer_high) << 32 };
216+
print_line("Data Buffer: {}", data_buffer);
217+
print_line("TRB Transfer Length: {:#x}", data_stage.transfer_request_block_transfer_length);
218+
print_line("TD Size: {:#x}", data_stage.transfer_descriptor_size);
219+
print_line("Interrupter Target: {:#x}", data_stage.interrupter_target);
220+
print_line("Cycle bit: {}", data_stage.cycle_bit);
221+
print_line("Evaluate Next TRB: {}", data_stage.evaluate_next_transfer_request_block);
222+
print_line("Interrupt-on Short Packet: {}", data_stage.interrupt_on_short_packet);
223+
print_line("No Snoop: {}", data_stage.no_snoop);
224+
print_line("Chain bit: {}", data_stage.chain_bit);
225+
print_line("Interrupt On Completion: {}", data_stage.interrupt_on_completion);
226+
print_line("Immediate Data: {}", data_stage.immediate_data);
227+
print_line("Direction: {}", data_stage.direction);
228+
break;
229+
}
230+
case Status_Stage:
231+
print_line("Interrupter Target: {:#x}", status_stage.interrupter_target);
232+
print_line("Cycle bit: {}", status_stage.cycle_bit);
233+
print_line("Evaluate Next TRB: {}", status_stage.evaluate_next_transfer_request_block);
234+
print_line("Chain bit: {}", status_stage.chain_bit);
235+
print_line("Interrupt On Completion: {}", setup_stage.interrupt_on_completion);
236+
print_line("Direction: {}", status_stage.direction);
237+
break;
238+
case Isoch: {
239+
auto data_buffer = PhysicalAddress { isoch.data_buffer_pointer_low | static_cast<u64>(isoch.data_buffer_pointer_high) << 32 };
240+
print_line("Data Buffer: {}", data_buffer);
241+
print_line("TRB Transfer Length: {:#x}", isoch.transfer_request_block_transfer_length);
242+
print_line("TD Size/TBC: {:#x}", isoch.transfer_descriptor_size_OR_transfer_burst_count);
243+
print_line("Interrupter Target: {:#x}", isoch.interrupter_target);
244+
print_line("Cycle bit: {}", isoch.cycle_bit);
245+
print_line("Evaluate Next TRB: {}", isoch.evaluate_next_transfer_request_block);
246+
print_line("Interrupt-on Short Packet: {}", isoch.interrupt_on_short_packet);
247+
print_line("No Snoop: {}", isoch.no_snoop);
248+
print_line("Chain bit: {}", isoch.chain_bit);
249+
print_line("Interrupt On Completion: {}", isoch.interrupt_on_completion);
250+
print_line("Immediate Data: {}", isoch.immediate_data);
251+
print_line("Transfer Burst Count/TRB Status: {:#x}", isoch.transfer_burst_count_OR_transfer_request_block_status_OR_reserved0);
252+
print_line("Block Event Interrupt: {}", isoch.block_event_interrupt);
253+
print_line("Transfer Last Burst Packet Count: {:#x}", isoch.transfer_last_burst_packet_count);
254+
print_line("Frame ID: {:#x}", isoch.frame_id);
255+
print_line("Start Isoch ASAP: {}", isoch.start_isoch_as_soon_as_possible);
256+
break;
257+
}
258+
case Link: {
259+
auto ring_segment_pointer = PhysicalAddress { link.ring_segment_pointer_low | static_cast<u64>(link.ring_segment_pointer_high) << 32 };
260+
print_line("Ring Segment Pointer: {}", ring_segment_pointer);
261+
print_line("Interrupter Target: {:#x}", link.interrupter_target);
262+
print_line("Cycle bit: {}", link.cycle_bit);
263+
print_line("Toggle Cycle: {}", link.toggle_cycle);
264+
print_line("Chain bit: {}", link.chain_bit);
265+
print_line("Interrupt On Completion: {}", link.interrupt_on_completion);
266+
break;
267+
}
268+
case Event_Data: {
269+
auto event_data_ptr = PhysicalAddress { event_data.event_data_low | static_cast<u64>(event_data.event_data_high) << 32 };
270+
print_line("Event Data: {}", event_data_ptr);
271+
print_line("Interrupter Target: {:#x}", event_data.interrupter_target);
272+
print_line("Cycle bit: {}", event_data.cycle_bit);
273+
print_line("Evaluate Next TRB: {}", event_data.evaluate_next_transfer_request_block);
274+
print_line("Chain bit: {}", event_data.chain_bit);
275+
print_line("Interrupt On Completion: {}", event_data.interrupt_on_completion);
276+
print_line("Block Event Interrupt: {}", event_data.block_event_interrupt);
277+
break;
278+
}
279+
case No_Op:
280+
print_line("Interrupter Target: {:#x}", no_op.interrupter_target);
281+
print_line("Cycle bit: {}", no_op.cycle_bit);
282+
print_line("Evaluate Next TRB: {}", no_op.evaluate_next_transfer_request_block);
283+
print_line("Chain bit: {}", no_op.chain_bit);
284+
print_line("Interrupt On Completion: {}", no_op.interrupt_on_completion);
285+
break;
286+
case Enable_Slot_Command:
287+
print_line("Cycle bit: {}", enable_slot_command.cycle_bit);
288+
print_line("Slot Type: {:#x}", enable_slot_command.slot_type);
289+
break;
290+
case Disable_Slot_Command:
291+
print_line("Cycle bit: {}", disable_slot_command.cycle_bit);
292+
print_line("Slot ID: {}", disable_slot_command.slot_id);
293+
break;
294+
case Address_Device_Command: {
295+
auto input_context_pointer = PhysicalAddress { address_device_command.input_context_pointer_low | static_cast<u64>(address_device_command.input_context_pointer_high) << 32 };
296+
print_line("Input Context Pointer: {}", input_context_pointer);
297+
print_line("Cycle bit: {}", address_device_command.cycle_bit);
298+
print_line("Block Set Address Request: {}", address_device_command.block_set_address_request);
299+
print_line("Slot ID: {}", address_device_command.slot_id);
300+
break;
301+
}
302+
case Configure_Endpoint_Command: {
303+
auto input_context_pointer = PhysicalAddress { configure_endpoint_command.input_context_pointer_low | static_cast<u64>(configure_endpoint_command.input_context_pointer_high) << 32 };
304+
print_line("Input Context Pointer: {}", input_context_pointer);
305+
print_line("Cycle bit: {}", configure_endpoint_command.cycle_bit);
306+
print_line("Deconfigure: {}", configure_endpoint_command.deconfigure);
307+
print_line("Slot ID: {}", configure_endpoint_command.slot_id);
308+
break;
309+
}
310+
case Evaluate_Context_Command: {
311+
auto input_context_pointer = PhysicalAddress { evaluate_context_command.input_context_pointer_low | static_cast<u64>(evaluate_context_command.input_context_pointer_high) << 32 };
312+
print_line("Input Context Pointer: {}", input_context_pointer);
313+
print_line("Cycle bit: {}", evaluate_context_command.cycle_bit);
314+
print_line("Slot ID: {}", evaluate_context_command.slot_id);
315+
break;
316+
}
317+
case Reset_Endpoint_Command:
318+
print_line("Cycle bit: {}", reset_endpoint_command.cycle_bit);
319+
print_line("Transfer State Preserve: {}", reset_endpoint_command.transfer_state_preserve);
320+
print_line("Endpoint ID: {}", reset_endpoint_command.endpoint_id);
321+
print_line("Slot ID: {}", reset_endpoint_command.slot_id);
322+
break;
323+
case Stop_Endpoint_Command:
324+
print_line("Cycle bit: {}", stop_endpoint_command.cycle_bit);
325+
print_line("Endpoint ID: {}", stop_endpoint_command.endpoint_id);
326+
print_line("Suspend: {}", stop_endpoint_command.suspend);
327+
print_line("Slot ID: {}", stop_endpoint_command.slot_id);
328+
break;
329+
case Set_TR_Dequeue_Pointer_Command: {
330+
auto new_tr_dequeue_pointer = PhysicalAddress { set_tr_dequeue_pointer_command.new_tr_dequeue_pointer_low | static_cast<u64>(set_tr_dequeue_pointer_command.new_tr_dequeue_pointer_high) << 32 };
331+
print_line("Dequeue Cycle State: {}", set_tr_dequeue_pointer_command.dequeue_cycle_state);
332+
print_line("Stream Context Type: {:#x}", set_tr_dequeue_pointer_command.stream_context_type);
333+
print_line("New TR Dequeue Pointer: {}", new_tr_dequeue_pointer);
334+
print_line("Stream ID: {:#x}", set_tr_dequeue_pointer_command.stream_id);
335+
print_line("Cycle bit: {}", set_tr_dequeue_pointer_command.cycle_bit);
336+
print_line("Endpoint ID: {}", set_tr_dequeue_pointer_command.endpoint_id);
337+
print_line("Slot ID: {}", set_tr_dequeue_pointer_command.slot_id);
338+
break;
339+
}
340+
case Reset_Device_Command:
341+
print_line("Cycle bit: {}", reset_device_command.cycle_bit);
342+
print_line("Slot ID: {}", reset_device_command.slot_id);
343+
break;
344+
case Force_Event_Command: {
345+
auto event_trb_pointer = PhysicalAddress { force_event_command.event_transfer_request_block_pointer_low | static_cast<u64>(force_event_command.event_transfer_request_block_pointer_high) << 32 };
346+
print_line("Event TRB Pointer: {}", event_trb_pointer);
347+
print_line("VF Interrupter Target: {:#x}", force_event_command.vf_interrupter_target);
348+
print_line("Cycle bit: {}", force_event_command.cycle_bit);
349+
print_line("VF ID: {:#x}", force_event_command.vf_id);
350+
break;
351+
}
352+
case Negotiate_Bandwidth_Command:
353+
print_line("Cycle bit: {}", negotiate_bandwidth_command.cycle_bit);
354+
print_line("Slot ID: {}", negotiate_bandwidth_command.slot_id);
355+
break;
356+
case Set_Latency_Tolerance_Value_Command:
357+
print_line("Cycle bit: {}", set_latency_tolerance_value_command.cycle_bit);
358+
print_line("Best Effort Latency Tolerance Value: {:#x}", set_latency_tolerance_value_command.best_effort_latency_tolerance_value);
359+
break;
360+
case Get_Port_Bandwidth_Command: {
361+
auto port_bandwidth_context_pointer = PhysicalAddress { get_port_bandwidth_command.port_bandwidth_context_pointer_low | static_cast<u64>(get_port_bandwidth_command.port_bandwidth_context_pointer_high) << 32 };
362+
print_line("Port Bandwidth Context Pointer: {}", port_bandwidth_context_pointer);
363+
print_line("Cycle bit: {}", get_port_bandwidth_command.cycle_bit);
364+
print_line("Device Speed: {:#x}", get_port_bandwidth_command.device_speed);
365+
print_line("Hub Slot ID: {}", get_port_bandwidth_command.hub_slot_id);
366+
break;
367+
}
368+
case Force_Header_Command: {
369+
auto header_info = PhysicalAddress { force_header_command.header_info_low | static_cast<u64>(force_header_command.header_info_high) << 32 };
370+
print_line("Packet Type: {:#x}", force_header_command.packet_type);
371+
print_line("Header Info: {:#x}", header_info);
372+
print_line("Cycle bit: {}", force_header_command.cycle_bit);
373+
print_line("Root Hub Port Number: {:#x}", force_header_command.root_hub_port_number);
374+
break;
375+
}
376+
case No_Op_Command:
377+
print_line("Cycle bit: {}", no_op_command.cycle_bit);
378+
break;
379+
case Get_Extended_Property_Command: {
380+
auto extended_property_context_pointer = PhysicalAddress { get_extended_property_command.extended_property_context_pointer_low | static_cast<u64>(get_extended_property_command.extended_property_context_pointer_high) << 32 };
381+
print_line("Extended Property Context Pointer: {}", extended_property_context_pointer);
382+
print_line("Extended Capability Identifier: {:#x}", get_extended_property_command.extended_capability_identifier);
383+
print_line("Cycle bit: {}", get_extended_property_command.cycle_bit);
384+
print_line("Command SubType: {:#x}", get_extended_property_command.command_sub_type);
385+
print_line("Endpoint ID: {}", get_extended_property_command.endpoint_id);
386+
print_line("Slot ID: {}", get_extended_property_command.slot_id);
387+
break;
388+
}
389+
case Set_Extended_Property_Command:
390+
print_line("Extended Capability Identifier: {:#x}", set_extended_property_command.extended_capability_identifier);
391+
print_line("Capability Parameter: {:#x}", set_extended_property_command.capability_parameter);
392+
print_line("Cycle bit: {}", set_extended_property_command.cycle_bit);
393+
print_line("Command SubType: {:#x}", set_extended_property_command.command_sub_type);
394+
print_line("Endpoint ID: {}", set_extended_property_command.endpoint_id);
395+
print_line("Slot ID: {}", set_extended_property_command.slot_id);
396+
break;
397+
case Transfer_Event: {
398+
auto trb_pointer = PhysicalAddress { transfer_event.transfer_request_block_pointer_low | static_cast<u64>(transfer_event.transfer_request_block_pointer_high) << 32 };
399+
print_line("TRB Pointer: {}", trb_pointer);
400+
print_line("TRB Transfer Length: {:#x}", transfer_event.transfer_request_block_transfer_length);
401+
print_line("Completion Code: {}", enum_to_string(transfer_event.completion_code));
402+
print_line("Cycle bit: {}", transfer_event.cycle_bit);
403+
print_line("Event Data: {}", transfer_event.event_data);
404+
print_line("Endpoint ID: {}", transfer_event.endpoint_id);
405+
print_line("Slot ID: {}", transfer_event.slot_id);
406+
break;
407+
}
408+
case Command_Completion_Event: {
409+
auto command_trb_pointer = PhysicalAddress { command_completion_event.command_transfer_request_block_pointer_low | static_cast<u64>(command_completion_event.command_transfer_request_block_pointer_high) << 32 };
410+
print_line("Command TRB Pointer: {}", command_trb_pointer);
411+
print_line("Command Completion Parameter: {:#x}", command_completion_event.command_completion_parameter);
412+
print_line("Completion Code: {}", enum_to_string(command_completion_event.completion_code));
413+
print_line("Cycle bit: {}", command_completion_event.cycle_bit);
414+
print_line("VF ID: {}", command_completion_event.vf_id);
415+
print_line("Slot ID: {}", command_completion_event.slot_id);
416+
break;
417+
}
418+
case Port_Status_Change_Event:
419+
print_line("Port ID: {}", port_status_change_event.port_id);
420+
print_line("Completion Code: {}", enum_to_string(port_status_change_event.completion_code));
421+
print_line("Cycle bit: {}", port_status_change_event.cycle_bit);
422+
break;
423+
case Bandwidth_Request_Event:
424+
print_line("Completion Code: {}", enum_to_string(bandwidth_request_event.completion_code));
425+
print_line("Cycle bit: {}", bandwidth_request_event.cycle_bit);
426+
print_line("Slot ID: {}", bandwidth_request_event.slot_id);
427+
break;
428+
case Doorbell_Event:
429+
print_line("DB Reason: {:#x}", doorbell_event.doorbell_reason);
430+
print_line("Completion Code: {}", enum_to_string(doorbell_event.completion_code));
431+
print_line("Cycle bit: {}", doorbell_event.cycle_bit);
432+
print_line("VF ID: {}", doorbell_event.vf_id);
433+
print_line("Slot ID: {}", doorbell_event.slot_id);
434+
break;
435+
case Host_Controller_Event:
436+
print_line("Completion Code: {}", enum_to_string(host_controller_event.completion_code));
437+
print_line("Cycle bit: {}", host_controller_event.cycle_bit);
438+
break;
439+
case Device_Notification_Event: {
440+
auto device_notification_data = PhysicalAddress { device_notification_event.device_notification_data_low | static_cast<u64>(device_notification_event.device_notification_data_high) << 32 };
441+
print_line("Notification Type: {:#x}", device_notification_event.notification_type);
442+
print_line("Device Notification Data: {:#x}", device_notification_data);
443+
print_line("Completion Code: {}", enum_to_string(device_notification_event.completion_code));
444+
print_line("Cycle bit: {}", device_notification_event.cycle_bit);
445+
print_line("Slot ID: {}", device_notification_event.slot_id);
446+
break;
447+
}
448+
case Microframe_Index_Wrap_Event:
449+
print_line("Completion Code: {}", enum_to_string(microframe_index_wrap_event.completion_code));
450+
print_line("Cycle bit: {}", microframe_index_wrap_event.cycle_bit);
451+
break;
452+
default:
453+
print_line("-- Unknown --");
454+
break;
455+
}
456+
}
457+
167458
}

Kernel/Bus/USB/xHCI/DataStructures.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
namespace Kernel::USB::xHCI {
1515

1616
union TransferRequestBlock {
17+
void dump(StringView prefix) const;
18+
1719
enum class TRBType : u32 {
1820
Normal = 1,
1921
Setup_Stage = 2,

0 commit comments

Comments
 (0)