root/usr/src/uts/common/sys/1394/adapters/hci1394_ohci.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 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_1394_ADAPTERS_HCI1394_OHCI_H
#define _SYS_1394_ADAPTERS_HCI1394_OHCI_H

/*
 * hci1394_ohci.h
 *    Provides access macros and routines to the OpenHCI HW.
 */

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/ddi.h>
#include <sys/modctl.h>
#include <sys/sunddi.h>
#include <sys/types.h>
#include <sys/note.h>

#include <sys/1394/adapters/hci1394_def.h>
#include <sys/1394/adapters/hci1394_buf.h>


#define OHCI_MAX_SELFID_SIZE            2048
#define OHCI_BUSGEN_MAX                 0xFF


/* Misc */
#define OHCI_REG_SET                    1       /* ddi_regs_map_setup */
#define OHCI_CHIP_RESET_TIME_IN_uSEC    ((clock_t)100)    /* 100uS */
#define OHCI_BUS_RESET_TIME_IN_uSEC     ((clock_t)100000) /* 100mS */
#define OHCI_MAX_COOKIE                 16
#define OHCI_uS_PER_BUS_CYCLE           125
#define OHCI_nS_PER_BUS_CYCLE           125000
#define OHCI_BUS_CYCLE_TO_uS(cycles)    (cycles * OHCI_uS_PER_BUS_CYCLE)
#define OHCI_BUS_CYCLE_TO_nS(cycles)    (cycles * OHCI_nS_PER_BUS_CYCLE)
#define OHCI_CYCLE_SEC_SHIFT            13
#define OHCI_CYCLE_SEC_MASK             0xE000
#define OHCI_CYCLE_CNT_MASK             0x1FFF
#define OHCI_MAX_CYCLE_CNT              8000
#define OHCI_TIMESTAMP_MASK             0xFFFF
#define OHCI_REG_ADDR_MASK              0x7FC

/* OpenHCI Global Swap location in PCI space */
#define OHCI_PCI_HCI_CONTROL_REG        ((off_t)0x40)
#define OHCI_PCI_GLOBAL_SWAP            0x00000001


/* PHY Register #1 */
#define OHCI_PHY_RHB                    0x80
#define OHCI_PHY_IBR                    0x40
#define OHCI_PHY_MAX_GAP                0x3F

/* PHY Register #4 */
#define OHCI_PHY_EXTND_MASK             0xE0
#define OHCI_PHY_EXTND                  0xE0

/* PHY Register #4 */
#define OHCI_PHY_CNTDR                  0x40

/* PHY Register #5 */
#define OHCI_PHY_ISBR                   0x40
#define OHCI_PHY_LOOP_ERR               0x20
#define OHCI_PHY_PWRFAIL_ERR            0x10
#define OHCI_PHY_TIMEOUT_ERR            0x08
#define OHCI_PHY_PORTEVT_ERR            0x04
#define OHCI_PHY_ENBL_ACCEL             0x02
#define OHCI_PHY_ENBL_MULTI             0x01

/* OpenHCI Event Codes.  Refer to OHCI 1.0 section 3.1.1 */
#define OHCI_EVT_NO_STATUS              0x0
#define OHCI_EVT_LONG_PACKET            0x2
#define OHCI_EVT_MISSING_ACK            0x3
#define OHCI_EVT_UNDERRUN               0x4
#define OHCI_EVT_OVERRUN                0x5
#define OHCI_EVT_DESCRIPTOR_READ        0x6
#define OHCI_EVT_DATA_READ              0x7
#define OHCI_EVT_DATA_WRITE             0x8
#define OHCI_EVT_BUS_RESET              0x9
#define OHCI_EVT_TIMEOUT                0xA
#define OHCI_EVT_TCODE_ERR              0xB
#define OHCI_EVT_UNKNOWN                0xE
#define OHCI_EVT_FLUSHED                0xF
#define OHCI_ACK_COMPLETE               0x11
#define OHCI_ACK_PENDING                0x12
#define OHCI_ACK_BUSY_X                 0x14
#define OHCI_ACK_BUSY_A                 0x15
#define OHCI_ACK_BUSY_B                 0x16
#define OHCI_ACK_TARDY                  0x1B
#define OHCI_ACK_CONFLICT_ERROR         0x1C
#define OHCI_ACK_DATA_ERROR             0x1D
#define OHCI_ACK_TYPE_ERROR             0x1E
#define OHCI_ACK_ADDRESS_ERROR          0x1F

#define OHCI_REG_NODEID_ROOT            0x40000000
#define OHCI_REG_BUSOPTIONS_CMC         0x40000000

