root/usr/src/uts/common/sys/usb/hcd/ehci/ehcid.h
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
 */

#ifndef _SYS_USB_EHCID_H
#define _SYS_USB_EHCID_H


#ifdef  __cplusplus
extern "C" {
#endif

/*
 * Enchanced Host Controller Driver (EHCI)
 *
 * The EHCI driver is a software driver which interfaces to the Universal
 * Serial Bus layer (USBA) and the Host Controller (HC). The interface to
 * the Host Controller is defined by the EHCI Host Controller Interface.
 *
 * This header file describes the data structures and function prototypes
 * required for the EHCI Driver to maintain state of Host Controller (HC),
 * to perform different USB transfers and for the bandwidth allocations.
 */

#include <sys/usb/hcd/ehci/ehci.h>
#include <sys/usb/hcd/ehci/ehci_hub.h>


/*
 * EHCI Bandwidth Maintainence Structure.
 *
 * The ehci_bandwidth array keeps track of allocated bandwidth for ehci
 * host controller. There are 32 bandwidth lists corresponding to 32 ms
 * periodic frame lists.  Each bandwidth list inturn will contain eight
 * micro frame bandwidth lists.
 */
#define EHCI_MAX_UFRAMES        8       /* Max uframes 125us per frame */

typedef struct ehci_frame_bandwidth {
        uint_t                  ehci_allocated_frame_bandwidth;
        uint_t                  ehci_micro_frame_bandwidth[EHCI_MAX_UFRAMES];
} ehci_frame_bandwidth_t;


/*
 * EHCI Host Controller state structure
 *
 * The Host Controller Driver (HCD) maintains the state of Host Controller
 * (HC). There is an ehci_state structure per instance  of the EHCI
 * host controller.
 */
typedef struct ehci_state {
        dev_info_t              *ehci_dip;              /* Dip of HC */
        uint_t                  ehci_instance;
        usba_hcdi_ops_t         *ehci_hcdi_ops;         /* HCDI structure */
        uint_t                  ehci_flags;             /* Used for cleanup */
        uint16_t                ehci_vendor_id;         /* chip vendor */
        uint16_t                ehci_device_id;         /* chip device */
        uint8_t                 ehci_rev_id;            /* chip revison */

        ddi_acc_handle_t        ehci_caps_handle;       /* Caps Reg Handle */
        ehci_caps_t             *ehci_capsp;            /* Capability Regs */
        ehci_regs_t             *ehci_regsp;            /* Operational Regs */

        ddi_acc_handle_t        ehci_config_handle;     /* Config space hndle */
        uint_t                  ehci_frame_interval;    /* Frme inter reg */
        ddi_dma_attr_t          ehci_dma_attr;          /* DMA attributes */

        ddi_intr_handle_t       *ehci_htable;           /* intr handle */
        int                     ehci_intr_type;         /* intr type used */
        int                     ehci_intr_cnt;          /* # of intrs inuse */
        uint_t                  ehci_intr_pri;          /* intr priority */
        int                     ehci_intr_cap;          /* intr capabilities */
        boolean_t               ehci_msi_enabled;       /* default to true */
        kmutex_t                ehci_int_mutex;         /* Global EHCI mutex */

        /* Periodic Frame List area */
        ehci_periodic_frame_list_t      *ehci_periodic_frame_list_tablep;
                                /* Virtual Periodic Frame List ptr */
        ddi_dma_cookie_t        ehci_pflt_cookie;       /* DMA cookie */
        ddi_dma_handle_t        ehci_pflt_dma_handle;   /* DMA handle */
        ddi_acc_handle_t        ehci_pflt_mem_handle;   /* Memory handle */

        /*
         * There are two pools of memory. One pool contains the memory for
         * the transfer descriptors and other pool contains the memory for
         * the endpoint descriptors. The advantage of the pools is that it's
         * easy to go back and forth between the iommu and the cpu addresses.
         *
         * The pools are protected by the ehci_int_mutex because the memory
         * in the pools may be accessed by either the host controller or the
         * host controller driver.
         */

        /* Endpoint descriptor pool */
        ehci_qh_t               *ehci_qh_pool_addr;     /* Start of the pool */
        ddi_dma_cookie_t        ehci_qh_pool_cookie;    /* DMA cookie */
        ddi_dma_handle_t        ehci_qh_pool_dma_handle;        /* DMA handle */
        ddi_acc_handle_t        ehci_qh_pool_mem_handle;        /* Mem handle */
        uint_t                  ehci_dma_addr_bind_flag;        /* DMA flag */

        /* General transfer descriptor pool */
        ehci_qtd_t              *ehci_qtd_pool_addr;    /* Start of the pool */
        ddi_dma_cookie_t        ehci_qtd_pool_cookie;   /* DMA cookie */
        ddi_dma_handle_t        ehci_qtd_pool_dma_handle;       /* DMA hndle */
        ddi_acc_handle_t        ehci_qtd_pool_mem_handle;       /* Mem hndle */

        /* Isochronous transfer descriptor pool */
        ehci_itd_t              *ehci_itd_pool_addr;    /* Start of the pool */
        ddi_dma_cookie_t        ehci_itd_pool_cookie;   /* DMA cookie */
        ddi_dma_handle_t        ehci_itd_pool_dma_handle;       /* DMA hndle */
        ddi_acc_handle_t        ehci_itd_pool_mem_handle;       /* Mem hndle */

        /* Condition variable for advance on Asynchronous Schedule */
        kcondvar_t              ehci_async_schedule_advance_cv;

        /* Head of Asynchronous Schedule List */
        ehci_qh_t               *ehci_head_of_async_sched_list;

        /*
         * List of QTD inserted either into Asynchronous or Periodic
         * Schedule lists.
         */
        ehci_qtd_t              *ehci_active_qtd_list;
        /*
         * List of ITD active itd list.
         */
        ehci_itd_t              *ehci_active_itd_list;

        /*
         * Bandwidth fields
         *
         * The ehci_bandwidth array keeps track of allocated bandwidth for
         * ehci host controller. There are 32 bandwidth lists corresponding
         * to 32 ms periodic frame lists. Each bandwidth list in turn will
         * contain eight micro frame bandwidth lists.
         *
         * ehci_min_frame_bandwidth field indicates least allocated milli
         * second bandwidth list.
         */
        ehci_frame_bandwidth_t  ehci_frame_bandwidth[EHCI_NUM_INTR_QH_LISTS];

        /* No. of open pipes, async qh, and periodic qh */
        uint_t                  ehci_open_pipe_count;
        uint_t                  ehci_open_async_count;
        uint_t                  ehci_open_periodic_count;

        /* No. of async and periodic requests */
        uint_t                  ehci_async_req_count;
        uint_t                  ehci_periodic_req_count;

        /*
         * Endpoint Reclamation List
         *
         * The interrupt list processing cannot be stopped when a periodic
         * endpoint is removed from the list.  The endpoints are detached
         * from the interrupt lattice tree and put on to the reclaimation
         * list. On next SOF interrupt all those endpoints,  which are on
         * the reclaimation list will be deallocated.
         */
        ehci_qh_t               *ehci_reclaim_list;     /* Reclaimation list */

        ehci_root_hub_t         ehci_root_hub;          /* Root hub info */

        /* Frame number overflow information */
        usb_frame_number_t      ehci_fno;

        /* For host controller error counter */
        uint_t                  ehci_hc_error;

        /*
         * ehci_missed_intr_sts is used to save the normal mode interrupt
         * status information  if an interrupt is pending for normal mode
         * when polled code is entered.
         */
        uint_t                  ehci_missed_intr_sts;

        /*
         * Saved copy of the ehci registers of the normal mode & change
         * required ehci registers values for the polled mode operation.
         * Before returning from the polled mode to normal mode replace
         * the required current registers with this saved ehci registers
         * copy.
         */
        ehci_regs_t     ehci_polled_save_regs;

        /*
         * Saved copy of the interrupt table used in normal ehci mode and
         * replace this table by another interrupt table that used in the
         * POLLED mode.
         */
        ehci_qh_t *ehci_polled_frame_list_table[EHCI_NUM_PERIODIC_FRAME_LISTS];

        /* ehci polled mode enter counter */
        uint_t                  ehci_polled_enter_count;

        /*
         * counter for polled mode and used in suspend mode to see if
         * there is a keyboard connected.
         */
        uint_t                  ehci_polled_kbd_count;

        /* counter for polled read and use it to clean the interrupt status */
        uint_t                  ehci_polled_read_count;

#if defined(__x86)
        /* counter for polled root hub status */
        uint_t                  ehci_polled_root_hub_count;
#endif  /* __x86 */

        /* EHCI Host Controller Software State information */
        uint_t                  ehci_hc_soft_state;

        /* Log handle for debug, console, log messages */
        usb_log_handle_t        ehci_log_hdl;

        /* Kstat structures */
        kstat_t                 *ehci_intrs_stats;
        kstat_t                 *ehci_total_stats;
        kstat_t                 *ehci_count_stats[USB_N_COUNT_KSTATS];
} ehci_state_t;

typedef struct ehci_intrs_stats {
        struct kstat_named      ehci_sts_async_sched_status;
        struct kstat_named      ehci_sts_periodic_sched_status;
        struct kstat_named      ehci_sts_empty_async_schedule;
        struct kstat_named      ehci_sts_host_ctrl_halted;
        struct kstat_named      ehci_sts_async_advance_intr;
        struct kstat_named      ehci_sts_host_system_error_intr;
        struct kstat_named      ehci_sts_frm_list_rollover_intr;
        struct kstat_named      ehci_sts_rh_port_change_intr;
        struct kstat_named      ehci_sts_usb_error_intr;
        struct kstat_named      ehci_sts_usb_intr;
        struct kstat_named      ehci_sts_not_claimed;
        struct kstat_named      ehci_sts_total;
} ehci_intrs_stats_t;

/*
 * ehci kstat defines
 */
#define EHCI_INTRS_STATS(ehci)  ((ehci)->ehci_intrs_stats)
#define EHCI_INTRS_STATS_DATA(ehci)     \
        ((ehci_intrs_stats_t *)EHCI_INTRS_STATS((ehci))->ks_data)

#define EHCI_TOTAL_STATS(ehci)  ((ehci)->ehci_total_stats)
#define EHCI_TOTAL_STATS_DATA(ehci)     (KSTAT_IO_PTR((ehci)->ehci_total_stats))
#define EHCI_CTRL_STATS(ehci)   \
        (KSTAT_IO_PTR((ehci)->ehci_count_stats[USB_EP_ATTR_CONTROL]))
#define EHCI_BULK_STATS(ehci)   \
        (KSTAT_IO_PTR((ehci)->ehci_count_stats[USB_EP_ATTR_BULK]))
#define EHCI_INTR_STATS(ehci)   \
        (KSTAT_IO_PTR((ehci)->ehci_count_stats[USB_EP_ATTR_INTR]))
#define EHCI_ISOC_STATS(ehci)   \
        (KSTAT_IO_PTR((ehci)->ehci_count_stats[USB_EP_ATTR_ISOCH]))

/* warlock directives, stable data */
_NOTE(MUTEX_PROTECTS_DATA(ehci_state_t::ehci_int_mutex, ehci_state_t))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_intr_pri))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_dip))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_regsp))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_instance))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_vendor_id))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_device_id))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_rev_id))

