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