/* hci_regs_s.ir_ctxt_regs.ctxt_match */
#define OHCI_MTC_TAG3_MASK              0x80000000
#define OHCI_MTC_TAG3_SHIFT             31
#define OHCI_MTC_TAG2_MASK              0x40000000
#define OHCI_MTC_TAG2_SHIFT             30
#define OHCI_MTC_TAG1_MASK              0x20000000
#define OHCI_MTC_TAG1_SHIFT             29
#define OHCI_MTC_TAG0_MASK              0x10000000
#define OHCI_MTC_TAG0_SHIFT             28
#define OHCI_MTC_MATCH_MASK             0x07FFF000
#define OHCI_MTC_MATCH_SHIFT            12
#define OHCI_MTC_SYNC_MASK              0x00000F00
#define OHCI_MTC_SYNC_SHIFT             8
#define OHCI_MTC_TAG1SY_MASK            0x00000040
#define OHCI_MTC_TAG1SY_SHIFT           6
#define OHCI_MTC_CHAN_MASK              0x0000003F
#define OHCI_MTC_CHAN_SHIFT             0

/* hci_regs_s.self_id_buflo - See OpenHCI 1.00 section 11.1 */
#define OHCI_SLF_BUF_LO                 0xFFFFF800

/* hci_regs_s.self_id_count - See OpenHCI 1.00 section 11.2 */
#define OHCI_SLFC_ERROR                 0x80000000
#define OHCI_SLFC_GEN_MASK              0x00FF0000
#define OHCI_SLFC_GEN_SHIFT             16
#define OHCI_SLFC_NUM_QUADS_MASK        0x00001FFC


/*
 * hci_regs_s.int_event_* and hci_regs_s.int_mask_*
 * See OpenHCI 1.00 section 6
 */
#define OHCI_INTR_REQ_TX_CMPLT          0x00000001
#define OHCI_INTR_RESP_TX_CMPLT         0x00000002
#define OHCI_INTR_ARRQ                  0x00000004
#define OHCI_INTR_ARRS                  0x00000008
#define OHCI_INTR_RQPKT                 0x00000010
#define OHCI_INTR_RSPKT                 0x00000020
#define OHCI_INTR_ISOCH_TX              0x00000040      /* RO */
#define OHCI_INTR_ISOCH_RX              0x00000080      /* RO */
#define OHCI_INTR_POST_WR_ERR           0x00000100
#define OHCI_INTR_LOCK_RESP_ERR         0x00000200
#define OHCI_INTR_SELFID_CMPLT          0x00010000
#define OHCI_INTR_BUS_RESET             0x00020000
#define OHCI_INTR_PHY                   0x00080000
#define OHCI_INTR_CYC_SYNCH             0x00100000
#define OHCI_INTR_CYC_64_SECS           0x00200000
#define OHCI_INTR_CYC_LOST              0x00400000
#define OHCI_INTR_CYC_INCONSISTENT      0x00800000
#define OHCI_INTR_UNRECOVERABLE_ERR     0x01000000
#define OHCI_INTR_CYC_TOO_LONG          0x02000000
#define OHCI_INTR_PHY_REG_RCVD          0x04000000
#define OHCI_INTR_VENDOR_SPECIFIC       0x40000000
#define OHCI_INTR_MASTER_INTR_ENBL      0x80000000      /* int_mask_* only */

/* hci_regs_s.fairness_ctrl - See OpenHCI 1.00 section 5.8 */
#define OHCI_FAIR_PRI_REQ               0x000000FF

/* hci_regs_s.link_ctrl_set/clr - See OpenHCI 1.00 section 5.9 */
#define OHCI_LC_CYC_SRC                 0x00400000
#define OHCI_LC_CYC_MAST                0x00200000
#define OHCI_LC_CTIME_ENBL              0x00100000
#define OHCI_LC_RCV_PHY                 0x00000400
#define OHCI_LC_RCV_SELF                0x00000200
#define OHCI_LC_CYC_SYNC                0x00000010

/* Defines for registers in HCI register space */
/* Note: bits are read/write unless otherwise noted (RO-read only) */

/* hci_regs_s.version - See OpenHCI 1.00 section 5.2 */
#define OHCI_VER_GUID_ROM               0x01000000
#define OHCI_VER_VERSION_MASK           0x00FF0000
#define OHCI_VER_VERSION_SHIFT          16
#define OHCI_VER_REVISION_MASK          0x000000FF
#define OHCI_VERSION(version) \
        ((version & OHCI_VER_VERSION_MASK) >> OHCI_VER_VERSION_SHIFT)
#define OHCI_REVISION(revision) \
        (revision & OHCI_VER_REVISION_MASK)

/* hci_regs_s.guid_rom - See OpenHCI 1.00 section 5.3 */
#define OHCI_GROM_ADDR_RESET            0x80000000      /* 1-initiate reset */
#define OHCI_GROM_RD_START              0x02000000      /* 1-start byte read */
#define OHCI_GROM_RD_DATA               0x00FF0000      /* RO */

