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

1.14.8.1! pgoyette    1: /*     $NetBSD: ahci.c,v 1.15 2018/04/09 16:21:10 jakllsch 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.14.8.1! pgoyette   67: __KERNEL_RCSID(0, "$NetBSD: ahci.c,v 1.15 2018/04/09 16:21:10 jakllsch 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.13      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.13      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.13      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.13      skrll      98: static struct usbd_xfer *
                     99:                        ahci_allocx(struct usbd_bus *, unsigned int);
                    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.13      skrll     103: static int             ahci_roothub_ctrl(struct usbd_bus *, usb_device_request_t *,
                    104:     void *, int);
1.12      skrll     105:
1.13      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.13      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.13      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.13      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,
                    173:        .ubm_rhctrl = ahci_roothub_ctrl,
1.1       dyoung    174: };
                    175:
                    176: struct usbd_pipe_methods ahci_root_intr_methods = {
1.13      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.13      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.13      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.13      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.13      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.13      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.13      skrll     238:                return 1;
1.1       dyoung    239:
1.13      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.13      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.13      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.13      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.13      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.13      skrll     353: ahci_open(struct usbd_pipe *pipe)
1.1       dyoung    354: {
1.13      skrll     355:        struct usbd_device *dev = pipe->up_dev;
1.1       dyoung    356:        struct ahci_pipe *apipe = (struct ahci_pipe *)pipe;
1.13      skrll     357:        usb_endpoint_descriptor_t *ed = pipe->up_endpoint->ue_edesc;
                    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.13      skrll     361:                dev->ud_addr, ed->bEndpointAddress, rhaddr));
1.1       dyoung    362:
                    363:        apipe->toggle=0;
                    364:
1.13      skrll     365:        if (dev->ud_addr == rhaddr) {
1.1       dyoung    366:                switch (ed->bEndpointAddress) {
                    367:                case USB_CONTROL_ENDPOINT:
1.13      skrll     368:                        pipe->up_methods = &roothub_ctrl_methods;
1.1       dyoung    369:                        break;
1.13      skrll     370:                case UE_DIR_IN | USBROOTHUB_INTR_ENDPT:
                    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.13      skrll     381:                        pipe->up_methods = &ahci_device_ctrl_methods;
1.1       dyoung    382:                        break;
                    383:                case UE_INTERRUPT:
                    384:                        DPRINTF(D_MSG, ("interrupt "));
1.13      skrll     385:                        pipe->up_methods = &ahci_device_intr_methods;
1.1       dyoung    386:                        break;
                    387:                case UE_ISOCHRONOUS:
                    388:                        DPRINTF(D_MSG, ("isochronous "));
1.13      skrll     389:                        pipe->up_methods = &ahci_device_isoc_methods;
1.1       dyoung    390:                        break;
                    391:                case UE_BULK:
                    392:                        DPRINTF(D_MSG, ("bluk "));
1.13      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.13      skrll     412: #define AHCI_BUS2SC(bus)       ((bus)->ub_hcpriv)
                    413: #define AHCI_PIPE2SC(pipe)     AHCI_BUS2SC((pipe)->up_dev->ud_bus)
                    414: #define AHCI_XFER2SC(xfer)     AHCI_BUS2SC((xfer)->ux_bus)
                    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.13      skrll     424:        struct usbd_xfer *xfer = arg;
                    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.13      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.13      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.13      skrll     457: struct usbd_xfer *
                    458: ahci_allocx(struct usbd_bus *bus, unsigned int nframes)
1.1       dyoung    459: {
1.13      skrll     460:        struct ahci_softc *sc = AHCI_BUS2SC(bus);
                    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.13      skrll     467:                SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, ux_next);
1.1       dyoung    468: #ifdef DIAGNOSTIC
1.13      skrll     469:                if (xfer->ux_state != XFER_FREE) {
1.1       dyoung    470:                        printf("ahci_allocx: xfer=%p not free, 0x%08x\n",
1.13      skrll     471:                                xfer, xfer->ux_state);
1.1       dyoung    472:                }
                    473: #endif
                    474:        } else {
1.13      skrll     475:                xfer = kmem_alloc(sizeof(*xfer), KM_SLEEP);
1.1       dyoung    476:        }
                    477:
1.14      chs       478:        memset(xfer, 0, sizeof(*xfer));
1.1       dyoung    479: #ifdef DIAGNOSTIC
1.14      chs       480:        xfer->ux_state = XFER_BUSY;
1.1       dyoung    481: #endif
                    482:
                    483:        return xfer;
                    484: }
                    485:
                    486: void
1.13      skrll     487: ahci_freex(struct usbd_bus *bus, struct usbd_xfer *xfer)
1.1       dyoung    488: {
1.13      skrll     489:        struct ahci_softc *sc = AHCI_BUS2SC(bus);
1.1       dyoung    490:
                    491:        DPRINTF(D_MEM, ("SLfreex"));
                    492:
                    493: #ifdef DIAGNOSTIC
1.13      skrll     494:        if (xfer->ux_state != XFER_BUSY) {
1.1       dyoung    495:                printf("ahci_freex: xfer=%p not busy, 0x%08x\n",
1.13      skrll     496:                        xfer, xfer->ux_state);
1.1       dyoung    497:                return;
                    498:        }
1.13      skrll     499:        xfer->ux_state = XFER_FREE;
1.1       dyoung    500: #endif
1.13      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.13      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.13      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.13      skrll     523: ahci_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req,
                    524:     void *buf, int buflen)
1.1       dyoung    525: {
1.13      skrll     526:        struct ahci_softc *sc = AHCI_BUS2SC(bus);
                    527:        uint16_t len, value, index;
                    528:        usb_port_status_t ps;
1.1       dyoung    529:        int totlen = 0;
1.13      skrll     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.13      skrll     541:                switch (value) {
                    542: #define sd ((usb_string_descriptor_t *)buf)
                    543:                case C(2, UDESC_STRING):
                    544:                        /* Product */
                    545:                        totlen = usb_makestrdesc(sd, len, "ADM5120 root hub");
1.1       dyoung    546:                        break;
                    547:                default:
                    548:                        printf("unknownGetDescriptor=%x", value);
1.14.8.1! pgoyette  549:                        /* FALLTHROUGH */
        !           550:                case C(0, UDESC_DEVICE):
        !           551:                case C(1, UDESC_STRING):
1.13      skrll     552:                        /* default from usbroothub */
                    553:                        return buflen;
