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

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

CVSweb <webmaster@jp.NetBSD.org>