/* hci_regs_s.at_retries - See OpenHCI 1.00 section 5.4 */
#define OHCI_RET_SECLIM_MASK            0xE0000000      /* dual-phase retry */
#define OHCI_RET_SECLIM_SHIFT           29
#define OHCI_RET_CYCLLIM_MASK           0xFFFF0000      /* dual-phase retry */
#define OHCI_RET_CYCLLIM_SHIFT          16
#define OHCI_RET_MAX_PHYS_RESP_MASK     0x00000F00      /* physical resp rtry */
#define OHCI_RET_MAX_PHYS_RESP_SHIFT    8
#define OHCI_RET_MAX_ATRESP_MASK        0x000000F0      /* AT response retry */
#define OHCI_RET_MAX_ATRESP_SHIFT       4
#define OHCI_RET_MAX_ATREQ_MASK         0x0000000F      /* AT request retry */
#define OHCI_RET_MAX_ATREQ_SHIFT        0

/* hci_regs_s.csr_ctrl - See OpenHCI 1.00 section 5.5.1 */
#define OHCI_CSR_DONE           0x80000000      /* RO 1-cmp_swap complete */
#define OHCI_CSR_SELECT         0x00000003

#define OHCI_CSR_SEL_BUS_MGR_ID         0       /* bus manager ID register */
#define OHCI_CSR_SEL_BANDWIDTH_AVAIL    1       /* bandwidth available reg */
#define OHCI_CSR_SEL_CHANS_AVAIL_HI     2       /* channels_available_hi reg */
#define OHCI_CSR_SEL_CHANS_AVAIL_LO     3       /* channels_available_lo reg */

/* hci_regs_s.config_rom_hdr - See OpenHCI 1.00 section 5.5.6 */
#define OHCI_CROM_INFO_LEN      0xFF000000
#define OHCI_CROM_CRC_LEN       0x00FF0000
#define OHCI_CROM_ROM_CRC_VAL   0x0000FFFF

/* hci_regs_s.bus_options - See OpenHCI 1.00 section 5.5.4 */
#define OHCI_BOPT_IRMC          0x80000000      /* Isoch resrce mgr capable */
#define OHCI_BOPT_CMC           0x40000000      /* cycle master capable */
#define OHCI_BOPT_ISC           0x20000000      /* isochronous data capable */
#define OHCI_BOPT_BMC           0x10000000      /* bus manager capable */
#define OHCI_BOPT_PMC           0x80000000      /* power manager capable */
#define OHCI_BOPT_CYC_CLK_ACC   0x00FF0000
#define OHCI_BOPT_MAX_REC       0x0000F000
#define OHCI_BOPT_GEN           0x000000C0
#define OHCI_BOPT_LINK_SPD      0x00000007

/* hci_regs_s.guid_hi - See OpenHCI 1.00 section 5.5.5 */
#define OHCI_GUID_NODE_VENDOR_ID        0xFFFFFF00
#define OHCI_GUID_CHIP_ID_HI            0x000000FF

/* hci_regs_s.config_rom_maplo - See OpenHCI 1.00 section 5.5.6 */
#define OHCI_CMAP_ADDR                  0xFFFFFF00      /* 1k aligned */

/* hci_regs_s.posted_write_addrhi - See OpenHCI 1.00 section 13.2.8.1 */
#define OHCI_POST_SOURCE_ID             0xFFFF0000
#define OHCI_POST_OFFSET_HI             0x0000FFFF

/* hci_regs_s.vendor_id - See OpenHCI 1.00 section 5.2 */
#define OHCI_VEND_ID                    0x00FFFFFF
#define OHCI_VEND_UNIQUE                0xFF000000

/* hci_regs_s.hc_ctrl_set/clr - See OpenHCI 1.00 section 5.7 */
#define OHCI_HC_NO_BSWAP        0x40000000      /* 1-big endian,0-little end */
#define OHCI_HC_PROG_PHY_ENBL   0x00800000      /* 1-prog phy capabilities */
#define OHCI_HC_APHY_ENBL       0x00040000      /* 1-Aphy enhancements enbld */
#define OHCI_HC_LPS             0x00080000      /* 1-link pwr on, 0-off */
#define OHCI_HC_POSTWR_ENBL     0x00040000      /* 1-enabled, 0-disabled */
#define OHCI_HC_LINK_ENBL       0x00020000      /* 1-enabled, 0-disabled */
#define OHCI_HC_SOFT_RESET      0x00010000      /* 1-reset in prog, 0-done */

/* hci_regs_s.node_id - See OpenHCI 1.00 section 5.10 */
#define OHCI_NDID_IDVALID               0x80000000
#define OHCI_NDID_ROOT_MASK             0x40000000
#define OHCI_NDID_ROOT_SHIFT            30
#define OHCI_NDID_CPS_MASK              0x08000000
#define OHCI_NDID_CPS_SHIFT             27
#define OHCI_NDID_BUSNUM_MASK           0x0000FFC0
#define OHCI_NDID_BUSNUM_SHIFT          6
#define OHCI_NDID_NODENUM_MASK          0x0000003F
#define OHCI_NDID_NODENUM_SHIFT         0