1.1       dyoung    554:                }
                    555:                break;
                    556:        /*
                    557:         * Hub specific requests
                    558:         */
                    559:        case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
                    560:                /* Clear Hub Feature, 11.16.2.1, not supported */
                    561:                DPRINTF(D_MSG, ("ClearHubFeature not supported\n"));
                    562:                break;
                    563:        case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
                    564:
                    565: #define WPS(x) REG_WRITE(ADMHCD_REG_PORTSTATUS0+(index-1)*4, (x))
                    566:                /* Clear Port Feature, 11.16.2.2 */
                    567:                if (index != 1 && index != 2 ) {
1.13      skrll     568:                        return -1;
1.1       dyoung    569:                }
                    570:                switch (value) {
                    571:                case UHF_PORT_POWER:
                    572:                        DPRINTF(D_MSG, ("POWER_OFF "));
                    573:                        WPS(ADMHCD_LSDA);
                    574:                        break;
                    575:                case UHF_PORT_SUSPEND:
                    576:                        DPRINTF(D_MSG, ("SUSPEND "));
                    577:                        WPS(ADMHCD_POCI);
                    578:                        break;
                    579:                case UHF_PORT_ENABLE:
                    580:                        DPRINTF(D_MSG, ("ENABLE "));
                    581:                        WPS(ADMHCD_CCS);
                    582:                        break;
                    583:                case UHF_C_PORT_CONNECTION:
                    584:                        WPS(ADMHCD_CSC);
                    585:                        break;
                    586:                case UHF_C_PORT_RESET:
                    587:                        WPS(ADMHCD_PRSC);
                    588:                        break;
                    589:                case UHF_C_PORT_SUSPEND:
                    590:                        WPS(ADMHCD_PSSC);
                    591:                        break;
                    592:                case UHF_C_PORT_ENABLE:
                    593:                        WPS(ADMHCD_PESC);
                    594:                        break;
                    595:                case UHF_C_PORT_OVER_CURRENT:
                    596:                        WPS(ADMHCD_OCIC);
                    597:                        break;
                    598:                default:
                    599:                        printf("ClrPortFeatERR:value=0x%x ", value);
1.13      skrll     600:                        return -1;
1.1       dyoung    601:                }
                    602:                //DPRINTF(D_XFER, ("CH=%04x ", sc->sc_change));
                    603: #undef WPS
                    604:                break;
                    605:        case C(UR_GET_BUS_STATE, UT_READ_CLASS_OTHER):
                    606:                /* Get Bus State, 11.16.2.3, not supported */
                    607:                /* shall return a STALL... */
                    608:                break;
                    609:        case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
                    610:                /* Get Hub Descriptor, 11.16.2.4 */
                    611:                DPRINTF(D_MSG, ("UR_GET_DESCRIPTOR RCD"));
                    612:                if ((value&0xff) != 0) {
1.13      skrll     613:                        return -1;
1.1       dyoung    614:                }
1.13      skrll     615:                usb_hub_descriptor_t hubd;
                    616:
                    617:                totlen = min(buflen, sizeof(hubd));
                    618:                memcpy(&hubd, buf, totlen);
                    619:                hubd.bNbrPorts = 2;
                    620:                USETW(hubd.wHubCharacteristics, 0);
                    621:                hubd.bPwrOn2PwrGood = 0;
                    622:                memcpy(buf, &hubd, totlen);
1.1       dyoung    623:                break;
                    624:        case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
                    625:                /* Get Hub Status, 11.16.2.5 */
                    626:                DPRINTF(D_MSG, ("UR_GET_STATUS RCD"));
                    627:                if (len != 4) {
1.13      skrll     628:                        return -1;
1.1       dyoung    629:                }
                    630:                memset(buf, 0, len);
                    631:                totlen = len;
                    632:                break;
                    633:        case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
                    634:                /* Get Port Status, 11.16.2.6 */
                    635:                if ((index != 1 && index != 2)  || len != 4) {
                    636:                        printf("index=%d,len=%d ", index, len);
1.13      skrll     637:                        return -1;
1.1       dyoung    638:                }
                    639:                status = REG_READ(ADMHCD_REG_PORTSTATUS0+(index-1)*4);
                    640:                DPRINTF(D_MSG, ("UR_GET_STATUS RCO=%x ", status));
                    641:
                    642:                //DPRINTF(D_XFER, ("ST=%04x,CH=%04x ", status, sc->sc_change));
                    643:                USETW(ps.wPortStatus, status  & (UPS_CURRENT_CONNECT_STATUS|UPS_PORT_ENABLED|UPS_SUSPEND|UPS_OVERCURRENT_INDICATOR|UPS_RESET|UPS_PORT_POWER|UPS_LOW_SPEED));
                    644:                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.13      skrll     645:                totlen = min(len, sizeof(ps));
                    646:                memcpy(buf, &ps, totlen);
1.1       dyoung    647:                break;
                    648:        case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
                    649:                /* Set Hub Descriptor, 11.16.2.7, not supported */
                    650:                /* STALL ? */
1.13      skrll     651:                return -1;
1.1       dyoung    652:        case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
                    653:                /* Set Hub Feature, 11.16.2.8, not supported */
                    654:                break;
                    655:        case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
                    656: #define WPS(x) REG_WRITE(ADMHCD_REG_PORTSTATUS0+(index-1)*4, (x))
                    657:                /* Set Port Feature, 11.16.2.9 */
                    658:                if ((index != 1) && (index !=2)) {
                    659:                        printf("index=%d ", index);
1.13      skrll     660:                        return -1;
1.1       dyoung    661:                }
                    662:                switch (value) {
                    663:                case UHF_PORT_RESET:
                    664:                        DPRINTF(D_MSG, ("PORT_RESET "));
                    665:                        WPS(ADMHCD_PRS);
                    666:                        break;
                    667:                case UHF_PORT_POWER:
                    668:                        DPRINTF(D_MSG, ("PORT_POWER "));
                    669:                        WPS(ADMHCD_PPS);
                    670:                        break;
                    671:                case UHF_PORT_ENABLE:
                    672:                        DPRINTF(D_MSG, ("PORT_ENABLE "));
                    673:                        WPS(ADMHCD_PES);
                    674:                        break;
                    675:                default:
                    676:                        printf("SetPortFeatERR=0x%x ", value);
1.13      skrll     677:                        return -1;
1.1       dyoung    678:                }
                    679: #undef WPS
                    680:                break;
                    681:        default:
                    682:                DPRINTF(D_MSG, ("ioerr(UR=%02x,UT=%02x) ",
                    683:                        req->bRequest, req->bmRequestType));
1.13      skrll     684:                /* default from usbroothub */
                    685:                return buflen;
1.1       dyoung    686:        }
                    687:
1.13      skrll     688:        return totlen;
1.1       dyoung    689: }
                    690:
                    691: static usbd_status
