1*ca68072aSmpi /* $OpenBSD: uhcivar.h,v 1.33 2014/05/18 17:10:27 mpi Exp $ */ 272a11251Snate /* $NetBSD: uhcivar.h,v 1.36 2002/12/31 00:39:11 augustss Exp $ */ 35deafb75Saaron /* $FreeBSD: src/sys/dev/usb/uhcivar.h,v 1.14 1999/11/17 22:33:42 n_hibma Exp $ */ 412fe8f0eSfgsch 512fe8f0eSfgsch /* 612fe8f0eSfgsch * Copyright (c) 1998 The NetBSD Foundation, Inc. 712fe8f0eSfgsch * All rights reserved. 812fe8f0eSfgsch * 912fe8f0eSfgsch * This code is derived from software contributed to The NetBSD Foundation 1082426cf3Sfgsch * by Lennart Augustsson (lennart@augustsson.net) at 1112fe8f0eSfgsch * Carlstedt Research & Technology. 1212fe8f0eSfgsch * 1312fe8f0eSfgsch * Redistribution and use in source and binary forms, with or without 1412fe8f0eSfgsch * modification, are permitted provided that the following conditions 1512fe8f0eSfgsch * are met: 1612fe8f0eSfgsch * 1. Redistributions of source code must retain the above copyright 1712fe8f0eSfgsch * notice, this list of conditions and the following disclaimer. 1812fe8f0eSfgsch * 2. Redistributions in binary form must reproduce the above copyright 1912fe8f0eSfgsch * notice, this list of conditions and the following disclaimer in the 2012fe8f0eSfgsch * documentation and/or other materials provided with the distribution. 2112fe8f0eSfgsch * 2212fe8f0eSfgsch * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2312fe8f0eSfgsch * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2412fe8f0eSfgsch * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2512fe8f0eSfgsch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2612fe8f0eSfgsch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2712fe8f0eSfgsch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2812fe8f0eSfgsch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2912fe8f0eSfgsch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3012fe8f0eSfgsch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3112fe8f0eSfgsch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3212fe8f0eSfgsch * POSSIBILITY OF SUCH DAMAGE. 3312fe8f0eSfgsch */ 3412fe8f0eSfgsch 3512fe8f0eSfgsch /* 3612fe8f0eSfgsch * To avoid having 1024 TDs for each isochronous transfer we introduce 3712fe8f0eSfgsch * a virtual frame list. Every UHCI_VFRAMELIST_COUNT entries in the real 38bcc0e93aSaaron * frame list points to a non-active TD. These, in turn, form the 3912fe8f0eSfgsch * starts of the virtual frame list. This also has the advantage that it 40bcc0e93aSaaron * simplifies linking in/out of TDs/QHs in the schedule. 4112fe8f0eSfgsch * Furthermore, initially each of the inactive TDs point to an inactive 4212fe8f0eSfgsch * QH that forms the start of the interrupt traffic for that slot. 4312fe8f0eSfgsch * Each of these QHs point to the same QH that is the start of control 44bcc0e93aSaaron * traffic. This QH points at another QH which is the start of the 45bcc0e93aSaaron * bulk traffic. 4612fe8f0eSfgsch * 4712fe8f0eSfgsch * UHCI_VFRAMELIST_COUNT should be a power of 2 and <= UHCI_FRAMELIST_COUNT. 4812fe8f0eSfgsch */ 4912fe8f0eSfgsch #define UHCI_VFRAMELIST_COUNT 128 5012fe8f0eSfgsch 51ab0b1be7Smglocker struct uhci_soft_qh; 52ab0b1be7Smglocker struct uhci_soft_td; 5312fe8f0eSfgsch 54f8958cb1Sfgsch typedef union { 55f8958cb1Sfgsch struct uhci_soft_qh *sqh; 56f8958cb1Sfgsch struct uhci_soft_td *std; 57f8958cb1Sfgsch } uhci_soft_td_qh_t; 58f8958cb1Sfgsch 5912fe8f0eSfgsch /* 6012fe8f0eSfgsch * An interrupt info struct contains the information needed to 6112fe8f0eSfgsch * execute a requested routine when the controller generates an 6212fe8f0eSfgsch * interrupt. Since we cannot know which transfer generated 6312fe8f0eSfgsch * the interrupt all structs are linked together so they can be 6412fe8f0eSfgsch * searched at interrupt time. 6512fe8f0eSfgsch */ 665b152b0bSmpi struct uhci_xfer { 675b152b0bSmpi struct usbd_xfer xfer; 685b152b0bSmpi LIST_ENTRY(uhci_xfer) inext; 69ab0b1be7Smglocker struct uhci_soft_td *stdstart; 70ab0b1be7Smglocker struct uhci_soft_td *stdend; 715b152b0bSmpi int curframe; 7212fe8f0eSfgsch #ifdef DIAGNOSTIC 7312fe8f0eSfgsch int isdone; 7412fe8f0eSfgsch #endif 75ab0b1be7Smglocker }; 7612fe8f0eSfgsch 7712fe8f0eSfgsch /* 7812fe8f0eSfgsch * Extra information that we need for a TD. 7912fe8f0eSfgsch */ 8012fe8f0eSfgsch struct uhci_soft_td { 81ab0b1be7Smglocker struct uhci_td td; /* The real TD, must be first */ 82f8958cb1Sfgsch uhci_soft_td_qh_t link; /* soft version of the td_link field */ 83f8958cb1Sfgsch uhci_physaddr_t physaddr; /* TD's physical address. */ 8412fe8f0eSfgsch }; 85f8958cb1Sfgsch /* 86f8958cb1Sfgsch * Make the size such that it is a multiple of UHCI_TD_ALIGN. This way 87eff3e1aaSaaron * we can pack a number of soft TD together and have the real TD well 88f8958cb1Sfgsch * aligned. 89f8958cb1Sfgsch * NOTE: Minimum size is 32 bytes. 90f8958cb1Sfgsch */ 91f8958cb1Sfgsch #define UHCI_STD_SIZE ((sizeof (struct uhci_soft_td) + UHCI_TD_ALIGN - 1) / UHCI_TD_ALIGN * UHCI_TD_ALIGN) 92f8958cb1Sfgsch #define UHCI_STD_CHUNK 128 /*(PAGE_SIZE / UHCI_TD_SIZE)*/ 9312fe8f0eSfgsch 9412fe8f0eSfgsch /* 9512fe8f0eSfgsch * Extra information that we need for a QH. 9612fe8f0eSfgsch */ 9712fe8f0eSfgsch struct uhci_soft_qh { 98ab0b1be7Smglocker struct uhci_qh qh; /* The real QH, must be first */ 99ab0b1be7Smglocker struct uhci_soft_qh *hlink; /* soft version of qh_hlink */ 100ab0b1be7Smglocker struct uhci_soft_td *elink; /* soft version of qh_elink */ 101f8958cb1Sfgsch uhci_physaddr_t physaddr; /* QH's physical address. */ 10212fe8f0eSfgsch int pos; /* Timeslot position */ 10312fe8f0eSfgsch }; 104f8958cb1Sfgsch /* See comment about UHCI_STD_SIZE. */ 105f8958cb1Sfgsch #define UHCI_SQH_SIZE ((sizeof (struct uhci_soft_qh) + UHCI_QH_ALIGN - 1) / UHCI_QH_ALIGN * UHCI_QH_ALIGN) 106f8958cb1Sfgsch #define UHCI_SQH_CHUNK 128 /*(PAGE_SIZE / UHCI_QH_SIZE)*/ 10712fe8f0eSfgsch 10812fe8f0eSfgsch /* 109eff3e1aaSaaron * Information about an entry in the virtual frame list. 11012fe8f0eSfgsch */ 11112fe8f0eSfgsch struct uhci_vframe { 112ab0b1be7Smglocker struct uhci_soft_td *htd; /* pointer to dummy TD */ 113ab0b1be7Smglocker struct uhci_soft_td *etd; /* pointer to last TD */ 114ab0b1be7Smglocker struct uhci_soft_qh *hqh; /* pointer to dummy QH */ 115ab0b1be7Smglocker struct uhci_soft_qh *eqh; /* pointer to last QH */ 11612fe8f0eSfgsch u_int bandwidth; /* max bandwidth used by this frame */ 11712fe8f0eSfgsch }; 11812fe8f0eSfgsch 119ab0b1be7Smglocker struct uhci_softc { 12012fe8f0eSfgsch struct usbd_bus sc_bus; /* base device */ 12112fe8f0eSfgsch bus_space_tag_t iot; 12212fe8f0eSfgsch bus_space_handle_t ioh; 12382426cf3Sfgsch bus_size_t sc_size; 12412fe8f0eSfgsch 12512fe8f0eSfgsch uhci_physaddr_t *sc_pframes; 126ab0b1be7Smglocker struct usb_dma sc_dma; 12712fe8f0eSfgsch struct uhci_vframe sc_vframes[UHCI_VFRAMELIST_COUNT]; 12812fe8f0eSfgsch 129ab0b1be7Smglocker struct uhci_soft_qh *sc_lctl_start; /* dummy QH for low speed control */ 130ab0b1be7Smglocker struct uhci_soft_qh *sc_lctl_end; /* last control QH */ 131ab0b1be7Smglocker struct uhci_soft_qh *sc_hctl_start;/* dummy QH for high speed control */ 132ab0b1be7Smglocker struct uhci_soft_qh *sc_hctl_end; /* last control QH */ 133ab0b1be7Smglocker struct uhci_soft_qh *sc_bulk_start; /* dummy QH for bulk */ 134ab0b1be7Smglocker struct uhci_soft_qh *sc_bulk_end; /* last bulk transfer */ 135ab0b1be7Smglocker struct uhci_soft_qh *sc_last_qh; /* dummy QH at the end */ 136591e0ca7Saaron u_int32_t sc_loops; /* number of QHs that wants looping */ 13712fe8f0eSfgsch 138ab0b1be7Smglocker struct uhci_soft_td *sc_freetds; /* TD free list */ 139ab0b1be7Smglocker struct uhci_soft_qh *sc_freeqhs; /* QH free list */ 140eff3e1aaSaaron 14112fe8f0eSfgsch u_int8_t sc_conf; /* device configuration */ 14212fe8f0eSfgsch 143eff3e1aaSaaron u_int8_t sc_saved_sof; 144eff3e1aaSaaron u_int16_t sc_saved_frnum; 14512fe8f0eSfgsch 14672a11251Snate char sc_softwake; 14772a11251Snate 148eff3e1aaSaaron char sc_isreset; 14912fe8f0eSfgsch char sc_suspend; 15012fe8f0eSfgsch 1515b152b0bSmpi LIST_HEAD(, uhci_xfer) sc_intrhead; 15212fe8f0eSfgsch 153bcc0e93aSaaron /* Info for the root hub interrupt "pipe". */ 154*ca68072aSmpi struct usbd_xfer *sc_intrxfer; 155*ca68072aSmpi struct timeout sc_root_intr; 15612fe8f0eSfgsch 15772a11251Snate char sc_vendor[32]; /* vendor string for root hub */ 158eff3e1aaSaaron int sc_id_vendor; /* vendor ID for root hub */ 159ab0b1be7Smglocker }; 16012fe8f0eSfgsch 161ab0b1be7Smglocker usbd_status uhci_init(struct uhci_softc *); 162ab0b1be7Smglocker usbd_status uhci_run(struct uhci_softc *, int run); 163591e0ca7Saaron int uhci_intr(void *); 16444fe0a2dSmpi int uhci_detach(struct device *, int); 165e78728c7Spirofti int uhci_activate(struct device *, int); 166