[BACK]Return to ahci.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / mips / adm5120 / dev

Annotation of src/sys/arch/mips/adm5120/dev/ahci.c, Revision 1.6

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

CVSweb <webmaster@jp.NetBSD.org>