1// Copyright 2018 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/device.h>
8#include <ddk/protocol/usb.h>
9#include <ddk/usb-request/usb-request.h>
10#include <lib/sync/completion.h>
11#include <xdc-server-utils/packet.h>
12
13#include "xdc-hw.h"
14#include "xhci-transfer-common.h"
15#include "xhci-trb.h"
16
17#define TRANSFER_RING_SIZE     (PAGE_SIZE / sizeof(xhci_trb_t))
18
19// The type and length fields for a string descriptor are one byte each.
20#define STR_DESC_METADATA_LEN  2
21#define MAX_STR_LEN            64
22
23// There are only two endpoints, one for bulk OUT and one for bulk IN.
24#define OUT_EP_IDX             0
25#define IN_EP_IDX              1
26#define NUM_EPS                2
27
28// See XHCI Spec, 7.6.3.2
29#define EP_CTX_MAX_PACKET_SIZE 1024
30
31#define MAX_EP_DEBUG_NAME_LEN  4
32
33typedef enum {
34    XDC_EP_STATE_DEAD = 0,  // device does not exist or has been removed
35    XDC_EP_STATE_RUNNING,   // EP is accepting TRBs on the transfer ring
36    XDC_EP_STATE_HALTED,    // EP halted due to stall
37    XDC_EP_STATE_STOPPED    // EP halt has been cleared, but not yet accepting TRBs
38} xdc_ep_state_t;
39
40typedef struct {
41    xhci_transfer_ring_t transfer_ring;
42    list_node_t queued_reqs;     // requests waiting to be processed
43    usb_request_t* current_req;  // request currently being processed
44    list_node_t pending_reqs;    // processed requests waiting for completion, including current_req
45    xhci_transfer_state_t transfer_state;  // transfer state for current_req
46    uint8_t direction;  // USB_DIR_OUT or USB_DIR_IN
47
48    xdc_ep_state_t state;
49    bool got_err_event; // encountered a TRB error on the event ring
50
51    char name[MAX_EP_DEBUG_NAME_LEN];  // For debug printing.
52} xdc_endpoint_t;
53
54typedef struct {
55    uint8_t len;
56    uint8_t type;
57    uint8_t string[MAX_STR_LEN];
58} xdc_str_desc_t;
59
60typedef struct {
61    xdc_str_desc_t str_0_desc;
62    xdc_str_desc_t manufacturer_desc;
63    xdc_str_desc_t product_desc;
64    xdc_str_desc_t serial_num_desc;
65} xdc_str_descs_t;
66
67// This is used by the xdc_poll thread to monitors changes in the debug capability register state,
68// and handle completed requests.
69// TODO(jocelyndang): move this and all poll thread related functions into a single file.
70typedef struct {
71    // Whether a Root Hub Port is connected to a Debug Host and assigned to the Debug Capability.
72    bool connected;
73    // The last connection time in nanoseconds, with respect to the monotonic clock.
74    zx_time_t last_conn;
75
76    // Whether the Debug Device is in the Configured state.
77    // Changes to this are also copied to the xdc struct configured mmember.
78    bool configured;
79
80    bool halt_in;
81    bool halt_out;
82
83    // Requests that need their complete_cb called.
84    list_node_t completed_reqs;
85} xdc_poll_state_t;
86
87typedef struct {
88    zx_device_t* zxdev;
89
90    // Shared from XHCI.
91    zx_handle_t bti_handle;
92    void* mmio;
93
94    xdc_debug_cap_regs_t* debug_cap_regs;
95
96    // Underlying buffer for the event ring segment table
97    io_buffer_t erst_buffer;
98    erst_entry_t* erst_array;
99
100    xhci_event_ring_t event_ring;
101
102    // Underlying buffer for the context data and string descriptors.
103    io_buffer_t context_str_descs_buffer;
104    xdc_context_data_t* context_data;
105    xdc_str_descs_t* str_descs;
106
107    thrd_t start_thread;
108
109    // Whether to suspend all activity.
110    atomic_bool suspended;
111
112    xdc_endpoint_t eps[NUM_EPS];
113    // Whether the Debug Device is in the Configured state.
114    bool configured;
115    // Needs to be acquired before accessing the eps and configured members.
116    // TODO(jocelyndang): make these separate locks?
117    mtx_t lock;
118
119    bool writable;
120    usb_request_pool_t free_write_reqs;
121    mtx_t write_lock;
122
123    list_node_t free_read_reqs;
124    xdc_packet_state_t cur_read_packet;
125    mtx_t read_lock;
126
127    list_node_t instance_list;
128    // Streams registered by the host.
129    list_node_t host_streams;
130    mtx_t instance_list_lock;
131
132    // At least one xdc instance has been opened.
133    sync_completion_t has_instance_completion;
134    atomic_int num_instances;
135} xdc_t;
136
137// TODO(jocelyndang): we should get our own handles rather than borrowing them from XHCI.
138zx_status_t xdc_bind(zx_device_t* parent, zx_handle_t bti_handle, void* mmio);
139
140void xdc_endpoint_set_halt_locked(xdc_t* xdc, xdc_poll_state_t* poll_state, xdc_endpoint_t* ep)
141                                  __TA_REQUIRES(xdc->lock);
142