/* this may not be stable data in the future */
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_qtd_pool_addr))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_qtd_pool_mem_handle))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_qtd_pool_cookie))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_qh_pool_addr))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_qh_pool_mem_handle))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_qh_pool_cookie))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_itd_pool_addr))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_itd_pool_mem_handle))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_itd_pool_cookie))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_dma_addr_bind_flag))
_NOTE(DATA_READABLE_WITHOUT_LOCK(ehci_state_t::ehci_log_hdl))

_NOTE(LOCK_ORDER(ehci_state::ehci_int_mutex \
                usba_pipe_handle_data::p_mutex \
                usba_device::usb_mutex \
                usba_ph_impl::usba_ph_mutex))

/*
 * Host Contoller Software States
 *
 * EHCI_CTLR_INIT_STATE:
 *      The host controller soft state will be set to this during the
 *      ehci_attach.
 *
 * EHCI_CTLR_SUSPEND_STATE:
 *      The host controller soft state will be set to this during the
 *      ehci_cpr_suspend.
 *
 * EHCI_CTLR_OPERATIONAL_STATE:
 *      The host controller soft state will be set to this after moving
 *      host controller to operational state and host controller start
 *      generating SOF successfully.
 *
 * EHCI_CTLR_ERROR_STATE:
 *      The host controller soft state will be set to this during the
 *      no SOF or UE error conditions.
 *
 *      Under this state or condition, only pipe stop polling, pipe reset
 *      and pipe close are allowed. But all other entry points like  pipe
 *      open, get/set pipe policy, cotrol send/receive, bulk send/receive
 *      isoch send/receive, start polling etc. will fail.
 *
 * State Diagram for the host controller software state
 *
 *
 * ehci_attach->[INIT_STATE]
 *      |
 *      |       -------->----[ERROR_STATE]--<-----------<---
 *      |      |      Failure (UE/no SOF condition)         |
 *      |      ^                                            ^
 *      V      |      Success                               |
 * ehci_init_ctlr--->--------[OPERATIONAL_STATE]------>-ehci_send/recv/polling
 *      ^                                           |
 *      |                                           |
 *      |                                           V
 *      -<-ehci_cpr_resume--[SUSPEND_STATE]-<-ehci_cpr_suspend
 */
