|
5 | 5 | * SPDX-License-Identifier: BSD-2-Clause |
6 | 6 | */ |
7 | 7 |
|
| 8 | +#include <AK/StringBuilder.h> |
8 | 9 | #include <AK/StringView.h> |
9 | 10 | #include <Kernel/Bus/USB/xHCI/DataStructures.h> |
| 11 | +#include <Kernel/Memory/PhysicalAddress.h> |
10 | 12 |
|
11 | 13 | namespace Kernel::USB::xHCI { |
12 | 14 |
|
@@ -164,4 +166,293 @@ StringView enum_to_string(TransferRequestBlock::TRBType trb_type) |
164 | 166 | } |
165 | 167 | } |
166 | 168 |
|
| 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 | + |
167 | 458 | } |
0 commit comments