/* hci_regs_s.phy_ctrl - See OpenHCI 1.00 section 5.11, 1394-1994 J.4.1 */
#define OHCI_PHYC_RDDONE                0x80000000
#define OHCI_PHYC_RDREG                 0x00008000
#define OHCI_PHYC_WRREG                 0x00004000
#define OHCI_PHYC_RDADDR_MASK           0x0F000000
#define OHCI_PHYC_RDADDR_SHIFT          24
#define OHCI_PHYC_RDDATA_MASK           0x00FF0000
#define OHCI_PHYC_RDDATA_SHIFT          16
#define OHCI_PHYC_REGADDR_MASK          0x00000F00
#define OHCI_PHYC_REGADDR_SHIFT         8
#define OHCI_PHYC_WRDATA_MASK           0x000000FF
#define OHCI_PHYC_WRDATA_SHIFT          0

/* hci_regs_s.context_ctrl -- several contexts */
#define OHCI_CC_RUN_MASK                0x00008000
#define OHCI_CC_RUN_SHIFT               15
#define OHCI_CC_WAKE_MASK               0x00001000
#define OHCI_CC_WAKE_SHIFT              12
#define OHCI_CC_DEAD_MASK               0x00000800
#define OHCI_CC_DEAD_SHIFT              11
#define OHCI_CC_ACTIVE_MASK             0x00000400
#define OHCI_CC_ACTIVE_SHIFT            10

#define OHCI_CC_SPD_MASK                0x000000E0
#define OHCI_CC_SPD_SHIFT               5
#define OHCI_CC_EVT_MASK                0x0000001F
#define OHCI_CC_EVT_SHIFT               0

/* hci_regs context_ctrl for IR */
#define OHCI_IRCTL_BFILL_MASK           0x80000000
#define OHCI_IRCTL_BFILL_SHIFT          31
#define OHCI_IRCTL_IHDR_MASK            0x40000000
#define OHCI_IRCTL_IHDR_SHIFT           30
#define OHCI_IRCTL_MTC_ENBL_MASK        0x20000000
#define OHCI_IRCTL_MTC_ENBL_SHIFT       29
#define OHCI_IRCTL_MULTI_MASK           0x10000000
#define OHCI_IRCTL_MULTI_SHIFT          28

/* hci_regs context_ctrl for IT */
#define OHCI_ITCTL_MTC_ENBL_MASK        0x80000000
#define OHCI_ITCTL_MTC_ENBL_SHIFT       31
#define OHCI_ITCTL_MATCH_MASK           0x7FFF0000
#define OHCI_ITCTL_MATCH_SHIFT          16


#define HCI1394_IS_ARRESP(tcode) \
        ((tcode == IEEE1394_TCODE_WRITE_RESP) || \
        (tcode == IEEE1394_TCODE_READ_QUADLET_RESP) || \
        (tcode == IEEE1394_TCODE_READ_BLOCK_RESP) || \
        (tcode == IEEE1394_TCODE_LOCK_RESP))

#define HCI1394_IS_ARREQ(tcode) \
        ((tcode == IEEE1394_TCODE_READ_QUADLET) || \
        (tcode == IEEE1394_TCODE_WRITE_QUADLET) || \
        (tcode == IEEE1394_TCODE_READ_BLOCK) || \
        (tcode == IEEE1394_TCODE_WRITE_BLOCK) || \
        (tcode == IEEE1394_TCODE_LOCK) || \
        (tcode == IEEE1394_TCODE_PHY))

#define HCI1394_IRCTXT_CTRL_SET(HCIP, I, BFFILL, IHDR, MATCHENBL, MULTI, RUN, \
        WAKE)   (ddi_put32((HCIP)->ohci->ohci_reg_handle, \
        &(HCIP)->ohci->ohci_regs->ir[(I)].ctxt_ctrl_set, \
        0 | (((BFFILL) << OHCI_IRCTL_BFILL_SHIFT) & OHCI_IRCTL_BFILL_MASK) | \
        (((IHDR) << OHCI_IRCTL_IHDR_SHIFT) & OHCI_IRCTL_IHDR_MASK) | \
        (((MATCHENBL) << OHCI_IRCTL_MTC_ENBL_SHIFT) & \
            OHCI_IRCTL_MTC_ENBL_MASK) | \
        (((MULTI) << OHCI_IRCTL_MULTI_SHIFT) & OHCI_IRCTL_MULTI_MASK) | \
        (((RUN) << OHCI_CC_RUN_SHIFT) & OHCI_CC_RUN_MASK) | \
        (((WAKE) << OHCI_CC_WAKE_SHIFT) & OHCI_CC_WAKE_MASK)))

