diff --git a/Kernel/Bus/USB/USBPipe.cpp b/Kernel/Bus/USB/USBPipe.cpp index 982cc14093..6b0ff1f3cd 100644 --- a/Kernel/Bus/USB/USBPipe.cpp +++ b/Kernel/Bus/USB/USBPipe.cpp @@ -14,10 +14,11 @@ namespace Kernel::USB { ErrorOr> Pipe::try_create_pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, i8 device_address, u8 poll_interval) { - return adopt_nonnull_own_or_enomem(new (nothrow) Pipe(controller, type, direction, endpoint_address, max_packet_size, poll_interval, device_address)); + auto dma_region = TRY(MM.allocate_kernel_region(PAGE_SIZE, "USB device DMA buffer", Memory::Region::Access::ReadWrite)); + return adopt_nonnull_own_or_enomem(new (nothrow) Pipe(controller, type, direction, endpoint_address, max_packet_size, poll_interval, device_address, move(dma_region))); } -Pipe::Pipe(USBController const& controller, Type type, Pipe::Direction direction, u16 max_packet_size) +Pipe::Pipe(USBController const& controller, Type type, Pipe::Direction direction, u16 max_packet_size, NonnullOwnPtr dma_buffer) : m_controller(controller) , m_type(type) , m_direction(direction) @@ -25,18 +26,20 @@ Pipe::Pipe(USBController const& controller, Type type, Pipe::Direction direction , m_max_packet_size(max_packet_size) , m_poll_interval(0) , m_data_toggle(false) + , m_dma_buffer(move(dma_buffer)) { } -Pipe::Pipe(USBController const& controller, Type type, Direction direction, USBEndpointDescriptor& endpoint [[maybe_unused]]) +Pipe::Pipe(USBController const& controller, Type type, Direction direction, USBEndpointDescriptor& endpoint [[maybe_unused]], NonnullOwnPtr dma_buffer) : m_controller(controller) , m_type(type) , m_direction(direction) + , m_dma_buffer(move(dma_buffer)) { // TODO: decode endpoint structure } -Pipe::Pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, u8 poll_interval, i8 device_address) +Pipe::Pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, u8 poll_interval, i8 device_address, NonnullOwnPtr dma_buffer) : m_controller(controller) , m_type(type) , m_direction(direction) @@ -45,11 +48,14 @@ Pipe::Pipe(USBController const& controller, Type type, Direction direction, u8 e , m_max_packet_size(max_packet_size) , m_poll_interval(poll_interval) , m_data_toggle(false) + , m_dma_buffer(move(dma_buffer)) { } ErrorOr Pipe::control_transfer(u8 request_type, u8 request, u16 value, u16 index, u16 length, void* data) { + MutexLocker lock(m_dma_buffer_lock); + USBRequestData usb_request; usb_request.request_type = request_type; @@ -58,7 +64,7 @@ ErrorOr Pipe::control_transfer(u8 request_type, u8 request, u16 value, u usb_request.index = index; usb_request.length = length; - auto transfer = TRY(Transfer::try_create(*this, length)); + auto transfer = TRY(Transfer::try_create(*this, length, *m_dma_buffer)); transfer->set_setup_packet(usb_request); dbgln_if(USB_DEBUG, "Pipe: Transfer allocated @ {}", transfer->buffer_physical()); @@ -74,8 +80,10 @@ ErrorOr Pipe::control_transfer(u8 request_type, u8 request, u16 value, u ErrorOr Pipe::bulk_transfer(u16 length, void* data) { + MutexLocker lock(m_dma_buffer_lock); + size_t transfer_length = 0; - auto transfer = TRY(Transfer::try_create(*this, length)); + auto transfer = TRY(Transfer::try_create(*this, length, *m_dma_buffer)); if (m_direction == Direction::In) { dbgln_if(USB_DEBUG, "Pipe: Bulk in transfer allocated @ {}", transfer->buffer_physical()); diff --git a/Kernel/Bus/USB/USBPipe.h b/Kernel/Bus/USB/USBPipe.h index 0371f80517..2d43203984 100644 --- a/Kernel/Bus/USB/USBPipe.h +++ b/Kernel/Bus/USB/USBPipe.h @@ -9,6 +9,7 @@ #include #include #include +#include #include namespace Kernel::USB { @@ -59,9 +60,9 @@ public: ErrorOr control_transfer(u8 request_type, u8 request, u16 value, u16 index, u16 length, void* data); ErrorOr bulk_transfer(u16 length, void* data); - Pipe(USBController const& controller, Type type, Direction direction, u16 max_packet_size); - Pipe(USBController const& controller, Type type, Direction direction, USBEndpointDescriptor& endpoint); - Pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, u8 poll_interval, i8 device_address); + Pipe(USBController const& controller, Type type, Direction direction, u16 max_packet_size, NonnullOwnPtr dma_buffer); + Pipe(USBController const& controller, Type type, Direction direction, USBEndpointDescriptor& endpoint, NonnullOwnPtr dma_buffer); + Pipe(USBController const& controller, Type type, Direction direction, u8 endpoint_address, u16 max_packet_size, u8 poll_interval, i8 device_address, NonnullOwnPtr dma_buffer); private: friend class Device; @@ -77,5 +78,9 @@ private: u16 m_max_packet_size { 0 }; // Max packet size for this pipe u8 m_poll_interval { 0 }; // Polling interval (in frames) bool m_data_toggle { false }; // Data toggle for stuffing bit + + Mutex m_dma_buffer_lock { "USB pipe mutex" }; + + NonnullOwnPtr m_dma_buffer; }; } diff --git a/Kernel/Bus/USB/USBTransfer.cpp b/Kernel/Bus/USB/USBTransfer.cpp index e664e7ced9..4f489389f2 100644 --- a/Kernel/Bus/USB/USBTransfer.cpp +++ b/Kernel/Bus/USB/USBTransfer.cpp @@ -9,17 +9,14 @@ namespace Kernel::USB { -ErrorOr> Transfer::try_create(Pipe& pipe, u16 length) +ErrorOr> Transfer::try_create(Pipe& pipe, u16 length, Memory::Region& dma_buffer) { - // Initialize data buffer for transfer - // This will definitely need to be refactored in the future, I doubt this will scale well... - auto region = TRY(MM.allocate_kernel_region(PAGE_SIZE, "USB Transfer Buffer", Memory::Region::Access::ReadWrite)); - return adopt_nonnull_ref_or_enomem(new (nothrow) Transfer(pipe, length, move(region))); + return adopt_nonnull_ref_or_enomem(new (nothrow) Transfer(pipe, length, dma_buffer)); } -Transfer::Transfer(Pipe& pipe, u16 len, NonnullOwnPtr data_buffer) +Transfer::Transfer(Pipe& pipe, u16 len, Memory::Region& dma_buffer) : m_pipe(pipe) - , m_data_buffer(move(data_buffer)) + , m_dma_buffer(dma_buffer) , m_transfer_data_size(len) { } @@ -45,7 +42,7 @@ void Transfer::set_setup_packet(USBRequestData const& request) ErrorOr Transfer::write_buffer(u16 len, void* data) { - VERIFY(len <= m_data_buffer->size()); + VERIFY(len <= m_dma_buffer.size()); m_transfer_data_size = len; memcpy(buffer().as_ptr(), data, len); diff --git a/Kernel/Bus/USB/USBTransfer.h b/Kernel/Bus/USB/USBTransfer.h index 914a3c6d72..fe8e7d6713 100644 --- a/Kernel/Bus/USB/USBTransfer.h +++ b/Kernel/Bus/USB/USBTransfer.h @@ -19,7 +19,7 @@ namespace Kernel::USB { class Transfer : public RefCounted { public: - static ErrorOr> try_create(Pipe&, u16 length); + static ErrorOr> try_create(Pipe&, u16 length, Memory::Region& dma_buffer); Transfer() = delete; ~Transfer(); @@ -34,20 +34,20 @@ public: USBRequestData const& request() const { return m_request; } Pipe const& pipe() const { return m_pipe; } Pipe& pipe() { return m_pipe; } - VirtualAddress buffer() const { return m_data_buffer->vaddr(); } - PhysicalAddress buffer_physical() const { return m_data_buffer->physical_page(0)->paddr(); } + VirtualAddress buffer() const { return m_dma_buffer.vaddr(); } + PhysicalAddress buffer_physical() const { return m_dma_buffer.physical_page(0)->paddr(); } u16 transfer_data_size() const { return m_transfer_data_size; } bool complete() const { return m_complete; } bool error_occurred() const { return m_error_occurred; } private: - Transfer(Pipe& pipe, u16 len, NonnullOwnPtr); - Pipe& m_pipe; // Pipe that initiated this transfer - USBRequestData m_request; // USB request - NonnullOwnPtr m_data_buffer; // DMA Data buffer for transaction - u16 m_transfer_data_size { 0 }; // Size of the transfer's data stage - bool m_complete { false }; // Has this transfer been completed? - bool m_error_occurred { false }; // Did an error occur during this transfer? + Transfer(Pipe& pipe, u16 len, Memory::Region& dma_buffer); + Pipe& m_pipe; // Pipe that initiated this transfer + Memory::Region& m_dma_buffer; // DMA buffer + USBRequestData m_request; // USB request + u16 m_transfer_data_size { 0 }; // Size of the transfer's data stage + bool m_complete { false }; // Has this transfer been completed? + bool m_error_occurred { false }; // Did an error occur during this transfer? }; }