#define EHCI_CTLR_INIT_STATE            0       /* Initilization state */
#define EHCI_CTLR_SUSPEND_STATE         1       /* Suspend state */
#define EHCI_CTLR_OPERATIONAL_STATE     2       /* Operational state */
#define EHCI_CTLR_ERROR_STATE           3       /* Ue error or no sof state */

/*
 * Flags for initializatoin of host controller
 */
#define EHCI_NORMAL_INITIALIZATION      0       /* Normal initialization */
#define EHCI_REINITIALIZATION           1       /* Re-initialization */

/*
 * Periodic and non-periodic macros
 */
#define EHCI_PERIODIC_ENDPOINT(endpoint) (((endpoint->bmAttributes &\
                                USB_EP_ATTR_MASK) == USB_EP_ATTR_INTR) ||\
                                ((endpoint->bmAttributes &\
                                USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH))

#define EHCI_NON_PERIODIC_ENDPOINT(endpoint) (((endpoint->bmAttributes &\
                                USB_EP_ATTR_MASK) == USB_EP_ATTR_CONTROL) ||\
                                ((endpoint->bmAttributes &\
                                USB_EP_ATTR_MASK) == USB_EP_ATTR_BULK))

#define EHCI_ISOC_ENDPOINT(endpoint) (((endpoint->bmAttributes &\
                                USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH))

#define EHCI_INTR_ENDPOINT(endpoint) (((endpoint->bmAttributes &\
                                USB_EP_ATTR_MASK) == USB_EP_ATTR_INTR))


/*
 * EHCI QH and QTD Pool sizes.
 */
#define EHCI_QH_POOL_SIZE       1000
#define EHCI_QTD_POOL_SIZE      200
#define EHCI_ITD_POOL_SIZE      200

/*
 * ehci_dma_addr_bind_flag values
 *
 * This flag indicates if the various DMA addresses allocated by the EHCI
 * have been bound to their respective handles. This is needed to recover
 * without errors from ehci_cleanup when it calls ddi_dma_unbind_handle()
 */
#define EHCI_QTD_POOL_BOUND     0x01    /* For QTD pools  */
#define EHCI_QH_POOL_BOUND      0x02    /* For QH pools  */
#define EHCI_PFLT_DMA_BOUND     0x04    /* For Periodic Frame List area */
#define EHCI_ITD_POOL_BOUND     0x08    /* For QTD pools  */

/*
 * Maximum SOF wait count
 */
#define MAX_SOF_WAIT_COUNT      2       /* Wait for maximum SOF frames */

/*
 * One uFrame   125 micro seconds
 * One Frame    1 milli second or 8 uFrames
 */
#define EHCI_uFRAMES_PER_USB_FRAME              8
#define EHCI_uFRAMES_PER_USB_FRAME_SHIFT        3


/*
 * Pipe private structure
 *
 * There is an instance of this structure per pipe.  This structure holds
 * HCD specific pipe information.  A pointer to this structure is kept in
 * the USBA pipe handle (usba_pipe_handle_data_t).
 */
typedef struct ehci_pipe_private {
        usba_pipe_handle_data_t *pp_pipe_handle;        /* Back ptr to handle */
        ehci_qh_t               *pp_qh;                 /* Pipe's qh */

        /* State of the pipe */
        uint_t                  pp_state;               /* See below */

        /* Local copy of the pipe policy */
        usb_pipe_policy_t       pp_policy;

        /* For Periodic Pipes Only */
        uint_t                  pp_pnode;               /* periodic node */
        uchar_t                 pp_smask;               /* Start split mask */
        uchar_t                 pp_cmask;               /* Comp split mask */
        uint_t                  pp_cur_periodic_req_cnt; /* Curr req count */
        uint_t                  pp_max_periodic_req_cnt; /* Max req count */

        /* For Isochronous pipes only */
        usb_frame_number_t      pp_next_frame_number;   /* Next frame no */

        /*
         * Each pipe may have multiple transfer wrappers. Each transfer
         * wrapper represents a USB transfer on the bus.  A transfer is
         * made up of one or more transactions.
         */
        struct ehci_trans_wrapper *pp_tw_head;  /* Head of the list */
        struct ehci_trans_wrapper *pp_tw_tail;  /* Tail of the list */

        struct ehci_isoc_xwrapper *pp_itw_head; /* Head of the list */
        struct ehci_isoc_xwrapper *pp_itw_tail; /* Tail of the list */

        /*
         * Pipe's transfer timeout handling & this transfer timeout handling
         * will be per pipe.
         */
        struct ehci_trans_wrapper *pp_timeout_list;     /* Timeout list */
        timeout_id_t            pp_timer_id;            /* Timer id  */

        /* Done td count */
        uint_t                  pp_count_done_qtds;     /* Done td count */

        /* Errors */
        usb_cr_t                pp_error;               /* Pipe error */

        /* Condition variable for transfers completion event */
        kcondvar_t              pp_xfer_cmpl_cv;        /* Xfer completion */

        /* Pipe flag */
        uint_t                  pp_flag;                /* For polled mode */

        /* Halting States */
        uint_t                  pp_halt_state;          /* Is it halting */

        /* Condition variable for halt completion event */
        kcondvar_t              pp_halt_cmpl_cv;        /* Xfer completion */

        /*
         * HCD gets Interrupt/Isochronous IN polling request only once and
         * it has to insert next polling requests after completion of first
         * request until either stop polling/pipe close is called. So  HCD
         * has to take copy of the original Interrupt/Isochronous IN request.
         */
        usb_opaque_t            pp_client_periodic_in_reqp;
} ehci_pipe_private_t;

_NOTE(MUTEX_PROTECTS_DATA(ehci_state_t::ehci_int_mutex, ehci_pipe_private_t))

/*
 * Pipe states
 *
 * ehci pipe states will be similar to usba. Refer usbai.h.
 */