#define HCI1394_IRCTXT_CTRL_CLR(HCIP, I, BFFILL, IHDR, MATCHENBL, MULTI, RUN) \
        (ddi_put32((HCIP)->ohci->ohci_reg_handle, \
        &(HCIP)->ohci->ohci_regs->ir[(I)].ctxt_ctrl_clr, \
        0 | (((BFFILL) << OHCI_IRCTL_BFILL_SHIFT) & OHCI_IRCTL_BFILL_MASK) | \
        (((IHDR) << OHCI_IRCTL_IHDR_SHIFT) & OHCI_IRCTL_IHDR_MASK) | \
        (((MATCHENBL) << OHCI_IRCTL_MTC_ENBL_SHIFT) & \
            OHCI_IRCTL_MTC_ENBL_MASK) | \
        (((MULTI) << OHCI_IRCTL_MULTI_SHIFT) & OHCI_IRCTL_MULTI_MASK) | \
        (((RUN) << OHCI_CC_RUN_SHIFT) & OHCI_CC_RUN_MASK)))

#define HCI1394_ITCTXT_CTRL_SET(HCIP, I, MATCHENBL, MATCH, RUN, WAKE) \
        (ddi_put32((HCIP)->ohci->ohci_reg_handle, \
        &(HCIP)->ohci->ohci_regs->it[(I)].ctxt_ctrl_set, 0 | \
        (((MATCHENBL) << OHCI_ITCTL_MTC_ENBL_SHIFT) & \
            OHCI_ITCTL_MTC_ENBL_MASK) | \
        (((MATCH) << OHCI_ITCTL_MATCH_SHIFT) & OHCI_ITCTL_MATCH_MASK) | \
        (((RUN) << OHCI_CC_RUN_SHIFT) & OHCI_CC_RUN_MASK) | \
        (((WAKE) << OHCI_CC_WAKE_SHIFT) & OHCI_CC_WAKE_MASK)))

#define HCI1394_ITCTXT_CTRL_CLR(HCIP, I, MATCHENBL, MATCH, RUN) \
        (ddi_put32((HCIP)->ohci->ohci_reg_handle, \
        &(HCIP)->ohci->ohci_regs->it[(I)].ctxt_ctrl_clr, 0 | \
        (((MATCHENBL) << OHCI_ITCTL_MTC_ENBL_SHIFT) & \
            OHCI_ITCTL_MTC_ENBL_MASK) | \
        (((MATCH) << OHCI_ITCTL_MATCH_SHIFT) & OHCI_ITCTL_MATCH_MASK) | \
        (((RUN) << OHCI_CC_RUN_SHIFT) & OHCI_CC_RUN_MASK)))


#define HCI1394_IRCTXT_MATCH_WRITE(HCIP, I, TAG3, TAG2, TAG1, TAG0, MATCH, \
        SYNC, TAG1SYNC, CHAN)   (ddi_put32((HCIP)->ohci->ohci_reg_handle, \
        &(HCIP)->ohci->ohci_regs->ir[(I)].ctxt_match, 0 | \
        (((TAG3) << OHCI_MTC_TAG3_SHIFT) & OHCI_MTC_TAG3_MASK) | \
        (((TAG2) << OHCI_MTC_TAG2_SHIFT) & OHCI_MTC_TAG2_MASK) | \
        (((TAG1) << OHCI_MTC_TAG1_SHIFT) & OHCI_MTC_TAG1_MASK) | \
        (((TAG0) << OHCI_MTC_TAG0_SHIFT) & OHCI_MTC_TAG0_MASK) | \
        (((MATCH) << OHCI_MTC_MATCH_SHIFT) & OHCI_MTC_MATCH_MASK) | \
        (((SYNC) << OHCI_MTC_SYNC_SHIFT) & OHCI_MTC_SYNC_MASK) | \
        (((TAG1SYNC) << OHCI_MTC_TAG1SY_SHIFT) & OHCI_MTC_TAG1SY_MASK) | \
        (((CHAN) << OHCI_MTC_CHAN_SHIFT) & OHCI_MTC_CHAN_MASK)))

#define HCI1394_ISOCH_CTXT_ACTIVE(SOFTSTATEP, CTXTP) \
        (ddi_get32((SOFTSTATEP)->ohci->ohci_reg_handle, \
        &(CTXTP)->ctxt_regsp->ctxt_ctrl_set) & OHCI_CC_ACTIVE_MASK)

#define HCI1394_ISOCH_CTXT_RUN(SOFTSTATEP, CTXTP) \
        (ddi_get32((SOFTSTATEP)->ohci->ohci_reg_handle, \
        &(CTXTP)->ctxt_regsp->ctxt_ctrl_set) & OHCI_CC_RUN_MASK)

#define HCI1394_ISOCH_CTXT_CMD_PTR(SOFTSTATEP, CTXTP) \
        (ddi_get32((SOFTSTATEP)->ohci->ohci_reg_handle, \
        &(CTXTP)->ctxt_regsp->cmd_ptrlo))

/*
 * 1394 OpenHCI 1.0 general context register layout
 *    All contexts except for Isoch Receive have the following layout
 *    See the OpenHCI v1.0 specification for register definitions.
 */
typedef struct hci1394_ctxt_regs_s {
        uint32_t        ctxt_ctrl_set;
        uint32_t        ctxt_ctrl_clr;
        uint32_t        reserved;
        uint32_t        cmd_ptrlo;
} hci1394_ctxt_regs_t;

