blob: 6c09beea242a1b837759104d4c85ab80ebda1126 [file] [log] [blame]
// Copyright 2016 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.
#pragma once
#include <ddk/io-buffer.h>
#include <zircon/listnode.h>
#include "xhci-hw.h"
// used for both command ring and transfer rings
typedef struct xhci_transfer_ring {
io_buffer_t buffer;
xhci_trb_t* start;
xhci_trb_t* current; // next to be filled by producer
uint8_t pcs; // producer cycle status
xhci_trb_t* dequeue_ptr; // next to be processed by consumer
// (not used for command ring)
size_t size; // number of TRBs in ring
bool full; // true if there are no available TRBs,
// this is needed to differentiate between
// an empty and full ring state
} xhci_transfer_ring_t;
typedef struct xhci_event_ring {
io_buffer_t buffer;
xhci_trb_t* start;
xhci_trb_t* current;
xhci_trb_t* end;
uint8_t ccs; // consumer cycle status
} xhci_event_ring_t;
typedef struct xhci xhci_t;
zx_status_t xhci_transfer_ring_init(xhci_transfer_ring_t* tr, zx_handle_t bti_handle, int count);
void xhci_transfer_ring_free(xhci_transfer_ring_t* ring);
size_t xhci_transfer_ring_free_trbs(xhci_transfer_ring_t* ring);
zx_status_t xhci_event_ring_init(xhci_event_ring_t*, zx_handle_t bti_handle,
erst_entry_t* erst_array, int count);
void xhci_event_ring_free(xhci_event_ring_t* ring);
void xhci_clear_trb(xhci_trb_t* trb);
// Converts a transfer trb into a NO-OP transfer TRB, does nothing if it is the LINK TRB.
void xhci_set_transfer_noop_trb(xhci_trb_t* trb);
xhci_trb_t* xhci_read_trb_ptr(xhci_transfer_ring_t* ring, xhci_trb_t* trb);
xhci_trb_t* xhci_get_next_trb(xhci_transfer_ring_t* ring, xhci_trb_t* trb);
void xhci_increment_ring(xhci_transfer_ring_t* ring);
void xhci_set_dequeue_ptr(xhci_transfer_ring_t* ring, xhci_trb_t* new_ptr);
// Returns the TRB corresponding to the given physical address, or NULL if the address is invalid.
xhci_trb_t* xhci_transfer_ring_phys_to_trb(xhci_transfer_ring_t* ring, zx_paddr_t phys);
static inline zx_paddr_t xhci_transfer_ring_start_phys(xhci_transfer_ring_t* ring) {
return io_buffer_phys(&ring->buffer);
}
static inline zx_paddr_t xhci_transfer_ring_current_phys(xhci_transfer_ring_t* ring) {
return io_buffer_phys(&ring->buffer) + ((ring->current - ring->start) * sizeof(xhci_trb_t));
}
static inline zx_paddr_t xhci_event_ring_start_phys(xhci_event_ring_t* ring) {
return io_buffer_phys(&ring->buffer);
}
static inline zx_paddr_t xhci_event_ring_current_phys(xhci_event_ring_t* ring) {
return io_buffer_phys(&ring->buffer) + ((ring->current - ring->start) * sizeof(xhci_trb_t));
}