#define EHCI_PIPE_STATE_IDLE            1       /* Pipe is in ready state */
#define EHCI_PIPE_STATE_ACTIVE          2       /* Pipe is in busy state */
#define EHCI_PIPE_STATE_ERROR           3       /* Pipe is in error state */

/* Additional ehci pipe states for the ehci_pipe_cleanup */
#define EHCI_PIPE_STATE_CLOSE           4       /* Pipe close */
#define EHCI_PIPE_STATE_RESET           5       /* Pipe reset */
#define EHCI_PIPE_STATE_STOP_POLLING    6       /* Pipe stop polling */

/*
 * Pipe flag
 *
 * Interrupt or polled mode.
 */
#define EHCI_INTERRUPT_MODE_FLAG        0       /* Interrupt mode flag */
#define EHCI_POLLED_MODE_FLAG           1       /* Polled mode flag */

/* Pipe specific flags */
#define EHCI_ISOC_XFER_CONTINUE         1       /* For isoc transfers */

/*
 * Halting States
 *  prevent halting from interleaving.
 */
#define EHCI_HALT_STATE_FREE            0       /* Pipe free to accept reqs */
#define EHCI_HALT_STATE_HALTING         1       /* Currently Halting */

/*
 * Request values for Clear_TT_Buffer
 */
#define EHCI_CLEAR_TT_BUFFER_REQTYPE    (USB_DEV_REQ_TYPE_CLASS | \
                                        USB_DEV_REQ_RCPT_OTHER)
#define EHCI_CLEAR_TT_BUFFER_BREQ       8

/*
 * USB frame offset
 *
 * Add appropriate frame offset to the current usb frame number and use it
 * as a starting frame number for a given usb isochronous request.
 */
#define EHCI_FRAME_OFFSET               2       /* Frame offset */

/*
 * Different interrupt polling intervals supported for high speed
 * devices and its range must be from 1 to 16 units. This value is
 * used as th exponent for a 2 ^ (bInterval - 1). Ex: a Binterval
 * of 4 means a period of 8us (2 ^ (4-1)).
 *
 * The following values are defined after above convertion in terms
 * 125us units.
 */
#define EHCI_INTR_1US_POLL              1       /* 1us poll interval */
#define EHCI_INTR_2US_POLL              2       /* 2us poll interval */
#define EHCI_INTR_4US_POLL              4       /* 4us poll interval */
#define EHCI_INTR_XUS_POLL              8       /* 8us and above */

/*
 * The following indecies are are used to calculate Start and complete
 * masks as per the polling interval.
 */
#define EHCI_1US_MASK_INDEX             14      /* 1us mask index */
#define EHCI_2US_MASK_INDEX             12      /* 2us mask index */
#define EHCI_4US_MASK_INDEX             8       /* 4us mask index */
#define EHCI_XUS_MASK_INDEX             0       /* 8us and above */

/*
 * Different interrupt polling intervals supported for low/full/high
 * speed devices. For high speed devices, the following values are
 * applicable after convertion.
 */
#define EHCI_INTR_1MS_POLL              1       /* 1ms poll interval */
#define EHCI_INTR_2MS_POLL              2       /* 2ms poll interval */
#define EHCI_INTR_4MS_POLL              4       /* 4ms poll interval */
#define EHCI_INTR_8MS_POLL              8       /* 8ms poll interval */
#define EHCI_INTR_16MS_POLL             16      /* 16ms poll interval */
#define EHCI_INTR_32MS_POLL             32      /* 32ms poll interval */

/*
 * Number of interrupt transfer requests that should be maintained on
 * the interrupt endpoint corresponding to different polling intervals
 * supported.
 */
#define EHCI_INTR_1MS_REQS              4       /* 1ms polling interval */
#define EHCI_INTR_2MS_REQS              2       /* 2ms polling interval */
#define EHCI_INTR_XMS_REQS              1       /* Between 4ms and 32ms */

/* Function prototype */
typedef void (*ehci_handler_function_t)(
        ehci_state_t                    *ehcip,
        ehci_pipe_private_t             *pp,
        struct ehci_trans_wrapper       *tw,
        ehci_qtd_t                      *qtd,
        void                            *ehci_handle_callback_value);


/*
 * Transfer wrapper
 *
 * The transfer wrapper represents a USB transfer on the bus and there
 * is one instance per USB transfer.  A transfer is made up of one or
 * more transactions. EHCI uses one QTD for one transaction. So one
 * transfer wrapper may have one or more QTDs associated.
 *
 * The data to be transferred are contained in the TW buffer which is
 * virtually contiguous but physically discontiguous. When preparing
 * the QTDs for a USB transfer, the DMA cookies corresponding to the
 * TW buffer need to be walked through to retrieve the DMA addresses.
 *
 * Control and bulk pipes will have one transfer wrapper per transfer
 * and where as Isochronous and Interrupt pipes will only have one
 * transfer wrapper. The transfers wrapper are continually reused for
 * the Interrupt and Isochronous pipes as those pipes are polled.
 */
typedef struct ehci_trans_wrapper {
        struct ehci_trans_wrapper       *tw_next;       /* Next wrapper */
        ehci_pipe_private_t             *tw_pipe_private; /* Back ptr */
        ddi_dma_handle_t                tw_dmahandle;   /* DMA handle */
        ddi_acc_handle_t                tw_accesshandle; /* Acc hndle */
        ddi_dma_cookie_t                tw_cookie;      /* DMA cookie */
        uint_t                          tw_ncookies;    /* DMA cookie count */
        uint_t                          tw_cookie_idx;  /* DMA cookie index */
        size_t                          tw_dma_offs;    /* DMA buffer offset */
        uint32_t                        tw_id;          /* 32bit ID */
        size_t                          tw_length;      /* Txfer length */
        char                            *tw_buf;        /* Buffer for Xfer */
        usb_flags_t                     tw_flags;       /* Flags */
        uint_t                          tw_num_qtds;    /* Number of QTDs */
        ehci_qtd_t                      *tw_qtd_head;   /* Head QTD */
        ehci_qtd_t                      *tw_qtd_tail;   /* Tail QTD */
        uint_t                          tw_direction;   /* Direction of QTD */

        /* Current transfer request pointer */
        usb_opaque_t                    tw_curr_xfer_reqp;

        /* Transfer timeout information */
        int                             tw_timeout;     /* Timeout value */
        struct ehci_trans_wrapper       *tw_timeout_next; /* Xfer Timeout Q */

        /*
         * This is the function to call when this td is done. This way
         * we don't have to look in the td to figure out what kind it is.
         */
        ehci_handler_function_t         tw_handle_qtd;

        /*
         * This is the callback value used when processing a done td.
         */
        usb_opaque_t                    tw_handle_callback_value;

        /* We preallocate all the td's for each tw and place them here */
        ehci_qtd_t                      *tw_qtd_free_list;
        ehci_qtd_t                      *tw_alt_qtd;
} ehci_trans_wrapper_t;