1.13      skrll     692: ahci_root_intr_transfer(struct usbd_xfer *xfer)
1.1       dyoung    693: {
1.13      skrll     694:        struct ahci_softc *sc = AHCI_XFER2SC(xfer);
1.1       dyoung    695:        usbd_status error;
                    696:
                    697:        DPRINTF(D_TRACE, ("SLRItransfer "));
                    698:
                    699:        /* Insert last in queue */
1.12      skrll     700:        mutex_enter(&sc->sc_lock);
1.1       dyoung    701:        error = usb_insert_transfer(xfer);
1.12      skrll     702:        mutex_exit(&sc->sc_lock);
1.1       dyoung    703:        if (error)
                    704:                return error;
                    705:
                    706:        /*
                    707:         * Pipe isn't running (otherwise error would be USBD_INPROG),
                    708:         * start first.
                    709:         */
1.13      skrll     710:        return ahci_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
1.1       dyoung    711: }
                    712:
                    713: static usbd_status
1.13      skrll     714: ahci_root_intr_start(struct usbd_xfer *xfer)
1.1       dyoung    715: {
1.13      skrll     716:        struct ahci_softc *sc = AHCI_XFER2SC(xfer);
1.1       dyoung    717:
                    718:        DPRINTF(D_TRACE, ("SLRIstart "));
                    719:
1.13      skrll     720:        sc->sc_interval = MS_TO_TICKS(xfer->ux_pipe->up_endpoint->ue_edesc->bInterval);
1.6       dyoung    721:        callout_reset(&sc->sc_poll_handle, sc->sc_interval, ahci_poll_hub, xfer);
1.1       dyoung    722:        sc->sc_intr_xfer = xfer;
                    723:        return USBD_IN_PROGRESS;
                    724: }
                    725:
                    726: static void
1.13      skrll     727: ahci_root_intr_abort(struct usbd_xfer *xfer)
1.1       dyoung    728: {
                    729:        DPRINTF(D_TRACE, ("SLRIabort "));
                    730: }
                    731:
                    732: static void
1.13      skrll     733: ahci_root_intr_close(struct usbd_pipe *pipe)
1.1       dyoung    734: {
1.13      skrll     735:        struct ahci_softc *sc = AHCI_PIPE2SC(pipe);
1.1       dyoung    736:
                    737:        DPRINTF(D_TRACE, ("SLRIclose "));
                    738:
1.6       dyoung    739:        callout_stop(&sc->sc_poll_handle);
1.1       dyoung    740:        sc->sc_intr_xfer = NULL;
                    741: }
                    742:
                    743: static void
1.13      skrll     744: ahci_root_intr_done(struct usbd_xfer *xfer)
1.1       dyoung    745: {
                    746:        //DPRINTF(D_XFER, ("RIdn "));
                    747: }
                    748:
                    749: static usbd_status
1.13      skrll     750: ahci_device_ctrl_transfer(struct usbd_xfer *xfer)
1.1       dyoung    751: {
1.13      skrll     752:        struct ahci_softc *sc = AHCI_XFER2SC(xfer);
1.1       dyoung    753:        usbd_status error;
                    754:
                    755:        DPRINTF(D_TRACE, ("C"));
                    756:
1.12      skrll     757:        mutex_enter(&sc->sc_lock);
1.1       dyoung    758:        error = usb_insert_transfer(xfer);
1.12      skrll     759:        mutex_exit(&sc->sc_lock);
1.1       dyoung    760:        if (error)
                    761:                return error;
                    762:
1.13      skrll     763:        return ahci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
1.1       dyoung    764: }
                    765:
                    766: static usbd_status
1.13      skrll     767: ahci_device_ctrl_start(struct usbd_xfer *xfer)
1.1       dyoung    768: {
                    769:        usbd_status status =  USBD_NORMAL_COMPLETION;
                    770:        int s, err;
                    771:        static struct admhcd_ed ep_v __attribute__((aligned(16))), *ep;
                    772:        static struct admhcd_td td_v[4] __attribute__((aligned(16))), *td, *td1, *td2, *td3;
                    773:        static usb_dma_t reqdma;
1.13      skrll     774:        struct usbd_pipe *pipe = xfer->ux_pipe;
                    775:        usb_device_request_t *req = &xfer->ux_request;
                    776:        struct ahci_softc *sc = AHCI_XFER2SC(xfer);
1.1       dyoung    777:        int len, isread;
1.11      skrll     778:
1.1       dyoung    779:
                    780: #if 0
1.13      skrll     781:        struct ahci_pipe *apipe = (struct ahci_pipe *)xfer->ux_pipe;
1.1       dyoung    782: #endif
1.12      skrll     783:        mutex_enter(&sc->sc_lock);
1.1       dyoung    784: /*     printf("ctrl_start>>>\n"); */
                    785:
                    786: #ifdef DIAGNOSTIC
1.13      skrll     787:        if (!(xfer->ux_rqflags & URQ_REQUEST)) {
                    788:                /* XXX panic */
                    789:                printf("ahci_device_ctrl_transfer: not a request\n");
                    790:                return USBD_INVAL;
                    791:        }
1.1       dyoung    792: #endif
                    793:
1.13      skrll     794: #define KSEG1ADDR(x) (0xa0000000 | (((uint32_t)x) & 0x1fffffff))
1.1       dyoung    795:        DPRINTF(D_TRACE, ("st "));
                    796:        if (!ep) {
1.13      skrll     797:                ep = (struct admhcd_ed *)KSEG1ADDR(&ep_v);
1.11      skrll     798:                td = (struct admhcd_td *)KSEG1ADDR(&td_v[0]);
                    799:                td1 = (struct admhcd_td *)KSEG1ADDR(&td_v[1]);
                    800:                td2 = (struct admhcd_td *)KSEG1ADDR(&td_v[2]);
                    801:                td3 = (struct admhcd_td *)KSEG1ADDR(&td_v[3]);
1.1       dyoung    802:                err = usb_allocmem(&sc->sc_bus,
                    803:                        sizeof(usb_device_request_t),
                    804:                        0, &reqdma);
                    805:                if (err)
1.13      skrll     806:                        return USBD_NOMEM;
1.1       dyoung    807:
                    808:                /* printf("ep: %p\n",ep); */
                    809:        };
                    810:
1.13      skrll     811:        ep->control =  pipe->up_dev->ud_addr | \
                    812:                ((pipe->up_dev->ud_speed==USB_SPEED_FULL)?ADMHCD_ED_SPEED:0) | \
                    813:                ((UGETW(pipe->up_endpoint->ue_edesc->wMaxPacketSize))<<ADMHCD_ED_MAXSHIFT);
1.1       dyoung    814:        memcpy(KERNADDR(&reqdma, 0), req, sizeof *req);
                    815: /*     printf("status: %x\n",REG_READ(ADMHCD_REG_PORTSTATUS0));
                    816:        printf("ep_control: %x\n",ep->control);
1.13      skrll     817:        printf("speed: %x\n",pipe->up_dev->ud_speed);
1.1       dyoung    818:        printf("req: %p\n",req);
1.13      skrll     819:        printf("dmabuf: %p\n",xfer->ux_dmabuf.block); */
1.1       dyoung    820:
                    821:        isread = req->bmRequestType & UT_READ;
                    822:        len = UGETW(req->wLength);
                    823:
1.13      skrll     824:        ep->next = ep;
1.1       dyoung    825:
1.13      skrll     826:        td->buffer = DMAADDR(&reqdma,0) | 0xa0000000;
                    827:        td->buflen=sizeof(*req);
                    828:        td->control=ADMHCD_TD_SETUP | ADMHCD_TD_DATA0 | ADMHCD_TD_OWN;
1.1       dyoung    829:
                    830:        if (len) {
                    831:                td->next = td1;
                    832:
1.13      skrll     833:                td1->buffer = DMAADDR(&xfer->ux_dmabuf,0) | 0xa0000000;
1.1       dyoung    834:                td1->buflen = len;
                    835:                td1->next = td2;
                    836:                td1->control= (isread?ADMHCD_TD_IN:ADMHCD_TD_OUT) | ADMHCD_TD_DATA1 | ADMHCD_TD_R | ADMHCD_TD_OWN;
1.13      skrll     837:        } else {
                    838:                td1->control = 0;
                    839:                td->next = td2;
                    840:        };
1.1       dyoung    841:
                    842:        td2->buffer = 0;
                    843:        td2->buflen= 0;
                    844:        td2->next = td3;
                    845:        td2->control = (isread?ADMHCD_TD_OUT:ADMHCD_TD_IN) | ADMHCD_TD_DATA1 | ADMHCD_TD_OWN;
                    846:
                    847:        td3->buffer = 0;
                    848:        td3->buflen= 0;
                    849:        td3->next = 0;
                    850:        td3->control = 0;
                    851:
                    852:        ep->head = td;
                    853:        ep->tail = td3;
                    854: /*
                    855:        printf("ep: %p\n",ep);
                    856:        printf("ep->next: %p\n",ep->next);
                    857:        printf("ep->head: %p\n",ep->head);
                    858:        printf("ep->tail: %p\n",ep->tail);
                    859:        printf("td: %p\n",td);
                    860:        printf("td->next: %p\n",td->next);
                    861:        printf("td->buffer: %x\n",td->buffer);
                    862:        printf("td->buflen: %x\n",td->buflen);
                    863:        printf("td1: %p\n",td1);
                    864:        printf("td1->next: %p\n",td1->next);
                    865:        printf("td2: %p\n",td2);
                    866:        printf("td2->next: %p\n",td2->next);
                    867:        printf("td3: %p\n",td3);
                    868:        printf("td3->next: %p\n",td3->next);
                    869: */
                    870:
1.13      skrll     871:        REG_WRITE(ADMHCD_REG_HOSTHEAD, (uint32_t)ep);
                    872:        REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP | ADMHCD_DMA_EN);
