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