more fifo
Change-Id: Ia5ed1eb7f7df0fe803d7afc101ad806cd20d4951
diff --git a/system/dev/usb/dwc3/dwc3-commands.cpp b/system/dev/usb/dwc3/dwc3-commands.cpp
index a1d2d8e..5315a34 100644
--- a/system/dev/usb/dwc3/dwc3-commands.cpp
+++ b/system/dev/usb/dwc3/dwc3-commands.cpp
@@ -9,6 +9,8 @@
#include <stdio.h>
+namespace dwc3 {
+
static void dwc3_ep_cmd(dwc3_t* dwc, unsigned ep_num, uint32_t command, uint32_t param0,
uint32_t param1, uint32_t param2, uint32_t flags) {
auto* mmio = dwc3_mmio(dwc);
@@ -70,3 +72,5 @@
void dwc3_cmd_ep_clear_stall(dwc3_t* dwc, unsigned ep_num) {
dwc3_ep_cmd(dwc, ep_num, DEPCSTALL, 0, 0, 0, DEPCMD_CMDIOC);
}
+
+} // namespace dwc3
diff --git a/system/dev/usb/dwc3/dwc3-endpoints.cpp b/system/dev/usb/dwc3/dwc3-endpoints.cpp
index e9cbcdd..257db6c 100644
--- a/system/dev/usb/dwc3/dwc3-endpoints.cpp
+++ b/system/dev/usb/dwc3/dwc3-endpoints.cpp
@@ -18,9 +18,7 @@
#define EP_FIFO_SIZE PAGE_SIZE
-static zx_paddr_t dwc3_ep_trb_phys(dwc3_endpoint_t* ep, dwc3_trb_t* trb) {
- return io_buffer_phys(&ep->fifo.buffer) + (trb - ep->fifo.first) * sizeof(*trb);
-}
+namespace dwc3 {
static void dwc3_enable_ep(dwc3_t* dwc, unsigned ep_num, bool enable) {
volatile void* reg = dwc3_mmio(dwc) + DALEPENA;
@@ -41,37 +39,14 @@
zx_status_t dwc3_ep_fifo_init(dwc3_t* dwc, unsigned ep_num) {
ZX_DEBUG_ASSERT(ep_num < countof(dwc->eps));
dwc3_endpoint_t* ep = &dwc->eps[ep_num];
- dwc3_fifo_t* fifo = &ep->fifo;
- static_assert(EP_FIFO_SIZE <= PAGE_SIZE, "");
- zx_status_t status = io_buffer_init(&fifo->buffer, dwc->bti_handle.get(), EP_FIFO_SIZE,
- IO_BUFFER_RW | IO_BUFFER_CONTIG);
- if (status != ZX_OK) {
- return status;
- }
-
- fifo->first = static_cast<dwc3_trb_t*>(io_buffer_virt(&fifo->buffer));
- fifo->next = fifo->first;
- fifo->current = nullptr;
- fifo->last = fifo->first + (EP_FIFO_SIZE / sizeof(dwc3_trb_t)) - 1;
-
- // set up link TRB pointing back to the start of the fifo
- dwc3_trb_t* trb = fifo->last;
- zx_paddr_t trb_phys = io_buffer_phys(&fifo->buffer);
- trb->ptr_low = (uint32_t)trb_phys;
- trb->ptr_high = (uint32_t)(trb_phys >> 32);
- trb->status = 0;
- trb->control = TRB_TRBCTL_LINK | TRB_HWO;
- io_buffer_cache_flush(&ep->fifo.buffer, (trb - ep->fifo.first) * sizeof(*trb), sizeof(*trb));
-
- return ZX_OK;
+ return ep->fifo.Init(EP_FIFO_SIZE, zx::unowned_handle(dwc->bti_handle));
}
void dwc3_ep_fifo_release(dwc3_t* dwc, unsigned ep_num) {
ZX_DEBUG_ASSERT(ep_num < countof(dwc->eps));
dwc3_endpoint_t* ep = &dwc->eps[ep_num];
-
- io_buffer_release(&ep->fifo.buffer);
+ ep->fifo.Release();
}
void dwc3_ep_start_transfer(dwc3_t* dwc, unsigned ep_num, unsigned type, zx_paddr_t buffer,
@@ -81,13 +56,7 @@
// special case: EP0_OUT and EP0_IN use the same fifo
dwc3_endpoint_t* ep = (ep_num == EP0_IN ? &dwc->eps[EP0_OUT] : &dwc->eps[ep_num]);
- dwc3_trb_t* trb = ep->fifo.next++;
- if (ep->fifo.next == ep->fifo.last) {
- ep->fifo.next = ep->fifo.first;
- }
- if (ep->fifo.current == nullptr) {
- ep->fifo.current = trb;
- }
+ auto* trb = ep->fifo.Next(true);
trb->ptr_low = (uint32_t)buffer;
trb->ptr_high = (uint32_t)(buffer >> 32);
@@ -97,21 +66,18 @@
} else {
trb->control = type | TRB_LST | TRB_IOC | TRB_HWO;
}
- io_buffer_cache_flush(&ep->fifo.buffer, (trb - ep->fifo.first) * sizeof(*trb), sizeof(*trb));
+ ep->fifo.FlushTrb(trb);
if (send_zlp) {
- dwc3_trb_t* zlp_trb = ep->fifo.next++;
- if (ep->fifo.next == ep->fifo.last) {
- ep->fifo.next = ep->fifo.first;
- }
+ dwc3_trb_t* zlp_trb = ep->fifo.Next(false);
zlp_trb->ptr_low = 0;
zlp_trb->ptr_high = 0;
zlp_trb->status = TRB_BUFSIZ(0);
zlp_trb->control = type | TRB_LST | TRB_IOC | TRB_HWO;
- io_buffer_cache_flush(&ep->fifo.buffer, (zlp_trb - ep->fifo.first) * sizeof(*trb), sizeof(*trb));
+ ep->fifo.FlushInvalidateTrb(zlp_trb);
}
- dwc3_cmd_ep_start_transfer(dwc, ep_num, dwc3_ep_trb_phys(ep, trb));
+ dwc3_cmd_ep_start_transfer(dwc, ep_num, ep->fifo.GetTrbPhys(trb));
}
static void dwc3_ep_queue_next_locked(dwc3_t* dwc, dwc3_endpoint_t* ep) {
@@ -255,16 +221,6 @@
}
}
-static void dwc_ep_read_trb(dwc3_endpoint_t* ep, dwc3_trb_t* trb, dwc3_trb_t* out_trb) {
- if (trb >= ep->fifo.first && trb < ep->fifo.last) {
- io_buffer_cache_flush_invalidate(&ep->fifo.buffer, (trb - ep->fifo.first) * sizeof(*trb),
- sizeof(*trb));
- memcpy((void *)out_trb, (void *)trb, sizeof(*trb));
- } else {
- zxlogf(ERROR, "dwc_ep_read_trb: bad trb\n");
- }
-}
-
void dwc3_ep_xfer_started(dwc3_t* dwc, unsigned ep_num, unsigned rsrc_id) {
dwc3_endpoint_t* ep = &dwc->eps[ep_num];
fbl::AutoLock lock(&ep->lock);
@@ -305,8 +261,7 @@
if (req) {
dwc3_trb_t trb;
- dwc_ep_read_trb(ep, ep->fifo.current, &trb);
- ep->fifo.current = nullptr;
+ ep->fifo.ReadAndClearCurrentTrb(&trb);
if (trb.control & TRB_HWO) {
zxlogf(ERROR, "TRB_HWO still set in dwc3_ep_xfer_complete\n");
}
@@ -360,3 +315,5 @@
usb_request_complete(req, reason, 0);
}
}
+
+} // namespace dwc3
diff --git a/system/dev/usb/dwc3/dwc3-ep0.cpp b/system/dev/usb/dwc3/dwc3-ep0.cpp
index c431dd1..b9e712a 100644
--- a/system/dev/usb/dwc3/dwc3-ep0.cpp
+++ b/system/dev/usb/dwc3/dwc3-ep0.cpp
@@ -14,6 +14,8 @@
#define EP0_LOCK(dwc) (&(dwc)->eps[EP0_OUT].lock)
+namespace dwc3 {
+
static void dwc3_queue_setup_locked(dwc3_t* dwc) {
io_buffer_cache_flush_invalidate(&dwc->ep0_buffer, 0, sizeof(usb_setup_t));
dwc3_ep_start_transfer(dwc, EP0_OUT, TRB_TRBCTL_SETUP, io_buffer_phys(&dwc->ep0_buffer),
@@ -215,3 +217,5 @@
break;
}
}
+
+} // namespace dwc3
diff --git a/system/dev/usb/dwc3/dwc3-events.cpp b/system/dev/usb/dwc3/dwc3-events.cpp
index 68286a6..c83ea11 100644
--- a/system/dev/usb/dwc3/dwc3-events.cpp
+++ b/system/dev/usb/dwc3/dwc3-events.cpp
@@ -11,6 +11,8 @@
#include <stdio.h>
#include <unistd.h>
+namespace dwc3 {
+
static void dwc3_handle_ep_event(dwc3_t* dwc, uint32_t event) {
uint32_t type = DEPEVT_TYPE(event);
uint32_t ep_num = DEPEVT_PHYS_EP(event);
@@ -236,3 +238,5 @@
dwc->irq_handle.destroy();
thrd_join(dwc->irq_thread, nullptr);
}
+
+} // namespace dwc3
diff --git a/system/dev/usb/dwc3/dwc3-fifo.cpp b/system/dev/usb/dwc3/dwc3-fifo.cpp
new file mode 100644
index 0000000..d410039
--- /dev/null
+++ b/system/dev/usb/dwc3/dwc3-fifo.cpp
@@ -0,0 +1,66 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "dwc3-fifo.h"
+
+#include <string.h>
+
+namespace dwc3 {
+
+
+zx_status_t Dwc3Fifo::Init(size_t buffer_size, zx::unowned_handle bti) {
+ ZX_DEBUG_ASSERT(buffer_size <= PAGE_SIZE);
+ auto status = io_buffer_init(&buffer_, bti->get(), buffer_size, IO_BUFFER_RW | IO_BUFFER_CONTIG);
+ if (status != ZX_OK) {
+ return status;
+ }
+
+ first_ = static_cast<dwc3_trb_t*>(io_buffer_virt(&buffer_));
+ next_ = first_;
+ current_ = nullptr;
+ last_ = first_ + (buffer_size / sizeof(dwc3_trb_t)) - 1;
+
+ // set up link TRB pointing back to the start of the fifo
+ dwc3_trb_t* trb = last_;
+ zx_paddr_t trb_phys = io_buffer_phys(&buffer_);
+ trb->ptr_low = (uint32_t)trb_phys;
+ trb->ptr_high = (uint32_t)(trb_phys >> 32);
+ trb->status = 0;
+ trb->control = TRB_TRBCTL_LINK | TRB_HWO;
+ io_buffer_cache_flush(&buffer_, (trb - first_) * sizeof(*trb), sizeof(*trb));
+
+ return ZX_OK;
+}
+
+void Dwc3Fifo::Release() {
+ io_buffer_release(&buffer_);
+ first_ = next_ = current_ = last_ = nullptr;
+}
+
+
+dwc3_trb_t* Dwc3Fifo::Next(bool set_current) {
+ dwc3_trb_t* trb = next_++;
+
+ if (next_ == last_) {
+ next_ = first_;
+ }
+ if (set_current && current_ == nullptr) {
+ current_ = trb;
+ }
+ return trb;
+}
+
+void Dwc3Fifo::ReadAndClearCurrentTrb(dwc3_trb_t* out_trb) {
+ ZX_DEBUG_ASSERT(current_ != nullptr);
+ volatile dwc3_trb_t* trb = current_;
+ current_ = nullptr;
+
+ FlushInvalidateTrb(trb);
+ out_trb->ptr_low = trb->ptr_low;
+ out_trb->ptr_high = trb->ptr_high;
+ out_trb->status = trb->status;
+ out_trb->control = trb->control;
+}
+
+} // namespace dwc3
diff --git a/system/dev/usb/dwc3/dwc3-fifo.h b/system/dev/usb/dwc3/dwc3-fifo.h
index 4f6a512..2dc5365 100644
--- a/system/dev/usb/dwc3/dwc3-fifo.h
+++ b/system/dev/usb/dwc3/dwc3-fifo.h
@@ -5,6 +5,8 @@
#pragma once
#include <ddk/io-buffer.h>
+#include <fbl/macros.h>
+#include <lib/zx/handle.h>
#include "dwc3-types.h"
@@ -12,15 +14,32 @@
class Dwc3Fifo {
public:
+ zx_status_t Init(size_t buffer_size, zx::unowned_handle bti);
+ void Release();
+
+ dwc3_trb_t* Next(bool set_current);
+ void ReadAndClearCurrentTrb(dwc3_trb_t* out_trb);
+
+ inline void FlushTrb(dwc3_trb_t* trb) {
+ io_buffer_cache_flush(&buffer_, (trb - first_) * sizeof(*trb), sizeof(*trb));
+ }
+
+ inline void FlushInvalidateTrb(dwc3_trb_t* trb) {
+ io_buffer_cache_flush_invalidate(&buffer_, (trb - first_) * sizeof(*trb), sizeof(*trb));
+ }
+
+ inline zx_paddr_t GetTrbPhys(dwc3_trb_t* trb) {
+ return io_buffer_phys(&buffer_) + (trb - first_) * sizeof(*trb);
+ }
private:
DISALLOW_COPY_ASSIGN_AND_MOVE(Dwc3Fifo);
- io_buffer_t buffer;
- dwc3_trb_t* first; // first TRB in the fifo
- dwc3_trb_t* next; // next free TRB in the fifo
- dwc3_trb_t* current; // TRB for currently pending transaction
- dwc3_trb_t* last; // last TRB in the fifo (link TRB)
+ io_buffer_t buffer_;
+ dwc3_trb_t* first_; // first TRB in the fifo
+ dwc3_trb_t* next_; // next free TRB in the fifo
+ dwc3_trb_t* current_; // TRB for currently pending transaction
+ dwc3_trb_t* last_; // last TRB in the fifo (link TRB)
};
} // namespace dwc3
diff --git a/system/dev/usb/dwc3/dwc3.cpp b/system/dev/usb/dwc3/dwc3.cpp
index 30cfb0f..8543e50 100644
--- a/system/dev/usb/dwc3/dwc3.cpp
+++ b/system/dev/usb/dwc3/dwc3.cpp
@@ -20,6 +20,8 @@
#include "dwc3-regs.h"
#include "dwc3-types.h"
+namespace dwc3 {
+
// MMIO indices
enum {
MMIO_USB3OTG,
@@ -454,7 +456,7 @@
return device;
}();
-zx_status_t dwc3_bind(void* ctx, zx_device_t* parent) {
+static zx_status_t dwc3_do_bind(zx_device_t* parent) {
zxlogf(INFO, "dwc3_bind\n");
auto* dwc = static_cast<dwc3_t*>(calloc(1, sizeof(dwc3_t)));
@@ -536,3 +538,9 @@
dwc3_release(dwc);
return status;
}
+
+} // namespace dwc3
+
+zx_status_t dwc3_bind(void* ctx, zx_device_t* parent) {
+ return dwc3::dwc3_do_bind(parent);
+}
diff --git a/system/dev/usb/dwc3/dwc3.h b/system/dev/usb/dwc3/dwc3.h
index 7a371cd..6eb2a7c 100644
--- a/system/dev/usb/dwc3/dwc3.h
+++ b/system/dev/usb/dwc3/dwc3.h
@@ -43,6 +43,8 @@
// converts a USB endpoint address to 0 - 31 index
#define dwc3_ep_num(addr) ((((addr) & 0xF) << 1) | !!((addr) & USB_DIR_IN))
+namespace dwc3 {
+
typedef enum {
EP0_STATE_NONE,
EP0_STATE_SETUP, // Queued setup phase
@@ -54,15 +56,7 @@
} dwc3_ep0_state;
typedef struct {
- io_buffer_t buffer;
- dwc3_trb_t* first; // first TRB in the fifo
- dwc3_trb_t* next; // next free TRB in the fifo
- dwc3_trb_t* current; // TRB for currently pending transaction
- dwc3_trb_t* last; // last TRB in the fifo (link TRB)
-} dwc3_fifo_t;
-
-typedef struct {
- dwc3_fifo_t fifo;
+ Dwc3Fifo fifo;
list_node_t queued_reqs; // requests waiting to be processed
usb_request_t* current_req; // request currently being processed
unsigned rsrc_id; // resource ID for current_req
@@ -173,8 +167,6 @@
void dwc3_wait_bits(volatile uint32_t* ptr, uint32_t bits, uint32_t expected);
void dwc3_print_status(dwc3_t* dwc);
-namespace dwc3 {
-
class Dwc3;
using Dwc3Type = ddk::Device<Dwc3>;
diff --git a/system/dev/usb/dwc3/rules.mk b/system/dev/usb/dwc3/rules.mk
index d9104ed..149034d 100644
--- a/system/dev/usb/dwc3/rules.mk
+++ b/system/dev/usb/dwc3/rules.mk
@@ -15,6 +15,7 @@
$(LOCAL_DIR)/dwc3-endpoints.cpp \
$(LOCAL_DIR)/dwc3-ep0.cpp \
$(LOCAL_DIR)/dwc3-events.cpp \
+ $(LOCAL_DIR)/dwc3-fifo.cpp \
MODULE_STATIC_LIBS := \
system/ulib/ddk \