1.1       dyoung    873: /*     printf("1: %x %x %x %x\n", ep->control, td->control, td1->control, td2->control); */
1.13      skrll     874:        s=100;
                    875:        while (s--) {
                    876:                delay_ms(10);
1.1       dyoung    877: /*                printf("%x %x %x %x\n", ep->control, td->control, td1->control, td2->control);*/
                    878:                status = USBD_TIMEOUT;
1.13      skrll     879:                if (td->control & ADMHCD_TD_OWN) continue;
1.1       dyoung    880:
1.13      skrll     881:                err = (td->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT;
                    882:                if (err) {
1.1       dyoung    883:                        status = USBD_IOERROR;
1.13      skrll     884:                        break;
                    885:                };
1.1       dyoung    886:
                    887:                status = USBD_TIMEOUT;
1.13      skrll     888:                if (td1->control & ADMHCD_TD_OWN) continue;
                    889:                err = (td1->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT;
                    890:                if (err) {
1.1       dyoung    891:                        status = USBD_IOERROR;
1.13      skrll     892:                        break;
                    893:                };
1.1       dyoung    894:
                    895:                status = USBD_TIMEOUT;
1.13      skrll     896:                if (td2->control & ADMHCD_TD_OWN) continue;
                    897:                err = (td2->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT;
                    898:                if (err) {
1.1       dyoung    899:                        status = USBD_IOERROR;
1.13      skrll     900:                };
1.1       dyoung    901:                status = USBD_NORMAL_COMPLETION;
1.13      skrll     902:                break;
1.1       dyoung    903:
                    904:        };
1.13      skrll     905:        REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP);
1.1       dyoung    906:
1.13      skrll     907:        xfer->ux_actlen = len;
                    908:        xfer->ux_status = status;
1.1       dyoung    909:
                    910: /*     printf("ctrl_start<<<\n"); */
                    911:
                    912:        usb_transfer_complete(xfer);
1.12      skrll     913:        mutex_exit(&sc->sc_lock);
                    914:        return USBD_NORMAL_COMPLETION;
1.1       dyoung    915: }
                    916:
                    917: static void
1.13      skrll     918: ahci_device_ctrl_abort(struct usbd_xfer *xfer)
1.1       dyoung    919: {
                    920:        DPRINTF(D_TRACE, ("Cab "));
                    921:        ahci_abort_xfer(xfer, USBD_CANCELLED);
                    922: }
                    923:
                    924: static void
1.13      skrll     925: ahci_device_ctrl_close(struct usbd_pipe *pipe)
1.1       dyoung    926: {
                    927:        DPRINTF(D_TRACE, ("Ccl "));
                    928: }
                    929:
                    930: static void
1.13      skrll     931: ahci_device_ctrl_done(struct usbd_xfer *xfer)
1.1       dyoung    932: {
                    933:        DPRINTF(D_TRACE, ("Cdn "));
                    934: }
                    935:
                    936: static usbd_status
1.13      skrll     937: ahci_device_intr_transfer(struct usbd_xfer *xfer)
1.1       dyoung    938: {
1.13      skrll     939:        struct ahci_softc *sc = AHCI_XFER2SC(xfer);
1.1       dyoung    940:        usbd_status error;
                    941:
                    942:        DPRINTF(D_TRACE, ("INTRtrans "));
                    943:
1.12      skrll     944:        mutex_enter(&sc->sc_lock);
1.1       dyoung    945:        error = usb_insert_transfer(xfer);
1.12      skrll     946:        mutex_exit(&sc->sc_lock);
1.1       dyoung    947:        if (error)
                    948:                return error;
                    949:
1.13      skrll     950:        return ahci_device_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
1.1       dyoung    951: }
                    952:
                    953: static usbd_status
1.13      skrll     954: ahci_device_intr_start(struct usbd_xfer *xfer)
1.1       dyoung    955: {
1.13      skrll     956:        struct usbd_pipe *pipe = xfer->ux_pipe;
1.1       dyoung    957:        struct ahci_xfer *sx;
                    958:
                    959:        DPRINTF(D_TRACE, ("INTRstart "));
                    960:
1.13      skrll     961:        sx = kmem_intr_alloc(sizeof(*sx), KM_NOSLEEP);
1.1       dyoung    962:        if (sx == NULL)
                    963:                goto reterr;
                    964:        memset(sx, 0, sizeof(*sx));
1.13      skrll     965:        sx->sx_xfer = xfer;
                    966:        xfer->ux_hcpriv = sx;
1.1       dyoung    967:
                    968:        /* initialize callout */
1.6       dyoung    969:        callout_init(&sx->sx_callout_t, 0);
1.11      skrll     970:        callout_reset(&sx->sx_callout_t,
1.13      skrll     971:                MS_TO_TICKS(pipe->up_endpoint->ue_edesc->bInterval),
1.1       dyoung    972:                ahci_poll_device, sx);
                    973:
                    974:        /* ACK */
                    975:        return USBD_IN_PROGRESS;
                    976:
                    977:  reterr:
                    978:        return USBD_IOERROR;
                    979: }
                    980:
                    981: static void
                    982: ahci_poll_device(void *arg)
                    983: {
                    984:        struct ahci_xfer *sx = (struct ahci_xfer *)arg;
1.13      skrll     985:        struct usbd_xfer *xfer = sx->sx_xfer;
                    986:        struct usbd_pipe *pipe = xfer->ux_pipe;
                    987:        struct ahci_softc *sc = AHCI_XFER2SC(xfer);
1.1       dyoung    988:        void *buf;
                    989:        int pid;
                    990:        int r;
                    991:
                    992:        DPRINTF(D_TRACE, ("pldev"));
                    993:
1.6       dyoung    994:        callout_reset(&sx->sx_callout_t,
1.13      skrll     995:                MS_TO_TICKS(pipe->up_endpoint->ue_edesc->bInterval),
1.1       dyoung    996:                ahci_poll_device, sx);
                    997:
                    998:        /* interrupt transfer */
1.13      skrll     999:        pid = (UE_GET_DIR(pipe->up_endpoint->ue_edesc->bEndpointAddress) == UE_DIR_IN)
1.1       dyoung   1000:            ? ADMHCD_TD_IN : ADMHCD_TD_OUT;
1.13      skrll    1001:        buf = KERNADDR(&xfer->ux_dmabuf, 0);
1.1       dyoung   1002:
1.13      skrll    1003:        r = ahci_transaction(sc, pipe, pid, xfer->ux_length, buf, 0/*toggle*/);
1.1       dyoung   1004:        if (r < 0) {
1.2       perry    1005:                DPRINTF(D_MSG, ("%s error", __func__));
1.1       dyoung   1006:                return;
                   1007:        }
                   1008:        /* no change, return NAK */
                   1009:        if (r == 0)
                   1010:                return;
                   1011:
1.13      skrll    1012:        xfer->ux_status = USBD_NORMAL_COMPLETION;
1.12      skrll    1013:        mutex_enter(&sc->sc_lock);
1.1       dyoung   1014:        usb_transfer_complete(xfer);
1.12      skrll    1015:        mutex_exit(&sc->sc_lock);
1.1       dyoung   1016: }
                   1017:
                   1018: static void
1.13      skrll    1019: ahci_device_intr_abort(struct usbd_xfer *xfer)
1.1       dyoung   1020: {
                   1021:        struct ahci_xfer *sx;
                   1022:
                   1023:        DPRINTF(D_TRACE, ("INTRabort "));
                   1024:
1.13      skrll    1025:        sx = xfer->ux_hcpriv;
1.1       dyoung   1026:        if (sx) {
1.6       dyoung   1027:                callout_stop(&sx->sx_callout_t);
1.13      skrll    1028:                kmem_intr_free(sx, sizeof(*sx));
                   1029:                xfer->ux_hcpriv = NULL;
1.1       dyoung   1030:        } else {
1.2       perry    1031:                printf("%s: sx == NULL!\n", __func__);
1.1       dyoung   1032:        }
                   1033:        ahci_abort_xfer(xfer, USBD_CANCELLED);
                   1034: }
                   1035:
                   1036: static void
1.13      skrll    1037: ahci_device_intr_close(struct usbd_pipe *pipe)
1.1       dyoung   1038: {
                   1039:        DPRINTF(D_TRACE, ("INTRclose "));
                   1040: }
                   1041:
                   1042: static void
1.13      skrll    1043: ahci_device_intr_done(struct usbd_xfer *xfer)
1.1       dyoung   1044: {
                   1045:        DPRINTF(D_TRACE, ("INTRdone "));
                   1046: }
                   1047:
                   1048: static usbd_status
1.13      skrll    1049: ahci_device_isoc_transfer(struct usbd_xfer *xfer)
1.1       dyoung   1050: {
                   1051:        DPRINTF(D_TRACE, ("S"));
                   1052:        return USBD_NORMAL_COMPLETION;
                   1053: }
                   1054:
                   1055: static usbd_status
1.13      skrll    1056: ahci_device_isoc_start(struct usbd_xfer *xfer)
1.1       dyoung   1057: {
                   1058:        DPRINTF(D_TRACE, ("st "));
                   1059:        return USBD_NORMAL_COMPLETION;
                   1060: }
                   1061:
                   1062: static void
1.13      skrll    1063: ahci_device_isoc_abort(struct usbd_xfer *xfer)
1.1       dyoung   1064: {
                   1065:        DPRINTF(D_TRACE, ("Sab "));
                   1066: }
                   1067:
                   1068: static void
1.13      skrll    1069: ahci_device_isoc_close(struct usbd_pipe *pipe)
1.1       dyoung   1070: {
                   1071:        DPRINTF(D_TRACE, ("Scl "));
                   1072: }
                   1073:
                   1074: static void
1.13      skrll    1075: ahci_device_isoc_done(struct usbd_xfer *xfer)
1.1       dyoung   1076: {
                   1077:        DPRINTF(D_TRACE, ("Sdn "));
                   1078: }
                   1079:
                   1080: static usbd_status
1.13      skrll    1081: ahci_device_bulk_transfer(struct usbd_xfer *xfer)
1.1       dyoung   1082: {
1.13      skrll    1083:        struct ahci_softc *sc = AHCI_XFER2SC(xfer);
1.1       dyoung   1084:        usbd_status error;
                   1085:
                   1086:        DPRINTF(D_TRACE, ("B"));
                   1087:
1.12      skrll    1088:        mutex_enter(&sc->sc_lock);
1.1       dyoung   1089:        error = usb_insert_transfer(xfer);
1.12      skrll    1090:        mutex_exit(&sc->sc_lock);
1.1       dyoung   1091:        if (error)
                   1092:                return error;
                   1093:
1.13      skrll    1094:        return ahci_device_bulk_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
1.1       dyoung   1095: }
                   1096:
                   1097: static usbd_status
1.13      skrll    1098: ahci_device_bulk_start(struct usbd_xfer *xfer)
1.1       dyoung   1099: {
                   1100: #define NBULK_TDS 32
                   1101:        static volatile int level = 0;
                   1102:        usbd_status status =  USBD_NORMAL_COMPLETION;
                   1103:        int s, err;
                   1104:        static struct admhcd_ed ep_v __attribute__((aligned(16))), *ep;
                   1105:        static struct admhcd_td td_v[NBULK_TDS] __attribute__((aligned(16))), *td[NBULK_TDS];
1.13      skrll    1106:        struct usbd_pipe *pipe = xfer->ux_pipe;
                   1107:        struct ahci_softc *sc = AHCI_XFER2SC(xfer);
1.1       dyoung   1108:        int endpt, i, len, tlen, segs, offset, isread, toggle, short_ok;
1.13      skrll    1109:        struct ahci_pipe *apipe = (struct ahci_pipe *)xfer->ux_pipe;
1.1       dyoung   1110:
1.13      skrll    1111: #define KSEG1ADDR(x) (0xa0000000 | (((uint32_t)x) & 0x1fffffff))
1.1       dyoung   1112:        DPRINTF(D_TRACE, ("st "));
                   1113:
                   1114: #ifdef DIAGNOSTIC
1.13      skrll    1115:        if (xfer->ux_rqflags & URQ_REQUEST) {
1.1       dyoung   1116:                /* XXX panic */
                   1117:                printf("ohci_device_bulk_start: a request\n");
1.13      skrll    1118:                return USBD_INVAL;
1.1       dyoung   1119:        }
                   1120: #endif
                   1121:
1.12      skrll    1122:        mutex_enter(&sc->sc_lock);
1.1       dyoung   1123:        level++;
                   1124: /*     printf("bulk_start>>>\n"); */
                   1125:
                   1126:        if (!ep) {
1.13      skrll    1127:                ep = (struct admhcd_ed *)KSEG1ADDR(&ep_v);
1.1       dyoung   1128:                for (i=0; i<NBULK_TDS; i++) {
1.11      skrll    1129:                        td[i] = (struct admhcd_td *)KSEG1ADDR(&td_v[i]);
1.1       dyoung   1130:                };
                   1131: /*             printf("ep: %p\n",ep);*/
                   1132:        };
                   1133:        if (apipe->toggle == 0) {
                   1134:                toggle = ADMHCD_TD_DATA0;
                   1135:        } else {
                   1136:                toggle = apipe->toggle;
                   1137:        };
                   1138:
1.13      skrll    1139:        endpt = pipe->up_endpoint->ue_edesc->bEndpointAddress;
                   1140:        ep->control = pipe->up_dev->ud_addr | ((endpt & 0xf) << ADMHCD_ED_EPSHIFT)|\
                   1141:                ((pipe->up_dev->ud_speed==USB_SPEED_FULL)?ADMHCD_ED_SPEED:0) | \
                   1142:                ((UGETW(pipe->up_endpoint->ue_edesc->wMaxPacketSize))<<ADMHCD_ED_MAXSHIFT);
1.1       dyoung   1143:
1.13      skrll    1144:        short_ok = xfer->ux_flags & USBD_SHORT_XFER_OK?ADMHCD_TD_R:0;
1.1       dyoung   1145: /*     printf("level: %d\n",level);
                   1146:        printf("short_xfer: %x\n",short_ok);
                   1147:        printf("ep_control: %x\n",ep->control);
1.13      skrll    1148:        printf("speed: %x\n",pipe->up_dev->ud_speed);
                   1149:        printf("dmabuf: %p\n",xfer->ux_dmabuf.block); */
1.1       dyoung   1150:
1.13      skrll    1151:        isread = UE_GET_DIR(endpt) == UE_DIR_IN;
                   1152:        len = xfer->ux_length;
1.1       dyoung   1153:
1.13      skrll    1154:        ep->next = ep;
1.1       dyoung   1155:
                   1156:        i = 0;
                   1157:        offset = 0;
                   1158:        while ((len>0) || (i==0)) {
                   1159:                tlen = min(len,4096);
1.13      skrll    1160:                td[i]->buffer = DMAADDR(&xfer->ux_dmabuf,offset) | 0xa0000000;
1.1       dyoung   1161:                td[i]->buflen=tlen;
                   1162:                td[i]->control=(isread?ADMHCD_TD_IN:ADMHCD_TD_OUT) | toggle | ADMHCD_TD_OWN | short_ok;
                   1163:                td[i]->len=tlen;
                   1164:                toggle = ADMHCD_TD_TOGGLE;
                   1165:                len -= tlen;
                   1166:                offset += tlen;
                   1167:                td[i]->next = td[i+1];
                   1168:                i++;
                   1169:        };
                   1170:
                   1171:        td[i]->buffer = 0;
                   1172:        td[i]->buflen = 0;
                   1173:        td[i]->control = 0;
                   1174:        td[i]->next = 0;
                   1175:
                   1176:        ep->head = td[0];
                   1177:        ep->tail = td[i];
                   1178:        segs = i;
                   1179:        len = 0;
                   1180:
                   1181: /*     printf("segs: %d\n",segs);
                   1182:        printf("ep: %p\n",ep);
                   1183:        printf("ep->control: %x\n",ep->control);
                   1184:        printf("ep->next: %p\n",ep->next);
                   1185:        printf("ep->head: %p\n",ep->head);
                   1186:        printf("ep->tail: %p\n",ep->tail);
                   1187:        for (i=0; i<segs; i++) {
                   1188:                printf("td[%d]: %p\n",i,td[i]);
                   1189:                printf("td[%d]->control: %x\n",i,td[i]->control);
                   1190:                printf("td[%d]->next: %p\n",i,td[i]->next);
                   1191:                printf("td[%d]->buffer: %x\n",i,td[i]->buffer);
                   1192:                printf("td[%d]->buflen: %x\n",i,td[i]->buflen);
                   1193:        }; */
                   1194:
1.13      skrll    1195:        REG_WRITE(ADMHCD_REG_HOSTHEAD, (uint32_t)ep);
                   1196:        REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP | ADMHCD_DMA_EN);
1.1       dyoung   1197:        i = 0;
                   1198: /*     printf("1: %x %d %x %x\n", ep->control, i, td[i]->control, td[i]->buflen); */
1.13      skrll    1199:        s=100;
1.1       dyoung   1200:        err = 0;
1.13      skrll    1201:        while (s--) {
1.1       dyoung   1202: /*                printf("%x %d %x %x\n", ep->control, i, td[i]->control, td[i]->buflen); */
                   1203:                status = USBD_TIMEOUT;
1.13      skrll    1204:                if (td[i]->control & ADMHCD_TD_OWN) {
1.1       dyoung   1205:                        delay_ms(3);
                   1206:                        continue;
                   1207:                };
                   1208:
                   1209:                len += td[i]->len - td[i]->buflen;
                   1210:
1.13      skrll    1211:                err = (td[i]->control & ADMHCD_TD_ERRMASK)>>ADMHCD_TD_ERRSHIFT;
                   1212:                if (err) {
1.1       dyoung   1213:                        status = USBD_IOERROR;
1.13      skrll    1214:                        break;
                   1215:                };
1.11      skrll    1216:
1.1       dyoung   1217:                i++;
                   1218:                if (i==segs) {
                   1219:                        status = USBD_NORMAL_COMPLETION;
                   1220:                        break;
                   1221:                };
                   1222:
                   1223:        };
1.13      skrll    1224:        REG_WRITE(ADMHCD_REG_HOSTCONTROL, ADMHCD_STATE_OP);
1.1       dyoung   1225:
1.13      skrll    1226:        apipe->toggle = ((uint32_t)ep->head & 2)?ADMHCD_TD_DATA1:ADMHCD_TD_DATA0;
1.1       dyoung   1227: /*     printf("bulk_transfer_done: status: %x, err: %x, len: %x, toggle: %x\n", status,err,len,apipe->toggle); */
                   1228:
                   1229:        if (short_ok && (err == 0x9 || err == 0xd)) {
                   1230: /*             printf("bulk_transfer_done: short_transfer fix\n"); */
                   1231:                status = USBD_NORMAL_COMPLETION;
                   1232:        };
1.13      skrll    1233:        xfer->ux_actlen = len;
                   1234:        xfer->ux_status = status;
1.1       dyoung   1235:
                   1236:        level--;
                   1237: /*     printf("bulk_start<<<\n"); */
                   1238:
                   1239:        usb_transfer_complete(xfer);
1.12      skrll    1240:        mutex_exit(&sc->sc_lock);
                   1241:
                   1242:        return USBD_NORMAL_COMPLETION;
1.1       dyoung   1243: }
                   1244:
                   1245: static void
