ahci.c revision 1.12.6.8 1 1.12.6.8 skrll /* $NetBSD: ahci.c,v 1.12.6.8 2014/12/03 14:18:07 skrll Exp $ */
2 1.1 dyoung
3 1.1 dyoung /*-
4 1.1 dyoung * Copyright (c) 2007 Ruslan Ermilov and Vsevolod Lobko.
5 1.1 dyoung * All rights reserved.
6 1.1 dyoung *
7 1.1 dyoung * Redistribution and use in source and binary forms, with or
8 1.1 dyoung * without modification, are permitted provided that the following
9 1.1 dyoung * conditions are met:
10 1.1 dyoung * 1. Redistributions of source code must retain the above copyright
11 1.1 dyoung * notice, this list of conditions and the following disclaimer.
12 1.1 dyoung * 2. Redistributions in binary form must reproduce the above
13 1.1 dyoung * copyright notice, this list of conditions and the following
14 1.1 dyoung * disclaimer in the documentation and/or other materials provided
15 1.1 dyoung * with the distribution.
16 1.1 dyoung * 3. The names of the authors may not be used to endorse or promote
17 1.1 dyoung * products derived from this software without specific prior
18 1.1 dyoung * written permission.
19 1.1 dyoung *
20 1.1 dyoung * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY
21 1.1 dyoung * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 1.1 dyoung * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 1.1 dyoung * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
24 1.1 dyoung * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25 1.1 dyoung * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 1.1 dyoung * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
27 1.1 dyoung * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 1.1 dyoung * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
29 1.1 dyoung * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 1.1 dyoung * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31 1.1 dyoung * OF SUCH DAMAGE.
32 1.1 dyoung */
33 1.1 dyoung /*
34 1.1 dyoung * Copyright (c) 2001 The NetBSD Foundation, Inc.
35 1.1 dyoung * All rights reserved.
36 1.1 dyoung *
37 1.1 dyoung * This code is derived from software contributed to The NetBSD Foundation
38 1.1 dyoung * by Tetsuya Isaki.
39 1.1 dyoung *
40 1.1 dyoung * Redistribution and use in source and binary forms, with or without
41 1.1 dyoung * modification, are permitted provided that the following conditions
42 1.1 dyoung * are met:
43 1.1 dyoung * 1. Redistributions of source code must retain the above copyright
44 1.1 dyoung * notice, this list of conditions and the following disclaimer.
45 1.1 dyoung * 2. Redistributions in binary form must reproduce the above copyright
46 1.1 dyoung * notice, this list of conditions and the following disclaimer in the
47 1.1 dyoung * documentation and/or other materials provided with the distribution.
48 1.1 dyoung *
49 1.1 dyoung * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
50 1.1 dyoung * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
51 1.1 dyoung * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
52 1.1 dyoung * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
53 1.1 dyoung * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
54 1.1 dyoung * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
55 1.1 dyoung * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
56 1.1 dyoung * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
57 1.1 dyoung * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58 1.1 dyoung * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59 1.1 dyoung * POSSIBILITY OF SUCH DAMAGE.
60 1.1 dyoung */
61 1.1 dyoung
62 1.1 dyoung /*
63 1.1 dyoung * !! HIGHLY EXPERIMENTAL CODE !!
64 1.1 dyoung */
65 1.1 dyoung
66 1.1 dyoung #include <sys/cdefs.h>
67 1.12.6.8 skrll __KERNEL_RCSID(0, "$NetBSD: ahci.c,v 1.12.6.8 2014/12/03 14:18:07 skrll Exp $");
68 1.1 dyoung
69 1.1 dyoung #include <sys/param.h>
70 1.1 dyoung #include <sys/systm.h>
71 1.1 dyoung #include <sys/kernel.h>
72 1.1 dyoung #include <sys/proc.h>
73 1.1 dyoung #include <sys/device.h>
74 1.12.6.8 skrll #include <sys/kmem.h>
75 1.1 dyoung
76 1.7 dyoung #include <sys/bus.h>
77 1.1 dyoung #include <machine/cpu.h>
78 1.1 dyoung
79 1.1 dyoung #include <dev/usb/usb.h>
80 1.1 dyoung #include <dev/usb/usbdi.h>
81 1.1 dyoung #include <dev/usb/usbdivar.h>
82 1.1 dyoung #include <dev/usb/usb_mem.h>
83 1.1 dyoung #include <dev/usb/usbdevs.h>
84 1.1 dyoung
85 1.1 dyoung #include <mips/adm5120/include/adm5120reg.h>
86 1.1 dyoung #include <mips/adm5120/include/adm5120var.h>
87 1.1 dyoung #include <mips/adm5120/include/adm5120_obiovar.h>
88 1.1 dyoung
89 1.1 dyoung #include <mips/adm5120/dev/ahcireg.h>
90 1.1 dyoung #include <mips/adm5120/dev/ahcivar.h>
91 1.1 dyoung
92 1.1 dyoung static usbd_status ahci_open(usbd_pipe_handle);
93 1.1 dyoung static void ahci_softintr(void *);
94 1.1 dyoung static void ahci_poll(struct usbd_bus *);
95 1.1 dyoung static void ahci_poll_hub(void *);
96 1.1 dyoung static void ahci_poll_device(void *arg);
97 1.1 dyoung static usbd_xfer_handle ahci_allocx(struct usbd_bus *);
98 1.1 dyoung static void ahci_freex(struct usbd_bus *, usbd_xfer_handle);
99 1.1 dyoung
100 1.12 skrll static void ahci_get_lock(struct usbd_bus *, kmutex_t **);
101 1.12 skrll
102 1.1 dyoung static int ahci_str(usb_string_descriptor_t *, int, const char *);
103 1.1 dyoung
104 1.1 dyoung static usbd_status ahci_root_ctrl_transfer(usbd_xfer_handle);
105 1.1 dyoung static usbd_status ahci_root_ctrl_start(usbd_xfer_handle);
106 1.1 dyoung static void ahci_root_ctrl_abort(usbd_xfer_handle);
107 1.1 dyoung static void ahci_root_ctrl_close(usbd_pipe_handle);
108 1.1 dyoung static void ahci_root_ctrl_done(usbd_xfer_handle);
109 1.1 dyoung
110 1.1 dyoung static usbd_status ahci_root_intr_transfer(usbd_xfer_handle);
111 1.1 dyoung static usbd_status ahci_root_intr_start(usbd_xfer_handle);
112 1.1 dyoung static void ahci_root_intr_abort(usbd_xfer_handle);
113 1.1 dyoung static void ahci_root_intr_close(usbd_pipe_handle);
114 1.1 dyoung static void ahci_root_intr_done(usbd_xfer_handle);
115 1.1 dyoung
116 1.1 dyoung static usbd_status ahci_device_ctrl_transfer(usbd_xfer_handle);
117 1.1 dyoung static usbd_status ahci_device_ctrl_start(usbd_xfer_handle);
118 1.1 dyoung static void ahci_device_ctrl_abort(usbd_xfer_handle);
119 1.1 dyoung static void ahci_device_ctrl_close(usbd_pipe_handle);
120 1.1 dyoung static void ahci_device_ctrl_done(usbd_xfer_handle);
121 1.1 dyoung
122 1.1 dyoung static usbd_status ahci_device_intr_transfer(usbd_xfer_handle);
123 1.1 dyoung static usbd_status ahci_device_intr_start(usbd_xfer_handle);
124 1.1 dyoung static void ahci_device_intr_abort(usbd_xfer_handle);
125 1.1 dyoung static void ahci_device_intr_close(usbd_pipe_handle);
126 1.1 dyoung static void ahci_device_intr_done(usbd_xfer_handle);
127 1.1 dyoung
128 1.1 dyoung static usbd_status ahci_device_isoc_transfer(usbd_xfer_handle);
129 1.1 dyoung static usbd_status ahci_device_isoc_start(usbd_xfer_handle);
130 1.1 dyoung static void ahci_device_isoc_abort(usbd_xfer_handle);
131 1.1 dyoung static void ahci_device_isoc_close(usbd_pipe_handle);
132 1.1 dyoung static void ahci_device_isoc_done(usbd_xfer_handle);
133 1.1 dyoung
134 1.1 dyoung static usbd_status ahci_device_bulk_transfer(usbd_xfer_handle);
135 1.1 dyoung static usbd_status ahci_device_bulk_start(usbd_xfer_handle);
136 1.1 dyoung static void ahci_device_bulk_abort(usbd_xfer_handle);
137 1.1 dyoung static void ahci_device_bulk_close(usbd_pipe_handle);
138 1.1 dyoung static void ahci_device_bulk_done(usbd_xfer_handle);
139 1.1 dyoung
140 1.1 dyoung static int ahci_transaction(struct ahci_softc *,
141 1.12.6.1 skrll usbd_pipe_handle, uint8_t, int, u_char *, uint8_t);
142 1.1 dyoung static void ahci_noop(usbd_pipe_handle);
143 1.1 dyoung static void ahci_abort_xfer(usbd_xfer_handle, usbd_status);
144 1.1 dyoung static void ahci_device_clear_toggle(usbd_pipe_handle);
145 1.1 dyoung
146 1.1 dyoung extern int usbdebug;
147 1.1 dyoung extern int uhubdebug;
148 1.1 dyoung extern int umassdebug;
149 1.1 dyoung int ahci_dummy;
150 1.1 dyoung
151 1.1 dyoung #define AHCI_DEBUG
152 1.1 dyoung
153 1.1 dyoung /* For root hub */
154 1.1 dyoung #define AHCI_INTR_ENDPT (1)
155 1.1 dyoung
156 1.1 dyoung #ifdef AHCI_DEBUG
157 1.1 dyoung #define D_TRACE (0x0001) /* function trace */
158 1.1 dyoung #define D_MSG (0x0002) /* debug messages */
159 1.1 dyoung #define D_XFER (0x0004) /* transfer messages (noisy!) */
160 1.1 dyoung #define D_MEM (0x0008) /* memory allocation */
161 1.1 dyoung
162 1.1 dyoung int ahci_debug = 0;
163 1.1 dyoung #define DPRINTF(z,x) if((ahci_debug&(z))!=0)printf x
164 1.1 dyoung void print_req(usb_device_request_t *);
165 1.1 dyoung void print_req_hub(usb_device_request_t *);
166 1.1 dyoung void print_dumpreg(struct ahci_softc *);
167 1.1 dyoung void print_xfer(usbd_xfer_handle);
168 1.1 dyoung #else
169 1.1 dyoung #define DPRINTF(z,x)
170 1.1 dyoung #endif
171 1.1 dyoung
172 1.1 dyoung
173 1.1 dyoung struct usbd_bus_methods ahci_bus_methods = {
174 1.12.6.3 skrll .ubm_open = ahci_open,
175 1.12.6.3 skrll .ubm_softint = ahci_softintr,
176 1.12.6.3 skrll .ubm_dopoll = ahci_poll,
177 1.12.6.3 skrll .ubm_allocx = ahci_allocx,
178 1.12.6.3 skrll .ubm_freex = ahci_freex,
179 1.12.6.3 skrll .ubm_getlock = ahci_get_lock,
180 1.1 dyoung };
181 1.1 dyoung
182 1.1 dyoung struct usbd_pipe_methods ahci_root_ctrl_methods = {
183 1.12.6.3 skrll .upm_transfer = ahci_root_ctrl_transfer,
184 1.12.6.3 skrll .upm_start = ahci_root_ctrl_start,
185 1.12.6.3 skrll .upm_abort = ahci_root_ctrl_abort,
186 1.12.6.3 skrll .upm_close = ahci_root_ctrl_close,
187 1.12.6.3 skrll .upm_cleartoggle = ahci_noop,
188 1.12.6.3 skrll .upm_done = ahci_root_ctrl_done,
189 1.1 dyoung };
190 1.1 dyoung
191 1.1 dyoung struct usbd_pipe_methods ahci_root_intr_methods = {
192 1.12.6.3 skrll .upm_transfer = ahci_root_intr_transfer,
193 1.12.6.3 skrll .upm_start = ahci_root_intr_start,
194 1.12.6.3 skrll .upm_abort = ahci_root_intr_abort,
195 1.12.6.3 skrll .upm_close = ahci_root_intr_close,
196 1.12.6.3 skrll .upm_cleartoggle = ahci_noop,
197 1.12.6.3 skrll .upm_done = ahci_root_intr_done,
198 1.1 dyoung };
199 1.1 dyoung
200 1.1 dyoung struct usbd_pipe_methods ahci_device_ctrl_methods = {
201 1.12.6.3 skrll .upm_transfer = ahci_device_ctrl_transfer,
202 1.12.6.3 skrll .upm_start = ahci_device_ctrl_start,
203 1.12.6.3 skrll .upm_abort = ahci_device_ctrl_abort,
204 1.12.6.3 skrll .upm_close = ahci_device_ctrl_close,
205 1.12.6.3 skrll .upm_cleartoggle = ahci_noop,
206 1.12.6.3 skrll .upm_done = ahci_device_ctrl_done,
207 1.1 dyoung };
208 1.1 dyoung
209 1.1 dyoung struct usbd_pipe_methods ahci_device_intr_methods = {
210 1.12.6.3 skrll .upm_transfer = ahci_device_intr_transfer,
211 1.12.6.3 skrll .upm_start = ahci_device_intr_start,
212 1.12.6.3 skrll .upm_abort = ahci_device_intr_abort,
213 1.12.6.3 skrll .upm_close = ahci_device_intr_close,
214 1.12.6.3 skrll .upm_cleartoggle = ahci_device_clear_toggle,
215 1.12.6.3 skrll .upm_done = ahci_device_intr_done,
216 1.1 dyoung };
217 1.1 dyoung
218 1.1 dyoung struct usbd_pipe_methods ahci_device_isoc_methods = {
219 1.12.6.3 skrll .upm_transfer = ahci_device_isoc_transfer,
220 1.12.6.3 skrll .upm_start = ahci_device_isoc_start,
221 1.12.6.3 skrll .upm_abort = ahci_device_isoc_abort,
222 1.12.6.3 skrll .upm_close = ahci_device_isoc_close,
223 1.12.6.3 skrll .upm_cleartoggle = ahci_noop,
224 1.12.6.3 skrll .upm_done = ahci_device_isoc_done,
225 1.1 dyoung };
226 1.1 dyoung
227 1.1 dyoung struct usbd_pipe_methods ahci_device_bulk_methods = {
228 1.12.6.3 skrll .upm_transfer = ahci_device_bulk_transfer,
229 1.12.6.3 skrll .upm_start = ahci_device_bulk_start,
230 1.12.6.3 skrll .upm_abort = ahci_device_bulk_abort,
231 1.12.6.3 skrll .upm_close = ahci_device_bulk_close,
232 1.12.6.3 skrll .upm_cleartoggle = ahci_device_clear_toggle,
233 1.12.6.3 skrll .upm_done = ahci_device_bulk_done,
234 1.1 dyoung };
235 1.1 dyoung
236 1.1 dyoung struct ahci_pipe {
237 1.1 dyoung struct usbd_pipe pipe;
238 1.12.6.1 skrll uint32_t toggle;
239 1.1 dyoung };
240 1.1 dyoung
241 1.9 chs static int ahci_match(device_t, cfdata_t, void *);
242 1.4 dyoung static void ahci_attach(device_t, device_t, void *);
243 1.1 dyoung
244 1.9 chs CFATTACH_DECL_NEW(ahci, sizeof(struct ahci_softc),
245 1.1 dyoung ahci_match, ahci_attach, NULL, NULL);
246 1.1 dyoung
247 1.1 dyoung static int
248 1.4 dyoung ahci_match(device_t parent, struct cfdata *cf, void *aux)
249 1.1 dyoung {
250 1.1 dyoung struct obio_attach_args *aa = aux;
251 1.1 dyoung
252 1.1 dyoung if (strcmp(aa->oba_name, cf->cf_name) == 0)
253 1.1 dyoung return (1);
254 1.1 dyoung
255 1.1 dyoung return (0);
256 1.1 dyoung }
257 1.1 dyoung
258 1.1 dyoung #define REG_READ(o) bus_space_read_4(sc->sc_st, sc->sc_ioh, (o))
259 1.1 dyoung #define REG_WRITE(o,v) bus_space_write_4(sc->sc_st, sc->sc_ioh, (o),(v))
260 1.1 dyoung
261 1.1 dyoung /*
262 1.1 dyoung * Attach SL11H/SL811HS. Return 0 if success.
263 1.1 dyoung */
264 1.1 dyoung void
265 1.4 dyoung ahci_attach(device_t parent, device_t self, void *aux)
266 1.1 dyoung {
267 1.1 dyoung struct obio_attach_args *aa = aux;
268 1.4 dyoung struct ahci_softc *sc = device_private(self);
269 1.1 dyoung
270 1.1 dyoung printf("\n");
271 1.1 dyoung sc->sc_dmat = aa->oba_dt;
272 1.1 dyoung sc->sc_st = aa->oba_st;
273 1.1 dyoung
274 1.1 dyoung /* Initialize sc */
275 1.12.6.5 skrll sc->sc_bus.ub_revision = USBREV_1_1;
276 1.12.6.5 skrll sc->sc_bus.ub_methods = &ahci_bus_methods;
277 1.12.6.5 skrll sc->sc_bus.ub_pipesize = sizeof(struct ahci_pipe);
278 1.12.6.5 skrll sc->sc_bus.ub_dmatag = sc->sc_dmat;
279 1.12.6.5 skrll sc->sc_bus.ub_usedma = true;
280 1.1 dyoung
281 1.1 dyoung /* Map the device. */
282 1.1 dyoung if (bus_space_map(sc->sc_st, aa->oba_addr,
283 1.1 dyoung 512, 0, &sc->sc_ioh) != 0) {
284 1.4 dyoung aprint_error_dev(self, "unable to map device\n");
285 1.1 dyoung return;
286 1.1 dyoung }
287 1.1 dyoung
288 1.1 dyoung /* Hook up the interrupt handler. */
289 1.1 dyoung sc->sc_ih = adm5120_intr_establish(aa->oba_irq, INTR_IRQ, ahci_intr, sc);
290 1.1 dyoung
291 1.1 dyoung if (sc->sc_ih == NULL) {
292 1.4 dyoung aprint_error_dev(self,
293 1.4 dyoung "unable to register interrupt handler\n");
294 1.1 dyoung return;
295 1.1 dyoung }
296 1.1 dyoung
297 1.1 dyoung SIMPLEQ_INIT(&sc->sc_free_xfers);
298 1.1 dyoung
299 1.6 dyoung callout_init(&sc->sc_poll_handle, 0);
300 1.1 dyoung
301 1.12 skrll mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB);
302 1.12 skrll mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED /* XXXNH */);
303 1.12 skrll
304 1.1 dyoung REG_WRITE(ADMHCD_REG_INTENABLE, 0); /* disable interrupts */
305 1.1 dyoung REG_WRITE(ADMHCD_REG_CONTROL, ADMHCD_SW_RESET); /* reset */
306 1.1 dyoung delay_ms(10);
307 1.12.6.2 skrll while (REG_READ(ADMHCD_REG_CONTROL) & ADMHCD_SW_RESET)
308 1.12.6.2 skrll delay_ms(1);
309 1.1 dyoung
310 1.1 dyoung REG_WRITE(ADMHCD_REG_CONTROL, ADMHCD_HOST_EN);
311 1.12.6.2 skrll REG_WRITE(ADMHCD_REG_HOSTHEAD, 0x00000000);
312 1.12.6.2 skrll REG_WRITE(ADMHCD_REG_FMINTERVAL, 0x20002edf);
313 1.12.6.2 skrll REG_WRITE(ADMHCD_REG_LSTHRESH, 0x628);
314 1.12.6.2 skrll REG_WRITE(ADMHCD_REG_RHDESCR, ADMHCD_NPS | ADMHCD_LPSC);
315 1.12.6.2 skrll REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP);
316 1.1 dyoung
317 1.1 dyoung REG_WRITE(ADMHCD_REG_INTENABLE, 0); /* XXX: enable interrupts */
318 1.1 dyoung
319 1.1 dyoung #ifdef USB_DEBUG
320 1.1 dyoung /* usbdebug = 0x7f;
321 1.1 dyoung uhubdebug = 0x7f;
322 1.1 dyoung umassdebug = 0xffffffff; */
323 1.1 dyoung #endif
324 1.1 dyoung
325 1.1 dyoung /* Attach USB devices */
326 1.1 dyoung sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint);
327 1.1 dyoung
328 1.1 dyoung }
329 1.1 dyoung
330 1.1 dyoung int
331 1.1 dyoung ahci_intr(void *arg)
332 1.1 dyoung {
333 1.1 dyoung #if 0
334 1.1 dyoung struct ahci_softc *sc = arg;
335 1.12.6.1 skrll uint8_t r;
336 1.1 dyoung #ifdef AHCI_DEBUG
337 1.1 dyoung char bitbuf[256];
338 1.1 dyoung #endif
339 1.1 dyoung
340 1.1 dyoung r = sl11read(sc, SL11_ISR);
341 1.1 dyoung
342 1.1 dyoung sl11write(sc, SL11_ISR, SL11_ISR_DATA | SL11_ISR_SOFTIMER);
343 1.1 dyoung
344 1.1 dyoung if ((r & SL11_ISR_RESET)) {
345 1.1 dyoung sc->sc_flags |= AHCDF_RESET;
346 1.1 dyoung sl11write(sc, SL11_ISR, SL11_ISR_RESET);
347 1.1 dyoung }
348 1.1 dyoung if ((r & SL11_ISR_INSERT)) {
349 1.1 dyoung sc->sc_flags |= AHCDF_INSERT;
350 1.1 dyoung sl11write(sc, SL11_ISR, SL11_ISR_INSERT);
351 1.1 dyoung }
352 1.1 dyoung
353 1.1 dyoung #ifdef AHCI_DEBUG
354 1.5 christos snprintb(bitbuf, sizeof(bitbuf),
355 1.5 christos ((sl11read(sc, SL11_CTRL) & SL11_CTRL_SUSPEND)
356 1.5 christos ? "\20\x8""D+\7RESUME\6INSERT\5SOF\4res\3""BABBLE\2USBB\1USBA"
357 1.5 christos : "\20\x8""D+\7RESET\6INSERT\5SOF\4res\3""BABBLE\2USBB\1USBA"),
358 1.5 christos r);
359 1.11 skrll
360 1.1 dyoung DPRINTF(D_XFER, ("I=%s ", bitbuf));
361 1.1 dyoung #endif /* AHCI_DEBUG */
362 1.1 dyoung #endif
363 1.1 dyoung
364 1.1 dyoung return 0;
365 1.1 dyoung }
366 1.1 dyoung
367 1.1 dyoung usbd_status
368 1.1 dyoung ahci_open(usbd_pipe_handle pipe)
369 1.1 dyoung {
370 1.12.6.5 skrll usbd_device_handle dev = pipe->up_dev;
371 1.12.6.5 skrll struct ahci_softc *sc = (struct ahci_softc *)dev->ud_bus;
372 1.1 dyoung struct ahci_pipe *apipe = (struct ahci_pipe *)pipe;
373 1.12.6.5 skrll usb_endpoint_descriptor_t *ed = pipe->up_endpoint->ue_edesc;
374 1.1 dyoung
375 1.1 dyoung DPRINTF(D_TRACE, ("ahci_open(addr=%d,ep=%d,scaddr=%d)",
376 1.12.6.5 skrll dev->ud_addr, ed->bEndpointAddress, sc->sc_addr));
377 1.1 dyoung
378 1.1 dyoung apipe->toggle=0;
379 1.1 dyoung
380 1.12.6.5 skrll if (dev->ud_addr == sc->sc_addr) {
381 1.1 dyoung switch (ed->bEndpointAddress) {
382 1.1 dyoung case USB_CONTROL_ENDPOINT:
383 1.12.6.5 skrll pipe->up_methods = &ahci_root_ctrl_methods;
384 1.1 dyoung break;
385 1.1 dyoung case UE_DIR_IN | AHCI_INTR_ENDPT:
386 1.12.6.5 skrll pipe->up_methods = &ahci_root_intr_methods;
387 1.1 dyoung break;
388 1.1 dyoung default:
389 1.1 dyoung printf("open:endpointErr!\n");
390 1.1 dyoung return USBD_INVAL;
391 1.1 dyoung }
392 1.1 dyoung } else {
393 1.1 dyoung switch (ed->bmAttributes & UE_XFERTYPE) {
394 1.1 dyoung case UE_CONTROL:
395 1.1 dyoung DPRINTF(D_MSG, ("control "));
396 1.12.6.5 skrll pipe->up_methods = &ahci_device_ctrl_methods;
397 1.1 dyoung break;
398 1.1 dyoung case UE_INTERRUPT:
399 1.1 dyoung DPRINTF(D_MSG, ("interrupt "));
400 1.12.6.5 skrll pipe->up_methods = &ahci_device_intr_methods;
401 1.1 dyoung break;
402 1.1 dyoung case UE_ISOCHRONOUS:
403 1.1 dyoung DPRINTF(D_MSG, ("isochronous "));
404 1.12.6.5 skrll pipe->up_methods = &ahci_device_isoc_methods;
405 1.1 dyoung break;
406 1.1 dyoung case UE_BULK:
407 1.1 dyoung DPRINTF(D_MSG, ("bluk "));
408 1.12.6.5 skrll pipe->up_methods = &ahci_device_bulk_methods;
409 1.1 dyoung break;
410 1.1 dyoung }
411 1.1 dyoung }
412 1.1 dyoung return USBD_NORMAL_COMPLETION;
413 1.1 dyoung }
414 1.1 dyoung
415 1.1 dyoung void
416 1.1 dyoung ahci_softintr(void *arg)
417 1.1 dyoung {
418 1.2 perry DPRINTF(D_TRACE, ("%s()", __func__));
419 1.1 dyoung }
420 1.1 dyoung
421 1.1 dyoung void
422 1.1 dyoung ahci_poll(struct usbd_bus *bus)
423 1.1 dyoung {
424 1.2 perry DPRINTF(D_TRACE, ("%s()", __func__));
425 1.1 dyoung }
426 1.1 dyoung
427 1.1 dyoung /*
428 1.1 dyoung * Emulation of interrupt transfer for status change endpoint
429 1.1 dyoung * of root hub.
430 1.1 dyoung */
431 1.1 dyoung void
432 1.1 dyoung ahci_poll_hub(void *arg)
433 1.1 dyoung {
434 1.1 dyoung usbd_xfer_handle xfer = arg;
435 1.12.6.5 skrll usbd_pipe_handle pipe = xfer->ux_pipe;
436 1.12.6.5 skrll struct ahci_softc *sc = (struct ahci_softc *)pipe->up_dev->ud_bus;
437 1.1 dyoung u_char *p;
438 1.1 dyoung static int p0_state=0;
439 1.1 dyoung static int p1_state=0;
440 1.1 dyoung
441 1.6 dyoung callout_reset(&sc->sc_poll_handle, sc->sc_interval, ahci_poll_hub, xfer);
442 1.1 dyoung
443 1.1 dyoung /* USB spec 11.13.3 (p.260) */
444 1.12.6.5 skrll p = KERNADDR(&xfer->ux_dmabuf, 0);
445 1.1 dyoung p[0] = 0;
446 1.1 dyoung if ((REG_READ(ADMHCD_REG_PORTSTATUS0) & ADMHCD_CCS) != p0_state) {
447 1.1 dyoung p[0] = 2;
448 1.1 dyoung DPRINTF(D_TRACE, ("!"));
449 1.1 dyoung p0_state=(REG_READ(ADMHCD_REG_PORTSTATUS0) & ADMHCD_CCS);
450 1.1 dyoung };
451 1.1 dyoung if ((REG_READ(ADMHCD_REG_PORTSTATUS1) & ADMHCD_CCS) != p1_state) {
452 1.1 dyoung p[0] = 2;
453 1.1 dyoung DPRINTF(D_TRACE, ("@"));
454 1.1 dyoung p1_state=(REG_READ(ADMHCD_REG_PORTSTATUS1) & ADMHCD_CCS);
455 1.1 dyoung };
456 1.1 dyoung
457 1.1 dyoung /* no change, return NAK */
458 1.1 dyoung if (p[0] == 0)
459 1.1 dyoung return;
460 1.1 dyoung
461 1.12.6.5 skrll xfer->ux_actlen = 1;
462 1.12.6.5 skrll xfer->ux_status = USBD_NORMAL_COMPLETION;
463 1.12 skrll mutex_enter(&sc->sc_lock);
464 1.1 dyoung usb_transfer_complete(xfer);
465 1.12 skrll mutex_exit(&sc->sc_lock);
466 1.1 dyoung }
467 1.1 dyoung
468 1.1 dyoung usbd_xfer_handle
469 1.1 dyoung ahci_allocx(struct usbd_bus *bus)
470 1.1 dyoung {
471 1.1 dyoung struct ahci_softc *sc = (struct ahci_softc *)bus;
472 1.1 dyoung usbd_xfer_handle xfer;
473 1.1 dyoung
474 1.1 dyoung DPRINTF(D_MEM, ("SLallocx"));
475 1.1 dyoung
476 1.1 dyoung xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
477 1.1 dyoung if (xfer) {
478 1.12.6.5 skrll SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, ux_next);
479 1.1 dyoung #ifdef DIAGNOSTIC
480 1.12.6.5 skrll if (xfer->ux_state != XFER_FREE) {
481 1.1 dyoung printf("ahci_allocx: xfer=%p not free, 0x%08x\n",
482 1.12.6.5 skrll xfer, xfer->ux_state);
483 1.1 dyoung }
484 1.1 dyoung #endif
485 1.1 dyoung } else {
486 1.12.6.8 skrll xfer = kmem_alloc(sizeof(*xfer), KM_SLEEP);
487 1.1 dyoung }
488 1.1 dyoung
489 1.1 dyoung if (xfer) {
490 1.1 dyoung memset(xfer, 0, sizeof(*xfer));
491 1.1 dyoung #ifdef DIAGNOSTIC
492 1.12.6.5 skrll xfer->ux_state = XFER_BUSY;
493 1.1 dyoung #endif
494 1.1 dyoung }
495 1.1 dyoung
496 1.1 dyoung return xfer;
497 1.1 dyoung }
498 1.1 dyoung
499 1.1 dyoung void
500 1.1 dyoung ahci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer)
501 1.1 dyoung {
502 1.1 dyoung struct ahci_softc *sc = (struct ahci_softc *)bus;
503 1.1 dyoung
504 1.1 dyoung DPRINTF(D_MEM, ("SLfreex"));
505 1.1 dyoung
506 1.1 dyoung #ifdef DIAGNOSTIC
507 1.12.6.5 skrll if (xfer->ux_state != XFER_BUSY) {
508 1.1 dyoung printf("ahci_freex: xfer=%p not busy, 0x%08x\n",
509 1.12.6.5 skrll xfer, xfer->ux_state);
510 1.1 dyoung return;
511 1.1 dyoung }
512 1.12.6.5 skrll xfer->ux_state = XFER_FREE;
513 1.1 dyoung #endif
514 1.12.6.5 skrll SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, ux_next);
515 1.1 dyoung }
516 1.1 dyoung
517 1.12 skrll static void
518 1.12 skrll ahci_get_lock(struct usbd_bus *bus, kmutex_t **lock)
519 1.12 skrll {
520 1.12.6.5 skrll struct ahci_softc *sc = bus->ub_hcpriv;
521 1.12 skrll
522 1.12 skrll *lock = &sc->sc_lock;
523 1.12 skrll }
524 1.12 skrll
525 1.1 dyoung void
526 1.1 dyoung ahci_noop(usbd_pipe_handle pipe)
527 1.1 dyoung {
528 1.2 perry DPRINTF(D_TRACE, ("%s()", __func__));
529 1.1 dyoung }
530 1.1 dyoung
531 1.1 dyoung /*
532 1.1 dyoung * Data structures and routines to emulate the root hub.
533 1.1 dyoung */
534 1.1 dyoung usb_device_descriptor_t ahci_devd = {
535 1.12.6.6 skrll .bLength = USB_DEVICE_DESCRIPTOR_SIZE,
536 1.12.6.6 skrll .bDescriptorType = UDESC_DEVICE,
537 1.12.6.6 skrll .bcdUSB = {0x01, 0x01},
538 1.12.6.6 skrll .bDeviceClass = UDCLASS_HUB,
539 1.12.6.6 skrll .bDeviceSubClass = UDSUBCLASS_HUB,
540 1.12.6.6 skrll .bDeviceProtocol = 0,
541 1.12.6.6 skrll .bMaxPacketSize = 64,
542 1.12.6.6 skrll .idVendor = {
543 1.12.6.7 skrll USB_VENDOR_SCANLOGIC & 0xff,
544 1.12.6.6 skrll USB_VENDOR_SCANLOGIC >> 8
545 1.12.6.6 skrll },
546 1.12.6.6 skrll .idProduct = {0},
547 1.12.6.6 skrll .bcdDevice = {0},
548 1.12.6.6 skrll .iManufacturer = 1,
549 1.12.6.6 skrll .iProduct = 2,
550 1.12.6.6 skrll .iSerialNumber = 0,
551 1.12.6.6 skrll .bNumConfigurations = 1
552 1.1 dyoung };
553 1.1 dyoung
554 1.1 dyoung usb_config_descriptor_t ahci_confd = {
555 1.12.6.7 skrll .bLength = USB_CONFIG_DESCRIPTOR_SIZE,
556 1.12.6.7 skrll .bDescriptorType = UDESC_CONFIG,
557 1.12.6.7 skrll .wTotalLength = {
558 1.12.6.7 skrll USB_CONFIG_DESCRIPTOR_SIZE +
559 1.12.6.7 skrll USB_INTERFACE_DESCRIPTOR_SIZE +
560 1.12.6.7 skrll USB_ENDPOINT_DESCRIPTOR_SIZE,
561 1.12.6.7 skrll },
562 1.12.6.7 skrll .bNumInterface = 1,
563 1.12.6.7 skrll .bConfigurationValue = 1,
564 1.12.6.7 skrll .iConfiguration = 0,
565 1.12.6.7 skrll .bmAttributes = UC_SELF_POWERED,
566 1.12.6.7 skrll .bMaxPower = 250
567 1.1 dyoung };
568 1.1 dyoung
569 1.1 dyoung usb_interface_descriptor_t ahci_ifcd = {
570 1.12.6.7 skrll .bLength = USB_INTERFACE_DESCRIPTOR_SIZE,
571 1.12.6.7 skrll .bDescriptorType = UDESC_INTERFACE,
572 1.12.6.7 skrll .bInterfaceNumber = 0,
573 1.12.6.7 skrll .bAlternateSetting = 0,
574 1.12.6.7 skrll .bNumEndpoints = 1,
575 1.12.6.7 skrll .bInterfaceClass = UICLASS_HUB,
576 1.12.6.7 skrll .bInterfaceSubClass = UISUBCLASS_HUB,
577 1.12.6.7 skrll .bInterfaceProtocol = 0,
578 1.12.6.7 skrll .iInterface = 0
579 1.1 dyoung };
580 1.1 dyoung
581 1.1 dyoung usb_endpoint_descriptor_t ahci_endpd = {
582 1.12.6.7 skrll .bLength = USB_ENDPOINT_DESCRIPTOR_SIZE,
583 1.12.6.7 skrll .bDescriptorType = UDESC_ENDPOINT,
584 1.12.6.7 skrll .bEndpointAddress = UE_DIR_IN | AHCI_INTR_ENDPT,
585 1.12.6.7 skrll .bmAttributes = UE_INTERRUPT,
586 1.12.6.7 skrll .wMaxPacketSize = {8},
587 1.12.6.7 skrll .bInterval = 255
588 1.1 dyoung };
589 1.1 dyoung
590 1.1 dyoung usb_hub_descriptor_t ahci_hubd = {
591 1.12.6.7 skrll .bDescLength = USB_HUB_DESCRIPTOR_SIZE,
592 1.12.6.7 skrll .bDescriptorType = UDESC_HUB,
593 1.12.6.7 skrll .bNbrPorts = 2,
594 1.12.6.7 skrll .wHubCharacteristics = { 0, 0 },
595 1.12.6.7 skrll .bPwrOn2PwrGood = 0,
596 1.12.6.7 skrll .bHubContrCurrent = 0,
597 1.12.6.7 skrll .DeviceRemovable = { 0x00 },
598 1.12.6.7 skrll .PortPowerCtrlMask = { 0x00 }
599 1.1 dyoung };
600 1.1 dyoung
601 1.1 dyoung static int
602 1.1 dyoung ahci_str(usb_string_descriptor_t *p, int l, const char *s)
603 1.1 dyoung {
604 1.1 dyoung int i;
605 1.1 dyoung
606 1.1 dyoung if (l == 0)
607 1.1 dyoung return 0;
608 1.1 dyoung p->bLength = 2 * strlen(s) + 2;
609 1.1 dyoung if (l == 1)
610 1.1 dyoung return 1;
611 1.1 dyoung p->bDescriptorType = UDESC_STRING;
612 1.1 dyoung l -= 2;
613 1.1 dyoung for (i = 0; s[i] && l > 1; i++, l -= 2)
614 1.1 dyoung USETW2(p->bString[i], 0, s[i]);
615 1.1 dyoung return 2 * i + 2;
616 1.1 dyoung }
617 1.1 dyoung
618 1.1 dyoung usbd_status
619 1.1 dyoung ahci_root_ctrl_transfer(usbd_xfer_handle xfer)
620 1.1 dyoung {
621 1.12.6.5 skrll struct ahci_softc *sc = (struct ahci_softc *)xfer->ux_pipe->up_dev->ud_bus;
622 1.1 dyoung usbd_status error;
623 1.1 dyoung
624 1.1 dyoung DPRINTF(D_TRACE, ("SLRCtrans "));
625 1.1 dyoung
626 1.1 dyoung /* Insert last in queue */
627 1.12 skrll mutex_enter(&sc->sc_lock);
628 1.1 dyoung error = usb_insert_transfer(xfer);
629 1.12 skrll mutex_exit(&sc->sc_lock);
630 1.1 dyoung if (error) {
631 1.1 dyoung DPRINTF(D_MSG, ("usb_insert_transfer returns err! "));
632 1.1 dyoung return error;
633 1.1 dyoung }
634 1.1 dyoung
635 1.1 dyoung /*
636 1.1 dyoung * Pipe isn't running (otherwise error would be USBD_INPROG),
637 1.1 dyoung * so start it first.
638 1.1 dyoung */
639 1.12.6.5 skrll return ahci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
640 1.1 dyoung }
641 1.1 dyoung
642 1.1 dyoung usbd_status
643 1.1 dyoung ahci_root_ctrl_start(usbd_xfer_handle xfer)
644 1.1 dyoung {
645 1.12.6.5 skrll struct ahci_softc *sc = (struct ahci_softc *)xfer->ux_pipe->up_dev->ud_bus;
646 1.1 dyoung usb_device_request_t *req;
647 1.12 skrll int len, value, index, l, status;
648 1.1 dyoung int totlen = 0;
649 1.1 dyoung void *buf = NULL;
650 1.1 dyoung usb_port_status_t ps;
651 1.1 dyoung usbd_status error;
652 1.1 dyoung
653 1.1 dyoung
654 1.1 dyoung DPRINTF(D_TRACE, ("SLRCstart "));
655 1.1 dyoung
656 1.12.6.5 skrll req = &xfer->ux_request;
657 1.1 dyoung
658 1.1 dyoung len = UGETW(req->wLength);
659 1.1 dyoung value = UGETW(req->wValue);
660 1.1 dyoung index = UGETW(req->wIndex);
661 1.1 dyoung
662 1.1 dyoung if (len)
663 1.12.6.5 skrll buf = KERNADDR(&xfer->ux_dmabuf, 0);
664 1.1 dyoung
665 1.1 dyoung #ifdef AHCI_DEBUG
666 1.1 dyoung if ((ahci_debug & D_TRACE))
667 1.1 dyoung print_req_hub(req);
668 1.1 dyoung #endif
669 1.1 dyoung
670 1.1 dyoung #define C(x,y) ((x) | ((y) << 8))
671 1.1 dyoung switch (C(req->bRequest, req->bmRequestType)) {
672 1.1 dyoung case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
673 1.1 dyoung DPRINTF(D_MSG, ("UR_CLEAR_FEATURE(DEVICE)XXX "));
674 1.1 dyoung break;
675 1.1 dyoung case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
676 1.1 dyoung DPRINTF(D_MSG, ("UR_CLEAR_FEATURE(INTERFACE)XXX "));
677 1.1 dyoung break;
678 1.1 dyoung case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
679 1.1 dyoung DPRINTF(D_MSG, ("UR_CLEAR_FEATURE(ENDPOINT)XXX "));
680 1.1 dyoung break;
681 1.1 dyoung case C(UR_GET_CONFIG, UT_READ_DEVICE):
682 1.1 dyoung DPRINTF(D_MSG, ("UR_GET_CONFIG "));
683 1.1 dyoung if (len > 0) {
684 1.12.6.1 skrll *(uint8_t *)buf = sc->sc_conf;
685 1.1 dyoung totlen = 1;
686 1.1 dyoung }
687 1.1 dyoung break;
688 1.1 dyoung case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
689 1.1 dyoung switch (value >> 8) {
690 1.1 dyoung case UDESC_DEVICE:
691 1.1 dyoung DPRINTF(D_MSG, ("UDESC_DEVICE "));
692 1.1 dyoung if ((value & 0xff) != 0) {
693 1.1 dyoung error = USBD_IOERROR;
694 1.1 dyoung goto ret;
695 1.1 dyoung }
696 1.1 dyoung totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
697 1.1 dyoung memcpy(buf, &ahci_devd, l);
698 1.1 dyoung break;
699 1.1 dyoung case UDESC_CONFIG:
700 1.1 dyoung DPRINTF(D_MSG, ("UDESC_CONFIG "));
701 1.1 dyoung if ((value & 0xff) != 0) {
702 1.1 dyoung error = USBD_IOERROR;
703 1.1 dyoung goto ret;
704 1.1 dyoung }
705 1.1 dyoung totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
706 1.1 dyoung memcpy(buf, &ahci_confd, l);
707 1.1 dyoung buf = (char *)buf + l;
708 1.1 dyoung len -= l;
709 1.1 dyoung
710 1.1 dyoung l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE);
711 1.1 dyoung totlen += l;
712 1.1 dyoung memcpy(buf, &ahci_ifcd, l);
713 1.1 dyoung buf = (char *)buf + l;
714 1.1 dyoung len -= l;
715 1.1 dyoung
716 1.1 dyoung l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE);
717 1.1 dyoung totlen += l;
718 1.1 dyoung memcpy(buf, &ahci_endpd, l);
719 1.1 dyoung break;
720 1.1 dyoung case UDESC_STRING:
721 1.1 dyoung DPRINTF(D_MSG, ("UDESC_STR "));
722 1.1 dyoung if (len == 0)
723 1.1 dyoung break;
724 1.12.6.1 skrll *(uint8_t *)buf = 0;
725 1.1 dyoung totlen = 1;
726 1.1 dyoung switch (value & 0xff) {
727 1.1 dyoung case 0:
728 1.1 dyoung break;
729 1.1 dyoung case 1: /* Vendor */
730 1.1 dyoung totlen = ahci_str(buf, len, "ADMTek");
731 1.1 dyoung break;
732 1.1 dyoung case 2: /* Product */
733 1.1 dyoung totlen = ahci_str(buf, len, "ADM5120 root hub");
734 1.1 dyoung break;
735 1.1 dyoung default:
736 1.1 dyoung printf("strerr%d ", value & 0xff);
737 1.1 dyoung break;
738 1.1 dyoung }
739 1.1 dyoung break;
740 1.1 dyoung default:
741 1.1 dyoung printf("unknownGetDescriptor=%x", value);
742 1.1 dyoung error = USBD_IOERROR;
743 1.1 dyoung break;
744 1.1 dyoung }
745 1.1 dyoung break;
746 1.1 dyoung case C(UR_GET_INTERFACE, UT_READ_INTERFACE):
747 1.1 dyoung /* Get Interface, 9.4.4 */
748 1.1 dyoung if (len > 0) {
749 1.12.6.1 skrll *(uint8_t *)buf = 0;
750 1.1 dyoung totlen = 1;
751 1.1 dyoung }
752 1.1 dyoung break;
753 1.1 dyoung case C(UR_GET_STATUS, UT_READ_DEVICE):
754 1.1 dyoung /* Get Status from device, 9.4.5 */
755 1.1 dyoung if (len > 1) {
756 1.1 dyoung USETW(((usb_status_t *)buf)->wStatus, UDS_SELF_POWERED);
757 1.1 dyoung totlen = 2;
758 1.1 dyoung }
759 1.1 dyoung break;
760 1.1 dyoung case C(UR_GET_STATUS, UT_READ_INTERFACE):
761 1.1 dyoung case C(UR_GET_STATUS, UT_READ_ENDPOINT):
762 1.1 dyoung /* Get Status from interface, endpoint, 9.4.5 */
763 1.1 dyoung if (len > 1) {
764 1.1 dyoung USETW(((usb_status_t *)buf)->wStatus, 0);
765 1.1 dyoung totlen = 2;
766 1.1 dyoung }
767 1.1 dyoung break;
768 1.1 dyoung case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
769 1.1 dyoung /* Set Address, 9.4.6 */
770 1.1 dyoung DPRINTF(D_MSG, ("UR_SET_ADDRESS "));
771 1.1 dyoung if (value >= USB_MAX_DEVICES) {
772 1.1 dyoung error = USBD_IOERROR;
773 1.1 dyoung goto ret;
774 1.1 dyoung }
775 1.1 dyoung sc->sc_addr = value;
776 1.1 dyoung break;
777 1.1 dyoung case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
778 1.1 dyoung /* Set Configuration, 9.4.7 */
779 1.1 dyoung DPRINTF(D_MSG, ("UR_SET_CONFIG "));
780 1.1 dyoung if (value != 0 && value != 1) {
781 1.1 dyoung error = USBD_IOERROR;
782 1.1 dyoung goto ret;
783 1.1 dyoung }
784 1.1 dyoung sc->sc_conf = value;
785 1.1 dyoung break;
786 1.1 dyoung case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
787 1.1 dyoung /* Set Descriptor, 9.4.8, not supported */
788 1.1 dyoung DPRINTF(D_MSG, ("UR_SET_DESCRIPTOR,WRITE_DEVICE not supported\n"));
789 1.1 dyoung break;
790 1.1 dyoung case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
791 1.1 dyoung case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
792 1.1 dyoung case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
793 1.1 dyoung /* Set Feature, 9.4.9, not supported */
794 1.1 dyoung DPRINTF(D_MSG, ("UR_SET_FEATURE not supported\n"));
795 1.1 dyoung error = USBD_IOERROR;
796 1.1 dyoung break;
797 1.1 dyoung case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
798 1.1 dyoung /* Set Interface, 9.4.10, not supported */
799 1.1 dyoung break;
800 1.1 dyoung case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
801 1.1 dyoung /* Synch Frame, 9.4.11, not supported */
802 1.1 dyoung break;
803 1.1 dyoung
804 1.1 dyoung /*
805 1.1 dyoung * Hub specific requests
806 1.1 dyoung */
807 1.1 dyoung case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
808 1.1 dyoung /* Clear Hub Feature, 11.16.2.1, not supported */
809 1.1 dyoung DPRINTF(D_MSG, ("ClearHubFeature not supported\n"));
810 1.1 dyoung break;
811 1.1 dyoung case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
812 1.1 dyoung
813 1.1 dyoung #define WPS(x) REG_WRITE(ADMHCD_REG_PORTSTATUS0+(index-1)*4, (x))
814 1.1 dyoung /* Clear Port Feature, 11.16.2.2 */
815 1.1 dyoung if (index != 1 && index != 2 ) {
816 1.1 dyoung error = USBD_IOERROR;
817 1.1 dyoung goto ret;
818 1.1 dyoung }
819 1.1 dyoung switch (value) {
820 1.1 dyoung case UHF_PORT_POWER:
821 1.1 dyoung DPRINTF(D_MSG, ("POWER_OFF "));
822 1.1 dyoung WPS(ADMHCD_LSDA);
823 1.1 dyoung break;
824 1.1 dyoung case UHF_PORT_SUSPEND:
825 1.1 dyoung DPRINTF(D_MSG, ("SUSPEND "));
826 1.1 dyoung WPS(ADMHCD_POCI);
827 1.1 dyoung break;
828 1.1 dyoung case UHF_PORT_ENABLE:
829 1.1 dyoung DPRINTF(D_MSG, ("ENABLE "));
830 1.1 dyoung WPS(ADMHCD_CCS);
831 1.1 dyoung break;
832 1.1 dyoung case UHF_C_PORT_CONNECTION:
833 1.1 dyoung WPS(ADMHCD_CSC);
834 1.1 dyoung break;
835 1.1 dyoung case UHF_C_PORT_RESET:
836 1.1 dyoung WPS(ADMHCD_PRSC);
837 1.1 dyoung break;
838 1.1 dyoung case UHF_C_PORT_SUSPEND:
839 1.1 dyoung WPS(ADMHCD_PSSC);
840 1.1 dyoung break;
841 1.1 dyoung case UHF_C_PORT_ENABLE:
842 1.1 dyoung WPS(ADMHCD_PESC);
843 1.1 dyoung break;
844 1.1 dyoung case UHF_C_PORT_OVER_CURRENT:
845 1.1 dyoung WPS(ADMHCD_OCIC);
846 1.1 dyoung break;
847 1.1 dyoung default:
848 1.1 dyoung printf("ClrPortFeatERR:value=0x%x ", value);
849 1.1 dyoung error = USBD_IOERROR;
850 1.1 dyoung break;
851 1.1 dyoung }
852 1.1 dyoung //DPRINTF(D_XFER, ("CH=%04x ", sc->sc_change));
853 1.1 dyoung #undef WPS
854 1.1 dyoung break;
855 1.1 dyoung case C(UR_GET_BUS_STATE, UT_READ_CLASS_OTHER):
856 1.1 dyoung /* Get Bus State, 11.16.2.3, not supported */
857 1.1 dyoung /* shall return a STALL... */
858 1.1 dyoung break;
859 1.1 dyoung case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
860 1.1 dyoung /* Get Hub Descriptor, 11.16.2.4 */
861 1.1 dyoung DPRINTF(D_MSG, ("UR_GET_DESCRIPTOR RCD"));
862 1.1 dyoung if ((value&0xff) != 0) {
863 1.1 dyoung error = USBD_IOERROR;
864 1.1 dyoung goto ret;
865 1.1 dyoung }
866 1.1 dyoung l = min(len, USB_HUB_DESCRIPTOR_SIZE);
867 1.1 dyoung totlen = l;
868 1.1 dyoung memcpy(buf, &ahci_hubd, l);
869 1.1 dyoung break;
870 1.1 dyoung case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
871 1.1 dyoung /* Get Hub Status, 11.16.2.5 */
872 1.1 dyoung DPRINTF(D_MSG, ("UR_GET_STATUS RCD"));
873 1.1 dyoung if (len != 4) {
874 1.1 dyoung error = USBD_IOERROR;
875 1.1 dyoung goto ret;
876 1.1 dyoung }
877 1.1 dyoung memset(buf, 0, len);
878 1.1 dyoung totlen = len;
879 1.1 dyoung break;
880 1.1 dyoung case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
881 1.1 dyoung /* Get Port Status, 11.16.2.6 */
882 1.1 dyoung if ((index != 1 && index != 2) || len != 4) {
883 1.1 dyoung printf("index=%d,len=%d ", index, len);
884 1.1 dyoung error = USBD_IOERROR;
885 1.1 dyoung goto ret;
886 1.1 dyoung }
887 1.1 dyoung status = REG_READ(ADMHCD_REG_PORTSTATUS0+(index-1)*4);
888 1.1 dyoung DPRINTF(D_MSG, ("UR_GET_STATUS RCO=%x ", status));
889 1.1 dyoung
890 1.1 dyoung //DPRINTF(D_XFER, ("ST=%04x,CH=%04x ", status, sc->sc_change));
891 1.1 dyoung USETW(ps.wPortStatus, status & (UPS_CURRENT_CONNECT_STATUS|UPS_PORT_ENABLED|UPS_SUSPEND|UPS_OVERCURRENT_INDICATOR|UPS_RESET|UPS_PORT_POWER|UPS_LOW_SPEED));
892 1.1 dyoung USETW(ps.wPortChange, (status>>16) & (UPS_C_CONNECT_STATUS|UPS_C_PORT_ENABLED|UPS_C_SUSPEND|UPS_C_OVERCURRENT_INDICATOR|UPS_C_PORT_RESET));
893 1.1 dyoung l = min(len, sizeof(ps));
894 1.1 dyoung memcpy(buf, &ps, l);
895 1.1 dyoung totlen = l;
896 1.1 dyoung break;
897 1.1 dyoung case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
898 1.1 dyoung /* Set Hub Descriptor, 11.16.2.7, not supported */
899 1.1 dyoung /* STALL ? */
900 1.1 dyoung error = USBD_IOERROR;
901 1.1 dyoung break;
902 1.1 dyoung case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
903 1.1 dyoung /* Set Hub Feature, 11.16.2.8, not supported */
904 1.1 dyoung break;
905 1.1 dyoung case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
906 1.1 dyoung #define WPS(x) REG_WRITE(ADMHCD_REG_PORTSTATUS0+(index-1)*4, (x))
907 1.1 dyoung /* Set Port Feature, 11.16.2.9 */
908 1.1 dyoung if ((index != 1) && (index !=2)) {
909 1.1 dyoung printf("index=%d ", index);
910 1.1 dyoung error = USBD_IOERROR;
911 1.1 dyoung goto ret;
912 1.1 dyoung }
913 1.1 dyoung switch (value) {
914 1.1 dyoung case UHF_PORT_RESET:
915 1.1 dyoung DPRINTF(D_MSG, ("PORT_RESET "));
916 1.1 dyoung WPS(ADMHCD_PRS);
917 1.1 dyoung break;
918 1.1 dyoung case UHF_PORT_POWER:
919 1.1 dyoung DPRINTF(D_MSG, ("PORT_POWER "));
920 1.1 dyoung WPS(ADMHCD_PPS);
921 1.1 dyoung break;
922 1.1 dyoung case UHF_PORT_ENABLE:
923 1.1 dyoung DPRINTF(D_MSG, ("PORT_ENABLE "));
924 1.1 dyoung WPS(ADMHCD_PES);
925 1.1 dyoung break;
926 1.1 dyoung default:
927 1.1 dyoung printf("SetPortFeatERR=0x%x ", value);
928 1.1 dyoung error = USBD_IOERROR;
929 1.1 dyoung break;
930 1.1 dyoung }
931 1.1 dyoung #undef WPS
932 1.1 dyoung break;
933 1.1 dyoung default:
934 1.1 dyoung DPRINTF(D_MSG, ("ioerr(UR=%02x,UT=%02x) ",
935 1.1 dyoung req->bRequest, req->bmRequestType));
936 1.1 dyoung error = USBD_IOERROR;
937 1.1 dyoung goto ret;
938 1.1 dyoung }
939 1.12.6.5 skrll xfer->ux_actlen = totlen;
940 1.1 dyoung error = USBD_NORMAL_COMPLETION;
941 1.1 dyoung ret:
942 1.12.6.5 skrll xfer->ux_status = error;
943 1.12 skrll mutex_enter(&sc->sc_lock);
944 1.1 dyoung usb_transfer_complete(xfer);
945 1.12 skrll mutex_exit(&sc->sc_lock);
946 1.1 dyoung return USBD_IN_PROGRESS;
947 1.1 dyoung }
948 1.1 dyoung
949 1.1 dyoung void
950 1.1 dyoung ahci_root_ctrl_abort(usbd_xfer_handle xfer)
951 1.1 dyoung {
952 1.1 dyoung DPRINTF(D_TRACE, ("SLRCabort "));
953 1.1 dyoung }
954 1.1 dyoung
955 1.1 dyoung void
956 1.1 dyoung ahci_root_ctrl_close(usbd_pipe_handle pipe)
957 1.1 dyoung {
958 1.1 dyoung DPRINTF(D_TRACE, ("SLRCclose "));
959 1.1 dyoung }
960 1.1 dyoung
961 1.1 dyoung void
962 1.1 dyoung ahci_root_ctrl_done(usbd_xfer_handle xfer)
963 1.1 dyoung {
964 1.1 dyoung DPRINTF(D_TRACE, ("SLRCdone\n"));
965 1.1 dyoung }
966 1.1 dyoung
967 1.1 dyoung static usbd_status
968 1.1 dyoung ahci_root_intr_transfer(usbd_xfer_handle xfer)
969 1.1 dyoung {
970 1.12.6.5 skrll struct ahci_softc *sc = (struct ahci_softc *)xfer->ux_pipe->up_dev->ud_bus;
971 1.1 dyoung usbd_status error;
972 1.1 dyoung
973 1.1 dyoung DPRINTF(D_TRACE, ("SLRItransfer "));
974 1.1 dyoung
975 1.1 dyoung /* Insert last in queue */
976 1.12 skrll mutex_enter(&sc->sc_lock);
977 1.1 dyoung error = usb_insert_transfer(xfer);
978 1.12 skrll mutex_exit(&sc->sc_lock);
979 1.1 dyoung if (error)
980 1.1 dyoung return error;
981 1.1 dyoung
982 1.1 dyoung /*
983 1.1 dyoung * Pipe isn't running (otherwise error would be USBD_INPROG),
984 1.1 dyoung * start first.
985 1.1 dyoung */
986 1.12.6.5 skrll return ahci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
987 1.1 dyoung }
988 1.1 dyoung
989 1.1 dyoung static usbd_status
990 1.1 dyoung ahci_root_intr_start(usbd_xfer_handle xfer)
991 1.1 dyoung {
992 1.12.6.5 skrll usbd_pipe_handle pipe = xfer->ux_pipe;
993 1.12.6.5 skrll struct ahci_softc *sc = (struct ahci_softc *)pipe->up_dev->ud_bus;
994 1.1 dyoung
995 1.1 dyoung DPRINTF(D_TRACE, ("SLRIstart "));
996 1.1 dyoung
997 1.12.6.5 skrll sc->sc_interval = MS_TO_TICKS(xfer->ux_pipe->up_endpoint->ue_edesc->bInterval);
998 1.6 dyoung callout_reset(&sc->sc_poll_handle, sc->sc_interval, ahci_poll_hub, xfer);
999 1.1 dyoung sc->sc_intr_xfer = xfer;
1000 1.1 dyoung return USBD_IN_PROGRESS;
1001 1.1 dyoung }
1002 1.1 dyoung
1003 1.1 dyoung static void
1004 1.1 dyoung ahci_root_intr_abort(usbd_xfer_handle xfer)
1005 1.1 dyoung {
1006 1.1 dyoung DPRINTF(D_TRACE, ("SLRIabort "));
1007 1.1 dyoung }
1008 1.1 dyoung
1009 1.1 dyoung static void
1010 1.1 dyoung ahci_root_intr_close(usbd_pipe_handle pipe)
1011 1.1 dyoung {
1012 1.12.6.5 skrll struct ahci_softc *sc = (struct ahci_softc *)pipe->up_dev->ud_bus;
1013 1.1 dyoung
1014 1.1 dyoung DPRINTF(D_TRACE, ("SLRIclose "));
1015 1.1 dyoung
1016 1.6 dyoung callout_stop(&sc->sc_poll_handle);
1017 1.1 dyoung sc->sc_intr_xfer = NULL;
1018 1.1 dyoung }
1019 1.1 dyoung
1020 1.1 dyoung static void
1021 1.1 dyoung ahci_root_intr_done(usbd_xfer_handle xfer)
1022 1.1 dyoung {
1023 1.1 dyoung //DPRINTF(D_XFER, ("RIdn "));
1024 1.1 dyoung }
1025 1.1 dyoung
1026 1.1 dyoung static usbd_status
1027 1.1 dyoung ahci_device_ctrl_transfer(usbd_xfer_handle xfer)
1028 1.1 dyoung {
1029 1.12.6.5 skrll struct ahci_softc *sc = (struct ahci_softc *)xfer->ux_pipe->up_dev->ud_bus;
1030 1.1 dyoung usbd_status error;
1031 1.1 dyoung
1032 1.1 dyoung DPRINTF(D_TRACE, ("C"));
1033 1.1 dyoung
1034 1.12 skrll mutex_enter(&sc->sc_lock);
1035 1.1 dyoung error = usb_insert_transfer(xfer);
1036 1.12 skrll mutex_exit(&sc->sc_lock);
1037 1.1 dyoung if (error)
1038 1.1 dyoung return error;
1039 1.1 dyoung
1040 1.12.6.5 skrll return ahci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
1041 1.1 dyoung }
1042 1.1 dyoung
1043 1.1 dyoung static usbd_status
1044 1.1 dyoung ahci_device_ctrl_start(usbd_xfer_handle xfer)
1045 1.1 dyoung {
1046 1.1 dyoung usbd_status status = USBD_NORMAL_COMPLETION;
1047 1.1 dyoung int s, err;
1048 1.1 dyoung static struct admhcd_ed ep_v __attribute__((aligned(16))), *ep;
1049 1.1 dyoung static struct admhcd_td td_v[4] __attribute__((aligned(16))), *td, *td1, *td2, *td3;
1050 1.1 dyoung static usb_dma_t reqdma;
1051 1.12.6.5 skrll usbd_pipe_handle pipe = xfer->ux_pipe;
1052 1.12.6.5 skrll usb_device_request_t *req = &xfer->ux_request;
1053 1.12.6.5 skrll struct ahci_softc *sc = (struct ahci_softc *)pipe->up_dev->ud_bus;
1054 1.1 dyoung int len, isread;
1055 1.11 skrll
1056 1.1 dyoung
1057 1.1 dyoung #if 0
1058 1.12.6.5 skrll struct ahci_pipe *apipe = (struct ahci_pipe *)xfer->ux_pipe;
1059 1.1 dyoung #endif
1060 1.12 skrll mutex_enter(&sc->sc_lock);
1061 1.1 dyoung /* printf("ctrl_start>>>\n"); */
1062 1.1 dyoung
1063 1.1 dyoung #ifdef DIAGNOSTIC
1064 1.12.6.5 skrll if (!(xfer->ux_rqflags & URQ_REQUEST)) {
1065 1.12.6.2 skrll /* XXX panic */
1066 1.12.6.2 skrll printf("ahci_device_ctrl_transfer: not a request\n");
1067 1.12.6.2 skrll return (USBD_INVAL);
1068 1.12.6.2 skrll }
1069 1.1 dyoung #endif
1070 1.1 dyoung
1071 1.12.6.1 skrll #define KSEG1ADDR(x) (0xa0000000 | (((uint32_t)x) & 0x1fffffff))
1072 1.1 dyoung DPRINTF(D_TRACE, ("st "));
1073 1.1 dyoung if (!ep) {
1074 1.12.6.2 skrll ep = (struct admhcd_ed *)KSEG1ADDR(&ep_v);
1075 1.11 skrll td = (struct admhcd_td *)KSEG1ADDR(&td_v[0]);
1076 1.11 skrll td1 = (struct admhcd_td *)KSEG1ADDR(&td_v[1]);
1077 1.11 skrll td2 = (struct admhcd_td *)KSEG1ADDR(&td_v[2]);
1078 1.11 skrll td3 = (struct admhcd_td *)KSEG1ADDR(&td_v[3]);
1079 1.1 dyoung err = usb_allocmem(&sc->sc_bus,
1080 1.1 dyoung sizeof(usb_device_request_t),
1081 1.1 dyoung 0, &reqdma);
1082 1.1 dyoung if (err)
1083 1.1 dyoung return (USBD_NOMEM);
1084 1.1 dyoung
1085 1.1 dyoung /* printf("ep: %p\n",ep); */
1086 1.1 dyoung };
1087 1.1 dyoung
1088 1.12.6.5 skrll ep->control = pipe->up_dev->ud_addr | \
1089 1.12.6.5 skrll ((pipe->up_dev->ud_speed==USB_SPEED_FULL)?ADMHCD_ED_SPEED:0) | \
1090 1.12.6.5 skrll ((UGETW(pipe->up_endpoint->ue_edesc->wMaxPacketSize))<<ADMHCD_ED_MAXSHIFT);
1091 1.1 dyoung memcpy(KERNADDR(&reqdma, 0), req, sizeof *req);
1092 1.1 dyoung /* printf("status: %x\n",REG_READ(ADMHCD_REG_PORTSTATUS0));
1093 1.1 dyoung printf("ep_control: %x\n",ep->control);
1094 1.12.6.5 skrll printf("speed: %x\n",pipe->up_dev->ud_speed);
1095 1.1 dyoung printf("req: %p\n",req);
1096 1.12.6.5 skrll printf("dmabuf: %p\n",xfer->ux_dmabuf.block); */
1097 1.1 dyoung
1098 1.1 dyoung isread = req->bmRequestType & UT_READ;
1099 1.1 dyoung len = UGETW(req->wLength);
1100 1.1 dyoung
1101 1.12.6.2 skrll ep->next = ep;
1102 1.1 dyoung
1103 1.12.6.2 skrll td->buffer = DMAADDR(&reqdma,0) | 0xa0000000;
1104 1.12.6.2 skrll td->buflen=sizeof(*req);
1105 1.12.6.2 skrll td->control=ADMHCD_TD_SETUP | ADMHCD_TD_DATA0 | ADMHCD_TD_OWN;
1106 1.1 dyoung
1107 1.1 dyoung if (len) {
1108 1.1 dyoung td->next = td1;
1109 1.1 dyoung
1110 1.12.6.5 skrll td1->buffer = DMAADDR(&xfer->ux_dmabuf,0) | 0xa0000000;
1111 1.1 dyoung td1->buflen = len;
1112 1.1 dyoung td1->next = td2;
1113 1.1 dyoung td1->control= (isread?ADMHCD_TD_IN:ADMHCD_TD_OUT) | ADMHCD_TD_DATA1 | ADMHCD_TD_R | ADMHCD_TD_OWN;
1114 1.12.6.2 skrll } else {
1115 1.12.6.2 skrll td1->control = 0;
1116 1.12.6.2 skrll td->next = td2;
1117 1.12.6.2 skrll };
1118 1.1 dyoung
1119 1.1 dyoung td2->buffer = 0;
1120 1.1 dyoung td2->buflen= 0;
1121 1.1 dyoung td2->next = td3;
1122 1.1 dyoung td2->control = (isread?ADMHCD_TD_OUT:ADMHCD_TD_IN) | ADMHCD_TD_DATA1 | ADMHCD_TD_OWN;
1123 1.1 dyoung
1124 1.1 dyoung td3->buffer = 0;
1125 1.1 dyoung td3->buflen= 0;
1126 1.1 dyoung td3->next = 0;
1127 1.1 dyoung td3->control = 0;
1128 1.1 dyoung
1129 1.1 dyoung ep->head = td;
1130 1.1 dyoung ep->tail = td3;
1131 1.1 dyoung /*
1132 1.1 dyoung printf("ep: %p\n",ep);
1133 1.1 dyoung printf("ep->next: %p\n",ep->next);
1134 1.1 dyoung printf("ep->head: %p\n",ep->head);
1135 1.1 dyoung printf("ep->tail: %p\n",ep->tail);
1136 1.1 dyoung printf("td: %p\n",td);
1137 1.1 dyoung printf("td->next: %p\n",td->next);
1138 1.1 dyoung printf("td->buffer: %x\n",td->buffer);
1139 1.1 dyoung printf("td->buflen: %x\n",td->buflen);
1140 1.1 dyoung printf("td1: %p\n",td1);
1141 1.1 dyoung printf("td1->next: %p\n",td1->next);
1142 1.1 dyoung printf("td2: %p\n",td2);
1143 1.1 dyoung printf("td2->next: %p\n",td2->next);
1144 1.1 dyoung printf("td3: %p\n",td3);
1145 1.1 dyoung printf("td3->next: %p\n",td3->next);
1146 1.1 dyoung */
1147 1.1 dyoung
1148 1.12.6.2 skrll REG_WRITE(ADMHCD_REG_HOSTHEAD, (uint32_t)ep);
1149 1.12.6.2 skrll REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP | ADMHCD_DMA_EN);
1150 1.1 dyoung /* printf("1: %x %x %x %x\n", ep->control, td->control, td1->control, td2->control); */
1151 1.12.6.2 skrll s=100;
1152 1.12.6.2 skrll while (s--) {
1153 1.12.6.2 skrll delay_ms(10);
1154 1.1 dyoung /* printf("%x %x %x %x\n", ep->control, td->control, td1->control, td2->control);*/
1155 1.1 dyoung status = USBD_TIMEOUT;
1156 1.12.6.2 skrll if (td->control & ADMHCD_TD_OWN) continue;
1157 1.1 dyoung
1158 1.12.6.2 skrll err = (td->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT;
1159 1.12.6.2 skrll if (err) {
1160 1.1 dyoung status = USBD_IOERROR;
1161 1.12.6.2 skrll break;
1162 1.12.6.2 skrll };
1163 1.1 dyoung
1164 1.1 dyoung status = USBD_TIMEOUT;
1165 1.12.6.2 skrll if (td1->control & ADMHCD_TD_OWN) continue;
1166 1.12.6.2 skrll err = (td1->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT;
1167 1.12.6.2 skrll if (err) {
1168 1.1 dyoung status = USBD_IOERROR;
1169 1.12.6.2 skrll break;
1170 1.12.6.2 skrll };
1171 1.1 dyoung
1172 1.1 dyoung status = USBD_TIMEOUT;
1173 1.12.6.2 skrll if (td2->control & ADMHCD_TD_OWN) continue;
1174 1.12.6.2 skrll err = (td2->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT;
1175 1.12.6.2 skrll if (err) {
1176 1.1 dyoung status = USBD_IOERROR;
1177 1.12.6.2 skrll };
1178 1.1 dyoung status = USBD_NORMAL_COMPLETION;
1179 1.12.6.2 skrll break;
1180 1.1 dyoung
1181 1.1 dyoung };
1182 1.12.6.2 skrll REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP);
1183 1.1 dyoung
1184 1.12.6.5 skrll xfer->ux_actlen = len;
1185 1.12.6.5 skrll xfer->ux_status = status;
1186 1.1 dyoung
1187 1.1 dyoung /* printf("ctrl_start<<<\n"); */
1188 1.1 dyoung
1189 1.1 dyoung usb_transfer_complete(xfer);
1190 1.12 skrll mutex_exit(&sc->sc_lock);
1191 1.12 skrll return USBD_NORMAL_COMPLETION;
1192 1.1 dyoung }
1193 1.1 dyoung
1194 1.1 dyoung static void
1195 1.1 dyoung ahci_device_ctrl_abort(usbd_xfer_handle xfer)
1196 1.1 dyoung {
1197 1.1 dyoung DPRINTF(D_TRACE, ("Cab "));
1198 1.1 dyoung ahci_abort_xfer(xfer, USBD_CANCELLED);
1199 1.1 dyoung }
1200 1.1 dyoung
1201 1.1 dyoung static void
1202 1.1 dyoung ahci_device_ctrl_close(usbd_pipe_handle pipe)
1203 1.1 dyoung {
1204 1.1 dyoung DPRINTF(D_TRACE, ("Ccl "));
1205 1.1 dyoung }
1206 1.1 dyoung
1207 1.1 dyoung static void
1208 1.1 dyoung ahci_device_ctrl_done(usbd_xfer_handle xfer)
1209 1.1 dyoung {
1210 1.1 dyoung DPRINTF(D_TRACE, ("Cdn "));
1211 1.1 dyoung }
1212 1.1 dyoung
1213 1.1 dyoung static usbd_status
1214 1.1 dyoung ahci_device_intr_transfer(usbd_xfer_handle xfer)
1215 1.1 dyoung {
1216 1.12.6.5 skrll struct ahci_softc *sc = (struct ahci_softc *)xfer->ux_pipe->up_dev->ud_bus;
1217 1.1 dyoung usbd_status error;
1218 1.1 dyoung
1219 1.1 dyoung DPRINTF(D_TRACE, ("INTRtrans "));
1220 1.1 dyoung
1221 1.12 skrll mutex_enter(&sc->sc_lock);
1222 1.1 dyoung error = usb_insert_transfer(xfer);
1223 1.12 skrll mutex_exit(&sc->sc_lock);
1224 1.1 dyoung if (error)
1225 1.1 dyoung return error;
1226 1.1 dyoung
1227 1.12.6.5 skrll return ahci_device_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
1228 1.1 dyoung }
1229 1.1 dyoung
1230 1.1 dyoung static usbd_status
1231 1.1 dyoung ahci_device_intr_start(usbd_xfer_handle xfer)
1232 1.1 dyoung {
1233 1.12.6.5 skrll usbd_pipe_handle pipe = xfer->ux_pipe;
1234 1.1 dyoung struct ahci_xfer *sx;
1235 1.1 dyoung
1236 1.1 dyoung DPRINTF(D_TRACE, ("INTRstart "));
1237 1.1 dyoung
1238 1.12.6.8 skrll sx = kmem_intr_alloc(sizeof(*sx), KM_NOSLEEP);
1239 1.1 dyoung if (sx == NULL)
1240 1.1 dyoung goto reterr;
1241 1.1 dyoung memset(sx, 0, sizeof(*sx));
1242 1.1 dyoung sx->sx_xfer = xfer;
1243 1.12.6.5 skrll xfer->ux_hcpriv = sx;
1244 1.1 dyoung
1245 1.1 dyoung /* initialize callout */
1246 1.6 dyoung callout_init(&sx->sx_callout_t, 0);
1247 1.11 skrll callout_reset(&sx->sx_callout_t,
1248 1.12.6.5 skrll MS_TO_TICKS(pipe->up_endpoint->ue_edesc->bInterval),
1249 1.1 dyoung ahci_poll_device, sx);
1250 1.1 dyoung
1251 1.1 dyoung /* ACK */
1252 1.1 dyoung return USBD_IN_PROGRESS;
1253 1.1 dyoung
1254 1.1 dyoung reterr:
1255 1.1 dyoung return USBD_IOERROR;
1256 1.1 dyoung }
1257 1.1 dyoung
1258 1.1 dyoung static void
1259 1.1 dyoung ahci_poll_device(void *arg)
1260 1.1 dyoung {
1261 1.1 dyoung struct ahci_xfer *sx = (struct ahci_xfer *)arg;
1262 1.1 dyoung usbd_xfer_handle xfer = sx->sx_xfer;
1263 1.12.6.5 skrll usbd_pipe_handle pipe = xfer->ux_pipe;
1264 1.12.6.5 skrll struct ahci_softc *sc = (struct ahci_softc *)pipe->up_dev->ud_bus;
1265 1.1 dyoung void *buf;
1266 1.1 dyoung int pid;
1267 1.1 dyoung int r;
1268 1.1 dyoung
1269 1.1 dyoung DPRINTF(D_TRACE, ("pldev"));
1270 1.1 dyoung
1271 1.6 dyoung callout_reset(&sx->sx_callout_t,
1272 1.12.6.5 skrll MS_TO_TICKS(pipe->up_endpoint->ue_edesc->bInterval),
1273 1.1 dyoung ahci_poll_device, sx);
1274 1.1 dyoung
1275 1.1 dyoung /* interrupt transfer */
1276 1.12.6.5 skrll pid = (UE_GET_DIR(pipe->up_endpoint->ue_edesc->bEndpointAddress) == UE_DIR_IN)
1277 1.1 dyoung ? ADMHCD_TD_IN : ADMHCD_TD_OUT;
1278 1.12.6.5 skrll buf = KERNADDR(&xfer->ux_dmabuf, 0);
1279 1.1 dyoung
1280 1.12.6.5 skrll r = ahci_transaction(sc, pipe, pid, xfer->ux_length, buf, 0/*toggle*/);
1281 1.1 dyoung if (r < 0) {
1282 1.2 perry DPRINTF(D_MSG, ("%s error", __func__));
1283 1.1 dyoung return;
1284 1.1 dyoung }
1285 1.1 dyoung /* no change, return NAK */
1286 1.1 dyoung if (r == 0)
1287 1.1 dyoung return;
1288 1.1 dyoung
1289 1.12.6.5 skrll xfer->ux_status = USBD_NORMAL_COMPLETION;
1290 1.12 skrll mutex_enter(&sc->sc_lock);
1291 1.1 dyoung usb_transfer_complete(xfer);
1292 1.12 skrll mutex_exit(&sc->sc_lock);
1293 1.1 dyoung }
1294 1.1 dyoung
1295 1.1 dyoung static void
1296 1.1 dyoung ahci_device_intr_abort(usbd_xfer_handle xfer)
1297 1.1 dyoung {
1298 1.1 dyoung struct ahci_xfer *sx;
1299 1.1 dyoung
1300 1.1 dyoung DPRINTF(D_TRACE, ("INTRabort "));
1301 1.1 dyoung
1302 1.12.6.5 skrll sx = xfer->ux_hcpriv;
1303 1.1 dyoung if (sx) {
1304 1.6 dyoung callout_stop(&sx->sx_callout_t);
1305 1.12.6.8 skrll kmem_intr_free(sx, sizeof(*sx));
1306 1.12.6.5 skrll xfer->ux_hcpriv = NULL;
1307 1.1 dyoung } else {
1308 1.2 perry printf("%s: sx == NULL!\n", __func__);
1309 1.1 dyoung }
1310 1.1 dyoung ahci_abort_xfer(xfer, USBD_CANCELLED);
1311 1.1 dyoung }
1312 1.1 dyoung
1313 1.1 dyoung static void
1314 1.1 dyoung ahci_device_intr_close(usbd_pipe_handle pipe)
1315 1.1 dyoung {
1316 1.1 dyoung DPRINTF(D_TRACE, ("INTRclose "));
1317 1.1 dyoung }
1318 1.1 dyoung
1319 1.1 dyoung static void
1320 1.1 dyoung ahci_device_intr_done(usbd_xfer_handle xfer)
1321 1.1 dyoung {
1322 1.1 dyoung DPRINTF(D_TRACE, ("INTRdone "));
1323 1.1 dyoung }
1324 1.1 dyoung
1325 1.1 dyoung static usbd_status
1326 1.1 dyoung ahci_device_isoc_transfer(usbd_xfer_handle xfer)
1327 1.1 dyoung {
1328 1.1 dyoung DPRINTF(D_TRACE, ("S"));
1329 1.1 dyoung return USBD_NORMAL_COMPLETION;
1330 1.1 dyoung }
1331 1.1 dyoung
1332 1.1 dyoung static usbd_status
1333 1.1 dyoung ahci_device_isoc_start(usbd_xfer_handle xfer)
1334 1.1 dyoung {
1335 1.1 dyoung DPRINTF(D_TRACE, ("st "));
1336 1.1 dyoung return USBD_NORMAL_COMPLETION;
1337 1.1 dyoung }
1338 1.1 dyoung
1339 1.1 dyoung static void
1340 1.1 dyoung ahci_device_isoc_abort(usbd_xfer_handle xfer)
1341 1.1 dyoung {
1342 1.1 dyoung DPRINTF(D_TRACE, ("Sab "));
1343 1.1 dyoung }
1344 1.1 dyoung
1345 1.1 dyoung static void
1346 1.1 dyoung ahci_device_isoc_close(usbd_pipe_handle pipe)
1347 1.1 dyoung {
1348 1.1 dyoung DPRINTF(D_TRACE, ("Scl "));
1349 1.1 dyoung }
1350 1.1 dyoung
1351 1.1 dyoung static void
1352 1.1 dyoung ahci_device_isoc_done(usbd_xfer_handle xfer)
1353 1.1 dyoung {
1354 1.1 dyoung DPRINTF(D_TRACE, ("Sdn "));
1355 1.1 dyoung }
1356 1.1 dyoung
1357 1.1 dyoung static usbd_status
1358 1.1 dyoung ahci_device_bulk_transfer(usbd_xfer_handle xfer)
1359 1.1 dyoung {
1360 1.12.6.5 skrll struct ahci_softc *sc = (struct ahci_softc *)xfer->ux_pipe->up_dev->ud_bus;
1361 1.1 dyoung usbd_status error;
1362 1.1 dyoung
1363 1.1 dyoung DPRINTF(D_TRACE, ("B"));
1364 1.1 dyoung
1365 1.12 skrll mutex_enter(&sc->sc_lock);
1366 1.1 dyoung error = usb_insert_transfer(xfer);
1367 1.12 skrll mutex_exit(&sc->sc_lock);
1368 1.1 dyoung if (error)
1369 1.1 dyoung return error;
1370 1.1 dyoung
1371 1.12.6.5 skrll return ahci_device_bulk_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
1372 1.1 dyoung }
1373 1.1 dyoung
1374 1.1 dyoung static usbd_status
1375 1.1 dyoung ahci_device_bulk_start(usbd_xfer_handle xfer)
1376 1.1 dyoung {
1377 1.1 dyoung #define NBULK_TDS 32
1378 1.1 dyoung static volatile int level = 0;
1379 1.1 dyoung usbd_status status = USBD_NORMAL_COMPLETION;
1380 1.1 dyoung int s, err;
1381 1.1 dyoung static struct admhcd_ed ep_v __attribute__((aligned(16))), *ep;
1382 1.1 dyoung static struct admhcd_td td_v[NBULK_TDS] __attribute__((aligned(16))), *td[NBULK_TDS];
1383 1.12.6.5 skrll usbd_pipe_handle pipe = xfer->ux_pipe;
1384 1.12.6.5 skrll struct ahci_softc *sc = (struct ahci_softc *)pipe->up_dev->ud_bus;
1385 1.1 dyoung int endpt, i, len, tlen, segs, offset, isread, toggle, short_ok;
1386 1.12.6.5 skrll struct ahci_pipe *apipe = (struct ahci_pipe *)xfer->ux_pipe;
1387 1.1 dyoung
1388 1.12.6.1 skrll #define KSEG1ADDR(x) (0xa0000000 | (((uint32_t)x) & 0x1fffffff))
1389 1.1 dyoung DPRINTF(D_TRACE, ("st "));
1390 1.1 dyoung
1391 1.1 dyoung #ifdef DIAGNOSTIC
1392 1.12.6.5 skrll if (xfer->ux_rqflags & URQ_REQUEST) {
1393 1.1 dyoung /* XXX panic */
1394 1.1 dyoung printf("ohci_device_bulk_start: a request\n");
1395 1.1 dyoung return (USBD_INVAL);
1396 1.1 dyoung }
1397 1.1 dyoung #endif
1398 1.1 dyoung
1399 1.12 skrll mutex_enter(&sc->sc_lock);
1400 1.1 dyoung level++;
1401 1.1 dyoung /* printf("bulk_start>>>\n"); */
1402 1.1 dyoung
1403 1.1 dyoung if (!ep) {
1404 1.12.6.2 skrll ep = (struct admhcd_ed *)KSEG1ADDR(&ep_v);
1405 1.1 dyoung for (i=0; i<NBULK_TDS; i++) {
1406 1.11 skrll td[i] = (struct admhcd_td *)KSEG1ADDR(&td_v[i]);
1407 1.1 dyoung };
1408 1.1 dyoung /* printf("ep: %p\n",ep);*/
1409 1.1 dyoung };
1410 1.1 dyoung if (apipe->toggle == 0) {
1411 1.1 dyoung toggle = ADMHCD_TD_DATA0;
1412 1.1 dyoung } else {
1413 1.1 dyoung toggle = apipe->toggle;
1414 1.1 dyoung };
1415 1.1 dyoung
1416 1.12.6.5 skrll endpt = pipe->up_endpoint->ue_edesc->bEndpointAddress;
1417 1.12.6.5 skrll ep->control = pipe->up_dev->ud_addr | ((endpt & 0xf) << ADMHCD_ED_EPSHIFT)|\
1418 1.12.6.5 skrll ((pipe->up_dev->ud_speed==USB_SPEED_FULL)?ADMHCD_ED_SPEED:0) | \
1419 1.12.6.5 skrll ((UGETW(pipe->up_endpoint->ue_edesc->wMaxPacketSize))<<ADMHCD_ED_MAXSHIFT);
1420 1.1 dyoung
1421 1.12.6.5 skrll short_ok = xfer->ux_flags & USBD_SHORT_XFER_OK?ADMHCD_TD_R:0;
1422 1.1 dyoung /* printf("level: %d\n",level);
1423 1.1 dyoung printf("short_xfer: %x\n",short_ok);
1424 1.1 dyoung printf("ep_control: %x\n",ep->control);
1425 1.12.6.5 skrll printf("speed: %x\n",pipe->up_dev->ud_speed);
1426 1.12.6.5 skrll printf("dmabuf: %p\n",xfer->ux_dmabuf.block); */
1427 1.1 dyoung
1428 1.12.6.2 skrll isread = UE_GET_DIR(endpt) == UE_DIR_IN;
1429 1.12.6.5 skrll len = xfer->ux_length;
1430 1.1 dyoung
1431 1.12.6.2 skrll ep->next = ep;
1432 1.1 dyoung
1433 1.1 dyoung i = 0;
1434 1.1 dyoung offset = 0;
1435 1.1 dyoung while ((len>0) || (i==0)) {
1436 1.1 dyoung tlen = min(len,4096);
1437 1.12.6.5 skrll td[i]->buffer = DMAADDR(&xfer->ux_dmabuf,offset) | 0xa0000000;
1438 1.1 dyoung td[i]->buflen=tlen;
1439 1.1 dyoung td[i]->control=(isread?ADMHCD_TD_IN:ADMHCD_TD_OUT) | toggle | ADMHCD_TD_OWN | short_ok;
1440 1.1 dyoung td[i]->len=tlen;
1441 1.1 dyoung toggle = ADMHCD_TD_TOGGLE;
1442 1.1 dyoung len -= tlen;
1443 1.1 dyoung offset += tlen;
1444 1.1 dyoung td[i]->next = td[i+1];
1445 1.1 dyoung i++;
1446 1.1 dyoung };
1447 1.1 dyoung
1448 1.1 dyoung td[i]->buffer = 0;
1449 1.1 dyoung td[i]->buflen = 0;
1450 1.1 dyoung td[i]->control = 0;
1451 1.1 dyoung td[i]->next = 0;
1452 1.1 dyoung
1453 1.1 dyoung ep->head = td[0];
1454 1.1 dyoung ep->tail = td[i];
1455 1.1 dyoung segs = i;
1456 1.1 dyoung len = 0;
1457 1.1 dyoung
1458 1.1 dyoung /* printf("segs: %d\n",segs);
1459 1.1 dyoung printf("ep: %p\n",ep);
1460 1.1 dyoung printf("ep->control: %x\n",ep->control);
1461 1.1 dyoung printf("ep->next: %p\n",ep->next);
1462 1.1 dyoung printf("ep->head: %p\n",ep->head);
1463 1.1 dyoung printf("ep->tail: %p\n",ep->tail);
1464 1.1 dyoung for (i=0; i<segs; i++) {
1465 1.1 dyoung printf("td[%d]: %p\n",i,td[i]);
1466 1.1 dyoung printf("td[%d]->control: %x\n",i,td[i]->control);
1467 1.1 dyoung printf("td[%d]->next: %p\n",i,td[i]->next);
1468 1.1 dyoung printf("td[%d]->buffer: %x\n",i,td[i]->buffer);
1469 1.1 dyoung printf("td[%d]->buflen: %x\n",i,td[i]->buflen);
1470 1.1 dyoung }; */
1471 1.1 dyoung
1472 1.12.6.2 skrll REG_WRITE(ADMHCD_REG_HOSTHEAD, (uint32_t)ep);
1473 1.12.6.2 skrll REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP | ADMHCD_DMA_EN);
1474 1.1 dyoung i = 0;
1475 1.1 dyoung /* printf("1: %x %d %x %x\n", ep->control, i, td[i]->control, td[i]->buflen); */
1476 1.12.6.2 skrll s=100;
1477 1.1 dyoung err = 0;
1478 1.12.6.2 skrll while (s--) {
1479 1.1 dyoung /* printf("%x %d %x %x\n", ep->control, i, td[i]->control, td[i]->buflen); */
1480 1.1 dyoung status = USBD_TIMEOUT;
1481 1.12.6.2 skrll if (td[i]->control & ADMHCD_TD_OWN) {
1482 1.1 dyoung delay_ms(3);
1483 1.1 dyoung continue;
1484 1.1 dyoung };
1485 1.1 dyoung
1486 1.1 dyoung len += td[i]->len - td[i]->buflen;
1487 1.1 dyoung
1488 1.12.6.2 skrll err = (td[i]->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT;
1489 1.12.6.2 skrll if (err) {
1490 1.1 dyoung status = USBD_IOERROR;
1491 1.12.6.2 skrll break;
1492 1.12.6.2 skrll };
1493 1.11 skrll
1494 1.1 dyoung i++;
1495 1.1 dyoung if (i==segs) {
1496 1.1 dyoung status = USBD_NORMAL_COMPLETION;
1497 1.1 dyoung break;
1498 1.1 dyoung };
1499 1.1 dyoung
1500 1.1 dyoung };
1501 1.12.6.2 skrll REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP);
1502 1.1 dyoung
1503 1.12.6.1 skrll apipe->toggle = ((uint32_t)ep->head & 2)?ADMHCD_TD_DATA1:ADMHCD_TD_DATA0;
1504 1.1 dyoung /* printf("bulk_transfer_done: status: %x, err: %x, len: %x, toggle: %x\n", status,err,len,apipe->toggle); */
1505 1.1 dyoung
1506 1.1 dyoung if (short_ok && (err == 0x9 || err == 0xd)) {
1507 1.1 dyoung /* printf("bulk_transfer_done: short_transfer fix\n"); */
1508 1.1 dyoung status = USBD_NORMAL_COMPLETION;
1509 1.1 dyoung };
1510 1.12.6.5 skrll xfer->ux_actlen = len;
1511 1.12.6.5 skrll xfer->ux_status = status;
1512 1.1 dyoung
1513 1.1 dyoung level--;
1514 1.1 dyoung /* printf("bulk_start<<<\n"); */
1515 1.1 dyoung
1516 1.1 dyoung usb_transfer_complete(xfer);
1517 1.12 skrll mutex_exit(&sc->sc_lock);
1518 1.12 skrll
1519 1.12 skrll return USBD_NORMAL_COMPLETION;
1520 1.1 dyoung }
1521 1.1 dyoung
1522 1.1 dyoung static void
1523 1.1 dyoung ahci_device_bulk_abort(usbd_xfer_handle xfer)
1524 1.1 dyoung {
1525 1.1 dyoung DPRINTF(D_TRACE, ("Bab "));
1526 1.1 dyoung ahci_abort_xfer(xfer, USBD_CANCELLED);
1527 1.1 dyoung }
1528 1.1 dyoung
1529 1.1 dyoung static void
1530 1.1 dyoung ahci_device_bulk_close(usbd_pipe_handle pipe)
1531 1.1 dyoung {
1532 1.1 dyoung DPRINTF(D_TRACE, ("Bcl "));
1533 1.1 dyoung }
1534 1.1 dyoung
1535 1.1 dyoung static void
1536 1.1 dyoung ahci_device_bulk_done(usbd_xfer_handle xfer)
1537 1.1 dyoung {
1538 1.1 dyoung DPRINTF(D_TRACE, ("Bdn "));
1539 1.1 dyoung }
1540 1.1 dyoung
1541 1.1 dyoung #define DATA0_RD (0x03)
1542 1.1 dyoung #define DATA0_WR (0x07)
1543 1.1 dyoung #define AHCI_TIMEOUT (5000)
1544 1.1 dyoung
1545 1.1 dyoung /*
1546 1.1 dyoung * Do a transaction.
1547 1.1 dyoung * return 1 if ACK, 0 if NAK, -1 if error.
1548 1.1 dyoung */
1549 1.1 dyoung static int
1550 1.1 dyoung ahci_transaction(struct ahci_softc *sc, usbd_pipe_handle pipe,
1551 1.12.6.1 skrll uint8_t pid, int len, u_char *buf, uint8_t toggle)
1552 1.1 dyoung {
1553 1.1 dyoung return -1;
1554 1.1 dyoung #if 0
1555 1.1 dyoung #ifdef AHCI_DEBUG
1556 1.1 dyoung char str[64];
1557 1.1 dyoung int i;
1558 1.1 dyoung #endif
1559 1.1 dyoung int timeout;
1560 1.1 dyoung int ls_via_hub = 0;
1561 1.1 dyoung int pl;
1562 1.12.6.1 skrll uint8_t isr;
1563 1.12.6.1 skrll uint8_t result = 0;
1564 1.12.6.5 skrll uint8_t devaddr = pipe->up_dev->ud_addr;
1565 1.12.6.5 skrll uint8_t endpointaddr = pipe->up_endpoint->ue_edesc->bEndpointAddress;
1566 1.12.6.1 skrll uint8_t endpoint;
1567 1.12.6.1 skrll uint8_t cmd = DATA0_RD;
1568 1.1 dyoung
1569 1.1 dyoung endpoint = UE_GET_ADDR(endpointaddr);
1570 1.1 dyoung DPRINTF(D_XFER, ("\n(%x,%d%s%d,%d) ",
1571 1.1 dyoung pid, len, (pid == SL11_PID_IN) ? "<-" : "->", devaddr, endpoint));
1572 1.1 dyoung
1573 1.1 dyoung /* Set registers */
1574 1.1 dyoung sl11write(sc, SL11_E0ADDR, 0x40);
1575 1.1 dyoung sl11write(sc, SL11_E0LEN, len);
1576 1.1 dyoung sl11write(sc, SL11_E0PID, (pid << 4) + endpoint);
1577 1.1 dyoung sl11write(sc, SL11_E0DEV, devaddr);
1578 1.1 dyoung
1579 1.1 dyoung /* Set buffer unless PID_IN */
1580 1.1 dyoung if (pid != SL11_PID_IN) {
1581 1.1 dyoung if (len > 0)
1582 1.1 dyoung sl11write_region(sc, 0x40, buf, len);
1583 1.1 dyoung cmd = DATA0_WR;
1584 1.1 dyoung }
1585 1.1 dyoung
1586 1.1 dyoung /* timing ? */
1587 1.1 dyoung pl = (len >> 3) + 3;
1588 1.1 dyoung
1589 1.1 dyoung /* Low speed device via HUB */
1590 1.1 dyoung /* XXX does not work... */
1591 1.12.6.5 skrll if ((sc->sc_fullspeed) && pipe->up_dev->ud_speed == USB_SPEED_LOW) {
1592 1.1 dyoung pl = len + 16;
1593 1.1 dyoung cmd |= SL11_EPCTRL_PREAMBLE;
1594 1.1 dyoung
1595 1.1 dyoung /*
1596 1.1 dyoung * SL811HS/T rev 1.2 has a bug, when it got PID_IN
1597 1.1 dyoung * from LowSpeed device via HUB.
1598 1.1 dyoung */
1599 1.1 dyoung if (sc->sc_sltype == SLTYPE_SL811HS_R12 && pid == SL11_PID_IN) {
1600 1.1 dyoung ls_via_hub = 1;
1601 1.1 dyoung DPRINTF(D_MSG, ("LSvH "));
1602 1.1 dyoung }
1603 1.1 dyoung }
1604 1.1 dyoung
1605 1.1 dyoung /* timing ? */
1606 1.12.6.1 skrll if (sl11read(sc, SL811_CSOF) <= (uint8_t)pl)
1607 1.1 dyoung cmd |= SL11_EPCTRL_SOF;
1608 1.1 dyoung
1609 1.1 dyoung /* Transfer */
1610 1.1 dyoung sl11write(sc, SL11_ISR, 0xff);
1611 1.1 dyoung sl11write(sc, SL11_E0CTRL, cmd | toggle);
1612 1.1 dyoung
1613 1.1 dyoung /* Polling */
1614 1.1 dyoung for (timeout = AHCI_TIMEOUT; timeout; timeout--) {
1615 1.1 dyoung isr = sl11read(sc, SL11_ISR);
1616 1.1 dyoung if ((isr & SL11_ISR_USBA))
1617 1.1 dyoung break;
1618 1.1 dyoung }
1619 1.1 dyoung
1620 1.1 dyoung /* Check result status */
1621 1.1 dyoung result = sl11read(sc, SL11_E0STAT);
1622 1.1 dyoung if (!(result & SL11_EPSTAT_NAK) && ls_via_hub) {
1623 1.1 dyoung /* Resend PID_IN within 20usec */
1624 1.1 dyoung sl11write(sc, SL11_ISR, 0xff);
1625 1.1 dyoung sl11write(sc, SL11_E0CTRL, SL11_EPCTRL_ARM);
1626 1.1 dyoung }
1627 1.1 dyoung
1628 1.1 dyoung sl11write(sc, SL11_ISR, 0xff);
1629 1.1 dyoung
1630 1.1 dyoung DPRINTF(D_XFER, ("t=%d i=%x ", AHCI_TIMEOUT - timeout, isr));
1631 1.1 dyoung #if AHCI_DEBUG
1632 1.5 christos snprintb(str, sizeof(str),
1633 1.5 christos "\20\x8STALL\7NAK\6OV\5SETUP\4DATA1\3TIMEOUT\2ERR\1ACK", result);
1634 1.1 dyoung DPRINTF(D_XFER, ("STAT=%s ", str));
1635 1.1 dyoung #endif
1636 1.1 dyoung
1637 1.1 dyoung if ((result & SL11_EPSTAT_ERROR))
1638 1.1 dyoung return -1;
1639 1.1 dyoung
1640 1.1 dyoung if ((result & SL11_EPSTAT_NAK))
1641 1.1 dyoung return 0;
1642 1.1 dyoung
1643 1.1 dyoung /* Read buffer if PID_IN */
1644 1.1 dyoung if (pid == SL11_PID_IN && len > 0) {
1645 1.1 dyoung sl11read_region(sc, buf, 0x40, len);
1646 1.1 dyoung #if AHCI_DEBUG
1647 1.1 dyoung for (i = 0; i < len; i++)
1648 1.1 dyoung DPRINTF(D_XFER, ("%02X ", buf[i]));
1649 1.1 dyoung #endif
1650 1.1 dyoung }
1651 1.1 dyoung
1652 1.1 dyoung return 1;
1653 1.1 dyoung #endif
1654 1.1 dyoung }
1655 1.1 dyoung
1656 1.1 dyoung void
1657 1.1 dyoung ahci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
1658 1.1 dyoung {
1659 1.12.6.5 skrll xfer->ux_status = status;
1660 1.1 dyoung usb_transfer_complete(xfer);
1661 1.1 dyoung }
1662 1.1 dyoung
1663 1.1 dyoung void
1664 1.1 dyoung ahci_device_clear_toggle(usbd_pipe_handle pipe)
1665 1.1 dyoung {
1666 1.12.6.2 skrll struct ahci_pipe *apipe = (struct ahci_pipe *)pipe;
1667 1.1 dyoung apipe->toggle = 0;
1668 1.1 dyoung }
1669 1.1 dyoung
1670 1.1 dyoung #ifdef AHCI_DEBUG
1671 1.1 dyoung void
1672 1.1 dyoung print_req(usb_device_request_t *r)
1673 1.1 dyoung {
1674 1.1 dyoung const char *xmes[]={
1675 1.1 dyoung "GETSTAT",
1676 1.1 dyoung "CLRFEAT",
1677 1.1 dyoung "res",
1678 1.1 dyoung "SETFEAT",
1679 1.1 dyoung "res",
1680 1.1 dyoung "SETADDR",
1681 1.1 dyoung "GETDESC",
1682 1.1 dyoung "SETDESC",
1683 1.1 dyoung "GETCONF",
1684 1.1 dyoung "SETCONF",
1685 1.1 dyoung "GETIN/F",
1686 1.1 dyoung "SETIN/F",
1687 1.1 dyoung "SYNC_FR"
1688 1.1 dyoung };
1689 1.1 dyoung int req, type, value, index, len;
1690 1.1 dyoung
1691 1.1 dyoung req = r->bRequest;
1692 1.1 dyoung type = r->bmRequestType;
1693 1.1 dyoung value = UGETW(r->wValue);
1694 1.1 dyoung index = UGETW(r->wIndex);
1695 1.1 dyoung len = UGETW(r->wLength);
1696 1.1 dyoung
1697 1.1 dyoung printf("%x,%s,v=%d,i=%d,l=%d ",
1698 1.1 dyoung type, xmes[req], value, index, len);
1699 1.1 dyoung }
1700 1.1 dyoung
1701 1.1 dyoung void
1702 1.1 dyoung print_req_hub(usb_device_request_t *r)
1703 1.1 dyoung {
1704 1.1 dyoung struct {
1705 1.1 dyoung int req;
1706 1.1 dyoung int type;
1707 1.1 dyoung const char *str;
1708 1.1 dyoung } conf[] = {
1709 1.1 dyoung { 1, 0x20, "ClrHubFeat" },
1710 1.1 dyoung { 1, 0x23, "ClrPortFeat" },
1711 1.1 dyoung { 2, 0xa3, "GetBusState" },
1712 1.1 dyoung { 6, 0xa0, "GetHubDesc" },
1713 1.1 dyoung { 0, 0xa0, "GetHubStat" },
1714 1.1 dyoung { 0, 0xa3, "GetPortStat" },
1715 1.1 dyoung { 7, 0x20, "SetHubDesc" },
1716 1.1 dyoung { 3, 0x20, "SetHubFeat" },
1717 1.1 dyoung { 3, 0x23, "SetPortFeat" },
1718 1.1 dyoung {-1, 0, NULL},
1719 1.1 dyoung };
1720 1.1 dyoung int i;
1721 1.1 dyoung int value, index, len;
1722 1.1 dyoung
1723 1.1 dyoung value = UGETW(r->wValue);
1724 1.1 dyoung index = UGETW(r->wIndex);
1725 1.1 dyoung len = UGETW(r->wLength);
1726 1.1 dyoung for (i = 0; ; i++) {
1727 1.1 dyoung if (conf[i].req == -1 )
1728 1.1 dyoung return print_req(r);
1729 1.1 dyoung if (r->bmRequestType == conf[i].type && r->bRequest == conf[i].req) {
1730 1.1 dyoung printf("%s", conf[i].str);
1731 1.1 dyoung break;
1732 1.1 dyoung }
1733 1.1 dyoung }
1734 1.1 dyoung printf(",v=%d,i=%d,l=%d ", value, index, len);
1735 1.1 dyoung }
1736 1.1 dyoung
1737 1.1 dyoung void
1738 1.1 dyoung print_dumpreg(struct ahci_softc *sc)
1739 1.1 dyoung {
1740 1.1 dyoung #if 0
1741 1.1 dyoung printf("00=%02x,01=%02x,02=%02x,03=%02x,04=%02x,"
1742 1.1 dyoung "08=%02x,09=%02x,0A=%02x,0B=%02x,0C=%02x,",
1743 1.1 dyoung sl11read(sc, 0), sl11read(sc, 1),
1744 1.1 dyoung sl11read(sc, 2), sl11read(sc, 3),
1745 1.1 dyoung sl11read(sc, 4), sl11read(sc, 8),
1746 1.1 dyoung sl11read(sc, 9), sl11read(sc, 10),
1747 1.1 dyoung sl11read(sc, 11), sl11read(sc, 12)
1748 1.1 dyoung );
1749 1.1 dyoung printf("CR1=%02x,IER=%02x,0D=%02x,0E=%02x,0F=%02x ",
1750 1.1 dyoung sl11read(sc, 5), sl11read(sc, 6),
1751 1.1 dyoung sl11read(sc, 13), sl11read(sc, 14), sl11read(sc, 15)
1752 1.1 dyoung );
1753 1.1 dyoung #endif
1754 1.1 dyoung }
1755 1.1 dyoung
1756 1.1 dyoung void
1757 1.1 dyoung print_xfer(usbd_xfer_handle xfer)
1758 1.1 dyoung {
1759 1.1 dyoung printf("xfer: length=%d, actlen=%d, flags=%x, timeout=%d,",
1760 1.12.6.5 skrll xfer->ux_length, xfer->ux_actlen, xfer->ux_flags, xfer->ux_timeout);
1761 1.1 dyoung printf("request{ ");
1762 1.12.6.5 skrll print_req_hub(&xfer->ux_request);
1763 1.1 dyoung printf("} ");
1764 1.1 dyoung }
1765 1.1 dyoung #endif /* AHCI_DEBUG */
1766