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