_NOTE(MUTEX_PROTECTS_DATA(ehci_state_t::ehci_int_mutex, ehci_trans_wrapper))

/*
 * Isochronous Transfer Wrapper
 *
 * This transfer wrapper is built specifically for the LOW/FULL/HIGH speed
 * isochronous transfers.  A transfer wrapper consists of one or more
 * transactionsl, but there is one one instance per USB transfer request.
 *
 * The isochrnous transfer wrapper are continiously reused because these
 * pipes are polled.
 */
typedef struct ehci_isoc_xwrapper {
        struct ehci_isoc_xwrapper       *itw_next;      /* Next wrapper in pp */
        ehci_pipe_private_t             *itw_pipe_private;

        /* DMA and memory pointers */
        ddi_dma_handle_t                itw_dmahandle;  /* DMA handle ETT */
        ddi_acc_handle_t                itw_accesshandle; /* Acc hndle */
        ddi_dma_cookie_t                itw_cookie;     /* DMA cookie */

        /* Transfer information */
        char                            *itw_buf;       /* Buffer for Xfer */
        size_t                          itw_length;     /* Txfer length */
        usb_flags_t                     itw_flags;      /* Flags */
        usb_port_status_t               itw_port_status; /* Port Speed */
        uint_t                          itw_direction;  /* Direction of ITD */

        /* ITD information */
        uint_t                          itw_num_itds;   /* Number of ITDs */
        ehci_itd_t                      *itw_itd_head;  /* Head ITD */
        ehci_itd_t                      *itw_itd_tail;  /* Tail ITD */
        usb_isoc_req_t                  *itw_curr_xfer_reqp;
        usb_isoc_pkt_descr_t            *itw_curr_isoc_pktp;

        /* We preallocate all the td's for each tw and place them here */
        ehci_itd_t                      *itw_itd_free_list;

        /* Device and hub information needed by every iTD */
        uint_t                          itw_hub_addr;
        uint_t                          itw_hub_port;
        uint_t                          itw_endpoint_num;
        uint_t                          itw_device_addr;

        /*
         * Callback handling function and arguement.  Called when an iTD is
         * is done.
         */
        usb_opaque_t                    itw_handle_callback_value;

        /* 32bit ID */
        uint32_t                        itw_id;
} ehci_isoc_xwrapper_t;

_NOTE(MUTEX_PROTECTS_DATA(ehci_state_t::ehci_int_mutex, ehci_isoc_xwrapper_t))

/*
 * Time waits for the different EHCI specific operations.
 * These timeout values are specified in terms of microseconds.
 */
#define EHCI_RESET_TIMEWAIT     10000   /* HC reset waiting time */
#define EHCI_TIMEWAIT           10000   /* HC any other waiting time */
#define EHCI_SOF_TIMEWAIT       20000   /* SOF Wait time */
#define EHCI_TAKEOVER_DELAY     10000   /* HC take over waiting time */
#define EHCI_TAKEOVER_WAIT_COUNT        25      /* HC take over waiting count */

/* These timeout values are specified in seconds */
#define EHCI_DEFAULT_XFER_TIMEOUT       5 /* Default transfer timeout */
#define EHCI_XFER_CMPL_TIMEWAIT         3 /* Xfers completion timewait */

/* EHCI flags for general use */
#define EHCI_FLAGS_NOSLEEP      0x000   /* Don't wait for SOF */
#define EHCI_FLAGS_SLEEP        0x100   /* Wait for SOF */
#define EHCI_FLAGS_DMA_SYNC     0x200   /* Call ddi_dma_sync */

/*
 * Maximum allowable data transfer  size per transaction as supported
 * by EHCI is 20k. (See EHCI Host Controller Interface Spec Rev 0.96)
 *
 * Also within QTD, there will be five buffer pointers abd each buffer
 * pointer can transfer upto 4k bytes of data.
 */
#define EHCI_MAX_QTD_XFER_SIZE  0x5000  /* Maxmum data per transaction */
#define EHCI_MAX_QTD_BUF_SIZE   0x1000  /* Maxmum data per buffer */

/*
 * The maximum allowable bulk data transfer size. It can be different
 * from EHCI_MAX_QTD_XFER_SIZE and if it is more then ehci driver will
 * take care of  breaking a bulk data request into  multiples of ehci
 * EHCI_MAX_QTD_XFER_SIZE  until request is satisfied.  Currently this
 * value is set to 640k bytes.
 */
#define EHCI_MAX_BULK_XFER_SIZE 0xA0000 /* Maximum bulk transfer size */

/*
 * Timeout flags
 *
 * These flags will be used to stop the timer before timeout handler
 * gets executed.
 */
#define EHCI_REMOVE_XFER_IFLAST 1       /* Stop the timer if it is last QTD */
#define EHCI_REMOVE_XFER_ALWAYS 2       /* Stop the timer without condition */


/*
 * High speed bandwidth allocation
 *
 * The following definitions are used during bandwidth calculations
 * for a given high speed endpoint or high speed split transactions.
 */
#define HS_BUS_BANDWIDTH        7500    /* Up to 7500 bytes per 125us */
#define HS_MAX_POLL_INTERVAL    16      /* Max high speed polling interval */
#define HS_MIN_POLL_INTERVAL    1       /* Min high speed polling interval */
#define HS_SOF                  12      /* Length in bytes of High speed SOF */
#define HS_EOF                  70      /* Length in bytes of High speed EOF */
#define TREE_HEIGHT             5       /* Log base 2 of 32 */

/*
 * As per USB 2.0 specification section 5.5.4, 20% of bus time is reserved
 * for the non-periodic high-speed transfers. Where as peridoic high-speed
 * transfers will get 80% of the bus time. In one micro-frame or 125us, we
 * can transfer 7500 bytes or 60,000 bits.
 */
#define HS_NON_PERIODIC_BANDWIDTH       1500
#define HS_PERIODIC_BANDWIDTH           (HS_BUS_BANDWIDTH - HS_SOF - \
                                        HS_EOF - HS_NON_PERIODIC_BANDWIDTH)