1.13      skrll    1246: ahci_device_bulk_abort(struct usbd_xfer *xfer)
1.1       dyoung   1247: {
                   1248:        DPRINTF(D_TRACE, ("Bab "));
                   1249:        ahci_abort_xfer(xfer, USBD_CANCELLED);
                   1250: }
                   1251:
                   1252: static void
1.13      skrll    1253: ahci_device_bulk_close(struct usbd_pipe *pipe)
1.1       dyoung   1254: {
                   1255:        DPRINTF(D_TRACE, ("Bcl "));
                   1256: }
                   1257:
                   1258: static void
1.13      skrll    1259: ahci_device_bulk_done(struct usbd_xfer *xfer)
1.1       dyoung   1260: {
                   1261:        DPRINTF(D_TRACE, ("Bdn "));
                   1262: }
                   1263:
                   1264: #define DATA0_RD       (0x03)
                   1265: #define DATA0_WR       (0x07)
                   1266: #define AHCI_TIMEOUT   (5000)
                   1267:
                   1268: /*
                   1269:  * Do a transaction.
                   1270:  * return 1 if ACK, 0 if NAK, -1 if error.
                   1271:  */
                   1272: static int
1.13      skrll    1273: ahci_transaction(struct ahci_softc *sc, struct usbd_pipe *pipe,
                   1274:        uint8_t pid, int len, u_char *buf, uint8_t toggle)
