1*9d524485Skettenis /* $OpenBSD: ehcivar.h,v 1.37 2016/10/02 06:36:39 kettenis Exp $ */ 2f51a9b2fSpascoe /* $NetBSD: ehcivar.h,v 1.19 2005/04/29 15:04:29 augustss Exp $ */ 38e3f8616Sderaadt 48e3f8616Sderaadt /* 58e3f8616Sderaadt * Copyright (c) 2001 The NetBSD Foundation, Inc. 68e3f8616Sderaadt * All rights reserved. 78e3f8616Sderaadt * 88e3f8616Sderaadt * This code is derived from software contributed to The NetBSD Foundation 98e3f8616Sderaadt * by Lennart Augustsson (lennart@augustsson.net). 108e3f8616Sderaadt * 118e3f8616Sderaadt * Redistribution and use in source and binary forms, with or without 128e3f8616Sderaadt * modification, are permitted provided that the following conditions 138e3f8616Sderaadt * are met: 148e3f8616Sderaadt * 1. Redistributions of source code must retain the above copyright 158e3f8616Sderaadt * notice, this list of conditions and the following disclaimer. 168e3f8616Sderaadt * 2. Redistributions in binary form must reproduce the above copyright 178e3f8616Sderaadt * notice, this list of conditions and the following disclaimer in the 188e3f8616Sderaadt * documentation and/or other materials provided with the distribution. 198e3f8616Sderaadt * 208e3f8616Sderaadt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 218e3f8616Sderaadt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 228e3f8616Sderaadt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 238e3f8616Sderaadt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 248e3f8616Sderaadt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 258e3f8616Sderaadt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 268e3f8616Sderaadt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 278e3f8616Sderaadt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 288e3f8616Sderaadt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 298e3f8616Sderaadt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 308e3f8616Sderaadt * POSSIBILITY OF SUCH DAMAGE. 318e3f8616Sderaadt */ 328e3f8616Sderaadt 33ab0b1be7Smglocker struct ehci_soft_qtd { 34ab0b1be7Smglocker struct ehci_qtd qtd; 358e3f8616Sderaadt struct ehci_soft_qtd *nextqtd; /* mirrors nextqtd in TD */ 368e3f8616Sderaadt ehci_physaddr_t physaddr; 37ab0b1be7Smglocker struct usb_dma dma; /* qTD's DMA infos */ 38ab0b1be7Smglocker int offs; /* qTD's offset in struct usb_dma */ 398e3f8616Sderaadt LIST_ENTRY(ehci_soft_qtd) hnext; 408e3f8616Sderaadt u_int16_t len; 41ab0b1be7Smglocker }; 428e3f8616Sderaadt #define EHCI_SQTD_SIZE ((sizeof (struct ehci_soft_qtd) + EHCI_QTD_ALIGN - 1) / EHCI_QTD_ALIGN * EHCI_QTD_ALIGN) 438e3f8616Sderaadt #define EHCI_SQTD_CHUNK (EHCI_PAGE_SIZE / EHCI_SQTD_SIZE) 448e3f8616Sderaadt 45ab0b1be7Smglocker struct ehci_soft_qh { 46ab0b1be7Smglocker struct ehci_qh qh; 478e3f8616Sderaadt struct ehci_soft_qh *next; 48f51a9b2fSpascoe struct ehci_soft_qh *prev; 498e3f8616Sderaadt struct ehci_soft_qtd *sqtd; 508e3f8616Sderaadt ehci_physaddr_t physaddr; 51ab0b1be7Smglocker struct usb_dma dma; /* QH's DMA infos */ 52ab0b1be7Smglocker int offs; /* QH's offset in struct usb_dma */ 532bbf6894Sdlg int islot; 54ab0b1be7Smglocker }; 558e3f8616Sderaadt #define EHCI_SQH_SIZE ((sizeof (struct ehci_soft_qh) + EHCI_QH_ALIGN - 1) / EHCI_QH_ALIGN * EHCI_QH_ALIGN) 568e3f8616Sderaadt #define EHCI_SQH_CHUNK (EHCI_PAGE_SIZE / EHCI_SQH_SIZE) 578e3f8616Sderaadt 58ab0b1be7Smglocker struct ehci_soft_itd { 59f0ce5612Smpi union { 60ab0b1be7Smglocker struct ehci_itd itd; 61f0ce5612Smpi struct ehci_sitd sitd; 62f0ce5612Smpi }; 63532eeba4Smglocker union { 64532eeba4Smglocker struct { 65532eeba4Smglocker /* soft_itds links in a periodic frame*/ 66532eeba4Smglocker struct ehci_soft_itd *next; 67532eeba4Smglocker struct ehci_soft_itd *prev; 68532eeba4Smglocker } frame_list; 69532eeba4Smglocker /* circular list of free itds */ 70532eeba4Smglocker LIST_ENTRY(ehci_soft_itd) free_list; 71532eeba4Smglocker } u; 72532eeba4Smglocker struct ehci_soft_itd *xfer_next; /* Next soft_itd in xfer */ 73532eeba4Smglocker ehci_physaddr_t physaddr; 74ab0b1be7Smglocker struct usb_dma dma; 75532eeba4Smglocker int offs; 76532eeba4Smglocker int slot; 77532eeba4Smglocker struct timeval t; /* store free time */ 78ab0b1be7Smglocker }; 79532eeba4Smglocker #define EHCI_ITD_SIZE ((sizeof(struct ehci_soft_itd) + EHCI_QH_ALIGN - 1) / EHCI_ITD_ALIGN * EHCI_ITD_ALIGN) 80532eeba4Smglocker #define EHCI_ITD_CHUNK (EHCI_PAGE_SIZE / EHCI_ITD_SIZE) 81532eeba4Smglocker 828e3f8616Sderaadt struct ehci_xfer { 838e3f8616Sderaadt struct usbd_xfer xfer; 84f0ce5612Smpi TAILQ_ENTRY(ehci_xfer) inext; /* List of active xfers */ 85f0ce5612Smpi union { 86f0ce5612Smpi struct { 87f0ce5612Smpi struct ehci_soft_qtd *start, *end; 88f0ce5612Smpi } sqtd; /* Ctrl/Bulk/Interrupt TD */ 89f0ce5612Smpi struct { 90f0ce5612Smpi struct ehci_soft_itd *start, *end; 91f0ce5612Smpi } itd; /* Isochronous TD */ 92f0ce5612Smpi } _TD; 93f0ce5612Smpi #define sqtdstart _TD.sqtd.start 94f0ce5612Smpi #define sqtdend _TD.sqtd.end 95f0ce5612Smpi #define itdstart _TD.itd.start 96f0ce5612Smpi #define itdend _TD.itd.end 97f0ce5612Smpi 98f0ce5612Smpi uint32_t ehci_xfer_flags; 998e3f8616Sderaadt #ifdef DIAGNOSTIC 1008e3f8616Sderaadt int isdone; 1018e3f8616Sderaadt #endif 1028e3f8616Sderaadt }; 103f51a9b2fSpascoe #define EHCI_XFER_ABORTING 0x0001 /* xfer is aborting. */ 104f51a9b2fSpascoe #define EHCI_XFER_ABORTWAIT 0x0002 /* abort completion is being awaited. */ 105f51a9b2fSpascoe 1062bbf6894Sdlg /* Information about an entry in the interrupt list. */ 1072bbf6894Sdlg struct ehci_soft_islot { 108ab0b1be7Smglocker struct ehci_soft_qh *sqh; /* Queue Head. */ 1092bbf6894Sdlg }; 1102bbf6894Sdlg 1112bbf6894Sdlg #define EHCI_FRAMELIST_MAXCOUNT 1024 1122bbf6894Sdlg #define EHCI_IPOLLRATES 8 /* Poll rates (1ms, 2, 4, 8 .. 128) */ 1132bbf6894Sdlg #define EHCI_INTRQHS ((1 << EHCI_IPOLLRATES) - 1) 1142bbf6894Sdlg #define EHCI_IQHIDX(lev, pos) \ 1152bbf6894Sdlg ((((pos) & ((1 << (lev)) - 1)) | (1 << (lev))) - 1) 1162bbf6894Sdlg #define EHCI_ILEV_IVAL(lev) (1 << (lev)) 1172bbf6894Sdlg 1188e3f8616Sderaadt 1198e3f8616Sderaadt #define EHCI_HASH_SIZE 128 1208e3f8616Sderaadt #define EHCI_COMPANION_MAX 8 1218e3f8616Sderaadt 122532eeba4Smglocker #define EHCI_FREE_LIST_INTERVAL 100 123532eeba4Smglocker 124ab0b1be7Smglocker struct ehci_softc { 1258e3f8616Sderaadt struct usbd_bus sc_bus; /* base device */ 1268e3f8616Sderaadt bus_space_tag_t iot; 1278e3f8616Sderaadt bus_space_handle_t ioh; 1288e3f8616Sderaadt bus_size_t sc_size; 1298e3f8616Sderaadt u_int sc_offs; /* offset to operational regs */ 130951a7db3Spascoe int sc_flags; /* misc flags */ 131951a7db3Spascoe #define EHCIF_DROPPED_INTR_WORKAROUND 0x01 1320d8c8f4eSmpi #define EHCIF_PCB_INTR 0x02 133*9d524485Skettenis #define EHCIF_USBMODE 0x04 1348e3f8616Sderaadt 1358e3f8616Sderaadt char sc_vendor[16]; /* vendor string for root hub */ 1368e3f8616Sderaadt int sc_id_vendor; /* vendor ID for root hub */ 1378e3f8616Sderaadt 138ab0b1be7Smglocker struct usb_dma sc_fldma; 1392bbf6894Sdlg ehci_link_t *sc_flist; 1408e3f8616Sderaadt u_int sc_flsize; 1412bbf6894Sdlg 1422bbf6894Sdlg struct ehci_soft_islot sc_islots[EHCI_INTRQHS]; 1438e3f8616Sderaadt 144532eeba4Smglocker /* jcmm - an array matching sc_flist, but with software pointers, 145532eeba4Smglocker * not hardware address pointers 146532eeba4Smglocker */ 147532eeba4Smglocker struct ehci_soft_itd **sc_softitds; 148532eeba4Smglocker 1492fcae2bbSmglocker TAILQ_HEAD(, ehci_xfer) sc_intrhead; 1508e3f8616Sderaadt 151ab0b1be7Smglocker struct ehci_soft_qh *sc_freeqhs; 152ab0b1be7Smglocker struct ehci_soft_qtd *sc_freeqtds; 153532eeba4Smglocker LIST_HEAD(sc_freeitds, ehci_soft_itd) sc_freeitds; 1548e3f8616Sderaadt 1558e3f8616Sderaadt int sc_noport; 1568e3f8616Sderaadt u_int8_t sc_conf; /* device configuration */ 157ab0b1be7Smglocker struct usbd_xfer *sc_intrxfer; 1588e3f8616Sderaadt char sc_isreset; 1598e3f8616Sderaadt char sc_softwake; 1608e3f8616Sderaadt 1618e3f8616Sderaadt u_int32_t sc_eintrs; 162ab0b1be7Smglocker struct ehci_soft_qh *sc_async_head; 1638e3f8616Sderaadt 164b06716e1Sjsg struct rwlock sc_doorbell_lock; 1658e3f8616Sderaadt 16634eef271Smbalmer struct timeout sc_tmo_intrlist; 167ab0b1be7Smglocker }; 1688e3f8616Sderaadt 1698e3f8616Sderaadt #define EREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (a)) 1708e3f8616Sderaadt #define EREAD2(sc, a) bus_space_read_2((sc)->iot, (sc)->ioh, (a)) 1718e3f8616Sderaadt #define EREAD4(sc, a) bus_space_read_4((sc)->iot, (sc)->ioh, (a)) 1728e3f8616Sderaadt #define EWRITE1(sc, a, x) bus_space_write_1((sc)->iot, (sc)->ioh, (a), (x)) 1738e3f8616Sderaadt #define EWRITE2(sc, a, x) bus_space_write_2((sc)->iot, (sc)->ioh, (a), (x)) 1748e3f8616Sderaadt #define EWRITE4(sc, a, x) bus_space_write_4((sc)->iot, (sc)->ioh, (a), (x)) 1758e3f8616Sderaadt #define EOREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a)) 1768e3f8616Sderaadt #define EOREAD2(sc, a) bus_space_read_2((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a)) 1778e3f8616Sderaadt #define EOREAD4(sc, a) bus_space_read_4((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a)) 1788e3f8616Sderaadt #define EOWRITE1(sc, a, x) bus_space_write_1((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x)) 1798e3f8616Sderaadt #define EOWRITE2(sc, a, x) bus_space_write_2((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x)) 1808e3f8616Sderaadt #define EOWRITE4(sc, a, x) bus_space_write_4((sc)->iot, (sc)->ioh, (sc)->sc_offs+(a), (x)) 1818e3f8616Sderaadt 182ab0b1be7Smglocker usbd_status ehci_init(struct ehci_softc *); 1838e3f8616Sderaadt int ehci_intr(void *); 18444fe0a2dSmpi int ehci_detach(struct device *, int); 185e78728c7Spirofti int ehci_activate(struct device *, int); 186425a4fc5Smpi usbd_status ehci_reset(struct ehci_softc *); 187425a4fc5Smpi 188