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