1.1       dyoung   1275: {
                   1276:        return -1;
                   1277: #if 0
                   1278: #ifdef AHCI_DEBUG
                   1279:        char str[64];
                   1280:        int i;
                   1281: #endif
                   1282:        int timeout;
                   1283:        int ls_via_hub = 0;
                   1284:        int pl;
1.13      skrll    1285:        uint8_t isr;
                   1286:        uint8_t result = 0;
                   1287:        uint8_t devaddr = pipe->up_dev->ud_addr;
                   1288:        uint8_t endpointaddr = pipe->up_endpoint->ue_edesc->bEndpointAddress;
                   1289:        uint8_t endpoint;
                   1290:        uint8_t cmd = DATA0_RD;
1.1       dyoung   1291:
                   1292:        endpoint = UE_GET_ADDR(endpointaddr);
                   1293:        DPRINTF(D_XFER, ("\n(%x,%d%s%d,%d) ",
                   1294:                pid, len, (pid == SL11_PID_IN) ? "<-" : "->", devaddr, endpoint));
                   1295:
                   1296:        /* Set registers */
                   1297:        sl11write(sc, SL11_E0ADDR, 0x40);
                   1298:        sl11write(sc, SL11_E0LEN,  len);
                   1299:        sl11write(sc, SL11_E0PID,  (pid << 4) + endpoint);
                   1300:        sl11write(sc, SL11_E0DEV,  devaddr);
                   1301:
                   1302:        /* Set buffer unless PID_IN */
                   1303:        if (pid != SL11_PID_IN) {
                   1304:                if (len > 0)
                   1305:                        sl11write_region(sc, 0x40, buf, len);
                   1306:                cmd = DATA0_WR;
                   1307:        }
                   1308:
                   1309:        /* timing ? */
                   1310:        pl = (len >> 3) + 3;
                   1311:
                   1312:        /* Low speed device via HUB */
                   1313:        /* XXX does not work... */
1.13      skrll    1314:        if ((sc->sc_fullspeed) && pipe->up_dev->ud_speed == USB_SPEED_LOW) {
1.1       dyoung   1315:                pl = len + 16;
                   1316:                cmd |= SL11_EPCTRL_PREAMBLE;
                   1317:
                   1318:                /*
                   1319:                 * SL811HS/T rev 1.2 has a bug, when it got PID_IN
                   1320:                 * from LowSpeed device via HUB.
                   1321:                 */
                   1322:                if (sc->sc_sltype == SLTYPE_SL811HS_R12 && pid == SL11_PID_IN) {
                   1323:                        ls_via_hub = 1;
                   1324:                        DPRINTF(D_MSG, ("LSvH "));
                   1325:                }
                   1326:        }
                   1327:
                   1328:        /* timing ? */
1.13      skrll    1329:        if (sl11read(sc, SL811_CSOF) <= (uint8_t)pl)
1.1       dyoung   1330:                cmd |= SL11_EPCTRL_SOF;
                   1331:
                   1332:        /* Transfer */
                   1333:        sl11write(sc, SL11_ISR, 0xff);
                   1334:        sl11write(sc, SL11_E0CTRL, cmd | toggle);
                   1335:
                   1336:        /* Polling */
                   1337:        for (timeout = AHCI_TIMEOUT; timeout; timeout--) {
                   1338:                isr = sl11read(sc, SL11_ISR);
                   1339:                if ((isr & SL11_ISR_USBA))
                   1340:                        break;
                   1341:        }
                   1342:
                   1343:        /* Check result status */
                   1344:        result = sl11read(sc, SL11_E0STAT);
                   1345:        if (!(result & SL11_EPSTAT_NAK) && ls_via_hub) {
                   1346:                /* Resend PID_IN within 20usec */
                   1347:                sl11write(sc, SL11_ISR, 0xff);
                   1348:                sl11write(sc, SL11_E0CTRL, SL11_EPCTRL_ARM);
                   1349:        }
                   1350:
                   1351:        sl11write(sc, SL11_ISR, 0xff);
                   1352:
                   1353:        DPRINTF(D_XFER, ("t=%d i=%x ", AHCI_TIMEOUT - timeout, isr));
                   1354: #if AHCI_DEBUG
1.5       christos 1355:        snprintb(str, sizeof(str),
                   1356:            "\20\x8STALL\7NAK\6OV\5SETUP\4DATA1\3TIMEOUT\2ERR\1ACK", result);
1.1       dyoung   1357:        DPRINTF(D_XFER, ("STAT=%s ", str));
                   1358: #endif
                   1359:
                   1360:        if ((result & SL11_EPSTAT_ERROR))
                   1361:                return -1;
                   1362:
                   1363:        if ((result & SL11_EPSTAT_NAK))
                   1364:                return 0;
                   1365:
                   1366:        /* Read buffer if PID_IN */
                   1367:        if (pid == SL11_PID_IN && len > 0) {
                   1368:                sl11read_region(sc, buf, 0x40, len);
                   1369: #if AHCI_DEBUG
                   1370:                for (i = 0; i < len; i++)
                   1371:                        DPRINTF(D_XFER, ("%02X ", buf[i]));
                   1372: #endif
                   1373:        }
                   1374:
                   1375:        return 1;
                   1376: #endif
                   1377: }
                   1378:
                   1379: void
