1*4c87aefeSPatrick Mooney /*- 2*4c87aefeSPatrick Mooney * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*4c87aefeSPatrick Mooney * 4*4c87aefeSPatrick Mooney * Copyright (c) 2014 Leon Dang <ldang@nahannisys.com> 5*4c87aefeSPatrick Mooney * Copyright 2018 Joyent, Inc. 6*4c87aefeSPatrick Mooney * All rights reserved. 7*4c87aefeSPatrick Mooney * 8*4c87aefeSPatrick Mooney * Redistribution and use in source and binary forms, with or without 9*4c87aefeSPatrick Mooney * modification, are permitted provided that the following conditions 10*4c87aefeSPatrick Mooney * are met: 11*4c87aefeSPatrick Mooney * 1. Redistributions of source code must retain the above copyright 12*4c87aefeSPatrick Mooney * notice, this list of conditions and the following disclaimer. 13*4c87aefeSPatrick Mooney * 2. Redistributions in binary form must reproduce the above copyright 14*4c87aefeSPatrick Mooney * notice, this list of conditions and the following disclaimer in the 15*4c87aefeSPatrick Mooney * documentation and/or other materials provided with the distribution. 16*4c87aefeSPatrick Mooney * 17*4c87aefeSPatrick Mooney * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18*4c87aefeSPatrick Mooney * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*4c87aefeSPatrick Mooney * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*4c87aefeSPatrick Mooney * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21*4c87aefeSPatrick Mooney * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*4c87aefeSPatrick Mooney * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23*4c87aefeSPatrick Mooney * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24*4c87aefeSPatrick Mooney * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25*4c87aefeSPatrick Mooney * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26*4c87aefeSPatrick Mooney * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27*4c87aefeSPatrick Mooney * SUCH DAMAGE. 28*4c87aefeSPatrick Mooney */ 29*4c87aefeSPatrick Mooney /* 30*4c87aefeSPatrick Mooney XHCI options: 31*4c87aefeSPatrick Mooney -s <n>,xhci,{devices} 32*4c87aefeSPatrick Mooney 33*4c87aefeSPatrick Mooney devices: 34*4c87aefeSPatrick Mooney tablet USB tablet mouse 35*4c87aefeSPatrick Mooney */ 36*4c87aefeSPatrick Mooney #include <sys/cdefs.h> 37*4c87aefeSPatrick Mooney __FBSDID("$FreeBSD$"); 38*4c87aefeSPatrick Mooney 39*4c87aefeSPatrick Mooney #include <sys/param.h> 40*4c87aefeSPatrick Mooney #include <sys/uio.h> 41*4c87aefeSPatrick Mooney #include <sys/types.h> 42*4c87aefeSPatrick Mooney #include <sys/queue.h> 43*4c87aefeSPatrick Mooney 44*4c87aefeSPatrick Mooney #include <stdio.h> 45*4c87aefeSPatrick Mooney #include <stdlib.h> 46*4c87aefeSPatrick Mooney #include <stdint.h> 47*4c87aefeSPatrick Mooney #include <string.h> 48*4c87aefeSPatrick Mooney #include <errno.h> 49*4c87aefeSPatrick Mooney #include <pthread.h> 50*4c87aefeSPatrick Mooney #include <unistd.h> 51*4c87aefeSPatrick Mooney 52*4c87aefeSPatrick Mooney #include <dev/usb/usbdi.h> 53*4c87aefeSPatrick Mooney #include <dev/usb/usb.h> 54*4c87aefeSPatrick Mooney #include <dev/usb/usb_freebsd.h> 55*4c87aefeSPatrick Mooney #include <xhcireg.h> 56*4c87aefeSPatrick Mooney 57*4c87aefeSPatrick Mooney #include "bhyverun.h" 58*4c87aefeSPatrick Mooney #include "pci_emul.h" 59*4c87aefeSPatrick Mooney #include "pci_xhci.h" 60*4c87aefeSPatrick Mooney #include "usb_emul.h" 61*4c87aefeSPatrick Mooney 62*4c87aefeSPatrick Mooney 63*4c87aefeSPatrick Mooney static int xhci_debug = 0; 64*4c87aefeSPatrick Mooney #define DPRINTF(params) if (xhci_debug) printf params 65*4c87aefeSPatrick Mooney #define WPRINTF(params) printf params 66*4c87aefeSPatrick Mooney 67*4c87aefeSPatrick Mooney 68*4c87aefeSPatrick Mooney #define XHCI_NAME "xhci" 69*4c87aefeSPatrick Mooney #define XHCI_MAX_DEVS 8 /* 4 USB3 + 4 USB2 devs */ 70*4c87aefeSPatrick Mooney 71*4c87aefeSPatrick Mooney #define XHCI_MAX_SLOTS 64 /* min allowed by Windows drivers */ 72*4c87aefeSPatrick Mooney 73*4c87aefeSPatrick Mooney /* 74*4c87aefeSPatrick Mooney * XHCI data structures can be up to 64k, but limit paddr_guest2host mapping 75*4c87aefeSPatrick Mooney * to 4k to avoid going over the guest physical memory barrier. 76*4c87aefeSPatrick Mooney */ 77*4c87aefeSPatrick Mooney #define XHCI_PADDR_SZ 4096 /* paddr_guest2host max size */ 78*4c87aefeSPatrick Mooney 79*4c87aefeSPatrick Mooney #define XHCI_ERST_MAX 0 /* max 2^entries event ring seg tbl */ 80*4c87aefeSPatrick Mooney 81*4c87aefeSPatrick Mooney #define XHCI_CAPLEN (4*8) /* offset of op register space */ 82*4c87aefeSPatrick Mooney #define XHCI_HCCPRAMS2 0x1C /* offset of HCCPARAMS2 register */ 83*4c87aefeSPatrick Mooney #define XHCI_PORTREGS_START 0x400 84*4c87aefeSPatrick Mooney #define XHCI_DOORBELL_MAX 256 85*4c87aefeSPatrick Mooney 86*4c87aefeSPatrick Mooney #define XHCI_STREAMS_MAX 1 /* 4-15 in XHCI spec */ 87*4c87aefeSPatrick Mooney 88*4c87aefeSPatrick Mooney /* caplength and hci-version registers */ 89*4c87aefeSPatrick Mooney #define XHCI_SET_CAPLEN(x) ((x) & 0xFF) 90*4c87aefeSPatrick Mooney #define XHCI_SET_HCIVERSION(x) (((x) & 0xFFFF) << 16) 91*4c87aefeSPatrick Mooney #define XHCI_GET_HCIVERSION(x) (((x) >> 16) & 0xFFFF) 92*4c87aefeSPatrick Mooney 93*4c87aefeSPatrick Mooney /* hcsparams1 register */ 94*4c87aefeSPatrick Mooney #define XHCI_SET_HCSP1_MAXSLOTS(x) ((x) & 0xFF) 95*4c87aefeSPatrick Mooney #define XHCI_SET_HCSP1_MAXINTR(x) (((x) & 0x7FF) << 8) 96*4c87aefeSPatrick Mooney #define XHCI_SET_HCSP1_MAXPORTS(x) (((x) & 0xFF) << 24) 97*4c87aefeSPatrick Mooney 98*4c87aefeSPatrick Mooney /* hcsparams2 register */ 99*4c87aefeSPatrick Mooney #define XHCI_SET_HCSP2_IST(x) ((x) & 0x0F) 100*4c87aefeSPatrick Mooney #define XHCI_SET_HCSP2_ERSTMAX(x) (((x) & 0x0F) << 4) 101*4c87aefeSPatrick Mooney #define XHCI_SET_HCSP2_MAXSCRATCH_HI(x) (((x) & 0x1F) << 21) 102*4c87aefeSPatrick Mooney #define XHCI_SET_HCSP2_MAXSCRATCH_LO(x) (((x) & 0x1F) << 27) 103*4c87aefeSPatrick Mooney 104*4c87aefeSPatrick Mooney /* hcsparams3 register */ 105*4c87aefeSPatrick Mooney #define XHCI_SET_HCSP3_U1EXITLATENCY(x) ((x) & 0xFF) 106*4c87aefeSPatrick Mooney #define XHCI_SET_HCSP3_U2EXITLATENCY(x) (((x) & 0xFFFF) << 16) 107*4c87aefeSPatrick Mooney 108*4c87aefeSPatrick Mooney /* hccparams1 register */ 109*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP1_AC64(x) ((x) & 0x01) 110*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP1_BNC(x) (((x) & 0x01) << 1) 111*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP1_CSZ(x) (((x) & 0x01) << 2) 112*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP1_PPC(x) (((x) & 0x01) << 3) 113*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP1_PIND(x) (((x) & 0x01) << 4) 114*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP1_LHRC(x) (((x) & 0x01) << 5) 115*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP1_LTC(x) (((x) & 0x01) << 6) 116*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP1_NSS(x) (((x) & 0x01) << 7) 117*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP1_PAE(x) (((x) & 0x01) << 8) 118*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP1_SPC(x) (((x) & 0x01) << 9) 119*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP1_SEC(x) (((x) & 0x01) << 10) 120*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP1_CFC(x) (((x) & 0x01) << 11) 121*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP1_MAXPSA(x) (((x) & 0x0F) << 12) 122*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP1_XECP(x) (((x) & 0xFFFF) << 16) 123*4c87aefeSPatrick Mooney 124*4c87aefeSPatrick Mooney /* hccparams2 register */ 125*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP2_U3C(x) ((x) & 0x01) 126*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP2_CMC(x) (((x) & 0x01) << 1) 127*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP2_FSC(x) (((x) & 0x01) << 2) 128*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP2_CTC(x) (((x) & 0x01) << 3) 129*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP2_LEC(x) (((x) & 0x01) << 4) 130*4c87aefeSPatrick Mooney #define XHCI_SET_HCCP2_CIC(x) (((x) & 0x01) << 5) 131*4c87aefeSPatrick Mooney 132*4c87aefeSPatrick Mooney /* other registers */ 133*4c87aefeSPatrick Mooney #define XHCI_SET_DOORBELL(x) ((x) & ~0x03) 134*4c87aefeSPatrick Mooney #define XHCI_SET_RTSOFFSET(x) ((x) & ~0x0F) 135*4c87aefeSPatrick Mooney 136*4c87aefeSPatrick Mooney /* register masks */ 137*4c87aefeSPatrick Mooney #define XHCI_PS_PLS_MASK (0xF << 5) /* port link state */ 138*4c87aefeSPatrick Mooney #define XHCI_PS_SPEED_MASK (0xF << 10) /* port speed */ 139*4c87aefeSPatrick Mooney #define XHCI_PS_PIC_MASK (0x3 << 14) /* port indicator */ 140*4c87aefeSPatrick Mooney 141*4c87aefeSPatrick Mooney /* port register set */ 142*4c87aefeSPatrick Mooney #define XHCI_PORTREGS_BASE 0x400 /* base offset */ 143*4c87aefeSPatrick Mooney #define XHCI_PORTREGS_PORT0 0x3F0 144*4c87aefeSPatrick Mooney #define XHCI_PORTREGS_SETSZ 0x10 /* size of a set */ 145*4c87aefeSPatrick Mooney 146*4c87aefeSPatrick Mooney #define MASK_64_HI(x) ((x) & ~0xFFFFFFFFULL) 147*4c87aefeSPatrick Mooney #define MASK_64_LO(x) ((x) & 0xFFFFFFFFULL) 148*4c87aefeSPatrick Mooney 149*4c87aefeSPatrick Mooney #define FIELD_REPLACE(a,b,m,s) (((a) & ~((m) << (s))) | \ 150*4c87aefeSPatrick Mooney (((b) & (m)) << (s))) 151*4c87aefeSPatrick Mooney #define FIELD_COPY(a,b,m,s) (((a) & ~((m) << (s))) | \ 152*4c87aefeSPatrick Mooney (((b) & ((m) << (s))))) 153*4c87aefeSPatrick Mooney 154*4c87aefeSPatrick Mooney struct pci_xhci_trb_ring { 155*4c87aefeSPatrick Mooney uint64_t ringaddr; /* current dequeue guest address */ 156*4c87aefeSPatrick Mooney uint32_t ccs; /* consumer cycle state */ 157*4c87aefeSPatrick Mooney }; 158*4c87aefeSPatrick Mooney 159*4c87aefeSPatrick Mooney /* device endpoint transfer/stream rings */ 160*4c87aefeSPatrick Mooney struct pci_xhci_dev_ep { 161*4c87aefeSPatrick Mooney union { 162*4c87aefeSPatrick Mooney struct xhci_trb *_epu_tr; 163*4c87aefeSPatrick Mooney struct xhci_stream_ctx *_epu_sctx; 164*4c87aefeSPatrick Mooney } _ep_trbsctx; 165*4c87aefeSPatrick Mooney #define ep_tr _ep_trbsctx._epu_tr 166*4c87aefeSPatrick Mooney #define ep_sctx _ep_trbsctx._epu_sctx 167*4c87aefeSPatrick Mooney 168*4c87aefeSPatrick Mooney union { 169*4c87aefeSPatrick Mooney struct pci_xhci_trb_ring _epu_trb; 170*4c87aefeSPatrick Mooney struct pci_xhci_trb_ring *_epu_sctx_trbs; 171*4c87aefeSPatrick Mooney } _ep_trb_rings; 172*4c87aefeSPatrick Mooney #define ep_ringaddr _ep_trb_rings._epu_trb.ringaddr 173*4c87aefeSPatrick Mooney #define ep_ccs _ep_trb_rings._epu_trb.ccs 174*4c87aefeSPatrick Mooney #define ep_sctx_trbs _ep_trb_rings._epu_sctx_trbs 175*4c87aefeSPatrick Mooney 176*4c87aefeSPatrick Mooney struct usb_data_xfer *ep_xfer; /* transfer chain */ 177*4c87aefeSPatrick Mooney }; 178*4c87aefeSPatrick Mooney 179*4c87aefeSPatrick Mooney /* device context base address array: maps slot->device context */ 180*4c87aefeSPatrick Mooney struct xhci_dcbaa { 181*4c87aefeSPatrick Mooney uint64_t dcba[USB_MAX_DEVICES+1]; /* xhci_dev_ctx ptrs */ 182*4c87aefeSPatrick Mooney }; 183*4c87aefeSPatrick Mooney 184*4c87aefeSPatrick Mooney /* port status registers */ 185*4c87aefeSPatrick Mooney struct pci_xhci_portregs { 186*4c87aefeSPatrick Mooney uint32_t portsc; /* port status and control */ 187*4c87aefeSPatrick Mooney uint32_t portpmsc; /* port pwr mgmt status & control */ 188*4c87aefeSPatrick Mooney uint32_t portli; /* port link info */ 189*4c87aefeSPatrick Mooney uint32_t porthlpmc; /* port hardware LPM control */ 190*4c87aefeSPatrick Mooney } __packed; 191*4c87aefeSPatrick Mooney #define XHCI_PS_SPEED_SET(x) (((x) & 0xF) << 10) 192*4c87aefeSPatrick Mooney 193*4c87aefeSPatrick Mooney /* xHC operational registers */ 194*4c87aefeSPatrick Mooney struct pci_xhci_opregs { 195*4c87aefeSPatrick Mooney uint32_t usbcmd; /* usb command */ 196*4c87aefeSPatrick Mooney uint32_t usbsts; /* usb status */ 197*4c87aefeSPatrick Mooney uint32_t pgsz; /* page size */ 198*4c87aefeSPatrick Mooney uint32_t dnctrl; /* device notification control */ 199*4c87aefeSPatrick Mooney uint64_t crcr; /* command ring control */ 200*4c87aefeSPatrick Mooney uint64_t dcbaap; /* device ctx base addr array ptr */ 201*4c87aefeSPatrick Mooney uint32_t config; /* configure */ 202*4c87aefeSPatrick Mooney 203*4c87aefeSPatrick Mooney /* guest mapped addresses: */ 204*4c87aefeSPatrick Mooney struct xhci_trb *cr_p; /* crcr dequeue */ 205*4c87aefeSPatrick Mooney struct xhci_dcbaa *dcbaa_p; /* dev ctx array ptr */ 206*4c87aefeSPatrick Mooney }; 207*4c87aefeSPatrick Mooney 208*4c87aefeSPatrick Mooney /* xHC runtime registers */ 209*4c87aefeSPatrick Mooney struct pci_xhci_rtsregs { 210*4c87aefeSPatrick Mooney uint32_t mfindex; /* microframe index */ 211*4c87aefeSPatrick Mooney struct { /* interrupter register set */ 212*4c87aefeSPatrick Mooney uint32_t iman; /* interrupter management */ 213*4c87aefeSPatrick Mooney uint32_t imod; /* interrupter moderation */ 214*4c87aefeSPatrick Mooney uint32_t erstsz; /* event ring segment table size */ 215*4c87aefeSPatrick Mooney uint32_t rsvd; 216*4c87aefeSPatrick Mooney uint64_t erstba; /* event ring seg-tbl base addr */ 217*4c87aefeSPatrick Mooney uint64_t erdp; /* event ring dequeue ptr */ 218*4c87aefeSPatrick Mooney } intrreg __packed; 219*4c87aefeSPatrick Mooney 220*4c87aefeSPatrick Mooney /* guest mapped addresses */ 221*4c87aefeSPatrick Mooney struct xhci_event_ring_seg *erstba_p; 222*4c87aefeSPatrick Mooney struct xhci_trb *erst_p; /* event ring segment tbl */ 223*4c87aefeSPatrick Mooney int er_deq_seg; /* event ring dequeue segment */ 224*4c87aefeSPatrick Mooney int er_enq_idx; /* event ring enqueue index - xHCI */ 225*4c87aefeSPatrick Mooney int er_enq_seg; /* event ring enqueue segment */ 226*4c87aefeSPatrick Mooney uint32_t er_events_cnt; /* number of events in ER */ 227*4c87aefeSPatrick Mooney uint32_t event_pcs; /* producer cycle state flag */ 228*4c87aefeSPatrick Mooney }; 229*4c87aefeSPatrick Mooney 230*4c87aefeSPatrick Mooney 231*4c87aefeSPatrick Mooney struct pci_xhci_softc; 232*4c87aefeSPatrick Mooney 233*4c87aefeSPatrick Mooney 234*4c87aefeSPatrick Mooney /* 235*4c87aefeSPatrick Mooney * USB device emulation container. 236*4c87aefeSPatrick Mooney * This is referenced from usb_hci->hci_sc; 1 pci_xhci_dev_emu for each 237*4c87aefeSPatrick Mooney * emulated device instance. 238*4c87aefeSPatrick Mooney */ 239*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu { 240*4c87aefeSPatrick Mooney struct pci_xhci_softc *xsc; 241*4c87aefeSPatrick Mooney 242*4c87aefeSPatrick Mooney /* XHCI contexts */ 243*4c87aefeSPatrick Mooney struct xhci_dev_ctx *dev_ctx; 244*4c87aefeSPatrick Mooney struct pci_xhci_dev_ep eps[XHCI_MAX_ENDPOINTS]; 245*4c87aefeSPatrick Mooney int dev_slotstate; 246*4c87aefeSPatrick Mooney 247*4c87aefeSPatrick Mooney struct usb_devemu *dev_ue; /* USB emulated dev */ 248*4c87aefeSPatrick Mooney void *dev_sc; /* device's softc */ 249*4c87aefeSPatrick Mooney 250*4c87aefeSPatrick Mooney struct usb_hci hci; 251*4c87aefeSPatrick Mooney }; 252*4c87aefeSPatrick Mooney 253*4c87aefeSPatrick Mooney struct pci_xhci_softc { 254*4c87aefeSPatrick Mooney struct pci_devinst *xsc_pi; 255*4c87aefeSPatrick Mooney 256*4c87aefeSPatrick Mooney pthread_mutex_t mtx; 257*4c87aefeSPatrick Mooney 258*4c87aefeSPatrick Mooney uint32_t caplength; /* caplen & hciversion */ 259*4c87aefeSPatrick Mooney uint32_t hcsparams1; /* structural parameters 1 */ 260*4c87aefeSPatrick Mooney uint32_t hcsparams2; /* structural parameters 2 */ 261*4c87aefeSPatrick Mooney uint32_t hcsparams3; /* structural parameters 3 */ 262*4c87aefeSPatrick Mooney uint32_t hccparams1; /* capability parameters 1 */ 263*4c87aefeSPatrick Mooney uint32_t dboff; /* doorbell offset */ 264*4c87aefeSPatrick Mooney uint32_t rtsoff; /* runtime register space offset */ 265*4c87aefeSPatrick Mooney uint32_t hccparams2; /* capability parameters 2 */ 266*4c87aefeSPatrick Mooney 267*4c87aefeSPatrick Mooney uint32_t regsend; /* end of configuration registers */ 268*4c87aefeSPatrick Mooney 269*4c87aefeSPatrick Mooney struct pci_xhci_opregs opregs; 270*4c87aefeSPatrick Mooney struct pci_xhci_rtsregs rtsregs; 271*4c87aefeSPatrick Mooney 272*4c87aefeSPatrick Mooney struct pci_xhci_portregs *portregs; 273*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu **devices; /* XHCI[port] = device */ 274*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu **slots; /* slots assigned from 1 */ 275*4c87aefeSPatrick Mooney int ndevices; 276*4c87aefeSPatrick Mooney 277*4c87aefeSPatrick Mooney int usb2_port_start; 278*4c87aefeSPatrick Mooney int usb3_port_start; 279*4c87aefeSPatrick Mooney }; 280*4c87aefeSPatrick Mooney 281*4c87aefeSPatrick Mooney 282*4c87aefeSPatrick Mooney /* portregs and devices arrays are set up to start from idx=1 */ 283*4c87aefeSPatrick Mooney #define XHCI_PORTREG_PTR(x,n) &(x)->portregs[(n)] 284*4c87aefeSPatrick Mooney #define XHCI_DEVINST_PTR(x,n) (x)->devices[(n)] 285*4c87aefeSPatrick Mooney #define XHCI_SLOTDEV_PTR(x,n) (x)->slots[(n)] 286*4c87aefeSPatrick Mooney 287*4c87aefeSPatrick Mooney #define XHCI_HALTED(sc) ((sc)->opregs.usbsts & XHCI_STS_HCH) 288*4c87aefeSPatrick Mooney 289*4c87aefeSPatrick Mooney #define XHCI_GADDR(sc,a) paddr_guest2host((sc)->xsc_pi->pi_vmctx, \ 290*4c87aefeSPatrick Mooney (a), \ 291*4c87aefeSPatrick Mooney XHCI_PADDR_SZ - ((a) & (XHCI_PADDR_SZ-1))) 292*4c87aefeSPatrick Mooney 293*4c87aefeSPatrick Mooney static int xhci_in_use; 294*4c87aefeSPatrick Mooney 295*4c87aefeSPatrick Mooney /* map USB errors to XHCI */ 296*4c87aefeSPatrick Mooney static const int xhci_usb_errors[USB_ERR_MAX] = { 297*4c87aefeSPatrick Mooney [USB_ERR_NORMAL_COMPLETION] = XHCI_TRB_ERROR_SUCCESS, 298*4c87aefeSPatrick Mooney [USB_ERR_PENDING_REQUESTS] = XHCI_TRB_ERROR_RESOURCE, 299*4c87aefeSPatrick Mooney [USB_ERR_NOT_STARTED] = XHCI_TRB_ERROR_ENDP_NOT_ON, 300*4c87aefeSPatrick Mooney [USB_ERR_INVAL] = XHCI_TRB_ERROR_INVALID, 301*4c87aefeSPatrick Mooney [USB_ERR_NOMEM] = XHCI_TRB_ERROR_RESOURCE, 302*4c87aefeSPatrick Mooney [USB_ERR_CANCELLED] = XHCI_TRB_ERROR_STOPPED, 303*4c87aefeSPatrick Mooney [USB_ERR_BAD_ADDRESS] = XHCI_TRB_ERROR_PARAMETER, 304*4c87aefeSPatrick Mooney [USB_ERR_BAD_BUFSIZE] = XHCI_TRB_ERROR_PARAMETER, 305*4c87aefeSPatrick Mooney [USB_ERR_BAD_FLAG] = XHCI_TRB_ERROR_PARAMETER, 306*4c87aefeSPatrick Mooney [USB_ERR_NO_CALLBACK] = XHCI_TRB_ERROR_STALL, 307*4c87aefeSPatrick Mooney [USB_ERR_IN_USE] = XHCI_TRB_ERROR_RESOURCE, 308*4c87aefeSPatrick Mooney [USB_ERR_NO_ADDR] = XHCI_TRB_ERROR_RESOURCE, 309*4c87aefeSPatrick Mooney [USB_ERR_NO_PIPE] = XHCI_TRB_ERROR_RESOURCE, 310*4c87aefeSPatrick Mooney [USB_ERR_ZERO_NFRAMES] = XHCI_TRB_ERROR_UNDEFINED, 311*4c87aefeSPatrick Mooney [USB_ERR_ZERO_MAXP] = XHCI_TRB_ERROR_UNDEFINED, 312*4c87aefeSPatrick Mooney [USB_ERR_SET_ADDR_FAILED] = XHCI_TRB_ERROR_RESOURCE, 313*4c87aefeSPatrick Mooney [USB_ERR_NO_POWER] = XHCI_TRB_ERROR_ENDP_NOT_ON, 314*4c87aefeSPatrick Mooney [USB_ERR_TOO_DEEP] = XHCI_TRB_ERROR_RESOURCE, 315*4c87aefeSPatrick Mooney [USB_ERR_IOERROR] = XHCI_TRB_ERROR_TRB, 316*4c87aefeSPatrick Mooney [USB_ERR_NOT_CONFIGURED] = XHCI_TRB_ERROR_ENDP_NOT_ON, 317*4c87aefeSPatrick Mooney [USB_ERR_TIMEOUT] = XHCI_TRB_ERROR_CMD_ABORTED, 318*4c87aefeSPatrick Mooney [USB_ERR_SHORT_XFER] = XHCI_TRB_ERROR_SHORT_PKT, 319*4c87aefeSPatrick Mooney [USB_ERR_STALLED] = XHCI_TRB_ERROR_STALL, 320*4c87aefeSPatrick Mooney [USB_ERR_INTERRUPTED] = XHCI_TRB_ERROR_CMD_ABORTED, 321*4c87aefeSPatrick Mooney [USB_ERR_DMA_LOAD_FAILED] = XHCI_TRB_ERROR_DATA_BUF, 322*4c87aefeSPatrick Mooney [USB_ERR_BAD_CONTEXT] = XHCI_TRB_ERROR_TRB, 323*4c87aefeSPatrick Mooney [USB_ERR_NO_ROOT_HUB] = XHCI_TRB_ERROR_UNDEFINED, 324*4c87aefeSPatrick Mooney [USB_ERR_NO_INTR_THREAD] = XHCI_TRB_ERROR_UNDEFINED, 325*4c87aefeSPatrick Mooney [USB_ERR_NOT_LOCKED] = XHCI_TRB_ERROR_UNDEFINED, 326*4c87aefeSPatrick Mooney }; 327*4c87aefeSPatrick Mooney #define USB_TO_XHCI_ERR(e) ((e) < USB_ERR_MAX ? xhci_usb_errors[(e)] : \ 328*4c87aefeSPatrick Mooney XHCI_TRB_ERROR_INVALID) 329*4c87aefeSPatrick Mooney 330*4c87aefeSPatrick Mooney static int pci_xhci_insert_event(struct pci_xhci_softc *sc, 331*4c87aefeSPatrick Mooney struct xhci_trb *evtrb, int do_intr); 332*4c87aefeSPatrick Mooney static void pci_xhci_dump_trb(struct xhci_trb *trb); 333*4c87aefeSPatrick Mooney static void pci_xhci_assert_interrupt(struct pci_xhci_softc *sc); 334*4c87aefeSPatrick Mooney static void pci_xhci_reset_slot(struct pci_xhci_softc *sc, int slot); 335*4c87aefeSPatrick Mooney static void pci_xhci_reset_port(struct pci_xhci_softc *sc, int portn, int warm); 336*4c87aefeSPatrick Mooney static void pci_xhci_update_ep_ring(struct pci_xhci_softc *sc, 337*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev, struct pci_xhci_dev_ep *devep, 338*4c87aefeSPatrick Mooney struct xhci_endp_ctx *ep_ctx, uint32_t streamid, 339*4c87aefeSPatrick Mooney uint64_t ringaddr, int ccs); 340*4c87aefeSPatrick Mooney 341*4c87aefeSPatrick Mooney static void 342*4c87aefeSPatrick Mooney pci_xhci_set_evtrb(struct xhci_trb *evtrb, uint64_t port, uint32_t errcode, 343*4c87aefeSPatrick Mooney uint32_t evtype) 344*4c87aefeSPatrick Mooney { 345*4c87aefeSPatrick Mooney evtrb->qwTrb0 = port << 24; 346*4c87aefeSPatrick Mooney evtrb->dwTrb2 = XHCI_TRB_2_ERROR_SET(errcode); 347*4c87aefeSPatrick Mooney evtrb->dwTrb3 = XHCI_TRB_3_TYPE_SET(evtype); 348*4c87aefeSPatrick Mooney } 349*4c87aefeSPatrick Mooney 350*4c87aefeSPatrick Mooney 351*4c87aefeSPatrick Mooney /* controller reset */ 352*4c87aefeSPatrick Mooney static void 353*4c87aefeSPatrick Mooney pci_xhci_reset(struct pci_xhci_softc *sc) 354*4c87aefeSPatrick Mooney { 355*4c87aefeSPatrick Mooney int i; 356*4c87aefeSPatrick Mooney 357*4c87aefeSPatrick Mooney sc->rtsregs.er_enq_idx = 0; 358*4c87aefeSPatrick Mooney sc->rtsregs.er_events_cnt = 0; 359*4c87aefeSPatrick Mooney sc->rtsregs.event_pcs = 1; 360*4c87aefeSPatrick Mooney 361*4c87aefeSPatrick Mooney for (i = 1; i <= XHCI_MAX_SLOTS; i++) { 362*4c87aefeSPatrick Mooney pci_xhci_reset_slot(sc, i); 363*4c87aefeSPatrick Mooney } 364*4c87aefeSPatrick Mooney } 365*4c87aefeSPatrick Mooney 366*4c87aefeSPatrick Mooney static uint32_t 367*4c87aefeSPatrick Mooney pci_xhci_usbcmd_write(struct pci_xhci_softc *sc, uint32_t cmd) 368*4c87aefeSPatrick Mooney { 369*4c87aefeSPatrick Mooney int do_intr = 0; 370*4c87aefeSPatrick Mooney int i; 371*4c87aefeSPatrick Mooney 372*4c87aefeSPatrick Mooney if (cmd & XHCI_CMD_RS) { 373*4c87aefeSPatrick Mooney do_intr = (sc->opregs.usbcmd & XHCI_CMD_RS) == 0; 374*4c87aefeSPatrick Mooney 375*4c87aefeSPatrick Mooney sc->opregs.usbcmd |= XHCI_CMD_RS; 376*4c87aefeSPatrick Mooney sc->opregs.usbsts &= ~XHCI_STS_HCH; 377*4c87aefeSPatrick Mooney sc->opregs.usbsts |= XHCI_STS_PCD; 378*4c87aefeSPatrick Mooney 379*4c87aefeSPatrick Mooney /* Queue port change event on controller run from stop */ 380*4c87aefeSPatrick Mooney if (do_intr) 381*4c87aefeSPatrick Mooney for (i = 1; i <= XHCI_MAX_DEVS; i++) { 382*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev; 383*4c87aefeSPatrick Mooney struct pci_xhci_portregs *port; 384*4c87aefeSPatrick Mooney struct xhci_trb evtrb; 385*4c87aefeSPatrick Mooney 386*4c87aefeSPatrick Mooney if ((dev = XHCI_DEVINST_PTR(sc, i)) == NULL) 387*4c87aefeSPatrick Mooney continue; 388*4c87aefeSPatrick Mooney 389*4c87aefeSPatrick Mooney port = XHCI_PORTREG_PTR(sc, i); 390*4c87aefeSPatrick Mooney port->portsc |= XHCI_PS_CSC | XHCI_PS_CCS; 391*4c87aefeSPatrick Mooney port->portsc &= ~XHCI_PS_PLS_MASK; 392*4c87aefeSPatrick Mooney 393*4c87aefeSPatrick Mooney /* 394*4c87aefeSPatrick Mooney * XHCI 4.19.3 USB2 RxDetect->Polling, 395*4c87aefeSPatrick Mooney * USB3 Polling->U0 396*4c87aefeSPatrick Mooney */ 397*4c87aefeSPatrick Mooney if (dev->dev_ue->ue_usbver == 2) 398*4c87aefeSPatrick Mooney port->portsc |= 399*4c87aefeSPatrick Mooney XHCI_PS_PLS_SET(UPS_PORT_LS_POLL); 400*4c87aefeSPatrick Mooney else 401*4c87aefeSPatrick Mooney port->portsc |= 402*4c87aefeSPatrick Mooney XHCI_PS_PLS_SET(UPS_PORT_LS_U0); 403*4c87aefeSPatrick Mooney 404*4c87aefeSPatrick Mooney pci_xhci_set_evtrb(&evtrb, i, 405*4c87aefeSPatrick Mooney XHCI_TRB_ERROR_SUCCESS, 406*4c87aefeSPatrick Mooney XHCI_TRB_EVENT_PORT_STS_CHANGE); 407*4c87aefeSPatrick Mooney 408*4c87aefeSPatrick Mooney if (pci_xhci_insert_event(sc, &evtrb, 0) != 409*4c87aefeSPatrick Mooney XHCI_TRB_ERROR_SUCCESS) 410*4c87aefeSPatrick Mooney break; 411*4c87aefeSPatrick Mooney } 412*4c87aefeSPatrick Mooney } else { 413*4c87aefeSPatrick Mooney sc->opregs.usbcmd &= ~XHCI_CMD_RS; 414*4c87aefeSPatrick Mooney sc->opregs.usbsts |= XHCI_STS_HCH; 415*4c87aefeSPatrick Mooney sc->opregs.usbsts &= ~XHCI_STS_PCD; 416*4c87aefeSPatrick Mooney } 417*4c87aefeSPatrick Mooney 418*4c87aefeSPatrick Mooney /* start execution of schedule; stop when set to 0 */ 419*4c87aefeSPatrick Mooney cmd |= sc->opregs.usbcmd & XHCI_CMD_RS; 420*4c87aefeSPatrick Mooney 421*4c87aefeSPatrick Mooney if (cmd & XHCI_CMD_HCRST) { 422*4c87aefeSPatrick Mooney /* reset controller */ 423*4c87aefeSPatrick Mooney pci_xhci_reset(sc); 424*4c87aefeSPatrick Mooney cmd &= ~XHCI_CMD_HCRST; 425*4c87aefeSPatrick Mooney } 426*4c87aefeSPatrick Mooney 427*4c87aefeSPatrick Mooney cmd &= ~(XHCI_CMD_CSS | XHCI_CMD_CRS); 428*4c87aefeSPatrick Mooney 429*4c87aefeSPatrick Mooney if (do_intr) 430*4c87aefeSPatrick Mooney pci_xhci_assert_interrupt(sc); 431*4c87aefeSPatrick Mooney 432*4c87aefeSPatrick Mooney return (cmd); 433*4c87aefeSPatrick Mooney } 434*4c87aefeSPatrick Mooney 435*4c87aefeSPatrick Mooney static void 436*4c87aefeSPatrick Mooney pci_xhci_portregs_write(struct pci_xhci_softc *sc, uint64_t offset, 437*4c87aefeSPatrick Mooney uint64_t value) 438*4c87aefeSPatrick Mooney { 439*4c87aefeSPatrick Mooney struct xhci_trb evtrb; 440*4c87aefeSPatrick Mooney struct pci_xhci_portregs *p; 441*4c87aefeSPatrick Mooney int port; 442*4c87aefeSPatrick Mooney uint32_t oldpls, newpls; 443*4c87aefeSPatrick Mooney 444*4c87aefeSPatrick Mooney if (sc->portregs == NULL) 445*4c87aefeSPatrick Mooney return; 446*4c87aefeSPatrick Mooney 447*4c87aefeSPatrick Mooney port = (offset - XHCI_PORTREGS_PORT0) / XHCI_PORTREGS_SETSZ; 448*4c87aefeSPatrick Mooney offset = (offset - XHCI_PORTREGS_PORT0) % XHCI_PORTREGS_SETSZ; 449*4c87aefeSPatrick Mooney 450*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: portregs wr offset 0x%lx, port %u: 0x%lx\r\n", 451*4c87aefeSPatrick Mooney offset, port, value)); 452*4c87aefeSPatrick Mooney 453*4c87aefeSPatrick Mooney assert(port >= 0); 454*4c87aefeSPatrick Mooney 455*4c87aefeSPatrick Mooney if (port > XHCI_MAX_DEVS) { 456*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: portregs_write port %d > ndevices\r\n", 457*4c87aefeSPatrick Mooney port)); 458*4c87aefeSPatrick Mooney return; 459*4c87aefeSPatrick Mooney } 460*4c87aefeSPatrick Mooney 461*4c87aefeSPatrick Mooney if (XHCI_DEVINST_PTR(sc, port) == NULL) { 462*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: portregs_write to unattached port %d\r\n", 463*4c87aefeSPatrick Mooney port)); 464*4c87aefeSPatrick Mooney } 465*4c87aefeSPatrick Mooney 466*4c87aefeSPatrick Mooney p = XHCI_PORTREG_PTR(sc, port); 467*4c87aefeSPatrick Mooney switch (offset) { 468*4c87aefeSPatrick Mooney case 0: 469*4c87aefeSPatrick Mooney /* port reset or warm reset */ 470*4c87aefeSPatrick Mooney if (value & (XHCI_PS_PR | XHCI_PS_WPR)) { 471*4c87aefeSPatrick Mooney pci_xhci_reset_port(sc, port, value & XHCI_PS_WPR); 472*4c87aefeSPatrick Mooney break; 473*4c87aefeSPatrick Mooney } 474*4c87aefeSPatrick Mooney 475*4c87aefeSPatrick Mooney if ((p->portsc & XHCI_PS_PP) == 0) { 476*4c87aefeSPatrick Mooney WPRINTF(("pci_xhci: portregs_write to unpowered " 477*4c87aefeSPatrick Mooney "port %d\r\n", port)); 478*4c87aefeSPatrick Mooney break; 479*4c87aefeSPatrick Mooney } 480*4c87aefeSPatrick Mooney 481*4c87aefeSPatrick Mooney /* Port status and control register */ 482*4c87aefeSPatrick Mooney oldpls = XHCI_PS_PLS_GET(p->portsc); 483*4c87aefeSPatrick Mooney newpls = XHCI_PS_PLS_GET(value); 484*4c87aefeSPatrick Mooney 485*4c87aefeSPatrick Mooney p->portsc &= XHCI_PS_PED | XHCI_PS_PLS_MASK | 486*4c87aefeSPatrick Mooney XHCI_PS_SPEED_MASK | XHCI_PS_PIC_MASK; 487*4c87aefeSPatrick Mooney 488*4c87aefeSPatrick Mooney if (XHCI_DEVINST_PTR(sc, port)) 489*4c87aefeSPatrick Mooney p->portsc |= XHCI_PS_CCS; 490*4c87aefeSPatrick Mooney 491*4c87aefeSPatrick Mooney p->portsc |= (value & 492*4c87aefeSPatrick Mooney ~(XHCI_PS_OCA | 493*4c87aefeSPatrick Mooney XHCI_PS_PR | 494*4c87aefeSPatrick Mooney XHCI_PS_PED | 495*4c87aefeSPatrick Mooney XHCI_PS_PLS_MASK | /* link state */ 496*4c87aefeSPatrick Mooney XHCI_PS_SPEED_MASK | 497*4c87aefeSPatrick Mooney XHCI_PS_PIC_MASK | /* port indicator */ 498*4c87aefeSPatrick Mooney XHCI_PS_LWS | XHCI_PS_DR | XHCI_PS_WPR)); 499*4c87aefeSPatrick Mooney 500*4c87aefeSPatrick Mooney /* clear control bits */ 501*4c87aefeSPatrick Mooney p->portsc &= ~(value & 502*4c87aefeSPatrick Mooney (XHCI_PS_CSC | 503*4c87aefeSPatrick Mooney XHCI_PS_PEC | 504*4c87aefeSPatrick Mooney XHCI_PS_WRC | 505*4c87aefeSPatrick Mooney XHCI_PS_OCC | 506*4c87aefeSPatrick Mooney XHCI_PS_PRC | 507*4c87aefeSPatrick Mooney XHCI_PS_PLC | 508*4c87aefeSPatrick Mooney XHCI_PS_CEC | 509*4c87aefeSPatrick Mooney XHCI_PS_CAS)); 510*4c87aefeSPatrick Mooney 511*4c87aefeSPatrick Mooney /* port disable request; for USB3, don't care */ 512*4c87aefeSPatrick Mooney if (value & XHCI_PS_PED) 513*4c87aefeSPatrick Mooney DPRINTF(("Disable port %d request\r\n", port)); 514*4c87aefeSPatrick Mooney 515*4c87aefeSPatrick Mooney if (!(value & XHCI_PS_LWS)) 516*4c87aefeSPatrick Mooney break; 517*4c87aefeSPatrick Mooney 518*4c87aefeSPatrick Mooney DPRINTF(("Port new PLS: %d\r\n", newpls)); 519*4c87aefeSPatrick Mooney switch (newpls) { 520*4c87aefeSPatrick Mooney case 0: /* U0 */ 521*4c87aefeSPatrick Mooney case 3: /* U3 */ 522*4c87aefeSPatrick Mooney if (oldpls != newpls) { 523*4c87aefeSPatrick Mooney p->portsc &= ~XHCI_PS_PLS_MASK; 524*4c87aefeSPatrick Mooney p->portsc |= XHCI_PS_PLS_SET(newpls) | 525*4c87aefeSPatrick Mooney XHCI_PS_PLC; 526*4c87aefeSPatrick Mooney 527*4c87aefeSPatrick Mooney if (oldpls != 0 && newpls == 0) { 528*4c87aefeSPatrick Mooney pci_xhci_set_evtrb(&evtrb, port, 529*4c87aefeSPatrick Mooney XHCI_TRB_ERROR_SUCCESS, 530*4c87aefeSPatrick Mooney XHCI_TRB_EVENT_PORT_STS_CHANGE); 531*4c87aefeSPatrick Mooney 532*4c87aefeSPatrick Mooney pci_xhci_insert_event(sc, &evtrb, 1); 533*4c87aefeSPatrick Mooney } 534*4c87aefeSPatrick Mooney } 535*4c87aefeSPatrick Mooney break; 536*4c87aefeSPatrick Mooney 537*4c87aefeSPatrick Mooney default: 538*4c87aefeSPatrick Mooney DPRINTF(("Unhandled change port %d PLS %u\r\n", 539*4c87aefeSPatrick Mooney port, newpls)); 540*4c87aefeSPatrick Mooney break; 541*4c87aefeSPatrick Mooney } 542*4c87aefeSPatrick Mooney break; 543*4c87aefeSPatrick Mooney case 4: 544*4c87aefeSPatrick Mooney /* Port power management status and control register */ 545*4c87aefeSPatrick Mooney p->portpmsc = value; 546*4c87aefeSPatrick Mooney break; 547*4c87aefeSPatrick Mooney case 8: 548*4c87aefeSPatrick Mooney /* Port link information register */ 549*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci attempted write to PORTLI, port %d\r\n", 550*4c87aefeSPatrick Mooney port)); 551*4c87aefeSPatrick Mooney break; 552*4c87aefeSPatrick Mooney case 12: 553*4c87aefeSPatrick Mooney /* 554*4c87aefeSPatrick Mooney * Port hardware LPM control register. 555*4c87aefeSPatrick Mooney * For USB3, this register is reserved. 556*4c87aefeSPatrick Mooney */ 557*4c87aefeSPatrick Mooney p->porthlpmc = value; 558*4c87aefeSPatrick Mooney break; 559*4c87aefeSPatrick Mooney } 560*4c87aefeSPatrick Mooney } 561*4c87aefeSPatrick Mooney 562*4c87aefeSPatrick Mooney struct xhci_dev_ctx * 563*4c87aefeSPatrick Mooney pci_xhci_get_dev_ctx(struct pci_xhci_softc *sc, uint32_t slot) 564*4c87aefeSPatrick Mooney { 565*4c87aefeSPatrick Mooney uint64_t devctx_addr; 566*4c87aefeSPatrick Mooney struct xhci_dev_ctx *devctx; 567*4c87aefeSPatrick Mooney 568*4c87aefeSPatrick Mooney assert(slot > 0 && slot <= sc->ndevices); 569*4c87aefeSPatrick Mooney assert(sc->opregs.dcbaa_p != NULL); 570*4c87aefeSPatrick Mooney 571*4c87aefeSPatrick Mooney devctx_addr = sc->opregs.dcbaa_p->dcba[slot]; 572*4c87aefeSPatrick Mooney 573*4c87aefeSPatrick Mooney if (devctx_addr == 0) { 574*4c87aefeSPatrick Mooney DPRINTF(("get_dev_ctx devctx_addr == 0\r\n")); 575*4c87aefeSPatrick Mooney return (NULL); 576*4c87aefeSPatrick Mooney } 577*4c87aefeSPatrick Mooney 578*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: get dev ctx, slot %u devctx addr %016lx\r\n", 579*4c87aefeSPatrick Mooney slot, devctx_addr)); 580*4c87aefeSPatrick Mooney devctx = XHCI_GADDR(sc, devctx_addr & ~0x3FUL); 581*4c87aefeSPatrick Mooney 582*4c87aefeSPatrick Mooney return (devctx); 583*4c87aefeSPatrick Mooney } 584*4c87aefeSPatrick Mooney 585*4c87aefeSPatrick Mooney struct xhci_trb * 586*4c87aefeSPatrick Mooney pci_xhci_trb_next(struct pci_xhci_softc *sc, struct xhci_trb *curtrb, 587*4c87aefeSPatrick Mooney uint64_t *guestaddr) 588*4c87aefeSPatrick Mooney { 589*4c87aefeSPatrick Mooney struct xhci_trb *next; 590*4c87aefeSPatrick Mooney 591*4c87aefeSPatrick Mooney assert(curtrb != NULL); 592*4c87aefeSPatrick Mooney 593*4c87aefeSPatrick Mooney if (XHCI_TRB_3_TYPE_GET(curtrb->dwTrb3) == XHCI_TRB_TYPE_LINK) { 594*4c87aefeSPatrick Mooney if (guestaddr) 595*4c87aefeSPatrick Mooney *guestaddr = curtrb->qwTrb0 & ~0xFUL; 596*4c87aefeSPatrick Mooney 597*4c87aefeSPatrick Mooney next = XHCI_GADDR(sc, curtrb->qwTrb0 & ~0xFUL); 598*4c87aefeSPatrick Mooney } else { 599*4c87aefeSPatrick Mooney if (guestaddr) 600*4c87aefeSPatrick Mooney *guestaddr += sizeof(struct xhci_trb) & ~0xFUL; 601*4c87aefeSPatrick Mooney 602*4c87aefeSPatrick Mooney next = curtrb + 1; 603*4c87aefeSPatrick Mooney } 604*4c87aefeSPatrick Mooney 605*4c87aefeSPatrick Mooney return (next); 606*4c87aefeSPatrick Mooney } 607*4c87aefeSPatrick Mooney 608*4c87aefeSPatrick Mooney static void 609*4c87aefeSPatrick Mooney pci_xhci_assert_interrupt(struct pci_xhci_softc *sc) 610*4c87aefeSPatrick Mooney { 611*4c87aefeSPatrick Mooney 612*4c87aefeSPatrick Mooney sc->rtsregs.intrreg.erdp |= XHCI_ERDP_LO_BUSY; 613*4c87aefeSPatrick Mooney sc->rtsregs.intrreg.iman |= XHCI_IMAN_INTR_PEND; 614*4c87aefeSPatrick Mooney sc->opregs.usbsts |= XHCI_STS_EINT; 615*4c87aefeSPatrick Mooney 616*4c87aefeSPatrick Mooney /* only trigger interrupt if permitted */ 617*4c87aefeSPatrick Mooney if ((sc->opregs.usbcmd & XHCI_CMD_INTE) && 618*4c87aefeSPatrick Mooney (sc->rtsregs.intrreg.iman & XHCI_IMAN_INTR_ENA)) { 619*4c87aefeSPatrick Mooney if (pci_msi_enabled(sc->xsc_pi)) 620*4c87aefeSPatrick Mooney pci_generate_msi(sc->xsc_pi, 0); 621*4c87aefeSPatrick Mooney else 622*4c87aefeSPatrick Mooney pci_lintr_assert(sc->xsc_pi); 623*4c87aefeSPatrick Mooney } 624*4c87aefeSPatrick Mooney } 625*4c87aefeSPatrick Mooney 626*4c87aefeSPatrick Mooney static void 627*4c87aefeSPatrick Mooney pci_xhci_deassert_interrupt(struct pci_xhci_softc *sc) 628*4c87aefeSPatrick Mooney { 629*4c87aefeSPatrick Mooney 630*4c87aefeSPatrick Mooney if (!pci_msi_enabled(sc->xsc_pi)) 631*4c87aefeSPatrick Mooney pci_lintr_assert(sc->xsc_pi); 632*4c87aefeSPatrick Mooney } 633*4c87aefeSPatrick Mooney 634*4c87aefeSPatrick Mooney static void 635*4c87aefeSPatrick Mooney pci_xhci_init_ep(struct pci_xhci_dev_emu *dev, int epid) 636*4c87aefeSPatrick Mooney { 637*4c87aefeSPatrick Mooney struct xhci_dev_ctx *dev_ctx; 638*4c87aefeSPatrick Mooney struct pci_xhci_dev_ep *devep; 639*4c87aefeSPatrick Mooney struct xhci_endp_ctx *ep_ctx; 640*4c87aefeSPatrick Mooney uint32_t pstreams; 641*4c87aefeSPatrick Mooney int i; 642*4c87aefeSPatrick Mooney 643*4c87aefeSPatrick Mooney dev_ctx = dev->dev_ctx; 644*4c87aefeSPatrick Mooney ep_ctx = &dev_ctx->ctx_ep[epid]; 645*4c87aefeSPatrick Mooney devep = &dev->eps[epid]; 646*4c87aefeSPatrick Mooney pstreams = XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0); 647*4c87aefeSPatrick Mooney if (pstreams > 0) { 648*4c87aefeSPatrick Mooney DPRINTF(("init_ep %d with pstreams %d\r\n", epid, pstreams)); 649*4c87aefeSPatrick Mooney assert(devep->ep_sctx_trbs == NULL); 650*4c87aefeSPatrick Mooney 651*4c87aefeSPatrick Mooney devep->ep_sctx = XHCI_GADDR(dev->xsc, ep_ctx->qwEpCtx2 & 652*4c87aefeSPatrick Mooney XHCI_EPCTX_2_TR_DQ_PTR_MASK); 653*4c87aefeSPatrick Mooney devep->ep_sctx_trbs = calloc(pstreams, 654*4c87aefeSPatrick Mooney sizeof(struct pci_xhci_trb_ring)); 655*4c87aefeSPatrick Mooney for (i = 0; i < pstreams; i++) { 656*4c87aefeSPatrick Mooney devep->ep_sctx_trbs[i].ringaddr = 657*4c87aefeSPatrick Mooney devep->ep_sctx[i].qwSctx0 & 658*4c87aefeSPatrick Mooney XHCI_SCTX_0_TR_DQ_PTR_MASK; 659*4c87aefeSPatrick Mooney devep->ep_sctx_trbs[i].ccs = 660*4c87aefeSPatrick Mooney XHCI_SCTX_0_DCS_GET(devep->ep_sctx[i].qwSctx0); 661*4c87aefeSPatrick Mooney } 662*4c87aefeSPatrick Mooney } else { 663*4c87aefeSPatrick Mooney DPRINTF(("init_ep %d with no pstreams\r\n", epid)); 664*4c87aefeSPatrick Mooney devep->ep_ringaddr = ep_ctx->qwEpCtx2 & 665*4c87aefeSPatrick Mooney XHCI_EPCTX_2_TR_DQ_PTR_MASK; 666*4c87aefeSPatrick Mooney devep->ep_ccs = XHCI_EPCTX_2_DCS_GET(ep_ctx->qwEpCtx2); 667*4c87aefeSPatrick Mooney devep->ep_tr = XHCI_GADDR(dev->xsc, devep->ep_ringaddr); 668*4c87aefeSPatrick Mooney DPRINTF(("init_ep tr DCS %x\r\n", devep->ep_ccs)); 669*4c87aefeSPatrick Mooney } 670*4c87aefeSPatrick Mooney 671*4c87aefeSPatrick Mooney if (devep->ep_xfer == NULL) { 672*4c87aefeSPatrick Mooney devep->ep_xfer = malloc(sizeof(struct usb_data_xfer)); 673*4c87aefeSPatrick Mooney USB_DATA_XFER_INIT(devep->ep_xfer); 674*4c87aefeSPatrick Mooney } 675*4c87aefeSPatrick Mooney } 676*4c87aefeSPatrick Mooney 677*4c87aefeSPatrick Mooney static void 678*4c87aefeSPatrick Mooney pci_xhci_disable_ep(struct pci_xhci_dev_emu *dev, int epid) 679*4c87aefeSPatrick Mooney { 680*4c87aefeSPatrick Mooney struct xhci_dev_ctx *dev_ctx; 681*4c87aefeSPatrick Mooney struct pci_xhci_dev_ep *devep; 682*4c87aefeSPatrick Mooney struct xhci_endp_ctx *ep_ctx; 683*4c87aefeSPatrick Mooney 684*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci disable_ep %d\r\n", epid)); 685*4c87aefeSPatrick Mooney 686*4c87aefeSPatrick Mooney dev_ctx = dev->dev_ctx; 687*4c87aefeSPatrick Mooney ep_ctx = &dev_ctx->ctx_ep[epid]; 688*4c87aefeSPatrick Mooney ep_ctx->dwEpCtx0 = (ep_ctx->dwEpCtx0 & ~0x7) | XHCI_ST_EPCTX_DISABLED; 689*4c87aefeSPatrick Mooney 690*4c87aefeSPatrick Mooney devep = &dev->eps[epid]; 691*4c87aefeSPatrick Mooney if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) > 0 && 692*4c87aefeSPatrick Mooney devep->ep_sctx_trbs != NULL) 693*4c87aefeSPatrick Mooney free(devep->ep_sctx_trbs); 694*4c87aefeSPatrick Mooney 695*4c87aefeSPatrick Mooney if (devep->ep_xfer != NULL) { 696*4c87aefeSPatrick Mooney free(devep->ep_xfer); 697*4c87aefeSPatrick Mooney devep->ep_xfer = NULL; 698*4c87aefeSPatrick Mooney } 699*4c87aefeSPatrick Mooney 700*4c87aefeSPatrick Mooney memset(devep, 0, sizeof(struct pci_xhci_dev_ep)); 701*4c87aefeSPatrick Mooney } 702*4c87aefeSPatrick Mooney 703*4c87aefeSPatrick Mooney 704*4c87aefeSPatrick Mooney /* reset device at slot and data structures related to it */ 705*4c87aefeSPatrick Mooney static void 706*4c87aefeSPatrick Mooney pci_xhci_reset_slot(struct pci_xhci_softc *sc, int slot) 707*4c87aefeSPatrick Mooney { 708*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev; 709*4c87aefeSPatrick Mooney 710*4c87aefeSPatrick Mooney dev = XHCI_SLOTDEV_PTR(sc, slot); 711*4c87aefeSPatrick Mooney 712*4c87aefeSPatrick Mooney if (!dev) { 713*4c87aefeSPatrick Mooney DPRINTF(("xhci reset unassigned slot (%d)?\r\n", slot)); 714*4c87aefeSPatrick Mooney } else { 715*4c87aefeSPatrick Mooney dev->dev_slotstate = XHCI_ST_DISABLED; 716*4c87aefeSPatrick Mooney } 717*4c87aefeSPatrick Mooney 718*4c87aefeSPatrick Mooney /* TODO: reset ring buffer pointers */ 719*4c87aefeSPatrick Mooney } 720*4c87aefeSPatrick Mooney 721*4c87aefeSPatrick Mooney static int 722*4c87aefeSPatrick Mooney pci_xhci_insert_event(struct pci_xhci_softc *sc, struct xhci_trb *evtrb, 723*4c87aefeSPatrick Mooney int do_intr) 724*4c87aefeSPatrick Mooney { 725*4c87aefeSPatrick Mooney struct pci_xhci_rtsregs *rts; 726*4c87aefeSPatrick Mooney uint64_t erdp; 727*4c87aefeSPatrick Mooney int erdp_idx; 728*4c87aefeSPatrick Mooney int err; 729*4c87aefeSPatrick Mooney struct xhci_trb *evtrbptr; 730*4c87aefeSPatrick Mooney 731*4c87aefeSPatrick Mooney err = XHCI_TRB_ERROR_SUCCESS; 732*4c87aefeSPatrick Mooney 733*4c87aefeSPatrick Mooney rts = &sc->rtsregs; 734*4c87aefeSPatrick Mooney 735*4c87aefeSPatrick Mooney erdp = rts->intrreg.erdp & ~0xF; 736*4c87aefeSPatrick Mooney erdp_idx = (erdp - rts->erstba_p[rts->er_deq_seg].qwEvrsTablePtr) / 737*4c87aefeSPatrick Mooney sizeof(struct xhci_trb); 738*4c87aefeSPatrick Mooney 739*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: insert event 0[%lx] 2[%x] 3[%x]\r\n" 740*4c87aefeSPatrick Mooney "\terdp idx %d/seg %d, enq idx %d/seg %d, pcs %u\r\n" 741*4c87aefeSPatrick Mooney "\t(erdp=0x%lx, erst=0x%lx, tblsz=%u, do_intr %d)\r\n", 742*4c87aefeSPatrick Mooney evtrb->qwTrb0, evtrb->dwTrb2, evtrb->dwTrb3, 743*4c87aefeSPatrick Mooney erdp_idx, rts->er_deq_seg, rts->er_enq_idx, 744*4c87aefeSPatrick Mooney rts->er_enq_seg, 745*4c87aefeSPatrick Mooney rts->event_pcs, erdp, rts->erstba_p->qwEvrsTablePtr, 746*4c87aefeSPatrick Mooney rts->erstba_p->dwEvrsTableSize, do_intr)); 747*4c87aefeSPatrick Mooney 748*4c87aefeSPatrick Mooney evtrbptr = &rts->erst_p[rts->er_enq_idx]; 749*4c87aefeSPatrick Mooney 750*4c87aefeSPatrick Mooney /* TODO: multi-segment table */ 751*4c87aefeSPatrick Mooney if (rts->er_events_cnt >= rts->erstba_p->dwEvrsTableSize) { 752*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci[%d] cannot insert event; ring full\r\n", 753*4c87aefeSPatrick Mooney __LINE__)); 754*4c87aefeSPatrick Mooney err = XHCI_TRB_ERROR_EV_RING_FULL; 755*4c87aefeSPatrick Mooney goto done; 756*4c87aefeSPatrick Mooney } 757*4c87aefeSPatrick Mooney 758*4c87aefeSPatrick Mooney if (rts->er_events_cnt == rts->erstba_p->dwEvrsTableSize - 1) { 759*4c87aefeSPatrick Mooney struct xhci_trb errev; 760*4c87aefeSPatrick Mooney 761*4c87aefeSPatrick Mooney if ((evtrbptr->dwTrb3 & 0x1) == (rts->event_pcs & 0x1)) { 762*4c87aefeSPatrick Mooney 763*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci[%d] insert evt err: ring full\r\n", 764*4c87aefeSPatrick Mooney __LINE__)); 765*4c87aefeSPatrick Mooney 766*4c87aefeSPatrick Mooney errev.qwTrb0 = 0; 767*4c87aefeSPatrick Mooney errev.dwTrb2 = XHCI_TRB_2_ERROR_SET( 768*4c87aefeSPatrick Mooney XHCI_TRB_ERROR_EV_RING_FULL); 769*4c87aefeSPatrick Mooney errev.dwTrb3 = XHCI_TRB_3_TYPE_SET( 770*4c87aefeSPatrick Mooney XHCI_TRB_EVENT_HOST_CTRL) | 771*4c87aefeSPatrick Mooney rts->event_pcs; 772*4c87aefeSPatrick Mooney rts->er_events_cnt++; 773*4c87aefeSPatrick Mooney memcpy(&rts->erst_p[rts->er_enq_idx], &errev, 774*4c87aefeSPatrick Mooney sizeof(struct xhci_trb)); 775*4c87aefeSPatrick Mooney rts->er_enq_idx = (rts->er_enq_idx + 1) % 776*4c87aefeSPatrick Mooney rts->erstba_p->dwEvrsTableSize; 777*4c87aefeSPatrick Mooney err = XHCI_TRB_ERROR_EV_RING_FULL; 778*4c87aefeSPatrick Mooney do_intr = 1; 779*4c87aefeSPatrick Mooney 780*4c87aefeSPatrick Mooney goto done; 781*4c87aefeSPatrick Mooney } 782*4c87aefeSPatrick Mooney } else { 783*4c87aefeSPatrick Mooney rts->er_events_cnt++; 784*4c87aefeSPatrick Mooney } 785*4c87aefeSPatrick Mooney 786*4c87aefeSPatrick Mooney evtrb->dwTrb3 &= ~XHCI_TRB_3_CYCLE_BIT; 787*4c87aefeSPatrick Mooney evtrb->dwTrb3 |= rts->event_pcs; 788*4c87aefeSPatrick Mooney 789*4c87aefeSPatrick Mooney memcpy(&rts->erst_p[rts->er_enq_idx], evtrb, sizeof(struct xhci_trb)); 790*4c87aefeSPatrick Mooney rts->er_enq_idx = (rts->er_enq_idx + 1) % 791*4c87aefeSPatrick Mooney rts->erstba_p->dwEvrsTableSize; 792*4c87aefeSPatrick Mooney 793*4c87aefeSPatrick Mooney if (rts->er_enq_idx == 0) 794*4c87aefeSPatrick Mooney rts->event_pcs ^= 1; 795*4c87aefeSPatrick Mooney 796*4c87aefeSPatrick Mooney done: 797*4c87aefeSPatrick Mooney if (do_intr) 798*4c87aefeSPatrick Mooney pci_xhci_assert_interrupt(sc); 799*4c87aefeSPatrick Mooney 800*4c87aefeSPatrick Mooney return (err); 801*4c87aefeSPatrick Mooney } 802*4c87aefeSPatrick Mooney 803*4c87aefeSPatrick Mooney static uint32_t 804*4c87aefeSPatrick Mooney pci_xhci_cmd_enable_slot(struct pci_xhci_softc *sc, uint32_t *slot) 805*4c87aefeSPatrick Mooney { 806*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev; 807*4c87aefeSPatrick Mooney uint32_t cmderr; 808*4c87aefeSPatrick Mooney int i; 809*4c87aefeSPatrick Mooney 810*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_NO_SLOTS; 811*4c87aefeSPatrick Mooney if (sc->portregs != NULL) 812*4c87aefeSPatrick Mooney for (i = 1; i <= XHCI_MAX_SLOTS; i++) { 813*4c87aefeSPatrick Mooney dev = XHCI_SLOTDEV_PTR(sc, i); 814*4c87aefeSPatrick Mooney if (dev && dev->dev_slotstate == XHCI_ST_DISABLED) { 815*4c87aefeSPatrick Mooney *slot = i; 816*4c87aefeSPatrick Mooney dev->dev_slotstate = XHCI_ST_ENABLED; 817*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_SUCCESS; 818*4c87aefeSPatrick Mooney dev->hci.hci_address = i; 819*4c87aefeSPatrick Mooney break; 820*4c87aefeSPatrick Mooney } 821*4c87aefeSPatrick Mooney } 822*4c87aefeSPatrick Mooney 823*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci enable slot (error=%d) slot %u\r\n", 824*4c87aefeSPatrick Mooney cmderr != XHCI_TRB_ERROR_SUCCESS, *slot)); 825*4c87aefeSPatrick Mooney 826*4c87aefeSPatrick Mooney return (cmderr); 827*4c87aefeSPatrick Mooney } 828*4c87aefeSPatrick Mooney 829*4c87aefeSPatrick Mooney static uint32_t 830*4c87aefeSPatrick Mooney pci_xhci_cmd_disable_slot(struct pci_xhci_softc *sc, uint32_t slot) 831*4c87aefeSPatrick Mooney { 832*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev; 833*4c87aefeSPatrick Mooney uint32_t cmderr; 834*4c87aefeSPatrick Mooney 835*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci disable slot %u\r\n", slot)); 836*4c87aefeSPatrick Mooney 837*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_NO_SLOTS; 838*4c87aefeSPatrick Mooney if (sc->portregs == NULL) 839*4c87aefeSPatrick Mooney goto done; 840*4c87aefeSPatrick Mooney 841*4c87aefeSPatrick Mooney if (slot > sc->ndevices) { 842*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON; 843*4c87aefeSPatrick Mooney goto done; 844*4c87aefeSPatrick Mooney } 845*4c87aefeSPatrick Mooney 846*4c87aefeSPatrick Mooney dev = XHCI_SLOTDEV_PTR(sc, slot); 847*4c87aefeSPatrick Mooney if (dev) { 848*4c87aefeSPatrick Mooney if (dev->dev_slotstate == XHCI_ST_DISABLED) { 849*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON; 850*4c87aefeSPatrick Mooney } else { 851*4c87aefeSPatrick Mooney dev->dev_slotstate = XHCI_ST_DISABLED; 852*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_SUCCESS; 853*4c87aefeSPatrick Mooney /* TODO: reset events and endpoints */ 854*4c87aefeSPatrick Mooney } 855*4c87aefeSPatrick Mooney } 856*4c87aefeSPatrick Mooney 857*4c87aefeSPatrick Mooney done: 858*4c87aefeSPatrick Mooney return (cmderr); 859*4c87aefeSPatrick Mooney } 860*4c87aefeSPatrick Mooney 861*4c87aefeSPatrick Mooney static uint32_t 862*4c87aefeSPatrick Mooney pci_xhci_cmd_reset_device(struct pci_xhci_softc *sc, uint32_t slot) 863*4c87aefeSPatrick Mooney { 864*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev; 865*4c87aefeSPatrick Mooney struct xhci_dev_ctx *dev_ctx; 866*4c87aefeSPatrick Mooney struct xhci_endp_ctx *ep_ctx; 867*4c87aefeSPatrick Mooney uint32_t cmderr; 868*4c87aefeSPatrick Mooney int i; 869*4c87aefeSPatrick Mooney 870*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_NO_SLOTS; 871*4c87aefeSPatrick Mooney if (sc->portregs == NULL) 872*4c87aefeSPatrick Mooney goto done; 873*4c87aefeSPatrick Mooney 874*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci reset device slot %u\r\n", slot)); 875*4c87aefeSPatrick Mooney 876*4c87aefeSPatrick Mooney dev = XHCI_SLOTDEV_PTR(sc, slot); 877*4c87aefeSPatrick Mooney if (!dev || dev->dev_slotstate == XHCI_ST_DISABLED) 878*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON; 879*4c87aefeSPatrick Mooney else { 880*4c87aefeSPatrick Mooney dev->dev_slotstate = XHCI_ST_DEFAULT; 881*4c87aefeSPatrick Mooney 882*4c87aefeSPatrick Mooney dev->hci.hci_address = 0; 883*4c87aefeSPatrick Mooney dev_ctx = pci_xhci_get_dev_ctx(sc, slot); 884*4c87aefeSPatrick Mooney 885*4c87aefeSPatrick Mooney /* slot state */ 886*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx3 = FIELD_REPLACE( 887*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx3, XHCI_ST_SLCTX_DEFAULT, 888*4c87aefeSPatrick Mooney 0x1F, 27); 889*4c87aefeSPatrick Mooney 890*4c87aefeSPatrick Mooney /* number of contexts */ 891*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx0 = FIELD_REPLACE( 892*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx0, 1, 0x1F, 27); 893*4c87aefeSPatrick Mooney 894*4c87aefeSPatrick Mooney /* reset all eps other than ep-0 */ 895*4c87aefeSPatrick Mooney for (i = 2; i <= 31; i++) { 896*4c87aefeSPatrick Mooney ep_ctx = &dev_ctx->ctx_ep[i]; 897*4c87aefeSPatrick Mooney ep_ctx->dwEpCtx0 = FIELD_REPLACE( ep_ctx->dwEpCtx0, 898*4c87aefeSPatrick Mooney XHCI_ST_EPCTX_DISABLED, 0x7, 0); 899*4c87aefeSPatrick Mooney } 900*4c87aefeSPatrick Mooney 901*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_SUCCESS; 902*4c87aefeSPatrick Mooney } 903*4c87aefeSPatrick Mooney 904*4c87aefeSPatrick Mooney pci_xhci_reset_slot(sc, slot); 905*4c87aefeSPatrick Mooney 906*4c87aefeSPatrick Mooney done: 907*4c87aefeSPatrick Mooney return (cmderr); 908*4c87aefeSPatrick Mooney } 909*4c87aefeSPatrick Mooney 910*4c87aefeSPatrick Mooney static uint32_t 911*4c87aefeSPatrick Mooney pci_xhci_cmd_address_device(struct pci_xhci_softc *sc, uint32_t slot, 912*4c87aefeSPatrick Mooney struct xhci_trb *trb) 913*4c87aefeSPatrick Mooney { 914*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev; 915*4c87aefeSPatrick Mooney struct xhci_input_dev_ctx *input_ctx; 916*4c87aefeSPatrick Mooney struct xhci_slot_ctx *islot_ctx; 917*4c87aefeSPatrick Mooney struct xhci_dev_ctx *dev_ctx; 918*4c87aefeSPatrick Mooney struct xhci_endp_ctx *ep0_ctx; 919*4c87aefeSPatrick Mooney uint32_t cmderr; 920*4c87aefeSPatrick Mooney 921*4c87aefeSPatrick Mooney input_ctx = XHCI_GADDR(sc, trb->qwTrb0 & ~0xFUL); 922*4c87aefeSPatrick Mooney islot_ctx = &input_ctx->ctx_slot; 923*4c87aefeSPatrick Mooney ep0_ctx = &input_ctx->ctx_ep[1]; 924*4c87aefeSPatrick Mooney 925*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_SUCCESS; 926*4c87aefeSPatrick Mooney 927*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: address device, input ctl: D 0x%08x A 0x%08x,\r\n" 928*4c87aefeSPatrick Mooney " slot %08x %08x %08x %08x\r\n" 929*4c87aefeSPatrick Mooney " ep0 %08x %08x %016lx %08x\r\n", 930*4c87aefeSPatrick Mooney input_ctx->ctx_input.dwInCtx0, input_ctx->ctx_input.dwInCtx1, 931*4c87aefeSPatrick Mooney islot_ctx->dwSctx0, islot_ctx->dwSctx1, 932*4c87aefeSPatrick Mooney islot_ctx->dwSctx2, islot_ctx->dwSctx3, 933*4c87aefeSPatrick Mooney ep0_ctx->dwEpCtx0, ep0_ctx->dwEpCtx1, ep0_ctx->qwEpCtx2, 934*4c87aefeSPatrick Mooney ep0_ctx->dwEpCtx4)); 935*4c87aefeSPatrick Mooney 936*4c87aefeSPatrick Mooney /* when setting address: drop-ctx=0, add-ctx=slot+ep0 */ 937*4c87aefeSPatrick Mooney if ((input_ctx->ctx_input.dwInCtx0 != 0) || 938*4c87aefeSPatrick Mooney (input_ctx->ctx_input.dwInCtx1 & 0x03) != 0x03) { 939*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: address device, input ctl invalid\r\n")); 940*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_TRB; 941*4c87aefeSPatrick Mooney goto done; 942*4c87aefeSPatrick Mooney } 943*4c87aefeSPatrick Mooney 944*4c87aefeSPatrick Mooney /* assign address to slot */ 945*4c87aefeSPatrick Mooney dev_ctx = pci_xhci_get_dev_ctx(sc, slot); 946*4c87aefeSPatrick Mooney 947*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: address device, dev ctx\r\n" 948*4c87aefeSPatrick Mooney " slot %08x %08x %08x %08x\r\n", 949*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx0, dev_ctx->ctx_slot.dwSctx1, 950*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx2, dev_ctx->ctx_slot.dwSctx3)); 951*4c87aefeSPatrick Mooney 952*4c87aefeSPatrick Mooney dev = XHCI_SLOTDEV_PTR(sc, slot); 953*4c87aefeSPatrick Mooney assert(dev != NULL); 954*4c87aefeSPatrick Mooney 955*4c87aefeSPatrick Mooney dev->hci.hci_address = slot; 956*4c87aefeSPatrick Mooney dev->dev_ctx = dev_ctx; 957*4c87aefeSPatrick Mooney 958*4c87aefeSPatrick Mooney if (dev->dev_ue->ue_reset == NULL || 959*4c87aefeSPatrick Mooney dev->dev_ue->ue_reset(dev->dev_sc) < 0) { 960*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_ENDP_NOT_ON; 961*4c87aefeSPatrick Mooney goto done; 962*4c87aefeSPatrick Mooney } 963*4c87aefeSPatrick Mooney 964*4c87aefeSPatrick Mooney memcpy(&dev_ctx->ctx_slot, islot_ctx, sizeof(struct xhci_slot_ctx)); 965*4c87aefeSPatrick Mooney 966*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx3 = 967*4c87aefeSPatrick Mooney XHCI_SCTX_3_SLOT_STATE_SET(XHCI_ST_SLCTX_ADDRESSED) | 968*4c87aefeSPatrick Mooney XHCI_SCTX_3_DEV_ADDR_SET(slot); 969*4c87aefeSPatrick Mooney 970*4c87aefeSPatrick Mooney memcpy(&dev_ctx->ctx_ep[1], ep0_ctx, sizeof(struct xhci_endp_ctx)); 971*4c87aefeSPatrick Mooney ep0_ctx = &dev_ctx->ctx_ep[1]; 972*4c87aefeSPatrick Mooney ep0_ctx->dwEpCtx0 = (ep0_ctx->dwEpCtx0 & ~0x7) | 973*4c87aefeSPatrick Mooney XHCI_EPCTX_0_EPSTATE_SET(XHCI_ST_EPCTX_RUNNING); 974*4c87aefeSPatrick Mooney 975*4c87aefeSPatrick Mooney pci_xhci_init_ep(dev, 1); 976*4c87aefeSPatrick Mooney 977*4c87aefeSPatrick Mooney dev->dev_slotstate = XHCI_ST_ADDRESSED; 978*4c87aefeSPatrick Mooney 979*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: address device, output ctx\r\n" 980*4c87aefeSPatrick Mooney " slot %08x %08x %08x %08x\r\n" 981*4c87aefeSPatrick Mooney " ep0 %08x %08x %016lx %08x\r\n", 982*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx0, dev_ctx->ctx_slot.dwSctx1, 983*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx2, dev_ctx->ctx_slot.dwSctx3, 984*4c87aefeSPatrick Mooney ep0_ctx->dwEpCtx0, ep0_ctx->dwEpCtx1, ep0_ctx->qwEpCtx2, 985*4c87aefeSPatrick Mooney ep0_ctx->dwEpCtx4)); 986*4c87aefeSPatrick Mooney 987*4c87aefeSPatrick Mooney done: 988*4c87aefeSPatrick Mooney return (cmderr); 989*4c87aefeSPatrick Mooney } 990*4c87aefeSPatrick Mooney 991*4c87aefeSPatrick Mooney static uint32_t 992*4c87aefeSPatrick Mooney pci_xhci_cmd_config_ep(struct pci_xhci_softc *sc, uint32_t slot, 993*4c87aefeSPatrick Mooney struct xhci_trb *trb) 994*4c87aefeSPatrick Mooney { 995*4c87aefeSPatrick Mooney struct xhci_input_dev_ctx *input_ctx; 996*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev; 997*4c87aefeSPatrick Mooney struct xhci_dev_ctx *dev_ctx; 998*4c87aefeSPatrick Mooney struct xhci_endp_ctx *ep_ctx, *iep_ctx; 999*4c87aefeSPatrick Mooney uint32_t cmderr; 1000*4c87aefeSPatrick Mooney int i; 1001*4c87aefeSPatrick Mooney 1002*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_SUCCESS; 1003*4c87aefeSPatrick Mooney 1004*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci config_ep slot %u\r\n", slot)); 1005*4c87aefeSPatrick Mooney 1006*4c87aefeSPatrick Mooney dev = XHCI_SLOTDEV_PTR(sc, slot); 1007*4c87aefeSPatrick Mooney assert(dev != NULL); 1008*4c87aefeSPatrick Mooney 1009*4c87aefeSPatrick Mooney if ((trb->dwTrb3 & XHCI_TRB_3_DCEP_BIT) != 0) { 1010*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci config_ep - deconfigure ep slot %u\r\n", 1011*4c87aefeSPatrick Mooney slot)); 1012*4c87aefeSPatrick Mooney if (dev->dev_ue->ue_stop != NULL) 1013*4c87aefeSPatrick Mooney dev->dev_ue->ue_stop(dev->dev_sc); 1014*4c87aefeSPatrick Mooney 1015*4c87aefeSPatrick Mooney dev->dev_slotstate = XHCI_ST_ADDRESSED; 1016*4c87aefeSPatrick Mooney 1017*4c87aefeSPatrick Mooney dev->hci.hci_address = 0; 1018*4c87aefeSPatrick Mooney dev_ctx = pci_xhci_get_dev_ctx(sc, slot); 1019*4c87aefeSPatrick Mooney 1020*4c87aefeSPatrick Mooney /* number of contexts */ 1021*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx0 = FIELD_REPLACE( 1022*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx0, 1, 0x1F, 27); 1023*4c87aefeSPatrick Mooney 1024*4c87aefeSPatrick Mooney /* slot state */ 1025*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx3 = FIELD_REPLACE( 1026*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx3, XHCI_ST_SLCTX_ADDRESSED, 1027*4c87aefeSPatrick Mooney 0x1F, 27); 1028*4c87aefeSPatrick Mooney 1029*4c87aefeSPatrick Mooney /* disable endpoints */ 1030*4c87aefeSPatrick Mooney for (i = 2; i < 32; i++) 1031*4c87aefeSPatrick Mooney pci_xhci_disable_ep(dev, i); 1032*4c87aefeSPatrick Mooney 1033*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_SUCCESS; 1034*4c87aefeSPatrick Mooney 1035*4c87aefeSPatrick Mooney goto done; 1036*4c87aefeSPatrick Mooney } 1037*4c87aefeSPatrick Mooney 1038*4c87aefeSPatrick Mooney if (dev->dev_slotstate < XHCI_ST_ADDRESSED) { 1039*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: config_ep slotstate x%x != addressed\r\n", 1040*4c87aefeSPatrick Mooney dev->dev_slotstate)); 1041*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_SLOT_NOT_ON; 1042*4c87aefeSPatrick Mooney goto done; 1043*4c87aefeSPatrick Mooney } 1044*4c87aefeSPatrick Mooney 1045*4c87aefeSPatrick Mooney /* In addressed/configured state; 1046*4c87aefeSPatrick Mooney * for each drop endpoint ctx flag: 1047*4c87aefeSPatrick Mooney * ep->state = DISABLED 1048*4c87aefeSPatrick Mooney * for each add endpoint ctx flag: 1049*4c87aefeSPatrick Mooney * cp(ep-in, ep-out) 1050*4c87aefeSPatrick Mooney * ep->state = RUNNING 1051*4c87aefeSPatrick Mooney * for each drop+add endpoint flag: 1052*4c87aefeSPatrick Mooney * reset ep resources 1053*4c87aefeSPatrick Mooney * cp(ep-in, ep-out) 1054*4c87aefeSPatrick Mooney * ep->state = RUNNING 1055*4c87aefeSPatrick Mooney * if input->DisabledCtx[2-31] < 30: (at least 1 ep not disabled) 1056*4c87aefeSPatrick Mooney * slot->state = configured 1057*4c87aefeSPatrick Mooney */ 1058*4c87aefeSPatrick Mooney 1059*4c87aefeSPatrick Mooney input_ctx = XHCI_GADDR(sc, trb->qwTrb0 & ~0xFUL); 1060*4c87aefeSPatrick Mooney dev_ctx = dev->dev_ctx; 1061*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: config_ep inputctx: D:x%08x A:x%08x 7:x%08x\r\n", 1062*4c87aefeSPatrick Mooney input_ctx->ctx_input.dwInCtx0, input_ctx->ctx_input.dwInCtx1, 1063*4c87aefeSPatrick Mooney input_ctx->ctx_input.dwInCtx7)); 1064*4c87aefeSPatrick Mooney 1065*4c87aefeSPatrick Mooney for (i = 2; i <= 31; i++) { 1066*4c87aefeSPatrick Mooney ep_ctx = &dev_ctx->ctx_ep[i]; 1067*4c87aefeSPatrick Mooney 1068*4c87aefeSPatrick Mooney if (input_ctx->ctx_input.dwInCtx0 & 1069*4c87aefeSPatrick Mooney XHCI_INCTX_0_DROP_MASK(i)) { 1070*4c87aefeSPatrick Mooney DPRINTF((" config ep - dropping ep %d\r\n", i)); 1071*4c87aefeSPatrick Mooney pci_xhci_disable_ep(dev, i); 1072*4c87aefeSPatrick Mooney } 1073*4c87aefeSPatrick Mooney 1074*4c87aefeSPatrick Mooney if (input_ctx->ctx_input.dwInCtx1 & 1075*4c87aefeSPatrick Mooney XHCI_INCTX_1_ADD_MASK(i)) { 1076*4c87aefeSPatrick Mooney iep_ctx = &input_ctx->ctx_ep[i]; 1077*4c87aefeSPatrick Mooney 1078*4c87aefeSPatrick Mooney DPRINTF((" enable ep[%d] %08x %08x %016lx %08x\r\n", 1079*4c87aefeSPatrick Mooney i, iep_ctx->dwEpCtx0, iep_ctx->dwEpCtx1, 1080*4c87aefeSPatrick Mooney iep_ctx->qwEpCtx2, iep_ctx->dwEpCtx4)); 1081*4c87aefeSPatrick Mooney 1082*4c87aefeSPatrick Mooney memcpy(ep_ctx, iep_ctx, sizeof(struct xhci_endp_ctx)); 1083*4c87aefeSPatrick Mooney 1084*4c87aefeSPatrick Mooney pci_xhci_init_ep(dev, i); 1085*4c87aefeSPatrick Mooney 1086*4c87aefeSPatrick Mooney /* ep state */ 1087*4c87aefeSPatrick Mooney ep_ctx->dwEpCtx0 = FIELD_REPLACE( 1088*4c87aefeSPatrick Mooney ep_ctx->dwEpCtx0, XHCI_ST_EPCTX_RUNNING, 0x7, 0); 1089*4c87aefeSPatrick Mooney } 1090*4c87aefeSPatrick Mooney } 1091*4c87aefeSPatrick Mooney 1092*4c87aefeSPatrick Mooney /* slot state to configured */ 1093*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx3 = FIELD_REPLACE( 1094*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx3, XHCI_ST_SLCTX_CONFIGURED, 0x1F, 27); 1095*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx0 = FIELD_COPY( 1096*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx0, input_ctx->ctx_slot.dwSctx0, 0x1F, 27); 1097*4c87aefeSPatrick Mooney dev->dev_slotstate = XHCI_ST_CONFIGURED; 1098*4c87aefeSPatrick Mooney 1099*4c87aefeSPatrick Mooney DPRINTF(("EP configured; slot %u [0]=0x%08x [1]=0x%08x [2]=0x%08x " 1100*4c87aefeSPatrick Mooney "[3]=0x%08x\r\n", 1101*4c87aefeSPatrick Mooney slot, dev_ctx->ctx_slot.dwSctx0, dev_ctx->ctx_slot.dwSctx1, 1102*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx2, dev_ctx->ctx_slot.dwSctx3)); 1103*4c87aefeSPatrick Mooney 1104*4c87aefeSPatrick Mooney done: 1105*4c87aefeSPatrick Mooney return (cmderr); 1106*4c87aefeSPatrick Mooney } 1107*4c87aefeSPatrick Mooney 1108*4c87aefeSPatrick Mooney static uint32_t 1109*4c87aefeSPatrick Mooney pci_xhci_cmd_reset_ep(struct pci_xhci_softc *sc, uint32_t slot, 1110*4c87aefeSPatrick Mooney struct xhci_trb *trb) 1111*4c87aefeSPatrick Mooney { 1112*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev; 1113*4c87aefeSPatrick Mooney struct pci_xhci_dev_ep *devep; 1114*4c87aefeSPatrick Mooney struct xhci_dev_ctx *dev_ctx; 1115*4c87aefeSPatrick Mooney struct xhci_endp_ctx *ep_ctx; 1116*4c87aefeSPatrick Mooney uint32_t cmderr, epid; 1117*4c87aefeSPatrick Mooney uint32_t type; 1118*4c87aefeSPatrick Mooney 1119*4c87aefeSPatrick Mooney epid = XHCI_TRB_3_EP_GET(trb->dwTrb3); 1120*4c87aefeSPatrick Mooney 1121*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: reset ep %u: slot %u\r\n", epid, slot)); 1122*4c87aefeSPatrick Mooney 1123*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_SUCCESS; 1124*4c87aefeSPatrick Mooney 1125*4c87aefeSPatrick Mooney type = XHCI_TRB_3_TYPE_GET(trb->dwTrb3); 1126*4c87aefeSPatrick Mooney 1127*4c87aefeSPatrick Mooney dev = XHCI_SLOTDEV_PTR(sc, slot); 1128*4c87aefeSPatrick Mooney assert(dev != NULL); 1129*4c87aefeSPatrick Mooney 1130*4c87aefeSPatrick Mooney if (type == XHCI_TRB_TYPE_STOP_EP && 1131*4c87aefeSPatrick Mooney (trb->dwTrb3 & XHCI_TRB_3_SUSP_EP_BIT) != 0) { 1132*4c87aefeSPatrick Mooney /* XXX suspend endpoint for 10ms */ 1133*4c87aefeSPatrick Mooney } 1134*4c87aefeSPatrick Mooney 1135*4c87aefeSPatrick Mooney if (epid < 1 || epid > 31) { 1136*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: reset ep: invalid epid %u\r\n", epid)); 1137*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_TRB; 1138*4c87aefeSPatrick Mooney goto done; 1139*4c87aefeSPatrick Mooney } 1140*4c87aefeSPatrick Mooney 1141*4c87aefeSPatrick Mooney devep = &dev->eps[epid]; 1142*4c87aefeSPatrick Mooney if (devep->ep_xfer != NULL) 1143*4c87aefeSPatrick Mooney USB_DATA_XFER_RESET(devep->ep_xfer); 1144*4c87aefeSPatrick Mooney 1145*4c87aefeSPatrick Mooney dev_ctx = dev->dev_ctx; 1146*4c87aefeSPatrick Mooney assert(dev_ctx != NULL); 1147*4c87aefeSPatrick Mooney 1148*4c87aefeSPatrick Mooney ep_ctx = &dev_ctx->ctx_ep[epid]; 1149*4c87aefeSPatrick Mooney 1150*4c87aefeSPatrick Mooney ep_ctx->dwEpCtx0 = (ep_ctx->dwEpCtx0 & ~0x7) | XHCI_ST_EPCTX_STOPPED; 1151*4c87aefeSPatrick Mooney 1152*4c87aefeSPatrick Mooney if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) == 0) 1153*4c87aefeSPatrick Mooney ep_ctx->qwEpCtx2 = devep->ep_ringaddr | devep->ep_ccs; 1154*4c87aefeSPatrick Mooney 1155*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: reset ep[%u] %08x %08x %016lx %08x\r\n", 1156*4c87aefeSPatrick Mooney epid, ep_ctx->dwEpCtx0, ep_ctx->dwEpCtx1, ep_ctx->qwEpCtx2, 1157*4c87aefeSPatrick Mooney ep_ctx->dwEpCtx4)); 1158*4c87aefeSPatrick Mooney 1159*4c87aefeSPatrick Mooney if (type == XHCI_TRB_TYPE_RESET_EP && 1160*4c87aefeSPatrick Mooney (dev->dev_ue->ue_reset == NULL || 1161*4c87aefeSPatrick Mooney dev->dev_ue->ue_reset(dev->dev_sc) < 0)) { 1162*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_ENDP_NOT_ON; 1163*4c87aefeSPatrick Mooney goto done; 1164*4c87aefeSPatrick Mooney } 1165*4c87aefeSPatrick Mooney 1166*4c87aefeSPatrick Mooney done: 1167*4c87aefeSPatrick Mooney return (cmderr); 1168*4c87aefeSPatrick Mooney } 1169*4c87aefeSPatrick Mooney 1170*4c87aefeSPatrick Mooney 1171*4c87aefeSPatrick Mooney static uint32_t 1172*4c87aefeSPatrick Mooney pci_xhci_find_stream(struct pci_xhci_softc *sc, struct xhci_endp_ctx *ep, 1173*4c87aefeSPatrick Mooney uint32_t streamid, struct xhci_stream_ctx **osctx) 1174*4c87aefeSPatrick Mooney { 1175*4c87aefeSPatrick Mooney struct xhci_stream_ctx *sctx; 1176*4c87aefeSPatrick Mooney uint32_t maxpstreams; 1177*4c87aefeSPatrick Mooney 1178*4c87aefeSPatrick Mooney maxpstreams = XHCI_EPCTX_0_MAXP_STREAMS_GET(ep->dwEpCtx0); 1179*4c87aefeSPatrick Mooney if (maxpstreams == 0) 1180*4c87aefeSPatrick Mooney return (XHCI_TRB_ERROR_TRB); 1181*4c87aefeSPatrick Mooney 1182*4c87aefeSPatrick Mooney if (maxpstreams > XHCI_STREAMS_MAX) 1183*4c87aefeSPatrick Mooney return (XHCI_TRB_ERROR_INVALID_SID); 1184*4c87aefeSPatrick Mooney 1185*4c87aefeSPatrick Mooney if (XHCI_EPCTX_0_LSA_GET(ep->dwEpCtx0) == 0) { 1186*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: find_stream; LSA bit not set\r\n")); 1187*4c87aefeSPatrick Mooney return (XHCI_TRB_ERROR_INVALID_SID); 1188*4c87aefeSPatrick Mooney } 1189*4c87aefeSPatrick Mooney 1190*4c87aefeSPatrick Mooney /* only support primary stream */ 1191*4c87aefeSPatrick Mooney if (streamid > maxpstreams) 1192*4c87aefeSPatrick Mooney return (XHCI_TRB_ERROR_STREAM_TYPE); 1193*4c87aefeSPatrick Mooney 1194*4c87aefeSPatrick Mooney sctx = XHCI_GADDR(sc, ep->qwEpCtx2 & ~0xFUL) + streamid; 1195*4c87aefeSPatrick Mooney if (!XHCI_SCTX_0_SCT_GET(sctx->qwSctx0)) 1196*4c87aefeSPatrick Mooney return (XHCI_TRB_ERROR_STREAM_TYPE); 1197*4c87aefeSPatrick Mooney 1198*4c87aefeSPatrick Mooney *osctx = sctx; 1199*4c87aefeSPatrick Mooney 1200*4c87aefeSPatrick Mooney return (XHCI_TRB_ERROR_SUCCESS); 1201*4c87aefeSPatrick Mooney } 1202*4c87aefeSPatrick Mooney 1203*4c87aefeSPatrick Mooney 1204*4c87aefeSPatrick Mooney static uint32_t 1205*4c87aefeSPatrick Mooney pci_xhci_cmd_set_tr(struct pci_xhci_softc *sc, uint32_t slot, 1206*4c87aefeSPatrick Mooney struct xhci_trb *trb) 1207*4c87aefeSPatrick Mooney { 1208*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev; 1209*4c87aefeSPatrick Mooney struct pci_xhci_dev_ep *devep; 1210*4c87aefeSPatrick Mooney struct xhci_dev_ctx *dev_ctx; 1211*4c87aefeSPatrick Mooney struct xhci_endp_ctx *ep_ctx; 1212*4c87aefeSPatrick Mooney uint32_t cmderr, epid; 1213*4c87aefeSPatrick Mooney uint32_t streamid; 1214*4c87aefeSPatrick Mooney 1215*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_SUCCESS; 1216*4c87aefeSPatrick Mooney 1217*4c87aefeSPatrick Mooney dev = XHCI_SLOTDEV_PTR(sc, slot); 1218*4c87aefeSPatrick Mooney assert(dev != NULL); 1219*4c87aefeSPatrick Mooney 1220*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci set_tr: new-tr x%016lx, SCT %u DCS %u\r\n" 1221*4c87aefeSPatrick Mooney " stream-id %u, slot %u, epid %u, C %u\r\n", 1222*4c87aefeSPatrick Mooney (trb->qwTrb0 & ~0xF), (uint32_t)((trb->qwTrb0 >> 1) & 0x7), 1223*4c87aefeSPatrick Mooney (uint32_t)(trb->qwTrb0 & 0x1), (trb->dwTrb2 >> 16) & 0xFFFF, 1224*4c87aefeSPatrick Mooney XHCI_TRB_3_SLOT_GET(trb->dwTrb3), 1225*4c87aefeSPatrick Mooney XHCI_TRB_3_EP_GET(trb->dwTrb3), trb->dwTrb3 & 0x1)); 1226*4c87aefeSPatrick Mooney 1227*4c87aefeSPatrick Mooney epid = XHCI_TRB_3_EP_GET(trb->dwTrb3); 1228*4c87aefeSPatrick Mooney if (epid < 1 || epid > 31) { 1229*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: set_tr_deq: invalid epid %u\r\n", epid)); 1230*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_TRB; 1231*4c87aefeSPatrick Mooney goto done; 1232*4c87aefeSPatrick Mooney } 1233*4c87aefeSPatrick Mooney 1234*4c87aefeSPatrick Mooney dev_ctx = dev->dev_ctx; 1235*4c87aefeSPatrick Mooney assert(dev_ctx != NULL); 1236*4c87aefeSPatrick Mooney 1237*4c87aefeSPatrick Mooney ep_ctx = &dev_ctx->ctx_ep[epid]; 1238*4c87aefeSPatrick Mooney devep = &dev->eps[epid]; 1239*4c87aefeSPatrick Mooney 1240*4c87aefeSPatrick Mooney switch (XHCI_EPCTX_0_EPSTATE_GET(ep_ctx->dwEpCtx0)) { 1241*4c87aefeSPatrick Mooney case XHCI_ST_EPCTX_STOPPED: 1242*4c87aefeSPatrick Mooney case XHCI_ST_EPCTX_ERROR: 1243*4c87aefeSPatrick Mooney break; 1244*4c87aefeSPatrick Mooney default: 1245*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci cmd set_tr invalid state %x\r\n", 1246*4c87aefeSPatrick Mooney XHCI_EPCTX_0_EPSTATE_GET(ep_ctx->dwEpCtx0))); 1247*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_CONTEXT_STATE; 1248*4c87aefeSPatrick Mooney goto done; 1249*4c87aefeSPatrick Mooney } 1250*4c87aefeSPatrick Mooney 1251*4c87aefeSPatrick Mooney streamid = XHCI_TRB_2_STREAM_GET(trb->dwTrb2); 1252*4c87aefeSPatrick Mooney if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) > 0) { 1253*4c87aefeSPatrick Mooney struct xhci_stream_ctx *sctx; 1254*4c87aefeSPatrick Mooney 1255*4c87aefeSPatrick Mooney sctx = NULL; 1256*4c87aefeSPatrick Mooney cmderr = pci_xhci_find_stream(sc, ep_ctx, streamid, &sctx); 1257*4c87aefeSPatrick Mooney if (sctx != NULL) { 1258*4c87aefeSPatrick Mooney assert(devep->ep_sctx != NULL); 1259*4c87aefeSPatrick Mooney 1260*4c87aefeSPatrick Mooney devep->ep_sctx[streamid].qwSctx0 = trb->qwTrb0; 1261*4c87aefeSPatrick Mooney devep->ep_sctx_trbs[streamid].ringaddr = 1262*4c87aefeSPatrick Mooney trb->qwTrb0 & ~0xF; 1263*4c87aefeSPatrick Mooney devep->ep_sctx_trbs[streamid].ccs = 1264*4c87aefeSPatrick Mooney XHCI_EPCTX_2_DCS_GET(trb->qwTrb0); 1265*4c87aefeSPatrick Mooney } 1266*4c87aefeSPatrick Mooney } else { 1267*4c87aefeSPatrick Mooney if (streamid != 0) { 1268*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci cmd set_tr streamid %x != 0\r\n", 1269*4c87aefeSPatrick Mooney streamid)); 1270*4c87aefeSPatrick Mooney } 1271*4c87aefeSPatrick Mooney ep_ctx->qwEpCtx2 = trb->qwTrb0 & ~0xFUL; 1272*4c87aefeSPatrick Mooney devep->ep_ringaddr = ep_ctx->qwEpCtx2 & ~0xFUL; 1273*4c87aefeSPatrick Mooney devep->ep_ccs = trb->qwTrb0 & 0x1; 1274*4c87aefeSPatrick Mooney devep->ep_tr = XHCI_GADDR(sc, devep->ep_ringaddr); 1275*4c87aefeSPatrick Mooney 1276*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci set_tr first TRB:\r\n")); 1277*4c87aefeSPatrick Mooney pci_xhci_dump_trb(devep->ep_tr); 1278*4c87aefeSPatrick Mooney } 1279*4c87aefeSPatrick Mooney ep_ctx->dwEpCtx0 = (ep_ctx->dwEpCtx0 & ~0x7) | XHCI_ST_EPCTX_STOPPED; 1280*4c87aefeSPatrick Mooney 1281*4c87aefeSPatrick Mooney done: 1282*4c87aefeSPatrick Mooney return (cmderr); 1283*4c87aefeSPatrick Mooney } 1284*4c87aefeSPatrick Mooney 1285*4c87aefeSPatrick Mooney static uint32_t 1286*4c87aefeSPatrick Mooney pci_xhci_cmd_eval_ctx(struct pci_xhci_softc *sc, uint32_t slot, 1287*4c87aefeSPatrick Mooney struct xhci_trb *trb) 1288*4c87aefeSPatrick Mooney { 1289*4c87aefeSPatrick Mooney struct xhci_input_dev_ctx *input_ctx; 1290*4c87aefeSPatrick Mooney struct xhci_slot_ctx *islot_ctx; 1291*4c87aefeSPatrick Mooney struct xhci_dev_ctx *dev_ctx; 1292*4c87aefeSPatrick Mooney struct xhci_endp_ctx *ep0_ctx; 1293*4c87aefeSPatrick Mooney uint32_t cmderr; 1294*4c87aefeSPatrick Mooney 1295*4c87aefeSPatrick Mooney input_ctx = XHCI_GADDR(sc, trb->qwTrb0 & ~0xFUL); 1296*4c87aefeSPatrick Mooney islot_ctx = &input_ctx->ctx_slot; 1297*4c87aefeSPatrick Mooney ep0_ctx = &input_ctx->ctx_ep[1]; 1298*4c87aefeSPatrick Mooney 1299*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_SUCCESS; 1300*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: eval ctx, input ctl: D 0x%08x A 0x%08x,\r\n" 1301*4c87aefeSPatrick Mooney " slot %08x %08x %08x %08x\r\n" 1302*4c87aefeSPatrick Mooney " ep0 %08x %08x %016lx %08x\r\n", 1303*4c87aefeSPatrick Mooney input_ctx->ctx_input.dwInCtx0, input_ctx->ctx_input.dwInCtx1, 1304*4c87aefeSPatrick Mooney islot_ctx->dwSctx0, islot_ctx->dwSctx1, 1305*4c87aefeSPatrick Mooney islot_ctx->dwSctx2, islot_ctx->dwSctx3, 1306*4c87aefeSPatrick Mooney ep0_ctx->dwEpCtx0, ep0_ctx->dwEpCtx1, ep0_ctx->qwEpCtx2, 1307*4c87aefeSPatrick Mooney ep0_ctx->dwEpCtx4)); 1308*4c87aefeSPatrick Mooney 1309*4c87aefeSPatrick Mooney /* this command expects drop-ctx=0 & add-ctx=slot+ep0 */ 1310*4c87aefeSPatrick Mooney if ((input_ctx->ctx_input.dwInCtx0 != 0) || 1311*4c87aefeSPatrick Mooney (input_ctx->ctx_input.dwInCtx1 & 0x03) == 0) { 1312*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: eval ctx, input ctl invalid\r\n")); 1313*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_TRB; 1314*4c87aefeSPatrick Mooney goto done; 1315*4c87aefeSPatrick Mooney } 1316*4c87aefeSPatrick Mooney 1317*4c87aefeSPatrick Mooney /* assign address to slot; in this emulation, slot_id = address */ 1318*4c87aefeSPatrick Mooney dev_ctx = pci_xhci_get_dev_ctx(sc, slot); 1319*4c87aefeSPatrick Mooney 1320*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: eval ctx, dev ctx\r\n" 1321*4c87aefeSPatrick Mooney " slot %08x %08x %08x %08x\r\n", 1322*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx0, dev_ctx->ctx_slot.dwSctx1, 1323*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx2, dev_ctx->ctx_slot.dwSctx3)); 1324*4c87aefeSPatrick Mooney 1325*4c87aefeSPatrick Mooney if (input_ctx->ctx_input.dwInCtx1 & 0x01) { /* slot ctx */ 1326*4c87aefeSPatrick Mooney /* set max exit latency */ 1327*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx1 = FIELD_COPY( 1328*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx1, input_ctx->ctx_slot.dwSctx1, 1329*4c87aefeSPatrick Mooney 0xFFFF, 0); 1330*4c87aefeSPatrick Mooney 1331*4c87aefeSPatrick Mooney /* set interrupter target */ 1332*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx2 = FIELD_COPY( 1333*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx2, input_ctx->ctx_slot.dwSctx2, 1334*4c87aefeSPatrick Mooney 0x3FF, 22); 1335*4c87aefeSPatrick Mooney } 1336*4c87aefeSPatrick Mooney if (input_ctx->ctx_input.dwInCtx1 & 0x02) { /* control ctx */ 1337*4c87aefeSPatrick Mooney /* set max packet size */ 1338*4c87aefeSPatrick Mooney dev_ctx->ctx_ep[1].dwEpCtx1 = FIELD_COPY( 1339*4c87aefeSPatrick Mooney dev_ctx->ctx_ep[1].dwEpCtx1, ep0_ctx->dwEpCtx1, 1340*4c87aefeSPatrick Mooney 0xFFFF, 16); 1341*4c87aefeSPatrick Mooney 1342*4c87aefeSPatrick Mooney ep0_ctx = &dev_ctx->ctx_ep[1]; 1343*4c87aefeSPatrick Mooney } 1344*4c87aefeSPatrick Mooney 1345*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: eval ctx, output ctx\r\n" 1346*4c87aefeSPatrick Mooney " slot %08x %08x %08x %08x\r\n" 1347*4c87aefeSPatrick Mooney " ep0 %08x %08x %016lx %08x\r\n", 1348*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx0, dev_ctx->ctx_slot.dwSctx1, 1349*4c87aefeSPatrick Mooney dev_ctx->ctx_slot.dwSctx2, dev_ctx->ctx_slot.dwSctx3, 1350*4c87aefeSPatrick Mooney ep0_ctx->dwEpCtx0, ep0_ctx->dwEpCtx1, ep0_ctx->qwEpCtx2, 1351*4c87aefeSPatrick Mooney ep0_ctx->dwEpCtx4)); 1352*4c87aefeSPatrick Mooney 1353*4c87aefeSPatrick Mooney done: 1354*4c87aefeSPatrick Mooney return (cmderr); 1355*4c87aefeSPatrick Mooney } 1356*4c87aefeSPatrick Mooney 1357*4c87aefeSPatrick Mooney static int 1358*4c87aefeSPatrick Mooney pci_xhci_complete_commands(struct pci_xhci_softc *sc) 1359*4c87aefeSPatrick Mooney { 1360*4c87aefeSPatrick Mooney struct xhci_trb evtrb; 1361*4c87aefeSPatrick Mooney struct xhci_trb *trb; 1362*4c87aefeSPatrick Mooney uint64_t crcr; 1363*4c87aefeSPatrick Mooney uint32_t ccs; /* cycle state (XHCI 4.9.2) */ 1364*4c87aefeSPatrick Mooney uint32_t type; 1365*4c87aefeSPatrick Mooney uint32_t slot; 1366*4c87aefeSPatrick Mooney uint32_t cmderr; 1367*4c87aefeSPatrick Mooney int error; 1368*4c87aefeSPatrick Mooney 1369*4c87aefeSPatrick Mooney error = 0; 1370*4c87aefeSPatrick Mooney sc->opregs.crcr |= XHCI_CRCR_LO_CRR; 1371*4c87aefeSPatrick Mooney 1372*4c87aefeSPatrick Mooney trb = sc->opregs.cr_p; 1373*4c87aefeSPatrick Mooney ccs = sc->opregs.crcr & XHCI_CRCR_LO_RCS; 1374*4c87aefeSPatrick Mooney crcr = sc->opregs.crcr & ~0xF; 1375*4c87aefeSPatrick Mooney 1376*4c87aefeSPatrick Mooney while (1) { 1377*4c87aefeSPatrick Mooney sc->opregs.cr_p = trb; 1378*4c87aefeSPatrick Mooney 1379*4c87aefeSPatrick Mooney type = XHCI_TRB_3_TYPE_GET(trb->dwTrb3); 1380*4c87aefeSPatrick Mooney 1381*4c87aefeSPatrick Mooney if ((trb->dwTrb3 & XHCI_TRB_3_CYCLE_BIT) != 1382*4c87aefeSPatrick Mooney (ccs & XHCI_TRB_3_CYCLE_BIT)) 1383*4c87aefeSPatrick Mooney break; 1384*4c87aefeSPatrick Mooney 1385*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: cmd type 0x%x, Trb0 x%016lx dwTrb2 x%08x" 1386*4c87aefeSPatrick Mooney " dwTrb3 x%08x, TRB_CYCLE %u/ccs %u\r\n", 1387*4c87aefeSPatrick Mooney type, trb->qwTrb0, trb->dwTrb2, trb->dwTrb3, 1388*4c87aefeSPatrick Mooney trb->dwTrb3 & XHCI_TRB_3_CYCLE_BIT, ccs)); 1389*4c87aefeSPatrick Mooney 1390*4c87aefeSPatrick Mooney cmderr = XHCI_TRB_ERROR_SUCCESS; 1391*4c87aefeSPatrick Mooney evtrb.dwTrb2 = 0; 1392*4c87aefeSPatrick Mooney evtrb.dwTrb3 = (ccs & XHCI_TRB_3_CYCLE_BIT) | 1393*4c87aefeSPatrick Mooney XHCI_TRB_3_TYPE_SET(XHCI_TRB_EVENT_CMD_COMPLETE); 1394*4c87aefeSPatrick Mooney slot = 0; 1395*4c87aefeSPatrick Mooney 1396*4c87aefeSPatrick Mooney switch (type) { 1397*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_LINK: /* 0x06 */ 1398*4c87aefeSPatrick Mooney if (trb->dwTrb3 & XHCI_TRB_3_TC_BIT) 1399*4c87aefeSPatrick Mooney ccs ^= XHCI_CRCR_LO_RCS; 1400*4c87aefeSPatrick Mooney break; 1401*4c87aefeSPatrick Mooney 1402*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_ENABLE_SLOT: /* 0x09 */ 1403*4c87aefeSPatrick Mooney cmderr = pci_xhci_cmd_enable_slot(sc, &slot); 1404*4c87aefeSPatrick Mooney break; 1405*4c87aefeSPatrick Mooney 1406*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_DISABLE_SLOT: /* 0x0A */ 1407*4c87aefeSPatrick Mooney slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); 1408*4c87aefeSPatrick Mooney cmderr = pci_xhci_cmd_disable_slot(sc, slot); 1409*4c87aefeSPatrick Mooney break; 1410*4c87aefeSPatrick Mooney 1411*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_ADDRESS_DEVICE: /* 0x0B */ 1412*4c87aefeSPatrick Mooney slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); 1413*4c87aefeSPatrick Mooney cmderr = pci_xhci_cmd_address_device(sc, slot, trb); 1414*4c87aefeSPatrick Mooney break; 1415*4c87aefeSPatrick Mooney 1416*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_CONFIGURE_EP: /* 0x0C */ 1417*4c87aefeSPatrick Mooney slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); 1418*4c87aefeSPatrick Mooney cmderr = pci_xhci_cmd_config_ep(sc, slot, trb); 1419*4c87aefeSPatrick Mooney break; 1420*4c87aefeSPatrick Mooney 1421*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_EVALUATE_CTX: /* 0x0D */ 1422*4c87aefeSPatrick Mooney slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); 1423*4c87aefeSPatrick Mooney cmderr = pci_xhci_cmd_eval_ctx(sc, slot, trb); 1424*4c87aefeSPatrick Mooney break; 1425*4c87aefeSPatrick Mooney 1426*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_RESET_EP: /* 0x0E */ 1427*4c87aefeSPatrick Mooney DPRINTF(("Reset Endpoint on slot %d\r\n", slot)); 1428*4c87aefeSPatrick Mooney slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); 1429*4c87aefeSPatrick Mooney cmderr = pci_xhci_cmd_reset_ep(sc, slot, trb); 1430*4c87aefeSPatrick Mooney break; 1431*4c87aefeSPatrick Mooney 1432*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_STOP_EP: /* 0x0F */ 1433*4c87aefeSPatrick Mooney DPRINTF(("Stop Endpoint on slot %d\r\n", slot)); 1434*4c87aefeSPatrick Mooney slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); 1435*4c87aefeSPatrick Mooney cmderr = pci_xhci_cmd_reset_ep(sc, slot, trb); 1436*4c87aefeSPatrick Mooney break; 1437*4c87aefeSPatrick Mooney 1438*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_SET_TR_DEQUEUE: /* 0x10 */ 1439*4c87aefeSPatrick Mooney slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); 1440*4c87aefeSPatrick Mooney cmderr = pci_xhci_cmd_set_tr(sc, slot, trb); 1441*4c87aefeSPatrick Mooney break; 1442*4c87aefeSPatrick Mooney 1443*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_RESET_DEVICE: /* 0x11 */ 1444*4c87aefeSPatrick Mooney slot = XHCI_TRB_3_SLOT_GET(trb->dwTrb3); 1445*4c87aefeSPatrick Mooney cmderr = pci_xhci_cmd_reset_device(sc, slot); 1446*4c87aefeSPatrick Mooney break; 1447*4c87aefeSPatrick Mooney 1448*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_FORCE_EVENT: /* 0x12 */ 1449*4c87aefeSPatrick Mooney /* TODO: */ 1450*4c87aefeSPatrick Mooney break; 1451*4c87aefeSPatrick Mooney 1452*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_NEGOTIATE_BW: /* 0x13 */ 1453*4c87aefeSPatrick Mooney break; 1454*4c87aefeSPatrick Mooney 1455*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_SET_LATENCY_TOL: /* 0x14 */ 1456*4c87aefeSPatrick Mooney break; 1457*4c87aefeSPatrick Mooney 1458*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_GET_PORT_BW: /* 0x15 */ 1459*4c87aefeSPatrick Mooney break; 1460*4c87aefeSPatrick Mooney 1461*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_FORCE_HEADER: /* 0x16 */ 1462*4c87aefeSPatrick Mooney break; 1463*4c87aefeSPatrick Mooney 1464*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_NOOP_CMD: /* 0x17 */ 1465*4c87aefeSPatrick Mooney break; 1466*4c87aefeSPatrick Mooney 1467*4c87aefeSPatrick Mooney default: 1468*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: unsupported cmd %x\r\n", type)); 1469*4c87aefeSPatrick Mooney break; 1470*4c87aefeSPatrick Mooney } 1471*4c87aefeSPatrick Mooney 1472*4c87aefeSPatrick Mooney if (type != XHCI_TRB_TYPE_LINK) { 1473*4c87aefeSPatrick Mooney /* 1474*4c87aefeSPatrick Mooney * insert command completion event and assert intr 1475*4c87aefeSPatrick Mooney */ 1476*4c87aefeSPatrick Mooney evtrb.qwTrb0 = crcr; 1477*4c87aefeSPatrick Mooney evtrb.dwTrb2 |= XHCI_TRB_2_ERROR_SET(cmderr); 1478*4c87aefeSPatrick Mooney evtrb.dwTrb3 |= XHCI_TRB_3_SLOT_SET(slot); 1479*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: command 0x%x result: 0x%x\r\n", 1480*4c87aefeSPatrick Mooney type, cmderr)); 1481*4c87aefeSPatrick Mooney pci_xhci_insert_event(sc, &evtrb, 1); 1482*4c87aefeSPatrick Mooney } 1483*4c87aefeSPatrick Mooney 1484*4c87aefeSPatrick Mooney trb = pci_xhci_trb_next(sc, trb, &crcr); 1485*4c87aefeSPatrick Mooney } 1486*4c87aefeSPatrick Mooney 1487*4c87aefeSPatrick Mooney sc->opregs.crcr = crcr | (sc->opregs.crcr & XHCI_CRCR_LO_CA) | ccs; 1488*4c87aefeSPatrick Mooney sc->opregs.crcr &= ~XHCI_CRCR_LO_CRR; 1489*4c87aefeSPatrick Mooney return (error); 1490*4c87aefeSPatrick Mooney } 1491*4c87aefeSPatrick Mooney 1492*4c87aefeSPatrick Mooney static void 1493*4c87aefeSPatrick Mooney pci_xhci_dump_trb(struct xhci_trb *trb) 1494*4c87aefeSPatrick Mooney { 1495*4c87aefeSPatrick Mooney static const char *trbtypes[] = { 1496*4c87aefeSPatrick Mooney "RESERVED", 1497*4c87aefeSPatrick Mooney "NORMAL", 1498*4c87aefeSPatrick Mooney "SETUP_STAGE", 1499*4c87aefeSPatrick Mooney "DATA_STAGE", 1500*4c87aefeSPatrick Mooney "STATUS_STAGE", 1501*4c87aefeSPatrick Mooney "ISOCH", 1502*4c87aefeSPatrick Mooney "LINK", 1503*4c87aefeSPatrick Mooney "EVENT_DATA", 1504*4c87aefeSPatrick Mooney "NOOP", 1505*4c87aefeSPatrick Mooney "ENABLE_SLOT", 1506*4c87aefeSPatrick Mooney "DISABLE_SLOT", 1507*4c87aefeSPatrick Mooney "ADDRESS_DEVICE", 1508*4c87aefeSPatrick Mooney "CONFIGURE_EP", 1509*4c87aefeSPatrick Mooney "EVALUATE_CTX", 1510*4c87aefeSPatrick Mooney "RESET_EP", 1511*4c87aefeSPatrick Mooney "STOP_EP", 1512*4c87aefeSPatrick Mooney "SET_TR_DEQUEUE", 1513*4c87aefeSPatrick Mooney "RESET_DEVICE", 1514*4c87aefeSPatrick Mooney "FORCE_EVENT", 1515*4c87aefeSPatrick Mooney "NEGOTIATE_BW", 1516*4c87aefeSPatrick Mooney "SET_LATENCY_TOL", 1517*4c87aefeSPatrick Mooney "GET_PORT_BW", 1518*4c87aefeSPatrick Mooney "FORCE_HEADER", 1519*4c87aefeSPatrick Mooney "NOOP_CMD" 1520*4c87aefeSPatrick Mooney }; 1521*4c87aefeSPatrick Mooney uint32_t type; 1522*4c87aefeSPatrick Mooney 1523*4c87aefeSPatrick Mooney type = XHCI_TRB_3_TYPE_GET(trb->dwTrb3); 1524*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: trb[@%p] type x%02x %s 0:x%016lx 2:x%08x 3:x%08x\r\n", 1525*4c87aefeSPatrick Mooney trb, type, 1526*4c87aefeSPatrick Mooney type <= XHCI_TRB_TYPE_NOOP_CMD ? trbtypes[type] : "INVALID", 1527*4c87aefeSPatrick Mooney trb->qwTrb0, trb->dwTrb2, trb->dwTrb3)); 1528*4c87aefeSPatrick Mooney } 1529*4c87aefeSPatrick Mooney 1530*4c87aefeSPatrick Mooney static int 1531*4c87aefeSPatrick Mooney pci_xhci_xfer_complete(struct pci_xhci_softc *sc, struct usb_data_xfer *xfer, 1532*4c87aefeSPatrick Mooney uint32_t slot, uint32_t epid, int *do_intr) 1533*4c87aefeSPatrick Mooney { 1534*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev; 1535*4c87aefeSPatrick Mooney struct pci_xhci_dev_ep *devep; 1536*4c87aefeSPatrick Mooney struct xhci_dev_ctx *dev_ctx; 1537*4c87aefeSPatrick Mooney struct xhci_endp_ctx *ep_ctx; 1538*4c87aefeSPatrick Mooney struct xhci_trb *trb; 1539*4c87aefeSPatrick Mooney struct xhci_trb evtrb; 1540*4c87aefeSPatrick Mooney uint32_t trbflags; 1541*4c87aefeSPatrick Mooney uint32_t edtla; 1542*4c87aefeSPatrick Mooney int i, err; 1543*4c87aefeSPatrick Mooney 1544*4c87aefeSPatrick Mooney dev = XHCI_SLOTDEV_PTR(sc, slot); 1545*4c87aefeSPatrick Mooney devep = &dev->eps[epid]; 1546*4c87aefeSPatrick Mooney dev_ctx = pci_xhci_get_dev_ctx(sc, slot); 1547*4c87aefeSPatrick Mooney 1548*4c87aefeSPatrick Mooney assert(dev_ctx != NULL); 1549*4c87aefeSPatrick Mooney 1550*4c87aefeSPatrick Mooney ep_ctx = &dev_ctx->ctx_ep[epid]; 1551*4c87aefeSPatrick Mooney 1552*4c87aefeSPatrick Mooney err = XHCI_TRB_ERROR_SUCCESS; 1553*4c87aefeSPatrick Mooney *do_intr = 0; 1554*4c87aefeSPatrick Mooney edtla = 0; 1555*4c87aefeSPatrick Mooney 1556*4c87aefeSPatrick Mooney /* go through list of TRBs and insert event(s) */ 1557*4c87aefeSPatrick Mooney for (i = xfer->head; xfer->ndata > 0; ) { 1558*4c87aefeSPatrick Mooney evtrb.qwTrb0 = (uint64_t)xfer->data[i].hci_data; 1559*4c87aefeSPatrick Mooney trb = XHCI_GADDR(sc, evtrb.qwTrb0); 1560*4c87aefeSPatrick Mooney trbflags = trb->dwTrb3; 1561*4c87aefeSPatrick Mooney 1562*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: xfer[%d] done?%u:%d trb %x %016lx %x " 1563*4c87aefeSPatrick Mooney "(err %d) IOC?%d\r\n", 1564*4c87aefeSPatrick Mooney i, xfer->data[i].processed, xfer->data[i].blen, 1565*4c87aefeSPatrick Mooney XHCI_TRB_3_TYPE_GET(trbflags), evtrb.qwTrb0, 1566*4c87aefeSPatrick Mooney trbflags, err, 1567*4c87aefeSPatrick Mooney trb->dwTrb3 & XHCI_TRB_3_IOC_BIT ? 1 : 0)); 1568*4c87aefeSPatrick Mooney 1569*4c87aefeSPatrick Mooney if (!xfer->data[i].processed) { 1570*4c87aefeSPatrick Mooney xfer->head = i; 1571*4c87aefeSPatrick Mooney break; 1572*4c87aefeSPatrick Mooney } 1573*4c87aefeSPatrick Mooney 1574*4c87aefeSPatrick Mooney xfer->ndata--; 1575*4c87aefeSPatrick Mooney edtla += xfer->data[i].bdone; 1576*4c87aefeSPatrick Mooney 1577*4c87aefeSPatrick Mooney trb->dwTrb3 = (trb->dwTrb3 & ~0x1) | (xfer->data[i].ccs); 1578*4c87aefeSPatrick Mooney 1579*4c87aefeSPatrick Mooney pci_xhci_update_ep_ring(sc, dev, devep, ep_ctx, 1580*4c87aefeSPatrick Mooney xfer->data[i].streamid, xfer->data[i].trbnext, 1581*4c87aefeSPatrick Mooney xfer->data[i].ccs); 1582*4c87aefeSPatrick Mooney 1583*4c87aefeSPatrick Mooney /* Only interrupt if IOC or short packet */ 1584*4c87aefeSPatrick Mooney if (!(trb->dwTrb3 & XHCI_TRB_3_IOC_BIT) && 1585*4c87aefeSPatrick Mooney !((err == XHCI_TRB_ERROR_SHORT_PKT) && 1586*4c87aefeSPatrick Mooney (trb->dwTrb3 & XHCI_TRB_3_ISP_BIT))) { 1587*4c87aefeSPatrick Mooney 1588*4c87aefeSPatrick Mooney i = (i + 1) % USB_MAX_XFER_BLOCKS; 1589*4c87aefeSPatrick Mooney continue; 1590*4c87aefeSPatrick Mooney } 1591*4c87aefeSPatrick Mooney 1592*4c87aefeSPatrick Mooney evtrb.dwTrb2 = XHCI_TRB_2_ERROR_SET(err) | 1593*4c87aefeSPatrick Mooney XHCI_TRB_2_REM_SET(xfer->data[i].blen); 1594*4c87aefeSPatrick Mooney 1595*4c87aefeSPatrick Mooney evtrb.dwTrb3 = XHCI_TRB_3_TYPE_SET(XHCI_TRB_EVENT_TRANSFER) | 1596*4c87aefeSPatrick Mooney XHCI_TRB_3_SLOT_SET(slot) | XHCI_TRB_3_EP_SET(epid); 1597*4c87aefeSPatrick Mooney 1598*4c87aefeSPatrick Mooney if (XHCI_TRB_3_TYPE_GET(trbflags) == XHCI_TRB_TYPE_EVENT_DATA) { 1599*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci EVENT_DATA edtla %u\r\n", edtla)); 1600*4c87aefeSPatrick Mooney evtrb.qwTrb0 = trb->qwTrb0; 1601*4c87aefeSPatrick Mooney evtrb.dwTrb2 = (edtla & 0xFFFFF) | 1602*4c87aefeSPatrick Mooney XHCI_TRB_2_ERROR_SET(err); 1603*4c87aefeSPatrick Mooney evtrb.dwTrb3 |= XHCI_TRB_3_ED_BIT; 1604*4c87aefeSPatrick Mooney edtla = 0; 1605*4c87aefeSPatrick Mooney } 1606*4c87aefeSPatrick Mooney 1607*4c87aefeSPatrick Mooney *do_intr = 1; 1608*4c87aefeSPatrick Mooney 1609*4c87aefeSPatrick Mooney err = pci_xhci_insert_event(sc, &evtrb, 0); 1610*4c87aefeSPatrick Mooney if (err != XHCI_TRB_ERROR_SUCCESS) { 1611*4c87aefeSPatrick Mooney break; 1612*4c87aefeSPatrick Mooney } 1613*4c87aefeSPatrick Mooney 1614*4c87aefeSPatrick Mooney i = (i + 1) % USB_MAX_XFER_BLOCKS; 1615*4c87aefeSPatrick Mooney } 1616*4c87aefeSPatrick Mooney 1617*4c87aefeSPatrick Mooney return (err); 1618*4c87aefeSPatrick Mooney } 1619*4c87aefeSPatrick Mooney 1620*4c87aefeSPatrick Mooney static void 1621*4c87aefeSPatrick Mooney pci_xhci_update_ep_ring(struct pci_xhci_softc *sc, struct pci_xhci_dev_emu *dev, 1622*4c87aefeSPatrick Mooney struct pci_xhci_dev_ep *devep, struct xhci_endp_ctx *ep_ctx, 1623*4c87aefeSPatrick Mooney uint32_t streamid, uint64_t ringaddr, int ccs) 1624*4c87aefeSPatrick Mooney { 1625*4c87aefeSPatrick Mooney 1626*4c87aefeSPatrick Mooney if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) != 0) { 1627*4c87aefeSPatrick Mooney devep->ep_sctx[streamid].qwSctx0 = (ringaddr & ~0xFUL) | 1628*4c87aefeSPatrick Mooney (ccs & 0x1); 1629*4c87aefeSPatrick Mooney 1630*4c87aefeSPatrick Mooney devep->ep_sctx_trbs[streamid].ringaddr = ringaddr & ~0xFUL; 1631*4c87aefeSPatrick Mooney devep->ep_sctx_trbs[streamid].ccs = ccs & 0x1; 1632*4c87aefeSPatrick Mooney ep_ctx->qwEpCtx2 = (ep_ctx->qwEpCtx2 & ~0x1) | (ccs & 0x1); 1633*4c87aefeSPatrick Mooney 1634*4c87aefeSPatrick Mooney DPRINTF(("xhci update ep-ring stream %d, addr %lx\r\n", 1635*4c87aefeSPatrick Mooney streamid, devep->ep_sctx[streamid].qwSctx0)); 1636*4c87aefeSPatrick Mooney } else { 1637*4c87aefeSPatrick Mooney devep->ep_ringaddr = ringaddr & ~0xFUL; 1638*4c87aefeSPatrick Mooney devep->ep_ccs = ccs & 0x1; 1639*4c87aefeSPatrick Mooney devep->ep_tr = XHCI_GADDR(sc, ringaddr & ~0xFUL); 1640*4c87aefeSPatrick Mooney ep_ctx->qwEpCtx2 = (ringaddr & ~0xFUL) | (ccs & 0x1); 1641*4c87aefeSPatrick Mooney 1642*4c87aefeSPatrick Mooney DPRINTF(("xhci update ep-ring, addr %lx\r\n", 1643*4c87aefeSPatrick Mooney (devep->ep_ringaddr | devep->ep_ccs))); 1644*4c87aefeSPatrick Mooney } 1645*4c87aefeSPatrick Mooney } 1646*4c87aefeSPatrick Mooney 1647*4c87aefeSPatrick Mooney /* 1648*4c87aefeSPatrick Mooney * Outstanding transfer still in progress (device NAK'd earlier) so retry 1649*4c87aefeSPatrick Mooney * the transfer again to see if it succeeds. 1650*4c87aefeSPatrick Mooney */ 1651*4c87aefeSPatrick Mooney static int 1652*4c87aefeSPatrick Mooney pci_xhci_try_usb_xfer(struct pci_xhci_softc *sc, 1653*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev, struct pci_xhci_dev_ep *devep, 1654*4c87aefeSPatrick Mooney struct xhci_endp_ctx *ep_ctx, uint32_t slot, uint32_t epid) 1655*4c87aefeSPatrick Mooney { 1656*4c87aefeSPatrick Mooney struct usb_data_xfer *xfer; 1657*4c87aefeSPatrick Mooney int err; 1658*4c87aefeSPatrick Mooney int do_intr; 1659*4c87aefeSPatrick Mooney 1660*4c87aefeSPatrick Mooney ep_ctx->dwEpCtx0 = FIELD_REPLACE( 1661*4c87aefeSPatrick Mooney ep_ctx->dwEpCtx0, XHCI_ST_EPCTX_RUNNING, 0x7, 0); 1662*4c87aefeSPatrick Mooney 1663*4c87aefeSPatrick Mooney err = 0; 1664*4c87aefeSPatrick Mooney do_intr = 0; 1665*4c87aefeSPatrick Mooney 1666*4c87aefeSPatrick Mooney xfer = devep->ep_xfer; 1667*4c87aefeSPatrick Mooney #ifdef __FreeBSD__ 1668*4c87aefeSPatrick Mooney USB_DATA_XFER_LOCK(xfer); 1669*4c87aefeSPatrick Mooney #else 1670*4c87aefeSPatrick Mooney /* 1671*4c87aefeSPatrick Mooney * At least one caller needs to hold this lock across the call to this 1672*4c87aefeSPatrick Mooney * function and other code. To avoid deadlock from a recursive mutex 1673*4c87aefeSPatrick Mooney * enter, we ensure that all callers hold this lock. 1674*4c87aefeSPatrick Mooney */ 1675*4c87aefeSPatrick Mooney assert(USB_DATA_XFER_LOCK_HELD(xfer)); 1676*4c87aefeSPatrick Mooney #endif 1677*4c87aefeSPatrick Mooney 1678*4c87aefeSPatrick Mooney /* outstanding requests queued up */ 1679*4c87aefeSPatrick Mooney if (dev->dev_ue->ue_data != NULL) { 1680*4c87aefeSPatrick Mooney err = dev->dev_ue->ue_data(dev->dev_sc, xfer, 1681*4c87aefeSPatrick Mooney epid & 0x1 ? USB_XFER_IN : USB_XFER_OUT, epid/2); 1682*4c87aefeSPatrick Mooney if (err == USB_ERR_CANCELLED) { 1683*4c87aefeSPatrick Mooney if (USB_DATA_GET_ERRCODE(&xfer->data[xfer->head]) == 1684*4c87aefeSPatrick Mooney USB_NAK) 1685*4c87aefeSPatrick Mooney err = XHCI_TRB_ERROR_SUCCESS; 1686*4c87aefeSPatrick Mooney } else { 1687*4c87aefeSPatrick Mooney err = pci_xhci_xfer_complete(sc, xfer, slot, epid, 1688*4c87aefeSPatrick Mooney &do_intr); 1689*4c87aefeSPatrick Mooney if (err == XHCI_TRB_ERROR_SUCCESS && do_intr) { 1690*4c87aefeSPatrick Mooney pci_xhci_assert_interrupt(sc); 1691*4c87aefeSPatrick Mooney } 1692*4c87aefeSPatrick Mooney 1693*4c87aefeSPatrick Mooney 1694*4c87aefeSPatrick Mooney /* XXX should not do it if error? */ 1695*4c87aefeSPatrick Mooney USB_DATA_XFER_RESET(xfer); 1696*4c87aefeSPatrick Mooney } 1697*4c87aefeSPatrick Mooney } 1698*4c87aefeSPatrick Mooney 1699*4c87aefeSPatrick Mooney #ifdef __FreeBSD__ 1700*4c87aefeSPatrick Mooney USB_DATA_XFER_UNLOCK(xfer); 1701*4c87aefeSPatrick Mooney #endif 1702*4c87aefeSPatrick Mooney 1703*4c87aefeSPatrick Mooney return (err); 1704*4c87aefeSPatrick Mooney } 1705*4c87aefeSPatrick Mooney 1706*4c87aefeSPatrick Mooney 1707*4c87aefeSPatrick Mooney static int 1708*4c87aefeSPatrick Mooney pci_xhci_handle_transfer(struct pci_xhci_softc *sc, 1709*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev, struct pci_xhci_dev_ep *devep, 1710*4c87aefeSPatrick Mooney struct xhci_endp_ctx *ep_ctx, struct xhci_trb *trb, uint32_t slot, 1711*4c87aefeSPatrick Mooney uint32_t epid, uint64_t addr, uint32_t ccs, uint32_t streamid) 1712*4c87aefeSPatrick Mooney { 1713*4c87aefeSPatrick Mooney struct xhci_trb *setup_trb; 1714*4c87aefeSPatrick Mooney struct usb_data_xfer *xfer; 1715*4c87aefeSPatrick Mooney struct usb_data_xfer_block *xfer_block; 1716*4c87aefeSPatrick Mooney uint64_t val; 1717*4c87aefeSPatrick Mooney uint32_t trbflags; 1718*4c87aefeSPatrick Mooney int do_intr, err; 1719*4c87aefeSPatrick Mooney int do_retry; 1720*4c87aefeSPatrick Mooney 1721*4c87aefeSPatrick Mooney ep_ctx->dwEpCtx0 = FIELD_REPLACE(ep_ctx->dwEpCtx0, 1722*4c87aefeSPatrick Mooney XHCI_ST_EPCTX_RUNNING, 0x7, 0); 1723*4c87aefeSPatrick Mooney 1724*4c87aefeSPatrick Mooney xfer = devep->ep_xfer; 1725*4c87aefeSPatrick Mooney USB_DATA_XFER_LOCK(xfer); 1726*4c87aefeSPatrick Mooney 1727*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci handle_transfer slot %u\r\n", slot)); 1728*4c87aefeSPatrick Mooney 1729*4c87aefeSPatrick Mooney retry: 1730*4c87aefeSPatrick Mooney err = 0; 1731*4c87aefeSPatrick Mooney do_retry = 0; 1732*4c87aefeSPatrick Mooney do_intr = 0; 1733*4c87aefeSPatrick Mooney setup_trb = NULL; 1734*4c87aefeSPatrick Mooney 1735*4c87aefeSPatrick Mooney while (1) { 1736*4c87aefeSPatrick Mooney pci_xhci_dump_trb(trb); 1737*4c87aefeSPatrick Mooney 1738*4c87aefeSPatrick Mooney trbflags = trb->dwTrb3; 1739*4c87aefeSPatrick Mooney 1740*4c87aefeSPatrick Mooney if (XHCI_TRB_3_TYPE_GET(trbflags) != XHCI_TRB_TYPE_LINK && 1741*4c87aefeSPatrick Mooney (trbflags & XHCI_TRB_3_CYCLE_BIT) != 1742*4c87aefeSPatrick Mooney (ccs & XHCI_TRB_3_CYCLE_BIT)) { 1743*4c87aefeSPatrick Mooney DPRINTF(("Cycle-bit changed trbflags %x, ccs %x\r\n", 1744*4c87aefeSPatrick Mooney trbflags & XHCI_TRB_3_CYCLE_BIT, ccs)); 1745*4c87aefeSPatrick Mooney break; 1746*4c87aefeSPatrick Mooney } 1747*4c87aefeSPatrick Mooney 1748*4c87aefeSPatrick Mooney xfer_block = NULL; 1749*4c87aefeSPatrick Mooney 1750*4c87aefeSPatrick Mooney switch (XHCI_TRB_3_TYPE_GET(trbflags)) { 1751*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_LINK: 1752*4c87aefeSPatrick Mooney if (trb->dwTrb3 & XHCI_TRB_3_TC_BIT) 1753*4c87aefeSPatrick Mooney ccs ^= 0x1; 1754*4c87aefeSPatrick Mooney 1755*4c87aefeSPatrick Mooney xfer_block = usb_data_xfer_append(xfer, NULL, 0, 1756*4c87aefeSPatrick Mooney (void *)addr, ccs); 1757*4c87aefeSPatrick Mooney xfer_block->processed = 1; 1758*4c87aefeSPatrick Mooney break; 1759*4c87aefeSPatrick Mooney 1760*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_SETUP_STAGE: 1761*4c87aefeSPatrick Mooney if ((trbflags & XHCI_TRB_3_IDT_BIT) == 0 || 1762*4c87aefeSPatrick Mooney XHCI_TRB_2_BYTES_GET(trb->dwTrb2) != 8) { 1763*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: invalid setup trb\r\n")); 1764*4c87aefeSPatrick Mooney err = XHCI_TRB_ERROR_TRB; 1765*4c87aefeSPatrick Mooney goto errout; 1766*4c87aefeSPatrick Mooney } 1767*4c87aefeSPatrick Mooney setup_trb = trb; 1768*4c87aefeSPatrick Mooney 1769*4c87aefeSPatrick Mooney val = trb->qwTrb0; 1770*4c87aefeSPatrick Mooney if (!xfer->ureq) 1771*4c87aefeSPatrick Mooney xfer->ureq = malloc( 1772*4c87aefeSPatrick Mooney sizeof(struct usb_device_request)); 1773*4c87aefeSPatrick Mooney memcpy(xfer->ureq, &val, 1774*4c87aefeSPatrick Mooney sizeof(struct usb_device_request)); 1775*4c87aefeSPatrick Mooney 1776*4c87aefeSPatrick Mooney xfer_block = usb_data_xfer_append(xfer, NULL, 0, 1777*4c87aefeSPatrick Mooney (void *)addr, ccs); 1778*4c87aefeSPatrick Mooney xfer_block->processed = 1; 1779*4c87aefeSPatrick Mooney break; 1780*4c87aefeSPatrick Mooney 1781*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_NORMAL: 1782*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_ISOCH: 1783*4c87aefeSPatrick Mooney if (setup_trb != NULL) { 1784*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: trb not supposed to be in " 1785*4c87aefeSPatrick Mooney "ctl scope\r\n")); 1786*4c87aefeSPatrick Mooney err = XHCI_TRB_ERROR_TRB; 1787*4c87aefeSPatrick Mooney goto errout; 1788*4c87aefeSPatrick Mooney } 1789*4c87aefeSPatrick Mooney /* fall through */ 1790*4c87aefeSPatrick Mooney 1791*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_DATA_STAGE: 1792*4c87aefeSPatrick Mooney xfer_block = usb_data_xfer_append(xfer, 1793*4c87aefeSPatrick Mooney (void *)(trbflags & XHCI_TRB_3_IDT_BIT ? 1794*4c87aefeSPatrick Mooney &trb->qwTrb0 : XHCI_GADDR(sc, trb->qwTrb0)), 1795*4c87aefeSPatrick Mooney trb->dwTrb2 & 0x1FFFF, (void *)addr, ccs); 1796*4c87aefeSPatrick Mooney break; 1797*4c87aefeSPatrick Mooney 1798*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_STATUS_STAGE: 1799*4c87aefeSPatrick Mooney xfer_block = usb_data_xfer_append(xfer, NULL, 0, 1800*4c87aefeSPatrick Mooney (void *)addr, ccs); 1801*4c87aefeSPatrick Mooney break; 1802*4c87aefeSPatrick Mooney 1803*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_NOOP: 1804*4c87aefeSPatrick Mooney xfer_block = usb_data_xfer_append(xfer, NULL, 0, 1805*4c87aefeSPatrick Mooney (void *)addr, ccs); 1806*4c87aefeSPatrick Mooney xfer_block->processed = 1; 1807*4c87aefeSPatrick Mooney break; 1808*4c87aefeSPatrick Mooney 1809*4c87aefeSPatrick Mooney case XHCI_TRB_TYPE_EVENT_DATA: 1810*4c87aefeSPatrick Mooney xfer_block = usb_data_xfer_append(xfer, NULL, 0, 1811*4c87aefeSPatrick Mooney (void *)addr, ccs); 1812*4c87aefeSPatrick Mooney if ((epid > 1) && (trbflags & XHCI_TRB_3_IOC_BIT)) { 1813*4c87aefeSPatrick Mooney xfer_block->processed = 1; 1814*4c87aefeSPatrick Mooney } 1815*4c87aefeSPatrick Mooney break; 1816*4c87aefeSPatrick Mooney 1817*4c87aefeSPatrick Mooney default: 1818*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: handle xfer unexpected trb type " 1819*4c87aefeSPatrick Mooney "0x%x\r\n", 1820*4c87aefeSPatrick Mooney XHCI_TRB_3_TYPE_GET(trbflags))); 1821*4c87aefeSPatrick Mooney err = XHCI_TRB_ERROR_TRB; 1822*4c87aefeSPatrick Mooney goto errout; 1823*4c87aefeSPatrick Mooney } 1824*4c87aefeSPatrick Mooney 1825*4c87aefeSPatrick Mooney trb = pci_xhci_trb_next(sc, trb, &addr); 1826*4c87aefeSPatrick Mooney 1827*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: next trb: 0x%lx\r\n", (uint64_t)trb)); 1828*4c87aefeSPatrick Mooney 1829*4c87aefeSPatrick Mooney if (xfer_block) { 1830*4c87aefeSPatrick Mooney xfer_block->trbnext = addr; 1831*4c87aefeSPatrick Mooney xfer_block->streamid = streamid; 1832*4c87aefeSPatrick Mooney } 1833*4c87aefeSPatrick Mooney 1834*4c87aefeSPatrick Mooney if (!setup_trb && !(trbflags & XHCI_TRB_3_CHAIN_BIT) && 1835*4c87aefeSPatrick Mooney XHCI_TRB_3_TYPE_GET(trbflags) != XHCI_TRB_TYPE_LINK) { 1836*4c87aefeSPatrick Mooney break; 1837*4c87aefeSPatrick Mooney } 1838*4c87aefeSPatrick Mooney 1839*4c87aefeSPatrick Mooney /* handle current batch that requires interrupt on complete */ 1840*4c87aefeSPatrick Mooney if (trbflags & XHCI_TRB_3_IOC_BIT) { 1841*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: trb IOC bit set\r\n")); 1842*4c87aefeSPatrick Mooney if (epid == 1) 1843*4c87aefeSPatrick Mooney do_retry = 1; 1844*4c87aefeSPatrick Mooney break; 1845*4c87aefeSPatrick Mooney } 1846*4c87aefeSPatrick Mooney } 1847*4c87aefeSPatrick Mooney 1848*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci[%d]: xfer->ndata %u\r\n", __LINE__, xfer->ndata)); 1849*4c87aefeSPatrick Mooney 1850*4c87aefeSPatrick Mooney if (epid == 1) { 1851*4c87aefeSPatrick Mooney err = USB_ERR_NOT_STARTED; 1852*4c87aefeSPatrick Mooney if (dev->dev_ue->ue_request != NULL) 1853*4c87aefeSPatrick Mooney err = dev->dev_ue->ue_request(dev->dev_sc, xfer); 1854*4c87aefeSPatrick Mooney setup_trb = NULL; 1855*4c87aefeSPatrick Mooney } else { 1856*4c87aefeSPatrick Mooney /* handle data transfer */ 1857*4c87aefeSPatrick Mooney pci_xhci_try_usb_xfer(sc, dev, devep, ep_ctx, slot, epid); 1858*4c87aefeSPatrick Mooney err = XHCI_TRB_ERROR_SUCCESS; 1859*4c87aefeSPatrick Mooney goto errout; 1860*4c87aefeSPatrick Mooney } 1861*4c87aefeSPatrick Mooney 1862*4c87aefeSPatrick Mooney err = USB_TO_XHCI_ERR(err); 1863*4c87aefeSPatrick Mooney if ((err == XHCI_TRB_ERROR_SUCCESS) || 1864*4c87aefeSPatrick Mooney (err == XHCI_TRB_ERROR_SHORT_PKT)) { 1865*4c87aefeSPatrick Mooney err = pci_xhci_xfer_complete(sc, xfer, slot, epid, &do_intr); 1866*4c87aefeSPatrick Mooney if (err != XHCI_TRB_ERROR_SUCCESS) 1867*4c87aefeSPatrick Mooney do_retry = 0; 1868*4c87aefeSPatrick Mooney } 1869*4c87aefeSPatrick Mooney 1870*4c87aefeSPatrick Mooney errout: 1871*4c87aefeSPatrick Mooney if (err == XHCI_TRB_ERROR_EV_RING_FULL) 1872*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci[%d]: event ring full\r\n", __LINE__)); 1873*4c87aefeSPatrick Mooney 1874*4c87aefeSPatrick Mooney if (!do_retry) 1875*4c87aefeSPatrick Mooney USB_DATA_XFER_UNLOCK(xfer); 1876*4c87aefeSPatrick Mooney 1877*4c87aefeSPatrick Mooney if (do_intr) 1878*4c87aefeSPatrick Mooney pci_xhci_assert_interrupt(sc); 1879*4c87aefeSPatrick Mooney 1880*4c87aefeSPatrick Mooney if (do_retry) { 1881*4c87aefeSPatrick Mooney USB_DATA_XFER_RESET(xfer); 1882*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci[%d]: retry:continuing with next TRBs\r\n", 1883*4c87aefeSPatrick Mooney __LINE__)); 1884*4c87aefeSPatrick Mooney goto retry; 1885*4c87aefeSPatrick Mooney } 1886*4c87aefeSPatrick Mooney 1887*4c87aefeSPatrick Mooney if (epid == 1) 1888*4c87aefeSPatrick Mooney USB_DATA_XFER_RESET(xfer); 1889*4c87aefeSPatrick Mooney 1890*4c87aefeSPatrick Mooney return (err); 1891*4c87aefeSPatrick Mooney } 1892*4c87aefeSPatrick Mooney 1893*4c87aefeSPatrick Mooney static void 1894*4c87aefeSPatrick Mooney pci_xhci_device_doorbell(struct pci_xhci_softc *sc, uint32_t slot, 1895*4c87aefeSPatrick Mooney uint32_t epid, uint32_t streamid) 1896*4c87aefeSPatrick Mooney { 1897*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev; 1898*4c87aefeSPatrick Mooney struct pci_xhci_dev_ep *devep; 1899*4c87aefeSPatrick Mooney struct xhci_dev_ctx *dev_ctx; 1900*4c87aefeSPatrick Mooney struct xhci_endp_ctx *ep_ctx; 1901*4c87aefeSPatrick Mooney struct pci_xhci_trb_ring *sctx_tr; 1902*4c87aefeSPatrick Mooney struct xhci_trb *trb; 1903*4c87aefeSPatrick Mooney uint64_t ringaddr; 1904*4c87aefeSPatrick Mooney uint32_t ccs; 1905*4c87aefeSPatrick Mooney 1906*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci doorbell slot %u epid %u stream %u\r\n", 1907*4c87aefeSPatrick Mooney slot, epid, streamid)); 1908*4c87aefeSPatrick Mooney 1909*4c87aefeSPatrick Mooney if (slot == 0 || slot > sc->ndevices) { 1910*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: invalid doorbell slot %u\r\n", slot)); 1911*4c87aefeSPatrick Mooney return; 1912*4c87aefeSPatrick Mooney } 1913*4c87aefeSPatrick Mooney 1914*4c87aefeSPatrick Mooney dev = XHCI_SLOTDEV_PTR(sc, slot); 1915*4c87aefeSPatrick Mooney devep = &dev->eps[epid]; 1916*4c87aefeSPatrick Mooney dev_ctx = pci_xhci_get_dev_ctx(sc, slot); 1917*4c87aefeSPatrick Mooney if (!dev_ctx) { 1918*4c87aefeSPatrick Mooney return; 1919*4c87aefeSPatrick Mooney } 1920*4c87aefeSPatrick Mooney ep_ctx = &dev_ctx->ctx_ep[epid]; 1921*4c87aefeSPatrick Mooney 1922*4c87aefeSPatrick Mooney sctx_tr = NULL; 1923*4c87aefeSPatrick Mooney 1924*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: device doorbell ep[%u] %08x %08x %016lx %08x\r\n", 1925*4c87aefeSPatrick Mooney epid, ep_ctx->dwEpCtx0, ep_ctx->dwEpCtx1, ep_ctx->qwEpCtx2, 1926*4c87aefeSPatrick Mooney ep_ctx->dwEpCtx4)); 1927*4c87aefeSPatrick Mooney 1928*4c87aefeSPatrick Mooney if (ep_ctx->qwEpCtx2 == 0) 1929*4c87aefeSPatrick Mooney return; 1930*4c87aefeSPatrick Mooney 1931*4c87aefeSPatrick Mooney /* handle pending transfers */ 1932*4c87aefeSPatrick Mooney if (devep->ep_xfer->ndata > 0) { 1933*4c87aefeSPatrick Mooney #ifndef __FreeBSD__ 1934*4c87aefeSPatrick Mooney USB_DATA_XFER_LOCK(devep->ep_xfer); 1935*4c87aefeSPatrick Mooney #endif 1936*4c87aefeSPatrick Mooney pci_xhci_try_usb_xfer(sc, dev, devep, ep_ctx, slot, epid); 1937*4c87aefeSPatrick Mooney #ifndef __FreeBSD__ 1938*4c87aefeSPatrick Mooney USB_DATA_XFER_UNLOCK(devep->ep_xfer); 1939*4c87aefeSPatrick Mooney #endif 1940*4c87aefeSPatrick Mooney return; 1941*4c87aefeSPatrick Mooney } 1942*4c87aefeSPatrick Mooney 1943*4c87aefeSPatrick Mooney /* get next trb work item */ 1944*4c87aefeSPatrick Mooney if (XHCI_EPCTX_0_MAXP_STREAMS_GET(ep_ctx->dwEpCtx0) != 0) { 1945*4c87aefeSPatrick Mooney sctx_tr = &devep->ep_sctx_trbs[streamid]; 1946*4c87aefeSPatrick Mooney ringaddr = sctx_tr->ringaddr; 1947*4c87aefeSPatrick Mooney ccs = sctx_tr->ccs; 1948*4c87aefeSPatrick Mooney trb = XHCI_GADDR(sc, sctx_tr->ringaddr & ~0xFUL); 1949*4c87aefeSPatrick Mooney DPRINTF(("doorbell, stream %u, ccs %lx, trb ccs %x\r\n", 1950*4c87aefeSPatrick Mooney streamid, ep_ctx->qwEpCtx2 & XHCI_TRB_3_CYCLE_BIT, 1951*4c87aefeSPatrick Mooney trb->dwTrb3 & XHCI_TRB_3_CYCLE_BIT)); 1952*4c87aefeSPatrick Mooney } else { 1953*4c87aefeSPatrick Mooney ringaddr = devep->ep_ringaddr; 1954*4c87aefeSPatrick Mooney ccs = devep->ep_ccs; 1955*4c87aefeSPatrick Mooney trb = devep->ep_tr; 1956*4c87aefeSPatrick Mooney DPRINTF(("doorbell, ccs %lx, trb ccs %x\r\n", 1957*4c87aefeSPatrick Mooney ep_ctx->qwEpCtx2 & XHCI_TRB_3_CYCLE_BIT, 1958*4c87aefeSPatrick Mooney trb->dwTrb3 & XHCI_TRB_3_CYCLE_BIT)); 1959*4c87aefeSPatrick Mooney } 1960*4c87aefeSPatrick Mooney 1961*4c87aefeSPatrick Mooney if (XHCI_TRB_3_TYPE_GET(trb->dwTrb3) == 0) { 1962*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: ring %lx trb[%lx] EP %u is RESERVED?\r\n", 1963*4c87aefeSPatrick Mooney ep_ctx->qwEpCtx2, devep->ep_ringaddr, epid)); 1964*4c87aefeSPatrick Mooney return; 1965*4c87aefeSPatrick Mooney } 1966*4c87aefeSPatrick Mooney 1967*4c87aefeSPatrick Mooney pci_xhci_handle_transfer(sc, dev, devep, ep_ctx, trb, slot, epid, 1968*4c87aefeSPatrick Mooney ringaddr, ccs, streamid); 1969*4c87aefeSPatrick Mooney } 1970*4c87aefeSPatrick Mooney 1971*4c87aefeSPatrick Mooney static void 1972*4c87aefeSPatrick Mooney pci_xhci_dbregs_write(struct pci_xhci_softc *sc, uint64_t offset, 1973*4c87aefeSPatrick Mooney uint64_t value) 1974*4c87aefeSPatrick Mooney { 1975*4c87aefeSPatrick Mooney 1976*4c87aefeSPatrick Mooney offset = (offset - sc->dboff) / sizeof(uint32_t); 1977*4c87aefeSPatrick Mooney 1978*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: doorbell write offset 0x%lx: 0x%lx\r\n", 1979*4c87aefeSPatrick Mooney offset, value)); 1980*4c87aefeSPatrick Mooney 1981*4c87aefeSPatrick Mooney if (XHCI_HALTED(sc)) { 1982*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: controller halted\r\n")); 1983*4c87aefeSPatrick Mooney return; 1984*4c87aefeSPatrick Mooney } 1985*4c87aefeSPatrick Mooney 1986*4c87aefeSPatrick Mooney if (offset == 0) 1987*4c87aefeSPatrick Mooney pci_xhci_complete_commands(sc); 1988*4c87aefeSPatrick Mooney else if (sc->portregs != NULL) 1989*4c87aefeSPatrick Mooney pci_xhci_device_doorbell(sc, offset, 1990*4c87aefeSPatrick Mooney XHCI_DB_TARGET_GET(value), XHCI_DB_SID_GET(value)); 1991*4c87aefeSPatrick Mooney } 1992*4c87aefeSPatrick Mooney 1993*4c87aefeSPatrick Mooney static void 1994*4c87aefeSPatrick Mooney pci_xhci_rtsregs_write(struct pci_xhci_softc *sc, uint64_t offset, 1995*4c87aefeSPatrick Mooney uint64_t value) 1996*4c87aefeSPatrick Mooney { 1997*4c87aefeSPatrick Mooney struct pci_xhci_rtsregs *rts; 1998*4c87aefeSPatrick Mooney 1999*4c87aefeSPatrick Mooney offset -= sc->rtsoff; 2000*4c87aefeSPatrick Mooney 2001*4c87aefeSPatrick Mooney if (offset == 0) { 2002*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci attempted write to MFINDEX\r\n")); 2003*4c87aefeSPatrick Mooney return; 2004*4c87aefeSPatrick Mooney } 2005*4c87aefeSPatrick Mooney 2006*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: runtime regs write offset 0x%lx: 0x%lx\r\n", 2007*4c87aefeSPatrick Mooney offset, value)); 2008*4c87aefeSPatrick Mooney 2009*4c87aefeSPatrick Mooney offset -= 0x20; /* start of intrreg */ 2010*4c87aefeSPatrick Mooney 2011*4c87aefeSPatrick Mooney rts = &sc->rtsregs; 2012*4c87aefeSPatrick Mooney 2013*4c87aefeSPatrick Mooney switch (offset) { 2014*4c87aefeSPatrick Mooney case 0x00: 2015*4c87aefeSPatrick Mooney if (value & XHCI_IMAN_INTR_PEND) 2016*4c87aefeSPatrick Mooney rts->intrreg.iman &= ~XHCI_IMAN_INTR_PEND; 2017*4c87aefeSPatrick Mooney rts->intrreg.iman = (value & XHCI_IMAN_INTR_ENA) | 2018*4c87aefeSPatrick Mooney (rts->intrreg.iman & XHCI_IMAN_INTR_PEND); 2019*4c87aefeSPatrick Mooney 2020*4c87aefeSPatrick Mooney if (!(value & XHCI_IMAN_INTR_ENA)) 2021*4c87aefeSPatrick Mooney pci_xhci_deassert_interrupt(sc); 2022*4c87aefeSPatrick Mooney 2023*4c87aefeSPatrick Mooney break; 2024*4c87aefeSPatrick Mooney 2025*4c87aefeSPatrick Mooney case 0x04: 2026*4c87aefeSPatrick Mooney rts->intrreg.imod = value; 2027*4c87aefeSPatrick Mooney break; 2028*4c87aefeSPatrick Mooney 2029*4c87aefeSPatrick Mooney case 0x08: 2030*4c87aefeSPatrick Mooney rts->intrreg.erstsz = value & 0xFFFF; 2031*4c87aefeSPatrick Mooney break; 2032*4c87aefeSPatrick Mooney 2033*4c87aefeSPatrick Mooney case 0x10: 2034*4c87aefeSPatrick Mooney /* ERSTBA low bits */ 2035*4c87aefeSPatrick Mooney rts->intrreg.erstba = MASK_64_HI(sc->rtsregs.intrreg.erstba) | 2036*4c87aefeSPatrick Mooney (value & ~0x3F); 2037*4c87aefeSPatrick Mooney break; 2038*4c87aefeSPatrick Mooney 2039*4c87aefeSPatrick Mooney case 0x14: 2040*4c87aefeSPatrick Mooney /* ERSTBA high bits */ 2041*4c87aefeSPatrick Mooney rts->intrreg.erstba = (value << 32) | 2042*4c87aefeSPatrick Mooney MASK_64_LO(sc->rtsregs.intrreg.erstba); 2043*4c87aefeSPatrick Mooney 2044*4c87aefeSPatrick Mooney rts->erstba_p = XHCI_GADDR(sc, 2045*4c87aefeSPatrick Mooney sc->rtsregs.intrreg.erstba & ~0x3FUL); 2046*4c87aefeSPatrick Mooney 2047*4c87aefeSPatrick Mooney rts->erst_p = XHCI_GADDR(sc, 2048*4c87aefeSPatrick Mooney sc->rtsregs.erstba_p->qwEvrsTablePtr & ~0x3FUL); 2049*4c87aefeSPatrick Mooney 2050*4c87aefeSPatrick Mooney rts->er_enq_idx = 0; 2051*4c87aefeSPatrick Mooney rts->er_events_cnt = 0; 2052*4c87aefeSPatrick Mooney 2053*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: wr erstba erst (%p) ptr 0x%lx, sz %u\r\n", 2054*4c87aefeSPatrick Mooney rts->erstba_p, 2055*4c87aefeSPatrick Mooney rts->erstba_p->qwEvrsTablePtr, 2056*4c87aefeSPatrick Mooney rts->erstba_p->dwEvrsTableSize)); 2057*4c87aefeSPatrick Mooney break; 2058*4c87aefeSPatrick Mooney 2059*4c87aefeSPatrick Mooney case 0x18: 2060*4c87aefeSPatrick Mooney /* ERDP low bits */ 2061*4c87aefeSPatrick Mooney rts->intrreg.erdp = 2062*4c87aefeSPatrick Mooney MASK_64_HI(sc->rtsregs.intrreg.erdp) | 2063*4c87aefeSPatrick Mooney (rts->intrreg.erdp & XHCI_ERDP_LO_BUSY) | 2064*4c87aefeSPatrick Mooney (value & ~0xF); 2065*4c87aefeSPatrick Mooney if (value & XHCI_ERDP_LO_BUSY) { 2066*4c87aefeSPatrick Mooney rts->intrreg.erdp &= ~XHCI_ERDP_LO_BUSY; 2067*4c87aefeSPatrick Mooney rts->intrreg.iman &= ~XHCI_IMAN_INTR_PEND; 2068*4c87aefeSPatrick Mooney } 2069*4c87aefeSPatrick Mooney 2070*4c87aefeSPatrick Mooney rts->er_deq_seg = XHCI_ERDP_LO_SINDEX(value); 2071*4c87aefeSPatrick Mooney 2072*4c87aefeSPatrick Mooney break; 2073*4c87aefeSPatrick Mooney 2074*4c87aefeSPatrick Mooney case 0x1C: 2075*4c87aefeSPatrick Mooney /* ERDP high bits */ 2076*4c87aefeSPatrick Mooney rts->intrreg.erdp = (value << 32) | 2077*4c87aefeSPatrick Mooney MASK_64_LO(sc->rtsregs.intrreg.erdp); 2078*4c87aefeSPatrick Mooney 2079*4c87aefeSPatrick Mooney if (rts->er_events_cnt > 0) { 2080*4c87aefeSPatrick Mooney uint64_t erdp; 2081*4c87aefeSPatrick Mooney uint32_t erdp_i; 2082*4c87aefeSPatrick Mooney 2083*4c87aefeSPatrick Mooney erdp = rts->intrreg.erdp & ~0xF; 2084*4c87aefeSPatrick Mooney erdp_i = (erdp - rts->erstba_p->qwEvrsTablePtr) / 2085*4c87aefeSPatrick Mooney sizeof(struct xhci_trb); 2086*4c87aefeSPatrick Mooney 2087*4c87aefeSPatrick Mooney if (erdp_i <= rts->er_enq_idx) 2088*4c87aefeSPatrick Mooney rts->er_events_cnt = rts->er_enq_idx - erdp_i; 2089*4c87aefeSPatrick Mooney else 2090*4c87aefeSPatrick Mooney rts->er_events_cnt = 2091*4c87aefeSPatrick Mooney rts->erstba_p->dwEvrsTableSize - 2092*4c87aefeSPatrick Mooney (erdp_i - rts->er_enq_idx); 2093*4c87aefeSPatrick Mooney 2094*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: erdp 0x%lx, events cnt %u\r\n", 2095*4c87aefeSPatrick Mooney erdp, rts->er_events_cnt)); 2096*4c87aefeSPatrick Mooney } 2097*4c87aefeSPatrick Mooney 2098*4c87aefeSPatrick Mooney break; 2099*4c87aefeSPatrick Mooney 2100*4c87aefeSPatrick Mooney default: 2101*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci attempted write to RTS offset 0x%lx\r\n", 2102*4c87aefeSPatrick Mooney offset)); 2103*4c87aefeSPatrick Mooney break; 2104*4c87aefeSPatrick Mooney } 2105*4c87aefeSPatrick Mooney } 2106*4c87aefeSPatrick Mooney 2107*4c87aefeSPatrick Mooney static uint64_t 2108*4c87aefeSPatrick Mooney pci_xhci_portregs_read(struct pci_xhci_softc *sc, uint64_t offset) 2109*4c87aefeSPatrick Mooney { 2110*4c87aefeSPatrick Mooney int port; 2111*4c87aefeSPatrick Mooney uint32_t *p; 2112*4c87aefeSPatrick Mooney 2113*4c87aefeSPatrick Mooney if (sc->portregs == NULL) 2114*4c87aefeSPatrick Mooney return (0); 2115*4c87aefeSPatrick Mooney 2116*4c87aefeSPatrick Mooney port = (offset - 0x3F0) / 0x10; 2117*4c87aefeSPatrick Mooney 2118*4c87aefeSPatrick Mooney if (port > XHCI_MAX_DEVS) { 2119*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: portregs_read port %d >= XHCI_MAX_DEVS\r\n", 2120*4c87aefeSPatrick Mooney port)); 2121*4c87aefeSPatrick Mooney 2122*4c87aefeSPatrick Mooney /* return default value for unused port */ 2123*4c87aefeSPatrick Mooney return (XHCI_PS_SPEED_SET(3)); 2124*4c87aefeSPatrick Mooney } 2125*4c87aefeSPatrick Mooney 2126*4c87aefeSPatrick Mooney offset = (offset - 0x3F0) % 0x10; 2127*4c87aefeSPatrick Mooney 2128*4c87aefeSPatrick Mooney p = &sc->portregs[port].portsc; 2129*4c87aefeSPatrick Mooney p += offset / sizeof(uint32_t); 2130*4c87aefeSPatrick Mooney 2131*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: portregs read offset 0x%lx port %u -> 0x%x\r\n", 2132*4c87aefeSPatrick Mooney offset, port, *p)); 2133*4c87aefeSPatrick Mooney 2134*4c87aefeSPatrick Mooney return (*p); 2135*4c87aefeSPatrick Mooney } 2136*4c87aefeSPatrick Mooney 2137*4c87aefeSPatrick Mooney static void 2138*4c87aefeSPatrick Mooney pci_xhci_hostop_write(struct pci_xhci_softc *sc, uint64_t offset, 2139*4c87aefeSPatrick Mooney uint64_t value) 2140*4c87aefeSPatrick Mooney { 2141*4c87aefeSPatrick Mooney offset -= XHCI_CAPLEN; 2142*4c87aefeSPatrick Mooney 2143*4c87aefeSPatrick Mooney if (offset < 0x400) 2144*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: hostop write offset 0x%lx: 0x%lx\r\n", 2145*4c87aefeSPatrick Mooney offset, value)); 2146*4c87aefeSPatrick Mooney 2147*4c87aefeSPatrick Mooney switch (offset) { 2148*4c87aefeSPatrick Mooney case XHCI_USBCMD: 2149*4c87aefeSPatrick Mooney sc->opregs.usbcmd = pci_xhci_usbcmd_write(sc, value & 0x3F0F); 2150*4c87aefeSPatrick Mooney break; 2151*4c87aefeSPatrick Mooney 2152*4c87aefeSPatrick Mooney case XHCI_USBSTS: 2153*4c87aefeSPatrick Mooney /* clear bits on write */ 2154*4c87aefeSPatrick Mooney sc->opregs.usbsts &= ~(value & 2155*4c87aefeSPatrick Mooney (XHCI_STS_HSE|XHCI_STS_EINT|XHCI_STS_PCD|XHCI_STS_SSS| 2156*4c87aefeSPatrick Mooney XHCI_STS_RSS|XHCI_STS_SRE|XHCI_STS_CNR)); 2157*4c87aefeSPatrick Mooney break; 2158*4c87aefeSPatrick Mooney 2159*4c87aefeSPatrick Mooney case XHCI_PAGESIZE: 2160*4c87aefeSPatrick Mooney /* read only */ 2161*4c87aefeSPatrick Mooney break; 2162*4c87aefeSPatrick Mooney 2163*4c87aefeSPatrick Mooney case XHCI_DNCTRL: 2164*4c87aefeSPatrick Mooney sc->opregs.dnctrl = value & 0xFFFF; 2165*4c87aefeSPatrick Mooney break; 2166*4c87aefeSPatrick Mooney 2167*4c87aefeSPatrick Mooney case XHCI_CRCR_LO: 2168*4c87aefeSPatrick Mooney if (sc->opregs.crcr & XHCI_CRCR_LO_CRR) { 2169*4c87aefeSPatrick Mooney sc->opregs.crcr &= ~(XHCI_CRCR_LO_CS|XHCI_CRCR_LO_CA); 2170*4c87aefeSPatrick Mooney sc->opregs.crcr |= value & 2171*4c87aefeSPatrick Mooney (XHCI_CRCR_LO_CS|XHCI_CRCR_LO_CA); 2172*4c87aefeSPatrick Mooney } else { 2173*4c87aefeSPatrick Mooney sc->opregs.crcr = MASK_64_HI(sc->opregs.crcr) | 2174*4c87aefeSPatrick Mooney (value & (0xFFFFFFC0 | XHCI_CRCR_LO_RCS)); 2175*4c87aefeSPatrick Mooney } 2176*4c87aefeSPatrick Mooney break; 2177*4c87aefeSPatrick Mooney 2178*4c87aefeSPatrick Mooney case XHCI_CRCR_HI: 2179*4c87aefeSPatrick Mooney if (!(sc->opregs.crcr & XHCI_CRCR_LO_CRR)) { 2180*4c87aefeSPatrick Mooney sc->opregs.crcr = MASK_64_LO(sc->opregs.crcr) | 2181*4c87aefeSPatrick Mooney (value << 32); 2182*4c87aefeSPatrick Mooney 2183*4c87aefeSPatrick Mooney sc->opregs.cr_p = XHCI_GADDR(sc, 2184*4c87aefeSPatrick Mooney sc->opregs.crcr & ~0xF); 2185*4c87aefeSPatrick Mooney } 2186*4c87aefeSPatrick Mooney 2187*4c87aefeSPatrick Mooney if (sc->opregs.crcr & XHCI_CRCR_LO_CS) { 2188*4c87aefeSPatrick Mooney /* Stop operation of Command Ring */ 2189*4c87aefeSPatrick Mooney } 2190*4c87aefeSPatrick Mooney 2191*4c87aefeSPatrick Mooney if (sc->opregs.crcr & XHCI_CRCR_LO_CA) { 2192*4c87aefeSPatrick Mooney /* Abort command */ 2193*4c87aefeSPatrick Mooney } 2194*4c87aefeSPatrick Mooney 2195*4c87aefeSPatrick Mooney break; 2196*4c87aefeSPatrick Mooney 2197*4c87aefeSPatrick Mooney case XHCI_DCBAAP_LO: 2198*4c87aefeSPatrick Mooney sc->opregs.dcbaap = MASK_64_HI(sc->opregs.dcbaap) | 2199*4c87aefeSPatrick Mooney (value & 0xFFFFFFC0); 2200*4c87aefeSPatrick Mooney break; 2201*4c87aefeSPatrick Mooney 2202*4c87aefeSPatrick Mooney case XHCI_DCBAAP_HI: 2203*4c87aefeSPatrick Mooney sc->opregs.dcbaap = MASK_64_LO(sc->opregs.dcbaap) | 2204*4c87aefeSPatrick Mooney (value << 32); 2205*4c87aefeSPatrick Mooney sc->opregs.dcbaa_p = XHCI_GADDR(sc, sc->opregs.dcbaap & ~0x3FUL); 2206*4c87aefeSPatrick Mooney 2207*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: opregs dcbaap = 0x%lx (vaddr 0x%lx)\r\n", 2208*4c87aefeSPatrick Mooney sc->opregs.dcbaap, (uint64_t)sc->opregs.dcbaa_p)); 2209*4c87aefeSPatrick Mooney break; 2210*4c87aefeSPatrick Mooney 2211*4c87aefeSPatrick Mooney case XHCI_CONFIG: 2212*4c87aefeSPatrick Mooney sc->opregs.config = value & 0x03FF; 2213*4c87aefeSPatrick Mooney break; 2214*4c87aefeSPatrick Mooney 2215*4c87aefeSPatrick Mooney default: 2216*4c87aefeSPatrick Mooney if (offset >= 0x400) 2217*4c87aefeSPatrick Mooney pci_xhci_portregs_write(sc, offset, value); 2218*4c87aefeSPatrick Mooney 2219*4c87aefeSPatrick Mooney break; 2220*4c87aefeSPatrick Mooney } 2221*4c87aefeSPatrick Mooney } 2222*4c87aefeSPatrick Mooney 2223*4c87aefeSPatrick Mooney 2224*4c87aefeSPatrick Mooney static void 2225*4c87aefeSPatrick Mooney pci_xhci_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, 2226*4c87aefeSPatrick Mooney int baridx, uint64_t offset, int size, uint64_t value) 2227*4c87aefeSPatrick Mooney { 2228*4c87aefeSPatrick Mooney struct pci_xhci_softc *sc; 2229*4c87aefeSPatrick Mooney 2230*4c87aefeSPatrick Mooney sc = pi->pi_arg; 2231*4c87aefeSPatrick Mooney 2232*4c87aefeSPatrick Mooney assert(baridx == 0); 2233*4c87aefeSPatrick Mooney 2234*4c87aefeSPatrick Mooney 2235*4c87aefeSPatrick Mooney pthread_mutex_lock(&sc->mtx); 2236*4c87aefeSPatrick Mooney if (offset < XHCI_CAPLEN) /* read only registers */ 2237*4c87aefeSPatrick Mooney WPRINTF(("pci_xhci: write RO-CAPs offset %ld\r\n", offset)); 2238*4c87aefeSPatrick Mooney else if (offset < sc->dboff) 2239*4c87aefeSPatrick Mooney pci_xhci_hostop_write(sc, offset, value); 2240*4c87aefeSPatrick Mooney else if (offset < sc->rtsoff) 2241*4c87aefeSPatrick Mooney pci_xhci_dbregs_write(sc, offset, value); 2242*4c87aefeSPatrick Mooney else if (offset < sc->regsend) 2243*4c87aefeSPatrick Mooney pci_xhci_rtsregs_write(sc, offset, value); 2244*4c87aefeSPatrick Mooney else 2245*4c87aefeSPatrick Mooney WPRINTF(("pci_xhci: write invalid offset %ld\r\n", offset)); 2246*4c87aefeSPatrick Mooney 2247*4c87aefeSPatrick Mooney pthread_mutex_unlock(&sc->mtx); 2248*4c87aefeSPatrick Mooney } 2249*4c87aefeSPatrick Mooney 2250*4c87aefeSPatrick Mooney static uint64_t 2251*4c87aefeSPatrick Mooney pci_xhci_hostcap_read(struct pci_xhci_softc *sc, uint64_t offset) 2252*4c87aefeSPatrick Mooney { 2253*4c87aefeSPatrick Mooney uint64_t value; 2254*4c87aefeSPatrick Mooney 2255*4c87aefeSPatrick Mooney switch (offset) { 2256*4c87aefeSPatrick Mooney case XHCI_CAPLENGTH: /* 0x00 */ 2257*4c87aefeSPatrick Mooney value = sc->caplength; 2258*4c87aefeSPatrick Mooney break; 2259*4c87aefeSPatrick Mooney 2260*4c87aefeSPatrick Mooney case XHCI_HCSPARAMS1: /* 0x04 */ 2261*4c87aefeSPatrick Mooney value = sc->hcsparams1; 2262*4c87aefeSPatrick Mooney break; 2263*4c87aefeSPatrick Mooney 2264*4c87aefeSPatrick Mooney case XHCI_HCSPARAMS2: /* 0x08 */ 2265*4c87aefeSPatrick Mooney value = sc->hcsparams2; 2266*4c87aefeSPatrick Mooney break; 2267*4c87aefeSPatrick Mooney 2268*4c87aefeSPatrick Mooney case XHCI_HCSPARAMS3: /* 0x0C */ 2269*4c87aefeSPatrick Mooney value = sc->hcsparams3; 2270*4c87aefeSPatrick Mooney break; 2271*4c87aefeSPatrick Mooney 2272*4c87aefeSPatrick Mooney case XHCI_HCSPARAMS0: /* 0x10 */ 2273*4c87aefeSPatrick Mooney value = sc->hccparams1; 2274*4c87aefeSPatrick Mooney break; 2275*4c87aefeSPatrick Mooney 2276*4c87aefeSPatrick Mooney case XHCI_DBOFF: /* 0x14 */ 2277*4c87aefeSPatrick Mooney value = sc->dboff; 2278*4c87aefeSPatrick Mooney break; 2279*4c87aefeSPatrick Mooney 2280*4c87aefeSPatrick Mooney case XHCI_RTSOFF: /* 0x18 */ 2281*4c87aefeSPatrick Mooney value = sc->rtsoff; 2282*4c87aefeSPatrick Mooney break; 2283*4c87aefeSPatrick Mooney 2284*4c87aefeSPatrick Mooney case XHCI_HCCPRAMS2: /* 0x1C */ 2285*4c87aefeSPatrick Mooney value = sc->hccparams2; 2286*4c87aefeSPatrick Mooney break; 2287*4c87aefeSPatrick Mooney 2288*4c87aefeSPatrick Mooney default: 2289*4c87aefeSPatrick Mooney value = 0; 2290*4c87aefeSPatrick Mooney break; 2291*4c87aefeSPatrick Mooney } 2292*4c87aefeSPatrick Mooney 2293*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: hostcap read offset 0x%lx -> 0x%lx\r\n", 2294*4c87aefeSPatrick Mooney offset, value)); 2295*4c87aefeSPatrick Mooney 2296*4c87aefeSPatrick Mooney return (value); 2297*4c87aefeSPatrick Mooney } 2298*4c87aefeSPatrick Mooney 2299*4c87aefeSPatrick Mooney static uint64_t 2300*4c87aefeSPatrick Mooney pci_xhci_hostop_read(struct pci_xhci_softc *sc, uint64_t offset) 2301*4c87aefeSPatrick Mooney { 2302*4c87aefeSPatrick Mooney uint64_t value; 2303*4c87aefeSPatrick Mooney 2304*4c87aefeSPatrick Mooney offset = (offset - XHCI_CAPLEN); 2305*4c87aefeSPatrick Mooney 2306*4c87aefeSPatrick Mooney switch (offset) { 2307*4c87aefeSPatrick Mooney case XHCI_USBCMD: /* 0x00 */ 2308*4c87aefeSPatrick Mooney value = sc->opregs.usbcmd; 2309*4c87aefeSPatrick Mooney break; 2310*4c87aefeSPatrick Mooney 2311*4c87aefeSPatrick Mooney case XHCI_USBSTS: /* 0x04 */ 2312*4c87aefeSPatrick Mooney value = sc->opregs.usbsts; 2313*4c87aefeSPatrick Mooney break; 2314*4c87aefeSPatrick Mooney 2315*4c87aefeSPatrick Mooney case XHCI_PAGESIZE: /* 0x08 */ 2316*4c87aefeSPatrick Mooney value = sc->opregs.pgsz; 2317*4c87aefeSPatrick Mooney break; 2318*4c87aefeSPatrick Mooney 2319*4c87aefeSPatrick Mooney case XHCI_DNCTRL: /* 0x14 */ 2320*4c87aefeSPatrick Mooney value = sc->opregs.dnctrl; 2321*4c87aefeSPatrick Mooney break; 2322*4c87aefeSPatrick Mooney 2323*4c87aefeSPatrick Mooney case XHCI_CRCR_LO: /* 0x18 */ 2324*4c87aefeSPatrick Mooney value = sc->opregs.crcr & XHCI_CRCR_LO_CRR; 2325*4c87aefeSPatrick Mooney break; 2326*4c87aefeSPatrick Mooney 2327*4c87aefeSPatrick Mooney case XHCI_CRCR_HI: /* 0x1C */ 2328*4c87aefeSPatrick Mooney value = 0; 2329*4c87aefeSPatrick Mooney break; 2330*4c87aefeSPatrick Mooney 2331*4c87aefeSPatrick Mooney case XHCI_DCBAAP_LO: /* 0x30 */ 2332*4c87aefeSPatrick Mooney value = sc->opregs.dcbaap & 0xFFFFFFFF; 2333*4c87aefeSPatrick Mooney break; 2334*4c87aefeSPatrick Mooney 2335*4c87aefeSPatrick Mooney case XHCI_DCBAAP_HI: /* 0x34 */ 2336*4c87aefeSPatrick Mooney value = (sc->opregs.dcbaap >> 32) & 0xFFFFFFFF; 2337*4c87aefeSPatrick Mooney break; 2338*4c87aefeSPatrick Mooney 2339*4c87aefeSPatrick Mooney case XHCI_CONFIG: /* 0x38 */ 2340*4c87aefeSPatrick Mooney value = sc->opregs.config; 2341*4c87aefeSPatrick Mooney break; 2342*4c87aefeSPatrick Mooney 2343*4c87aefeSPatrick Mooney default: 2344*4c87aefeSPatrick Mooney if (offset >= 0x400) 2345*4c87aefeSPatrick Mooney value = pci_xhci_portregs_read(sc, offset); 2346*4c87aefeSPatrick Mooney else 2347*4c87aefeSPatrick Mooney value = 0; 2348*4c87aefeSPatrick Mooney 2349*4c87aefeSPatrick Mooney break; 2350*4c87aefeSPatrick Mooney } 2351*4c87aefeSPatrick Mooney 2352*4c87aefeSPatrick Mooney if (offset < 0x400) 2353*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: hostop read offset 0x%lx -> 0x%lx\r\n", 2354*4c87aefeSPatrick Mooney offset, value)); 2355*4c87aefeSPatrick Mooney 2356*4c87aefeSPatrick Mooney return (value); 2357*4c87aefeSPatrick Mooney } 2358*4c87aefeSPatrick Mooney 2359*4c87aefeSPatrick Mooney static uint64_t 2360*4c87aefeSPatrick Mooney pci_xhci_dbregs_read(struct pci_xhci_softc *sc, uint64_t offset) 2361*4c87aefeSPatrick Mooney { 2362*4c87aefeSPatrick Mooney 2363*4c87aefeSPatrick Mooney /* read doorbell always returns 0 */ 2364*4c87aefeSPatrick Mooney return (0); 2365*4c87aefeSPatrick Mooney } 2366*4c87aefeSPatrick Mooney 2367*4c87aefeSPatrick Mooney static uint64_t 2368*4c87aefeSPatrick Mooney pci_xhci_rtsregs_read(struct pci_xhci_softc *sc, uint64_t offset) 2369*4c87aefeSPatrick Mooney { 2370*4c87aefeSPatrick Mooney uint32_t value; 2371*4c87aefeSPatrick Mooney 2372*4c87aefeSPatrick Mooney offset -= sc->rtsoff; 2373*4c87aefeSPatrick Mooney value = 0; 2374*4c87aefeSPatrick Mooney 2375*4c87aefeSPatrick Mooney if (offset == XHCI_MFINDEX) { 2376*4c87aefeSPatrick Mooney value = sc->rtsregs.mfindex; 2377*4c87aefeSPatrick Mooney } else if (offset >= 0x20) { 2378*4c87aefeSPatrick Mooney int item; 2379*4c87aefeSPatrick Mooney uint32_t *p; 2380*4c87aefeSPatrick Mooney 2381*4c87aefeSPatrick Mooney offset -= 0x20; 2382*4c87aefeSPatrick Mooney item = offset % 32; 2383*4c87aefeSPatrick Mooney 2384*4c87aefeSPatrick Mooney assert(offset < sizeof(sc->rtsregs.intrreg)); 2385*4c87aefeSPatrick Mooney 2386*4c87aefeSPatrick Mooney p = &sc->rtsregs.intrreg.iman; 2387*4c87aefeSPatrick Mooney p += item / sizeof(uint32_t); 2388*4c87aefeSPatrick Mooney value = *p; 2389*4c87aefeSPatrick Mooney } 2390*4c87aefeSPatrick Mooney 2391*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: rtsregs read offset 0x%lx -> 0x%x\r\n", 2392*4c87aefeSPatrick Mooney offset, value)); 2393*4c87aefeSPatrick Mooney 2394*4c87aefeSPatrick Mooney return (value); 2395*4c87aefeSPatrick Mooney } 2396*4c87aefeSPatrick Mooney 2397*4c87aefeSPatrick Mooney static uint64_t 2398*4c87aefeSPatrick Mooney pci_xhci_xecp_read(struct pci_xhci_softc *sc, uint64_t offset) 2399*4c87aefeSPatrick Mooney { 2400*4c87aefeSPatrick Mooney uint32_t value; 2401*4c87aefeSPatrick Mooney 2402*4c87aefeSPatrick Mooney offset -= sc->regsend; 2403*4c87aefeSPatrick Mooney value = 0; 2404*4c87aefeSPatrick Mooney 2405*4c87aefeSPatrick Mooney switch (offset) { 2406*4c87aefeSPatrick Mooney case 0: 2407*4c87aefeSPatrick Mooney /* rev major | rev minor | next-cap | cap-id */ 2408*4c87aefeSPatrick Mooney value = (0x02 << 24) | (4 << 8) | XHCI_ID_PROTOCOLS; 2409*4c87aefeSPatrick Mooney break; 2410*4c87aefeSPatrick Mooney case 4: 2411*4c87aefeSPatrick Mooney /* name string = "USB" */ 2412*4c87aefeSPatrick Mooney value = 0x20425355; 2413*4c87aefeSPatrick Mooney break; 2414*4c87aefeSPatrick Mooney case 8: 2415*4c87aefeSPatrick Mooney /* psic | proto-defined | compat # | compat offset */ 2416*4c87aefeSPatrick Mooney value = ((XHCI_MAX_DEVS/2) << 8) | sc->usb2_port_start; 2417*4c87aefeSPatrick Mooney break; 2418*4c87aefeSPatrick Mooney case 12: 2419*4c87aefeSPatrick Mooney break; 2420*4c87aefeSPatrick Mooney case 16: 2421*4c87aefeSPatrick Mooney /* rev major | rev minor | next-cap | cap-id */ 2422*4c87aefeSPatrick Mooney value = (0x03 << 24) | XHCI_ID_PROTOCOLS; 2423*4c87aefeSPatrick Mooney break; 2424*4c87aefeSPatrick Mooney case 20: 2425*4c87aefeSPatrick Mooney /* name string = "USB" */ 2426*4c87aefeSPatrick Mooney value = 0x20425355; 2427*4c87aefeSPatrick Mooney break; 2428*4c87aefeSPatrick Mooney case 24: 2429*4c87aefeSPatrick Mooney /* psic | proto-defined | compat # | compat offset */ 2430*4c87aefeSPatrick Mooney value = ((XHCI_MAX_DEVS/2) << 8) | sc->usb3_port_start; 2431*4c87aefeSPatrick Mooney break; 2432*4c87aefeSPatrick Mooney case 28: 2433*4c87aefeSPatrick Mooney break; 2434*4c87aefeSPatrick Mooney default: 2435*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: xecp invalid offset 0x%lx\r\n", offset)); 2436*4c87aefeSPatrick Mooney break; 2437*4c87aefeSPatrick Mooney } 2438*4c87aefeSPatrick Mooney 2439*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci: xecp read offset 0x%lx -> 0x%x\r\n", 2440*4c87aefeSPatrick Mooney offset, value)); 2441*4c87aefeSPatrick Mooney 2442*4c87aefeSPatrick Mooney return (value); 2443*4c87aefeSPatrick Mooney } 2444*4c87aefeSPatrick Mooney 2445*4c87aefeSPatrick Mooney 2446*4c87aefeSPatrick Mooney static uint64_t 2447*4c87aefeSPatrick Mooney pci_xhci_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, 2448*4c87aefeSPatrick Mooney uint64_t offset, int size) 2449*4c87aefeSPatrick Mooney { 2450*4c87aefeSPatrick Mooney struct pci_xhci_softc *sc; 2451*4c87aefeSPatrick Mooney uint32_t value; 2452*4c87aefeSPatrick Mooney 2453*4c87aefeSPatrick Mooney sc = pi->pi_arg; 2454*4c87aefeSPatrick Mooney 2455*4c87aefeSPatrick Mooney assert(baridx == 0); 2456*4c87aefeSPatrick Mooney 2457*4c87aefeSPatrick Mooney pthread_mutex_lock(&sc->mtx); 2458*4c87aefeSPatrick Mooney if (offset < XHCI_CAPLEN) 2459*4c87aefeSPatrick Mooney value = pci_xhci_hostcap_read(sc, offset); 2460*4c87aefeSPatrick Mooney else if (offset < sc->dboff) 2461*4c87aefeSPatrick Mooney value = pci_xhci_hostop_read(sc, offset); 2462*4c87aefeSPatrick Mooney else if (offset < sc->rtsoff) 2463*4c87aefeSPatrick Mooney value = pci_xhci_dbregs_read(sc, offset); 2464*4c87aefeSPatrick Mooney else if (offset < sc->regsend) 2465*4c87aefeSPatrick Mooney value = pci_xhci_rtsregs_read(sc, offset); 2466*4c87aefeSPatrick Mooney else if (offset < (sc->regsend + 4*32)) 2467*4c87aefeSPatrick Mooney value = pci_xhci_xecp_read(sc, offset); 2468*4c87aefeSPatrick Mooney else { 2469*4c87aefeSPatrick Mooney value = 0; 2470*4c87aefeSPatrick Mooney WPRINTF(("pci_xhci: read invalid offset %ld\r\n", offset)); 2471*4c87aefeSPatrick Mooney } 2472*4c87aefeSPatrick Mooney 2473*4c87aefeSPatrick Mooney pthread_mutex_unlock(&sc->mtx); 2474*4c87aefeSPatrick Mooney 2475*4c87aefeSPatrick Mooney switch (size) { 2476*4c87aefeSPatrick Mooney case 1: 2477*4c87aefeSPatrick Mooney value &= 0xFF; 2478*4c87aefeSPatrick Mooney break; 2479*4c87aefeSPatrick Mooney case 2: 2480*4c87aefeSPatrick Mooney value &= 0xFFFF; 2481*4c87aefeSPatrick Mooney break; 2482*4c87aefeSPatrick Mooney case 4: 2483*4c87aefeSPatrick Mooney value &= 0xFFFFFFFF; 2484*4c87aefeSPatrick Mooney break; 2485*4c87aefeSPatrick Mooney } 2486*4c87aefeSPatrick Mooney 2487*4c87aefeSPatrick Mooney return (value); 2488*4c87aefeSPatrick Mooney } 2489*4c87aefeSPatrick Mooney 2490*4c87aefeSPatrick Mooney static void 2491*4c87aefeSPatrick Mooney pci_xhci_reset_port(struct pci_xhci_softc *sc, int portn, int warm) 2492*4c87aefeSPatrick Mooney { 2493*4c87aefeSPatrick Mooney struct pci_xhci_portregs *port; 2494*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev; 2495*4c87aefeSPatrick Mooney struct xhci_trb evtrb; 2496*4c87aefeSPatrick Mooney int error; 2497*4c87aefeSPatrick Mooney 2498*4c87aefeSPatrick Mooney assert(portn <= XHCI_MAX_DEVS); 2499*4c87aefeSPatrick Mooney 2500*4c87aefeSPatrick Mooney DPRINTF(("xhci reset port %d\r\n", portn)); 2501*4c87aefeSPatrick Mooney 2502*4c87aefeSPatrick Mooney port = XHCI_PORTREG_PTR(sc, portn); 2503*4c87aefeSPatrick Mooney dev = XHCI_DEVINST_PTR(sc, portn); 2504*4c87aefeSPatrick Mooney if (dev) { 2505*4c87aefeSPatrick Mooney port->portsc &= ~(XHCI_PS_PLS_MASK | XHCI_PS_PR | XHCI_PS_PRC); 2506*4c87aefeSPatrick Mooney port->portsc |= XHCI_PS_PED | 2507*4c87aefeSPatrick Mooney XHCI_PS_SPEED_SET(dev->dev_ue->ue_usbspeed); 2508*4c87aefeSPatrick Mooney 2509*4c87aefeSPatrick Mooney if (warm && dev->dev_ue->ue_usbver == 3) { 2510*4c87aefeSPatrick Mooney port->portsc |= XHCI_PS_WRC; 2511*4c87aefeSPatrick Mooney } 2512*4c87aefeSPatrick Mooney 2513*4c87aefeSPatrick Mooney if ((port->portsc & XHCI_PS_PRC) == 0) { 2514*4c87aefeSPatrick Mooney port->portsc |= XHCI_PS_PRC; 2515*4c87aefeSPatrick Mooney 2516*4c87aefeSPatrick Mooney pci_xhci_set_evtrb(&evtrb, portn, 2517*4c87aefeSPatrick Mooney XHCI_TRB_ERROR_SUCCESS, 2518*4c87aefeSPatrick Mooney XHCI_TRB_EVENT_PORT_STS_CHANGE); 2519*4c87aefeSPatrick Mooney error = pci_xhci_insert_event(sc, &evtrb, 1); 2520*4c87aefeSPatrick Mooney if (error != XHCI_TRB_ERROR_SUCCESS) 2521*4c87aefeSPatrick Mooney DPRINTF(("xhci reset port insert event " 2522*4c87aefeSPatrick Mooney "failed\r\n")); 2523*4c87aefeSPatrick Mooney } 2524*4c87aefeSPatrick Mooney } 2525*4c87aefeSPatrick Mooney } 2526*4c87aefeSPatrick Mooney 2527*4c87aefeSPatrick Mooney static void 2528*4c87aefeSPatrick Mooney pci_xhci_init_port(struct pci_xhci_softc *sc, int portn) 2529*4c87aefeSPatrick Mooney { 2530*4c87aefeSPatrick Mooney struct pci_xhci_portregs *port; 2531*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev; 2532*4c87aefeSPatrick Mooney 2533*4c87aefeSPatrick Mooney port = XHCI_PORTREG_PTR(sc, portn); 2534*4c87aefeSPatrick Mooney dev = XHCI_DEVINST_PTR(sc, portn); 2535*4c87aefeSPatrick Mooney if (dev) { 2536*4c87aefeSPatrick Mooney port->portsc = XHCI_PS_CCS | /* connected */ 2537*4c87aefeSPatrick Mooney XHCI_PS_PP; /* port power */ 2538*4c87aefeSPatrick Mooney 2539*4c87aefeSPatrick Mooney if (dev->dev_ue->ue_usbver == 2) { 2540*4c87aefeSPatrick Mooney port->portsc |= XHCI_PS_PLS_SET(UPS_PORT_LS_POLL) | 2541*4c87aefeSPatrick Mooney XHCI_PS_SPEED_SET(dev->dev_ue->ue_usbspeed); 2542*4c87aefeSPatrick Mooney } else { 2543*4c87aefeSPatrick Mooney port->portsc |= XHCI_PS_PLS_SET(UPS_PORT_LS_U0) | 2544*4c87aefeSPatrick Mooney XHCI_PS_PED | /* enabled */ 2545*4c87aefeSPatrick Mooney XHCI_PS_SPEED_SET(dev->dev_ue->ue_usbspeed); 2546*4c87aefeSPatrick Mooney } 2547*4c87aefeSPatrick Mooney 2548*4c87aefeSPatrick Mooney DPRINTF(("Init port %d 0x%x\n", portn, port->portsc)); 2549*4c87aefeSPatrick Mooney } else { 2550*4c87aefeSPatrick Mooney port->portsc = XHCI_PS_PLS_SET(UPS_PORT_LS_RX_DET) | XHCI_PS_PP; 2551*4c87aefeSPatrick Mooney DPRINTF(("Init empty port %d 0x%x\n", portn, port->portsc)); 2552*4c87aefeSPatrick Mooney } 2553*4c87aefeSPatrick Mooney } 2554*4c87aefeSPatrick Mooney 2555*4c87aefeSPatrick Mooney static int 2556*4c87aefeSPatrick Mooney pci_xhci_dev_intr(struct usb_hci *hci, int epctx) 2557*4c87aefeSPatrick Mooney { 2558*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev; 2559*4c87aefeSPatrick Mooney struct xhci_dev_ctx *dev_ctx; 2560*4c87aefeSPatrick Mooney struct xhci_trb evtrb; 2561*4c87aefeSPatrick Mooney struct pci_xhci_softc *sc; 2562*4c87aefeSPatrick Mooney struct pci_xhci_portregs *p; 2563*4c87aefeSPatrick Mooney struct xhci_endp_ctx *ep_ctx; 2564*4c87aefeSPatrick Mooney int error; 2565*4c87aefeSPatrick Mooney int dir_in; 2566*4c87aefeSPatrick Mooney int epid; 2567*4c87aefeSPatrick Mooney 2568*4c87aefeSPatrick Mooney dir_in = epctx & 0x80; 2569*4c87aefeSPatrick Mooney epid = epctx & ~0x80; 2570*4c87aefeSPatrick Mooney 2571*4c87aefeSPatrick Mooney /* HW endpoint contexts are 0-15; convert to epid based on dir */ 2572*4c87aefeSPatrick Mooney epid = (epid * 2) + (dir_in ? 1 : 0); 2573*4c87aefeSPatrick Mooney 2574*4c87aefeSPatrick Mooney assert(epid >= 1 && epid <= 31); 2575*4c87aefeSPatrick Mooney 2576*4c87aefeSPatrick Mooney dev = hci->hci_sc; 2577*4c87aefeSPatrick Mooney sc = dev->xsc; 2578*4c87aefeSPatrick Mooney 2579*4c87aefeSPatrick Mooney /* check if device is ready; OS has to initialise it */ 2580*4c87aefeSPatrick Mooney if (sc->rtsregs.erstba_p == NULL || 2581*4c87aefeSPatrick Mooney (sc->opregs.usbcmd & XHCI_CMD_RS) == 0 || 2582*4c87aefeSPatrick Mooney dev->dev_ctx == NULL) 2583*4c87aefeSPatrick Mooney return (0); 2584*4c87aefeSPatrick Mooney 2585*4c87aefeSPatrick Mooney p = XHCI_PORTREG_PTR(sc, hci->hci_port); 2586*4c87aefeSPatrick Mooney 2587*4c87aefeSPatrick Mooney /* raise event if link U3 (suspended) state */ 2588*4c87aefeSPatrick Mooney if (XHCI_PS_PLS_GET(p->portsc) == 3) { 2589*4c87aefeSPatrick Mooney p->portsc &= ~XHCI_PS_PLS_MASK; 2590*4c87aefeSPatrick Mooney p->portsc |= XHCI_PS_PLS_SET(UPS_PORT_LS_RESUME); 2591*4c87aefeSPatrick Mooney if ((p->portsc & XHCI_PS_PLC) != 0) 2592*4c87aefeSPatrick Mooney return (0); 2593*4c87aefeSPatrick Mooney 2594*4c87aefeSPatrick Mooney p->portsc |= XHCI_PS_PLC; 2595*4c87aefeSPatrick Mooney 2596*4c87aefeSPatrick Mooney pci_xhci_set_evtrb(&evtrb, hci->hci_port, 2597*4c87aefeSPatrick Mooney XHCI_TRB_ERROR_SUCCESS, XHCI_TRB_EVENT_PORT_STS_CHANGE); 2598*4c87aefeSPatrick Mooney error = pci_xhci_insert_event(sc, &evtrb, 0); 2599*4c87aefeSPatrick Mooney if (error != XHCI_TRB_ERROR_SUCCESS) 2600*4c87aefeSPatrick Mooney goto done; 2601*4c87aefeSPatrick Mooney } 2602*4c87aefeSPatrick Mooney 2603*4c87aefeSPatrick Mooney dev_ctx = dev->dev_ctx; 2604*4c87aefeSPatrick Mooney ep_ctx = &dev_ctx->ctx_ep[epid]; 2605*4c87aefeSPatrick Mooney if ((ep_ctx->dwEpCtx0 & 0x7) == XHCI_ST_EPCTX_DISABLED) { 2606*4c87aefeSPatrick Mooney DPRINTF(("xhci device interrupt on disabled endpoint %d\r\n", 2607*4c87aefeSPatrick Mooney epid)); 2608*4c87aefeSPatrick Mooney return (0); 2609*4c87aefeSPatrick Mooney } 2610*4c87aefeSPatrick Mooney 2611*4c87aefeSPatrick Mooney DPRINTF(("xhci device interrupt on endpoint %d\r\n", epid)); 2612*4c87aefeSPatrick Mooney 2613*4c87aefeSPatrick Mooney pci_xhci_device_doorbell(sc, hci->hci_port, epid, 0); 2614*4c87aefeSPatrick Mooney 2615*4c87aefeSPatrick Mooney done: 2616*4c87aefeSPatrick Mooney return (error); 2617*4c87aefeSPatrick Mooney } 2618*4c87aefeSPatrick Mooney 2619*4c87aefeSPatrick Mooney static int 2620*4c87aefeSPatrick Mooney pci_xhci_dev_event(struct usb_hci *hci, enum hci_usbev evid, void *param) 2621*4c87aefeSPatrick Mooney { 2622*4c87aefeSPatrick Mooney 2623*4c87aefeSPatrick Mooney DPRINTF(("xhci device event port %d\r\n", hci->hci_port)); 2624*4c87aefeSPatrick Mooney return (0); 2625*4c87aefeSPatrick Mooney } 2626*4c87aefeSPatrick Mooney 2627*4c87aefeSPatrick Mooney 2628*4c87aefeSPatrick Mooney 2629*4c87aefeSPatrick Mooney static void 2630*4c87aefeSPatrick Mooney pci_xhci_device_usage(char *opt) 2631*4c87aefeSPatrick Mooney { 2632*4c87aefeSPatrick Mooney 2633*4c87aefeSPatrick Mooney fprintf(stderr, "Invalid USB emulation \"%s\"\r\n", opt); 2634*4c87aefeSPatrick Mooney } 2635*4c87aefeSPatrick Mooney 2636*4c87aefeSPatrick Mooney static int 2637*4c87aefeSPatrick Mooney pci_xhci_parse_opts(struct pci_xhci_softc *sc, char *opts) 2638*4c87aefeSPatrick Mooney { 2639*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu **devices; 2640*4c87aefeSPatrick Mooney struct pci_xhci_dev_emu *dev; 2641*4c87aefeSPatrick Mooney struct usb_devemu *ue; 2642*4c87aefeSPatrick Mooney void *devsc; 2643*4c87aefeSPatrick Mooney char *uopt, *xopts, *config; 2644*4c87aefeSPatrick Mooney int usb3_port, usb2_port, i; 2645*4c87aefeSPatrick Mooney 2646*4c87aefeSPatrick Mooney uopt = NULL; 2647*4c87aefeSPatrick Mooney usb3_port = sc->usb3_port_start - 1; 2648*4c87aefeSPatrick Mooney usb2_port = sc->usb2_port_start - 1; 2649*4c87aefeSPatrick Mooney devices = NULL; 2650*4c87aefeSPatrick Mooney 2651*4c87aefeSPatrick Mooney if (opts == NULL) 2652*4c87aefeSPatrick Mooney goto portsfinal; 2653*4c87aefeSPatrick Mooney 2654*4c87aefeSPatrick Mooney devices = calloc(XHCI_MAX_DEVS, sizeof(struct pci_xhci_dev_emu *)); 2655*4c87aefeSPatrick Mooney 2656*4c87aefeSPatrick Mooney sc->slots = calloc(XHCI_MAX_SLOTS, sizeof(struct pci_xhci_dev_emu *)); 2657*4c87aefeSPatrick Mooney sc->devices = devices; 2658*4c87aefeSPatrick Mooney sc->ndevices = 0; 2659*4c87aefeSPatrick Mooney 2660*4c87aefeSPatrick Mooney uopt = strdup(opts); 2661*4c87aefeSPatrick Mooney for (xopts = strtok(uopt, ","); 2662*4c87aefeSPatrick Mooney xopts != NULL; 2663*4c87aefeSPatrick Mooney xopts = strtok(NULL, ",")) { 2664*4c87aefeSPatrick Mooney if (usb2_port == ((sc->usb2_port_start-1) + XHCI_MAX_DEVS/2) || 2665*4c87aefeSPatrick Mooney usb3_port == ((sc->usb3_port_start-1) + XHCI_MAX_DEVS/2)) { 2666*4c87aefeSPatrick Mooney WPRINTF(("pci_xhci max number of USB 2 or 3 " 2667*4c87aefeSPatrick Mooney "devices reached, max %d\r\n", XHCI_MAX_DEVS/2)); 2668*4c87aefeSPatrick Mooney usb2_port = usb3_port = -1; 2669*4c87aefeSPatrick Mooney goto done; 2670*4c87aefeSPatrick Mooney } 2671*4c87aefeSPatrick Mooney 2672*4c87aefeSPatrick Mooney /* device[=<config>] */ 2673*4c87aefeSPatrick Mooney if ((config = strchr(xopts, '=')) == NULL) 2674*4c87aefeSPatrick Mooney config = ""; /* no config */ 2675*4c87aefeSPatrick Mooney else 2676*4c87aefeSPatrick Mooney *config++ = '\0'; 2677*4c87aefeSPatrick Mooney 2678*4c87aefeSPatrick Mooney ue = usb_emu_finddev(xopts); 2679*4c87aefeSPatrick Mooney if (ue == NULL) { 2680*4c87aefeSPatrick Mooney pci_xhci_device_usage(xopts); 2681*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci device not found %s\r\n", xopts)); 2682*4c87aefeSPatrick Mooney usb2_port = usb3_port = -1; 2683*4c87aefeSPatrick Mooney goto done; 2684*4c87aefeSPatrick Mooney } 2685*4c87aefeSPatrick Mooney 2686*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci adding device %s, opts \"%s\"\r\n", 2687*4c87aefeSPatrick Mooney xopts, config)); 2688*4c87aefeSPatrick Mooney 2689*4c87aefeSPatrick Mooney dev = calloc(1, sizeof(struct pci_xhci_dev_emu)); 2690*4c87aefeSPatrick Mooney dev->xsc = sc; 2691*4c87aefeSPatrick Mooney dev->hci.hci_sc = dev; 2692*4c87aefeSPatrick Mooney dev->hci.hci_intr = pci_xhci_dev_intr; 2693*4c87aefeSPatrick Mooney dev->hci.hci_event = pci_xhci_dev_event; 2694*4c87aefeSPatrick Mooney 2695*4c87aefeSPatrick Mooney if (ue->ue_usbver == 2) { 2696*4c87aefeSPatrick Mooney dev->hci.hci_port = usb2_port + 1; 2697*4c87aefeSPatrick Mooney devices[usb2_port] = dev; 2698*4c87aefeSPatrick Mooney usb2_port++; 2699*4c87aefeSPatrick Mooney } else { 2700*4c87aefeSPatrick Mooney dev->hci.hci_port = usb3_port + 1; 2701*4c87aefeSPatrick Mooney devices[usb3_port] = dev; 2702*4c87aefeSPatrick Mooney usb3_port++; 2703*4c87aefeSPatrick Mooney } 2704*4c87aefeSPatrick Mooney 2705*4c87aefeSPatrick Mooney dev->hci.hci_address = 0; 2706*4c87aefeSPatrick Mooney devsc = ue->ue_init(&dev->hci, config); 2707*4c87aefeSPatrick Mooney if (devsc == NULL) { 2708*4c87aefeSPatrick Mooney pci_xhci_device_usage(xopts); 2709*4c87aefeSPatrick Mooney usb2_port = usb3_port = -1; 2710*4c87aefeSPatrick Mooney goto done; 2711*4c87aefeSPatrick Mooney } 2712*4c87aefeSPatrick Mooney 2713*4c87aefeSPatrick Mooney dev->dev_ue = ue; 2714*4c87aefeSPatrick Mooney dev->dev_sc = devsc; 2715*4c87aefeSPatrick Mooney 2716*4c87aefeSPatrick Mooney /* assign slot number to device */ 2717*4c87aefeSPatrick Mooney sc->slots[sc->ndevices] = dev; 2718*4c87aefeSPatrick Mooney 2719*4c87aefeSPatrick Mooney sc->ndevices++; 2720*4c87aefeSPatrick Mooney } 2721*4c87aefeSPatrick Mooney 2722*4c87aefeSPatrick Mooney portsfinal: 2723*4c87aefeSPatrick Mooney sc->portregs = calloc(XHCI_MAX_DEVS, sizeof(struct pci_xhci_portregs)); 2724*4c87aefeSPatrick Mooney 2725*4c87aefeSPatrick Mooney if (sc->ndevices > 0) { 2726*4c87aefeSPatrick Mooney /* port and slot numbering start from 1 */ 2727*4c87aefeSPatrick Mooney sc->devices--; 2728*4c87aefeSPatrick Mooney sc->portregs--; 2729*4c87aefeSPatrick Mooney sc->slots--; 2730*4c87aefeSPatrick Mooney 2731*4c87aefeSPatrick Mooney for (i = 1; i <= XHCI_MAX_DEVS; i++) { 2732*4c87aefeSPatrick Mooney pci_xhci_init_port(sc, i); 2733*4c87aefeSPatrick Mooney } 2734*4c87aefeSPatrick Mooney } else { 2735*4c87aefeSPatrick Mooney WPRINTF(("pci_xhci no USB devices configured\r\n")); 2736*4c87aefeSPatrick Mooney sc->ndevices = 1; 2737*4c87aefeSPatrick Mooney } 2738*4c87aefeSPatrick Mooney 2739*4c87aefeSPatrick Mooney done: 2740*4c87aefeSPatrick Mooney if (devices != NULL) { 2741*4c87aefeSPatrick Mooney if (usb2_port <= 0 && usb3_port <= 0) { 2742*4c87aefeSPatrick Mooney sc->devices = NULL; 2743*4c87aefeSPatrick Mooney for (i = 0; devices[i] != NULL; i++) 2744*4c87aefeSPatrick Mooney free(devices[i]); 2745*4c87aefeSPatrick Mooney sc->ndevices = -1; 2746*4c87aefeSPatrick Mooney 2747*4c87aefeSPatrick Mooney free(devices); 2748*4c87aefeSPatrick Mooney } 2749*4c87aefeSPatrick Mooney } 2750*4c87aefeSPatrick Mooney free(uopt); 2751*4c87aefeSPatrick Mooney return (sc->ndevices); 2752*4c87aefeSPatrick Mooney } 2753*4c87aefeSPatrick Mooney 2754*4c87aefeSPatrick Mooney static int 2755*4c87aefeSPatrick Mooney pci_xhci_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) 2756*4c87aefeSPatrick Mooney { 2757*4c87aefeSPatrick Mooney struct pci_xhci_softc *sc; 2758*4c87aefeSPatrick Mooney int error; 2759*4c87aefeSPatrick Mooney 2760*4c87aefeSPatrick Mooney if (xhci_in_use) { 2761*4c87aefeSPatrick Mooney WPRINTF(("pci_xhci controller already defined\r\n")); 2762*4c87aefeSPatrick Mooney return (-1); 2763*4c87aefeSPatrick Mooney } 2764*4c87aefeSPatrick Mooney xhci_in_use = 1; 2765*4c87aefeSPatrick Mooney 2766*4c87aefeSPatrick Mooney sc = calloc(1, sizeof(struct pci_xhci_softc)); 2767*4c87aefeSPatrick Mooney pi->pi_arg = sc; 2768*4c87aefeSPatrick Mooney sc->xsc_pi = pi; 2769*4c87aefeSPatrick Mooney 2770*4c87aefeSPatrick Mooney sc->usb2_port_start = (XHCI_MAX_DEVS/2) + 1; 2771*4c87aefeSPatrick Mooney sc->usb3_port_start = 1; 2772*4c87aefeSPatrick Mooney 2773*4c87aefeSPatrick Mooney /* discover devices */ 2774*4c87aefeSPatrick Mooney error = pci_xhci_parse_opts(sc, opts); 2775*4c87aefeSPatrick Mooney if (error < 0) 2776*4c87aefeSPatrick Mooney goto done; 2777*4c87aefeSPatrick Mooney else 2778*4c87aefeSPatrick Mooney error = 0; 2779*4c87aefeSPatrick Mooney 2780*4c87aefeSPatrick Mooney sc->caplength = XHCI_SET_CAPLEN(XHCI_CAPLEN) | 2781*4c87aefeSPatrick Mooney XHCI_SET_HCIVERSION(0x0100); 2782*4c87aefeSPatrick Mooney sc->hcsparams1 = XHCI_SET_HCSP1_MAXPORTS(XHCI_MAX_DEVS) | 2783*4c87aefeSPatrick Mooney XHCI_SET_HCSP1_MAXINTR(1) | /* interrupters */ 2784*4c87aefeSPatrick Mooney XHCI_SET_HCSP1_MAXSLOTS(XHCI_MAX_SLOTS); 2785*4c87aefeSPatrick Mooney sc->hcsparams2 = XHCI_SET_HCSP2_ERSTMAX(XHCI_ERST_MAX) | 2786*4c87aefeSPatrick Mooney XHCI_SET_HCSP2_IST(0x04); 2787*4c87aefeSPatrick Mooney sc->hcsparams3 = 0; /* no latency */ 2788*4c87aefeSPatrick Mooney sc->hccparams1 = XHCI_SET_HCCP1_NSS(1) | /* no 2nd-streams */ 2789*4c87aefeSPatrick Mooney XHCI_SET_HCCP1_SPC(1) | /* short packet */ 2790*4c87aefeSPatrick Mooney XHCI_SET_HCCP1_MAXPSA(XHCI_STREAMS_MAX); 2791*4c87aefeSPatrick Mooney sc->hccparams2 = XHCI_SET_HCCP2_LEC(1) | 2792*4c87aefeSPatrick Mooney XHCI_SET_HCCP2_U3C(1); 2793*4c87aefeSPatrick Mooney sc->dboff = XHCI_SET_DOORBELL(XHCI_CAPLEN + XHCI_PORTREGS_START + 2794*4c87aefeSPatrick Mooney XHCI_MAX_DEVS * sizeof(struct pci_xhci_portregs)); 2795*4c87aefeSPatrick Mooney 2796*4c87aefeSPatrick Mooney /* dboff must be 32-bit aligned */ 2797*4c87aefeSPatrick Mooney if (sc->dboff & 0x3) 2798*4c87aefeSPatrick Mooney sc->dboff = (sc->dboff + 0x3) & ~0x3; 2799*4c87aefeSPatrick Mooney 2800*4c87aefeSPatrick Mooney /* rtsoff must be 32-bytes aligned */ 2801*4c87aefeSPatrick Mooney sc->rtsoff = XHCI_SET_RTSOFFSET(sc->dboff + (XHCI_MAX_SLOTS+1) * 32); 2802*4c87aefeSPatrick Mooney if (sc->rtsoff & 0x1F) 2803*4c87aefeSPatrick Mooney sc->rtsoff = (sc->rtsoff + 0x1F) & ~0x1F; 2804*4c87aefeSPatrick Mooney 2805*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci dboff: 0x%x, rtsoff: 0x%x\r\n", sc->dboff, 2806*4c87aefeSPatrick Mooney sc->rtsoff)); 2807*4c87aefeSPatrick Mooney 2808*4c87aefeSPatrick Mooney sc->opregs.usbsts = XHCI_STS_HCH; 2809*4c87aefeSPatrick Mooney sc->opregs.pgsz = XHCI_PAGESIZE_4K; 2810*4c87aefeSPatrick Mooney 2811*4c87aefeSPatrick Mooney pci_xhci_reset(sc); 2812*4c87aefeSPatrick Mooney 2813*4c87aefeSPatrick Mooney sc->regsend = sc->rtsoff + 0x20 + 32; /* only 1 intrpter */ 2814*4c87aefeSPatrick Mooney 2815*4c87aefeSPatrick Mooney /* 2816*4c87aefeSPatrick Mooney * Set extended capabilities pointer to be after regsend; 2817*4c87aefeSPatrick Mooney * value of xecp field is 32-bit offset. 2818*4c87aefeSPatrick Mooney */ 2819*4c87aefeSPatrick Mooney sc->hccparams1 |= XHCI_SET_HCCP1_XECP(sc->regsend/4); 2820*4c87aefeSPatrick Mooney 2821*4c87aefeSPatrick Mooney pci_set_cfgdata16(pi, PCIR_DEVICE, 0x1E31); 2822*4c87aefeSPatrick Mooney pci_set_cfgdata16(pi, PCIR_VENDOR, 0x8086); 2823*4c87aefeSPatrick Mooney pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_SERIALBUS); 2824*4c87aefeSPatrick Mooney pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_SERIALBUS_USB); 2825*4c87aefeSPatrick Mooney pci_set_cfgdata8(pi, PCIR_PROGIF,PCIP_SERIALBUS_USB_XHCI); 2826*4c87aefeSPatrick Mooney pci_set_cfgdata8(pi, PCI_USBREV, PCI_USB_REV_3_0); 2827*4c87aefeSPatrick Mooney 2828*4c87aefeSPatrick Mooney pci_emul_add_msicap(pi, 1); 2829*4c87aefeSPatrick Mooney 2830*4c87aefeSPatrick Mooney /* regsend + xecp registers */ 2831*4c87aefeSPatrick Mooney pci_emul_alloc_bar(pi, 0, PCIBAR_MEM32, sc->regsend + 4*32); 2832*4c87aefeSPatrick Mooney DPRINTF(("pci_xhci pci_emu_alloc: %d\r\n", sc->regsend + 4*32)); 2833*4c87aefeSPatrick Mooney 2834*4c87aefeSPatrick Mooney 2835*4c87aefeSPatrick Mooney pci_lintr_request(pi); 2836*4c87aefeSPatrick Mooney 2837*4c87aefeSPatrick Mooney pthread_mutex_init(&sc->mtx, NULL); 2838*4c87aefeSPatrick Mooney 2839*4c87aefeSPatrick Mooney done: 2840*4c87aefeSPatrick Mooney if (error) { 2841*4c87aefeSPatrick Mooney free(sc); 2842*4c87aefeSPatrick Mooney } 2843*4c87aefeSPatrick Mooney 2844*4c87aefeSPatrick Mooney return (error); 2845*4c87aefeSPatrick Mooney } 2846*4c87aefeSPatrick Mooney 2847*4c87aefeSPatrick Mooney 2848*4c87aefeSPatrick Mooney 2849*4c87aefeSPatrick Mooney struct pci_devemu pci_de_xhci = { 2850*4c87aefeSPatrick Mooney .pe_emu = "xhci", 2851*4c87aefeSPatrick Mooney .pe_init = pci_xhci_init, 2852*4c87aefeSPatrick Mooney .pe_barwrite = pci_xhci_write, 2853*4c87aefeSPatrick Mooney .pe_barread = pci_xhci_read 2854*4c87aefeSPatrick Mooney }; 2855*4c87aefeSPatrick Mooney PCI_EMUL_SET(pci_de_xhci); 2856