root/usr/src/uts/common/sys/sata/adapters/si3124/si3124reg.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) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
 */

#ifndef _SI3124REG_H
#define _SI3124REG_H

#ifdef  __cplusplus
extern "C" {
#endif

#pragma pack(1)

typedef struct si_sge {
        /* offset 0x00 */
        union {
                uint64_t _sge_addr_ll;
                uint32_t _sge_addr_la[2];
        } _sge_addr_un;

#define sge_addr_low    _sge_addr_un._sge_addr_la[0]
#define sge_addr_high   _sge_addr_un._sge_addr_la[1]
#define sge_addr        _sge_addr_un._sge_addr_ll

        /* offset 0x08 */
        uint32_t sge_data_count;

        /* offset 0x0c */
        uint32_t sge_trm_lnk_drd_xcf_rsvd;

#define SET_SGE_LNK(sge)        (sge.sge_trm_lnk_drd_xcf_rsvd = 0x40000000)
#define SET_SGE_TRM(sge)        (sge.sge_trm_lnk_drd_xcf_rsvd = 0x80000000)
#define IS_SGE_TRM_SET(sge)     (sge.sge_trm_lnk_drd_xcf_rsvd & 0x80000000)

} si_sge_t;

/* Scatter Gather Table consists of four SGE entries */
typedef struct si_sgt {
        si_sge_t sgt_sge[4];
} si_sgt_t;


/* Register - Host to Device FIS (from SATA spec) */
typedef struct fis_reg_h2d {
        /* offset 0x00 */
        uint32_t fish_type_pmp_rsvd_cmddevctl_cmd_features;

#define SET_FIS_TYPE(fis, type) \
        ((&fis)->fish_type_pmp_rsvd_cmddevctl_cmd_features |= (type & 0xff))

#define SET_FIS_PMP(fis, pmp)   \
        ((&fis)->fish_type_pmp_rsvd_cmddevctl_cmd_features |= \
            ((pmp & 0xf) << 8))

#define SET_FIS_CDMDEVCTL(fis, cmddevctl)       \
        ((&fis)->fish_type_pmp_rsvd_cmddevctl_cmd_features |=   \
                ((cmddevctl & 0x1) << 15))

#define SET_FIS_COMMAND(fis, command)   \
        ((&fis)->fish_type_pmp_rsvd_cmddevctl_cmd_features |=   \
                ((command & 0xff) << 16))

#define GET_FIS_COMMAND(fis)    \
        (((&fis)->fish_type_pmp_rsvd_cmddevctl_cmd_features >> 16) & 0xff)

#define SET_FIS_FEATURES(fis, features) \
        ((&fis)->fish_type_pmp_rsvd_cmddevctl_cmd_features |=   \
                ((features & 0xff) << 24))

#define GET_FIS_FEATURES(fis)   \
        (((&fis)->fish_type_pmp_rsvd_cmddevctl_cmd_features >> 24) & 0xff)

        /* offset 0x04 */
        uint32_t fish_sector_cyllow_cylhi_devhead;

#define SET_FIS_SECTOR(fis, sector)     \
        ((&fis)->fish_sector_cyllow_cylhi_devhead |= ((sector & 0xff)))

#define GET_FIS_SECTOR(fis)     \
        ((&fis)->fish_sector_cyllow_cylhi_devhead & 0xff)

#define SET_FIS_CYL_LOW(fis, cyl_low)   \
        ((&fis)->fish_sector_cyllow_cylhi_devhead |= ((cyl_low & 0xff) << 8))

#define GET_FIS_CYL_LOW(fis)    \
        (((&fis)->fish_sector_cyllow_cylhi_devhead >> 8) & 0xff)

#define SET_FIS_CYL_HI(fis, cyl_hi)     \
        ((&fis)->fish_sector_cyllow_cylhi_devhead |= ((cyl_hi & 0xff) << 16))

#define GET_FIS_CYL_HI(fis)     \
        (((&fis)->fish_sector_cyllow_cylhi_devhead >> 16) & 0xff)

#define SET_FIS_DEV_HEAD(fis, dev_head) \
        ((&fis)->fish_sector_cyllow_cylhi_devhead |= ((dev_head & 0xff) << 24))

#define GET_FIS_DEV_HEAD(fis)   \
        (((&fis)->fish_sector_cyllow_cylhi_devhead >> 24) & 0xff)


        /* offset 0x08 */
        uint32_t fish_sectexp_cyllowexp_cylhiexp_featuresexp;

#define SET_FIS_SECTOR_EXP(fis, sectorexp)      \
        ((&fis)->fish_sectexp_cyllowexp_cylhiexp_featuresexp |= \
                ((sectorexp & 0xff)))

#define GET_FIS_SECTOR_EXP(fis) \
        ((&fis)->fish_sectexp_cyllowexp_cylhiexp_featuresexp  & 0xff)

#define SET_FIS_CYL_LOW_EXP(fis, cyllowexp)                     \
        ((&fis)->fish_sectexp_cyllowexp_cylhiexp_featuresexp |=         \
                ((cyllowexp & 0xff) << 8))

#define GET_FIS_CYL_LOW_EXP(fis)                        \
        (((&fis)->fish_sectexp_cyllowexp_cylhiexp_featuresexp >> 8) & 0xff)

#define SET_FIS_CYL_HI_EXP(fis, cylhiexp)                       \
        ((&fis)->fish_sectexp_cyllowexp_cylhiexp_featuresexp |=         \
                ((cylhiexp & 0xff) << 16))

#define GET_FIS_CYL_HI_EXP(fis)                 \
        (((&fis)->fish_sectexp_cyllowexp_cylhiexp_featuresexp >> 16) & 0xff)

#define SET_FIS_FEATURES_EXP(fis, features_exp)         \
        ((&fis)->fish_sectexp_cyllowexp_cylhiexp_featuresexp |=         \
                ((features_exp & 0xff) << 24))

        /* offset 0x0c */
        uint32_t fish_sectcount_sectcountexp_rsvd_devctl;

#define SET_FIS_SECTOR_COUNT(fis, sector_count) \
        ((&fis)->fish_sectcount_sectcountexp_rsvd_devctl |= \
            ((sector_count & 0xff)))

#define GET_FIS_SECTOR_COUNT(fis)       \
        ((&fis)->fish_sectcount_sectcountexp_rsvd_devctl & 0xff)

#define SET_FIS_SECTOR_COUNT_EXP(fis, sector_count_exp) \
        ((&fis)->fish_sectcount_sectcountexp_rsvd_devctl |= \
                ((sector_count_exp & 0xff) << 8))

#define GET_FIS_SECTOR_COUNT_EXP(fis)   \
        (((&fis)->fish_sectcount_sectcountexp_rsvd_devctl >> 8) & 0xff)

#define SET_FIS_SECTOR_DEVCTL(fis, devctl)      \
        ((&fis)->fish_sectcount_sectcountexp_rsvd_devctl |= \
            ((devctl & 0xff) << 24))

        /* offset 0x10 */
        uint32_t fish_rsvd3;            /* should be zero */
} fis_reg_h2d_t;




/*
 * Port Request Block
 */
typedef struct si_prb {
        /* offset 0x00 */
        uint32_t prb_control_override;

#define SET_PRB_CONTROL_PKT_READ(prb)   \
        (prb->prb_control_override |= (0x1 << 4))

#define SET_PRB_CONTROL_PKT_WRITE(prb)  \
        (prb->prb_control_override |= (0x1 << 5))

#define SET_PRB_CONTROL_SOFT_RESET(prb) \
        (prb->prb_control_override |= (0x1 << 7))

        /* offset 0x04 */
        uint32_t prb_received_count;

        /* offset 0x08 */
        fis_reg_h2d_t prb_fis;                  /* this is of 0x14 bytes size */

        /* offset 0x1c */
        uint32_t prb_rsvd3;

        /* offset 0x20 */
        si_sge_t prb_sge0;

        /* offset 0x30 */
        si_sge_t prb_sge1;

} si_prb_t;

#pragma pack()


/* Various interrupt bits */
#define INTR_COMMAND_COMPLETE           (0x1 << 0)
#define INTR_COMMAND_ERROR              (0x1 << 1)
#define INTR_PORT_READY                 (0x1 << 2)
#define INTR_POWER_CHANGE               (0x1 << 3)
#define INTR_PHYRDY_CHANGE              (0x1 << 4)
#define INTR_COMWAKE_RECEIVED           (0x1 << 5)
#define INTR_UNRECOG_FIS                (0x1 << 6)
#define INTR_DEV_XCHANGED               (0x1 << 7)
#define INTR_8B10B_DECODE_ERROR         (0x1 << 8)
#define INTR_CRC_ERROR                  (0x1 << 9)
#define INTR_HANDSHAKE_ERROR            (0x1 << 10)
#define INTR_SETDEVBITS_NOTIFY          (0x1 << 11)
#define INTR_MASK                       (0xfff)

/* Device signatures */
#define SI_SIGNATURE_PORT_MULTIPLIER    0x96690101
#define SI_SIGNATURE_ATAPI              0xeb140101
#define SI_SIGNATURE_DISK               0x00000101


/* Global definitions */
#define GLOBAL_OFFSET(si_ctlp)          (si_ctlp->sictl_global_addr)
#define GLOBAL_CONTROL_REG(si_ctlp)     (GLOBAL_OFFSET(si_ctlp)+0x40)
#define GLOBAL_INTERRUPT_STATUS(si_ctlp)        (GLOBAL_OFFSET(si_ctlp)+0x44)

/* Per port definitions */
#define PORT_OFFSET(si_ctlp, port)      (si_ctlp->sictl_port_addr + port*0x2000)
#define PORT_LRAM(si_ctlp, port, slot)          \
                        (PORT_OFFSET(si_ctlp, port) + 0x0 + slot*0x80)
#define PORT_CONTROL_SET(si_ctlp, port)         \
                        (PORT_OFFSET(si_ctlp, port) + 0x1000)
#define PORT_STATUS(si_ctlp, port)              \
                        (PORT_OFFSET(si_ctlp, port) + 0x1000)
#define PORT_CONTROL_CLEAR(si_ctlp, port)               \
                        (PORT_OFFSET(si_ctlp, port) + 0x1004)
#define PORT_INTERRUPT_STATUS(si_ctlp, port)    \
                        (PORT_OFFSET(si_ctlp, port) + 0x1008)
#define PORT_INTERRUPT_ENABLE_SET(si_ctlp, port)        \
                        (PORT_OFFSET(si_ctlp, port) + 0x1010)
#define PORT_INTERRUPT_ENABLE_CLEAR(si_ctlp, port) \
                        (PORT_OFFSET(si_ctlp, port) + 0x1014)
#define PORT_COMMAND_ERROR(si_ctlp, port)       \
                        (PORT_OFFSET(si_ctlp, port) + 0x1024)
#define PORT_SLOT_STATUS(si_ctlp, port) (PORT_OFFSET(si_ctlp, port) + 0x1800)

#define PORT_SCONTROL(si_ctlp, port)    (PORT_OFFSET(si_ctlp, port) + 0x1f00)
#define PORT_SSTATUS(si_ctlp, port)     (PORT_OFFSET(si_ctlp, port) + 0x1f04)
#define PORT_SERROR(si_ctlp, port)      (PORT_OFFSET(si_ctlp, port) + 0x1f08)
#define PORT_SACTIVE(si_ctlp, port)     (PORT_OFFSET(si_ctlp, port) + 0x1f0c)

#define PORT_COMMAND_ACTIVATION(si_ctlp, port, slot)    \
                        (PORT_OFFSET(si_ctlp, port) + 0x1c00 + slot*0x8)

#define PORT_SIGNATURE_MSB(si_ctlp, port, slot)         \
                        (PORT_OFFSET(si_ctlp, port) + slot*0x80 + 0x0c)
#define PORT_SIGNATURE_LSB(si_ctlp, port, slot)         \
                        (PORT_OFFSET(si_ctlp, port) + slot*0x80 + 0x14)

/* Interesting bits of Port Control Set register */
#define PORT_CONTROL_SET_BITS_PORT_RESET                0x1
#define PORT_CONTROL_SET_BITS_DEV_RESET                 0x2
#define PORT_CONTROL_SET_BITS_PORT_INITIALIZE           0x4
#define PORT_CONTROL_SET_BITS_PACKET_LEN                0x20
#define PORT_CONTROL_SET_BITS_RESUME                    0x40
#define PORT_CONTROL_SET_BITS_PM_ENABLE                 0x2000

/* Interesting bits of Port Control Clear register */
#define PORT_CONTROL_CLEAR_BITS_PORT_RESET              0x1
#define PORT_CONTROL_CLEAR_BITS_INTR_NCoR               0x8
#define PORT_CONTROL_CLEAR_BITS_PACKET_LEN              0x20
#define PORT_CONTROL_CLEAR_BITS_RESUME                  0x40

/* Interesting bits of Port Status register */
#define PORT_STATUS_BITS_PORT_READY             0x80000000

/* Interesting bits of Global Control register */
#define GLOBAL_CONTROL_REG_BITS_CLEAR           0x00000000

#define POST_PRB_ADDR(si_ctlp, si_portp, port, slot)                      \
        (void) ddi_dma_sync(si_portp->siport_prbpool_dma_handle,          \
                        slot * sizeof (si_prb_t),                         \
                        sizeof (si_prb_t),                                \
                        DDI_DMA_SYNC_FORDEV);                             \
                                                                          \
        (void) ddi_dma_sync(si_portp->siport_sgbpool_dma_handle,          \
                        slot * sizeof (si_sgblock_t) * si_dma_sg_number,  \
                        sizeof (si_sgblock_t) * si_dma_sg_number,         \
                        DDI_DMA_SYNC_FORDEV);                             \
                                                                          \
        ddi_put64(si_ctlp->sictl_port_acc_handle,                         \
                (uint64_t *)PORT_COMMAND_ACTIVATION(si_ctlp, port, slot), \
                (uint64_t)(si_portp->siport_prbpool_physaddr +            \
                slot*sizeof (si_prb_t)));

#define SI_SLOT_MASK    0x7fffffff
#define SI_NUM_SLOTS    0x1f            /* 31 */

#define ATTENTION_BIT   0x80000000
#define IS_ATTENTION_RAISED(slot_status)        (slot_status & ATTENTION_BIT)

#define SI3124_DEV_ID   0x3124
#define SI3132_DEV_ID   0x3132
#define SI3531_DEV_ID   0x3531

#define PM_CSR(devid)    ((devid == SI3124_DEV_ID) ? 0x68 : 0x58)

#define REGISTER_FIS_H2D        0x27

#define SI31xx_INTR_PORT_MASK   0xf

/* PCI BAR registers */
#define PCI_BAR0        1       /* Contains global register set */
#define PCI_BAR1        2       /* Contains port register set */

/* Port Status and Control Registers (from port multiplier spec) */
#define PSCR_REG0       0
#define PSCR_REG1       1
#define PSCR_REG2       2
#define PSCR_REG3       3

/* SStatus bit fields */
#define SSTATUS_DET_MASK        0x0000000f
#define SSTATUS_SPD_MASK        0x000000f0
#define SSTATUS_SPD_SHIFT       4
#define SSTATUS_IPM_MASK        0x00000f00
#define SSTATUS_IPM_SHIFT       8


#define SSTATUS_DET_NODEV_NOPHY          0x0 /* No device, no PHY */
#define SSTATUS_DET_DEVPRESENT_NOPHY     0x1 /* Dev present, no PHY */
#define SSTATUS_DET_DEVPRESENT_PHYONLINE 0x3 /* Dev present, PHY online */

#define SSTATUS_IPM_NODEV_NOPHY                 0x0 /* No dev, no PHY */
#define SSTATUS_IPM_INTERFACE_ACTIVE            0x1 /* Interface active */
#define SSTATUS_IPM_INTERFACE_POWERPARTIAL      0x2 /* partial power mgmnt */
#define SSTATUS_IPM_INTERFACE_POWERSLUMBER      0x6 /* slumber power mgmt */

/* SControl bit fields */
#define SCONTROL_DET_MASK       0x0000000f




/* Command Error codes */
#define CMD_ERR_DEVICEERRROR            1
#define CMD_ERR_SDBERROR                2
#define CMD_ERR_DATAFISERROR            3
#define CMD_ERR_SENDFISERROR            4
#define CMD_ERR_INCONSISTENTSTATE       5
#define CMD_ERR_DIRECTIONERROR          6
#define CMD_ERR_UNDERRUNERROR           7
#define CMD_ERR_OVERRUNERROR            8
#define CMD_ERR_PACKETPROTOCOLERROR     11
#define CMD_ERR_PLDSGTERRORBOUNDARY     16
#define CMD_ERR_PLDSGTERRORTARETABORT   17
#define CMD_ERR_PLDSGTERRORMASTERABORT  18
#define CMD_ERR_PLDSGTERRORPCIERR       19
#define CMD_ERR_PLDCMDERRORBOUNDARY     24
#define CMD_ERR_PLDCMDERRORTARGETABORT  25
#define CMD_ERR_PLDCMDERRORMASTERABORT  26
#define CMD_ERR_PLDCMDERORPCIERR        27
#define CMD_ERR_PSDERRORTARGETABORT     33
#define CMD_ERR_PSDERRORMASTERABORT     34
#define CMD_ERR_PSDERRORPCIERR          35
#define CMD_ERR_SENDSERVICEERROR        36

#ifdef  __cplusplus
}
#endif

#endif /* _SI3124REG_H */