/*
 * 1394 OpenHCI 1.0 Isochronous Receive context register layout
 *    See the OpenHCI v1.0 specification for register definitions.
 */
typedef struct hci1394_ir_ctxt_regs_s {
        uint32_t        ctxt_ctrl_set;
        uint32_t        ctxt_ctrl_clr;
        uint32_t        reserved0;
        uint32_t        cmd_ptrlo;
        uint32_t        ctxt_match;
        uint32_t        reserved1[3];
} hci1394_ir_ctxt_regs_t;

/*
 * 1394 OpenHCI 1.0 registers
 *    See the OpenHCI v1.0 specification for register definitions.
 */
typedef struct hci1394_regs_s {
        uint32_t                version;
        uint32_t                guid_rom;
        uint32_t                at_retries;
        uint32_t                csr_data;
        uint32_t                csr_compare_data;
        uint32_t                csr_ctrl;
        uint32_t                config_rom_hdr;
        uint32_t                bus_id;
        uint32_t                bus_options;
        uint32_t                guid_hi;
        uint32_t                guid_lo;
        uint32_t                reserved01;
        uint32_t                reserved02;
        uint32_t                config_rom_maplo;
        uint32_t                posted_write_addrlo;
        uint32_t                posted_write_addrhi;
        uint32_t                vendor_id;
        uint32_t                reserved03[3];
        uint32_t                hc_ctrl_set;
        uint32_t                hc_ctrl_clr;
        uint32_t                reserved06[2];
        uint32_t                reserved08;
        uint32_t                self_id_buflo;
        uint32_t                self_id_count;
        uint32_t                reserved09;
        uint32_t                ir_multi_maskhi_set;
        uint32_t                ir_multi_maskhi_clr;
        uint32_t                ir_multi_masklo_set;
        uint32_t                ir_multi_masklo_clr;
        uint32_t                intr_event_set;
        uint32_t                intr_event_clr;
        uint32_t                intr_mask_set;
        uint32_t                intr_mask_clr;
        uint32_t                it_intr_event_set;
        uint32_t                it_intr_event_clr;
        uint32_t                it_intr_mask_set;
        uint32_t                it_intr_mask_clr;
        uint32_t                ir_intr_event_set;
        uint32_t                ir_intr_event_clr;
        uint32_t                ir_intr_mask_set;
        uint32_t                ir_intr_mask_clr;
        uint32_t                reserved10[11];
        uint32_t                fairness_ctrl;
        uint32_t                link_ctrl_set;
        uint32_t                link_ctrl_clr;
        uint32_t                node_id;
        uint32_t                phy_ctrl;
        uint32_t                isoch_cycle_timer;
        uint32_t                reserved21[3];
        uint32_t                ar_req_filterhi_set;
        uint32_t                ar_req_filterhi_clr;
        uint32_t                ar_req_filterlo_set;
        uint32_t                ar_req_filterlo_clr;
        uint32_t                phys_req_filterhi_set;
        uint32_t                phys_req_filterhi_clr;
        uint32_t                phys_req_filterlo_set;
        uint32_t                phys_req_filterlo_clr;
        uint32_t                phys_upper_bound;
        uint32_t                reserved24[23];
        hci1394_ctxt_regs_t     at_req;
        uint32_t                reserved47[4];
        hci1394_ctxt_regs_t     at_resp;
        uint32_t                reserved51[4];
        hci1394_ctxt_regs_t     ar_req;
        uint32_t                reserved55[4];
        hci1394_ctxt_regs_t     ar_resp;
        uint32_t                reserved59[4];
        hci1394_ctxt_regs_t     it[HCI1394_MAX_ISOCH_CONTEXTS];
        hci1394_ir_ctxt_regs_t  ir[HCI1394_MAX_ISOCH_CONTEXTS];
} hci1394_regs_t;


