uhcivar.h revision 1.48.8.2 1 /* $NetBSD: uhcivar.h,v 1.48.8.2 2012/10/30 17:22:08 yamt Exp $ */
2
3 /*
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart (at) augustsson.net) at
9 * Carlstedt Research & Technology.
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 /*
34 * To avoid having 1024 TDs for each isochronous transfer we introduce
35 * a virtual frame list. Every UHCI_VFRAMELIST_COUNT entries in the real
36 * frame list points to a non-active TD. These, in turn, form the
37 * starts of the virtual frame list. This also has the advantage that it
38 * simplifies linking in/out of TDs/QHs in the schedule.
39 * Furthermore, initially each of the inactive TDs point to an inactive
40 * QH that forms the start of the interrupt traffic for that slot.
41 * Each of these QHs point to the same QH that is the start of control
42 * traffic. This QH points at another QH which is the start of the
43 * bulk traffic.
44 *
45 * UHCI_VFRAMELIST_COUNT should be a power of 2 and <= UHCI_FRAMELIST_COUNT.
46 */
47 #define UHCI_VFRAMELIST_COUNT 128
48
49 typedef struct uhci_soft_qh uhci_soft_qh_t;
50 typedef struct uhci_soft_td uhci_soft_td_t;
51
52 typedef union {
53 struct uhci_soft_qh *sqh;
54 struct uhci_soft_td *std;
55 } uhci_soft_td_qh_t;
56
57 /*
58 * An interrupt info struct contains the information needed to
59 * execute a requested routine when the controller generates an
60 * interrupt. Since we cannot know which transfer generated
61 * the interrupt all structs are linked together so they can be
62 * searched at interrupt time.
63 */
64 typedef struct uhci_intr_info {
65 struct uhci_softc *sc;
66 usbd_xfer_handle xfer;
67 uhci_soft_td_t *stdstart;
68 uhci_soft_td_t *stdend;
69 LIST_ENTRY(uhci_intr_info) list;
70 int isdone; /* used only when DIAGNOSTIC is defined */
71 } uhci_intr_info_t;
72
73 struct uhci_xfer {
74 struct usbd_xfer xfer;
75 uhci_intr_info_t iinfo;
76 struct usb_task abort_task;
77 int curframe;
78 };
79
80 #define UXFER(xfer) ((struct uhci_xfer *)(xfer))
81
82 /*
83 * Extra information that we need for a TD.
84 */
85 struct uhci_soft_td {
86 uhci_td_t td; /* The real TD, must be first */
87 uhci_soft_td_qh_t link; /* soft version of the td_link field */
88 uhci_physaddr_t physaddr; /* TD's physical address. */
89 usb_dma_t dma; /* TD's DMA infos */
90 int offs; /* TD's offset in usb_dma_t */
91 };
92 /*
93 * Make the size such that it is a multiple of UHCI_TD_ALIGN. This way
94 * we can pack a number of soft TD together and have the real TD well
95 * aligned.
96 * NOTE: Minimum size is 32 bytes.
97 */
98 #define UHCI_STD_SIZE ((sizeof (struct uhci_soft_td) + UHCI_TD_ALIGN - 1) / UHCI_TD_ALIGN * UHCI_TD_ALIGN)
99 #define UHCI_STD_CHUNK 128 /*(PAGE_SIZE / UHCI_TD_SIZE)*/
100
101 /*
102 * Extra information that we need for a QH.
103 */
104 struct uhci_soft_qh {
105 uhci_qh_t qh; /* The real QH, must be first */
106 uhci_soft_qh_t *hlink; /* soft version of qh_hlink */
107 uhci_soft_td_t *elink; /* soft version of qh_elink */
108 uhci_physaddr_t physaddr; /* QH's physical address. */
109 int pos; /* Timeslot position */
110 usb_dma_t dma; /* QH's DMA infos */
111 int offs; /* QH's offset in usb_dma_t */
112 };
113 /* See comment about UHCI_STD_SIZE. */
114 #define UHCI_SQH_SIZE ((sizeof (struct uhci_soft_qh) + UHCI_QH_ALIGN - 1) / UHCI_QH_ALIGN * UHCI_QH_ALIGN)
115 #define UHCI_SQH_CHUNK 128 /*(PAGE_SIZE / UHCI_QH_SIZE)*/
116
117 /*
118 * Information about an entry in the virtual frame list.
119 */
120 struct uhci_vframe {
121 uhci_soft_td_t *htd; /* pointer to dummy TD */
122 uhci_soft_td_t *etd; /* pointer to last TD */
123 uhci_soft_qh_t *hqh; /* pointer to dummy QH */
124 uhci_soft_qh_t *eqh; /* pointer to last QH */
125 u_int bandwidth; /* max bandwidth used by this frame */
126 };
127
128 typedef struct uhci_softc {
129 device_t sc_dev;
130 struct usbd_bus sc_bus;
131 bus_space_tag_t iot;
132 bus_space_handle_t ioh;
133 bus_size_t sc_size;
134
135 kmutex_t sc_lock;
136 kmutex_t sc_intr_lock;
137 kcondvar_t sc_softwake_cv;
138
139 uhci_physaddr_t *sc_pframes;
140 usb_dma_t sc_dma;
141 struct uhci_vframe sc_vframes[UHCI_VFRAMELIST_COUNT];
142
143 uhci_soft_qh_t *sc_lctl_start; /* dummy QH for low speed control */
144 uhci_soft_qh_t *sc_lctl_end; /* last control QH */
145 uhci_soft_qh_t *sc_hctl_start; /* dummy QH for high speed control */
146 uhci_soft_qh_t *sc_hctl_end; /* last control QH */
147 uhci_soft_qh_t *sc_bulk_start; /* dummy QH for bulk */
148 uhci_soft_qh_t *sc_bulk_end; /* last bulk transfer */
149 uhci_soft_qh_t *sc_last_qh; /* dummy QH at the end */
150 u_int32_t sc_loops; /* number of QHs that wants looping */
151
152 uhci_soft_td_t *sc_freetds; /* TD free list */
153 uhci_soft_qh_t *sc_freeqhs; /* QH free list */
154
155 SIMPLEQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */
156
157 u_int8_t sc_addr; /* device address */
158 u_int8_t sc_conf; /* device configuration */
159
160 u_int8_t sc_saved_sof;
161 u_int16_t sc_saved_frnum;
162
163 char sc_softwake;
164
165 char sc_isreset;
166 char sc_suspend;
167 char sc_dying;
168
169 LIST_HEAD(, uhci_intr_info) sc_intrhead;
170
171 /* Info for the root hub interrupt "pipe". */
172 int sc_ival; /* time between root hub intrs */
173 usbd_xfer_handle sc_intr_xfer; /* root hub interrupt transfer */
174 struct callout sc_poll_handle;
175
176 char sc_vendor[32]; /* vendor string for root hub */
177 int sc_id_vendor; /* vendor ID for root hub */
178
179 device_t sc_child; /* /dev/usb# device */
180 struct usb_dma_reserve sc_dma_reserve;
181 } uhci_softc_t;
182
183 usbd_status uhci_init(uhci_softc_t *);
184 int uhci_intr(void *);
185 int uhci_detach(uhci_softc_t *, int);
186 void uhci_childdet(device_t, device_t);
187 int uhci_activate(device_t, enum devact);
188 bool uhci_resume(device_t, const pmf_qual_t *);
189 bool uhci_suspend(device_t, const pmf_qual_t *);
190