[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.12.6.8

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

CVSweb <webmaster@jp.NetBSD.org>