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