ahci.c revision 1.30 1 1.30 riastrad /* $NetBSD: ahci.c,v 1.30 2022/03/03 06:12:11 riastradh 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.30 riastrad __KERNEL_RCSID(0, "$NetBSD: ahci.c,v 1.30 2022/03/03 06:12:11 riastradh 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.13 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.13 skrll #include <dev/usb/usbroothub.h>
85 1.1 dyoung
86 1.1 dyoung #include <mips/adm5120/include/adm5120reg.h>
87 1.1 dyoung #include <mips/adm5120/include/adm5120var.h>
88 1.1 dyoung #include <mips/adm5120/include/adm5120_obiovar.h>
89 1.1 dyoung
90 1.1 dyoung #include <mips/adm5120/dev/ahcireg.h>
91 1.1 dyoung #include <mips/adm5120/dev/ahcivar.h>
92 1.1 dyoung
93 1.13 skrll static usbd_status ahci_open(struct usbd_pipe *);
94 1.1 dyoung static void ahci_softintr(void *);
95 1.1 dyoung static void ahci_poll(struct usbd_bus *);
96 1.1 dyoung static void ahci_poll_hub(void *);
97 1.1 dyoung static void ahci_poll_device(void *arg);
98 1.13 skrll static struct usbd_xfer *
99 1.13 skrll ahci_allocx(struct usbd_bus *, unsigned int);
100 1.13 skrll static void ahci_freex(struct usbd_bus *, struct usbd_xfer *);
101 1.18 riastrad static void ahci_abortx(struct usbd_xfer *);
102 1.1 dyoung
103 1.12 skrll static void ahci_get_lock(struct usbd_bus *, kmutex_t **);
104 1.13 skrll static int ahci_roothub_ctrl(struct usbd_bus *, usb_device_request_t *,
105 1.13 skrll void *, int);
106 1.12 skrll
107 1.13 skrll static usbd_status ahci_root_intr_transfer(struct usbd_xfer *);
108 1.13 skrll static usbd_status ahci_root_intr_start(struct usbd_xfer *);
109 1.13 skrll static void ahci_root_intr_abort(struct usbd_xfer *);
110 1.13 skrll static void ahci_root_intr_close(struct usbd_pipe *);
111 1.13 skrll static void ahci_root_intr_done(struct usbd_xfer *);
112 1.13 skrll
113 1.13 skrll static usbd_status ahci_device_ctrl_transfer(struct usbd_xfer *);
114 1.13 skrll static usbd_status ahci_device_ctrl_start(struct usbd_xfer *);
115 1.13 skrll static void ahci_device_ctrl_abort(struct usbd_xfer *);
116 1.13 skrll static void ahci_device_ctrl_close(struct usbd_pipe *);
117 1.13 skrll static void ahci_device_ctrl_done(struct usbd_xfer *);
118 1.13 skrll
119 1.13 skrll static usbd_status ahci_device_intr_transfer(struct usbd_xfer *);
120 1.13 skrll static usbd_status ahci_device_intr_start(struct usbd_xfer *);
121 1.13 skrll static void ahci_device_intr_abort(struct usbd_xfer *);
122 1.13 skrll static void ahci_device_intr_close(struct usbd_pipe *);
123 1.13 skrll static void ahci_device_intr_done(struct usbd_xfer *);
124 1.13 skrll
125 1.13 skrll static usbd_status ahci_device_isoc_transfer(struct usbd_xfer *);
126 1.13 skrll static usbd_status ahci_device_isoc_start(struct usbd_xfer *);
127 1.13 skrll static void ahci_device_isoc_abort(struct usbd_xfer *);
128 1.13 skrll static void ahci_device_isoc_close(struct usbd_pipe *);
129 1.13 skrll static void ahci_device_isoc_done(struct usbd_xfer *);
130 1.13 skrll
131 1.13 skrll static usbd_status ahci_device_bulk_transfer(struct usbd_xfer *);
132 1.13 skrll static usbd_status ahci_device_bulk_start(struct usbd_xfer *);
133 1.13 skrll static void ahci_device_bulk_abort(struct usbd_xfer *);
134 1.13 skrll static void ahci_device_bulk_close(struct usbd_pipe *);
135 1.13 skrll static void ahci_device_bulk_done(struct usbd_xfer *);
136 1.1 dyoung
137 1.1 dyoung static int ahci_transaction(struct ahci_softc *,
138 1.13 skrll struct usbd_pipe *, uint8_t, int, u_char *, uint8_t);
139 1.13 skrll static void ahci_noop(struct usbd_pipe *);
140 1.13 skrll static void ahci_device_clear_toggle(struct usbd_pipe *);
141 1.1 dyoung
142 1.1 dyoung extern int usbdebug;
143 1.1 dyoung extern int uhubdebug;
144 1.1 dyoung extern int umassdebug;
145 1.1 dyoung int ahci_dummy;
146 1.1 dyoung
147 1.1 dyoung #define AHCI_DEBUG
148 1.1 dyoung
149 1.1 dyoung #ifdef AHCI_DEBUG
150 1.1 dyoung #define D_TRACE (0x0001) /* function trace */
151 1.1 dyoung #define D_MSG (0x0002) /* debug messages */
152 1.1 dyoung #define D_XFER (0x0004) /* transfer messages (noisy!) */
153 1.1 dyoung #define D_MEM (0x0008) /* memory allocation */
154 1.1 dyoung
155 1.1 dyoung int ahci_debug = 0;
156 1.1 dyoung #define DPRINTF(z,x) if((ahci_debug&(z))!=0)printf x
157 1.1 dyoung void print_req(usb_device_request_t *);
158 1.1 dyoung void print_req_hub(usb_device_request_t *);
159 1.1 dyoung void print_dumpreg(struct ahci_softc *);
160 1.13 skrll void print_xfer(struct usbd_xfer *);
161 1.1 dyoung #else
162 1.1 dyoung #define DPRINTF(z,x)
163 1.1 dyoung #endif
164 1.1 dyoung
165 1.1 dyoung
166 1.1 dyoung struct usbd_bus_methods ahci_bus_methods = {
167 1.13 skrll .ubm_open = ahci_open,
168 1.13 skrll .ubm_softint = ahci_softintr,
169 1.13 skrll .ubm_dopoll = ahci_poll,
170 1.13 skrll .ubm_allocx = ahci_allocx,
171 1.13 skrll .ubm_freex = ahci_freex,
172 1.18 riastrad .ubm_abortx = ahci_abortx,
173 1.13 skrll .ubm_getlock = ahci_get_lock,
174 1.13 skrll .ubm_rhctrl = ahci_roothub_ctrl,
175 1.1 dyoung };
176 1.1 dyoung
177 1.1 dyoung struct usbd_pipe_methods ahci_root_intr_methods = {
178 1.13 skrll .upm_transfer = ahci_root_intr_transfer,
179 1.13 skrll .upm_start = ahci_root_intr_start,
180 1.13 skrll .upm_abort = ahci_root_intr_abort,
181 1.13 skrll .upm_close = ahci_root_intr_close,
182 1.13 skrll .upm_cleartoggle = ahci_noop,
183 1.13 skrll .upm_done = ahci_root_intr_done,
184 1.1 dyoung };
185 1.1 dyoung
186 1.1 dyoung struct usbd_pipe_methods ahci_device_ctrl_methods = {
187 1.13 skrll .upm_transfer = ahci_device_ctrl_transfer,
188 1.13 skrll .upm_start = ahci_device_ctrl_start,
189 1.13 skrll .upm_abort = ahci_device_ctrl_abort,
190 1.13 skrll .upm_close = ahci_device_ctrl_close,
191 1.13 skrll .upm_cleartoggle = ahci_noop,
192 1.13 skrll .upm_done = ahci_device_ctrl_done,
193 1.1 dyoung };
194 1.1 dyoung
195 1.1 dyoung struct usbd_pipe_methods ahci_device_intr_methods = {
196 1.13 skrll .upm_transfer = ahci_device_intr_transfer,
197 1.13 skrll .upm_start = ahci_device_intr_start,
198 1.13 skrll .upm_abort = ahci_device_intr_abort,
199 1.13 skrll .upm_close = ahci_device_intr_close,
200 1.13 skrll .upm_cleartoggle = ahci_device_clear_toggle,
201 1.13 skrll .upm_done = ahci_device_intr_done,
202 1.1 dyoung };
203 1.1 dyoung
204 1.1 dyoung struct usbd_pipe_methods ahci_device_isoc_methods = {
205 1.13 skrll .upm_transfer = ahci_device_isoc_transfer,
206 1.13 skrll .upm_start = ahci_device_isoc_start,
207 1.13 skrll .upm_abort = ahci_device_isoc_abort,
208 1.13 skrll .upm_close = ahci_device_isoc_close,
209 1.13 skrll .upm_cleartoggle = ahci_noop,
210 1.13 skrll .upm_done = ahci_device_isoc_done,
211 1.1 dyoung };
212 1.1 dyoung
213 1.1 dyoung struct usbd_pipe_methods ahci_device_bulk_methods = {
214 1.13 skrll .upm_transfer = ahci_device_bulk_transfer,
215 1.13 skrll .upm_start = ahci_device_bulk_start,
216 1.13 skrll .upm_abort = ahci_device_bulk_abort,
217 1.13 skrll .upm_close = ahci_device_bulk_close,
218 1.13 skrll .upm_cleartoggle = ahci_device_clear_toggle,
219 1.13 skrll .upm_done = ahci_device_bulk_done,
220 1.1 dyoung };
221 1.1 dyoung
222 1.1 dyoung struct ahci_pipe {
223 1.1 dyoung struct usbd_pipe pipe;
224 1.13 skrll uint32_t toggle;
225 1.1 dyoung };
226 1.1 dyoung
227 1.9 chs static int ahci_match(device_t, cfdata_t, void *);
228 1.4 dyoung static void ahci_attach(device_t, device_t, void *);
229 1.1 dyoung
230 1.9 chs CFATTACH_DECL_NEW(ahci, sizeof(struct ahci_softc),
231 1.1 dyoung ahci_match, ahci_attach, NULL, NULL);
232 1.1 dyoung
233 1.1 dyoung static int
234 1.4 dyoung ahci_match(device_t parent, struct cfdata *cf, void *aux)
235 1.1 dyoung {
236 1.1 dyoung struct obio_attach_args *aa = aux;
237 1.1 dyoung
238 1.1 dyoung if (strcmp(aa->oba_name, cf->cf_name) == 0)
239 1.13 skrll return 1;
240 1.1 dyoung
241 1.13 skrll return 0;
242 1.1 dyoung }
243 1.1 dyoung
244 1.1 dyoung #define REG_READ(o) bus_space_read_4(sc->sc_st, sc->sc_ioh, (o))
245 1.1 dyoung #define REG_WRITE(o,v) bus_space_write_4(sc->sc_st, sc->sc_ioh, (o),(v))
246 1.1 dyoung
247 1.1 dyoung /*
248 1.1 dyoung * Attach SL11H/SL811HS. Return 0 if success.
249 1.1 dyoung */
250 1.1 dyoung void
251 1.4 dyoung ahci_attach(device_t parent, device_t self, void *aux)
252 1.1 dyoung {
253 1.1 dyoung struct obio_attach_args *aa = aux;
254 1.4 dyoung struct ahci_softc *sc = device_private(self);
255 1.1 dyoung
256 1.1 dyoung printf("\n");
257 1.1 dyoung sc->sc_dmat = aa->oba_dt;
258 1.1 dyoung sc->sc_st = aa->oba_st;
259 1.1 dyoung
260 1.1 dyoung /* Initialize sc */
261 1.13 skrll sc->sc_bus.ub_revision = USBREV_1_1;
262 1.13 skrll sc->sc_bus.ub_methods = &ahci_bus_methods;
263 1.13 skrll sc->sc_bus.ub_pipesize = sizeof(struct ahci_pipe);
264 1.13 skrll sc->sc_bus.ub_dmatag = sc->sc_dmat;
265 1.13 skrll sc->sc_bus.ub_usedma = true;
266 1.1 dyoung
267 1.1 dyoung /* Map the device. */
268 1.1 dyoung if (bus_space_map(sc->sc_st, aa->oba_addr,
269 1.1 dyoung 512, 0, &sc->sc_ioh) != 0) {
270 1.4 dyoung aprint_error_dev(self, "unable to map device\n");
271 1.1 dyoung return;
272 1.1 dyoung }
273 1.1 dyoung
274 1.1 dyoung /* Hook up the interrupt handler. */
275 1.1 dyoung sc->sc_ih = adm5120_intr_establish(aa->oba_irq, INTR_IRQ, ahci_intr, sc);
276 1.1 dyoung
277 1.1 dyoung if (sc->sc_ih == NULL) {
278 1.4 dyoung aprint_error_dev(self,
279 1.4 dyoung "unable to register interrupt handler\n");
280 1.1 dyoung return;
281 1.1 dyoung }
282 1.1 dyoung
283 1.1 dyoung SIMPLEQ_INIT(&sc->sc_free_xfers);
284 1.1 dyoung
285 1.6 dyoung callout_init(&sc->sc_poll_handle, 0);
286 1.19 riastrad callout_setfunc(&sc->sc_poll_handle, ahci_poll_hub, sc);
287 1.1 dyoung
288 1.12 skrll mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB);
289 1.12 skrll mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_SCHED /* XXXNH */);
290 1.12 skrll
291 1.1 dyoung REG_WRITE(ADMHCD_REG_INTENABLE, 0); /* disable interrupts */
292 1.1 dyoung REG_WRITE(ADMHCD_REG_CONTROL, ADMHCD_SW_RESET); /* reset */
293 1.1 dyoung delay_ms(10);
294 1.13 skrll while (REG_READ(ADMHCD_REG_CONTROL) & ADMHCD_SW_RESET)
295 1.13 skrll delay_ms(1);
296 1.1 dyoung
297 1.1 dyoung REG_WRITE(ADMHCD_REG_CONTROL, ADMHCD_HOST_EN);
298 1.13 skrll REG_WRITE(ADMHCD_REG_HOSTHEAD, 0x00000000);
299 1.13 skrll REG_WRITE(ADMHCD_REG_FMINTERVAL, 0x20002edf);
300 1.13 skrll REG_WRITE(ADMHCD_REG_LSTHRESH, 0x628);
301 1.13 skrll REG_WRITE(ADMHCD_REG_RHDESCR, ADMHCD_NPS | ADMHCD_LPSC);
302 1.13 skrll REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP);
303 1.1 dyoung
304 1.1 dyoung REG_WRITE(ADMHCD_REG_INTENABLE, 0); /* XXX: enable interrupts */
305 1.1 dyoung
306 1.1 dyoung #ifdef USB_DEBUG
307 1.1 dyoung /* usbdebug = 0x7f;
308 1.1 dyoung uhubdebug = 0x7f;
309 1.1 dyoung umassdebug = 0xffffffff; */
310 1.1 dyoung #endif
311 1.1 dyoung
312 1.1 dyoung /* Attach USB devices */
313 1.25 thorpej sc->sc_child = config_found(self, &sc->sc_bus, usbctlprint, CFARGS_NONE);
314 1.1 dyoung
315 1.1 dyoung }
316 1.1 dyoung
317 1.1 dyoung int
318 1.1 dyoung ahci_intr(void *arg)
319 1.1 dyoung {
320 1.1 dyoung #if 0
321 1.1 dyoung struct ahci_softc *sc = arg;
322 1.13 skrll uint8_t r;
323 1.1 dyoung #ifdef AHCI_DEBUG
324 1.1 dyoung char bitbuf[256];
325 1.1 dyoung #endif
326 1.1 dyoung
327 1.1 dyoung r = sl11read(sc, SL11_ISR);
328 1.1 dyoung
329 1.1 dyoung sl11write(sc, SL11_ISR, SL11_ISR_DATA | SL11_ISR_SOFTIMER);
330 1.1 dyoung
331 1.1 dyoung if ((r & SL11_ISR_RESET)) {
332 1.1 dyoung sc->sc_flags |= AHCDF_RESET;
333 1.1 dyoung sl11write(sc, SL11_ISR, SL11_ISR_RESET);
334 1.1 dyoung }
335 1.1 dyoung if ((r & SL11_ISR_INSERT)) {
336 1.1 dyoung sc->sc_flags |= AHCDF_INSERT;
337 1.1 dyoung sl11write(sc, SL11_ISR, SL11_ISR_INSERT);
338 1.1 dyoung }
339 1.1 dyoung
340 1.1 dyoung #ifdef AHCI_DEBUG
341 1.5 christos snprintb(bitbuf, sizeof(bitbuf),
342 1.5 christos ((sl11read(sc, SL11_CTRL) & SL11_CTRL_SUSPEND)
343 1.5 christos ? "\20\x8""D+\7RESUME\6INSERT\5SOF\4res\3""BABBLE\2USBB\1USBA"
344 1.5 christos : "\20\x8""D+\7RESET\6INSERT\5SOF\4res\3""BABBLE\2USBB\1USBA"),
345 1.5 christos r);
346 1.11 skrll
347 1.1 dyoung DPRINTF(D_XFER, ("I=%s ", bitbuf));
348 1.1 dyoung #endif /* AHCI_DEBUG */
349 1.1 dyoung #endif
350 1.1 dyoung
351 1.1 dyoung return 0;
352 1.1 dyoung }
353 1.1 dyoung
354 1.1 dyoung usbd_status
355 1.13 skrll ahci_open(struct usbd_pipe *pipe)
356 1.1 dyoung {
357 1.13 skrll struct usbd_device *dev = pipe->up_dev;
358 1.1 dyoung struct ahci_pipe *apipe = (struct ahci_pipe *)pipe;
359 1.13 skrll usb_endpoint_descriptor_t *ed = pipe->up_endpoint->ue_edesc;
360 1.13 skrll uint8_t rhaddr = dev->ud_bus->ub_rhaddr;
361 1.1 dyoung
362 1.1 dyoung DPRINTF(D_TRACE, ("ahci_open(addr=%d,ep=%d,scaddr=%d)",
363 1.13 skrll dev->ud_addr, ed->bEndpointAddress, rhaddr));
364 1.1 dyoung
365 1.1 dyoung apipe->toggle=0;
366 1.1 dyoung
367 1.13 skrll if (dev->ud_addr == rhaddr) {
368 1.1 dyoung switch (ed->bEndpointAddress) {
369 1.1 dyoung case USB_CONTROL_ENDPOINT:
370 1.13 skrll pipe->up_methods = &roothub_ctrl_methods;
371 1.1 dyoung break;
372 1.13 skrll case UE_DIR_IN | USBROOTHUB_INTR_ENDPT:
373 1.13 skrll pipe->up_methods = &ahci_root_intr_methods;
374 1.1 dyoung break;
375 1.1 dyoung default:
376 1.1 dyoung printf("open:endpointErr!\n");
377 1.1 dyoung return USBD_INVAL;
378 1.1 dyoung }
379 1.1 dyoung } else {
380 1.1 dyoung switch (ed->bmAttributes & UE_XFERTYPE) {
381 1.1 dyoung case UE_CONTROL:
382 1.1 dyoung DPRINTF(D_MSG, ("control "));
383 1.13 skrll pipe->up_methods = &ahci_device_ctrl_methods;
384 1.1 dyoung break;
385 1.1 dyoung case UE_INTERRUPT:
386 1.1 dyoung DPRINTF(D_MSG, ("interrupt "));
387 1.13 skrll pipe->up_methods = &ahci_device_intr_methods;
388 1.1 dyoung break;
389 1.1 dyoung case UE_ISOCHRONOUS:
390 1.1 dyoung DPRINTF(D_MSG, ("isochronous "));
391 1.13 skrll pipe->up_methods = &ahci_device_isoc_methods;
392 1.1 dyoung break;
393 1.1 dyoung case UE_BULK:
394 1.1 dyoung DPRINTF(D_MSG, ("bluk "));
395 1.13 skrll pipe->up_methods = &ahci_device_bulk_methods;
396 1.1 dyoung break;
397 1.1 dyoung }
398 1.1 dyoung }
399 1.1 dyoung return USBD_NORMAL_COMPLETION;
400 1.1 dyoung }
401 1.1 dyoung
402 1.1 dyoung void
403 1.1 dyoung ahci_softintr(void *arg)
404 1.1 dyoung {
405 1.2 perry DPRINTF(D_TRACE, ("%s()", __func__));
406 1.1 dyoung }
407 1.1 dyoung
408 1.1 dyoung void
409 1.1 dyoung ahci_poll(struct usbd_bus *bus)
410 1.1 dyoung {
411 1.2 perry DPRINTF(D_TRACE, ("%s()", __func__));
412 1.1 dyoung }
413 1.1 dyoung
414 1.13 skrll #define AHCI_BUS2SC(bus) ((bus)->ub_hcpriv)
415 1.13 skrll #define AHCI_PIPE2SC(pipe) AHCI_BUS2SC((pipe)->up_dev->ud_bus)
416 1.13 skrll #define AHCI_XFER2SC(xfer) AHCI_BUS2SC((xfer)->ux_bus)
417 1.13 skrll #define AHCI_APIPE2SC(ap) AHCI_BUS2SC((d)->pipe.up_dev->ud_bus)
418 1.13 skrll
419 1.1 dyoung /*
420 1.1 dyoung * Emulation of interrupt transfer for status change endpoint
421 1.1 dyoung * of root hub.
422 1.1 dyoung */
423 1.1 dyoung void
424 1.1 dyoung ahci_poll_hub(void *arg)
425 1.1 dyoung {
426 1.19 riastrad struct ahci_softc *sc = arg;
427 1.19 riastrad struct usbd_xfer *xfer;
428 1.1 dyoung u_char *p;
429 1.1 dyoung static int p0_state=0;
430 1.1 dyoung static int p1_state=0;
431 1.1 dyoung
432 1.19 riastrad mutex_enter(&sc->sc_lock);
433 1.19 riastrad
434 1.19 riastrad /*
435 1.19 riastrad * If the intr xfer has completed or been synchronously
436 1.19 riastrad * aborted, we have nothing to do.
437 1.19 riastrad */
438 1.19 riastrad xfer = sc->sc_intr_xfer;
439 1.19 riastrad if (xfer == NULL)
440 1.19 riastrad goto out;
441 1.20 riastrad KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
442 1.19 riastrad
443 1.19 riastrad /*
444 1.19 riastrad * If the intr xfer for which we were scheduled is done, and
445 1.19 riastrad * another intr xfer has been submitted, let that one be dealt
446 1.19 riastrad * with when the callout fires again.
447 1.19 riastrad *
448 1.26 andvar * The call to callout_pending is racy, but the transition
449 1.19 riastrad * from pending to invoking happens atomically. The
450 1.19 riastrad * callout_ack ensures callout_invoking does not return true
451 1.19 riastrad * due to this invocation of the callout; the lock ensures the
452 1.19 riastrad * next invocation of the callout cannot callout_ack (unless it
453 1.19 riastrad * had already run to completion and nulled sc->sc_intr_xfer,
454 1.19 riastrad * in which case would have bailed out already).
455 1.19 riastrad */
456 1.19 riastrad callout_ack(&sc->sc_poll_handle);
457 1.19 riastrad if (callout_pending(&sc->sc_poll_handle) ||
458 1.19 riastrad callout_invoking(&sc->sc_poll_handle))
459 1.19 riastrad goto out;
460 1.1 dyoung
461 1.1 dyoung /* USB spec 11.13.3 (p.260) */
462 1.13 skrll p = KERNADDR(&xfer->ux_dmabuf, 0);
463 1.1 dyoung p[0] = 0;
464 1.1 dyoung if ((REG_READ(ADMHCD_REG_PORTSTATUS0) & ADMHCD_CCS) != p0_state) {
465 1.1 dyoung p[0] = 2;
466 1.1 dyoung DPRINTF(D_TRACE, ("!"));
467 1.1 dyoung p0_state=(REG_READ(ADMHCD_REG_PORTSTATUS0) & ADMHCD_CCS);
468 1.1 dyoung };
469 1.1 dyoung if ((REG_READ(ADMHCD_REG_PORTSTATUS1) & ADMHCD_CCS) != p1_state) {
470 1.1 dyoung p[0] = 2;
471 1.1 dyoung DPRINTF(D_TRACE, ("@"));
472 1.1 dyoung p1_state=(REG_READ(ADMHCD_REG_PORTSTATUS1) & ADMHCD_CCS);
473 1.1 dyoung };
474 1.1 dyoung
475 1.19 riastrad /* no change, return NAK and try again later */
476 1.19 riastrad if (p[0] == 0) {
477 1.19 riastrad callout_schedule(&sc->sc_poll_handle, sc->sc_interval);
478 1.19 riastrad goto out;
479 1.19 riastrad }
480 1.1 dyoung
481 1.19 riastrad /*
482 1.19 riastrad * Interrupt completed, and the xfer has not been completed or
483 1.19 riastrad * synchronously aborted. Complete the xfer now.
484 1.19 riastrad *
485 1.19 riastrad * XXX Set ux_isdone if DIAGNOSTIC?
486 1.19 riastrad */
487 1.13 skrll xfer->ux_actlen = 1;
488 1.13 skrll xfer->ux_status = USBD_NORMAL_COMPLETION;
489 1.1 dyoung usb_transfer_complete(xfer);
490 1.19 riastrad
491 1.19 riastrad out: mutex_exit(&sc->sc_lock);
492 1.1 dyoung }
493 1.1 dyoung
494 1.13 skrll struct usbd_xfer *
495 1.13 skrll ahci_allocx(struct usbd_bus *bus, unsigned int nframes)
496 1.1 dyoung {
497 1.13 skrll struct ahci_softc *sc = AHCI_BUS2SC(bus);
498 1.13 skrll struct usbd_xfer *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.13 skrll SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, ux_next);
505 1.1 dyoung #ifdef DIAGNOSTIC
506 1.13 skrll if (xfer->ux_state != XFER_FREE) {
507 1.1 dyoung printf("ahci_allocx: xfer=%p not free, 0x%08x\n",
508 1.13 skrll xfer, xfer->ux_state);
509 1.1 dyoung }
510 1.1 dyoung #endif
511 1.1 dyoung } else {
512 1.13 skrll xfer = kmem_alloc(sizeof(*xfer), KM_SLEEP);
513 1.1 dyoung }
514 1.1 dyoung
515 1.14 chs memset(xfer, 0, sizeof(*xfer));
516 1.1 dyoung #ifdef DIAGNOSTIC
517 1.14 chs xfer->ux_state = XFER_BUSY;
518 1.1 dyoung #endif
519 1.1 dyoung
520 1.1 dyoung return xfer;
521 1.1 dyoung }
522 1.1 dyoung
523 1.1 dyoung void
524 1.13 skrll ahci_freex(struct usbd_bus *bus, struct usbd_xfer *xfer)
525 1.1 dyoung {
526 1.13 skrll struct ahci_softc *sc = AHCI_BUS2SC(bus);
527 1.1 dyoung
528 1.1 dyoung DPRINTF(D_MEM, ("SLfreex"));
529 1.1 dyoung
530 1.1 dyoung #ifdef DIAGNOSTIC
531 1.17 rin if (xfer->ux_state != XFER_BUSY &&
532 1.17 rin xfer->ux_status != USBD_NOT_STARTED) {
533 1.1 dyoung printf("ahci_freex: xfer=%p not busy, 0x%08x\n",
534 1.13 skrll xfer, xfer->ux_state);
535 1.1 dyoung return;
536 1.1 dyoung }
537 1.13 skrll xfer->ux_state = XFER_FREE;
538 1.1 dyoung #endif
539 1.13 skrll SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, ux_next);
540 1.1 dyoung }
541 1.1 dyoung
542 1.12 skrll static void
543 1.12 skrll ahci_get_lock(struct usbd_bus *bus, kmutex_t **lock)
544 1.12 skrll {
545 1.13 skrll struct ahci_softc *sc = AHCI_BUS2SC(bus);
546 1.12 skrll
547 1.12 skrll *lock = &sc->sc_lock;
548 1.12 skrll }
549 1.12 skrll
550 1.1 dyoung void
551 1.13 skrll ahci_noop(struct usbd_pipe *pipe)
552 1.1 dyoung {
553 1.2 perry DPRINTF(D_TRACE, ("%s()", __func__));
554 1.1 dyoung }
555 1.1 dyoung
556 1.1 dyoung /*
557 1.1 dyoung * Data structures and routines to emulate the root hub.
558 1.1 dyoung */
559 1.1 dyoung
560 1.1 dyoung static int
561 1.13 skrll ahci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req,
562 1.13 skrll void *buf, int buflen)
563 1.1 dyoung {
564 1.13 skrll struct ahci_softc *sc = AHCI_BUS2SC(bus);
565 1.13 skrll uint16_t len, value, index;
566 1.13 skrll usb_port_status_t ps;
567 1.1 dyoung int totlen = 0;
568 1.13 skrll int status;
569 1.1 dyoung
570 1.1 dyoung DPRINTF(D_TRACE, ("SLRCstart "));
571 1.1 dyoung
572 1.30 riastrad KASSERT(bus->ub_polling || mutex_owned(bus->ub_lock));
573 1.30 riastrad
574 1.1 dyoung len = UGETW(req->wLength);
575 1.1 dyoung value = UGETW(req->wValue);
576 1.1 dyoung index = UGETW(req->wIndex);
577 1.1 dyoung
578 1.1 dyoung #define C(x,y) ((x) | ((y) << 8))
579 1.1 dyoung switch (C(req->bRequest, req->bmRequestType)) {
580 1.1 dyoung case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
581 1.13 skrll switch (value) {
582 1.13 skrll #define sd ((usb_string_descriptor_t *)buf)
583 1.13 skrll case C(2, UDESC_STRING):
584 1.13 skrll /* Product */
585 1.13 skrll totlen = usb_makestrdesc(sd, len, "ADM5120 root hub");
586 1.1 dyoung break;
587 1.1 dyoung default:
588 1.1 dyoung printf("unknownGetDescriptor=%x", value);
589 1.15 jakllsch /* FALLTHROUGH */
590 1.15 jakllsch case C(0, UDESC_DEVICE):
591 1.15 jakllsch case C(1, UDESC_STRING):
592 1.13 skrll /* default from usbroothub */
593 1.13 skrll return buflen;
594 1.1 dyoung }
595 1.1 dyoung break;
596 1.1 dyoung /*
597 1.1 dyoung * Hub specific requests
598 1.1 dyoung */
599 1.1 dyoung case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
600 1.1 dyoung /* Clear Hub Feature, 11.16.2.1, not supported */
601 1.1 dyoung DPRINTF(D_MSG, ("ClearHubFeature not supported\n"));
602 1.1 dyoung break;
603 1.1 dyoung case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
604 1.1 dyoung
605 1.1 dyoung #define WPS(x) REG_WRITE(ADMHCD_REG_PORTSTATUS0+(index-1)*4, (x))
606 1.1 dyoung /* Clear Port Feature, 11.16.2.2 */
607 1.1 dyoung if (index != 1 && index != 2 ) {
608 1.13 skrll return -1;
609 1.1 dyoung }
610 1.1 dyoung switch (value) {
611 1.1 dyoung case UHF_PORT_POWER:
612 1.1 dyoung DPRINTF(D_MSG, ("POWER_OFF "));
613 1.1 dyoung WPS(ADMHCD_LSDA);
614 1.1 dyoung break;
615 1.1 dyoung case UHF_PORT_SUSPEND:
616 1.1 dyoung DPRINTF(D_MSG, ("SUSPEND "));
617 1.1 dyoung WPS(ADMHCD_POCI);
618 1.1 dyoung break;
619 1.1 dyoung case UHF_PORT_ENABLE:
620 1.1 dyoung DPRINTF(D_MSG, ("ENABLE "));
621 1.1 dyoung WPS(ADMHCD_CCS);
622 1.1 dyoung break;
623 1.1 dyoung case UHF_C_PORT_CONNECTION:
624 1.1 dyoung WPS(ADMHCD_CSC);
625 1.1 dyoung break;
626 1.1 dyoung case UHF_C_PORT_RESET:
627 1.1 dyoung WPS(ADMHCD_PRSC);
628 1.1 dyoung break;
629 1.1 dyoung case UHF_C_PORT_SUSPEND:
630 1.1 dyoung WPS(ADMHCD_PSSC);
631 1.1 dyoung break;
632 1.1 dyoung case UHF_C_PORT_ENABLE:
633 1.1 dyoung WPS(ADMHCD_PESC);
634 1.1 dyoung break;
635 1.1 dyoung case UHF_C_PORT_OVER_CURRENT:
636 1.1 dyoung WPS(ADMHCD_OCIC);
637 1.1 dyoung break;
638 1.1 dyoung default:
639 1.1 dyoung printf("ClrPortFeatERR:value=0x%x ", value);
640 1.13 skrll return -1;
641 1.1 dyoung }
642 1.1 dyoung //DPRINTF(D_XFER, ("CH=%04x ", sc->sc_change));
643 1.1 dyoung #undef WPS
644 1.1 dyoung break;
645 1.1 dyoung case C(UR_GET_BUS_STATE, UT_READ_CLASS_OTHER):
646 1.1 dyoung /* Get Bus State, 11.16.2.3, not supported */
647 1.1 dyoung /* shall return a STALL... */
648 1.1 dyoung break;
649 1.1 dyoung case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
650 1.1 dyoung /* Get Hub Descriptor, 11.16.2.4 */
651 1.1 dyoung DPRINTF(D_MSG, ("UR_GET_DESCRIPTOR RCD"));
652 1.1 dyoung if ((value&0xff) != 0) {
653 1.13 skrll return -1;
654 1.1 dyoung }
655 1.13 skrll usb_hub_descriptor_t hubd;
656 1.13 skrll
657 1.16 riastrad totlen = uimin(buflen, sizeof(hubd));
658 1.13 skrll memcpy(&hubd, buf, totlen);
659 1.13 skrll hubd.bNbrPorts = 2;
660 1.13 skrll USETW(hubd.wHubCharacteristics, 0);
661 1.13 skrll hubd.bPwrOn2PwrGood = 0;
662 1.13 skrll memcpy(buf, &hubd, totlen);
663 1.1 dyoung break;
664 1.1 dyoung case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
665 1.1 dyoung /* Get Hub Status, 11.16.2.5 */
666 1.1 dyoung DPRINTF(D_MSG, ("UR_GET_STATUS RCD"));
667 1.1 dyoung if (len != 4) {
668 1.13 skrll return -1;
669 1.1 dyoung }
670 1.1 dyoung memset(buf, 0, len);
671 1.1 dyoung totlen = len;
672 1.1 dyoung break;
673 1.1 dyoung case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
674 1.1 dyoung /* Get Port Status, 11.16.2.6 */
675 1.1 dyoung if ((index != 1 && index != 2) || len != 4) {
676 1.1 dyoung printf("index=%d,len=%d ", index, len);
677 1.13 skrll return -1;
678 1.1 dyoung }
679 1.1 dyoung status = REG_READ(ADMHCD_REG_PORTSTATUS0+(index-1)*4);
680 1.1 dyoung DPRINTF(D_MSG, ("UR_GET_STATUS RCO=%x ", status));
681 1.1 dyoung
682 1.1 dyoung //DPRINTF(D_XFER, ("ST=%04x,CH=%04x ", status, sc->sc_change));
683 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));
684 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));
685 1.16 riastrad totlen = uimin(len, sizeof(ps));
686 1.13 skrll memcpy(buf, &ps, totlen);
687 1.1 dyoung break;
688 1.1 dyoung case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
689 1.1 dyoung /* Set Hub Descriptor, 11.16.2.7, not supported */
690 1.1 dyoung /* STALL ? */
691 1.13 skrll return -1;
692 1.1 dyoung case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
693 1.1 dyoung /* Set Hub Feature, 11.16.2.8, not supported */
694 1.1 dyoung break;
695 1.1 dyoung case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
696 1.1 dyoung #define WPS(x) REG_WRITE(ADMHCD_REG_PORTSTATUS0+(index-1)*4, (x))
697 1.1 dyoung /* Set Port Feature, 11.16.2.9 */
698 1.1 dyoung if ((index != 1) && (index !=2)) {
699 1.1 dyoung printf("index=%d ", index);
700 1.13 skrll return -1;
701 1.1 dyoung }
702 1.1 dyoung switch (value) {
703 1.1 dyoung case UHF_PORT_RESET:
704 1.1 dyoung DPRINTF(D_MSG, ("PORT_RESET "));
705 1.1 dyoung WPS(ADMHCD_PRS);
706 1.1 dyoung break;
707 1.1 dyoung case UHF_PORT_POWER:
708 1.1 dyoung DPRINTF(D_MSG, ("PORT_POWER "));
709 1.1 dyoung WPS(ADMHCD_PPS);
710 1.1 dyoung break;
711 1.1 dyoung case UHF_PORT_ENABLE:
712 1.1 dyoung DPRINTF(D_MSG, ("PORT_ENABLE "));
713 1.1 dyoung WPS(ADMHCD_PES);
714 1.1 dyoung break;
715 1.1 dyoung default:
716 1.1 dyoung printf("SetPortFeatERR=0x%x ", value);
717 1.13 skrll return -1;
718 1.1 dyoung }
719 1.1 dyoung #undef WPS
720 1.1 dyoung break;
721 1.1 dyoung default:
722 1.1 dyoung DPRINTF(D_MSG, ("ioerr(UR=%02x,UT=%02x) ",
723 1.1 dyoung req->bRequest, req->bmRequestType));
724 1.13 skrll /* default from usbroothub */
725 1.13 skrll return buflen;
726 1.1 dyoung }
727 1.1 dyoung
728 1.13 skrll return totlen;
729 1.1 dyoung }
730 1.1 dyoung
731 1.1 dyoung static usbd_status
732 1.13 skrll ahci_root_intr_transfer(struct usbd_xfer *xfer)
733 1.1 dyoung {
734 1.1 dyoung
735 1.1 dyoung DPRINTF(D_TRACE, ("SLRItransfer "));
736 1.1 dyoung
737 1.29 riastrad /* Pipe isn't running, start first. */
738 1.13 skrll return ahci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
739 1.1 dyoung }
740 1.1 dyoung
741 1.1 dyoung static usbd_status
742 1.13 skrll ahci_root_intr_start(struct usbd_xfer *xfer)
743 1.1 dyoung {
744 1.13 skrll struct ahci_softc *sc = AHCI_XFER2SC(xfer);
745 1.1 dyoung
746 1.1 dyoung DPRINTF(D_TRACE, ("SLRIstart "));
747 1.1 dyoung
748 1.30 riastrad KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock);
749 1.30 riastrad
750 1.19 riastrad KASSERT(sc->sc_intr_xfer == NULL);
751 1.13 skrll sc->sc_interval = MS_TO_TICKS(xfer->ux_pipe->up_endpoint->ue_edesc->bInterval);
752 1.19 riastrad callout_schedule(&sc->sc_poll_handle, sc->sc_interval);
753 1.1 dyoung sc->sc_intr_xfer = xfer;
754 1.20 riastrad xfer->ux_status = USBD_IN_PROGRESS;
755 1.20 riastrad
756 1.1 dyoung return USBD_IN_PROGRESS;
757 1.1 dyoung }
758 1.1 dyoung
759 1.1 dyoung static void
760 1.13 skrll ahci_root_intr_abort(struct usbd_xfer *xfer)
761 1.1 dyoung {
762 1.19 riastrad struct ahci_softc *sc = AHCI_XFER2SC(xfer);
763 1.19 riastrad
764 1.1 dyoung DPRINTF(D_TRACE, ("SLRIabort "));
765 1.19 riastrad
766 1.19 riastrad KASSERT(mutex_owned(&sc->sc_lock));
767 1.19 riastrad KASSERT(xfer->ux_pipe->up_intrxfer == xfer);
768 1.19 riastrad
769 1.19 riastrad /*
770 1.19 riastrad * Try to stop the callout before it starts. If we got in too
771 1.19 riastrad * late, too bad; but if the callout had yet to run and time
772 1.19 riastrad * out the xfer, cancel it ourselves.
773 1.19 riastrad */
774 1.19 riastrad callout_stop(&sc->sc_poll_handle);
775 1.19 riastrad if (sc->sc_intr_xfer == NULL)
776 1.19 riastrad return;
777 1.19 riastrad
778 1.19 riastrad KASSERT(sc->sc_intr_xfer == xfer);
779 1.19 riastrad xfer->ux_status = USBD_CANCELLED;
780 1.19 riastrad usb_transfer_complete(xfer);
781 1.1 dyoung }
782 1.1 dyoung
783 1.1 dyoung static void
784 1.13 skrll ahci_root_intr_close(struct usbd_pipe *pipe)
785 1.1 dyoung {
786 1.19 riastrad struct ahci_softc *sc __diagused = AHCI_PIPE2SC(pipe);
787 1.1 dyoung
788 1.1 dyoung DPRINTF(D_TRACE, ("SLRIclose "));
789 1.1 dyoung
790 1.19 riastrad KASSERT(mutex_owned(&sc->sc_lock));
791 1.19 riastrad
792 1.19 riastrad /*
793 1.19 riastrad * The caller must arrange to have aborted the pipe already, so
794 1.19 riastrad * there can be no intr xfer in progress. The callout may
795 1.19 riastrad * still be pending from a prior intr xfer -- if it has already
796 1.19 riastrad * fired, it will see there is nothing to do, and do nothing.
797 1.19 riastrad */
798 1.19 riastrad KASSERT(sc->sc_intr_xfer == NULL);
799 1.19 riastrad KASSERT(!callout_pending(&sc->sc_poll_handle));
800 1.1 dyoung }
801 1.1 dyoung
802 1.1 dyoung static void
803 1.13 skrll ahci_root_intr_done(struct usbd_xfer *xfer)
804 1.1 dyoung {
805 1.19 riastrad struct ahci_softc *sc = AHCI_XFER2SC(xfer);
806 1.19 riastrad
807 1.1 dyoung //DPRINTF(D_XFER, ("RIdn "));
808 1.19 riastrad
809 1.19 riastrad KASSERT(mutex_owned(&sc->sc_lock));
810 1.19 riastrad
811 1.19 riastrad /* Claim the xfer so it doesn't get completed again. */
812 1.19 riastrad KASSERT(sc->sc_intr_xfer == xfer);
813 1.19 riastrad KASSERT(xfer->ux_status != USBD_IN_PROGRESS);
814 1.19 riastrad sc->sc_intr_xfer = NULL;
815 1.1 dyoung }
816 1.1 dyoung
817 1.1 dyoung static usbd_status
818 1.13 skrll ahci_device_ctrl_transfer(struct usbd_xfer *xfer)
819 1.1 dyoung {
820 1.1 dyoung
821 1.1 dyoung DPRINTF(D_TRACE, ("C"));
822 1.1 dyoung
823 1.13 skrll return ahci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
824 1.1 dyoung }
825 1.1 dyoung
826 1.1 dyoung static usbd_status
827 1.13 skrll ahci_device_ctrl_start(struct usbd_xfer *xfer)
828 1.1 dyoung {
829 1.1 dyoung usbd_status status = USBD_NORMAL_COMPLETION;
830 1.1 dyoung int s, err;
831 1.1 dyoung static struct admhcd_ed ep_v __attribute__((aligned(16))), *ep;
832 1.1 dyoung static struct admhcd_td td_v[4] __attribute__((aligned(16))), *td, *td1, *td2, *td3;
833 1.1 dyoung static usb_dma_t reqdma;
834 1.13 skrll struct usbd_pipe *pipe = xfer->ux_pipe;
835 1.13 skrll usb_device_request_t *req = &xfer->ux_request;
836 1.13 skrll struct ahci_softc *sc = AHCI_XFER2SC(xfer);
837 1.1 dyoung int len, isread;
838 1.11 skrll
839 1.30 riastrad KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock);
840 1.1 dyoung
841 1.1 dyoung #if 0
842 1.13 skrll struct ahci_pipe *apipe = (struct ahci_pipe *)xfer->ux_pipe;
843 1.1 dyoung #endif
844 1.1 dyoung /* printf("ctrl_start>>>\n"); */
845 1.1 dyoung
846 1.1 dyoung #ifdef DIAGNOSTIC
847 1.13 skrll if (!(xfer->ux_rqflags & URQ_REQUEST)) {
848 1.13 skrll /* XXX panic */
849 1.13 skrll printf("ahci_device_ctrl_transfer: not a request\n");
850 1.13 skrll return USBD_INVAL;
851 1.13 skrll }
852 1.1 dyoung #endif
853 1.1 dyoung
854 1.13 skrll #define KSEG1ADDR(x) (0xa0000000 | (((uint32_t)x) & 0x1fffffff))
855 1.1 dyoung DPRINTF(D_TRACE, ("st "));
856 1.1 dyoung if (!ep) {
857 1.13 skrll ep = (struct admhcd_ed *)KSEG1ADDR(&ep_v);
858 1.11 skrll td = (struct admhcd_td *)KSEG1ADDR(&td_v[0]);
859 1.11 skrll td1 = (struct admhcd_td *)KSEG1ADDR(&td_v[1]);
860 1.11 skrll td2 = (struct admhcd_td *)KSEG1ADDR(&td_v[2]);
861 1.11 skrll td3 = (struct admhcd_td *)KSEG1ADDR(&td_v[3]);
862 1.28 skrll err = usb_allocmem(sc->sc_bus.ub_dmatag,
863 1.1 dyoung sizeof(usb_device_request_t),
864 1.22 skrll 0, USBMALLOC_COHERENT, &reqdma);
865 1.1 dyoung if (err)
866 1.13 skrll return USBD_NOMEM;
867 1.1 dyoung
868 1.1 dyoung /* printf("ep: %p\n",ep); */
869 1.1 dyoung };
870 1.1 dyoung
871 1.13 skrll ep->control = pipe->up_dev->ud_addr | \
872 1.13 skrll ((pipe->up_dev->ud_speed==USB_SPEED_FULL)?ADMHCD_ED_SPEED:0) | \
873 1.13 skrll ((UGETW(pipe->up_endpoint->ue_edesc->wMaxPacketSize))<<ADMHCD_ED_MAXSHIFT);
874 1.23 skrll memcpy(KERNADDR(&reqdma, 0), req, sizeof(*req));
875 1.1 dyoung /* printf("status: %x\n",REG_READ(ADMHCD_REG_PORTSTATUS0));
876 1.1 dyoung printf("ep_control: %x\n",ep->control);
877 1.13 skrll printf("speed: %x\n",pipe->up_dev->ud_speed);
878 1.1 dyoung printf("req: %p\n",req);
879 1.13 skrll printf("dmabuf: %p\n",xfer->ux_dmabuf.block); */
880 1.1 dyoung
881 1.1 dyoung isread = req->bmRequestType & UT_READ;
882 1.1 dyoung len = UGETW(req->wLength);
883 1.1 dyoung
884 1.13 skrll ep->next = ep;
885 1.1 dyoung
886 1.13 skrll td->buffer = DMAADDR(&reqdma,0) | 0xa0000000;
887 1.13 skrll td->buflen=sizeof(*req);
888 1.13 skrll td->control=ADMHCD_TD_SETUP | ADMHCD_TD_DATA0 | ADMHCD_TD_OWN;
889 1.1 dyoung
890 1.1 dyoung if (len) {
891 1.1 dyoung td->next = td1;
892 1.1 dyoung
893 1.13 skrll td1->buffer = DMAADDR(&xfer->ux_dmabuf,0) | 0xa0000000;
894 1.1 dyoung td1->buflen = len;
895 1.1 dyoung td1->next = td2;
896 1.1 dyoung td1->control= (isread?ADMHCD_TD_IN:ADMHCD_TD_OUT) | ADMHCD_TD_DATA1 | ADMHCD_TD_R | ADMHCD_TD_OWN;
897 1.13 skrll } else {
898 1.13 skrll td1->control = 0;
899 1.13 skrll td->next = td2;
900 1.13 skrll };
901 1.1 dyoung
902 1.1 dyoung td2->buffer = 0;
903 1.1 dyoung td2->buflen= 0;
904 1.1 dyoung td2->next = td3;
905 1.1 dyoung td2->control = (isread?ADMHCD_TD_OUT:ADMHCD_TD_IN) | ADMHCD_TD_DATA1 | ADMHCD_TD_OWN;
906 1.1 dyoung
907 1.1 dyoung td3->buffer = 0;
908 1.1 dyoung td3->buflen= 0;
909 1.1 dyoung td3->next = 0;
910 1.1 dyoung td3->control = 0;
911 1.1 dyoung
912 1.1 dyoung ep->head = td;
913 1.1 dyoung ep->tail = td3;
914 1.1 dyoung /*
915 1.1 dyoung printf("ep: %p\n",ep);
916 1.1 dyoung printf("ep->next: %p\n",ep->next);
917 1.1 dyoung printf("ep->head: %p\n",ep->head);
918 1.1 dyoung printf("ep->tail: %p\n",ep->tail);
919 1.1 dyoung printf("td: %p\n",td);
920 1.1 dyoung printf("td->next: %p\n",td->next);
921 1.1 dyoung printf("td->buffer: %x\n",td->buffer);
922 1.1 dyoung printf("td->buflen: %x\n",td->buflen);
923 1.1 dyoung printf("td1: %p\n",td1);
924 1.1 dyoung printf("td1->next: %p\n",td1->next);
925 1.1 dyoung printf("td2: %p\n",td2);
926 1.1 dyoung printf("td2->next: %p\n",td2->next);
927 1.1 dyoung printf("td3: %p\n",td3);
928 1.1 dyoung printf("td3->next: %p\n",td3->next);
929 1.1 dyoung */
930 1.1 dyoung
931 1.13 skrll REG_WRITE(ADMHCD_REG_HOSTHEAD, (uint32_t)ep);
932 1.13 skrll REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP | ADMHCD_DMA_EN);
933 1.1 dyoung /* printf("1: %x %x %x %x\n", ep->control, td->control, td1->control, td2->control); */
934 1.13 skrll s=100;
935 1.13 skrll while (s--) {
936 1.13 skrll delay_ms(10);
937 1.1 dyoung /* printf("%x %x %x %x\n", ep->control, td->control, td1->control, td2->control);*/
938 1.1 dyoung status = USBD_TIMEOUT;
939 1.13 skrll if (td->control & ADMHCD_TD_OWN) continue;
940 1.1 dyoung
941 1.13 skrll err = (td->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT;
942 1.13 skrll if (err) {
943 1.1 dyoung status = USBD_IOERROR;
944 1.13 skrll break;
945 1.13 skrll };
946 1.1 dyoung
947 1.1 dyoung status = USBD_TIMEOUT;
948 1.13 skrll if (td1->control & ADMHCD_TD_OWN) continue;
949 1.13 skrll err = (td1->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT;
950 1.13 skrll if (err) {
951 1.1 dyoung status = USBD_IOERROR;
952 1.13 skrll break;
953 1.13 skrll };
954 1.1 dyoung
955 1.1 dyoung status = USBD_TIMEOUT;
956 1.13 skrll if (td2->control & ADMHCD_TD_OWN) continue;
957 1.13 skrll err = (td2->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT;
958 1.13 skrll if (err) {
959 1.1 dyoung status = USBD_IOERROR;
960 1.13 skrll };
961 1.1 dyoung status = USBD_NORMAL_COMPLETION;
962 1.13 skrll break;
963 1.1 dyoung
964 1.1 dyoung };
965 1.13 skrll REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP);
966 1.1 dyoung
967 1.13 skrll xfer->ux_actlen = len;
968 1.13 skrll xfer->ux_status = status;
969 1.1 dyoung
970 1.1 dyoung /* printf("ctrl_start<<<\n"); */
971 1.1 dyoung
972 1.1 dyoung usb_transfer_complete(xfer);
973 1.21 skrll
974 1.28 skrll usb_freemem(&reqdma);
975 1.21 skrll
976 1.12 skrll return USBD_NORMAL_COMPLETION;
977 1.1 dyoung }
978 1.1 dyoung
979 1.1 dyoung static void
980 1.13 skrll ahci_device_ctrl_abort(struct usbd_xfer *xfer)
981 1.1 dyoung {
982 1.1 dyoung DPRINTF(D_TRACE, ("Cab "));
983 1.18 riastrad usbd_xfer_abort(xfer);
984 1.1 dyoung }
985 1.1 dyoung
986 1.1 dyoung static void
987 1.13 skrll ahci_device_ctrl_close(struct usbd_pipe *pipe)
988 1.1 dyoung {
989 1.1 dyoung DPRINTF(D_TRACE, ("Ccl "));
990 1.1 dyoung }
991 1.1 dyoung
992 1.1 dyoung static void
993 1.13 skrll ahci_device_ctrl_done(struct usbd_xfer *xfer)
994 1.1 dyoung {
995 1.1 dyoung DPRINTF(D_TRACE, ("Cdn "));
996 1.1 dyoung }
997 1.1 dyoung
998 1.1 dyoung static usbd_status
999 1.13 skrll ahci_device_intr_transfer(struct usbd_xfer *xfer)
1000 1.1 dyoung {
1001 1.1 dyoung
1002 1.1 dyoung DPRINTF(D_TRACE, ("INTRtrans "));
1003 1.1 dyoung
1004 1.13 skrll return ahci_device_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
1005 1.1 dyoung }
1006 1.1 dyoung
1007 1.1 dyoung static usbd_status
1008 1.13 skrll ahci_device_intr_start(struct usbd_xfer *xfer)
1009 1.1 dyoung {
1010 1.30 riastrad struct ahci_softc *sc = AHCI_XFER2SC(xfer);
1011 1.13 skrll struct usbd_pipe *pipe = xfer->ux_pipe;
1012 1.1 dyoung struct ahci_xfer *sx;
1013 1.1 dyoung
1014 1.1 dyoung DPRINTF(D_TRACE, ("INTRstart "));
1015 1.1 dyoung
1016 1.30 riastrad KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock);
1017 1.30 riastrad
1018 1.13 skrll sx = kmem_intr_alloc(sizeof(*sx), KM_NOSLEEP);
1019 1.1 dyoung if (sx == NULL)
1020 1.1 dyoung goto reterr;
1021 1.1 dyoung memset(sx, 0, sizeof(*sx));
1022 1.13 skrll sx->sx_xfer = xfer;
1023 1.13 skrll xfer->ux_hcpriv = sx;
1024 1.1 dyoung
1025 1.1 dyoung /* initialize callout */
1026 1.6 dyoung callout_init(&sx->sx_callout_t, 0);
1027 1.11 skrll callout_reset(&sx->sx_callout_t,
1028 1.13 skrll MS_TO_TICKS(pipe->up_endpoint->ue_edesc->bInterval),
1029 1.1 dyoung ahci_poll_device, sx);
1030 1.1 dyoung
1031 1.1 dyoung /* ACK */
1032 1.1 dyoung return USBD_IN_PROGRESS;
1033 1.1 dyoung
1034 1.1 dyoung reterr:
1035 1.1 dyoung return USBD_IOERROR;
1036 1.1 dyoung }
1037 1.1 dyoung
1038 1.1 dyoung static void
1039 1.1 dyoung ahci_poll_device(void *arg)
1040 1.1 dyoung {
1041 1.1 dyoung struct ahci_xfer *sx = (struct ahci_xfer *)arg;
1042 1.13 skrll struct usbd_xfer *xfer = sx->sx_xfer;
1043 1.13 skrll struct usbd_pipe *pipe = xfer->ux_pipe;
1044 1.13 skrll struct ahci_softc *sc = AHCI_XFER2SC(xfer);
1045 1.1 dyoung void *buf;
1046 1.1 dyoung int pid;
1047 1.1 dyoung int r;
1048 1.1 dyoung
1049 1.1 dyoung DPRINTF(D_TRACE, ("pldev"));
1050 1.1 dyoung
1051 1.6 dyoung callout_reset(&sx->sx_callout_t,
1052 1.13 skrll MS_TO_TICKS(pipe->up_endpoint->ue_edesc->bInterval),
1053 1.1 dyoung ahci_poll_device, sx);
1054 1.1 dyoung
1055 1.1 dyoung /* interrupt transfer */
1056 1.13 skrll pid = (UE_GET_DIR(pipe->up_endpoint->ue_edesc->bEndpointAddress) == UE_DIR_IN)
1057 1.1 dyoung ? ADMHCD_TD_IN : ADMHCD_TD_OUT;
1058 1.13 skrll buf = KERNADDR(&xfer->ux_dmabuf, 0);
1059 1.1 dyoung
1060 1.13 skrll r = ahci_transaction(sc, pipe, pid, xfer->ux_length, buf, 0/*toggle*/);
1061 1.1 dyoung if (r < 0) {
1062 1.2 perry DPRINTF(D_MSG, ("%s error", __func__));
1063 1.1 dyoung return;
1064 1.1 dyoung }
1065 1.1 dyoung /* no change, return NAK */
1066 1.1 dyoung if (r == 0)
1067 1.1 dyoung return;
1068 1.1 dyoung
1069 1.13 skrll xfer->ux_status = USBD_NORMAL_COMPLETION;
1070 1.12 skrll mutex_enter(&sc->sc_lock);
1071 1.1 dyoung usb_transfer_complete(xfer);
1072 1.12 skrll mutex_exit(&sc->sc_lock);
1073 1.1 dyoung }
1074 1.1 dyoung
1075 1.1 dyoung static void
1076 1.13 skrll ahci_device_intr_abort(struct usbd_xfer *xfer)
1077 1.1 dyoung {
1078 1.1 dyoung struct ahci_xfer *sx;
1079 1.1 dyoung
1080 1.1 dyoung DPRINTF(D_TRACE, ("INTRabort "));
1081 1.1 dyoung
1082 1.13 skrll sx = xfer->ux_hcpriv;
1083 1.1 dyoung if (sx) {
1084 1.6 dyoung callout_stop(&sx->sx_callout_t);
1085 1.13 skrll kmem_intr_free(sx, sizeof(*sx));
1086 1.13 skrll xfer->ux_hcpriv = NULL;
1087 1.1 dyoung } else {
1088 1.2 perry printf("%s: sx == NULL!\n", __func__);
1089 1.1 dyoung }
1090 1.18 riastrad usbd_xfer_abort(xfer);
1091 1.1 dyoung }
1092 1.1 dyoung
1093 1.1 dyoung static void
1094 1.13 skrll ahci_device_intr_close(struct usbd_pipe *pipe)
1095 1.1 dyoung {
1096 1.1 dyoung DPRINTF(D_TRACE, ("INTRclose "));
1097 1.1 dyoung }
1098 1.1 dyoung
1099 1.1 dyoung static void
1100 1.13 skrll ahci_device_intr_done(struct usbd_xfer *xfer)
1101 1.1 dyoung {
1102 1.1 dyoung DPRINTF(D_TRACE, ("INTRdone "));
1103 1.1 dyoung }
1104 1.1 dyoung
1105 1.1 dyoung static usbd_status
1106 1.13 skrll ahci_device_isoc_transfer(struct usbd_xfer *xfer)
1107 1.1 dyoung {
1108 1.1 dyoung DPRINTF(D_TRACE, ("S"));
1109 1.1 dyoung return USBD_NORMAL_COMPLETION;
1110 1.1 dyoung }
1111 1.1 dyoung
1112 1.1 dyoung static usbd_status
1113 1.13 skrll ahci_device_isoc_start(struct usbd_xfer *xfer)
1114 1.1 dyoung {
1115 1.1 dyoung DPRINTF(D_TRACE, ("st "));
1116 1.1 dyoung return USBD_NORMAL_COMPLETION;
1117 1.1 dyoung }
1118 1.1 dyoung
1119 1.1 dyoung static void
1120 1.13 skrll ahci_device_isoc_abort(struct usbd_xfer *xfer)
1121 1.1 dyoung {
1122 1.1 dyoung DPRINTF(D_TRACE, ("Sab "));
1123 1.1 dyoung }
1124 1.1 dyoung
1125 1.1 dyoung static void
1126 1.13 skrll ahci_device_isoc_close(struct usbd_pipe *pipe)
1127 1.1 dyoung {
1128 1.1 dyoung DPRINTF(D_TRACE, ("Scl "));
1129 1.1 dyoung }
1130 1.1 dyoung
1131 1.1 dyoung static void
1132 1.13 skrll ahci_device_isoc_done(struct usbd_xfer *xfer)
1133 1.1 dyoung {
1134 1.1 dyoung DPRINTF(D_TRACE, ("Sdn "));
1135 1.1 dyoung }
1136 1.1 dyoung
1137 1.1 dyoung static usbd_status
1138 1.13 skrll ahci_device_bulk_transfer(struct usbd_xfer *xfer)
1139 1.1 dyoung {
1140 1.1 dyoung
1141 1.1 dyoung DPRINTF(D_TRACE, ("B"));
1142 1.1 dyoung
1143 1.13 skrll return ahci_device_bulk_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
1144 1.1 dyoung }
1145 1.1 dyoung
1146 1.1 dyoung static usbd_status
1147 1.13 skrll ahci_device_bulk_start(struct usbd_xfer *xfer)
1148 1.1 dyoung {
1149 1.1 dyoung #define NBULK_TDS 32
1150 1.1 dyoung static volatile int level = 0;
1151 1.1 dyoung usbd_status status = USBD_NORMAL_COMPLETION;
1152 1.1 dyoung int s, err;
1153 1.1 dyoung static struct admhcd_ed ep_v __attribute__((aligned(16))), *ep;
1154 1.1 dyoung static struct admhcd_td td_v[NBULK_TDS] __attribute__((aligned(16))), *td[NBULK_TDS];
1155 1.13 skrll struct usbd_pipe *pipe = xfer->ux_pipe;
1156 1.13 skrll struct ahci_softc *sc = AHCI_XFER2SC(xfer);
1157 1.1 dyoung int endpt, i, len, tlen, segs, offset, isread, toggle, short_ok;
1158 1.13 skrll struct ahci_pipe *apipe = (struct ahci_pipe *)xfer->ux_pipe;
1159 1.1 dyoung
1160 1.13 skrll #define KSEG1ADDR(x) (0xa0000000 | (((uint32_t)x) & 0x1fffffff))
1161 1.1 dyoung DPRINTF(D_TRACE, ("st "));
1162 1.1 dyoung
1163 1.30 riastrad KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock);
1164 1.30 riastrad
1165 1.1 dyoung #ifdef DIAGNOSTIC
1166 1.13 skrll if (xfer->ux_rqflags & URQ_REQUEST) {
1167 1.1 dyoung /* XXX panic */
1168 1.1 dyoung printf("ohci_device_bulk_start: a request\n");
1169 1.13 skrll return USBD_INVAL;
1170 1.1 dyoung }
1171 1.1 dyoung #endif
1172 1.1 dyoung
1173 1.1 dyoung level++;
1174 1.1 dyoung /* printf("bulk_start>>>\n"); */
1175 1.1 dyoung
1176 1.1 dyoung if (!ep) {
1177 1.13 skrll ep = (struct admhcd_ed *)KSEG1ADDR(&ep_v);
1178 1.1 dyoung for (i=0; i<NBULK_TDS; i++) {
1179 1.11 skrll td[i] = (struct admhcd_td *)KSEG1ADDR(&td_v[i]);
1180 1.1 dyoung };
1181 1.1 dyoung /* printf("ep: %p\n",ep);*/
1182 1.1 dyoung };
1183 1.1 dyoung if (apipe->toggle == 0) {
1184 1.1 dyoung toggle = ADMHCD_TD_DATA0;
1185 1.1 dyoung } else {
1186 1.1 dyoung toggle = apipe->toggle;
1187 1.1 dyoung };
1188 1.1 dyoung
1189 1.13 skrll endpt = pipe->up_endpoint->ue_edesc->bEndpointAddress;
1190 1.13 skrll ep->control = pipe->up_dev->ud_addr | ((endpt & 0xf) << ADMHCD_ED_EPSHIFT)|\
1191 1.13 skrll ((pipe->up_dev->ud_speed==USB_SPEED_FULL)?ADMHCD_ED_SPEED:0) | \
1192 1.13 skrll ((UGETW(pipe->up_endpoint->ue_edesc->wMaxPacketSize))<<ADMHCD_ED_MAXSHIFT);
1193 1.1 dyoung
1194 1.13 skrll short_ok = xfer->ux_flags & USBD_SHORT_XFER_OK?ADMHCD_TD_R:0;
1195 1.1 dyoung /* printf("level: %d\n",level);
1196 1.1 dyoung printf("short_xfer: %x\n",short_ok);
1197 1.1 dyoung printf("ep_control: %x\n",ep->control);
1198 1.13 skrll printf("speed: %x\n",pipe->up_dev->ud_speed);
1199 1.13 skrll printf("dmabuf: %p\n",xfer->ux_dmabuf.block); */
1200 1.1 dyoung
1201 1.13 skrll isread = UE_GET_DIR(endpt) == UE_DIR_IN;
1202 1.13 skrll len = xfer->ux_length;
1203 1.1 dyoung
1204 1.13 skrll ep->next = ep;
1205 1.1 dyoung
1206 1.1 dyoung i = 0;
1207 1.1 dyoung offset = 0;
1208 1.27 skrll while (len > 0 || i == 0) {
1209 1.16 riastrad tlen = uimin(len,4096);
1210 1.23 skrll td[i]->buffer = DMAADDR(&xfer->ux_dmabuf, offset) | 0xa0000000;
1211 1.23 skrll td[i]->buflen = tlen;
1212 1.23 skrll td[i]->control = (isread ? ADMHCD_TD_IN : ADMHCD_TD_OUT) |
1213 1.23 skrll toggle | ADMHCD_TD_OWN | short_ok;
1214 1.23 skrll td[i]->len = tlen;
1215 1.1 dyoung toggle = ADMHCD_TD_TOGGLE;
1216 1.1 dyoung len -= tlen;
1217 1.1 dyoung offset += tlen;
1218 1.23 skrll td[i]->next = td[i + 1];
1219 1.1 dyoung i++;
1220 1.1 dyoung };
1221 1.1 dyoung
1222 1.1 dyoung td[i]->buffer = 0;
1223 1.1 dyoung td[i]->buflen = 0;
1224 1.1 dyoung td[i]->control = 0;
1225 1.1 dyoung td[i]->next = 0;
1226 1.1 dyoung
1227 1.1 dyoung ep->head = td[0];
1228 1.1 dyoung ep->tail = td[i];
1229 1.1 dyoung segs = i;
1230 1.1 dyoung len = 0;
1231 1.1 dyoung
1232 1.22 skrll if (xfer->ux_length)
1233 1.22 skrll usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length,
1234 1.22 skrll isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
1235 1.22 skrll
1236 1.1 dyoung /* printf("segs: %d\n",segs);
1237 1.1 dyoung printf("ep: %p\n",ep);
1238 1.1 dyoung printf("ep->control: %x\n",ep->control);
1239 1.1 dyoung printf("ep->next: %p\n",ep->next);
1240 1.1 dyoung printf("ep->head: %p\n",ep->head);
1241 1.1 dyoung printf("ep->tail: %p\n",ep->tail);
1242 1.1 dyoung for (i=0; i<segs; i++) {
1243 1.1 dyoung printf("td[%d]: %p\n",i,td[i]);
1244 1.1 dyoung printf("td[%d]->control: %x\n",i,td[i]->control);
1245 1.1 dyoung printf("td[%d]->next: %p\n",i,td[i]->next);
1246 1.1 dyoung printf("td[%d]->buffer: %x\n",i,td[i]->buffer);
1247 1.1 dyoung printf("td[%d]->buflen: %x\n",i,td[i]->buflen);
1248 1.1 dyoung }; */
1249 1.1 dyoung
1250 1.13 skrll REG_WRITE(ADMHCD_REG_HOSTHEAD, (uint32_t)ep);
1251 1.13 skrll REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP | ADMHCD_DMA_EN);
1252 1.1 dyoung i = 0;
1253 1.1 dyoung /* printf("1: %x %d %x %x\n", ep->control, i, td[i]->control, td[i]->buflen); */
1254 1.13 skrll s=100;
1255 1.1 dyoung err = 0;
1256 1.13 skrll while (s--) {
1257 1.1 dyoung /* printf("%x %d %x %x\n", ep->control, i, td[i]->control, td[i]->buflen); */
1258 1.1 dyoung status = USBD_TIMEOUT;
1259 1.13 skrll if (td[i]->control & ADMHCD_TD_OWN) {
1260 1.1 dyoung delay_ms(3);
1261 1.1 dyoung continue;
1262 1.1 dyoung };
1263 1.1 dyoung
1264 1.1 dyoung len += td[i]->len - td[i]->buflen;
1265 1.1 dyoung
1266 1.13 skrll err = (td[i]->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT;
1267 1.13 skrll if (err) {
1268 1.1 dyoung status = USBD_IOERROR;
1269 1.13 skrll break;
1270 1.13 skrll };
1271 1.11 skrll
1272 1.1 dyoung i++;
1273 1.1 dyoung if (i==segs) {
1274 1.1 dyoung status = USBD_NORMAL_COMPLETION;
1275 1.1 dyoung break;
1276 1.1 dyoung };
1277 1.1 dyoung
1278 1.1 dyoung };
1279 1.13 skrll REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP);
1280 1.1 dyoung
1281 1.13 skrll apipe->toggle = ((uint32_t)ep->head & 2)?ADMHCD_TD_DATA1:ADMHCD_TD_DATA0;
1282 1.1 dyoung /* printf("bulk_transfer_done: status: %x, err: %x, len: %x, toggle: %x\n", status,err,len,apipe->toggle); */
1283 1.1 dyoung
1284 1.1 dyoung if (short_ok && (err == 0x9 || err == 0xd)) {
1285 1.1 dyoung /* printf("bulk_transfer_done: short_transfer fix\n"); */
1286 1.1 dyoung status = USBD_NORMAL_COMPLETION;
1287 1.1 dyoung };
1288 1.13 skrll xfer->ux_actlen = len;
1289 1.13 skrll xfer->ux_status = status;
1290 1.1 dyoung
1291 1.1 dyoung level--;
1292 1.1 dyoung /* printf("bulk_start<<<\n"); */
1293 1.1 dyoung
1294 1.22 skrll if (xfer->ux_length)
1295 1.22 skrll usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length,
1296 1.22 skrll isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1297 1.22 skrll
1298 1.1 dyoung usb_transfer_complete(xfer);
1299 1.12 skrll
1300 1.12 skrll return USBD_NORMAL_COMPLETION;
1301 1.1 dyoung }
1302 1.1 dyoung
1303 1.1 dyoung static void
1304 1.13 skrll ahci_device_bulk_abort(struct usbd_xfer *xfer)
1305 1.1 dyoung {
1306 1.1 dyoung DPRINTF(D_TRACE, ("Bab "));
1307 1.18 riastrad usbd_xfer_abort(xfer);
1308 1.1 dyoung }
1309 1.1 dyoung
1310 1.1 dyoung static void
1311 1.13 skrll ahci_device_bulk_close(struct usbd_pipe *pipe)
1312 1.1 dyoung {
1313 1.1 dyoung DPRINTF(D_TRACE, ("Bcl "));
1314 1.1 dyoung }
1315 1.1 dyoung
1316 1.1 dyoung static void
1317 1.13 skrll ahci_device_bulk_done(struct usbd_xfer *xfer)
1318 1.1 dyoung {
1319 1.1 dyoung DPRINTF(D_TRACE, ("Bdn "));
1320 1.1 dyoung }
1321 1.1 dyoung
1322 1.1 dyoung #define DATA0_RD (0x03)
1323 1.1 dyoung #define DATA0_WR (0x07)
1324 1.1 dyoung #define AHCI_TIMEOUT (5000)
1325 1.1 dyoung
1326 1.1 dyoung /*
1327 1.1 dyoung * Do a transaction.
1328 1.1 dyoung * return 1 if ACK, 0 if NAK, -1 if error.
1329 1.1 dyoung */
1330 1.1 dyoung static int
1331 1.13 skrll ahci_transaction(struct ahci_softc *sc, struct usbd_pipe *pipe,
1332 1.13 skrll uint8_t pid, int len, u_char *buf, uint8_t toggle)
1333 1.1 dyoung {
1334 1.1 dyoung return -1;
1335 1.1 dyoung #if 0
1336 1.1 dyoung #ifdef AHCI_DEBUG
1337 1.1 dyoung char str[64];
1338 1.1 dyoung int i;
1339 1.1 dyoung #endif
1340 1.1 dyoung int timeout;
1341 1.1 dyoung int ls_via_hub = 0;
1342 1.1 dyoung int pl;
1343 1.13 skrll uint8_t isr;
1344 1.13 skrll uint8_t result = 0;
1345 1.13 skrll uint8_t devaddr = pipe->up_dev->ud_addr;
1346 1.13 skrll uint8_t endpointaddr = pipe->up_endpoint->ue_edesc->bEndpointAddress;
1347 1.13 skrll uint8_t endpoint;
1348 1.13 skrll uint8_t cmd = DATA0_RD;
1349 1.1 dyoung
1350 1.1 dyoung endpoint = UE_GET_ADDR(endpointaddr);
1351 1.1 dyoung DPRINTF(D_XFER, ("\n(%x,%d%s%d,%d) ",
1352 1.1 dyoung pid, len, (pid == SL11_PID_IN) ? "<-" : "->", devaddr, endpoint));
1353 1.1 dyoung
1354 1.1 dyoung /* Set registers */
1355 1.1 dyoung sl11write(sc, SL11_E0ADDR, 0x40);
1356 1.1 dyoung sl11write(sc, SL11_E0LEN, len);
1357 1.1 dyoung sl11write(sc, SL11_E0PID, (pid << 4) + endpoint);
1358 1.1 dyoung sl11write(sc, SL11_E0DEV, devaddr);
1359 1.1 dyoung
1360 1.1 dyoung /* Set buffer unless PID_IN */
1361 1.1 dyoung if (pid != SL11_PID_IN) {
1362 1.1 dyoung if (len > 0)
1363 1.1 dyoung sl11write_region(sc, 0x40, buf, len);
1364 1.1 dyoung cmd = DATA0_WR;
1365 1.1 dyoung }
1366 1.1 dyoung
1367 1.1 dyoung /* timing ? */
1368 1.1 dyoung pl = (len >> 3) + 3;
1369 1.1 dyoung
1370 1.1 dyoung /* Low speed device via HUB */
1371 1.1 dyoung /* XXX does not work... */
1372 1.13 skrll if ((sc->sc_fullspeed) && pipe->up_dev->ud_speed == USB_SPEED_LOW) {
1373 1.1 dyoung pl = len + 16;
1374 1.1 dyoung cmd |= SL11_EPCTRL_PREAMBLE;
1375 1.1 dyoung
1376 1.1 dyoung /*
1377 1.1 dyoung * SL811HS/T rev 1.2 has a bug, when it got PID_IN
1378 1.1 dyoung * from LowSpeed device via HUB.
1379 1.1 dyoung */
1380 1.1 dyoung if (sc->sc_sltype == SLTYPE_SL811HS_R12 && pid == SL11_PID_IN) {
1381 1.1 dyoung ls_via_hub = 1;
1382 1.1 dyoung DPRINTF(D_MSG, ("LSvH "));
1383 1.1 dyoung }
1384 1.1 dyoung }
1385 1.1 dyoung
1386 1.1 dyoung /* timing ? */
1387 1.13 skrll if (sl11read(sc, SL811_CSOF) <= (uint8_t)pl)
1388 1.1 dyoung cmd |= SL11_EPCTRL_SOF;
1389 1.1 dyoung
1390 1.1 dyoung /* Transfer */
1391 1.1 dyoung sl11write(sc, SL11_ISR, 0xff);
1392 1.1 dyoung sl11write(sc, SL11_E0CTRL, cmd | toggle);
1393 1.1 dyoung
1394 1.1 dyoung /* Polling */
1395 1.1 dyoung for (timeout = AHCI_TIMEOUT; timeout; timeout--) {
1396 1.1 dyoung isr = sl11read(sc, SL11_ISR);
1397 1.1 dyoung if ((isr & SL11_ISR_USBA))
1398 1.1 dyoung break;
1399 1.1 dyoung }
1400 1.1 dyoung
1401 1.1 dyoung /* Check result status */
1402 1.1 dyoung result = sl11read(sc, SL11_E0STAT);
1403 1.1 dyoung if (!(result & SL11_EPSTAT_NAK) && ls_via_hub) {
1404 1.1 dyoung /* Resend PID_IN within 20usec */
1405 1.1 dyoung sl11write(sc, SL11_ISR, 0xff);
1406 1.1 dyoung sl11write(sc, SL11_E0CTRL, SL11_EPCTRL_ARM);
1407 1.1 dyoung }
1408 1.1 dyoung
1409 1.1 dyoung sl11write(sc, SL11_ISR, 0xff);
1410 1.1 dyoung
1411 1.1 dyoung DPRINTF(D_XFER, ("t=%d i=%x ", AHCI_TIMEOUT - timeout, isr));
1412 1.1 dyoung #if AHCI_DEBUG
1413 1.5 christos snprintb(str, sizeof(str),
1414 1.5 christos "\20\x8STALL\7NAK\6OV\5SETUP\4DATA1\3TIMEOUT\2ERR\1ACK", result);
1415 1.1 dyoung DPRINTF(D_XFER, ("STAT=%s ", str));
1416 1.1 dyoung #endif
1417 1.1 dyoung
1418 1.1 dyoung if ((result & SL11_EPSTAT_ERROR))
1419 1.1 dyoung return -1;
1420 1.1 dyoung
1421 1.1 dyoung if ((result & SL11_EPSTAT_NAK))
1422 1.1 dyoung return 0;
1423 1.1 dyoung
1424 1.1 dyoung /* Read buffer if PID_IN */
1425 1.1 dyoung if (pid == SL11_PID_IN && len > 0) {
1426 1.1 dyoung sl11read_region(sc, buf, 0x40, len);
1427 1.1 dyoung #if AHCI_DEBUG
1428 1.1 dyoung for (i = 0; i < len; i++)
1429 1.1 dyoung DPRINTF(D_XFER, ("%02X ", buf[i]));
1430 1.1 dyoung #endif
1431 1.1 dyoung }
1432 1.1 dyoung
1433 1.1 dyoung return 1;
1434 1.1 dyoung #endif
1435 1.1 dyoung }
1436 1.1 dyoung
1437 1.18 riastrad static void
1438 1.18 riastrad ahci_abortx(struct usbd_xfer *xfer)
1439 1.1 dyoung {
1440 1.18 riastrad /*
1441 1.18 riastrad * XXX This is totally busted; there's no way it can possibly
1442 1.18 riastrad * work! All transfers are busy-waited, it seems, so there is
1443 1.18 riastrad * no opportunity to abort.
1444 1.18 riastrad */
1445 1.18 riastrad KASSERT(xfer->ux_status != USBD_IN_PROGRESS);
1446 1.1 dyoung }
1447 1.1 dyoung
1448 1.1 dyoung void
1449 1.13 skrll ahci_device_clear_toggle(struct usbd_pipe *pipe)
1450 1.1 dyoung {
1451 1.13 skrll struct ahci_pipe *apipe = (struct ahci_pipe *)pipe;
1452 1.1 dyoung apipe->toggle = 0;
1453 1.1 dyoung }
1454 1.1 dyoung
1455 1.1 dyoung #ifdef AHCI_DEBUG
1456 1.1 dyoung void
1457 1.1 dyoung print_req(usb_device_request_t *r)
1458 1.1 dyoung {
1459 1.1 dyoung const char *xmes[]={
1460 1.1 dyoung "GETSTAT",
1461 1.1 dyoung "CLRFEAT",
1462 1.1 dyoung "res",
1463 1.1 dyoung "SETFEAT",
1464 1.1 dyoung "res",
1465 1.1 dyoung "SETADDR",
1466 1.1 dyoung "GETDESC",
1467 1.1 dyoung "SETDESC",
1468 1.1 dyoung "GETCONF",
1469 1.1 dyoung "SETCONF",
1470 1.1 dyoung "GETIN/F",
1471 1.1 dyoung "SETIN/F",
1472 1.1 dyoung "SYNC_FR"
1473 1.1 dyoung };
1474 1.1 dyoung int req, type, value, index, len;
1475 1.1 dyoung
1476 1.1 dyoung req = r->bRequest;
1477 1.1 dyoung type = r->bmRequestType;
1478 1.1 dyoung value = UGETW(r->wValue);
1479 1.1 dyoung index = UGETW(r->wIndex);
1480 1.1 dyoung len = UGETW(r->wLength);
1481 1.1 dyoung
1482 1.1 dyoung printf("%x,%s,v=%d,i=%d,l=%d ",
1483 1.1 dyoung type, xmes[req], value, index, len);
1484 1.1 dyoung }
1485 1.1 dyoung
1486 1.1 dyoung void
1487 1.1 dyoung print_req_hub(usb_device_request_t *r)
1488 1.1 dyoung {
1489 1.1 dyoung struct {
1490 1.1 dyoung int req;
1491 1.1 dyoung int type;
1492 1.1 dyoung const char *str;
1493 1.1 dyoung } conf[] = {
1494 1.1 dyoung { 1, 0x20, "ClrHubFeat" },
1495 1.1 dyoung { 1, 0x23, "ClrPortFeat" },
1496 1.1 dyoung { 2, 0xa3, "GetBusState" },
1497 1.1 dyoung { 6, 0xa0, "GetHubDesc" },
1498 1.1 dyoung { 0, 0xa0, "GetHubStat" },
1499 1.1 dyoung { 0, 0xa3, "GetPortStat" },
1500 1.1 dyoung { 7, 0x20, "SetHubDesc" },
1501 1.1 dyoung { 3, 0x20, "SetHubFeat" },
1502 1.1 dyoung { 3, 0x23, "SetPortFeat" },
1503 1.1 dyoung {-1, 0, NULL},
1504 1.1 dyoung };
1505 1.1 dyoung int i;
1506 1.1 dyoung int value, index, len;
1507 1.1 dyoung
1508 1.1 dyoung value = UGETW(r->wValue);
1509 1.1 dyoung index = UGETW(r->wIndex);
1510 1.1 dyoung len = UGETW(r->wLength);
1511 1.1 dyoung for (i = 0; ; i++) {
1512 1.1 dyoung if (conf[i].req == -1 )
1513 1.1 dyoung return print_req(r);
1514 1.1 dyoung if (r->bmRequestType == conf[i].type && r->bRequest == conf[i].req) {
1515 1.1 dyoung printf("%s", conf[i].str);
1516 1.1 dyoung break;
1517 1.1 dyoung }
1518 1.1 dyoung }
1519 1.1 dyoung printf(",v=%d,i=%d,l=%d ", value, index, len);
1520 1.1 dyoung }
1521 1.1 dyoung
1522 1.1 dyoung void
1523 1.1 dyoung print_dumpreg(struct ahci_softc *sc)
1524 1.1 dyoung {
1525 1.1 dyoung #if 0
1526 1.1 dyoung printf("00=%02x,01=%02x,02=%02x,03=%02x,04=%02x,"
1527 1.1 dyoung "08=%02x,09=%02x,0A=%02x,0B=%02x,0C=%02x,",
1528 1.1 dyoung sl11read(sc, 0), sl11read(sc, 1),
1529 1.1 dyoung sl11read(sc, 2), sl11read(sc, 3),
1530 1.1 dyoung sl11read(sc, 4), sl11read(sc, 8),
1531 1.1 dyoung sl11read(sc, 9), sl11read(sc, 10),
1532 1.1 dyoung sl11read(sc, 11), sl11read(sc, 12)
1533 1.1 dyoung );
1534 1.1 dyoung printf("CR1=%02x,IER=%02x,0D=%02x,0E=%02x,0F=%02x ",
1535 1.1 dyoung sl11read(sc, 5), sl11read(sc, 6),
1536 1.1 dyoung sl11read(sc, 13), sl11read(sc, 14), sl11read(sc, 15)
1537 1.1 dyoung );
1538 1.1 dyoung #endif
1539 1.1 dyoung }
1540 1.1 dyoung
1541 1.1 dyoung void
1542 1.13 skrll print_xfer(struct usbd_xfer *xfer)
1543 1.1 dyoung {
1544 1.1 dyoung printf("xfer: length=%d, actlen=%d, flags=%x, timeout=%d,",
1545 1.13 skrll xfer->ux_length, xfer->ux_actlen, xfer->ux_flags, xfer->ux_timeout);
1546 1.1 dyoung printf("request{ ");
1547 1.13 skrll print_req_hub(&xfer->ux_request);
1548 1.1 dyoung printf("} ");
1549 1.1 dyoung }
1550 1.1 dyoung #endif /* AHCI_DEBUG */
1551