1// Copyright 2016 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#pragma once 6 7#include <ddk/io-buffer.h> 8#include <zircon/listnode.h> 9 10#include "xhci-hw.h" 11 12// used for both command ring and transfer rings 13typedef struct xhci_transfer_ring { 14 io_buffer_t buffer; 15 xhci_trb_t* start; 16 xhci_trb_t* current; // next to be filled by producer 17 uint8_t pcs; // producer cycle status 18 xhci_trb_t* dequeue_ptr; // next to be processed by consumer 19 // (not used for command ring) 20 size_t size; // number of TRBs in ring 21 bool full; // true if there are no available TRBs, 22 // this is needed to differentiate between 23 // an empty and full ring state 24} xhci_transfer_ring_t; 25 26typedef struct xhci_event_ring { 27 io_buffer_t buffer; 28 xhci_trb_t* start; 29 xhci_trb_t* current; 30 xhci_trb_t* end; 31 uint8_t ccs; // consumer cycle status 32} xhci_event_ring_t; 33 34typedef struct xhci xhci_t; 35 36zx_status_t xhci_transfer_ring_init(xhci_transfer_ring_t* tr, zx_handle_t bti_handle, int count); 37void xhci_transfer_ring_free(xhci_transfer_ring_t* ring); 38size_t xhci_transfer_ring_free_trbs(xhci_transfer_ring_t* ring); 39zx_status_t xhci_event_ring_init(xhci_event_ring_t*, zx_handle_t bti_handle, 40 erst_entry_t* erst_array, int count); 41void xhci_event_ring_free(xhci_event_ring_t* ring); 42void xhci_clear_trb(xhci_trb_t* trb); 43// Converts a transfer trb into a NO-OP transfer TRB, does nothing if it is the LINK TRB. 44void xhci_set_transfer_noop_trb(xhci_trb_t* trb); 45void* xhci_read_trb_ptr(xhci_transfer_ring_t* ring, xhci_trb_t* trb); 46xhci_trb_t* xhci_get_next_trb(xhci_transfer_ring_t* ring, xhci_trb_t* trb); 47void xhci_increment_ring(xhci_transfer_ring_t* ring); 48void xhci_set_dequeue_ptr(xhci_transfer_ring_t* ring, xhci_trb_t* new_ptr); 49 50// Returns the TRB corresponding to the given physical address, or NULL if the address is invalid. 51xhci_trb_t* xhci_transfer_ring_phys_to_trb(xhci_transfer_ring_t* ring, zx_paddr_t phys); 52 53static inline zx_paddr_t xhci_transfer_ring_start_phys(xhci_transfer_ring_t* ring) { 54 return io_buffer_phys(&ring->buffer); 55} 56 57static inline zx_paddr_t xhci_transfer_ring_current_phys(xhci_transfer_ring_t* ring) { 58 return io_buffer_phys(&ring->buffer) + ((ring->current - ring->start) * sizeof(xhci_trb_t)); 59} 60 61static inline zx_paddr_t xhci_event_ring_start_phys(xhci_event_ring_t* ring) { 62 return io_buffer_phys(&ring->buffer); 63} 64 65static inline zx_paddr_t xhci_event_ring_current_phys(xhci_event_ring_t* ring) { 66 return io_buffer_phys(&ring->buffer) + ((ring->current - ring->start) * sizeof(xhci_trb_t)); 67} 68