/*
 * High speed periodic frame bandwidth will be eight times the micro frame
 * high speed periodic bandwidth.
 */
#define HS_PERIODIC_FRAME_BANDWIDTH     HS_PERIODIC_BANDWIDTH * EHCI_MAX_UFRAMES

/*
 * The following are the protocol overheads in terms of Bytes for the
 * different transfer types.  All these protocol overhead  values are
 * derived from the 5.11.3 section of USB 2.0 Specification.
 */
#define HS_NON_ISOC_PROTO_OVERHEAD      55
#define HS_ISOC_PROTO_OVERHEAD          38

/*
 * The following are THE protocol overheads in terms of Bytes for the
 * start and complete split transactions tokens overheads.  All these
 * protocol overhead values are derived from the 8.4.2.2 and 8.4.2.3
 * of USB2.0 Specification.
 */
#define START_SPLIT_OVERHEAD            04
#define COMPLETE_SPLIT_OVERHEAD         04

/*
 * The Host Controller (HC) delays are the USB host controller specific
 * delays. The value shown below is the host  controller delay for  the
 * given EHCI host controller.
 */
#define EHCI_HOST_CONTROLLER_DELAY      18

/*
 * Low/Full speed bandwidth allocation
 *
 * The following definitions are used during bandwidth calculations for
 * a given high speed hub or  a transaction translator  (TT) and  for a
 * given low/full speed device connected to high speed hub or TT  using
 * split transactions
 */
#define FS_BUS_BANDWIDTH        1500    /* Up to 1500 bytes per 1ms */
#define FS_MAX_POLL_INTERVAL    255     /* Max full speed poll interval */
#define FS_MIN_POLL_INTERVAL    1       /* Min full speed polling interval */
#define FS_SOF                  6       /* Length in bytes of Full speed SOF */
#define FS_EOF                  4       /* Length in bytes of Full speed EOF */

/*
 * Minimum polling interval for low speed endpoint
 *
 * According USB 2.0 Specification, a full-speed endpoint can specify
 * a desired polling interval 1ms to 255ms and a low speed endpoints
 * are limited to specifying only 10ms to 255ms. But some old keyboards
 * and mice uses polling interval of 8ms. For compatibility purpose,
 * we are using polling interval between 8ms and 255ms for low speed
 * endpoints. The ehci driver will use 8ms polling interval if a low
 * speed device reports a polling interval that is less than 8ms.
 */
#define LS_MAX_POLL_INTERVAL    255     /* Max low speed poll interval */
#define LS_MIN_POLL_INTERVAL    8       /* Min low speed polling interval */

/*
 * For non-periodic transfers, reserve atleast for one low-speed device
 * transaction. According to USB Bandwidth Analysis white paper and also
 * as per OHCI Specification 1.0a, section 7.3.5, page 123, one low-speed
 * transaction takes 0x628h full speed bits (197 bytes), which comes to
 * around 13% of USB frame time.
 *
 * The periodic transfers will  get around 87% of USB frame time.
 */
#define FS_NON_PERIODIC_BANDWIDTH       197
#define FS_PERIODIC_BANDWIDTH           (FS_BUS_BANDWIDTH - FS_SOF - \
                                        FS_EOF - FS_NON_PERIODIC_BANDWIDTH)

/*
 * The following are the protocol overheads in terms of Bytes for the
 * different transfer types.  All these protocol overhead  values are
 * derived from the 5.11.3 section of USB Specification and  with the
 * help of Bandwidth Analysis white paper which is posted on the  USB
 * developer forum.
 */
#define FS_NON_ISOC_PROTO_OVERHEAD      14
#define FS_ISOC_INPUT_PROTO_OVERHEAD    11
#define FS_ISOC_OUTPUT_PROTO_OVERHEAD   10
#define LOW_SPEED_PROTO_OVERHEAD        97
#define HUB_LOW_SPEED_PROTO_OVERHEAD    01

/* The maximum amount of isoch data that can be transferred in one uFrame */
#define MAX_UFRAME_SITD_XFER            188

/*
 * The low speed clock below represents that to transmit one low-speed
 * bit takes eight times more than one full speed bit time.
 */
#define LOW_SPEED_CLOCK                 8

/*
 * The Transaction Translator (TT) delay is the additional time needed
 * to execute low/full speed transaction from high speed split transaction
 * for the low/full device connected to the high speed extrenal hub.
 */
#define TT_DELAY                        18


/*
 * Macros for setting/getting information
 */
#define Get_QH(addr)            ddi_get32(ehcip->ehci_qh_pool_mem_handle, \
                                        (uint32_t *)&addr)

#define Set_QH(addr, val)       ddi_put32(ehcip->ehci_qh_pool_mem_handle,  \
                                        ((uint32_t *)&addr), \
                                        ((int32_t)(val)))

#define Get_QTD(addr)           ddi_get32(ehcip->ehci_qtd_pool_mem_handle, \
                                        (uint32_t *)&addr)

#define Set_QTD(addr, val)      ddi_put32(ehcip->ehci_qtd_pool_mem_handle, \
                                        ((uint32_t *)&addr), \
                                        ((int32_t)(val)))

#define Get_ITD(addr)           ddi_get32(ehcip->ehci_itd_pool_mem_handle, \
                                        (uint32_t *)&addr)

#define Set_ITD(addr, val)      ddi_put32(ehcip->ehci_itd_pool_mem_handle, \
                                        ((uint32_t *)&addr), \
                                        ((int32_t)(val)))

#define Get_ITD_BODY(ptr, addr)         ddi_get32( \
                                            ehcip->ehci_itd_pool_mem_handle, \
                                            (uint32_t *)&ptr->itd_body[addr])

#define Set_ITD_BODY(ptr, addr, val)    ddi_put32( \
                                            ehcip->ehci_itd_pool_mem_handle, \
                                            ((uint32_t *)&ptr->itd_body[addr]),\
                                            ((int32_t)(val)))

#define Get_ITD_INDEX(ptr, pos)         ddi_get32( \
                                            ehcip->ehci_itd_pool_mem_handle, \
                                            (uint32_t *)&ptr->itd_index[pos])

#define Set_ITD_INDEX(ptr, pos, val)    ddi_put32( \
                                            ehcip->ehci_itd_pool_mem_handle, \
                                            ((uint32_t *)&ptr->itd_index[pos]),\
                                            ((uint32_t)(val)))

