#ifndef _SATA_H
#define _SATA_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/types.h>
#include <sys/scsi/scsi.h>
#include <sys/scsi/impl/services.h>
#include <sys/sata/sata_defs.h>
#include <sys/sata/sata_hba.h>
#define SATA_STATE_PROBING 0x000001
#define SATA_STATE_PROBED 0x000002
struct sata_port_stats {
uint64_t link_lost;
uint64_t link_established;
uint64_t device_attached;
uint64_t device_detached;
uint64_t port_reset;
uint64_t port_pwr_changed;
};
typedef struct sata_port_stats sata_port_stats_t;
struct sata_drive_stats {
uint64_t media_error;
uint64_t drive_reset;
} sata_drv_stats_t;
typedef struct sata_drive_stats sata_drive_stats_t;
struct sata_ctrl_stats {
uint64_t ctrl_reset;
uint64_t ctrl_pwr_change;
};
typedef struct sata_ctrl_stats sata_ctrl_stats_t;
struct sata_hba_inst {
dev_info_t *satahba_dip;
struct sata_hba_inst *satahba_next;
struct sata_hba_inst *satahba_prev;
struct scsi_hba_tran *satahba_scsi_tran;
struct sata_hba_tran *satahba_tran;
kmutex_t satahba_mutex;
struct taskq *satahba_taskq;
uint_t satahba_event_flags;
struct sata_cport_info *satahba_dev_port[SATA_MAX_CPORTS];
uint_t satahba_open_flag;
struct sata_ctrl_stats satahba_stats;
uint_t satahba_attached;
};
typedef struct sata_hba_inst sata_hba_inst_t;
struct sata_cport_info {
sata_address_t cport_addr;
kmutex_t cport_mutex;
uint32_t cport_state;
uint32_t cport_event_flags;
struct sata_port_scr cport_scr;
uint32_t cport_dev_type;
union {
struct sata_drive_info *cport_sata_drive;
struct sata_pmult_info *cport_sata_pmult;
} cport_devp;
clock_t cport_link_lost_time;
clock_t cport_dev_attach_time;
struct sata_port_stats cport_stats;
boolean_t cport_tgtnode_clean;
};
typedef struct sata_cport_info sata_cport_info_t;
struct sata_drive_info {
sata_address_t satadrv_addr;
uint32_t satadrv_state;
uint32_t satadrv_event_flags;
clock_t satadrv_reset_time;
uint32_t satadrv_type;
uint32_t satadrv_status_reg;
uint32_t satadrv_error_reg;
uint16_t satadrv_features_support;
uint16_t satadrv_queue_depth;
uint16_t satadrv_atapi_cdb_len;
uint16_t satadrv_atapi_trans_ver;
uint16_t satadrv_settings;
uint16_t satadrv_features_enabled;
uint64_t satadrv_capacity;
uint64_t satadrv_max_queue_depth;
sata_id_t satadrv_id;
struct sata_drive_stats satadrv_stats;
uint8_t satadrv_standby_timer[4];
uint8_t satadrv_power_level;
};
typedef struct sata_drive_info sata_drive_info_t;
_NOTE(SCHEME_PROTECTS_DATA("unshared data", sata_drive_info))
struct sata_pmult_info {
sata_address_t pmult_addr;
uint32_t pmult_state;
uint32_t pmult_event_flags;
struct sata_pmult_gscr pmult_gscr;
uint32_t pmult_num_dev_ports;
struct sata_pmport_info *pmult_dev_port[SATA_MAX_PMPORTS - 1];
};
typedef struct sata_pmult_info sata_pmult_info_t;
_NOTE(SCHEME_PROTECTS_DATA("unshared data", sata_pmult_info))
_NOTE(MUTEX_PROTECTS_DATA(sata_cport_info::cport_mutex, \
sata_pmult_info::pmult_dev_port))
struct sata_pmport_info {
sata_address_t pmport_addr;
kmutex_t pmport_mutex;
uint32_t pmport_state;
uint32_t pmport_event_flags;
struct sata_port_scr pmport_scr;
uint32_t pmport_dev_type;
struct sata_drive_info *pmport_sata_drive;
clock_t pmport_link_lost_time;
clock_t pmport_dev_attach_time;
struct sata_port_stats pmport_stats;
boolean_t pmport_tgtnode_clean;
};
typedef struct sata_pmport_info sata_pmport_info_t;
#define SATA_POWER_ACTIVE 0x00
#define SATA_POWER_IDLE 0x01
#define SATA_POWER_STANDBY 0x02
#define SATA_POWER_STOPPED 0x03
#define SATA_CAP_POWER_CONDITON PM_CAPABLE_SPC4
#define SATA_CAP_SMART_PAGE PM_CAPABLE_SMART_LOG
#define SATA_CAP_LOG_SENSE PM_CAPABLE_LOG_SUPPORTED
#define SATA_PORT_DEVLINK_UP 0x00000103
#define SATA_PORT_DEVLINK_UP_MASK 0x0000010F
#define SATA_PORT_STATE_CLEAR_MASK (~(SATA_PSTATE_SHUTDOWN))
#define SATA_VALID_DEV_TYPE (SATA_DTYPE_ATADISK | \
SATA_DTYPE_ATAPICD | \
SATA_DTYPE_ATAPITAPE | \
SATA_DTYPE_ATAPIDISK)
#define SATA_DEV_F_DMA 0x01
#define SATA_DEV_F_LBA28 0x02
#define SATA_DEV_F_LBA48 0x04
#define SATA_DEV_F_NCQ 0x08
#define SATA_DEV_F_SATA1 0x10
#define SATA_DEV_F_SATA2 0x20
#define SATA_DEV_F_TCQ 0x40
#define SATA_DEV_F_SATA3 0x80
#define SATA_DEV_F_E_TAGGED_QING 0x01
#define SATA_DEV_F_E_UNTAGGED_QING 0x02
#define SATA_DEV_READ_AHEAD 0x0001
#define SATA_DEV_WRITE_CACHE 0x0002
#define SATA_DEV_DMA 0x0004
#define SATA_DEV_SERIAL_FEATURES 0x8000
#define SATA_DEV_ASYNCH_NOTIFY 0x2000
#define SATA_DEV_RMSN 0x0100
#define SATA_EVNT_MAIN 0x80000000
#define SATA_EVNT_SKIP 0x40000000
#define SATA_EVNT_INPROC_DEVICE_RESET 0x08000000
#define SATA_EVNT_CLEAR_DEVICE_RESET 0x04000000
#define SATA_EVNT_TARGET_NODE_CLEANUP 0x00000100
#define SATA_EVNT_AUTOONLINE_DEVICE 0x00000200
#define SATA_EVNT_LOCK_PORT_BUSY 0x00800000
#define SATA_APCTL_LOCK_PORT_BUSY 0x00400000
#define SATA_EVNT_PORT_EVENTS (SATA_EVNT_DEVICE_ATTACHED | \
SATA_EVNT_DEVICE_DETACHED | \
SATA_EVNT_LINK_LOST | \
SATA_EVNT_LINK_ESTABLISHED | \
SATA_EVNT_PMULT_LINK_CHANGED | \
SATA_EVNT_PORT_FAILED | \
SATA_EVNT_TARGET_NODE_CLEANUP | \
SATA_EVNT_AUTOONLINE_DEVICE)
#define SATA_EVNT_DRIVE_EVENTS (SATA_EVNT_DEVICE_RESET | \
SATA_EVNT_INPROC_DEVICE_RESET)
#define SATA_EVNT_CONTROLLER_EVENTS SATA_EVNT_PWR_LEVEL_CHANGED
#define SATA_EVNT_DAEMON_SLEEP_TIME 50000
#define SATA_EVNT_DAEMON_TERM_TIMEOUT 100000
#define SATA_EVNT_DAEMON_TERM_WAIT 60000000
#define SATA_EVNT_LINK_LOST_TIMEOUT 1000000
#define SATA_DEV_IDENTIFY_TIMEOUT 60000000
#define SATA_DEV_REPROBE_TIMEOUT 30000000
#define SATA_DEV_RETRY_DLY 10000
#define SATA_DEV_IDENTIFY_RETRY 1
#define SATA_DEV_IDENTIFY_NORETRY 0
#define SATA_DEVCTL_CLOSED 0
#define SATA_DEVCTL_SOPENED 1
#define SATA_DEVCTL_EXOPENED 2
typedef struct sata_pkt_txlate {
struct sata_hba_inst *txlt_sata_hba_inst;
struct scsi_pkt *txlt_scsi_pkt;
struct sata_pkt *txlt_sata_pkt;
ddi_dma_handle_t txlt_buf_dma_handle;
uint_t txlt_flags;
uint_t txlt_num_dma_win;
uint_t txlt_cur_dma_win;
uint_t txlt_curwin_num_dma_cookies;
uint_t txlt_curwin_processed_dma_cookies;
size_t txlt_total_residue;
ddi_dma_cookie_t txlt_dma_cookie;
int txlt_dma_cookie_list_len;
ddi_dma_cookie_t *txlt_dma_cookie_list;
int txlt_num_dma_cookies;
ddi_acc_handle_t txlt_tmp_buf_handle;
caddr_t txlt_tmp_buf;
} sata_pkt_txlate_t;
_NOTE(SCHEME_PROTECTS_DATA("unshared data", sata_pkt_txlate))
_NOTE(SCHEME_PROTECTS_DATA("unshared data", scsi_pkt))
#define SATA_MAX_SENSE_LEN MAX(sizeof (struct scsi_arq_status), \
sizeof (struct scsi_arq_status) - sizeof (struct scsi_extended_sense) + \
sizeof (struct scsi_descr_sense_hdr) + \
MAX(sizeof (struct scsi_cmd_specific_sense_descr), \
sizeof (struct scsi_ata_status_ret_sense_descr)))
struct sata_apt_sense_data {
struct scsi_status apt_status;
struct scsi_status apt_rqpkt_status;
uchar_t apt_rqpkt_reason;
uchar_t apt_rqpkt_resid;
uint_t apt_rqpkt_state;
uint_t apt_rqpkt_statistics;
struct scsi_descr_sense_hdr apt_sd_hdr;
struct scsi_ata_status_ret_sense_descr apt_sd_sense;
};
#define SD_SCSI_ASC_NO_ADD_SENSE 0x00
#define SD_SCSI_ASC_APT_INFO_AVAIL 0x00
#define SD_SCSI_ASC_LU_NOT_READY 0x04
#define SD_SCSI_ASC_LU_NOT_RESPONSE 0x05
#define SD_SCSI_ASC_WRITE_ERR 0x0c
#define SD_SCSI_ASC_UNREC_READ_ERR 0x11
#define SD_SCSI_ASC_INVALID_COMMAND_CODE 0x20
#define SD_SCSI_ASC_LBA_OUT_OF_RANGE 0x21
#define SD_SCSI_ASC_INVALID_FIELD_IN_CDB 0x24
#define SD_SCSI_ASC_INVALID_FIELD_IN_PARAMS_LIST 0x26
#define SD_SCSI_ASC_WRITE_PROTECTED 0x27
#define SD_SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED 0x28
#define SD_SCSI_ASC_RESET 0x29
#define SD_SCSI_ASC_CMD_SEQUENCE_ERR 0x2c
#define SD_SCSI_ASC_MEDIUM_NOT_PRESENT 0x3a
#define SD_SCSI_ASC_SAVING_PARAMS_NOT_SUPPORTED 0x39
#define SD_SCSI_ASC_INTERNAL_TARGET_FAILURE 0x44
#define SD_SCSI_ASC_INFO_UNIT_IUCRC_ERR 0x47
#define SD_SCSI_ASC_OP_MEDIUM_REM_REQ 0x5a
#define SD_SCSI_ASC_LOW_POWER_CONDITION_ON 0x5e
#define SCMD_SYNCHRONIZE_CACHE_G1 0x91
#define MODEPAGE_RW_ERRRECOV 0x01
#define SCSI_READ_CAPACITY16_MAX_LBA 0xfffffffffffffffe
#define SATA_IS_MEDIUM_ACCESS_CMD(cmd) \
(((cmd) == SCMD_READ) || ((cmd) == SCMD_WRITE) || \
((cmd) == SCMD_READ_G1) || ((cmd) == SCMD_WRITE_G1) || \
((cmd) == SCMD_READ_G4) || ((cmd) == SCMD_WRITE_G4) || \
((cmd) == SCMD_READ_G5) || ((cmd) == SCMD_WRITE_G5) || \
((cmd) == SCMD_VERIFY) || ((cmd) == SCMD_VERIFY_G4) || \
((cmd) == SCMD_VERIFY_G5) || ((cmd) == 0x7f) || \
((cmd) == SCMD_SYNCHRONIZE_CACHE) || ((cmd) == SCMD_SPACE_G4) || \
((cmd) == SCMD_READ_POSITION) || \
((cmd) == 0x90) || \
((cmd) == SCMD_READ_DEFECT_LIST) || \
((cmd) == 0xb7) || \
((cmd) == SCMD_READ_LONG) || ((cmd) == SCMD_SVC_ACTION_IN_G4) || \
((cmd) == SCMD_WRITE_LONG) || ((cmd) == SCMD_SVC_ACTION_OUT_G4) || \
((cmd) == 0x41) || ((cmd) == 0x93) || \
((cmd) == 0x52) || ((cmd) == 0x50) || \
((cmd) == 0x53) || ((cmd) == 0x51) || \
((cmd) == 0x7f))
#define SATA_TRAN(sata_hba_inst) \
sata_hba_inst->satahba_tran
#define SATA_DIP(sata_hba_inst) \
sata_hba_inst->satahba_dip
#define SATA_NUM_CPORTS(sata_hba_inst) \
sata_hba_inst->satahba_tran->sata_tran_hba_num_cports
#define SATA_QDEPTH(sata_hba_inst) \
sata_hba_inst->satahba_tran->sata_tran_hba_qdepth
#define SATA_FEATURES(sata_hba_inst) \
sata_hba_inst->satahba_tran->sata_tran_hba_features_support
#define SATA_DMA_ATTR(sata_hba_inst) \
sata_hba_inst->satahba_tran->sata_tran_hba_dma_attr
#define SATA_START_FUNC(sata_hba_inst) \
sata_hba_inst->satahba_tran->sata_tran_start
#define SATA_ABORT_FUNC(sata_hba_inst) \
sata_hba_inst->satahba_tran->sata_tran_abort
#define SATA_RESET_DPORT_FUNC(sata_hba_inst) \
sata_hba_inst->satahba_tran->sata_tran_reset_dport
#define SATA_PORT_DEACTIVATE_FUNC(sata_hba_inst) \
(sata_hba_inst->satahba_tran->sata_tran_hotplug_ops == NULL ? \
NULL : \
sata_hba_inst->satahba_tran->sata_tran_hotplug_ops->\
sata_tran_port_deactivate)
#define SATA_PORT_ACTIVATE_FUNC(sata_hba_inst) \
(sata_hba_inst->satahba_tran->sata_tran_hotplug_ops == NULL ? \
NULL : \
sata_hba_inst->satahba_tran->sata_tran_hotplug_ops->\
sata_tran_port_activate)
#define SATA_PROBE_PORT_FUNC(sata_hba_inst) \
sata_hba_inst->satahba_tran->sata_tran_probe_port
#define SATA_SELFTEST_FUNC(sata_hba_inst) \
sata_hba_inst->satahba_tran->sata_tran_selftest
#define SATA_CPORT_MUTEX(sata_hba_inst, cport) \
sata_hba_inst->satahba_dev_port[cport]->cport_mutex
#define SATA_CPORT_INFO(sata_hba_inst, cport) \
sata_hba_inst->satahba_dev_port[cport]
#define SATA_CPORT_STATE(sata_hba_inst, cport) \
sata_hba_inst->satahba_dev_port[cport]->cport_state
#define SATA_CPORT_EVENT_FLAGS(sata_hba_inst, cport) \
sata_hba_inst->satahba_dev_port[cport]->cport_event_flags
#define SATA_CPORT_SCR(sata_hba_inst, cport) \
sata_hba_inst->satahba_dev_port[cport]->cport_scr
#define SATA_CPORT_DEV_TYPE(sata_hba_inst, cport) \
sata_hba_inst->satahba_dev_port[cport]->cport_dev_type
#define SATA_CPORT_DRV_INFO(sata_hba_inst, cport) \
sata_hba_inst->satahba_dev_port[cport]->cport_devp.cport_sata_drive
#define SATA_CPORTINFO_DRV_TYPE(cportinfo) \
cportinfo->cport_dev_type
#define SATA_CPORTINFO_DRV_INFO(cportinfo) \
cportinfo->cport_devp.cport_sata_drive
#define SATA_CPORTINFO_PMULT_INFO(cportinfo) \
cportinfo->cport_devp.cport_sata_pmult
#define SATA_PMULT_INFO(sata_hba_inst, cport) \
sata_hba_inst->satahba_dev_port[cport]->cport_devp.cport_sata_pmult
#define SATA_NUM_PMPORTS(sata_hba_inst, cport) \
sata_hba_inst->satahba_dev_port[cport]->\
cport_devp.cport_sata_pmult->pmult_num_dev_ports
#define SATA_PMPORT_MUTEX(sata_hba_inst, cport, pmport) \
sata_hba_inst->satahba_dev_port[cport]->\
cport_devp.cport_sata_pmult->pmult_dev_port[pmport]->pmport_mutex
#define SATA_PMPORT_INFO(sata_hba_inst, cport, pmport) \
sata_hba_inst->satahba_dev_port[cport]->\
cport_devp.cport_sata_pmult->pmult_dev_port[pmport]
#define SATA_PMPORT_DRV_INFO(sata_hba_inst, cport, pmport) \
sata_hba_inst->satahba_dev_port[cport]->\
cport_devp.cport_sata_pmult->pmult_dev_port[pmport]->\
pmport_sata_drive
#define SATA_PMPORT_STATE(sata_hba_inst, cport, pmport) \
sata_hba_inst->satahba_dev_port[cport]->\
cport_devp.cport_sata_pmult->pmult_dev_port[pmport]->pmport_state
#define SATA_PMPORT_SCR(sata_hba_inst, cport, pmport) \
sata_hba_inst->satahba_dev_port[cport]->\
cport_devp.cport_sata_pmult->pmult_dev_port[pmport]->pmport_scr
#define SATA_PMPORT_DEV_TYPE(sata_hba_inst, cport, pmport) \
sata_hba_inst->satahba_dev_port[cport]->\
cport_devp.cport_sata_pmult->pmult_dev_port[pmport]->pmport_dev_type
#define SATA_PMPORT_EVENT_FLAGS(sata_hba_inst, cport, pmport) \
sata_hba_inst->satahba_dev_port[cport]->\
cport_devp.cport_sata_pmult->pmult_dev_port[pmport]->\
pmport_event_flags
#define SATA_PMPORTINFO_DRV_TYPE(pmportinfo) \
pmportinfo->pmport_dev_type
#define SATA_PMPORTINFO_DRV_INFO(pmportinfo) \
pmportinfo->pmport_sata_drive
#define SATA_TXLT_HBA_INST(spx) \
spx->txlt_sata_hba_inst
#define SATA_TXLT_CPORT(spx) \
spx->txlt_sata_pkt->satapkt_device.satadev_addr.cport
#define SATA_TXLT_PMPORT(spx) \
spx->txlt_sata_pkt->satapkt_device.satadev_addr.pmport
#define SATA_TXLT_QUAL(spx) \
spx->txlt_sata_pkt->satapkt_device.satadev_addr.qual
#define SATA_TXLT_CPORT_MUTEX(spx) \
spx->txlt_sata_hba_inst->\
satahba_dev_port[spx->txlt_sata_pkt->\
satapkt_device.satadev_addr.cport]->cport_mutex
#define SATA_TXLT_TASKQ(spx) \
spx->txlt_sata_hba_inst->\
satahba_taskq
#define SATA_AP_NODE 0x400
#define SATA_DEVCTL_NODE 0x000
#define SATA_PMULT_AP 0x200
#define SATA_PMULT_PORT_SHIFT 5
#define SATA_CNTRL_INSTANCE_SHIFT 11
#define SATA_CPORT_MASK 0x1f
#define SATA_PMULT_PORT_MASK 0xf
#define SATA_CNTRL_INSTANCE_MASK 0x03F
#define SATA_MAKE_DEVCTL_MINOR(controller_instance) \
((controller_instance << SATA_CNTRL_INSTANCE_SHIFT) | \
SATA_DEVCTL_NODE)
#define SATA_MAKE_AP_MINOR(cntrl_instance, cport, pmport, qual) \
(qual & (SATA_ADDR_PMPORT | SATA_ADDR_DPMPORT) ? \
(((cntrl_instance) << SATA_CNTRL_INSTANCE_SHIFT) | \
SATA_AP_NODE | SATA_PMULT_AP | \
(pmport << SATA_PMULT_PORT_SHIFT) | cport) : \
(((cntrl_instance) << SATA_CNTRL_INSTANCE_SHIFT) | \
SATA_AP_NODE | cport))
#define SATA_MINOR2INSTANCE(minor) \
((minor >> SATA_CNTRL_INSTANCE_SHIFT) & SATA_CNTRL_INSTANCE_MASK)
#define SATA_MAKE_AP_NUMBER(cport, pmport, qual) \
((qual & (SATA_ADDR_PMPORT | SATA_ADDR_DPMPORT)) ? \
(SATA_PMULT_AP | (pmport << SATA_PMULT_PORT_SHIFT) | cport) : \
(cport))
#define SATA_TO_SCSI_TARGET(cport, pmport, qual) \
(qual == SATA_ADDR_DCPORT ? cport : \
(cport | (pmport << SATA_PMULT_PORT_SHIFT) | SATA_PMULT_AP))
#define SCSI_TO_SATA_CPORT(scsi_target) \
(scsi_target & SATA_CPORT_MASK)
#define SCSI_TO_SATA_PMPORT(scsi_target) \
((scsi_target >> SATA_PMULT_PORT_SHIFT) & SATA_PMULT_PORT_MASK)
#define SCSI_TO_SATA_ADDR_QUAL(scsi_target) \
((scsi_target & SATA_PMULT_AP) ? SATA_ADDR_DPMPORT : \
SATA_ADDR_DCPORT)
#if DEBUG
#define SATA_DEBUG
#define SATA_DBG_SCSI_IF 1
#define SATA_DBG_HBA_IF 2
#define SATA_DBG_NODES 4
#define SATA_DBG_IOCTL_IF 8
#define SATA_DBG_EVENTS 0x10
#define SATA_DBG_EVENTS_PROC 0x20
#define SATA_DBG_EVENTS_PROCPST 0x40
#define SATA_DBG_EVENTS_CNTRL 0x80
#define SATA_DBG_EVENTS_DAEMON 0x100
#define SATA_DBG_DMA_SETUP 0x400
#define SATA_DBG_DEV_SETTINGS 0x800
#define SATA_DBG_ATAPI 0x1000
#define SATA_DBG_ATAPI_PACKET 0x8000
#define SATA_DBG_INTR_CTX 0x10000
#define SATA_DBG_PMULT 0x20000
typedef struct sata_atapi_cmd {
uint8_t acdb[SATA_ATAPI_MAX_CDB_LEN];
uint8_t arqs[SATA_ATAPI_RQSENSE_LEN];
uint_t sata_pkt_reason;
uint_t scsi_pkt_reason;
} sata_atapi_cmd_t;
#define SATADBG1(flag, sata, format, arg1) \
if (sata_debug_flags & (flag)) { \
sata_log(sata, CE_CONT, format, arg1); \
}
#define SATADBG2(flag, sata, format, arg1, arg2) \
if (sata_debug_flags & (flag)) { \
sata_log(sata, CE_CONT, format, arg1, arg2); \
}
#define SATADBG3(flag, sata, format, arg1, arg2, arg3) \
if (sata_debug_flags & (flag)) { \
sata_log(sata, CE_CONT, format, arg1, arg2, arg3); \
}
#else
#define SATADBG1(flag, dip, frmt, arg1)
#define SATADBG2(flag, dip, frmt, arg1, arg2)
#define SATADBG3(flag, dip, frmt, arg1, arg2, arg3)
#endif
#ifdef __cplusplus
}
#endif
#endif