1 /* $OpenBSD: ehcivar.h,v 1.37 2016/10/02 06:36:39 kettenis Exp $ */ 2 /* $NetBSD: ehcivar.h,v 1.19 2005/04/29 15:04:29 augustss Exp $ */ 3 4 /* 5 * Copyright (c) 2001 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Lennart Augustsson (lennart@augustsson.net). 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 struct ehci_soft_qtd { 34 struct ehci_qtd qtd; 35 struct ehci_soft_qtd *nextqtd; /* mirrors nextqtd in TD */ 36 ehci_physaddr_t physaddr; 37 struct usb_dma dma; /* qTD's DMA infos */ 38 int offs; /* qTD's offset in struct usb_dma */ 39 LIST_ENTRY(ehci_soft_qtd) hnext; 40 u_int16_t len; 41 }; 42 #define EHCI_SQTD_SIZE ((sizeof (struct ehci_soft_qtd) + EHCI_QTD_ALIGN - 1) / EHCI_QTD_ALIGN * EHCI_QTD_ALIGN) 43 #define EHCI_SQTD_CHUNK (EHCI_PAGE_SIZE / EHCI_SQTD_SIZE) 44 45 struct ehci_soft_qh { 46 struct ehci_qh qh; 47 struct ehci_soft_qh *next; 48 struct ehci_soft_qh *prev; 49 struct ehci_soft_qtd *sqtd; 50 ehci_physaddr_t physaddr; 51 struct usb_dma dma; /* QH's DMA infos */ 52 int offs; /* QH's offset in struct usb_dma */ 53 int islot; 54 }; 55 #define EHCI_SQH_SIZE ((sizeof (struct ehci_soft_qh) + EHCI_QH_ALIGN - 1) / EHCI_QH_ALIGN * EHCI_QH_ALIGN) 56 #define EHCI_SQH_CHUNK (EHCI_PAGE_SIZE / EHCI_SQH_SIZE) 57 58 struct ehci_soft_itd { 59 union { 60 struct ehci_itd itd; 61 struct ehci_sitd sitd; 62 }; 63 union { 64 struct { 65 /* soft_itds links in a periodic frame*/ 66 struct ehci_soft_itd *next; 67 struct ehci_soft_itd *prev; 68 } frame_list; 69 /* circular list of free itds */ 70 LIST_ENTRY(ehci_soft_itd) free_list; 71 } u; 72 struct ehci_soft_itd *xfer_next; /* Next soft_itd in xfer */ 73 ehci_physaddr_t physaddr; 74 struct usb_dma dma; 75 int offs; 76 int slot; 77 struct timeval t; /* store free time */ 78 }; 79 #define EHCI_ITD_SIZE ((sizeof(struct ehci_soft_itd) + EHCI_QH_ALIGN - 1) / EHCI_ITD_ALIGN * EHCI_ITD_ALIGN) 80 #define EHCI_ITD_CHUNK (EHCI_PAGE_SIZE / EHCI_ITD_SIZE) 81 82 struct ehci_xfer { 83 struct usbd_xfer xfer; 84 TAILQ_ENTRY(ehci_xfer) inext; /* List of active xfers */ 85 union { 86 struct { 87 struct ehci_soft_qtd *start, *end; 88 } sqtd; /* Ctrl/Bulk/Interrupt TD */ 89 struct { 90 struct ehci_soft_itd *start, *end; 91 } itd; /* Isochronous TD */ 92 } _TD; 93 #define sqtdstart _TD.sqtd.start 94 #define sqtdend _TD.sqtd.end 95 #define itdstart _TD.itd.start 96 #define itdend _TD.itd.end 97 98 uint32_t ehci_xfer_flags; 99 #ifdef DIAGNOSTIC 100 int isdone; 101 #endif 102 }; 103 #define EHCI_XFER_ABORTING 0x0001 /* xfer is aborting. */ 104 #define EHCI_XFER_ABORTWAIT 0x0002 /* abort completion is being awaited. */ 105 106 /* Information about an entry in the interrupt list. */ 107 struct ehci_soft_islot { 108 struct ehci_soft_qh *sqh; /* Queue Head. */ 109 }; 110 111 #define EHCI_FRAMELIST_MAXCOUNT 1024 112 #define EHCI_IPOLLRATES 8 /* Poll rates (1ms, 2, 4, 8 .. 128) */ 113 #define EHCI_INTRQHS ((1 << EHCI_IPOLLRATES) - 1) 114 #define EHCI_IQHIDX(lev, pos) \ 115 ((((pos) & ((1 << (lev)) - 1)) | (1 << (lev))) - 1) 116 #define EHCI_ILEV_IVAL(lev) (1 << (lev)) 117 118 119 #define EHCI_HASH_SIZE 128 120 #define EHCI_COMPANION_MAX 8 121 122 #define EHCI_FREE_LIST_INTERVAL 100 123 124 struct ehci_softc { 125 struct usbd_bus sc_bus; /* base device */ 126 bus_space_tag_t iot; 127 bus_space_handle_t ioh; 128 bus_size_t sc_size; 129 u_int sc_offs; /* offset to operational regs */ 130 int sc_flags; /* misc flags */ 131 #define EHCIF_DROPPED_INTR_WORKAROUND 0x01 132 #define EHCIF_PCB_INTR 0x02 133 #define EHCIF_USBMODE 0x04 134 135 char sc_vendor[16]; /* vendor string for root hub */ 136 int sc_id_vendor; /* vendor ID for root hub */ 137 138 struct usb_dma sc_fldma; 139 ehci_link_t *sc_flist; 140 u_int sc_flsize; 141 142 struct ehci_soft_islot sc_islots[EHCI_INTRQHS]; 143 144 /* jcmm - an array matching sc_flist, but with software pointers, 145 * not hardware address pointers 146 */ 147 struct ehci_soft_itd **sc_softitds; 148 149 TAILQ_HEAD(, ehci_xfer) sc_intrhead; 150 151 struct ehci_soft_qh *sc_freeqhs; 152 struct ehci_soft_qtd *sc_freeqtds; 153 LIST_HEAD(sc_freeitds, ehci_soft_itd) sc_freeitds; 154 155 int sc_noport; 156 u_int8_t sc_conf; /* device configuration */ 157 struct usbd_xfer *sc_intrxfer; 158 char sc_isreset; 159 char sc_softwake; 160 161 u_int32_t sc_eintrs; 162 struct ehci_soft_qh *sc_async_head; 163 164 struct rwlock sc_doorbell_lock; 165 166 struct timeout sc_tmo_intrlist; 167 }; 168 169 #define EREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (a)) 170 #define EREAD2(sc, a) bus_space_read_2((sc)->iot, (sc)->ioh, (a)) 171 #define EREAD4(sc, a) bus_space_read_4((sc)->iot, (sc)->ioh, (a)) 172 #define EWRITE1(sc, a, x) bus_space_write_1((sc)->iot, (sc)->ioh, (a), (x)) 173 #define EWRITE2(sc, a, x) bus_space_write_2((sc)->iot, (sc)->ioh, (a), (x)) 174 #define EWRITE4(sc, a, x) bus_space_write_4((sc)->iot, (sc)->ioh, (a), (x)) 175 #define EOREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a)) 176 #define EOREAD2(sc, a) bus_space_read_2((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a)) 177 #define EOREAD4(sc, a) bus_space_read_4((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a)) 178 #define EOWRITE1(sc, a, x) bus_space_write_1((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x)) 179 #define EOWRITE2(sc, a, x) bus_space_write_2((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x)) 180 #define EOWRITE4(sc, a, x) bus_space_write_4((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x)) 181 182 usbd_status ehci_init(struct ehci_softc *); 183 int ehci_intr(void *); 184 int ehci_detach(struct device *, int); 185 int ehci_activate(struct device *, int); 186 usbd_status ehci_reset(struct ehci_softc *); 187 188