#define Get_ITD_FRAME(addr)             ddi_get64( \
                                            ehcip->ehci_itd_pool_mem_handle, \
                                            (uint64_t *)&addr)

#define Set_ITD_FRAME(addr, val)        ddi_put64( \
                                            ehcip->ehci_itd_pool_mem_handle, \
                                            ((uint64_t *)&addr), \
                                            (val))

#define Get_PFLT(addr)          ddi_get32(ehcip->ehci_pflt_mem_handle, \
                                        (uint32_t *)&addr)

#define Set_PFLT(addr, val)     ddi_put32(ehcip->ehci_pflt_mem_handle, \
                                        ((uint32_t *)&addr), \
                                        ((int32_t)(uintptr_t)(val)))

#define Get_8Cap(addr)          ddi_get8(ehcip->ehci_caps_handle, \
                                        (uint8_t *)&ehcip->ehci_capsp->addr)

#define Get_16Cap(addr)         ddi_get16(ehcip->ehci_caps_handle, \
                                        (uint16_t *)&ehcip->ehci_capsp->addr)

#define Get_Cap(addr)           ddi_get32(ehcip->ehci_caps_handle, \
                                        (uint32_t *)&ehcip->ehci_capsp->addr)

#define Get_OpReg(addr)         ddi_get32(ehcip->ehci_caps_handle, \
                                        (uint32_t *)&ehcip->ehci_regsp->addr)

#define Set_OpReg(addr, val)    ddi_put32(ehcip->ehci_caps_handle, \
                                ((uint32_t *)&ehcip->ehci_regsp->addr), \
                                        ((int32_t)(val)))

#define CalculateITDMultiField(pkgSize)         (1 + (((pkgSize)>>11) & 0x03))

#define EHCI_MAX_RETRY          10

#define Set_OpRegRetry(addr, val, r) \
                                while (Get_OpReg(addr) != val) { \
                                        if (r >= EHCI_MAX_RETRY) \
                                                break; \
                                        r++; \
                                        Set_OpReg(addr, val); \
                                }

#define Sync_QH_QTD_Pool(ehcip) (void) ddi_dma_sync( \
                                ehcip->ehci_qh_pool_dma_handle, \
                                0, EHCI_QH_POOL_SIZE * sizeof (ehci_qh_t), \
                                DDI_DMA_SYNC_FORCPU); \
                                (void) ddi_dma_sync( \
                                ehcip->ehci_qtd_pool_dma_handle, \
                                0, EHCI_QTD_POOL_SIZE * sizeof (ehci_qtd_t), \
                                DDI_DMA_SYNC_FORCPU);

#define Sync_ITD_Pool(ehcip) (void) ddi_dma_sync( \
                                ehcip->ehci_itd_pool_dma_handle, \
                                0, EHCI_ITD_POOL_SIZE * sizeof (ehci_itd_t), \
                                DDI_DMA_SYNC_FORCPU);

#define Sync_IO_Buffer(dma_handle, length) \
                                (void) ddi_dma_sync(dma_handle, \
                                0, length, DDI_DMA_SYNC_FORCPU);

#define Sync_IO_Buffer_for_device(dma_handle, length) \
                                (void) ddi_dma_sync(dma_handle, \
                                0, length, DDI_DMA_SYNC_FORDEV);

/*
 * Macros to speed handling of 32bit IDs
 */
#define EHCI_GET_ID(x)          id32_alloc((void *)(x), KM_SLEEP)
#define EHCI_LOOKUP_ID(x)       id32_lookup((x))
#define EHCI_FREE_ID(x)         id32_free((x))


/*
 * Miscellaneous definitions.
 */

/* Data toggle bits */
#define DATA0           0
#define DATA1           1

/* Halt bit actions */
#define CLEAR_HALT      0
#define SET_HALT        1

typedef uint_t          halt_bit_t;

/*
 * Setup Packet
 */
typedef struct setup_pkt {
        uchar_t bmRequestType;
        uchar_t bRequest;
        ushort_t wValue;
        ushort_t wIndex;
        ushort_t wLength;
}setup_pkt_t;

#define SETUP_SIZE              8       /* Setup packet is always 8 bytes */

#define REQUEST_TYPE_OFFSET     0
#define REQUEST_OFFSET          1
#define VALUE_OFFSET            2
#define INDEX_OFFSET            4
#define LENGTH_OFFSET           6

#define TYPE_DEV_TO_HOST        0x80000000
#define DEVICE                  0x00000001
#define CONFIGURATION           0x00000002

/*
 * The following are used in attach to   indicate
 * what has been succesfully allocated, so detach
 * can remove them.
 */
#define EHCI_ATTACH             0x01    /* ehci driver initilization */
#define EHCI_ZALLOC             0x02    /* Memory for ehci state structure */
#define EHCI_INTR               0x04    /* Interrupt handler registered */
#define EHCI_USBAREG            0x08    /* USBA registered */
#define EHCI_RHREG              0x10    /* Root hub driver loaded */

/*
 * This variable is used in the EHCI_FLAGS to tell the ISR to broadcase
 * the ehci_async_schedule_advance_cv when an intr occurs.  It is used to
 * make sure that EHCI is receiving interrupts.
 */
#define EHCI_CV_INTR            0x20    /* Ask INTR to broadcast cv */

#define EHCI_UNIT(dev)  (getminor((dev)) & ~HUBD_IS_ROOT_HUB)

/*
 * Debug printing
 * Masks
 */
#define PRINT_MASK_ATTA         0x00000001      /* Attach time */
#define PRINT_MASK_LISTS        0x00000002      /* List management */
#define PRINT_MASK_ROOT_HUB     0x00000004      /* Root hub stuff */
#define PRINT_MASK_ALLOC        0x00000008      /* Alloc/dealloc descr */
#define PRINT_MASK_INTR         0x00000010      /* Interrupt handling */
#define PRINT_MASK_BW           0x00000020      /* Bandwidth */
#define PRINT_MASK_CBOPS        0x00000040      /* CB-OPS */
#define PRINT_MASK_HCDI         0x00000080      /* HCDI entry points */
#define PRINT_MASK_DUMPING      0x00000100      /* Dump ehci info */
#define PRINT_MASK_ALL          0xFFFFFFFF

#define PCI_VENDOR_NVIDIA       0x10de          /* PCI Vendor-id NVIDIA */
#define PCI_DEVICE_NVIDIA_CK804 0x5b
#define PCI_DEVICE_NVIDIA_MCP04 0x3c
/*
 * workaround for ALI chips
 */
