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