/* private structure to keep track of OpenHCI */
typedef struct hci1394_ohci_s {
        /* config ROM and selfid buffers */
        hci1394_buf_handle_t    ohci_cfgrom_handle;
        hci1394_buf_handle_t    ohci_selfid_handle;

        /*
         * Phy register #1 cached settings.  These are only used for 1394-1995
         * phy's.  When setting the root holdoff bit and gap count in 1394,
         * you send out a PHY configuration packet.  The 1995 PHY's will
         * not look at the PHY packet if we sent it out which means we have
         * to write directly to PHY register 1.  This creates some ugly race
         * conditions.  Since we will be following up these settings with a bus
         * reset shortly, we "cache" them until we generate the bus reset. This
         * solution is not perfect, but it is the best of a bad thing.
         */
        boolean_t               ohci_set_root_holdoff;
        boolean_t               ohci_set_gap_count;
        uint_t                  ohci_gap_count;

        /*
         * The bus time is kept using the cycle timer and then counting the
         * rollovers via the cycle 64 seconds interrupt. (NOTE: every 2
         * interrupts is one rollover)  We do not wish to be interrupting
         * the CPU if there is nothing plugged into the bus (since bus time
         * really isn't used for anything yet (maybe when bridges come out?)).
         * We will start with the interrupt disabled, if the bus master writes
         * to the CSR bus time register, we will enable the interrupt.  These
         * fields keep track of the rollover and whether or not the interrupt
         * is enabled.
         */
        volatile uint_t         ohci_bustime_count;
        boolean_t               ohci_bustime_enabled;

        /* whether we have a 1394-1995 or 1394A phy */
        h1394_phy_t             ohci_phy;

        /* General Driver Info */
        hci1394_drvinfo_t       *ohci_drvinfo;

        /*
         * self id buffer and config rom info.  These are towards bottom of the
         * structure to make debugging easier.
         */
        hci1394_buf_info_t      ohci_selfid;
        hci1394_buf_info_t      ohci_cfgrom;

        /* OpenHCI registers */
        ddi_acc_handle_t        ohci_reg_handle;
        hci1394_regs_t          *ohci_regs;

        /*
         * This mutex is used to protect "atomic" operations to the OpenHCI
         * hardware.  This includes reads and writes to the PHY, cswap
         * operations to the HW implemented CSR registers, and any read/modify/
         * write operations such as updating atreq retries.
         */
        kmutex_t                ohci_mutex;

        hci1394_state_t         *soft_state;
} hci1394_ohci_t;

_NOTE(SCHEME_PROTECTS_DATA("Single thread modifies", \
        hci1394_ohci_s::ohci_bustime_count \
        hci1394_ohci_s::ohci_bustime_enabled \
        hci1394_ohci_s::ohci_gap_count \
        hci1394_ohci_s::ohci_set_gap_count \
        hci1394_ohci_s::ohci_set_root_holdoff))

/* handle passed back from init() and used for rest of functions */
typedef hci1394_ohci_t *hci1394_ohci_handle_t;


int hci1394_ohci_init(hci1394_state_t *soft_state, hci1394_drvinfo_t *drvinfo,
    hci1394_ohci_handle_t *ohci_hdl);
void hci1394_ohci_fini(hci1394_ohci_handle_t *ohci_hdl);

void hci1394_ohci_reg_read(hci1394_ohci_handle_t ohci_hdl, uint_t offset,
    uint32_t *data);
void hci1394_ohci_reg_write(hci1394_ohci_handle_t ohci_hdl, uint_t offset,
    uint32_t data);
int hci1394_ohci_phy_init(hci1394_ohci_handle_t ohci_hdl);
int hci1394_ohci_phy_set(hci1394_ohci_handle_t ohci_hdl, uint_t regAddr,
    uint_t bits);
int hci1394_ohci_phy_clr(hci1394_ohci_handle_t ohci_hdl, uint_t regAddr,
    uint_t bits);
int hci1394_ohci_phy_read(hci1394_ohci_handle_t ohci_hdl, uint_t regAddr,
    uint_t *rdData);
int hci1394_ohci_phy_write(hci1394_ohci_handle_t ohci_hdl, uint_t regAddr,
    uint_t wrData);