#define PCI_VENDOR_ALI          0x10b9          /* PCI Vendor-id Acer */

/*
 * NEC on COMBO and Uli M1575 can support PM
 */
#define PCI_VENDOR_NEC_COMBO    0x1033
#define PCI_DEVICE_NEC_COMBO    0xe0
#define PCI_VENDOR_ULi_M1575    0x10b9
#define PCI_DEVICE_ULi_M1575    0x5239

/*
 * VIA chips have some problems, the workaround can ensure those chips
 * work reliably. Revisions >= 0x80 are part of a southbridge and appear
 * to be reliable.
 */
#define PCI_VENDOR_VIA          0x1106          /* PCI Vendor-id VIA */
#define PCI_VIA_REVISION_6212   0x80            /* VIA 6212 revision ID */

#define EHCI_VIA_LOST_INTERRUPTS        0x01
#define EHCI_VIA_ASYNC_SCHEDULE         0x02
#define EHCI_VIA_REDUCED_MAX_BULK_XFER_SIZE     0x04

#define EHCI_VIA_WORKAROUNDS \
        (EHCI_VIA_LOST_INTERRUPTS | \
        EHCI_VIA_ASYNC_SCHEDULE | \
        EHCI_VIA_REDUCED_MAX_BULK_XFER_SIZE)

#define EHCI_VIA_MAX_BULK_XFER_SIZE 0x8000 /* Maximum bulk transfer size */


/*
 * EHCI HCDI entry points
 *
 * The Host Controller Driver Interfaces (HCDI) are the software interfaces
 * between the Universal Serial Bus Driver (USBA) and the Host  Controller
 * Driver (HCD). The HCDI interfaces or entry points are subject to change.
 */
int             ehci_hcdi_pipe_open(
                                usba_pipe_handle_data_t *ph,
                                usb_flags_t             usb_flags);
int             ehci_hcdi_pipe_close(
                                usba_pipe_handle_data_t *ph,
                                usb_flags_t             usb_flags);
int             ehci_hcdi_pipe_reset(
                                usba_pipe_handle_data_t *ph,
                                usb_flags_t             usb_flags);
void            ehci_hcdi_pipe_reset_data_toggle(
                                usba_pipe_handle_data_t *ph);
int             ehci_hcdi_pipe_ctrl_xfer(
                                usba_pipe_handle_data_t *ph,
                                usb_ctrl_req_t          *ctrl_reqp,
                                usb_flags_t             usb_flags);
int             ehci_hcdi_bulk_transfer_size(
                                usba_device_t           *usba_device,
                                size_t                  *size);
int             ehci_hcdi_pipe_bulk_xfer(
                                usba_pipe_handle_data_t *ph,
                                usb_bulk_req_t          *bulk_reqp,
                                usb_flags_t             usb_flags);
int             ehci_hcdi_pipe_intr_xfer(
                                usba_pipe_handle_data_t *ph,
                                usb_intr_req_t          *intr_req,
                                usb_flags_t             usb_flags);
int             ehci_hcdi_pipe_stop_intr_polling(
                                usba_pipe_handle_data_t *ph,
                                usb_flags_t             usb_flags);
int             ehci_hcdi_get_current_frame_number(
                                usba_device_t           *usba_device,
                                usb_frame_number_t      *frame_number);
int             ehci_hcdi_get_max_isoc_pkts(
                                usba_device_t           *usba_device,
                                uint_t          *max_isoc_pkts_per_request);
int             ehci_hcdi_pipe_isoc_xfer(
                                usba_pipe_handle_data_t *ph,
                                usb_isoc_req_t          *isoc_reqp,
                                usb_flags_t             usb_flags);
int             ehci_hcdi_pipe_stop_isoc_polling(
                                usba_pipe_handle_data_t *ph,
                                usb_flags_t             usb_flags);

/*
 * EHCI Polled entry points function prototypes.
 */
int             ehci_hcdi_polled_input_init(
                                usba_pipe_handle_data_t *ph,
                                uchar_t                 **polled_buf,
                                usb_console_info_impl_t *info);
int             ehci_hcdi_polled_input_enter(
                                usb_console_info_impl_t *info);
int             ehci_hcdi_polled_read(
                                usb_console_info_impl_t *info,
                                uint_t                  *num_characters);
int             ehci_hcdi_polled_input_exit(
                                usb_console_info_impl_t *info);
int             ehci_hcdi_polled_input_fini(
                                usb_console_info_impl_t *info);
int             ehci_hcdi_polled_output_init(
                                usba_pipe_handle_data_t *ph,
                                usb_console_info_impl_t *console_output_info);
int             ehci_hcdi_polled_output_enter(
                                usb_console_info_impl_t *info);
int             ehci_hcdi_polled_write(
                                usb_console_info_impl_t *info,
                                uchar_t *buf,
                                uint_t num_characters,
                                uint_t *num_characters_written);
int             ehci_hcdi_polled_output_exit(
                                usb_console_info_impl_t *info);
int             ehci_hcdi_polled_output_fini(
                                usb_console_info_impl_t *info);
/*
 * EHCI Root Hub entry points function prototypes.
 */
int             ehci_init_root_hub(
                                ehci_state_t            *ehcip);
int             ehci_load_root_hub_driver(
                                ehci_state_t            *ehcip);
int             ehci_unload_root_hub_driver(
                                ehci_state_t            *ehcip);
int             ehci_handle_root_hub_pipe_open(
                                usba_pipe_handle_data_t *ph,
                                usb_flags_t             flags);
int             ehci_handle_root_hub_pipe_close(
                                usba_pipe_handle_data_t *ph);
int             ehci_handle_root_hub_pipe_reset(
                                usba_pipe_handle_data_t *ph,
                                usb_flags_t             flags);
int             ehci_handle_root_hub_request(
                                ehci_state_t            *ehcip,
                                usba_pipe_handle_data_t *ph,
                                usb_ctrl_req_t          *ctrl_reqp);
int             ehci_handle_root_hub_pipe_start_intr_polling(
                                usba_pipe_handle_data_t *ph,
                                usb_intr_req_t          *intr_reqp,
                                usb_flags_t             flags);
void            ehci_handle_root_hub_pipe_stop_intr_polling(
                                usba_pipe_handle_data_t *ph,
                                usb_flags_t             flags);

/*
 * EHCI Interrupt Handler entry point.
 */
uint_t          ehci_intr(caddr_t                       arg1,
                                caddr_t                 arg2);

#ifdef __cplusplus
}
#endif

#endif /* _SYS_USB_EHCID_H */