1.13      skrll    1380: ahci_abort_xfer(struct usbd_xfer *xfer, usbd_status status)
1.1       dyoung   1381: {
1.13      skrll    1382:        xfer->ux_status = status;
1.1       dyoung   1383:        usb_transfer_complete(xfer);
                   1384: }
                   1385:
                   1386: void
1.13      skrll    1387: ahci_device_clear_toggle(struct usbd_pipe *pipe)
1.1       dyoung   1388: {
1.13      skrll    1389:        struct ahci_pipe *apipe = (struct ahci_pipe *)pipe;
1.1       dyoung   1390:        apipe->toggle = 0;
                   1391: }
                   1392:
                   1393: #ifdef AHCI_DEBUG
                   1394: void
                   1395: print_req(usb_device_request_t *r)
                   1396: {
                   1397:        const char *xmes[]={
                   1398:                "GETSTAT",
                   1399:                "CLRFEAT",
                   1400:                "res",
                   1401:                "SETFEAT",
                   1402:                "res",
                   1403:                "SETADDR",
                   1404:                "GETDESC",
                   1405:                "SETDESC",
                   1406:                "GETCONF",
                   1407:                "SETCONF",
                   1408:                "GETIN/F",
                   1409:                "SETIN/F",
                   1410:                "SYNC_FR"
                   1411:        };
                   1412:        int req, type, value, index, len;
                   1413:
                   1414:        req   = r->bRequest;
                   1415:        type  = r->bmRequestType;
                   1416:        value = UGETW(r->wValue);
                   1417:        index = UGETW(r->wIndex);
                   1418:        len   = UGETW(r->wLength);
                   1419:
                   1420:        printf("%x,%s,v=%d,i=%d,l=%d ",
                   1421:                type, xmes[req], value, index, len);
                   1422: }
                   1423:
                   1424: void
                   1425: print_req_hub(usb_device_request_t *r)
                   1426: {
                   1427:        struct {
                   1428:                int req;
                   1429:                int type;
                   1430:                const char *str;
                   1431:        } conf[] = {
                   1432:                { 1, 0x20, "ClrHubFeat"  },
                   1433:                { 1, 0x23, "ClrPortFeat" },
                   1434:                { 2, 0xa3, "GetBusState" },
                   1435:                { 6, 0xa0, "GetHubDesc"  },
                   1436:                { 0, 0xa0, "GetHubStat"  },
                   1437:                { 0, 0xa3, "GetPortStat" },
                   1438:                { 7, 0x20, "SetHubDesc"  },
                   1439:                { 3, 0x20, "SetHubFeat"  },
                   1440:                { 3, 0x23, "SetPortFeat" },
                   1441:                {-1, 0, NULL},
                   1442:        };
                   1443:        int i;
                   1444:        int value, index, len;
                   1445:
                   1446:        value = UGETW(r->wValue);
                   1447:        index = UGETW(r->wIndex);
                   1448:        len   = UGETW(r->wLength);
                   1449:        for (i = 0; ; i++) {
                   1450:                if (conf[i].req == -1 )
                   1451:                        return print_req(r);
                   1452:                if (r->bmRequestType == conf[i].type && r->bRequest == conf[i].req) {
                   1453:                        printf("%s", conf[i].str);
                   1454:                        break;
                   1455:                }
                   1456:        }
                   1457:        printf(",v=%d,i=%d,l=%d ", value, index, len);
                   1458: }
                   1459:
                   1460: void
                   1461: print_dumpreg(struct ahci_softc *sc)
                   1462: {
                   1463: #if 0
                   1464:        printf("00=%02x,01=%02x,02=%02x,03=%02x,04=%02x,"
                   1465:               "08=%02x,09=%02x,0A=%02x,0B=%02x,0C=%02x,",
                   1466:                sl11read(sc, 0),  sl11read(sc, 1),
                   1467:                sl11read(sc, 2),  sl11read(sc, 3),
                   1468:                sl11read(sc, 4),  sl11read(sc, 8),
                   1469:                sl11read(sc, 9),  sl11read(sc, 10),
                   1470:                sl11read(sc, 11), sl11read(sc, 12)
                   1471:        );
                   1472:        printf("CR1=%02x,IER=%02x,0D=%02x,0E=%02x,0F=%02x ",
                   1473:                sl11read(sc, 5), sl11read(sc, 6),
                   1474:                sl11read(sc, 13), sl11read(sc, 14), sl11read(sc, 15)
                   1475:        );
                   1476: #endif
                   1477: }
                   1478:
                   1479: void
1.13      skrll    1480: print_xfer(struct usbd_xfer *xfer)
1.1       dyoung   1481: {
                   1482:        printf("xfer: length=%d, actlen=%d, flags=%x, timeout=%d,",
1.13      skrll    1483:                xfer->ux_length, xfer->ux_actlen, xfer->ux_flags, xfer->ux_timeout);
1.1       dyoung   1484:        printf("request{ ");
1.13      skrll    1485:        print_req_hub(&xfer->ux_request);
1.1       dyoung   1486:        printf("} ");
                   1487: }
                   1488: #endif /* AHCI_DEBUG */

CVSweb <webmaster@jp.NetBSD.org>