int hci1394_ohci_phy_info(hci1394_ohci_handle_t ohci_hdl, uint32_t *info);
void hci1394_ohci_intr_master_enable(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_intr_master_disable(hci1394_ohci_handle_t ohci_hdl);
uint32_t hci1394_ohci_intr_asserted(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_intr_enable(hci1394_ohci_handle_t ohci_hdl,
    uint32_t intr_mask);
void hci1394_ohci_intr_disable(hci1394_ohci_handle_t ohci_hdl,
    uint32_t intr_mask);
void hci1394_ohci_intr_clear(hci1394_ohci_handle_t ohci_hdl,
    uint32_t intr_mask);
uint32_t hci1394_ohci_it_intr_asserted(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_it_intr_enable(hci1394_ohci_handle_t ohci_hdl,
    uint32_t intr_mask);
void hci1394_ohci_it_intr_disable(hci1394_ohci_handle_t ohci_hdl,
    uint32_t intr_mask);
void hci1394_ohci_it_intr_clear(hci1394_ohci_handle_t ohci_hdl,
    uint32_t intr_mask);
int hci1394_ohci_it_ctxt_count_get(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_it_cmd_ptr_set(hci1394_ohci_handle_t ohci_hdl,
    uint_t context_number, uint32_t io_addr);
uint32_t hci1394_ohci_ir_intr_asserted(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_ir_intr_enable(hci1394_ohci_handle_t ohci_hdl,
    uint32_t intr_mask);
void hci1394_ohci_ir_intr_disable(hci1394_ohci_handle_t ohci_hdl,
    uint32_t intr_mask);
void hci1394_ohci_ir_intr_clear(hci1394_ohci_handle_t ohci_hdl,
    uint32_t intr_mask);
int hci1394_ohci_ir_ctxt_count_get(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_ir_cmd_ptr_set(hci1394_ohci_handle_t ohci_hdl,
    uint_t context_number, uint32_t io_addr);
void hci1394_ohci_link_enable(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_link_disable(hci1394_ohci_handle_t ohci_hdl);
uint_t hci1394_ohci_current_busgen(hci1394_ohci_handle_t ohci_hdl);
int hci1394_ohci_soft_reset(hci1394_ohci_handle_t ohci_hdl);
int hci1394_ohci_startup(hci1394_ohci_handle_t ohci_hdl);
uint64_t hci1394_ohci_guid(hci1394_ohci_handle_t ohci_hdl);
int hci1394_ohci_csr_read(hci1394_ohci_handle_t ohci_hdl, uint_t offset,
    uint32_t *data);
int hci1394_ohci_csr_cswap(hci1394_ohci_handle_t ohci_hdl, uint_t generation,
    uint_t offset, uint32_t compare, uint32_t swap, uint32_t *old);
int hci1394_ohci_bus_reset(hci1394_ohci_handle_t ohci_hdl);
int hci1394_ohci_bus_reset_nroot(hci1394_ohci_handle_t ohci_hdl);
int hci1394_ohci_bus_reset_short(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_postwr_addr(hci1394_ohci_handle_t ohci_hdl, uint64_t *addr);
int hci1394_ohci_contender_enable(hci1394_ohci_handle_t ohci_hdl);
int hci1394_ohci_root_holdoff_enable(hci1394_ohci_handle_t ohci_hdl);
int hci1394_ohci_gap_count_set(hci1394_ohci_handle_t ohci_hdl,
    uint_t gap_count);
int hci1394_ohci_phy_filter_set(hci1394_ohci_handle_t ohci_hdl,
    uint64_t mask, uint_t generation);
int hci1394_ohci_phy_filter_clr(hci1394_ohci_handle_t ohci_hdl,
    uint64_t mask, uint_t generation);
void hci1394_ohci_cfgrom_update(hci1394_ohci_handle_t ohci_hdl,
    void *local_buf, uint_t quadlet_count);
void hci1394_ohci_selfid_enable(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_selfid_read(hci1394_ohci_handle_t ohci_hdl, uint_t offset,
    uint32_t *data);
void hci1394_ohci_selfid_info(hci1394_ohci_handle_t ohci_hdl, uint_t *busgen,
    uint_t *size, boolean_t *error);
boolean_t hci1394_ohci_selfid_buf_current(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_selfid_sync(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_nodeid_set(hci1394_ohci_handle_t ohci_hdl, uint_t nodeid);
void hci1394_ohci_nodeid_get(hci1394_ohci_handle_t ohci_hdl, uint_t *nodeid);
void hci1394_ohci_nodeid_info(hci1394_ohci_handle_t ohci_hdl,
    uint_t *nodeid, boolean_t *error);
void hci1394_ohci_cycletime_get(hci1394_ohci_handle_t ohci_hdl,
    uint32_t *cycle_time);
void hci1394_ohci_cycletime_set(hci1394_ohci_handle_t ohci_hdl,
    uint32_t cycle_time);
void hci1394_ohci_bustime_get(hci1394_ohci_handle_t ohci_hdl,
    uint32_t *bus_time);
void hci1394_ohci_bustime_set(hci1394_ohci_handle_t ohci_hdl,
    uint32_t bus_time);
void hci1394_ohci_atreq_retries_get(hci1394_ohci_handle_t ohci_hdl,
    uint_t *atreq_retries);
void hci1394_ohci_atreq_retries_set(hci1394_ohci_handle_t ohci_hdl,
    uint_t atreq_retries);
void hci1394_ohci_isr_cycle64seconds(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_isr_phy(hci1394_ohci_handle_t ohci_hdl);
boolean_t hci1394_ohci_root_check(hci1394_ohci_handle_t ohci_hdl);
boolean_t hci1394_ohci_cmc_check(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_cycle_master_enable(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_cycle_master_disable(hci1394_ohci_handle_t ohci_hdl);
int hci1394_ohci_resume(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_bus_capabilities(hci1394_ohci_handle_t ohci_hdl,
    uint32_t *bus_capabilities);
boolean_t hci1394_ohci_at_active(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_atreq_start(hci1394_ohci_handle_t ohci_hdl,
    uint32_t cmdptr);
void hci1394_ohci_atreq_wake(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_atreq_stop(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_arresp_start(hci1394_ohci_handle_t ohci_hdl,
    uint32_t cmdptr);
void hci1394_ohci_arresp_wake(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_arresp_stop(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_arreq_start(hci1394_ohci_handle_t ohci_hdl,
    uint32_t cmdptr);
void hci1394_ohci_arreq_wake(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_arreq_stop(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_atresp_start(hci1394_ohci_handle_t ohci_hdl,
    uint32_t cmdptr);
void hci1394_ohci_atresp_wake(hci1394_ohci_handle_t ohci_hdl);
void hci1394_ohci_atresp_stop(hci1394_ohci_handle_t ohci_hdl);


#ifdef __cplusplus
}
#endif

#endif  /* _SYS_1394_ADAPTERS_HCI1394_OHCI_H */