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