summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/sys')
-rw-r--r--usr/src/uts/common/sys/Makefile2
-rw-r--r--usr/src/uts/common/sys/autoconf.h2
-rw-r--r--usr/src/uts/common/sys/bitset.h16
-rw-r--r--usr/src/uts/common/sys/damap.h156
-rw-r--r--usr/src/uts/common/sys/damap_impl.h181
-rw-r--r--usr/src/uts/common/sys/ddi_impldefs.h42
-rw-r--r--usr/src/uts/common/sys/devctl.h7
-rw-r--r--usr/src/uts/common/sys/devinfo_impl.h6
-rw-r--r--usr/src/uts/common/sys/id_space.h11
-rw-r--r--usr/src/uts/common/sys/mdi_impldefs.h33
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/mpapi_impl.h5
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/mpapi_scsi_vhci.h11
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/ata.h279
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/ata8-acs.h122
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/atapi7v3.h228
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs.h627
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_def.h514
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_iomb.h724
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_mpi.h222
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_param.h138
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_proto.h353
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_reg.h378
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_scsa.h92
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_sgl.h86
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_smhba.h72
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/smp_defs.h1100
-rw-r--r--usr/src/uts/common/sys/scsi/conf/autoconf.h36
-rw-r--r--usr/src/uts/common/sys/scsi/conf/device.h7
-rw-r--r--usr/src/uts/common/sys/scsi/generic/sas.h199
-rw-r--r--usr/src/uts/common/sys/scsi/generic/smp_frames.h1114
-rw-r--r--usr/src/uts/common/sys/scsi/impl/sas_transport.h217
-rw-r--r--usr/src/uts/common/sys/scsi/impl/transport.h143
-rw-r--r--usr/src/uts/common/sys/scsi/scsi_address.h5
-rw-r--r--usr/src/uts/common/sys/scsi/scsi_ctl.h20
-rw-r--r--usr/src/uts/common/sys/scsi/scsi_pkt.h7
-rw-r--r--usr/src/uts/common/sys/scsi/scsi_types.h20
-rw-r--r--usr/src/uts/common/sys/scsi/targets/smp.h16
-rw-r--r--usr/src/uts/common/sys/sunddi.h65
-rw-r--r--usr/src/uts/common/sys/sunmdi.h23
-rw-r--r--usr/src/uts/common/sys/sunndi.h44
-rw-r--r--usr/src/uts/common/sys/systm.h1
41 files changed, 7138 insertions, 186 deletions
diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile
index 29518c52ea..5300263225 100644
--- a/usr/src/uts/common/sys/Makefile
+++ b/usr/src/uts/common/sys/Makefile
@@ -142,6 +142,8 @@ CHKHDRS= \
cyclic_impl.h \
dacf.h \
dacf_impl.h \
+ damap.h \
+ damap_impl.h \
dc_ki.h \
ddi.h \
ddifm.h \
diff --git a/usr/src/uts/common/sys/autoconf.h b/usr/src/uts/common/sys/autoconf.h
index 5aa9351981..df743597b7 100644
--- a/usr/src/uts/common/sys/autoconf.h
+++ b/usr/src/uts/common/sys/autoconf.h
@@ -265,7 +265,7 @@ extern void i_ddi_forceattach_drivers(void);
extern int i_ddi_io_initialized(void);
extern dev_info_t *i_ddi_create_branch(dev_info_t *, int);
extern void i_ddi_add_devimap(dev_info_t *dip);
-extern void i_ddi_di_cache_invalidate(int kmflag);
+extern void i_ddi_di_cache_invalidate(void);
extern void i_ddi_di_cache_free(struct di_cache *cache);
/* devname_state - for /dev to denote reconfig and system available */
diff --git a/usr/src/uts/common/sys/bitset.h b/usr/src/uts/common/sys/bitset.h
index b14636373b..daf608e835 100644
--- a/usr/src/uts/common/sys/bitset.h
+++ b/usr/src/uts/common/sys/bitset.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -72,6 +72,20 @@ int bitset_in_set(bitset_t *, uint_t);
int bitset_is_null(bitset_t *);
uint_t bitset_find(bitset_t *);
+/*
+ * Bitset computations
+ */
+int bitset_and(bitset_t *, bitset_t *, bitset_t *);
+int bitset_or(bitset_t *, bitset_t *, bitset_t *);
+int bitset_xor(bitset_t *, bitset_t *, bitset_t *);
+
+/*
+ * Miscellaneous bitset operations
+ */
+void bitset_zero(bitset_t *);
+void bitset_copy(bitset_t *, bitset_t *);
+int bitset_match(bitset_t *, bitset_t *);
+
#endif /* !_KERNEL && !_KMEMUSER */
#ifdef __cplusplus
diff --git a/usr/src/uts/common/sys/damap.h b/usr/src/uts/common/sys/damap.h
new file mode 100644
index 0000000000..59777e8033
--- /dev/null
+++ b/usr/src/uts/common/sys/damap.h
@@ -0,0 +1,156 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_DAMAP_H
+#define _SYS_DAMAP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Delta (device) Address Map Interfaces
+ *
+ * These interfaces provide time-stablized sets of 'addresses',
+ * where addresses are string representations of device
+ * or bus-specific address. The mechanisms include interfaces to
+ * report and remove address from a map, time stabilization, callouts
+ * to higher-level configuration and unconfiguration actions, and
+ * address lookup functions.
+ *
+ * Per Address Reports
+ * With per-address reporting, the caller reports the addition and removal
+ * each address visible to it. Each report is independently time stabilized;
+ * Once a report has stabilized, the reported address is either
+ * activated & configured, or unconfigured & released.
+ *
+ * Full Set Reports
+ * When using fullset reporting, the report provider enumerates the entire
+ * set of addresses visible to the provider at a given point in time.
+ * The entire set is then stabilized.
+ * Upon stabilizing, any newly reported addresses are activated & configured
+ * and any previously active addresses which are no longer visible are
+ * automatically unconfigured and released, freeing the provider from
+ * the need to explicitly unconfigure addresses no longer present.
+ *
+ * Stabilization
+ * Once an address has been reported (or reported as removed), the report
+ * is time stabilized before the framework initiates a configuration
+ * or unconfiguration action. If the address is re-reported while undergoing
+ * stabilization, the timer is reset for either the address or the full
+ * set of addresses reported to the map.
+ *
+ * Activation/Release
+ * Once a reported address has passed its stabilization, the address is
+ * 'activated' by the framework. Once activated, the address is passed
+ * to a configuration callout to perform whatever actions are necessary.
+ * If a reported address is deleted or fails to stabilize, the address
+ * is released by the map.
+ * A report provider may register callback functions to be invoked
+ * as part of the address activation & release process. In addition to
+ * the callbacks, a provider can also supply a handle to provider-private
+ * data at the time an address is reported. This handle is returned to
+ * provider as an argument to the activation & release callbacks.
+ *
+ * Lookup/Access
+ * The set of stable addresses contained in a map can be obtained by
+ * calling interfaces to lookup either a single address or the full
+ * list of stable addresses.
+ */
+
+/*
+ * damap_t: Handle to a delta address map
+ * damap_id_t: Handle to an entry of damap_t
+ * damap_id_list_t: List of damap_id_handles
+ */
+typedef struct __damap_dm *damap_t;
+typedef struct __damap_id_list *damap_id_list_t;
+typedef id_t damap_id_t;
+
+#define NODAM (damap_id_t)0
+
+/*
+ * activate_cb: Provider callback when reported address is activated
+ * deactivate_cb: Provider callback when address has been released
+ *
+ * configure_cb: Class callout to configure newly activated addresses
+ * unconfig_cb: Class callout to unconfigure deactivated addresses
+ */
+typedef void (*damap_activate_cb_t)(void *, char *, int, void **);
+typedef void (*damap_deactivate_cb_t)(void *, char *, int, void *);
+
+typedef void (*damap_configure_cb_t)(void *, damap_t *, damap_id_list_t);
+typedef void (*damap_unconfig_cb_t)(void *, damap_t *, damap_id_list_t);
+
+/*
+ * Map reporting mode
+ */
+typedef enum {DAMAP_REPORT_PERADDR, DAMAP_REPORT_FULLSET} damap_rptmode_t;
+
+#define DAMAP_RESET 1 /* flag to damap_addrset_end */
+
+int damap_create(char *, size_t, damap_rptmode_t, clock_t,
+ void *, damap_activate_cb_t, damap_deactivate_cb_t,
+ void *, damap_configure_cb_t, damap_unconfig_cb_t,
+ damap_t **);
+void damap_destroy(damap_t *);
+
+char *damap_name(damap_t *);
+int damap_sync(damap_t *);
+
+int damap_addr_add(damap_t *, char *, damap_id_t *, nvlist_t *, void *);
+int damap_addr_del(damap_t *, char *);
+int damap_addrid_del(damap_t *, int);
+
+int damap_addrset_begin(damap_t *);
+int damap_addrset_add(damap_t *, char *, damap_id_t *, nvlist_t *, void *);
+int damap_addrset_end(damap_t *, int);
+int damap_addrset_reset(damap_t *, int);
+
+damap_id_t damap_id_next(damap_t *, damap_id_list_t, damap_id_t);
+char *damap_id2addr(damap_t *, damap_id_t);
+nvlist_t *damap_id2nvlist(damap_t *, damap_id_t);
+int damap_id_hold(damap_t *, damap_id_t);
+void damap_id_rele(damap_t *, damap_id_t);
+int damap_id_ref(damap_t *, damap_id_t);
+void damap_id_list_rele(damap_t *, damap_id_list_t);
+void *damap_id_priv_get(damap_t *, damap_id_t);
+void damap_id_priv_set(damap_t *, damap_id_t, void *);
+damap_id_t damap_lookup(damap_t *, char *);
+int damap_lookup_all(damap_t *, damap_id_list_t *);
+
+#define DAM_SUCCESS 0
+#define DAM_EEXIST 1
+#define DAM_MAPFULL 2
+#define DAM_EINVAL 3
+#define DAM_FAILURE 4
+#define DAM_SHAME 5
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_DAMAP_H */
diff --git a/usr/src/uts/common/sys/damap_impl.h b/usr/src/uts/common/sys/damap_impl.h
new file mode 100644
index 0000000000..1cbdad3716
--- /dev/null
+++ b/usr/src/uts/common/sys/damap_impl.h
@@ -0,0 +1,181 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_DAMAP_IMPL_H
+#define _SYS_DAMAP_IMPL_H
+
+#include <sys/isa_defs.h>
+#include <sys/dditypes.h>
+#include <sys/time.h>
+#include <sys/cmn_err.h>
+#include <sys/ddi_impldefs.h>
+#include <sys/ddi_implfuncs.h>
+#include <sys/ddi_isa.h>
+#include <sys/model.h>
+#include <sys/devctl.h>
+#include <sys/nvpair.h>
+#include <sys/sysevent.h>
+#include <sys/bitset.h>
+#include <sys/sdt.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct dam dam_t;
+
+/*
+ * activate_cb: Provider callback when reported address is activated
+ * deactivate_cb: Provider callback when address has been released
+ *
+ * configure_cb: Class callout to configure newly activated addresses
+ * unconfig_cb: Class callout to unconfigure deactivated addresses
+ */
+typedef void (*activate_cb_t)(void *, char *addr, int idx, void **privp);
+typedef void (*deactivate_cb_t)(void *, char *addr, int idx, void *priv);
+
+typedef void (*configure_cb_t)(void *, dam_t *mapp, bitset_t *config_ids);
+typedef void (*unconfig_cb_t)(void *, dam_t *mapp, bitset_t *unconfig_ids);
+
+struct dam {
+ char *dam_name;
+ int dam_flags; /* state and locks */
+ int dam_options; /* options at map creation */
+ int dam_rptmode; /* report mode */
+ clock_t dam_stabletmo; /* stabilization (ticks) */
+ uint_t dam_size; /* max index for addr hash */
+ id_t dam_high; /* highest index allocated */
+ timeout_id_t dam_tid; /* timeout(9F) ID */
+
+ void *dam_activate_arg; /* activation private */
+ activate_cb_t dam_activate_cb; /* activation callback */
+ deactivate_cb_t dam_deactivate_cb; /* deactivation callback */
+
+ void *dam_config_arg; /* config-private */
+ configure_cb_t dam_configure_cb; /* configure callout */
+ unconfig_cb_t dam_unconfig_cb; /* unconfigure callout */
+
+ ddi_strid *dam_addr_hash; /* addresss to ID hash */
+ bitset_t dam_active_set; /* activated address set */
+ bitset_t dam_stable_set; /* stable address set */
+ bitset_t dam_report_set; /* reported address set */
+ void *dam_da; /* per-address soft state */
+ ddi_taskq_t *dam_taskqp; /* taskq for map activation */
+ hrtime_t dam_last_update; /* last map update */
+ hrtime_t dam_last_stable; /* last map stable */
+ int dam_stable_cnt; /* # of times map stabilized */
+ int dam_stable_overrun;
+ kcondvar_t dam_cv;
+ kmutex_t dam_lock;
+ kstat_t *dam_kstatsp;
+};
+
+/*
+ * damap.dam_flags
+ */
+#define ADDR_LOCK 0x1000 /* per-addr lock */
+#define MAP_LOCK 0x2000 /* global map lock */
+#define DAM_LOCK(m, l) { \
+ mutex_enter(&(m)->dam_lock); \
+ while ((m)->dam_flags & (l)) \
+ cv_wait(&(m)->dam_cv, &(m)->dam_lock); \
+ (m)->dam_flags |= (l); \
+ mutex_exit(&(m)->dam_lock); \
+}
+#define DAM_UNLOCK(m, l) { \
+ mutex_enter(&(m)->dam_lock); \
+ (m)->dam_flags &= ~(l); \
+ cv_signal(&(m)->dam_cv); \
+ mutex_exit(&(m)->dam_lock); \
+}
+#define DAM_ASSERT_LOCKED(m, l) ASSERT((m)->dam_flags & (l))
+
+#define DAM_SPEND 0x10 /* stable pending */
+#define DAM_DESTROYPEND 0x20 /* in process of being destroyed */
+#define DAM_SETADD 0x100 /* fullset update pending */
+#define DAM_FLAG_SET(m, f) { \
+ mutex_enter(&(m)->dam_lock); \
+ (m)->dam_flags |= f; \
+ mutex_exit(&(m)->dam_lock); \
+}
+#define DAM_FLAG_CLR(m, f) { \
+ mutex_enter(&(m)->dam_lock); \
+ (m)->dam_flags &= ~f; \
+ mutex_exit(&(m)->dam_lock); \
+}
+
+/*
+ * per address softstate stucture
+ */
+typedef struct {
+ uint_t da_flags; /* flags */
+ int da_jitter; /* address report count */
+ int da_ref; /* refcount on address */
+ void *da_ppriv; /* stable provider private */
+ void *da_cfg_priv; /* config/unconfig private */
+ nvlist_t *da_nvl; /* stable nvlist */
+ void *da_ppriv_rpt; /* reported provider-private */
+ nvlist_t *da_nvl_rpt; /* reported nvlist */
+ int64_t da_deadline; /* lbolt64 value when stable */
+ hrtime_t da_last_report; /* timestamp of last report */
+ int da_report_cnt; /* # of times address reported */
+ hrtime_t da_last_stable; /* timestamp of last stable address */
+ int da_stable_cnt; /* # of times address has stabilized */
+ char *da_addr; /* string in dam_addr_hash (for mdb) */
+} dam_da_t;
+
+/*
+ * dam_da_t.da_flags
+ */
+#define DA_INIT 0x1 /* address initizized */
+#define DA_ACTIVE 0x2 /* address stable */
+#define DA_RELE 0x4 /* adddress released */
+
+
+/*
+ * report type
+ */
+#define RPT_ADDR_ADD 0
+#define RPT_ADDR_DEL 1
+
+#define DAM_IN_REPORT(m, i) (bitset_in_set(&(m)->dam_report_set, (i)))
+#define DAM_IS_STABLE(m, i) (bitset_in_set(&(m)->dam_active_set, (i)))
+
+/*
+ * DAM statistics
+ */
+struct dam_kstats {
+ struct kstat_named dam_stable;
+ struct kstat_named dam_stable_blocked;
+ struct kstat_named dam_rereport;
+ struct kstat_named dam_numstable;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_DAMAP_IMPL_H */
diff --git a/usr/src/uts/common/sys/ddi_impldefs.h b/usr/src/uts/common/sys/ddi_impldefs.h
index 7be6c896ad..5b5d103e08 100644
--- a/usr/src/uts/common/sys/ddi_impldefs.h
+++ b/usr/src/uts/common/sys/ddi_impldefs.h
@@ -40,6 +40,9 @@
#include <sys/ddidmareq.h>
#include <sys/ddi_intr.h>
#include <sys/ddi_isa.h>
+#include <sys/id_space.h>
+#include <sys/modhash.h>
+#include <sys/bitset.h>
#ifdef __cplusplus
extern "C" {
@@ -105,7 +108,7 @@ typedef struct devi_port {
} port;
uint64_t type64;
} info;
- void *priv_p;
+ void *priv_p;
} devi_port_t;
typedef struct devi_bus_priv {
@@ -145,7 +148,7 @@ struct dev_info {
struct dev_info *devi_next; /* Next instance of this device */
kmutex_t devi_lock; /* Protects per-devinfo data */
- /* logical parents for busop primitives */
+ /* logical parents for busop primitives */
struct dev_info *devi_bus_map_fault; /* bus_map_fault parent */
struct dev_info *devi_bus_dma_map; /* bus_dma_map parent */
@@ -395,12 +398,13 @@ struct dev_info {
#define DEVI_SET_DEVICE_REMOVED(dip) { \
ASSERT(mutex_owned(&DEVI(dip)->devi_lock)); \
- DEVI(dip)->devi_state |= DEVI_DEVICE_REMOVED; \
+ DEVI(dip)->devi_state |= DEVI_DEVICE_REMOVED | DEVI_S_REPORT; \
}
#define DEVI_SET_DEVICE_REINSERTED(dip) { \
ASSERT(mutex_owned(&DEVI(dip)->devi_lock)); \
DEVI(dip)->devi_state &= ~DEVI_DEVICE_REMOVED; \
+ DEVI(dip)->devi_state |= DEVI_S_REPORT; \
}
/* Bus state change macros */
@@ -691,11 +695,14 @@ struct ddi_minor {
*
* DDI_HIDDEN_NODE indicates that the node should not show up in snapshots
* or in /devices.
+ *
+ * DDI_HOTPLUG_NODE indicates that the node created by nexus hotplug.
*/
#define DDI_PERSISTENT 0x01
#define DDI_AUTO_ASSIGNED_NODEID 0x02
#define DDI_VHCI_NODE 0x04
#define DDI_HIDDEN_NODE 0x08
+#define DDI_HOTPLUG_NODE 0x10
#define DEVI_VHCI_NODE(dip) \
(DEVI(dip)->devi_node_attributes & DDI_VHCI_NODE)
@@ -741,16 +748,35 @@ struct ddi_parent_private_data {
#define sparc_pd_getintr(dev, n) (&DEVI_PD(dev)->par_intr[(n)])
#define sparc_pd_getrng(dev, n) (&DEVI_PD(dev)->par_rng[(n)])
+#ifdef _KERNEL
/*
- * This data structure is entirely private to the soft state allocator.
+ * This data structure is private to the indexed soft state allocator.
*/
-struct i_ddi_soft_state {
+typedef struct i_ddi_soft_state {
void **array; /* the array of pointers */
- kmutex_t lock; /* serialize access to this struct */
- size_t size; /* how many bytes per state struct */
+ kmutex_t lock; /* serialize access to this struct */
+ size_t size; /* how many bytes per state struct */
size_t n_items; /* how many structs herein */
struct i_ddi_soft_state *next; /* 'dirty' elements */
-};
+} i_ddi_soft_state;
+
+/*
+ * This data structure is private to the stringhashed soft state allocator.
+ */
+typedef struct i_ddi_soft_state_bystr {
+ size_t ss_size; /* how many bytes per state struct */
+ mod_hash_t *ss_mod_hash; /* hash implementation */
+} i_ddi_soft_state_bystr;
+
+/*
+ * This data structure is private to the ddi_strid_* implementation
+ */
+typedef struct i_ddi_strid {
+ id_space_t *strid_space;
+ mod_hash_t *strid_byid;
+ mod_hash_t *strid_bystr;
+} i_ddi_strid;
+#endif /* _KERNEL */
/*
* Solaris DDI DMA implementation structure and function definitions.
diff --git a/usr/src/uts/common/sys/devctl.h b/usr/src/uts/common/sys/devctl.h
index a201fded95..5dce50c72a 100644
--- a/usr/src/uts/common/sys/devctl.h
+++ b/usr/src/uts/common/sys/devctl.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -41,7 +41,7 @@ extern "C" {
* and nexus driver devctl IOCTL interface.
*
* Applications and nexus drivers may not access the contents of this
- * structure directly. Instead, drivers must use the ndi_dc_XXX(9n)
+ * structure directly. Instead, drivers must use the ndi_dc_*(9n)
* interfaces, while applications must use the interfaces provided by
* libdevice.so.1.
*/
@@ -230,6 +230,9 @@ typedef struct devctl_ap_state32 {
#define BUS_QUIESCED 0x20
#define BUS_SHUTDOWN 0x40
+#define DEVICE_STATES_ASCII "Dev_Online", "Dev_Busy", "Dev_Offline", \
+ "Dev_Down", "Bus_Active", "Bus_Quiesced", "Bus_Shutdown"
+
#define DC_DEVI_NODENAME "ndi_dc.devi_nodename"
#define DEVCTL_CONSTRUCT 0x1
diff --git a/usr/src/uts/common/sys/devinfo_impl.h b/usr/src/uts/common/sys/devinfo_impl.h
index e64f5fc601..4f874ea1e3 100644
--- a/usr/src/uts/common/sys/devinfo_impl.h
+++ b/usr/src/uts/common/sys/devinfo_impl.h
@@ -317,6 +317,7 @@ struct di_path {
uint_t path_snap_state; /* describes valid fields */
int path_instance; /* path instance */
uint64_t user_private_data;
+ uint_t path_flags; /* path flags */
};
/*
@@ -331,6 +332,11 @@ struct di_path {
#define DI_PATH_SNAP_LINKS 0x40 /* linkages have been postprocessed */
/*
+ * Flags for path_flags
+ */
+#define DI_PATH_FLAGS_DEVICE_REMOVED 0x01 /* peer of DI_DEVICE_REMOVED */
+
+/*
* path properties
*/
struct di_path_prop {
diff --git a/usr/src/uts/common/sys/id_space.h b/usr/src/uts/common/sys/id_space.h
index c6f7246658..1f7762316f 100644
--- a/usr/src/uts/common/sys/id_space.h
+++ b/usr/src/uts/common/sys/id_space.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _ID_SPACE_H
#define _ID_SPACE_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -47,6 +44,8 @@ void id_space_destroy(id_space_t *);
void id_space_extend(id_space_t *, id_t, id_t);
id_t id_alloc(id_space_t *);
id_t id_alloc_nosleep(id_space_t *);
+id_t id_allocff(id_space_t *);
+id_t id_allocff_nosleep(id_space_t *);
void id_free(id_space_t *, id_t);
#endif /* _KERNEL */
diff --git a/usr/src/uts/common/sys/mdi_impldefs.h b/usr/src/uts/common/sys/mdi_impldefs.h
index 0f2b0dfe58..563c62af08 100644
--- a/usr/src/uts/common/sys/mdi_impldefs.h
+++ b/usr/src/uts/common/sys/mdi_impldefs.h
@@ -342,7 +342,7 @@ typedef struct mdi_phci {
struct mdi_phci *ph_next; /* next pHCI link */
struct mdi_phci *ph_prev; /* prev pHCI link */
dev_info_t *ph_dip; /* pHCI devi handle */
- struct mdi_vhci *ph_vhci; /* pHCI back ref. to vHCI */
+ struct mdi_vhci *ph_vhci; /* pHCI back ref. to vHCI */
/* protected by MDI_PHCI_LOCK ph_mutex... */
kmutex_t ph_mutex; /* per-pHCI mutex */
@@ -398,7 +398,7 @@ typedef struct mdi_phci {
#define MDI_PHCI_IS_READY(ph) \
(((ph)->ph_flags & MDI_PHCI_DISABLE_MASK) == 0)
-#define MDI_PHCI_SET_OFFLINE(ph) {\
+#define MDI_PHCI_SET_OFFLINE(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags |= MDI_PHCI_FLAGS_OFFLINE; }
#define MDI_PHCI_SET_ONLINE(ph) {\
@@ -407,7 +407,7 @@ typedef struct mdi_phci {
#define MDI_PHCI_IS_OFFLINE(ph) \
((ph)->ph_flags & MDI_PHCI_FLAGS_OFFLINE)
-#define MDI_PHCI_SET_SUSPEND(ph) {\
+#define MDI_PHCI_SET_SUSPEND(ph) {\
ASSERT(MDI_PHCI_LOCKED(ph)); \
(ph)->ph_flags |= MDI_PHCI_FLAGS_SUSPEND; }
#define MDI_PHCI_SET_RESUME(ph) {\
@@ -501,7 +501,7 @@ typedef struct mdi_phci {
* OPTIMAL - Client device has at least one redundant path.
* DEGRADED - No redundant paths (critical). Failure in the current active
* path would result in data access failures.
- * FAILED - No paths are available to access this device.
+ * FAILED - No paths are available to access this device.
*
* Locking order:
*
@@ -517,7 +517,7 @@ typedef struct mdi_client {
char *ct_drvname; /* client driver name */
char *ct_guid; /* client guid */
client_lb_t ct_lb; /* load balancing scheme */
- client_lb_args_t *ct_lb_args; /* load balancing args */
+ client_lb_args_t *ct_lb_args; /* load balancing args */
/* protected by MDI_CLIENT_LOCK ct_mutex... */
@@ -726,8 +726,9 @@ struct mdi_pathinfo {
kcondvar_t pi_ref_cv; /* condition variable */
struct mdi_pi_kstats *pi_kstats; /* aggregate kstats */
int pi_pm_held; /* phci's kidsup incremented */
- int pi_preferred; /* Preferred path */
+ int pi_preferred; /* Preferred path */
void *pi_vprivate; /* vhci private info */
+ uint_t pi_flags; /* path flags */
};
/*
@@ -959,6 +960,26 @@ struct pi_errs {
#define MDI_PI_IS_SUSPENDED(pip) \
((MDI_PI(pip))->pi_phci->ph_flags & MDI_PHCI_FLAGS_SUSPEND)
+#define MDI_PI_FLAGS_SET_HIDDEN(pip) {\
+ ASSERT(MDI_PI_LOCKED(pip)); \
+ MDI_PI(pip)->pi_flags |= MDI_PATHINFO_FLAGS_HIDDEN; }
+#define MDI_PI_FLAGS_CLR_HIDDEN(pip) {\
+ ASSERT(MDI_PI_LOCKED(pip)); \
+ MDI_PI(pip)->pi_flags &= ~MDI_PATHINFO_FLAGS_HIDDEN; }
+#define MDI_PI_FLAGS_IS_HIDDEN(pip) \
+ ((MDI_PI(pip)->pi_flags & MDI_PATHINFO_FLAGS_HIDDEN) == \
+ MDI_PATHINFO_FLAGS_HIDDEN)
+
+#define MDI_PI_FLAGS_SET_DEVICE_REMOVED(pip) {\
+ ASSERT(MDI_PI_LOCKED(pip)); \
+ MDI_PI(pip)->pi_flags |= MDI_PATHINFO_FLAGS_DEVICE_REMOVED; }
+#define MDI_PI_FLAGS_CLR_DEVICE_REMOVED(pip) {\
+ ASSERT(MDI_PI_LOCKED(pip)); \
+ MDI_PI(pip)->pi_flags &= ~MDI_PATHINFO_FLAGS_DEVICE_REMOVED; }
+#define MDI_PI_FLAGS_IS_DEVICE_REMOVED(pip) \
+ ((MDI_PI(pip)->pi_flags & MDI_PATHINFO_FLAGS_DEVICE_REMOVED) == \
+ MDI_PATHINFO_FLAGS_DEVICE_REMOVED)
+
/*
* mdi_vhcache_client, mdi_vhcache_pathinfo, and mdi_vhcache_phci structures
* hold the vhci to phci client mappings of the on-disk vhci busconfig cache.
diff --git a/usr/src/uts/common/sys/scsi/adapters/mpapi_impl.h b/usr/src/uts/common/sys/scsi/adapters/mpapi_impl.h
index b54df92613..1f69323c62 100644
--- a/usr/src/uts/common/sys/scsi/adapters/mpapi_impl.h
+++ b/usr/src/uts/common/sys/scsi/adapters/mpapi_impl.h
@@ -19,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_SCSI_ADAPTERS_MPAPI_IMPL_H
#define _SYS_SCSI_ADAPTERS_MPAPI_IMPL_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/sunmdi.h>
#include <sys/sunddi.h>
#include <sys/mdi_impldefs.h>
@@ -253,6 +251,7 @@ typedef struct mp_path_prop {
#define MP_DRVR_PATH_STATE_REMOVED 5
#define MP_DRVR_PATH_STATE_TRANSITIONING 6
#define MP_DRVR_PATH_STATE_UNKNOWN 7
+#define MP_DRVR_PATH_STATE_UNINIT 8
/* Structure for MP_PROPRIETARY_LOAD_BALANCE_PROPERTIES */
diff --git a/usr/src/uts/common/sys/scsi/adapters/mpapi_scsi_vhci.h b/usr/src/uts/common/sys/scsi/adapters/mpapi_scsi_vhci.h
index dcb359c13e..652258acff 100644
--- a/usr/src/uts/common/sys/scsi/adapters/mpapi_scsi_vhci.h
+++ b/usr/src/uts/common/sys/scsi/adapters/mpapi_scsi_vhci.h
@@ -19,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_SCSI_ADAPTERS_MPAPI_SCSI_VHCI_H
#define _SYS_SCSI_ADAPTERS_MPAPI_SCSI_VHCI_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -110,11 +108,18 @@ typedef struct mpapi_lu_data {
/*
* Structure to maintain mpapi path data.
+ *
+ * The hide flag is set when pip was detroyed or should
+ * have been destroyed(MDI_PATHINFO_FLAGS_DEVICE_REMOVED).
+ * The valid flag is set to 0 when the path is neither online
+ * nor standby state. When hide flag is set the valid flag set
+ * to 0 also.
*/
typedef struct mpapi_path_data {
void *resp; /* pip */
char *path_name;
int valid;
+ int hide;
char pclass[MPAPI_SCSI_MAXPCLASSLEN];
mp_path_prop_t prop;
} mpapi_path_data_t;
diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/ata.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/ata.h
new file mode 100644
index 0000000000..f503d856ff
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/ata.h
@@ -0,0 +1,279 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Misc ATA definitions
+ */
+#ifndef _ATA_H
+#define _ATA_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ata8-acs.h"
+#include "atapi7v3.h"
+
+/*
+ * IDENTIFY Data
+ */
+typedef struct {
+ uint16_t word0;
+ uint16_t word1;
+ uint16_t word2;
+ uint16_t word3;
+ uint16_t word4;
+ uint16_t word5;
+ uint16_t word6;
+ uint16_t word7;
+ uint16_t word8;
+ uint16_t word9;
+ uint16_t serial_number[10];
+ uint16_t word20;
+ uint16_t word21;
+ uint16_t word22;
+ uint16_t firmware_revision[4];
+ uint16_t model_number[20];
+ uint16_t word47;
+ uint16_t word48;
+ uint16_t word49;
+ uint16_t word50;
+ uint16_t word51;
+ uint16_t word52;
+ uint16_t word53;
+ uint16_t word54;
+ uint16_t word55;
+ uint16_t word56;
+ uint16_t word57;
+ uint16_t word58;
+ uint16_t word59;
+ uint16_t word60;
+ uint16_t word61;
+ uint16_t word62;
+ uint16_t word63;
+ uint16_t word64;
+ uint16_t word65;
+ uint16_t word66;
+ uint16_t word67;
+ uint16_t word68;
+ uint16_t word69;
+ uint16_t word70;
+ uint16_t word71;
+ uint16_t word72;
+ uint16_t word73;
+ uint16_t word74;
+ uint16_t word75;
+ uint16_t word76;
+ uint16_t word77;
+ uint16_t word78;
+ uint16_t word79;
+ uint16_t word80;
+ uint16_t word81;
+ uint16_t word82;
+ uint16_t word83;
+ uint16_t word84;
+ uint16_t word85;
+ uint16_t word86;
+ uint16_t word87;
+ uint16_t word88;
+ uint16_t word89;
+ uint16_t word90;
+ uint16_t word91;
+ uint16_t word92;
+ uint16_t word93;
+ uint16_t word94;
+ uint16_t word95;
+ uint16_t word96;
+ uint16_t word97;
+ uint16_t word98;
+ uint16_t word99;
+ uint16_t word100;
+ uint16_t word101;
+ uint16_t word102;
+ uint16_t word103;
+ uint16_t word104;
+ uint16_t word105;
+ uint16_t word106;
+ uint16_t word107;
+ uint16_t word108;
+ uint16_t word109;
+ uint16_t word110;
+ uint16_t word111;
+ uint16_t word112;
+ uint16_t word113;
+ uint16_t word114;
+ uint16_t word115;
+ uint16_t word116;
+ uint16_t word117;
+ uint16_t word118;
+ uint16_t word119;
+ uint16_t word120;
+ uint16_t word121;
+ uint16_t word122;
+ uint16_t word123;
+ uint16_t word124;
+ uint16_t word125;
+ uint16_t word126;
+ uint16_t word127;
+ uint16_t word128;
+ uint16_t word129;
+ uint16_t word130;
+ uint16_t word131;
+ uint16_t word132;
+ uint16_t word133;
+ uint16_t word134;
+ uint16_t word135;
+ uint16_t word136;
+ uint16_t word137;
+ uint16_t word138;
+ uint16_t word139;
+ uint16_t word140;
+ uint16_t word141;
+ uint16_t word142;
+ uint16_t word143;
+ uint16_t word144;
+ uint16_t word145;
+ uint16_t word146;
+ uint16_t word147;
+ uint16_t word148;
+ uint16_t word149;
+ uint16_t word150;
+ uint16_t word151;
+ uint16_t word152;
+ uint16_t word153;
+ uint16_t word154;
+ uint16_t word155;
+ uint16_t word156;
+ uint16_t word157;
+ uint16_t word158;
+ uint16_t word159;
+ uint16_t word160;
+ uint16_t word161;
+ uint16_t word162;
+ uint16_t word163;
+ uint16_t word164;
+ uint16_t word165;
+ uint16_t word166;
+ uint16_t word167;
+ uint16_t word168;
+ uint16_t word169;
+ uint16_t word170;
+ uint16_t word171;
+ uint16_t word172;
+ uint16_t word173;
+ uint16_t word174;
+ uint16_t word175;
+ uint16_t word176;
+ uint16_t word177;
+ uint16_t word178;
+ uint16_t word179;
+ uint16_t word180;
+ uint16_t word181;
+ uint16_t word182;
+ uint16_t word183;
+ uint16_t word184;
+ uint16_t word185;
+ uint16_t word186;
+ uint16_t word187;
+ uint16_t word188;
+ uint16_t word189;
+ uint16_t word190;
+ uint16_t word191;
+ uint16_t word192;
+ uint16_t word193;
+ uint16_t word194;
+ uint16_t word195;
+ uint16_t word196;
+ uint16_t word197;
+ uint16_t word198;
+ uint16_t word199;
+ uint16_t word200;
+ uint16_t word201;
+ uint16_t word202;
+ uint16_t word203;
+ uint16_t word204;
+ uint16_t word205;
+ uint16_t word206;
+ uint16_t word207;
+ uint16_t word208;
+ uint16_t word209;
+ uint16_t word210;
+ uint16_t word211;
+ uint16_t word212;
+ uint16_t word213;
+ uint16_t word214;
+ uint16_t word215;
+ uint16_t word216;
+ uint16_t word217;
+ uint16_t word218;
+ uint16_t word219;
+ uint16_t word220;
+ uint16_t word221;
+ uint16_t word222;
+ uint16_t word223;
+ uint16_t word224;
+ uint16_t word225;
+ uint16_t word226;
+ uint16_t word227;
+ uint16_t word228;
+ uint16_t word229;
+ uint16_t word230;
+ uint16_t word231;
+ uint16_t word232;
+ uint16_t word233;
+ uint16_t word234;
+ uint16_t word235;
+ uint16_t word236;
+ uint16_t word237;
+ uint16_t word238;
+ uint16_t word239;
+ uint16_t word240;
+ uint16_t word241;
+ uint16_t word242;
+ uint16_t word243;
+ uint16_t word244;
+ uint16_t word245;
+ uint16_t word246;
+ uint16_t word247;
+ uint16_t word248;
+ uint16_t word249;
+ uint16_t word250;
+ uint16_t word251;
+ uint16_t word252;
+ uint16_t word253;
+ uint16_t word254;
+ uint16_t word255;
+} ata_identify_t;
+
+#define LBA_CAPACITY(ati) \
+ ((LE_16(ati->word83) & (1 << 10)) == 0)? \
+ (LE_16(ati->word60) | ((LE_16(ati->word61)) << 16)) : \
+ ((LE_16(ati->word100)) | ((LE_16(ati->word101)) << 16) | \
+ (((uint64_t)LE_16(ati->word102)) << 32) | \
+ (((uint64_t)LE_16(ati->word103)) << 48))
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _ATA_H */
diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/ata8-acs.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/ata8-acs.h
new file mode 100644
index 0000000000..6f0cc2d2cf
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/ata8-acs.h
@@ -0,0 +1,122 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * ATA8-ACS Definitions (subset) Working Draft AT Attachment 8 - ATA/ATAPI
+ * Command Set (D1699r4c)
+ */
+#ifndef _ATA8_ACS_H
+#define _ATA8_ACS_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * ATA Command Set
+ */
+enum ata_opcode {
+ ATA_NOP = 0x00,
+ CFA_REQUEST_EXTENDED_ERROR = 0x03,
+ DEVICE_RESET = 0x08,
+ READ_SECTORS = 0x20,
+ READ_SECTORS_EXT = 0x24,
+ READ_DMA_EXT = 0x25,
+ READ_DMA_QUEUED_EXT = 0x26,
+ READ_NATIVE_MAX_ADDRESS_EXT = 0x27,
+ READ_MULTIPLE_EXT = 0x29,
+ READ_STREAM_DMA_EXT = 0x2A,
+ READ_STREAM_EXT = 0x2B,
+ READ_LOG_EXT = 0x2F,
+ WRITE_SECTORS = 0x30,
+ WRITE_SECTORS_EXT = 0x34,
+ WRITE_DMA_EXT = 0x35,
+ WRITE_DMA_QUEUED_EXT = 0x36,
+ SET_MAX_ADDRESS_EXT = 0x37,
+ CFA_WRITE_SECTORS_WITHOUT_ERASE = 0x38,
+ WRITE_MULTIPLE_EXT = 0x39,
+ WRITE_STREAM_DMA_EXT = 0x3A,
+ WRITE_STREAM_EXT = 0x3B,
+ WRITE_DMA_FUA_EXT = 0x3D,
+ WRITE_DMA_QUEUED_FUA_EXT = 0x3E,
+ WRITE_LOG_EXT = 0x3F,
+ READ_VERIFY_SECTORS = 0x40,
+ READ_VERIFY_SECTORS_EXT = 0x42,
+ WRITE_UNCORRECTABLE_EXT = 0x45,
+ READ_LOG_DMA_EXT = 0x47,
+ CONFIGURE_STREAM = 0x51,
+ WRITE_LOG_DMA_EXT = 0x57,
+ TRUSTED_NON_DATA = 0x5B,
+ TRUSTED_RECEIVE = 0x5C,
+ TRUSTED_RECEIVE_DMA = 0x5D,
+ TRUSTED_SEND = 0x5E,
+ TRUSTED_SEND_DMA = 0x5E,
+ READ_FPDMA_QUEUED = 0x60,
+ WRITE_FPDMA_QUEUED = 0x61,
+ CFA_TRANSLATE_SECTOR = 0x87,
+ EXECUTE_DEVICE_DIAGNOSTIC = 0x90,
+ DOWNLOAD_MICROCODE = 0x92,
+ PACKET = 0xA0,
+ IDENTIFY_PACKET_DEVICE = 0xA1,
+ SERVICE = 0xA2,
+ SMART = 0xB0,
+ DEVICE_CONFIGURATION_OVERLAY = 0xB1,
+ NV_CACHE = 0xB6,
+ CFA_ERASE_SECTORS = 0xC0,
+ READ_MULTIPLE = 0xC4,
+ WRITE_MULTIPLE = 0xC5,
+ SET_MULTIPLE_MODE = 0xC6,
+ READ_DMA_QUEUED = 0xC7,
+ READ_DMA = 0xC8,
+ WRITE_DMA = 0xCA,
+ WRITE_DMA_QUEUED = 0xCC,
+ CFA_WRITE_MULTIPLE_WITHOUT_ERASE = 0xCD,
+ WRITE_MULTIPLE_FUA_EXT = 0xCE,
+ CHECK_MEDIA_CARD_TYPE = 0xD1,
+ STANDBY_IMMEDIATE = 0xE0,
+ IDLE_IMMEDIATE = 0xE1,
+ STANDBY = 0xE2,
+ IDLE = 0xE3,
+ ATA_READ_BUFFER = 0xE4,
+ CHECK_POWER_MODE = 0xE5,
+ SLEEP = 0xE6,
+ FLUSH_CACHE = 0xE7,
+ ATA_WRITE_BUFFER = 0xE8,
+ FLUSH_CACHE_EXT = 0xEA,
+ IDENTIFY_DEVICE = 0xEC,
+ MEDIA_EJECT = 0xED,
+ SET_FEATURES = 0xEF,
+ SECURITY_SET_PASSWORD = 0xF1,
+ SECURITY_UNLOCK = 0xF2,
+ SECURITY_ERASE_PREPARE = 0xF3,
+ SECURITY_ERASE_UNIT = 0xF4,
+ SECURITY_FREEZE_LOCK = 0xF5,
+ SECURITY_DISABLE_PASSWORD = 0xF6,
+ READ_NATIVE_MAX_ADDRESS = 0xF8,
+ SET_MAX_ADDRESS = 0xF9
+};
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _ATA8_ACS_H */
diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/atapi7v3.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/atapi7v3.h
new file mode 100644
index 0000000000..e1bdf10af2
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/atapi7v3.h
@@ -0,0 +1,228 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * ATAPI-7 Definitions (subset) that include Serial ATA
+ * ATA/ATAPI-7 V3 (d1532v3r4b-ATA-ATAPI-7)
+ */
+#ifndef _ATAPI7V3_H
+#define _ATAPI7V3_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Register - Host to Device FIS
+ */
+typedef struct {
+ uint8_t fis_type;
+ uint8_t idcbits;
+ uint8_t cmd;
+ uint8_t features;
+#define FEATURE_LBA 0x40
+ uint8_t lba_low;
+ uint8_t lba_mid;
+ uint8_t lba_hi;
+ uint8_t device;
+ uint8_t lba_low_exp;
+ uint8_t lba_mid_exp;
+ uint8_t lba_hi_exp;
+ uint8_t features_exp;
+ uint8_t sector_count;
+ uint8_t sector_count_exp;
+ uint8_t reserved0;
+ uint8_t control;
+ uint8_t reserved1[4];
+} register_h2d_fis_t;
+
+/*
+ * Register - Device to Host FIS
+ */
+typedef struct {
+ uint8_t fis_type;
+ uint8_t idcbits;
+ uint8_t status;
+ uint8_t error;
+ uint8_t lba_low;
+ uint8_t lba_mid;
+ uint8_t lba_hi;
+ uint8_t device;
+ uint8_t lba_low_exp;
+ uint8_t lba_mid_exp;
+ uint8_t lba_hi_exp;
+ uint8_t reserved0;
+ uint8_t sector_count;
+ uint8_t sector_count_exp;
+ uint8_t reserved1[6];
+} register_d2h_fis_t;
+
+typedef struct {
+ uint8_t fis_type;
+ uint8_t idcbits;
+ uint8_t status_bits;
+#define STATUS_HI_MASK 0xE
+#define STATUS_HI_SHIFT 4
+#define STATUS_LO_MASK 0x7
+ uint8_t error;
+ uint8_t reserved;
+} set_device_bits_fis_t;
+
+typedef struct {
+ uint8_t fis_type;
+ uint8_t reserved[3];
+} dma_activate_fis_type;
+
+typedef struct {
+ uint8_t fis_type;
+ uint8_t idcbits;
+ uint8_t reserved0[2];
+ uint32_t dma_buffer_id_lo;
+ uint32_t dma_buffer_id_hi;
+ uint32_t reserved1;
+ uint32_t dma_buffer_offset;
+ uint32_t dma_buffer_count;
+ uint32_t reserved2;
+} dma_fpactivate_fis_t;
+
+typedef struct {
+ uint8_t fis_type;
+ uint8_t reserved0;
+ uint8_t bist_bits;
+ uint8_t reserved1;
+ uint8_t data[8];
+} bist_activate_fis_t;
+#define BIST_T 0x80
+#define BIST_A 0x40
+#define BIST_S 0x20
+#define BIST_L 0x10
+#define BIST_F 0x08
+#define BIST_P 0x04
+#define BIST_V 0x01
+
+typedef struct {
+ uint8_t fis_type;
+ uint8_t idcbits;
+ uint8_t status;
+ uint8_t error;
+ uint8_t lba_low;
+ uint8_t lba_mid;
+ uint8_t lba_high;
+ uint8_t device;
+ uint8_t lba_low_exp;
+ uint8_t lba_mid_exp;
+ uint8_t lba_high_exp;
+ uint8_t reserved0;
+ uint8_t sector_count;
+ uint8_t sector_count_exp;
+ uint8_t reserved1;
+ uint8_t E_status;
+ uint16_t transfer_count;
+ uint16_t reserved2;
+} pio_setup_fis_t;
+
+typedef struct {
+ uint8_t fis_type;
+ uint32_t dwords[1];
+} bidirectional_fis_t;
+
+/*
+ * FIS Types
+ */
+
+#define FIS_REG_H2DEV 0x27 /* 5 DWORDS */
+#define FIS_REG_D2H 0x34 /* 5 DWORDS */
+#define FIS_SET_DEVICE_BITS 0xA1 /* 2 DWORDS */
+#define FIS_DMA_ACTIVATE 0x39 /* 1 DWORD */
+#define FIS_DMA_FPSETUP 0x41 /* 7 DWORDS */
+#define FIS_BIST_ACTIVATE 0x58 /* 3 DWORDS */
+#define FIS_PIO_SETUP 0x5F /* 5 DWORDS */
+#define FIS_BI 0x46 /* 1 DWORD min, 2048 DWORD max */
+
+/*
+ * IDC bits
+ */
+#define C_BIT 0x80
+#define I_BIT 0x40
+#define D_BIT 0x20
+
+/*
+ * 28-Bit Command Mapping from ACS to FIS
+ *
+ * ACS Field FIS Field
+ * --------------------------------------
+ * Feature (7:0) -> Feature
+ * Count (7:0) -> Sector Count
+ * LBA (7:0) -> LBA Low
+ * LBA (15:8) -> LBA Mid
+ * LBA (23:16) -> LBA High
+ * LBA (27:24) -> Device (3:0)
+ * Device (15:12) -> Device (7:4)
+ * Command -> Command
+ *
+ * 48- Bit Command Mapping from ACS to FIS
+ *
+ * ACS Field FIS Field
+ * --------------------------------------
+ * Feature (7:0) -> Feature
+ * Feature (15:8) -> Feature (exp)
+ * Count (7:0) -> Sector Count
+ * Count (15:8) -> Sector Count (exp)
+ * LBA (7:0) -> LBA Low
+ * LBA (15:8) -> LBA Mid
+ * LBA (23:16) -> LBA High
+ * LBA (31:24) -> LBA Low (exp)
+ * LBA (39:32) -> LBA Mid (exp)
+ * LBA (47:40) -> LBA High (exp)
+ * Device (15:12) -> Device (7:4)
+ * Command -> Command
+ *
+ * FIS (FIS_REG_H2DEV) layout:
+ *
+ * 31.........24 23...........16 15....................8.7.............0
+ * FEATURE | COMMAND | C R R RESERVED | FIS TYPE 0x27
+ * DEVICE | LBA HIGH | LBA MID | LBA LOW
+ * FEATURE(exp) | LBA HIGH(exp) | LBA MID(exp) | LBA LOW(exp)
+ * CONTROL | RESERVED | Sector Count(exp) | Sector Count
+ * RESERVED | RESERVED | RESERVED | RESERVED
+ *
+ * FIS (FIS_REG_D2H) layout:
+ *
+ * 31.........24 23...........16 15....................8.7.............0
+ * ERROR | STATUS | R I R RESERVED | FIS TYPE 0x34
+ * DEVICE | LBA HIGH | LBA MID | LBA LOW
+ * RESERVED | LBA HIGH(exp) | LBA MID(exp) | LBA LOW(exp)
+ * RESERVED | RESERVED | Sector Count(exp) | Sector Count
+ * RESERVED | RESERVED | RESERVED | RESERVED
+ */
+
+
+/*
+ * Reasonable size to reserve for holding the most common FIS types.
+ */
+typedef uint32_t fis_t[5];
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _ATAPI7V3_H */
diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs.h
new file mode 100644
index 0000000000..074560eeb6
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs.h
@@ -0,0 +1,627 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * This file is the principle header file for the PMCS driver
+ */
+#ifndef _PMCS_H
+#define _PMCS_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include <sys/cpuvar.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/modctl.h>
+#include <sys/pci.h>
+#include <sys/pcie.h>
+#include <sys/isa_defs.h>
+#include <sys/sunmdi.h>
+#include <sys/mdi_impldefs.h>
+#include <sys/scsi/scsi.h>
+#include <sys/scsi/impl/scsi_reset_notify.h>
+#include <sys/scsi/impl/sas_transport.h>
+#include <sys/scsi/generic/sas.h>
+#include <sys/atomic.h>
+#include <sys/byteorder.h>
+#include <sys/bitmap.h>
+#include <sys/queue.h>
+#include <sys/sdt.h>
+#include <sys/ddifm.h>
+#include <sys/fm/protocol.h>
+#include <sys/fm/util.h>
+#include <sys/fm/io/ddi.h>
+#include <sys/scsi/impl/spc3_types.h>
+
+typedef struct pmcs_hw pmcs_hw_t;
+typedef struct pmcs_iport pmcs_iport_t;
+typedef struct pmcs_phy pmcs_phy_t;
+typedef struct lsas_cmd lsas_cmd_t;
+typedef struct lsas_result lsas_result_t;
+typedef struct lsata_cmd lsata_cmd_t;
+typedef struct lsata_result lsata_result_t;
+typedef struct pmcwork pmcwork_t;
+typedef struct pmcs_cmd pmcs_cmd_t;
+typedef struct pmcs_xscsi pmcs_xscsi_t;
+typedef struct pmcs_lun pmcs_lun_t;
+typedef struct pmcs_chunk pmcs_chunk_t;
+
+#include <sys/scsi/adapters/pmcs/pmcs_param.h>
+#include <sys/scsi/adapters/pmcs/pmcs_reg.h>
+#include <sys/scsi/adapters/pmcs/pmcs_mpi.h>
+#include <sys/scsi/adapters/pmcs/pmcs_iomb.h>
+#include <sys/scsi/adapters/pmcs/pmcs_sgl.h>
+
+#include <sys/scsi/adapters/pmcs/smp_defs.h>
+#include <sys/scsi/adapters/pmcs/ata.h>
+#include <sys/scsi/adapters/pmcs/pmcs_def.h>
+#include <sys/scsi/adapters/pmcs/pmcs_proto.h>
+#include <sys/scsi/adapters/pmcs/pmcs_scsa.h>
+#include <sys/scsi/adapters/pmcs/pmcs_smhba.h>
+
+#define PMCS_MAX_UA_SIZE 32
+
+struct pmcs_xscsi {
+ uint32_t
+ ca : 1, /* SATA specific */
+ ncq : 1, /* SATA specific */
+ pio : 1, /* SATA specific */
+ special_needed : 1, /* SATA specific */
+ special_running : 1, /* SATA specific */
+ reset_success : 1, /* last reset ok */
+ reset_wait : 1, /* wait for reset */
+ resetting : 1, /* now resetting */
+ recover_wait : 1, /* wait for recovery */
+ recovering : 1, /* now recovering */
+ event_recovery : 1, /* event recovery */
+ draining : 1,
+ dying : 1,
+ new : 1,
+ assigned : 1,
+ dev_gone : 1,
+ phy_addressable : 1, /* Direct attach SATA */
+ dev_state : 4;
+ uint16_t maxdepth;
+ uint16_t qdepth;
+ uint16_t actv_cnt;
+ uint16_t target_num;
+ /* statlock protects both target stats and the special queue (sq) */
+ kmutex_t statlock;
+ int32_t ref_count;
+ dev_info_t *dip; /* Solaris device dip */
+ pmcs_phy_t *phy;
+ STAILQ_HEAD(wqh, pmcs_cmd) wq;
+ pmcs_cmd_t *wq_recovery_tail; /* See below */
+ kmutex_t wqlock;
+ STAILQ_HEAD(aqh, pmcs_cmd) aq;
+ kmutex_t aqlock;
+ STAILQ_HEAD(sqh, pmcs_cmd) sq; /* SATA specific */
+ uint32_t tagmap; /* SATA specific */
+ pmcs_hw_t *pwp;
+ ddi_soft_state_bystr *lun_sstate;
+ uint64_t capacity; /* SATA specific */
+ char unit_address[PMCS_MAX_UA_SIZE];
+ kcondvar_t reset_cv;
+ kcondvar_t abort_cv;
+ char *ua;
+ pmcs_dtype_t dtype;
+};
+
+/*
+ * wq_recovery_tail in the pmcs_xscsi structure is a pointer to a command in
+ * the wait queue (wq). That pointer is the last command in the wait queue
+ * that needs to be reissued after device state recovery is complete. Commands
+ * that need to be retried are reinserted into the wq after wq_recovery_tail
+ * to maintain the order in which the commands were originally submitted.
+ */
+
+#define PMCS_INVALID_TARGET_NUM (uint16_t)-1
+
+#define PMCS_TGT_WAIT_QUEUE 0x01
+#define PMCS_TGT_ACTIVE_QUEUE 0x02
+#define PMCS_TGT_SPECIAL_QUEUE 0x04
+#define PMCS_TGT_ALL_QUEUES 0xff
+
+/*
+ * LUN representation. Just a LUN (number) and pointer to the target
+ * structure (pmcs_xscsi).
+ */
+
+struct pmcs_lun {
+ pmcs_xscsi_t *target;
+ uint64_t lun_num; /* lun64 */
+ scsi_lun_t scsi_lun; /* Wire format */
+ char unit_address[PMCS_MAX_UA_SIZE];
+};
+
+/*
+ * Interrupt coalescing values
+ */
+#define PMCS_MAX_IO_COMPS_PER_INTR 12
+#define PMCS_MAX_IO_COMPS_HIWAT_SHIFT 6
+#define PMCS_MAX_IO_COMPS_LOWAT_SHIFT 10
+#define PMCS_QUANTUM_TIME_USECS (1000000 / 10) /* 1/10th sec. */
+#define PMCS_MAX_COAL_TIMER 0x200 /* Don't set > than this */
+#define PMCS_MAX_CQ_THREADS 4
+#define PMCS_COAL_TIMER_GRAN 2 /* Go up/down by 2 usecs */
+#define PMCS_INTR_THRESHOLD(x) ((x) * 6 / 10)
+
+/*
+ * This structure is used to maintain state with regard to I/O interrupt
+ * coalescing.
+ */
+
+typedef struct pmcs_io_intr_coal_s {
+ hrtime_t nsecs_between_intrs;
+ hrtime_t last_io_comp;
+ clock_t quantum;
+ uint32_t num_io_completions;
+ uint32_t num_intrs;
+ uint32_t max_io_completions;
+ uint32_t intr_latency;
+ uint32_t intr_threshold;
+ uint16_t intr_coal_timer;
+ boolean_t timer_on;
+ boolean_t stop_thread;
+ boolean_t int_cleared;
+} pmcs_io_intr_coal_t;
+
+typedef struct pmcs_cq_thr_info_s {
+ kthread_t *cq_thread;
+ kmutex_t cq_thr_lock;
+ kcondvar_t cq_cv;
+ pmcs_hw_t *cq_pwp;
+} pmcs_cq_thr_info_t;
+
+typedef struct pmcs_cq_info_s {
+ uint32_t cq_threads;
+ uint32_t cq_next_disp_thr;
+ boolean_t cq_stop;
+ pmcs_cq_thr_info_t *cq_thr_info;
+} pmcs_cq_info_t;
+
+typedef struct pmcs_iocomp_cb_s {
+ pmcwork_t *pwrk;
+ char iomb[PMCS_QENTRY_SIZE << 1];
+ struct pmcs_iocomp_cb_s *next;
+} pmcs_iocomp_cb_t;
+
+typedef struct pmcs_iqp_trace_s {
+ char *head;
+ char *curpos;
+ uint32_t size_left;
+} pmcs_iqp_trace_t;
+
+/*
+ * Used by string-based softstate as hint to possible size.
+ */
+
+#define PMCS_TGT_SSTATE_SZ 64
+#define PMCS_LUN_SSTATE_SZ 4
+
+/*
+ * HBA iport node softstate
+ */
+#define PMCS_IPORT_INVALID_PORT_ID 0xffff
+
+struct pmcs_iport {
+ kmutex_t lock; /* iport lock */
+ list_node_t list_node; /* list node for pwp->iports list_t */
+ kmutex_t refcnt_lock; /* refcnt lock */
+ kcondvar_t refcnt_cv; /* refcnt cv */
+ int refcnt; /* refcnt for this iport */
+ dev_info_t *dip; /* iport dip */
+ pmcs_hw_t *pwp; /* back pointer to HBA state */
+ pmcs_phy_t *pptr; /* pointer to this port's primary phy */
+ enum { /* unit address state in the phymap */
+ UA_INACTIVE,
+ UA_PEND_ACTIVATE,
+ UA_ACTIVE,
+ UA_PEND_DEACTIVATE
+ } ua_state;
+ char *ua; /* unit address (phy mask) */
+ int portid; /* portid */
+ int report_skip; /* skip or report during discovery */
+ list_t phys; /* list of phys on this port */
+ int nphy; /* number of phys in this port */
+ scsi_hba_tgtmap_t *iss_tgtmap; /* tgtmap */
+ ddi_soft_state_bystr *tgt_sstate; /* tgt softstate */
+};
+
+struct pmcs_chunk {
+ pmcs_chunk_t *next;
+ ddi_acc_handle_t acc_handle;
+ ddi_dma_handle_t dma_handle;
+ uint8_t *addrp;
+ uint64_t dma_addr;
+};
+
+/*
+ * HBA node (i.e. non-iport) softstate
+ */
+struct pmcs_hw {
+ /*
+ * Identity
+ */
+ dev_info_t *dip;
+
+ /*
+ * 16 possible initiator PHY WWNs
+ */
+ uint64_t sas_wwns[PMCS_MAX_PORTS];
+
+ /*
+ * Card State
+ */
+ enum pwpstate {
+ STATE_NIL,
+ STATE_PROBING,
+ STATE_RUNNING,
+ STATE_UNPROBING,
+ STATE_DEAD
+ } state;
+
+ uint32_t
+ fw_disable_update : 1,
+ fw_force_update : 1,
+ blocked : 1,
+ stuck : 1,
+ locks_initted : 1,
+ mpi_table_setup : 1,
+ hba_attached : 1,
+ iports_attached : 1,
+ suspended : 1,
+ separate_ports : 1,
+ fwlog : 4,
+ phymode : 3,
+ physpeed : 3,
+ resource_limited : 1,
+ configuring : 1,
+ ds_err_recovering : 1;
+
+ /*
+ * This HBA instance's iportmap and list of iport states.
+ * Note: iports_lock protects iports, iports_attached, and
+ * num_iports on the HBA softstate.
+ */
+ krwlock_t iports_lock;
+ scsi_hba_iportmap_t *hss_iportmap;
+ list_t iports;
+ int num_iports;
+
+ sas_phymap_t *hss_phymap;
+ int phymap_active;
+
+ /*
+ * Locks
+ */
+ kmutex_t lock;
+ kmutex_t dma_lock;
+ kmutex_t axil_lock;
+ kcondvar_t drain_cv;
+
+ /*
+ * FMA Capabilities
+ */
+ int fm_capabilities;
+
+ /*
+ * Register Access Handles
+ */
+ ddi_device_acc_attr_t dev_acc_attr;
+ ddi_device_acc_attr_t reg_acc_attr;
+ ddi_acc_handle_t pci_acc_handle;
+ ddi_acc_handle_t msg_acc_handle;
+ ddi_acc_handle_t top_acc_handle;
+ ddi_acc_handle_t mpi_acc_handle;
+ ddi_acc_handle_t gsm_acc_handle;
+ ddi_acc_handle_t iqp_acchdls[PMCS_MAX_IQ];
+ ddi_acc_handle_t oqp_acchdls[PMCS_MAX_IQ];
+ ddi_acc_handle_t cip_acchdls;
+ ddi_acc_handle_t fwlog_acchdl;
+ ddi_acc_handle_t regdump_acchdl;
+
+ /*
+ * DMA Handles
+ */
+ ddi_dma_attr_t iqp_dma_attr;
+ ddi_dma_attr_t oqp_dma_attr;
+ ddi_dma_attr_t cip_dma_attr;
+ ddi_dma_attr_t fwlog_dma_attr;
+ ddi_dma_attr_t regdump_dma_attr;
+ ddi_dma_handle_t iqp_handles[PMCS_MAX_IQ];
+ ddi_dma_handle_t oqp_handles[PMCS_MAX_OQ];
+ ddi_dma_handle_t cip_handles;
+ ddi_dma_handle_t fwlog_hndl;
+ ddi_dma_handle_t regdump_hndl;
+
+ /*
+ * Register Pointers
+ */
+ uint32_t *msg_regs; /* message unit registers */
+ uint32_t *top_regs; /* top unit registers */
+ uint32_t *mpi_regs; /* message passing unit registers */
+ uint32_t *gsm_regs; /* GSM registers */
+
+ /*
+ * Message Passing and other offsets.
+ *
+ * mpi_offset is the offset within the fourth register set (mpi_regs)
+ * that contains the base of the MPI structures. Since this is actually
+ * set by the card firmware, it can change from startup to startup.
+ *
+ * The other offsets (gst, iqc, oqc) are for similar tables in
+ * MPI space, typically only accessed during setup.
+ */
+ uint32_t mpi_offset;
+ uint32_t mpi_gst_offset;
+ uint32_t mpi_iqc_offset;
+ uint32_t mpi_oqc_offset;
+
+ /*
+ * Inbound and outbound queue depth
+ */
+ uint32_t ioq_depth;
+
+ /*
+ * Kernel addresses and offsets for Inbound Queue Producer Indices
+ *
+ * See comments in pmcs_iomb.h about Inbound Queues. Since it
+ * is relatively expensive to go across the PCIe bus to read or
+ * write inside the card, we maintain shadow copies in kernel
+ * memory and update the card as needed.
+ */
+ uint32_t shadow_iqpi[PMCS_MAX_IQ];
+ uint32_t iqpi_offset[PMCS_MAX_IQ];
+ uint32_t *iqp[PMCS_MAX_IQ];
+ kmutex_t iqp_lock[PMCS_NIQ];
+
+ pmcs_iqp_trace_t *iqpt;
+
+ /*
+ * Kernel addresses and offsets for Outbound Queue Consumer Indices
+ */
+ uint32_t *oqp[PMCS_MAX_OQ];
+ uint32_t oqci_offset[PMCS_MAX_OQ];
+
+ /*
+ * Driver's copy of the outbound queue indices
+ */
+
+ uint32_t oqci[PMCS_NOQ];
+ uint32_t oqpi[PMCS_NOQ];
+
+ /*
+ * DMA addresses for both Inbound and Outbound queues.
+ */
+ uint64_t oqaddr[PMCS_MAX_OQ];
+ uint64_t iqaddr[PMCS_MAX_IQ];
+
+ /*
+ * Producer/Queue Host Memory Pointers and scratch areas,
+ * as well as DMA scatter/gather chunk areas.
+ *
+ * See discussion in pmcs_def.h about how this is laid out.
+ */
+ uint8_t *cip;
+ uint64_t ciaddr;
+
+ /*
+ * Scratch area pointer and DMA addrress for SATA and SMP operations.
+ */
+ void *scratch;
+ uint64_t scratch_dma;
+ volatile uint8_t scratch_locked; /* Scratch area ownership */
+
+ /*
+ * Firmware log pointer
+ */
+ uint32_t *fwlogp;
+ uint64_t fwaddr;
+
+ /*
+ * Internal register dump region and flash chunk DMA info
+ */
+
+ caddr_t regdumpp;
+ uint32_t *flash_chunkp;
+ uint64_t flash_chunk_addr;
+
+ /*
+ * Card information, some determined during MPI setup
+ */
+ uint32_t fw; /* firmware version */
+ uint8_t max_iq; /* maximum inbound queues this card */
+ uint8_t max_oq; /* "" outbound "" */
+ uint8_t nphy; /* number of phys this card */
+ uint8_t chiprev; /* chip revision */
+ uint16_t max_cmd; /* max number of commands supported */
+ uint16_t max_dev; /* max number of devices supported */
+ uint16_t last_wq_dev; /* last dev whose wq was serviced */
+
+
+ /*
+ * Interrupt Setup stuff.
+ *
+ * int_type defines the kind of interrupt we're using with this card.
+ * oqvec defines the relationship between an Outbound Queue Number and
+ * a MSI-X vector.
+ */
+ enum {
+ PMCS_INT_NONE,
+ PMCS_INT_TIMER,
+ PMCS_INT_MSI,
+ PMCS_INT_MSIX,
+ PMCS_INT_FIXED
+ } int_type;
+ uint8_t oqvec[PMCS_NOQ];
+
+ /*
+ * Interrupt handle table and size
+ */
+ ddi_intr_handle_t *ih_table;
+ size_t ih_table_size;
+
+ timeout_id_t wdhandle;
+ uint32_t intr_mask;
+ int intr_cnt;
+ int intr_cap;
+ uint32_t odb_auto_clear;
+
+ /*
+ * DMA S/G chunk list
+ */
+ int nchunks;
+ pmcs_chunk_t *dma_chunklist;
+
+ /*
+ * Front of the DMA S/G chunk freelist
+ */
+ pmcs_dmachunk_t *dma_freelist;
+
+ /*
+ * PHY and Discovery Related Stuff
+ *
+ * The PMC chip can have up to 16 local phys. We build a level-first
+ * traversal tree of phys starting with the physical phys on the
+ * chip itself (i.e., treating the chip as if it were an expander).
+ *
+ * Our discovery process goes through a level and discovers what
+ * each entity is (and it's phy number within that expander's
+ * address space). It then configures each non-empty item (SAS,
+ * SATA/STP, EXPANDER). For expanders, it then performs
+ * discover on that expander itself via REPORT GENERAL and
+ * DISCOVERY SMP commands, attaching the discovered entities
+ * to the next level. Then we step down a level and continue
+ * (and so on).
+ *
+ * The PMC chip maintains an I_T_NEXUS notion based upon our
+ * registering each new device found (getting back a device handle).
+ *
+ * Like with the number of physical PHYS being a maximum of 16,
+ * there are a maximum number of PORTS also being 16. Some
+ * events apply to PORTS entirely, so we track PORTS as well.
+ */
+ pmcs_phy_t *root_phys; /* HBA PHYs (level 0) */
+ pmcs_phy_t *ports[PMCS_MAX_PORTS];
+ kmutex_t dead_phylist_lock; /* Protects dead_phys */
+ pmcs_phy_t *dead_phys; /* PHYs waiting to be freed */
+
+ kmem_cache_t *phy_cache;
+
+ /*
+ * Discovery-related items.
+ * config_lock: Protects config_changed and should never be held
+ * outside of getting or setting the value of config_changed.
+ * config_changed: Boolean indicating whether discovery needs to
+ * be restarted.
+ * configuring: 1 = discovery is running, 0 = discovery not running.
+ * NOTE: configuring is now in the bitfield above.
+ */
+ kmutex_t config_lock;
+ volatile boolean_t config_changed;
+
+ /*
+ * Work Related Stuff
+ *
+ * Each command given to the PMC chip has an associated work structure.
+ * See the discussion in pmcs_def.h about work structures.
+ */
+ pmcwork_t *work; /* pool of work structures */
+ STAILQ_HEAD(wfh, pmcwork) wf; /* current freelist */
+ STAILQ_HEAD(pfh, pmcwork) pf; /* current pending freelist */
+ uint16_t wserno; /* rolling serial number */
+ kmutex_t wfree_lock; /* freelist/actvlist/wserno lock */
+ kmutex_t pfree_lock; /* freelist/actvlist/wserno lock */
+
+ /*
+ * Solaris/SCSA items.
+ */
+ scsi_hba_tran_t *tran;
+ sas_hba_tran_t *smp_tran;
+ struct scsi_reset_notify_entry *reset_notify_listf;
+
+ /*
+ * Thread Level stuff.
+ *
+ * A number of tasks are done off worker thread taskq.
+ */
+ ddi_taskq_t *tq; /* For the worker thread */
+ volatile ulong_t work_flags;
+
+ /*
+ * Solaris target representation.
+ * targets = array of pointers to xscsi structures
+ * allocated by ssoftstate.
+ */
+ pmcs_xscsi_t **targets;
+
+ STAILQ_HEAD(dqh, pmcs_cmd) dq; /* dead commands */
+ STAILQ_HEAD(cqh, pmcs_cmd) cq; /* completed commands */
+ kmutex_t cq_lock;
+ kmem_cache_t *iocomp_cb_cache;
+ pmcs_iocomp_cb_t *iocomp_cb_head;
+ pmcs_iocomp_cb_t *iocomp_cb_tail;
+
+ uint16_t debug_mask;
+ uint16_t phyid_block_mask;
+ uint16_t phys_started;
+ uint32_t hipri_queue;
+ uint32_t mpibar;
+ uint32_t intr_pri;
+
+ pmcs_io_intr_coal_t io_intr_coal;
+ pmcs_cq_info_t cq_info;
+ kmutex_t ict_lock;
+ kcondvar_t ict_cv;
+ kthread_t *ict_thread;
+
+#ifdef DEBUG
+ kmutex_t dbglock;
+ uint32_t ltags[256];
+ uint32_t ftags[256];
+ hrtime_t ltime[256];
+ hrtime_t ftime[256];
+ uint16_t ftag_lines[256];
+ uint8_t lti; /* last tag index */
+ uint8_t fti; /* first tag index */
+#endif
+};
+
+extern void *pmcs_softc_state;
+extern void *pmcs_iport_softstate;
+
+/*
+ * Some miscellaneous, oft used strings
+ */
+extern const char pmcs_nowrk[];
+extern const char pmcs_nomsg[];
+extern const char pmcs_timeo[];
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _PMCS_H */
diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_def.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_def.h
new file mode 100644
index 0000000000..5ed39d0a79
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_def.h
@@ -0,0 +1,514 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef _PMCS_DEF_H
+#define _PMCS_DEF_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ NOTHING, /* nothing connected here */
+ SATA, /* SATA connection */
+ SAS, /* direct or indirect SAS connection */
+ EXPANDER, /* connection to an expander */
+ NEW /* Brand new device (pending state) */
+} pmcs_dtype_t;
+
+/*
+ * This structure defines a PHY device that represents what we
+ * are connected to.
+ *
+ * The eight real physical PHYs that are in the PMC8X6G are represented
+ * as an array of eight of these structures which define what these
+ * real PHYs are connected to.
+ *
+ * Depending upon what is actually connected to each PHY, the
+ * type set will define what we're connected to. If it is
+ * a direct SATA connection, the phy will describe a SATA endpoint
+ * If it is a direct SAS connection, it will describe a SAS
+ * endpoint.
+ *
+ * If it is an EXPANDER, this will describe the edge of an expander.
+ * As we perform discovery on what is in an EXPANDER we define an
+ * additional list of phys that represent what the Expander is connected to.
+ */
+#define PMCS_HW_MIN_LINK_RATE SAS_LINK_RATE_1_5GBIT
+#define PMCS_HW_MAX_LINK_RATE SAS_LINK_RATE_6GBIT
+
+#define PMCS_INVALID_DEVICE_ID 0xffffffff
+
+struct pmcs_phy {
+ pmcs_phy_t *sibling; /* sibling phy */
+ pmcs_phy_t *parent; /* parent phy */
+ pmcs_phy_t *children; /* head of list of children */
+ pmcs_phy_t *dead_next; /* dead PHY list link */
+ list_node_t list_node; /* list element */
+ uint32_t device_id; /* PMC8X6G device handle */
+ uint32_t
+ ncphy : 8, /* # of contained phys for expander */
+ hw_event_ack : 24; /* XXX: first level phy event acked */
+ uint8_t phynum; /* phy number on parent expander */
+ uint8_t width; /* how many phys wide */
+ uint8_t ds_recovery_retries; /* # error retry attempts */
+ pmcs_dtype_t dtype; /* current dtype of the phy */
+ pmcs_dtype_t pend_dtype; /* new dtype (pending change) */
+ uint32_t
+ level : 8, /* level in expander tree */
+ tolerates_sas2 : 1, /* tolerates SAS2 SMP */
+ spinup_hold : 1, /* spinup hold needs releasing */
+ atdt : 3, /* attached device type */
+ portid : 4, /* PMC8X6G port context */
+ link_rate : 4, /* current supported speeds */
+ valid_device_id : 1, /* device id is valid */
+ abort_sent : 1, /* we've sent an abort */
+ abort_pending : 1, /* we have an abort pending */
+ need_rl_ext : 1, /* need SATA RL_EXT recocvery */
+ subsidiary : 1, /* this is part of a wide phy */
+ configured : 1, /* is configured */
+ dead : 1, /* dead */
+ changed : 1; /* this phy is changing */
+ clock_t config_stop; /* When config attempts will stop */
+ hrtime_t abort_all_start;
+ kcondvar_t abort_all_cv; /* Wait for ABORT_ALL completion */
+ kmutex_t phy_lock;
+ volatile uint32_t ref_count; /* Targets & work on this PHY */
+ uint8_t sas_address[8]; /* SAS address for this PHY */
+ struct {
+ uint32_t
+ prog_min_rate :4,
+ hw_min_rate :4,
+ prog_max_rate :4,
+ hw_max_rate :4,
+ reserved :16;
+ } state;
+ char path[32]; /* path name for this phy */
+ pmcs_hw_t *pwp; /* back ptr to hba struct */
+ pmcs_iport_t *iport; /* back ptr to the iport handle */
+ pmcs_xscsi_t *target; /* back ptr to current target */
+ kstat_t *phy_stats; /* kstats for this phy */
+};
+
+/* maximum number of ds recovery retries (ds_recovery_retries) */
+#define PMCS_MAX_DS_RECOVERY_RETRIES 4
+
+
+/*
+ * Inbound and Outbound Queue Related Definitions.
+ *
+ * The PMC8X6G has a programmable number of inbound and outbound circular
+ * queues for use in message passing between the host and the PMC8X6G
+ * (up to 64 queues for the Rev C Chip). This driver does not use all
+ * possible queues.
+ *
+ * Each Queue is given 4K of consistent memory and we set a 64 byte size for
+ * the queue entry size (this gives us 256 queue entries per queue).
+ *
+ * This allocation then continues up a further PMCS_SCRATCH_SIZE bytes
+ * that the driver uses as a temporary scratch area for things like
+ * SMP discovery.
+ *
+ * This control area looks like this:
+ *
+ * Offset What
+ * ------------------------------------------------
+ * 0 IQ 0 Consumer Index
+ * 4 IQ 1 Consumer Index
+ * 8..255 ...
+ * 252..255 IQ 63 Consumer Index
+ * 256 OQ 0 Producer Index
+ * 260 OQ 1 Producer Index
+ * 264..259 ....
+ * 508..511 OQ 63 Producer Index
+ * 512..512+PMCS_SCRATCH_SIZE-1 Scratch area.
+ */
+#define IQCI_BASE_OFFSET 0
+#define IQ_OFFSET(qnum) (IQCI_BASE_OFFSET + (qnum << 2))
+#define OQPI_BASE_OFFSET 256
+#define OQ_OFFSET(qnum) (OQPI_BASE_OFFSET + (qnum << 2))
+
+/*
+ * Work related structures. Each one of these structures is paired
+ * with *any* command that is fed to the PMC8X6G via one of the
+ * Inbound Queues. The work structure has a tag to compare with
+ * the message that comes back out of an Outbound Queue. The
+ * work structure also points to the phy which this command is
+ * tied to. It also has a pointer a callback function (if defined).
+ * See that TAG Architecture below for the various kinds of
+ * dispositions of a work structure.
+ */
+
+/*
+ * Work Structure States
+ *
+ * NIL -> READY
+ * READY -> NIL
+ * READY -> ONCHIP
+ * ONCHIP -> INTR
+ * INTR -> READY
+ * INTR -> NIL
+ * INTR -> ABORTED
+ * INTR -> TIMED_OUT
+ * ABORTED -> NIL
+ * TIMED_OUT -> NIL
+ */
+typedef enum {
+ PMCS_WORK_STATE_NIL = 0,
+ PMCS_WORK_STATE_READY,
+ PMCS_WORK_STATE_ONCHIP,
+ PMCS_WORK_STATE_INTR,
+ PMCS_WORK_STATE_IOCOMPQ,
+ PMCS_WORK_STATE_ABORTED,
+ PMCS_WORK_STATE_TIMED_OUT
+} pmcs_work_state_t;
+
+struct pmcwork {
+ STAILQ_ENTRY(pmcwork) next;
+ kmutex_t lock;
+ kcondvar_t sleep_cv;
+ void *ptr; /* linkage or callback function */
+ void *arg; /* command specific data */
+ pmcs_phy_t *phy; /* phy who owns this command */
+ pmcs_xscsi_t *xp; /* Back pointer to xscsi struct */
+ volatile uint32_t htag; /* tag for this structure */
+ uint32_t
+ timer : 27,
+ onwire : 1,
+ dead : 1,
+ state : 3;
+ hrtime_t start; /* timestamp start */
+ uint32_t ssp_event; /* ssp event */
+ pmcs_dtype_t dtype; /* stash, incase phy gets cleared */
+
+ /* DEBUG-only fields from here on */
+ void *last_ptr;
+ void *last_arg;
+ pmcs_phy_t *last_phy;
+ pmcs_xscsi_t *last_xp;
+ uint32_t last_htag;
+ pmcs_work_state_t last_state;
+ hrtime_t finish;
+};
+
+#define PMCS_REC_EVENT 0xffffffff /* event recovery */
+
+/*
+ * This structure defines a PMC-Sierra defined firmware header.
+ */
+#pragma pack(4)
+typedef struct {
+ char vendor_id[8];
+ uint8_t product_id;
+ uint8_t hwrev;
+ uint8_t destination_partition;
+ uint8_t reserved0;
+ uint8_t fwrev[4];
+ uint32_t firmware_length;
+ uint32_t crc;
+ uint32_t start_address;
+ uint8_t data[];
+} pmcs_fw_hdr_t;
+#pragma pack()
+
+/*
+ * Offlevel work as a bit pattern.
+ */
+#define PMCS_WORK_DISCOVER 0
+#define PMCS_WORK_REM_DEVICES 2
+#define PMCS_WORK_ABORT_HANDLE 3
+#define PMCS_WORK_SPINUP_RELEASE 4
+#define PMCS_WORK_SAS_HW_ACK 5
+#define PMCS_WORK_SATA_RUN 6
+#define PMCS_WORK_RUN_QUEUES 7
+#define PMCS_WORK_ADD_DMA_CHUNKS 8
+#define PMCS_WORK_DS_ERR_RECOVERY 9
+#define PMCS_WORK_SSP_EVT_RECOVERY 10
+
+/*
+ * The actual values as they appear in work_flags
+ */
+#define PMCS_WORK_FLAG_DISCOVER (1 << 0)
+#define PMCS_WORK_FLAG_REM_DEVICES (1 << 2)
+#define PMCS_WORK_FLAG_ABORT_HANDLE (1 << 3)
+#define PMCS_WORK_FLAG_SPINUP_RELEASE (1 << 4)
+#define PMCS_WORK_FLAG_SAS_HW_ACK (1 << 5)
+#define PMCS_WORK_FLAG_SATA_RUN (1 << 6)
+#define PMCS_WORK_FLAG_RUN_QUEUES (1 << 7)
+#define PMCS_WORK_FLAG_ADD_DMA_CHUNKS (1 << 8)
+#define PMCS_WORK_FLAG_DS_ERR_RECOVERY (1 << 9)
+#define PMCS_WORK_FLAG_SSP_EVT_RECOVERY (1 << 10)
+
+/*
+ * This structure is used by this function to test MPI (and interrupts)
+ * after MPI has been started to make sure it's working reliably.
+ */
+typedef struct {
+ uint32_t signature;
+ uint32_t count;
+ uint32_t *ptr;
+} echo_test_t;
+#define ECHO_SIGNATURE 0xbebebeef
+
+/*
+ * Tag Architecture. The PMC has 32 bit tags for MPI messages.
+ * We use this tag this way.
+ *
+ * bits what
+ * ------------------------
+ * 31 done bit
+ * 30..28 tag type
+ * 27..12 rolling serial number
+ * 11..0 index into work area to get pmcwork structure
+ *
+ * A tag type of NONE means that nobody is waiting on any results,
+ * so the interrupt code frees the work structure that has this
+ * tag.
+ *
+ * A tag type of CBACK means that the the interrupt handler
+ * takes the tag 'arg' in the work structure to be a callback
+ * function pointer (see pmcs_cb_t). The callee is responsible
+ * for freeing the work structure that has this tag.
+ *
+ * A tag type of WAIT means that the issuer of the work needs
+ * be woken up from interrupt level when the command completes
+ * (or times out). If work structure tag 'arg' is non-null,
+ * up to 2*PMCS_QENTRY_SIZE bits of data from the Outbound Queue
+ * entry may be copied to the area pointed to by 'arg'. This
+ * allows issuers to get directly at the results of the command
+ * they issed. The synchronization point for the issuer and the
+ * interrupt code for command done notification is the setting
+ * of the 'DONE' bit in the tag as stored in the work structure.
+ */
+#define PMCS_TAG_TYPE_FREE 0
+#define PMCS_TAG_TYPE_NONE 1
+#define PMCS_TAG_TYPE_CBACK 2
+#define PMCS_TAG_TYPE_WAIT 3
+#define PMCS_TAG_TYPE_SHIFT 28
+#define PMCS_TAG_SERNO_SHIFT 12
+#define PMCS_TAG_INDEX_SHIFT 0
+#define PMCS_TAG_TYPE_MASK 0x70000000
+#define PMCS_TAG_DONE 0x80000000
+#define PMCS_TAG_SERNO_MASK 0x0ffff000
+#define PMCS_TAG_INDEX_MASK 0x00000fff
+#define PMCS_TAG_TYPE(x) \
+ (((x) & PMCS_TAG_TYPE_MASK) >> PMCS_TAG_TYPE_SHIFT)
+#define PMCS_TAG_SERNO(x) \
+ (((x) & PMCS_TAG_SERNO_MASK) >> PMCS_TAG_SERNO_SHIFT)
+#define PMCS_TAG_INDEX(x) \
+ (((x) & PMCS_TAG_INDEX_MASK) >> PMCS_TAG_INDEX_SHIFT)
+#define PMCS_TAG_FREE 0
+#define PMCS_COMMAND_DONE(x) \
+ (((x)->htag == PMCS_TAG_FREE) || (((x)->htag & PMCS_TAG_DONE) != 0))
+#define PMCS_COMMAND_ACTIVE(x) \
+ ((x)->htag != PMCS_TAG_FREE && (x)->state == PMCS_WORK_STATE_ONCHIP)
+
+/*
+ * Miscellaneous Definitions
+ */
+#define CLEAN_MESSAGE(m, x) { \
+ int _j = x; \
+ while (_j < PMCS_MSG_SIZE) { \
+ m[_j++] = 0; \
+ } \
+}
+
+#define COPY_MESSAGE(t, f, a) { \
+ int _j; \
+ for (_j = 0; _j < a; _j++) { \
+ t[_j] = f[_j]; \
+ } \
+ while (_j < PMCS_MSG_SIZE) { \
+ t[_j++] = 0; \
+ } \
+}
+
+#define PMCS_PHY_ADDRESSABLE(pp) \
+ ((pp)->level == 0 && (pp)->dtype == SATA && \
+ ((pp)->sas_address[0] >> 4) != 5)
+
+#define RESTART_DISCOVERY(pwp) \
+ ASSERT(!mutex_owned(&pwp->config_lock)); \
+ mutex_enter(&pwp->config_lock); \
+ pwp->config_changed = B_TRUE; \
+ mutex_exit(&pwp->config_lock); \
+ SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER);
+
+#define RESTART_DISCOVERY_LOCKED(pwp) \
+ ASSERT(mutex_owned(&pwp->config_lock)); \
+ pwp->config_changed = B_TRUE; \
+ SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER);
+
+#define PHY_CHANGED(pwp, p) \
+ pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s changed in %s line %d", \
+ p->path, __func__, __LINE__); \
+ p->changed = 1
+
+#define PHY_CHANGED_AT_LOCATION(pwp, p, func, line) \
+ pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s changed in %s line %d", \
+ p->path, func, line); \
+ p->changed = 1
+
+#define PHY_TYPE(pptr) \
+ (((pptr)->dtype == NOTHING)? "NOTHING" : \
+ (((pptr)->dtype == SATA)? "SATA" : \
+ (((pptr)->dtype == SAS)? "SAS" : "EXPANDER")))
+
+#define IS_ROOT_PHY(pptr) (pptr->parent == NULL)
+
+#define PMCS_HIPRI(pwp, oq, c) \
+ (pwp->hipri_queue & (1 << PMCS_IQ_OTHER)) ? \
+ (PMCS_IOMB_HIPRI | PMCS_IOMB_IN_SAS(oq, c)) : \
+ (PMCS_IOMB_IN_SAS(oq, c))
+
+#define SCHEDULE_WORK(hwp, wrk) \
+ (void) atomic_set_long_excl(&hwp->work_flags, wrk)
+
+/*
+ * Check to see if the requested work bit is set. Either way, the bit will
+ * be cleared upon return.
+ */
+#define WORK_SCHEDULED(hwp, wrk) \
+ (atomic_clear_long_excl(&hwp->work_flags, wrk) == 0)
+
+/*
+ * Check to see if the requested work bit is set. The value will not be
+ * changed in this case. The atomic_xx_nv operations can be quite expensive
+ * so this should not be used in non-DEBUG code.
+ */
+#define WORK_IS_SCHEDULED(hwp, wrk) \
+ ((atomic_and_ulong_nv(&hwp->work_flags, (ulong_t)-1) & (1 << wrk)) != 0)
+
+#define WAIT_FOR(p, t, r) \
+ r = 0; \
+ while (!PMCS_COMMAND_DONE(p)) { \
+ clock_t tmp = cv_timedwait(&p->sleep_cv, \
+ &p->lock, ddi_get_lbolt() + \
+ drv_usectohz(t * 1000)); \
+ if (!PMCS_COMMAND_DONE(p) && tmp < 0) { \
+ r = 1; \
+ break; \
+ } \
+ }
+
+/*
+ * Signal the next I/O completion thread to start running.
+ */
+
+#define PMCS_CQ_RUN_LOCKED(hwp) \
+ if (!STAILQ_EMPTY(&hwp->cq) || hwp->iocomp_cb_head) { \
+ pmcs_cq_thr_info_t *cqti; \
+ cqti = &hwp->cq_info.cq_thr_info \
+ [hwp->cq_info.cq_next_disp_thr]; \
+ hwp->cq_info.cq_next_disp_thr++; \
+ if (hwp->cq_info.cq_next_disp_thr == \
+ hwp->cq_info.cq_threads) { \
+ hwp->cq_info.cq_next_disp_thr = 0; \
+ } \
+ mutex_enter(&cqti->cq_thr_lock); \
+ cv_signal(&cqti->cq_cv); \
+ mutex_exit(&cqti->cq_thr_lock); \
+ } \
+
+#define PMCS_CQ_RUN(hwp) \
+ mutex_enter(&hwp->cq_lock); \
+ PMCS_CQ_RUN_LOCKED(hwp); \
+ mutex_exit(&hwp->cq_lock);
+
+
+/*
+ * Watchdog/SCSA timer definitions
+ */
+/* usecs to SCSA watchdog ticks */
+#define US2WT(x) (x)/10
+
+/*
+ * More misc
+ */
+#define BYTE0(x) (((x) >> 0) & 0xff)
+#define BYTE1(x) (((x) >> 8) & 0xff)
+#define BYTE2(x) (((x) >> 16) & 0xff)
+#define BYTE3(x) (((x) >> 24) & 0xff)
+#define BYTE4(x) (((x) >> 32) & 0xff)
+#define BYTE5(x) (((x) >> 40) & 0xff)
+#define BYTE6(x) (((x) >> 48) & 0xff)
+#define BYTE7(x) (((x) >> 56) & 0xff)
+#define WORD0(x) (((x) >> 0) & 0xffff)
+#define WORD1(x) (((x) >> 16) & 0xffff)
+#define WORD2(x) (((x) >> 32) & 0xffff)
+#define WORD3(x) (((x) >> 48) & 0xffff)
+#define DWORD0(x) ((uint32_t)(x))
+#define DWORD1(x) ((uint32_t)(((uint64_t)x) >> 32))
+
+#define SAS_ADDR_FMT "0x%02x%02x%02x%02x%02x%02x%02x%02x"
+#define SAS_ADDR_PRT(x) x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]
+
+#define PMCS_VALID_LINK_RATE(r) \
+ ((r == SAS_LINK_RATE_1_5GBIT) || (r == SAS_LINK_RATE_3GBIT) || \
+ (r == SAS_LINK_RATE_6GBIT))
+
+/*
+ * This is here to avoid inclusion of <sys/ctype.h> which is not lint clean.
+ */
+#define HEXDIGIT(x) (((x) >= '0' && (x) <= '9') || \
+ ((x) >= 'a' && (x) <= 'f') || ((x) >= 'A' && (x) <= 'F'))
+
+
+typedef void (*pmcs_cb_t) (pmcs_hw_t *, pmcwork_t *, uint32_t *);
+
+/*
+ * Defines and structure used for tracing/logging information
+ */
+
+#define PMCS_TBUF_ELEM_SIZE 120
+
+#ifdef DEBUG
+#define PMCS_TBUF_NUM_ELEMS_DEF 100000
+#else
+#define PMCS_TBUF_NUM_ELEMS_DEF 15000
+#endif
+
+typedef struct {
+ timespec_t timestamp;
+ char buf[PMCS_TBUF_ELEM_SIZE];
+} pmcs_tbuf_t;
+
+/*
+ * Firmware event log header format
+ */
+
+typedef struct pmcs_fw_event_hdr_s {
+ uint32_t fw_el_signature;
+ uint32_t fw_el_entry_start_offset;
+ uint32_t fw_el_rsvd1;
+ uint32_t fw_el_buf_size;
+ uint32_t fw_el_rsvd2;
+ uint32_t fw_el_oldest_idx;
+ uint32_t fw_el_latest_idx;
+ uint32_t fw_el_entry_size;
+} pmcs_fw_event_hdr_t;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _PMCS_DEF_H */
diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_iomb.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_iomb.h
new file mode 100644
index 0000000000..0a397aee98
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_iomb.h
@@ -0,0 +1,724 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * PMC 8x6G IOMB Definitions
+ */
+#ifndef _PMCS_IOMB_H
+#define _PMCS_IOMB_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * An IOMB (IO Message Buffer) is the principle means of communication
+ * between the PMC and the HOST. The host places IOMBs on the Inbound
+ * Queues (IQ) which are in HOST memory and updates a producer index
+ * within the PMC. The PMC pulls the IOMB off the IQ and updates a
+ * consumer index in HOST memory. If appropriate, when the PMC is
+ * done with the action requested by the IOMB, the PMC writes a
+ * reply IOMB to host memory and updates its producer index and
+ * interrupts the HOST.
+ */
+/*
+ * The first word of all IOMBs is always laid out thusly:
+ *
+ * |Byte 3 |Byte 2 |Byte 1 |Byte 0 |
+ * +-------------+-------------+----------------------+
+ * |V Resvd BC|Resvd OBID |CAT | OPCODE |
+ * +--------------------------------------------------+
+ *
+ * V == Valid
+ * BC = Buffer Count
+ * OBID = Outbound Queue ID
+ * CAT = Category
+ * OPCODE = Well, uh, OPCODE.
+ */
+
+#define PMCS_IOMB_VALID (1U << 31)
+#define PMCS_IOMB_HIPRI (1U << 30)
+#define PMCS_IOMB_BC_SHIFT (24)
+#define PMCS_IOMB_BC_MASK (0xf << PMCS_IOMB_BC_SHIFT)
+#define PMCS_IOMB_OBID_SHIFT (16)
+#define PMCS_IOMB_OBID_MASK (0xf << PMCS_IOMB_OBID_SHIFT)
+#define PMCS_IOMB_CAT_SHIFT (12)
+#define PMCS_IOMB_CAT_MASK (0xf << PMCS_IOMB_CAT_SHIFT)
+#define PMCS_IOMB_OPCODE_MASK (0xfff)
+
+
+#define PMCS_IOMB_CAT_NET 0
+#define PMCS_IOMB_CAT_FC 1
+#define PMCS_IOMB_CAT_SAS 2
+#define PMCS_IOMB_CAT_SCSI 3
+
+/*
+ * Shorthand
+ */
+#define PMCS_IOMB_IN_SAS(q, opcode) \
+ (PMCS_IOMB_VALID | (1 << PMCS_IOMB_BC_SHIFT) | \
+ (PMCS_IOMB_CAT_SAS << PMCS_IOMB_CAT_SHIFT) | \
+ ((q << PMCS_IOMB_OBID_SHIFT) & PMCS_IOMB_OBID_MASK) | \
+ (opcode & PMCS_IOMB_OPCODE_MASK))
+
+/*
+ * PMC IOMB Inbound Queue Opcodes
+ */
+#define PMCIN_ECHO 0x01
+#define PMCIN_GET_INFO 0x02
+#define PMCIN_GET_VPD 0x03
+#define PMCIN_PHY_START 0x04
+#define PMCIN_PHY_STOP 0x05
+#define PMCIN_SSP_INI_IO_START 0x06
+#define PMCIN_SSP_INI_TM_START 0x07
+#define PMCIN_SSP_INI_EXT_IO_START 0x08
+#define PMCIN_DEVICE_HANDLE_ACCEPT 0x09
+#define PMCIN_SSP_TGT_IO_START 0x0A
+#define PMCIN_SSP_TGT_RESPONSE_START 0x0B
+#define PMCIN_SSP_INI_EDC_EXT_IO_START 0x0C
+#define PMCIN_SSP_INI_EDC_EXT_IO_START1 0x0D
+#define PMCIN_SSP_TGT_EDC_IO_START 0x0E
+#define PMCIN_SSP_ABORT 0x0F
+#define PMCIN_DEREGISTER_DEVICE_HANDLE 0x10
+#define PMCIN_GET_DEVICE_HANDLE 0x11
+#define PMCIN_SMP_REQUEST 0x12
+#define PMCIN_SMP_RESPONSE 0x13
+#define PMCIN_SMP_ABORT 0x14
+#define PMCIN_ASSISTED_DISCOVERY 0x15
+#define PMCIN_REGISTER_DEVICE 0x16
+#define PMCIN_SATA_HOST_IO_START 0x17
+#define PMCIN_SATA_ABORT 0x18
+#define PMCIN_LOCAL_PHY_CONTROL 0x19
+#define PMCIN_GET_DEVICE_INFO 0x1A
+#define PMCIN_TWI 0x1B
+#define PMCIN_FW_FLASH_UPDATE 0x20
+#define PMCIN_SET_VPD 0x21
+#define PMCIN_GPIO 0x22
+#define PMCIN_SAS_DIAG_MODE_START_END 0x23
+#define PMCIN_SAS_DIAG_EXECUTE 0x24
+#define PMCIN_SAW_HW_EVENT_ACK 0x25
+#define PMCIN_GET_TIME_STAMP 0x26
+#define PMCIN_PORT_CONTROL 0x27
+#define PMCIN_GET_NVMD_DATA 0x28
+#define PMCIN_SET_NVMD_DATA 0x29
+#define PMCIN_SET_DEVICE_STATE 0x2A
+#define PMCIN_GET_DEVICE_STATE 0x2B
+
+/*
+ * General Inbound Queue related parameters (DWORD 4)
+ */
+#define PMCIN_MESSAGE_REPORT (1 << 2)
+#define PMCIN_DS_ABORT_TASK (1 << 3)
+#define PMCIN_DS_IN_RECOVERY (1 << 4)
+#define PMCIN_DATADIR_NONE (0x00 << 8)
+#define PMCIN_DATADIR_2_INI (0x01 << 8)
+#define PMCIN_DATADIR_2_DEV (0x02 << 8)
+
+
+/*
+ * SATA Host IO Start ATA Protocol Types
+ * (placed into DWORD 4)
+ */
+
+#define SATA_PROTOCOL_SRST_ASSERT (0x01 << 10)
+#define SATA_PROTOCOL_SRT_DEASSERT (0x02 << 10)
+#define SATA_PROTOCOL_EXECDEVDIAG (0x03 << 10)
+#define SATA_PROTOCOL_NONDATA (0x04 << 10)
+#define SATA_PROTOCOL_PIO (0x05 << 10)
+#define SATA_PROTOCOL_DMA (0x06 << 10)
+#define SATA_PROTOCOL_FPDMA (0x07 << 10)
+
+/*
+ * SAS Host IO Start TLR definitions
+ * (placed into DWORD 4)
+ */
+#define SAS_TLR_ALL 0 /* SAS 1.1 and SAS 2.0 per device mode page */
+#define SAS_TLR_ON 1 /* unconditionally on */
+#define SAS_TLR_OFF 2 /* unconditionally off */
+#define SAS_TLR_SAS2 3 /* SAS 2.0 per device mode page */
+
+/*
+ * IOP SMP Request Information
+ */
+#define SMP_INDIRECT_RESPONSE 0x01
+#define SMP_INDIRECT_REQUEST 0x02
+#define SMP_PHY_OVERRIDE 0x04
+#define SMP_REQUEST_LENGTH_SHIFT 16
+
+/*
+ * PHY Start related definitions
+ */
+#define PHY_LINK_1_5 0x01
+#define PHY_LINK_3 0x02
+#define PHY_LINK_6 0x04
+#define PHY_LINK_ALL (PHY_LINK_1_5 | PHY_LINK_3 | PHY_LINK_6)
+#define PHY_LINK_SHIFT 8
+
+#define PHY_LM_SAS 1
+#define PHY_LM_SATA 2
+#define PHY_LM_AUTO 3
+#define PHY_MODE_SHIFT 12
+
+#define PHY_SPINUP_HOLD (1 << 14)
+
+/*
+ * LOCAL PHY CONTROL related definitions
+ */
+
+/*
+ * Device Registration related definitions
+ */
+#define PMCS_DEVREG_LINK_RATE_SHIFT 24
+#define PMCS_DEVREG_TYPE_SATA 0
+#define PMCS_DEVREG_TYPE_SAS (1 << 28)
+#define PMCS_DEVREG_TYPE_SATA_DIRECT (1 << 29)
+
+#define PMCS_PHYID_SHIFT 4 /* level 0 registration only */
+#define PMCS_DEVREG_TLR 0x1 /* Transport Layer Retry */
+
+#define PMCS_DEVREG_IT_NEXUS_TIMEOUT 200U
+
+#define PMCS_DEVREG_HA 0x2 /* Host Assigned upper 16 */
+ /* bits for device ID. */
+/*
+ * These are used for getting/setting data in the NVRAM (SEEPROM, VPD, etc.)
+ */
+
+typedef struct pmcs_get_nvmd_cmd_s {
+ uint32_t header; /* DWORD 0 */
+ uint32_t htag; /* DWORD 1 */
+ uint8_t tdas_nvmd; /* DWORD 2 */
+ uint8_t tbn_tdps;
+ uint8_t tda;
+ uint8_t ip;
+ uint8_t doa[3]; /* DWORD 3 Data Offset Addr */
+ uint8_t d_len; /* Direct Pld Data Len */
+ uint32_t rsvd[8]; /* DWORDS 4-11 */
+ uint32_t ipbal; /* 12 - Ind Pld buf addr low */
+ uint32_t ipbah; /* 13 - Ind Pld buf addr high */
+ uint32_t ipdl; /* 14 - Ind Pld data length */
+ uint32_t rsvd3;
+} pmcs_get_nvmd_cmd_t;
+
+typedef struct pmcs_set_nvmd_cmd_s {
+ uint32_t header; /* DWORD 0 */
+ uint32_t htag; /* DWORD 1 */
+ uint8_t tdas_nvmd; /* DWORD 2 */
+ uint8_t tbn_tdps;
+ uint8_t tda;
+ uint8_t ip;
+ uint8_t doa[3]; /* DWORD 3 Data Offset Addr */
+ uint8_t d_len; /* Direct Pld Data Len */
+ uint32_t signature; /* DWORD 4 */
+ uint32_t rsvd[7]; /* DWORDS 5-11 */
+ uint32_t ipbal; /* 12 - Ind Pld buf addr low */
+ uint32_t ipbah; /* 13 - Ind Pld buf addr high */
+ uint32_t ipdl; /* 14 - Ind Pld data length */
+ uint32_t rsvd2;
+} pmcs_set_nvmd_cmd_t;
+
+#define PMCIN_NVMD_DIRECT_PLD 0x00
+#define PMCIN_NVMD_INDIRECT_PLD 0x80
+
+/* TWI bus number is upper 4 bits of tbn_tdps */
+#define PMCIN_NVMD_TBN(x) (x << 4)
+
+/* TWI Device Page Size bits (lower 4 bits of tbn_tdps */
+#define PMCIN_NVMD_TDPS_1 0 /* 1 byte */
+#define PMCIN_NVMD_TDPS_8 1 /* 8 bytes */
+#define PMCIN_NVMD_TDPS_16 2 /* 16 bytes */
+#define PMCIN_NVMD_TDPS_32 3 /* 32 bytes */
+
+/* TWI Device Address Size (upper 4 bits of tdas_nvmd) */
+#define PMCIN_NVMD_TDAS_1 (0 << 4) /* 1 byte */
+#define PMCIN_NVMD_TDAS_2 (1 << 4) /* 2 bytes */
+
+/*
+ * TWI Device Address
+ * The address used to access TWI device for the 2Kb SEEPROM device is
+ * arranged as follows:
+ * Bits 7-4 are fixed (0xA)
+ * Bits 3-1 are page numbers for each 256 byte page
+ * Bit 0: Set to "1" to read, "0" to write
+ * Bit 0 is set/reset by the firmware based on whether the command is a
+ * SET or a GET.
+ */
+#define PMCIN_TDA_BASE 0xA0
+#define PMCIN_TDA_PAGE(x) (PMCIN_TDA_BASE | (x << 1))
+
+/* NVM Device bits (lower 4 bits of tdas_nvmd) */
+#define PMCIN_NVMD_TWI 0 /* TWI Device */
+#define PMCIN_NVMD_SEEPROM 1 /* SEEPROM Device */
+#define PMCIN_NVMD_VPD 4 /* VPD Flash Memory */
+#define PMCIN_NVMD_AAP1 5 /* AAP1 Register Dump */
+#define PMCIN_NVMD_IOP 6 /* IOP Register Dump */
+
+#define PMCS_SEEPROM_PAGE_SIZE 256
+
+/*
+ * Minimum and maximum sizes of SPCBoot image
+ */
+#define PMCS_SPCBOOT_MIN_SIZE 64
+#define PMCS_SPCBOOT_MAX_SIZE 512
+
+#define PMCS_SEEPROM_SIGNATURE 0xFEDCBA98
+
+/*
+ * Register dump information
+ *
+ * There are two 16KB regions for register dump information
+ */
+
+#define PMCS_REGISTER_DUMP_FLASH_SIZE (1024 * 16)
+#define PMCS_REGISTER_DUMP_BLOCK_SIZE 4096 /* Must be read 4K at a time */
+#define PMCS_FLASH_CHUNK_SIZE 4096 /* Must be read 4K at a time */
+#define PMCS_REG_DUMP_SIZE (1024 * 1024 * 12)
+#define PMCS_NVMD_EVENT_LOG_OFFSET 0x10000
+#define PMCS_IQP_TRACE_BUFFER_SIZE (1024 * 512)
+
+/*
+ * The list of items we can retrieve via the GET_NVMD_DATA command
+ */
+
+typedef enum {
+ PMCS_NVMD_VPD = 0,
+ PMCS_NVMD_REG_DUMP,
+ PMCS_NVMD_EVENT_LOG,
+ PMCS_NVMD_SPCBOOT
+} pmcs_nvmd_type_t;
+
+/*
+ * Command types, descriptors and offsets for SAS_DIAG_EXECUTE.
+ */
+#define PMCS_DIAG_CMD_DESC_SHIFT 8
+#define PMCS_DIAG_CMD_SHIFT 13
+#define PMCS_DIAG_REPORT_GET 0x04 /* Get counters */
+#define PMCS_ERR_CNT_RESET 0x05 /* Clear counters */
+#define PMCS_DISPARITY_ERR_CNT 0x02 /* Disparity error count */
+#define PMCS_LOST_DWORD_SYNC_CNT 0x05 /* Lost DWord sync count */
+#define PMCS_INVALID_DWORD_CNT 0x06 /* Invalid DWord count */
+#define PMCS_RESET_FAILED_CNT 0x0C /* PHY reset failed count */
+
+/*
+ * VPD data layout
+ */
+
+#define PMCS_VPD_DATA_PAGE 2 /* VPD starts at offset 512 */
+#define PMCS_VPD_VERSION 2 /* Expected version number */
+#define PMCS_VPD_RO_BYTE 0x90 /* Start of "read-only" data */
+#define PMCS_VPD_START 0x82 /* VPD start byte */
+#define PMCS_VPD_END 0x78 /* VPD end byte */
+
+/*
+ * This structure defines the "header" for the VPD data. Everything
+ * following this structure is self-defining. The consumer just needs
+ * to allocate a buffer large enough for vpd_length + 3 bytes of data.
+ */
+
+typedef struct {
+ uint8_t eeprom_version;
+ uint8_t vpd_length[2]; /* # bytes that follow, little-endian */
+ uint8_t hba_sas_wwid[8];
+ uint8_t subsys_pid[2];
+ uint8_t subsys_vid[2];
+ uint8_t vpd_start_byte; /* 0x82 */
+ uint8_t strid_length[2]; /* little-endian */
+ /* strid_length bytes follow */
+} pmcs_vpd_header_t;
+
+typedef struct {
+ char keyword[2];
+ uint8_t value_length;
+ char value[1]; /* Length is actually value_length */
+} pmcs_vpd_kv_t;
+
+/*
+ * From here on out are definitions related to Outbound Queues
+ * (completions of Inbound Queue requests and async events)
+ */
+
+/*
+ * PMC IOMB Outbound Queue Opcodes
+ */
+#define PMCOUT_ECHO 0x01
+#define PMCOUT_GET_INFO 0x02
+#define PMCOUT_GET_VPD 0x03
+#define PMCOUT_SAS_HW_EVENT 0x04
+#define PMCOUT_SSP_COMPLETION 0x05
+#define PMCOUT_SMP_COMPLETION 0x06
+#define PMCOUT_LOCAL_PHY_CONTROL 0x07
+#define PMCOUT_SAS_ASSISTED_DISCOVERY_EVENT 0x08
+#define PMCOUT_SATA_ASSISTED_DISCOVERY_EVENT 0x09
+#define PMCOUT_DEVICE_REGISTRATION 0x0A
+#define PMCOUT_DEREGISTER_DEVICE_HANDLE 0x0B
+#define PMCOUT_GET_DEVICE_HANDLE 0x0C
+#define PMCOUT_SATA_COMPLETION 0x0D
+#define PMCOUT_SATA_EVENT 0x0E
+#define PMCOUT_SSP_EVENT 0x0F
+#define PMCOUT_DEVICE_HANDLE_ARRIVED 0x10
+#define PMCOUT_SMP_REQUEST_RECEIVED 0x11
+#define PMCOUT_SSP_REQUEST_RECEIVED 0x12
+#define PMCOUT_DEVICE_INFO 0x13
+#define PMCOUT_FW_FLASH_UPDATE 0x14
+#define PMCOUT_SET_VPD 0x15
+#define PMCOUT_GPIO 0x16
+#define PMCOUT_GPIO_EVENT 0x17
+#define PMCOUT_GENERAL_EVENT 0x18
+#define PMCOUT_TWI 0x19
+#define PMCOUT_SSP_ABORT 0x1A
+#define PMCOUT_SATA_ABORT 0x1B
+#define PMCOUT_SAS_DIAG_MODE_START_END 0x1C
+#define PMCOUT_SAS_DIAG_EXECUTE 0x1D
+#define PMCOUT_GET_TIME_STAMP 0x1E
+#define PMCOUT_SAS_HW_EVENT_ACK_ACK 0x1F
+#define PMCOUT_PORT_CONTROL 0x20
+#define PMCOUT_SKIP_ENTRIES 0x21
+#define PMCOUT_SMP_ABORT 0x22
+#define PMCOUT_GET_NVMD_DATA 0x23
+#define PMCOUT_SET_NVMD_DATA 0x24
+#define PMCOUT_DEVICE_HANDLE_REMOVED 0x25
+#define PMCOUT_SET_DEVICE_STATE 0x26
+#define PMCOUT_GET_DEVICE_STATE 0x27
+#define PMCOUT_SET_DEVICE_INFO 0x28
+
+/*
+ * General Outbound Status Definitions
+ */
+#define PMCOUT_STATUS_OK 0x00
+#define PMCOUT_STATUS_ABORTED 0x01
+#define PMCOUT_STATUS_OVERFLOW 0x02
+#define PMCOUT_STATUS_UNDERFLOW 0x03
+#define PMCOUT_STATUS_FAILED 0x04
+#define PMCOUT_STATUS_ABORT_RESET 0x05
+#define PMCOUT_STATUS_IO_NOT_VALID 0x06
+#define PMCOUT_STATUS_NO_DEVICE 0x07
+#define PMCOUT_STATUS_ILLEGAL_PARAMETER 0x08
+#define PMCOUT_STATUS_LINK_FAILURE 0x09
+#define PMCOUT_STATUS_PROG_ERROR 0x0A
+#define PMCOUT_STATUS_EDC_IN_ERROR 0x0B
+#define PMCOUT_STATUS_EDC_OUT_ERROR 0x0C
+#define PMCOUT_STATUS_ERROR_HW_TIMEOUT 0x0D
+#define PMCOUT_STATUS_XFER_ERR_BREAK 0x0E
+#define PMCOUT_STATUS_XFER_ERR_PHY_NOT_READY 0x0F
+#define PMCOUT_STATUS_OPEN_CNX_PROTOCOL_NOT_SUPPORTED 0x10
+#define PMCOUT_STATUS_OPEN_CNX_ERROR_ZONE_VIOLATION 0x11
+#define PMCOUT_STATUS_OPEN_CNX_ERROR_BREAK 0x12
+#define PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS 0x13
+#define PMCOUT_STATUS_OPENCNX_ERROR_BAD_DESTINATION 0x14
+#define PMCOUT_STATUS_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED 0x15
+#define PMCOUT_STATUS_OPEN_CNX_ERROR_STP_RESOURCES_BUSY 0x16
+#define PMCOUT_STATUS_OPEN_CNX_ERROR_WRONG_DESTINATION 0x17
+#define PMCOUT_STATUS_OPEN_CNX_ERROR_UNKNOWN_EROOR 0x18
+#define PMCOUT_STATUS_IO_XFER_ERROR_NAK_RECEIVED 0x19
+#define PMCOUT_STATUS_XFER_ERROR_ACK_NAK_TIMEOUT 0x1A
+#define PMCOUT_STATUS_XFER_ERROR_PEER_ABORTED 0x1B
+#define PMCOUT_STATUS_XFER_ERROR_RX_FRAME 0x1C
+#define PMCOUT_STATUS_IO_XFER_ERROR_DMA 0x1D
+#define PMCOUT_STATUS_XFER_ERROR_CREDIT_TIMEOUT 0x1E
+#define PMCOUT_STATUS_XFER_ERROR_SATA_LINK_TIMEOUT 0x1F
+#define PMCOUT_STATUS_XFER_ERROR_SATA 0x20
+#define PMCOUT_STATUS_XFER_ERROR_REJECTED_NCQ_MODE 0x21
+#define PMCOUT_STATUS_XFER_ERROR_ABORTED_DUE_TO_SRST 0x22
+#define PMCOUT_STATUS_XFER_ERROR_ABORTED_NCQ_MODE 0x23
+#define PMCOUT_STATUS_IO_XFER_OPEN_RETRY_TIMEOUT 0x24
+#define PMCOUT_STATUS_SMP_RESP_CONNECTION_ERROR 0x25
+#define PMCOUT_STATUS_XFER_ERROR_UNEXPECTED_PHASE 0x26
+#define PMCOUT_STATUS_XFER_ERROR_RDY_OVERRUN 0x27
+#define PMCOUT_STATUS_XFER_ERROR_RDY_NOT_EXPECTED 0x28
+/* 0x29 */
+/* 0x2A */
+/* 0x2B */
+/* 0x2C */
+/* 0x2D */
+/* 0x2E */
+/* 0x2F */
+#define PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT 0x30
+#define PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_BREAK_BEFORE_ACK_NACK 0x31
+#define PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_PHY_DOWN_BEFORE_ACK_NAK 0x32
+/* 0x33 */
+#define PMCOUT_STATUS_XFER_ERROR_OFFSET_MISMATCH 0x34
+#define PMCOUT_STATUS_XFER_ERROR_ZERO_DATA_LEN 0x35
+#define PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED 0x36
+#define PMCOUT_STATUS_ERROR_INTERNAL_SMP_RESOURCE 0x37
+#define PMCOUT_STATUS_IO_PORT_IN_RESET 0x38
+#define PMCOUT_STATUS_IO_DS_NON_OPERATIONAL 0x39
+#define PMCOUT_STATUS_IO_DS_IN_RECOVERY 0x3A
+#define PMCOUT_STATUS_IO_ABORT_IN_PROGRESS 0x40
+
+/*
+ * Device State definitions
+ */
+#define PMCS_DEVICE_STATE_OPERATIONAL 0x1
+#define PMCS_DEVICE_STATE_PORT_IN_RESET 0x2
+#define PMCS_DEVICE_STATE_IN_RECOVERY 0x3
+#define PMCS_DEVICE_STATE_IN_ERROR 0x4
+#define PMCS_DEVICE_STATE_NON_OPERATIONAL 0x7
+
+/*
+ * Reset Types
+ */
+#define PMCS_SSP_LINK_RESET 0x1
+#define PMCS_SSP_HARD_RESET 0x2
+#define PMCS_SMP_HARD_RESET 0x3
+
+/*
+ * PHYOP for LOCAL_PHY_CONTROL Command
+ */
+#define PMCS_PHYOP_LINK_RESET 0x01
+#define PMCS_PHYOP_HARD_RESET 0x02
+
+/*
+ * Specialized status values
+ */
+/* PHY Stop Status Results */
+#define IOP_PHY_STOP_OK 0x0
+#define IOP_PHY_STOP_INVALID 0x1
+#define IOP_PHY_STOP_ERROR 0x3
+#define IOP_PHY_STOP_ALREADY 0x4
+
+/* PHY Start Status Results */
+#define IOP_PHY_START_OK 0
+#define IOP_PHY_START_INVALID 1
+#define IOP_PHY_START_ALREADY 2
+#define IOP_PHY_START_ERROR 3
+
+/* SET/GET_NVMD status results */
+#define PMCS_NVMD_STAT_SUCCESS 0x0000
+#define PMCS_NVMD_STAT_PLD_NVMD_COMB_ERR 0x0001
+#define PMCS_NVMD_STAT_PLD_LEN_ERR 0x0002
+#define PMCS_NVMD_STAT_TWI_DEV_NACK 0x2001
+#define PMCS_NVMD_STAT_TWI_DEV_LOST_ARB 0x2002
+#define PMCS_NVMD_STAT_TWI_TIMEOUT 0x2021
+#define PMCS_NVMD_STAT_TWI_BUS_NACK 0x2081
+#define PMCS_NVMD_STAT_TWI_DEV_ARB_FAIL 0x2082
+#define PMCS_NVMD_STAT_TWI_BUS_SER_TIMEO 0x20FF
+#define PMCS_NVMD_STAT_PART_NOT_IN_FLASH 0x9001
+#define PMCS_NVMD_STAT_LEN_TOO_LARGE 0x9002
+#define PMCS_NVMD_STAT_FLASH_PRGRM_FAIL 0x9003
+#define PMCS_NVMD_STAT_DEVID_MATCH_FAIL 0x9004
+#define PMCS_NVMD_STAT_VENDID_MATCH_FAIL 0x9005
+#define PMCS_NVMD_STAT_SEC_ERASE_TIMEO 0x9006
+#define PMCS_NVMD_STAT_SEC_ERASE_CWE 0x9007
+#define PMCS_NVMD_STAT_FLASH_DEV_BUSY 0x9008
+#define PMCS_NVMD_STAT_FLASH_DEV_NOT_SUP 0x9009
+#define PMCS_NVMD_STAT_FLASH_NO_CFI 0x900A
+#define PMCS_NVMD_STAT_ERASE_BLOCKS 0x900B
+#define PMCS_NVMD_STAT_PART_READ_ONLY 0x900C
+#define PMCS_NVMD_STAT_PART_INV_MAP_TYPE 0x900D
+#define PMCS_NVMD_STAT_PART_INIT_STR_DIS 0x900E
+
+/*
+ * General Event Status Codes
+ */
+#define INBOUND_IOMB_V_BIT_NOT_SET 0x1
+#define INBOUND_IOMB_OPC_NOT_SUPPORTED 0x2
+
+/* Device Register Status Results */
+#define PMCS_DEVREG_OK 0x0
+#define PMCS_DEVREG_DEVICE_ALREADY_REGISTERED 0x2
+#define PMCS_DEVREG_PHY_ALREADY_REGISTERED 0x4
+
+/*
+ * Flash Update responses
+ */
+#define FLASH_UPDATE_COMPLETE_PENDING_REBOOT 0x0
+#define FLASH_UPDATE_IN_PROGRESS 0x1
+#define FLASH_UPDATE_HDR_ERR 0x2
+#define FLASH_UPDATE_OFFSET_ERR 0x3
+#define FLASH_UPDATE_UPDATE_CRC_ERR 0x4
+#define FLASH_UPDATE_LENGTH_ERR 0x5
+#define FLASH_UPDATE_HW_ERR 0x6
+#define FLASH_UPDATE_DNLD_NOT_SUPPORTED 0x10
+#define FLASH_UPDATE_DISABLED 0x11
+
+/*
+ * IOP SAS HW Event Related definitions
+ */
+
+#define IOP_EVENT_LINK_RATE(x) ((x >> 28) & 0xf)
+#define IOP_EVENT_STATUS(x) ((x >> 24) & 0xf)
+#define IOP_EVENT_EVENT(x) ((x >> 8) & 0xffff)
+#define IOP_EVENT_PHYNUM(x) ((x >> 4) & 0xf)
+#define IOP_EVENT_PORTID(x) ((x) & 0xf)
+
+
+#define IOP_EVENT_PHY_STOP_STATUS 0x03
+#define IOP_EVENT_SAS_PHY_UP 0x04
+#define IOP_EVENT_SATA_PHY_UP 0x05
+#define IOP_EVENT_SATA_SPINUP_HOLD 0x06
+#define IOP_EVENT_PHY_DOWN 0x07
+#define IOP_EVENT_PORT_INVALID 0x08 /* < fw 1.6 */
+#define IOP_EVENT_BROADCAST_CHANGE 0x09
+#define IOP_EVENT_BROADCAST_SES 0x0B
+#define IOP_EVENT_PHY_ERR_INBOUND_CRC 0x0C
+#define IOP_EVENT_HARD_RESET_RECEIVED 0x0D
+#define IOP_EVENT_EVENT_ID_FRAME_TIMO 0x0F
+#define IOP_EVENT_BROADCAST_EXP 0x10
+#define IOP_EVENT_PHY_START_STATUS 0x11
+#define IOP_EVENT_PHY_ERR_INVALID_DWORD 0x12
+#define IOP_EVENT_PHY_ERR_DISPARITY_ERROR 0x13
+#define IOP_EVENT_PHY_ERR_CODE_VIOLATION 0x14
+#define IOP_EVENT_PHY_ERR_LOSS_OF_DWORD_SYN 0x15
+#define IOP_EVENT_PHY_ERR_PHY_RESET_FAILD 0x16
+#define IOP_EVENT_PORT_RECOVERY_TIMER_TMO 0x17
+#define IOP_EVENT_PORT_RECOVER 0x18
+#define IOP_EVENT_PORT_RESET_TIMER_TMO 0x19
+#define IOP_EVENT_PORT_RESET_COMPLETE 0x20
+#define IOP_EVENT_BROADCAST_ASYNC_EVENT 0x21
+
+
+#define IOP_EVENT_PORT_STATE(x) ((x) & 0xf)
+#define IOP_EVENT_NPIP(x) (((x) >> 4) & 0xf)
+
+#define IOP_EVENT_PS_NIL 0x0 /* PORT_ID not valid yet */
+#define IOP_EVENT_PS_VALID 0x1 /* PORT_ID now valid */
+#define IOP_EVENT_PS_LOSTCOMM 0x2 /* Link temporarily down */
+#define IOP_EVENT_PS_IN_RESET 0x4 /* Port in reset */
+#define IOP_EVENT_PS_INVALID 0x8 /* PORT_ID now dead */
+
+/*
+ * HW Event Acknowledge Response Values
+ */
+#define SAS_HW_EVENT_ACK_OK 0x0
+#define SAS_HW_EVENT_ACK_INVALID_SEA 0x1
+#define SAS_HW_EVENT_ACK_INVALID_PHY 0x2
+#define SAS_HW_EVENT_ACK_INVALID_PORT 0x4
+#define SAS_HW_EVENT_ACK_INVALID_PARAM 0x8
+
+/*
+ * IOMB Queue definitions and Macros
+ */
+
+#define ADDQI(ix, n, qd) ((ix + n) & (qd - 1))
+#define INCQI(ix, qd) ix = ADDQI(ix, 1, qd)
+#define QI2O(ix, n, qd) (ADDQI(ix, n, qd) * PMCS_QENTRY_SIZE)
+
+/*
+ * Inbound Queue Producer Indices live inside the PMC card.
+ *
+ * Inbound Queue Consumer indices live in host memory. We use the Consumer
+ * Index to return a pointer to an Inbound Queue entry. We then can fill
+ * it with an IOMB. We then update the the Producer index which kicks
+ * card to read the IOMB we just wrote.
+ *
+ * There is one mutex for each inbound queue that is held from the time
+ * we get an entry until we increment the producer index, or released
+ * manually if we don't actually send the message.
+ */
+
+/*
+ * NB: the appropriate iqp_lock must be held
+ */
+#define GET_IQ_ENTRY(hwp, qnum) \
+ ((ADDQI(hwp->shadow_iqpi[qnum], 1, hwp->ioq_depth) == \
+ pmcs_rd_iqci(hwp, qnum)) ? NULL : \
+ &hwp->iqp[qnum][hwp->shadow_iqpi[qnum] * (PMCS_QENTRY_SIZE >> 2)])
+
+/*
+ * NB: This releases the lock on the Inbound Queue that GET_IO_IQ_ENTRY
+ * acquired below.
+ */
+#ifdef DEBUG
+#define INC_IQ_ENTRY(hwp, qnum) \
+{ \
+ uint32_t htag; \
+ ASSERT(mutex_owned(&(hwp)->iqp_lock[qnum])); \
+ htag = hwp->iqp[qnum][(hwp->shadow_iqpi[qnum] * \
+ (PMCS_QENTRY_SIZE >> 2)) + 1]; \
+ mutex_enter(&(hwp)->dbglock); \
+ pmcs_iqp_trace(hwp, qnum); \
+ mutex_exit(&(hwp)->dbglock); \
+ INCQI(hwp->shadow_iqpi[qnum], hwp->ioq_depth); \
+ if (ddi_dma_sync(hwp->cip_handles, 0, 0, \
+ DDI_DMA_SYNC_FORDEV) != DDI_SUCCESS) { \
+ pmcs_prt(hwp, PMCS_PRT_DEBUG, "Condition failed at " \
+ " %s():%d", __func__, __LINE__); \
+ } \
+ pmcs_wr_iqpi(hwp, qnum, hwp->shadow_iqpi[qnum]); \
+ mutex_exit(&(hwp)->iqp_lock[qnum]); \
+ mutex_enter(&(hwp)->dbglock); \
+ hwp->ftag_lines[hwp->fti] = __LINE__; \
+ hwp->ftime[hwp->fti] = gethrtime(); \
+ hwp->ftags[hwp->fti++] = htag; \
+ mutex_exit(&(hwp)->dbglock); \
+}
+#else
+#define INC_IQ_ENTRY(hwp, qnum) \
+ INCQI(hwp->shadow_iqpi[qnum], hwp->ioq_depth); \
+ if (ddi_dma_sync(hwp->cip_handles, 0, 0, \
+ DDI_DMA_SYNC_FORDEV) != DDI_SUCCESS) { \
+ pmcs_prt(hwp, PMCS_PRT_DEBUG, "Condition failed at " \
+ " %s():%d", __func__, __LINE__); \
+ } \
+ pmcs_wr_iqpi(hwp, qnum, hwp->shadow_iqpi[qnum]); \
+ mutex_exit(&(hwp)->iqp_lock[qnum])
+#endif
+
+
+/*
+ * NB: sucessfull acquisition of an IO Inbound Queue
+ * entry leaves the lock on that Inbound Queue held.
+ */
+#define GET_IO_IQ_ENTRY(pwp, msg, did, iq) \
+ iq = did & PMCS_IO_IQ_MASK; \
+ mutex_enter(&(pwp)->iqp_lock[iq]); \
+ msg = GET_IQ_ENTRY(pwp, iq); \
+ if (msg == NULL) { \
+ mutex_exit(&(pwp)->iqp_lock[iq]); \
+ for (iq = 0; iq <= PMCS_NON_HIPRI_QUEUES; iq++) { \
+ mutex_enter(&(pwp)->iqp_lock[iq]); \
+ msg = GET_IQ_ENTRY(pwp, iq); \
+ if (msg) { \
+ break; \
+ } \
+ mutex_exit(&(pwp->iqp_lock[iq])); \
+ } \
+ }
+
+/*
+ * Outbound Queue Macros
+ *
+ * Outbound Queue Consumer indices live inside the card.
+ *
+ * Outbound Queue Producer indices live in host memory. When the card
+ * wants to send an IOMB, it uses the producer index to find the spot
+ * to write the IOMB. After it's done it updates the producer index
+ * and interrupts the host. The host reads the producer index (from
+ * host memory) and reads IOMBs up to but not including that index.
+ * It writes that index back to the consumer index on the card,
+ * signifying that it has read up to that which the card has sent.
+ */
+#define GET_OQ_ENTRY(hwp, qn, ix, o) \
+ &hwp->oqp[qn][QI2O(ix, o, hwp->ioq_depth) >> 2]
+
+#define STEP_OQ_ENTRY(hwp, qn, ix, n) ix = ADDQI(ix, n, hwp->ioq_depth)
+
+#define SYNC_OQ_ENTRY(hwp, qn, ci, pi) \
+ pmcs_wr_oqci(hwp, qn, ci); \
+ (hwp)->oqci[qn] = ci; \
+ (hwp)->oqpi[qn] = pi
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _PMCS_IOMB_H */
diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_mpi.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_mpi.h
new file mode 100644
index 0000000000..b0c875e871
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_mpi.h
@@ -0,0 +1,222 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * PMC 8x6G Message Passing Interface Definitions
+ */
+#ifndef _PMCS_MPI_H
+#define _PMCS_MPI_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PMCS_DWRD(x) (x << 2)
+
+/*
+ * MPI Configuration Table Offsets
+ */
+#define PMCS_MPI_AS PMCS_DWRD(0) /* ASCII Signature */
+#define PMCS_SIGNATURE 0x53434D50
+
+#define PMCS_MPI_IR PMCS_DWRD(1) /* Interface Revision */
+#define PMCS_MPI_REVISION1 1
+
+#define PMCS_MPI_FW PMCS_DWRD(2) /* Firmware Version */
+#define PMCS_FW_TYPE(hwp) (hwp->fw & 0xf)
+#define PMCS_FW_TYPE_RELEASED 0
+#define PMCS_FW_TYPE_DEVELOPMENT 1
+#define PMCS_FW_TYPE_ALPHA 2
+#define PMCS_FW_TYPE_BETA 3
+#define PMCS_FW_VARIANT(hwp) ((hwp->fw >> 4) & 0xf)
+#define PMCS_FW_MAJOR(hwp) ((hwp->fw >> 24) & 0xff)
+#define PMCS_FW_MINOR(hwp) ((hwp->fw >> 16) & 0xff)
+#define PMCS_FW_MICRO(hwp) ((hwp->fw >> 8) & 0xff)
+#define PMCS_FW_REV(hwp) ((hwp->fw >> 8) & 0xffffff)
+#define PMCS_FW_VERSION(maj, min, mic) ((maj << 16)|(min << 8)|mic)
+
+#define PMCS_MPI_MOIO PMCS_DWRD(3) /* Maximum # of outstandiong I/Os */
+#define PMCS_MPI_INFO0 PMCS_DWRD(4) /* Maximum S/G Elem, Max Dev Handle */
+#define PMCS_MSGL(x) (x & 0xffff)
+#define PMCS_MD(x) ((x >> 16) & 0xffff)
+
+#define PMCS_MPI_INFO1 PMCS_DWRD(5) /* Info #0 */
+
+#define PMCS_MNIQ(x) (x & 0xff) /* Max # of Inbound Queues */
+#define PMCS_MNOQ(x) ((x >> 8) & 0xff) /* Max # of Outbound Queues */
+#define PMCS_HPIQ(x) ((x >> 16) & 0x1) /* High Pri Queue Supported */
+#define PMCS_ICS(x) ((x >> 18) & 0x1) /* Interrupt Coalescing */
+#define PMCS_NPHY(x) ((x >> 19) & 0x3f) /* Numbers of PHYs */
+#define PMCS_SASREV(x) ((x >> 25) & 0x7) /* SAS Revision Specification */
+
+#define PMCS_MPI_GSTO PMCS_DWRD(6) /* General Status Table Offset */
+#define PMCS_MPI_IQCTO PMCS_DWRD(7) /* Inbound Queue Config Table Offset */
+#define PMCS_MPI_OQCTO PMCS_DWRD(8) /* Outbound Queue Config Table Offset */
+
+#define PMCS_MPI_INFO2 PMCS_DWRD(9) /* Info #1 */
+
+#define IQ_NORMAL_PRI_DEPTH_SHIFT 0
+#define IQ_NORMAL_PRI_DEPTH_MASK 0xff
+#define IQ_HIPRI_PRI_DEPTH_SHIFT 8
+#define IQ_HIPRI_PRI_DEPTH_MASK 0xff00
+#define GENERAL_EVENT_OQ_SHIFT 16
+#define GENERAL_EVENT_OQ_MASK 0xff0000
+#define DEVICE_HANDLE_REMOVED_SHIFT 24
+#define DEVICE_HANDLE_REMOVED_MASK 0xff000000ul
+
+#define PMCS_MPI_EVQS PMCS_DWRD(0xA) /* SAS Event Queues */
+#define PMCS_MPI_EVQSET(pwp, oq, phy) { \
+ uint32_t woff = phy / 4; \
+ uint32_t shf = (phy % 4) * 8; \
+ uint32_t tmp = pmcs_rd_mpi_tbl(pwp, PMCS_MPI_EVQS + (woff << 2)); \
+ tmp &= ~(0xff << shf); \
+ tmp |= ((oq & 0xff) << shf); \
+ pmcs_wr_mpi_tbl(pwp, PMCS_MPI_EVQS + (woff << 2), tmp); \
+}
+
+#define PMCS_MPI_SNCQ PMCS_DWRD(0xC) /* Sata NCQ Notification Queues */
+#define PMCS_MPI_NCQSET(pwp, oq, phy) { \
+ uint32_t woff = phy / 4; \
+ uint32_t shf = (phy % 4) * 8; \
+ uint32_t tmp = pmcs_rd_mpi_tbl(pwp, PMCS_MPI_SNCQ + (woff << 2)); \
+ tmp &= ~(0xff << shf); \
+ tmp |= ((oq & 0xff) << shf); \
+ pmcs_wr_mpi_tbl(pwp, PMCS_MPI_SNCQ + (woff << 2), tmp); \
+}
+
+/*
+ * I_T Nexus Target Event Notification Queue
+ */
+#define PMCS_MPI_IT_NTENQ PMCS_DWRD(0xE)
+
+/*
+ * SSP Target Event Notification Queue
+ */
+#define PMCS_MPI_SSP_TENQ PMCS_DWRD(0x10)
+
+/*
+ * SMP Target Event Notification Queue
+ */
+#define PMCS_MPI_SMP_TENQ PMCS_DWRD(0x12)
+
+/*
+ * This specifies a log buffer in host memory for the MSGU.
+ */
+#define PMCS_MPI_MELBAH PMCS_DWRD(0x14) /* MSGU Log Buffer high 32 bits */
+#define PMCS_MPI_MELBAL PMCS_DWRD(0x15) /* MSGU Log Buffer low 32 bits */
+#define PMCS_MPI_MELBS PMCS_DWRD(0x16) /* size in bytes of MSGU log buffer */
+#define PMCS_MPI_MELSEV PMCS_DWRD(0x17) /* Log Severity */
+
+/*
+ * This specifies a log buffer in host memory for the IOP.
+ */
+#define PMCS_MPI_IELBAH PMCS_DWRD(0x18) /* IOP Log Buffer high 32 bits */
+#define PMCS_MPI_IELBAL PMCS_DWRD(0x19) /* IOP Log Buffer low 32 bits */
+#define PMCS_MPI_IELBS PMCS_DWRD(0x1A) /* size in bytes of IOP log buffer */
+#define PMCS_MPI_IELSEV PMCS_DWRD(0x1B) /* Log Severity */
+
+/*
+ * Fatal Error Handling
+ */
+#define PMCS_MPI_FERR PMCS_DWRD(0x1C)
+#define PMCS_FERRIE 0x1 /* Fatal Err Interrupt Enable */
+#define PMCS_FERIV_MASK 0xff00 /* Fatal Err Interrupt Mask */
+#define PMCS_FERIV_SHIFT 8 /* Fatal Err Interrupt Shift */
+
+#define PMCS_MPI_IRAE 0x20000 /* Interrupt Reassertion Enable */
+#define PMCS_MPI_IRAU 0x40000 /* Interrupt Reassertion Unit */
+#define PMCS_MPI_IRAD_MASK 0xfff80000 /* Reassertion Delay Mask */
+
+#define PMCS_FERDOMSGU PMCS_DWRD(0x1D)
+#define PMCS_FERDLMSGU PMCS_DWRD(0x1E)
+#define PMCS_FERDOIOP PMCS_DWRD(0x1F)
+#define PMCS_FERDLIOP PMCS_DWRD(0x20)
+
+/*
+ * MPI GST Table Offsets
+ */
+
+#define PMCS_GST_BASE 0
+#define PMCS_GST_IQFRZ0 (PMCS_GST_BASE + PMCS_DWRD(1))
+#define PMCS_GST_IQFRZ1 (PMCS_GST_BASE + PMCS_DWRD(2))
+#define PMCS_GST_MSGU_TICK (PMCS_GST_BASE + PMCS_DWRD(3))
+#define PMCS_GST_IOP_TICK (PMCS_GST_BASE + PMCS_DWRD(4))
+#define PMCS_GST_PHY_INFO(x) (PMCS_GST_BASE + PMCS_DWRD(0x6) + PMCS_DWRD(x))
+#define PMCS_GST_RERR_BASE (PMCS_GST_BASE + PMCS_DWRD(0x11))
+#define PMCS_GST_RERR_INFO(x) (PMCS_GST_RERR_BASE + PMCS_DWRD(x))
+
+#define PMCS_MPI_S(x) ((x) & 0x7)
+#define PMCS_QF(x) (((x) >> 3) & 0x1)
+#define PMCS_GSTLEN(x) (((x) >> 4) & 0x3fff)
+#define PMCS_HMI_ERR(x) (((x) >> 16) & 0xffff)
+
+#define PMCS_MPI_STATE_NIL 0
+#define PMCS_MPI_STATE_INIT 1
+#define PMCS_MPI_STATE_DEINIT 2
+#define PMCS_MPI_STATE_ERR 3
+
+/*
+ * MPI Inbound Queue Configuration Table Offsets
+ *
+ * Each Inbound Queue configuration area consumes 8 DWORDS (32 bit words),
+ * or 32 bytes.
+ */
+#define PMCS_IQC_PARMX(x) ((x) << 5)
+#define PMCS_IQBAHX(x) (((x) << 5) + 4)
+#define PMCS_IQBALX(x) (((x) << 5) + 8)
+#define PMCS_IQCIBAHX(x) (((x) << 5) + 12)
+#define PMCS_IQCIBALX(x) (((x) << 5) + 16)
+#define PMCS_IQPIBARX(x) (((x) << 5) + 20)
+#define PMCS_IQPIOFFX(x) (((x) << 5) + 24)
+#define PMCS_IQDX(x) ((x) & 0xffff)
+#define PMCS_IQESX(x) (((x) >> 16) & 0x3fff)
+#define PMCS_IQPX(x) (((x) >> 30) & 0x3)
+
+/*
+ * MPI Outbound Queue Configuration Table Offsets
+ *
+ * Each Outbound Queue configuration area consumes 9 DWORDS (32 bit words),
+ * or 36 bytes.
+ */
+#define PMCS_OQC_PARMX(x) (x * 36)
+#define PMCS_OQBAHX(x) ((x * 36) + 4)
+#define PMCS_OQBALX(x) ((x * 36) + 8)
+#define PMCS_OQPIBAHX(x) ((x * 36) + 12)
+#define PMCS_OQPIBALX(x) ((x * 36) + 16)
+#define PMCS_OQCIBARX(x) ((x * 36) + 20)
+#define PMCS_OQCIOFFX(x) ((x * 36) + 24)
+#define PMCS_OQIPARM(x) ((x * 36) + 28)
+#define PMCS_OQDICX(x) ((x * 36) + 32)
+
+#define PMCS_OQDX(x) ((x) & 0xffff)
+#define PMCS_OQESX(x) (((x) >> 16) & 0x3fff)
+#define PMCS_OQICT(x) ((x) & 0xffff)
+#define PMCS_OQICC(x) (((x) >> 16) & 0xff)
+#define PMCS_OQIV(x) (((x) >> 24) & 0xff)
+
+#define OQIEX (1 << 30)
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _PMCS_MPI_H */
diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_param.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_param.h
new file mode 100644
index 0000000000..0522ce6e88
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_param.h
@@ -0,0 +1,138 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * PMC Compile Time Tunable Parameters
+ */
+#ifndef _PMCS_PARAM_H
+#define _PMCS_PARAM_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Maximum number of microseconds we will try to configure a PHY
+ */
+#define PMCS_MAX_CONFIG_TIME (60 * 1000000)
+
+#define PMCS_MAX_OQ 64 /* maximum number of OutBound Queues */
+#define PMCS_MAX_IQ 64 /* maximum number of InBound Queues */
+
+#define PMCS_MAX_PORTS 16 /* maximum port contexts */
+
+#define PMCS_MAX_XPND 16 /* 16 levels of expansion */
+
+#define PMCS_INDICES_SIZE 512
+
+#define PMCS_MIN_CHUNK_PAGES 512
+#define PMCS_ADDTL_CHUNK_PAGES 8
+
+/*
+ * Scratch area has to hold Max SMP Request and Max SMP Response,
+ * plus some slop.
+ */
+#define PMCS_SCRATCH_SIZE 2304
+#define PMCS_INITIAL_DMA_OFF PMCS_INDICES_SIZE+PMCS_SCRATCH_SIZE
+#define PMCS_CONTROL_SIZE ptob(1)
+
+/*
+ * 2M bytes was allocated to firmware log and split between two logs
+ */
+#define PMCS_FWLOG_SIZE (2 << 20)
+#define PMCS_FWLOG_MAX 5 /* maximum logging level */
+#define SATLSIZE 1024
+
+/*
+ * PMCS_NQENTRY is tunable by setting pmcs-num-io-qentries
+ */
+#define PMCS_NQENTRY 512 /* 512 entries per queue */
+#define PMCS_MIN_NQENTRY 32 /* No less than 32 entries per queue */
+#define PMCS_QENTRY_SIZE 64 /* 64 bytes per entry */
+#define PMCS_MSG_SIZE (PMCS_QENTRY_SIZE >> 2)
+
+/*
+ * Watchdog interval, in usecs.
+ * NB: Needs to be evenly divisible by 10
+ */
+#define PMCS_WATCH_INTERVAL 250000 /* watchdog interval in us */
+
+/*
+ * Inbound Queue definitions
+ */
+#define PMCS_NIQ 9 /* 9 Inbound Queues */
+#define PMCS_IO_IQ_MASK 7 /* IO queues are 0..7 */
+#define PMCS_IQ_OTHER 8 /* "Other" queue is 8 (HiPri) */
+#define PMCS_NON_HIPRI_QUEUES PMCS_IO_IQ_MASK
+
+/*
+ * Outbound Queue definitions
+ *
+ * Note that the OQ definitions map to bits set in
+ * the Outbound Doorbell register to indicate service
+ * is needed on one of these queues.
+ */
+#define PMCS_NOQ 3 /* 3 Outbound Queues */
+
+#define PMCS_OQ_IODONE 0 /* I/O completion Outbound Queue */
+#define PMCS_OQ_GENERAL 1 /* General Outbound Queue */
+#define PMCS_OQ_EVENTS 2 /* Event Outbound Queue */
+
+
+/*
+ * External Scatter Gather come in chunks- each this many deep.
+ */
+#define PMCS_SGL_NCHUNKS 16 /* S/G List Chunk Size */
+#define PMCS_MAX_CHUNKS 32 /* max chunks per command */
+
+/*
+ * MSI/MSI-X related definitions.
+ *
+ * These are the maximum number of interrupt vectors we could use.
+ */
+#define PMCS_MAX_MSIX (PMCS_NOQ + 1)
+#define PMCS_MAX_MSI PMCS_MAX_MSIX
+#define PMCS_MAX_FIXED 1
+
+#define PMCS_MSIX_IODONE PMCS_OQ_IODONE /* I/O Interrupt vector */
+#define PMCS_MSIX_GENERAL PMCS_OQ_GENERAL /* General Interrupt vector */
+#define PMCS_MSIX_EVENTS PMCS_OQ_EVENTS /* Events Interrupt vector */
+#define PMCS_MSIX_FATAL (PMCS_MAX_MSIX-1) /* Fatal Int vector */
+
+#define PMCS_FATAL_INTERRUPT 15 /* fatal interrupt OBDB bit */
+
+/*
+ * Blessed firmware version
+ */
+#define PMCS_FIRMWARE_CODE_NAME "firmware"
+#define PMCS_FIRMWARE_ILA_NAME "ila"
+#define PMCS_FIRMWARE_SPCBOOT_NAME "SPCBoot"
+#define PMCS_FIRMWARE_START_SUF ".bin_start"
+#define PMCS_FIRMWARE_END_SUF ".bin_end"
+#define PMCS_FIRMWARE_FILENAME "misc/pmcs/pmcs8001fw"
+#define PMCS_FIRMWARE_VERSION_NAME "pmcs8001_fwversion"
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _PMCS_PARAM_H */
diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_proto.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_proto.h
new file mode 100644
index 0000000000..d28b0a56ef
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_proto.h
@@ -0,0 +1,353 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * This file provides prototype function definitions.
+ */
+#ifndef _PMCS_PROTO_H
+#define _PMCS_PROTO_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef enum {
+ PMCS_PRT_DEBUG = 0,
+ PMCS_PRT_DEBUG1,
+ PMCS_PRT_DEBUG2,
+ PMCS_PRT_DEBUG3,
+ PMCS_PRT_DEBUG_CONFIG,
+ PMCS_PRT_DEBUG_IPORT,
+ PMCS_PRT_DEBUG_MAP,
+ PMCS_PRT_DEBUG_UNDERFLOW,
+ PMCS_PRT_DEBUG_SCSI_STATUS,
+ PMCS_PRT_DEBUG_PHY_LOCKING,
+ PMCS_PRT_DEBUG_DEV_STATE,
+ PMCS_PRT_DEBUG_DEVEL,
+ PMCS_PRT_INFO,
+ PMCS_PRT_WARN,
+ PMCS_PRT_ERR
+} pmcs_prt_level_t;
+
+#define pmcs_prt(pwp, level, fmt...) { \
+ int lvl = level; \
+ if (((pwp->debug_mask & (1 << lvl)) != 0) || \
+ (lvl > PMCS_PRT_DEBUG_DEVEL)) { \
+ pmcs_prt_impl(pwp, lvl, fmt); \
+ } \
+}
+
+/*PRINTFLIKE3*/
+void
+pmcs_prt_impl(pmcs_hw_t *, pmcs_prt_level_t, const char *, ...)
+ __KPRINTFLIKE(3);
+
+boolean_t pmcs_assign_device(pmcs_hw_t *, pmcs_xscsi_t *);
+void pmcs_remove_device(pmcs_hw_t *, pmcs_phy_t *);
+void pmcs_handle_dead_phys(pmcs_hw_t *);
+
+int pmcs_acquire_scratch(pmcs_hw_t *, boolean_t);
+void pmcs_release_scratch(pmcs_hw_t *);
+
+/* get a work structure */
+pmcwork_t *pmcs_gwork(pmcs_hw_t *, uint32_t, pmcs_phy_t *);
+
+/* put a work structure */
+void pmcs_pwork(pmcs_hw_t *, struct pmcwork *);
+
+/* given a tag, find a work structure */
+pmcwork_t *pmcs_tag2wp(pmcs_hw_t *, uint32_t);
+
+/*
+ * Abort function
+ */
+int pmcs_abort(pmcs_hw_t *, pmcs_phy_t *, uint32_t, int, int);
+
+/*
+ * SSP Task Management Function
+ */
+int pmcs_ssp_tmf(pmcs_hw_t *, pmcs_phy_t *, uint8_t, uint32_t, uint64_t,
+ uint32_t *);
+
+/*
+ * Abort NCQ function
+ */
+int pmcs_sata_abort_ncq(pmcs_hw_t *, pmcs_phy_t *);
+
+/*
+ * Interrupt Functions
+ */
+void pmcs_general_intr(pmcs_hw_t *);
+void pmcs_iodone_intr(pmcs_hw_t *);
+void pmcs_event_intr(pmcs_hw_t *);
+void pmcs_timed_out(pmcs_hw_t *, uint32_t, const char *);
+
+/*
+ * Abort handler
+ */
+int pmcs_abort_handler(pmcs_hw_t *);
+
+/*
+ * Deregister all expander connected devices
+ */
+void pmcs_deregister_devices(pmcs_hw_t *, pmcs_phy_t *);
+int pmcs_register_device(pmcs_hw_t *, pmcs_phy_t *);
+void pmcs_deregister_device(pmcs_hw_t *, pmcs_phy_t *);
+
+/*
+ * endian transform a data structure
+ */
+void pmcs_endian_transform(pmcs_hw_t *, void *, void *, const uint8_t *);
+
+/* get the connection rate string */
+const char *pmcs_get_rate(unsigned int);
+
+/* get the device type string */
+const char *pmcs_get_typename(pmcs_dtype_t pmcs_dtype);
+
+/* get the SAS Task Management function name */
+const char *pmcs_tmf2str(int);
+
+/* get the PMC status string */
+const char *pmcs_status_str(uint32_t);
+
+/*
+ * WWN to Byte Array and vice versa conversion
+ */
+uint64_t pmcs_barray2wwn(uint8_t[8]);
+void pmcs_wwn2barray(uint64_t, uint8_t[8]);
+
+/*
+ * Print f/w version
+ */
+void pmcs_report_fwversion(pmcs_hw_t *);
+
+/*
+ * Build a device name.
+ */
+void pmcs_phy_name(pmcs_hw_t *, pmcs_phy_t *, char *, size_t);
+
+/*
+ * Find a PHY by device_id
+ */
+pmcs_phy_t *pmcs_find_phy_by_devid(pmcs_hw_t *, uint32_t);
+
+/*
+ * Find a PHY by wwn
+ */
+pmcs_phy_t *pmcs_find_phy_by_wwn(pmcs_hw_t *, uint64_t);
+
+/*
+ * Find a PHY by sas_address
+ */
+pmcs_phy_t *pmcs_find_phy_by_sas_address(pmcs_hw_t *, pmcs_iport_t *,
+ pmcs_phy_t *, char *);
+
+/*
+ * Print out a FIS
+ */
+void pmcs_fis_dump(pmcs_hw_t *, fis_t);
+
+/*
+ * Print an IOMB
+ */
+void pmcs_print_entry(pmcs_hw_t *, int, char *, void *);
+
+void pmcs_spinup_release(pmcs_hw_t *, pmcs_phy_t *phyp);
+
+/*
+ * Handler for events - can be called from interrupt level or from worker thread
+ */
+void pmcs_ack_events(pmcs_hw_t *);
+
+/*
+ * This function does some initial setup and hardware validation
+ */
+int pmcs_setup(pmcs_hw_t *);
+
+/*
+ * These functions start and stop the MPI (message passing interface)
+ */
+int pmcs_start_mpi(pmcs_hw_t *);
+int pmcs_stop_mpi(pmcs_hw_t *);
+
+/*
+ * This function checks firmware revisions against required revisions
+ * and attempts to flash new firmware (if possible).
+ */
+int pmcs_firmware_update(pmcs_hw_t *);
+
+/*
+ * This function runs ECHO commands to test both interrupts and queues
+ */
+int pmcs_echo_test(pmcs_hw_t *);
+
+/*
+ * These functions start, reset, and stop the physical chip PHYs
+ */
+int pmcs_start_phy(pmcs_hw_t *, int, int, int);
+int pmcs_start_phys(pmcs_hw_t *);
+void pmcs_stop_phy(pmcs_hw_t *, int);
+void pmcs_stop_phys(pmcs_hw_t *);
+
+/*
+ * These functions setup/teardown iport tgtmap
+ */
+int pmcs_iport_tgtmap_create(pmcs_iport_t *);
+int pmcs_iport_tgtmap_destroy(pmcs_iport_t *);
+
+/*
+ * Utility and wrapper functions for SAS_DIAG_EXECUTE
+ */
+int pmcs_sas_diag_execute(pmcs_hw_t *, uint32_t, uint32_t, uint8_t);
+int pmcs_get_diag_report(pmcs_hw_t *, uint32_t, uint8_t);
+int pmcs_clear_diag_counters(pmcs_hw_t *, uint8_t);
+
+/*
+ * Get current firmware timestamp
+ */
+int pmcs_get_time_stamp(pmcs_hw_t *, uint64_t *);
+
+/*
+ * Register Dump (including "internal" registers)
+ */
+void pmcs_register_dump(pmcs_hw_t *);
+void pmcs_iqp_trace(pmcs_hw_t *, uint32_t);
+void pmcs_register_dump_int(pmcs_hw_t *);
+int pmcs_dump_binary(pmcs_hw_t *, uint32_t *, uint32_t,
+ uint32_t, caddr_t, uint32_t);
+int pmcs_dump_feregs(pmcs_hw_t *, uint32_t *, uint8_t,
+ caddr_t, uint32_t);
+
+/*
+ * This function perform a soft reset.
+ * Hard reset is platform specific.
+ */
+int pmcs_soft_reset(pmcs_hw_t *, boolean_t);
+
+/*
+ * Some more reset functions
+ */
+int pmcs_reset_dev(pmcs_hw_t *, pmcs_phy_t *, uint64_t);
+int pmcs_reset_phy(pmcs_hw_t *, pmcs_phy_t *, uint8_t);
+
+/*
+ * These functions do topology configuration changes
+ */
+void pmcs_discover(pmcs_hw_t *);
+void pmcs_set_changed(pmcs_hw_t *, pmcs_phy_t *, boolean_t, int);
+void pmcs_kill_changed(pmcs_hw_t *, pmcs_phy_t *, int);
+void pmcs_clear_phy(pmcs_hw_t *, pmcs_phy_t *);
+int pmcs_kill_device(pmcs_hw_t *, pmcs_phy_t *);
+
+/*
+ * Firmware flash function
+ */
+int pmcs_fw_flash(pmcs_hw_t *, pmcs_fw_hdr_t *, uint32_t);
+
+/*
+ * Set a new value for the interrupt coalescing timer. If it's being set
+ * to zero (disabling), then re-enable auto clear if necessary. If it's
+ * being changed from zero, turn off auto clear if it was on.
+ */
+typedef enum {
+ DECREASE_TIMER = 0,
+ INCREASE_TIMER
+} pmcs_coal_timer_adj_t;
+
+void pmcs_check_intr_coal(void *arg);
+void pmcs_set_intr_coal_timer(pmcs_hw_t *pwp, pmcs_coal_timer_adj_t adj);
+
+/*
+ * Misc supporting routines
+ */
+void pmcs_check_iomb_status(pmcs_hw_t *pwp, uint32_t *iomb);
+void pmcs_clear_xp(pmcs_hw_t *, pmcs_xscsi_t *);
+
+int pmcs_run_sata_cmd(pmcs_hw_t *, pmcs_phy_t *, fis_t, uint32_t,
+ uint32_t, uint32_t);
+int pmcs_sata_identify(pmcs_hw_t *, pmcs_phy_t *);
+void pmcs_sata_work(pmcs_hw_t *);
+boolean_t pmcs_dma_setup(pmcs_hw_t *pwp, ddi_dma_attr_t *dma_attr,
+ ddi_acc_handle_t *acch, ddi_dma_handle_t *dmah, size_t length,
+ caddr_t *kvp, uint64_t *dma_addr);
+void pmcs_fm_ereport(pmcs_hw_t *pwp, char *detail);
+int pmcs_check_dma_handle(ddi_dma_handle_t handle);
+int pmcs_check_acc_handle(ddi_acc_handle_t handle);
+int pmcs_check_acc_dma_handle(pmcs_hw_t *pwp);
+int pmcs_get_nvmd(pmcs_hw_t *pwp, pmcs_nvmd_type_t nvmd_type, uint8_t nvmd,
+ uint32_t offset, char *buf, uint32_t size_left);
+boolean_t pmcs_set_nvmd(pmcs_hw_t *pwp, pmcs_nvmd_type_t nvmd_type,
+ uint8_t *buf, size_t len);
+void pmcs_complete_work_impl(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *iomb,
+ size_t amt);
+void pmcs_flush_target_queues(pmcs_hw_t *, pmcs_xscsi_t *, uint8_t);
+boolean_t pmcs_iport_has_targets(pmcs_hw_t *, pmcs_iport_t *);
+void pmcs_free_dma_chunklist(pmcs_hw_t *);
+int pmcs_get_dev_state(pmcs_hw_t *, pmcs_xscsi_t *, uint8_t *);
+int pmcs_set_dev_state(pmcs_hw_t *, pmcs_xscsi_t *, uint8_t);
+void pmcs_dev_state_recovery(pmcs_hw_t *, pmcs_phy_t *);
+int pmcs_send_err_recovery_cmd(pmcs_hw_t *, uint8_t, pmcs_xscsi_t *);
+void pmcs_start_ssp_event_recovery(pmcs_hw_t *pwp, pmcwork_t *pwrk,
+ uint32_t *iomb, size_t amt);
+void pmcs_ssp_event_recovery(pmcs_hw_t *);
+
+pmcs_iport_t *pmcs_get_iport_by_phy(pmcs_hw_t *pwp, pmcs_phy_t *pptr);
+void pmcs_rele_iport(pmcs_iport_t *iport);
+int pmcs_iport_configure_phys(pmcs_iport_t *iport);
+
+void pmcs_lock_phy(pmcs_phy_t *);
+void pmcs_unlock_phy(pmcs_phy_t *);
+
+void pmcs_destroy_target(pmcs_xscsi_t *);
+void pmcs_phymap_activate(void *, char *, void **);
+void pmcs_phymap_deactivate(void *, char *, void *);
+void pmcs_add_phy_to_iport(pmcs_iport_t *, pmcs_phy_t *);
+void pmcs_remove_phy_from_iport(pmcs_iport_t *, pmcs_phy_t *);
+void pmcs_free_all_phys(pmcs_hw_t *, pmcs_phy_t *);
+void pmcs_free_phys(pmcs_hw_t *, pmcs_phy_t *);
+
+int pmcs_phy_constructor(void *, void *, int);
+void pmcs_phy_destructor(void *, void *);
+
+void pmcs_inc_phy_ref_count(pmcs_phy_t *);
+void pmcs_dec_phy_ref_count(pmcs_phy_t *);
+
+/* Worker thread */
+void pmcs_worker(void *);
+
+pmcs_phy_t *pmcs_get_root_phy(pmcs_phy_t *);
+pmcs_xscsi_t *pmcs_get_target(pmcs_iport_t *, char *);
+
+void pmcs_fatal_handler(pmcs_hw_t *);
+
+/*
+ * Schedule device state recovery for this device immediately
+ */
+void pmcs_start_dev_state_recovery(pmcs_xscsi_t *, pmcs_phy_t *);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _PMCS_PROTO_H */
diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_reg.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_reg.h
new file mode 100644
index 0000000000..dd85718f7e
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_reg.h
@@ -0,0 +1,378 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * PMC 8x6G register definitions
+ */
+#ifndef _PMCS_REG_H
+#define _PMCS_REG_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * PCI Constants
+ */
+#define PMCS_VENDOR_ID 0x11F8
+#define PMCS_DEVICE_ID 0x8001
+
+#define PMCS_PM8001_REV_A 0
+#define PMCS_PM8001_REV_B 1
+#define PMCS_PM8001_REV_C 2
+
+#define PMCS_REGSET_0 1
+#define PMCS_REGSET_1 2
+#define PMCS_REGSET_2 3
+#define PMCS_REGSET_3 4
+
+
+/*
+ * PCIe BARs - 4 64KB memory regions
+ *
+ * BAR0-1 64KiB
+ * BAR2-3 64KiB
+ * BAR4 64KiB
+ * BAR5 64KiB
+ */
+
+/*
+ * The PMC 8x6G registers are defined by BARs in PCIe space.
+ *
+ * Four memory region BARS are used.
+ *
+ * The first is for the Messaging Unit.
+ *
+ * The second 64KiB region contains the PCS/PMA registers and some of the
+ * Top-Level registers.
+ *
+ * The third 64KiB region is a 64KiB window on the rest of the chip registers
+ * which can be shifted by writing a register in the second region.
+ *
+ * The fourth 64KiB region is for the message passing area.
+ */
+
+/*
+ * Messaging Unit Register Offsets
+ */
+#define PMCS_MSGU_IBDB 0x04 /* Inbound Doorbell */
+#define PMCS_MSGU_IBDB_CLEAR 0x20 /* InBound Doorbell Clear */
+#define PMCS_MSGU_OBDB 0x3c /* OutBound Doorbell */
+#define PMCS_MSGU_OBDB_CLEAR 0x40 /* OutBound Doorbell Clear */
+#define PMCS_MSGU_SCRATCH0 0x44 /* Scratchpad 0 */
+#define PMCS_MSGU_SCRATCH1 0x48 /* Scratchpad 1 */
+#define PMCS_MSGU_SCRATCH2 0x4C /* Scratchpad 2 */
+#define PMCS_MSGU_SCRATCH3 0x50 /* Scratchpad 3 */
+#define PMCS_MSGU_HOST_SCRATCH0 0x54 /* Host Scratchpad 0 */
+#define PMCS_MSGU_HOST_SCRATCH1 0x58 /* Host Scratchpad 1 */
+#define PMCS_MSGU_HOST_SCRATCH2 0x5C /* Host Scratchpad 2 */
+#define PMCS_MSGU_HOST_SCRATCH3 0x60 /* Host Scratchpad 3 */
+#define PMCS_MSGU_HOST_SCRATCH4 0x64 /* Host Scratchpad 4 */
+#define PMCS_MSGU_HOST_SCRATCH5 0x68 /* Host Scratchpad 5 */
+#define PMCS_MSGU_HOST_SCRATCH6 0x6C /* Host Scratchpad 6 */
+#define PMCS_MSGU_HOST_SCRATCH7 0x70 /* Host Scratchpad 7 */
+#define PMCS_MSGU_OBDB_MASK 0x74 /* Outbound Doorbell Mask */
+
+/*
+ * Inbound Doorbell and Doorbell Clear Definitions
+ * NB: The Doorbell Clear register is only used on RevA/8000 parts.
+ */
+#define PMCS_MSGU_IBDB_MPIIU 0x08 /* Initiate Unfreeze */
+#define PMCS_MSGU_IBDB_MPIIF 0x04 /* Initiate Freeze */
+#define PMCS_MSGU_IBDB_MPICTU 0x02 /* Initiate MPI Termination */
+#define PMCS_MSGU_IBDB_MPIINI 0x01 /* Initiate MPI */
+
+/*
+ * Outbound Doorbell and Doorbell Clear Register
+ *
+ * The Doorbell Clear register is only used on RevA/8000 parts.
+ *
+ * Each bit of the ODR is mapped 1-to-1 to a MSI or MSI-X vector
+ * table entry. There are 32 MSI and 16 MSI-X entries. The top
+ * 16 bits are mapped to the low 16 bits for MSI-X. For legacy
+ * INT-X, any bit will generate a host interrupt.
+ *
+ * Each bit in the Outbound Doorbell Clear is used to clear the
+ * corresponding bit in the ODR. For INT-X it also then deasserts
+ * any interrupt condition.
+ */
+#define PMCS_MSI_INTS 32
+#define PMCS_MSIX_INTS 16
+
+/*
+ * Scratchpad 0 Definitions
+ *
+ * When the AAP is ready state (see Scratchpad 1), bits 31:26 is the offset
+ * within PCIe space for another BAR that, when mapped, will point to a region
+ * that conains the MPI Configuration table (the offset of which is in bits
+ * 25:0 of this register)
+ *
+ * When the AAP is in error state, this register contains additional error
+ * information.
+ */
+#define PMCS_MSGU_MPI_BAR_SHIFT 26
+#define PMCS_MSGU_MPI_OFFSET_MASK ((1 << PMCS_MSGU_MPI_BAR_SHIFT) - 1)
+
+/*
+ * Scratchpad 1 Definitions
+ *
+ * The bottom two bits are the AAP state of the 8x6G.
+ *
+ * When the AAP is in error state, bits 31:10 contain the error indicator.
+ *
+ */
+#define PMCS_MSGU_AAP_STATE_MASK 0x03
+#define PMCS_MSGU_AAP_STATE_POR 0
+#define PMCS_MSGU_AAP_STATE_SOFT_RESET 1
+#define PMCS_MSGU_AAP_STATE_ERROR 2
+#define PMCS_MSGU_AAP_STATE_READY 3
+#define PMCS_MSGU_AAP_SFR_PROGRESS 0x04
+#define PMCS_MSGU_AAP_ERROR_MASK 0xfffffc00
+
+/*
+ * Scratchpad 2 Definitions
+ *
+ * Bits 31:10 contain error information if the IOP is in error state.
+ */
+#define PMCS_MSGU_IOP_STATE_MASK 0x03
+#define PMCS_MSGU_IOP_STATE_POR 0
+#define PMCS_MSGU_IOP_STATE_SOFT_RESET 1
+#define PMCS_MSGU_IOP_STATE_ERROR 2
+#define PMCS_MSGU_IOP_STATE_READY 3
+
+#define PMCS_MSGU_HOST_SOFT_RESET_READY 0x04
+#define PMCS_MSGU_CPU_SOFT_RESET_READY 0x08
+
+/*
+ * Scratchpad 3 Definitions
+ *
+ * Contains additional error information if the IOP is in error state
+ * (see Scratchpad 2)
+ */
+
+/*
+ * Host Scratchpad 0
+ * Soft Reset Signature
+ */
+#define HST_SFT_RESET_SIG 0x252ACBCD
+
+/*
+ * Host Scratchpad 1
+ *
+ * This is a bit mask for freeze or unfreeze operations for IQs 0..31
+ */
+
+/*
+ * Host Scratchpad 2
+ *
+ * This is a bit mask for freeze or unfreeze operations for IQs 32..63
+ */
+
+/*
+ * Outbound Doorbell Mask Register
+ *
+ * Each bit set here masks bits and interrupt assertion for the corresponding
+ * bit (and vector) in the ODR.
+ */
+
+/*
+ * GSM Registers
+ */
+#define GSM_BASE_MASK 0x00ffff
+#define NMI_EN_VPE0_IOP 0x60418
+#define NMI_EN_VPE0_AAP1 0x70418
+#define RB6_ACCESS 0x6A80C0
+#define GSM_CFG_AND_RESET 0x700000
+#define RAM_ECC_DOUBLE_ERROR_INDICATOR 0x700018
+#define READ_ADR_PARITY_CHK_EN 0x700038
+#define WRITE_ADR_PARITY_CHK_EN 0x700040
+#define WRITE_DATA_PARITY_CHK_EN 0x700048
+#define READ_ADR_PARITY_ERROR_INDICATOR 0x700058
+#define WRITE_ADR_PARITY_ERROR_INDICATOR 0x700060
+#define WRITE_DATA_PARITY_ERROR_INDICATOR 0x700068
+
+/*
+ * GSM Share Memory, IO Status Table and Ring Buffer
+ */
+#define GSM_SM_BLKSZ 0x10000
+#define GSM_SM_BASE 0x400000
+#define IO_STATUS_TABLE_BASE 0x640000
+#define RING_BUF_STORAGE_0 0x680000
+#define RING_BUF_STORAGE_1 0x690000
+#define RING_BUF_PTR_ACC_BASE 0x6A0000
+
+#define IO_STATUS_TABLE_BLKNM 0x4
+#define GSM_SM_BLKNM 0x10
+#define RING_BUF_PTR_OFF 0x1000
+#define RING_BUF_PTR_SIZE 0xFF8
+#define RING_BUF_ACC_OFF 0x8000
+#define RING_BUF_ACC_SIZE 0xFF8
+
+/*
+ * GSM Configuration and Reset Bits
+ */
+#define MST_XCBI_SW_RSTB (1 << 14)
+#define COM_SLV_SW_RSTB (1 << 13)
+#define QSSP_SW_RSTB (1 << 12)
+#define RAAE_SW_RSTB (1 << 11)
+#define RB_1_SW_RSTB (1 << 9)
+#define SM_SW_RSTB (1 << 8)
+
+#define COHERENCY_GAP_SHIFT 4
+#define COHERENCY_GAP_MASK 0xf0
+#define COHERENCY_GAP_DEFAULT (8 << COHERENCY_GAP_SHIFT)
+
+#define COHERENCY_MODE (1 << 3)
+#define RB_WSTRB_ERRCHK_EN (1 << 2)
+#define RAAE_PORT2_EN (1 << 1)
+#define GSM_WCI_MODE (1 << 0)
+#define PMCS_SOFT_RESET_BITS \
+ (COM_SLV_SW_RSTB|QSSP_SW_RSTB|RAAE_SW_RSTB|RB_1_SW_RSTB|SM_SW_RSTB)
+
+#define RB6_NMI_SIGNATURE 0x00001234
+
+/*
+ * PMCS PCI Configuration Registers
+ */
+#define PMCS_PCI_PMC 0x40
+#define PMCS_PCI_PMCSR 0x44
+#define PMCS_PCI_MSI 0x50
+#define PMCS_PCI_MAL 0x54
+#define PMCS_PCI_MAU 0x58
+#define PMCS_PCI_MD 0x5C
+#define PMCS_PCI_PCIE 0x70
+#define PMCS_PCI_DEV_CAP 0x74
+#define PMCS_PCI_DEV_CTRL 0x78
+#define PMCS_PCI_LINK_CAP 0x7C
+#define PMCS_PCI_LINK_CTRL 0x80
+#define PMCS_PCI_MSIX_CAP 0xAC
+#define PMCS_PCI_TBL_OFFSET 0xB0
+#define PMCS_PCI_PBA_OFFSET 0xB4
+#define PMCS_PCI_PCIE_CAP_HD 0x100
+#define PMCS_PCI_UE_STAT 0x104
+#define PMCS_PCI_UE_MASK 0x108
+#define PMCS_PCI_UE_SEV 0x10C
+#define PMCS_PCI_CE_STAT 0x110
+#define PMCS_PCI_CE_MASK 0x114
+#define PMCS_PCI_ADV_ERR_CTRL 0x118
+#define PMCS_PCI_HD_LOG_DW 0x11C
+
+/*
+ * Top Level Registers
+ */
+/* these registers are in MEMBASE-III */
+#define PMCS_SPC_RESET 0x0
+#define PMCS_SPC_BOOT_STRAP 0x8
+#define PMCS_SPC_DEVICE_ID 0x20
+#define PMCS_DEVICE_REVISION 0x24
+/* these registers are in MEMBASE-II */
+#define PMCS_EVENT_INT_ENABLE 0x3040
+#define PMCS_EVENT_INT_STAT 0x3044
+#define PMCS_ERROR_INT_ENABLE 0x3048
+#define PMCS_ERROR_INT_STAT 0x304C
+#define PMCS_AXI_TRANS 0x3258
+#define PMCS_OBDB_AUTO_CLR 0x335C
+#define PMCS_INT_COALESCING_TIMER 0x33C0
+#define PMCS_INT_COALESCING_CONTROL 0x33C4
+
+
+/*
+ * Chip Reset Register Bits (PMCS_SPC_RESET)
+ *
+ * NB: all bits are inverted. That is, the normal state is '1'.
+ * When '0' is set, the action is taken.
+ */
+#define PMCS_SPC_HARD_RESET 0x00
+#define PMCS_SPC_HARD_RESET_CLR 0xffffffff
+
+
+#define SW_DEVICE_RSTB (1 << 31)
+#define PCIE_PC_SXCBI_ARESETN (1 << 26)
+#define PMIC_CORE_RSTB (1 << 25)
+#define PMIC_SXCBI_ARESETN (1 << 24)
+#define LMS_SXCBI_ARESETN (1 << 23)
+#define PCS_SXCBI_ARESETN (1 << 22)
+#define PCIE_SFT_RSTB (1 << 21)
+#define PCIE_PWR_RSTB (1 << 20)
+#define PCIE_AL_SXCBI_ARESETN (1 << 19)
+#define BDMA_SXCBI_ARESETN (1 << 18)
+#define BDMA_CORE_RSTB (1 << 17)
+#define DDR2_RSTB (1 << 16)
+#define GSM_RSTB (1 << 8)
+#define PCS_RSTB (1 << 7)
+#define PCS_LM_RSTB (1 << 6)
+#define PCS_AAP2_SS_RSTB (1 << 5)
+#define PCS_AAP1_SS_RSTB (1 << 4)
+#define PCS_IOP_SS_RSTB (1 << 3)
+#define PCS_SPBC_RSTB (1 << 2)
+#define RAAE_RSTB (1 << 1)
+#define OSSP_RSTB (1 << 0)
+
+
+/*
+ * Timer Enables Register
+ */
+#define PMCS_TENABLE_WINDOW_OFFSET 0x30000
+#define PMCS_TENABLE_BASE 0x0209C
+#define PMCS_TENABLE_MULTIPLIER 0x04000
+
+/*
+ * Special register (MEMBASE-III) for Step 5.5 in soft reset sequence to set
+ * GPIO into tri-state mode (temporary workaround for 1.07.xx beta firmware)
+ */
+#define PMCS_GPIO_TRISTATE_MODE_ADDR 0x9010C
+#define PMCS_GPIO_TSMODE_BIT0 (1 << 0)
+#define PMCS_GPIO_TSMODE_BIT1 (1 << 1)
+
+
+/*
+ * Register Access Inline Functions
+ */
+uint32_t pmcs_rd_msgunit(pmcs_hw_t *, uint32_t);
+uint32_t pmcs_rd_gsm_reg(pmcs_hw_t *, uint32_t);
+uint32_t pmcs_rd_topunit(pmcs_hw_t *, uint32_t);
+uint32_t pmcs_rd_mpi_tbl(pmcs_hw_t *, uint32_t);
+uint32_t pmcs_rd_gst_tbl(pmcs_hw_t *, uint32_t);
+uint32_t pmcs_rd_iqc_tbl(pmcs_hw_t *, uint32_t);
+uint32_t pmcs_rd_oqc_tbl(pmcs_hw_t *, uint32_t);
+uint32_t pmcs_rd_iqci(pmcs_hw_t *, uint32_t);
+uint32_t pmcs_rd_iqpi(pmcs_hw_t *, uint32_t);
+uint32_t pmcs_rd_oqci(pmcs_hw_t *, uint32_t);
+uint32_t pmcs_rd_oqpi(pmcs_hw_t *, uint32_t);
+
+void pmcs_wr_msgunit(pmcs_hw_t *, uint32_t, uint32_t);
+void pmcs_wr_gsm_reg(pmcs_hw_t *, uint32_t, uint32_t);
+void pmcs_wr_topunit(pmcs_hw_t *, uint32_t, uint32_t);
+void pmcs_wr_mpi_tbl(pmcs_hw_t *, uint32_t, uint32_t);
+void pmcs_wr_gst_tbl(pmcs_hw_t *, uint32_t, uint32_t);
+void pmcs_wr_iqc_tbl(pmcs_hw_t *, uint32_t, uint32_t);
+void pmcs_wr_oqc_tbl(pmcs_hw_t *, uint32_t, uint32_t);
+void pmcs_wr_iqci(pmcs_hw_t *, uint32_t, uint32_t);
+void pmcs_wr_iqpi(pmcs_hw_t *, uint32_t, uint32_t);
+void pmcs_wr_oqci(pmcs_hw_t *, uint32_t, uint32_t);
+void pmcs_wr_oqpi(pmcs_hw_t *, uint32_t, uint32_t);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _PMCS_REG_H */
diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_scsa.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_scsa.h
new file mode 100644
index 0000000000..19db949654
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_scsa.h
@@ -0,0 +1,92 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * SCSI (SCSA) midlayer interface for PMC drier.
+ */
+#ifndef _PMCS_SCSA_H
+#define _PMCS_SCSA_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/scsi/scsi_types.h>
+
+#define ADDR2TRAN(ap) ((ap)->a_hba_tran)
+#define ADDR2PMC(ap) (ITRAN2PMC(ADDR2TRAN(ap)))
+
+#define CMD2TRAN(cmd) (CMD2PKT(cmd)->pkt_address.a_hba_tran)
+#define CMD2PMC(cmd) (ITRAN2PMC(CMD2TRAN(cmd)))
+
+#define PKT2ADDR(pkt) (&((pkt)->pkt_address))
+#define PKT2CMD(pkt) ((pmcs_cmd_t *)(pkt->pkt_ha_private))
+#define CMD2PKT(sp) (sp->cmd_pkt)
+#define PMCS_STATUS_LEN 264
+
+#define TRAN2PMC(tran) ((pmcs_hw_t *)(tran)->tran_hba_private)
+#define ITRAN2PMC(tran) \
+ (((pmcs_iport_t *)(tran)->tran_hba_private)->pwp)
+#define ITRAN2IPORT(tran) \
+ ((pmcs_iport_t *)(tran)->tran_hba_private)
+
+/*
+ * Wrapper around scsi_pkt.
+ */
+struct pmcs_cmd {
+ struct scsi_pkt *cmd_pkt; /* actual SCSI Packet */
+ STAILQ_ENTRY(pmcs_cmd) cmd_next; /* linked list */
+ pmcs_dmachunk_t *cmd_clist; /* list of dma chunks */
+ pmcs_xscsi_t *cmd_target; /* Pointer to target */
+ pmcs_lun_t *cmd_lun; /* Pointer to LU */
+ uint32_t cmd_tag; /* PMC htag */
+ uint8_t cmd_satltag; /* SATL tag */
+};
+
+#define SCSA_CDBLEN(sp) sp->cmd_pkt->pkt_cdblen
+#define SCSA_STSLEN(sp) sp->cmd_pkt->pkt_scblen
+#define SCSA_TGTLEN(sp) sp->cmd_pkt->pkt_tgtlen
+
+#define PMCS_WQ_RUN_SUCCESS 0
+#define PMCS_WQ_RUN_FAIL_RES 1 /* Failed to alloc rsrcs (e.g. DMA chunks) */
+#define PMCS_WQ_RUN_FAIL_OTHER 2 /* Any other failure */
+
+int pmcs_scsa_init(pmcs_hw_t *, const ddi_dma_attr_t *);
+
+void pmcs_latch_status(pmcs_hw_t *, pmcs_cmd_t *, uint8_t, uint8_t *,
+ size_t, char *);
+size_t pmcs_set_resid(struct scsi_pkt *, size_t, uint32_t);
+boolean_t pmcs_scsa_wq_run_one(pmcs_hw_t *, pmcs_xscsi_t *);
+void pmcs_scsa_wq_run(pmcs_hw_t *);
+void pmcs_scsa_cq_run(void *);
+
+int pmcs_config_one(pmcs_hw_t *, uint64_t, int, long, dev_info_t **);
+
+dev_info_t *pmcs_find_child_smp(pmcs_hw_t *, char *);
+int pmcs_config_one_smp(pmcs_hw_t *, uint64_t, dev_info_t **);
+
+int pmcs_run_sata_special(pmcs_hw_t *, pmcs_xscsi_t *);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _PMCS_SCSA_H */
diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_sgl.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_sgl.h
new file mode 100644
index 0000000000..e604ed751c
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_sgl.h
@@ -0,0 +1,86 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+#ifndef _PMCS_SGL_H
+#define _PMCS_SGL_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This is the strict physical representation of an external
+ * S/G list entry that the PMCS hardware uses. We manage them
+ * in chunks.
+ */
+typedef struct {
+ uint32_t sglal; /* Low 32 bit DMA address */
+ uint32_t sglah; /* High 32 bit DMA address */
+ uint32_t sglen; /* Length */
+ uint32_t flags;
+} pmcs_dmasgl_t;
+
+/*
+ * If this is bit is set in flags, then the address
+ * described by this structure is an array of SGLs,
+ * the last of which may contain *another* flag
+ * to continue the list.
+ */
+#define PMCS_DMASGL_EXTENSION (1U << 31)
+
+#define PMCS_SGL_CHUNKSZ (PMCS_SGL_NCHUNKS * (sizeof (pmcs_dmasgl_t)))
+
+/*
+ * This is how we keep track of chunks- we have a linked list of
+ * chunk pointers that are either on the free list or are tagged
+ * off of a SCSA command. We used to maintain offsets indices
+ * within the sglen area of the lest element of a chunk, but this
+ * is marked reserved and may not be reliably used future firmware
+ * revisions.
+ */
+typedef struct pmcs_dmachunk pmcs_dmachunk_t;
+struct pmcs_dmachunk {
+ pmcs_dmachunk_t *nxt;
+ pmcs_dmasgl_t *chunks;
+ unsigned long addr;
+ ddi_acc_handle_t acc_handle;
+ ddi_dma_handle_t dma_handle;
+};
+
+/*
+ * DMA related functions
+ */
+int pmcs_dma_load(pmcs_hw_t *, pmcs_cmd_t *, uint32_t *);
+void pmcs_dma_unload(pmcs_hw_t *, pmcs_cmd_t *);
+
+/*
+ * After allocating some DMA chunks, insert them
+ * into the free list and set them up for use.
+ */
+void pmcs_idma_chunks(pmcs_hw_t *, pmcs_dmachunk_t *,
+ pmcs_chunk_t *, unsigned long);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _PMCS_SGL_H */
diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_smhba.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_smhba.h
new file mode 100644
index 0000000000..f952a34060
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_smhba.h
@@ -0,0 +1,72 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * SM-HBA interfaces/definitions for PMC-S driver.
+ */
+#ifndef _PMCS_SMHBA_H
+#define _PMCS_SMHBA_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Leverage definition of data_type_t in nvpair.h */
+#include <sys/nvpair.h>
+
+#define PMCS_NUM_PHYS "num-phys"
+#define PMCS_NUM_PHYS_HBA "num-phys-hba"
+#define PMCS_SMHBA_SUPPORTED "sm-hba-supported"
+#define PMCS_DRV_VERSION "driver-version"
+#define PMCS_HWARE_VERSION "hardware-version"
+#define PMCS_FWARE_VERSION "firmware-version"
+#define PMCS_SUPPORTED_PROTOCOL "supported-protocol"
+
+#define PMCS_MANUFACTURER "Manufacturer"
+#define PMCS_SERIAL_NUMBER "SerialNumber"
+#define PMCS_MODEL_NAME "ModelName"
+
+/*
+ * Interfaces to add properties required for SM-HBA
+ *
+ * _add_xxx_prop() interfaces add only 1 prop that is specified in the args.
+ * _set_xxx_props() interfaces add more than 1 prop for a set of phys/devices.
+ */
+void pmcs_smhba_add_hba_prop(pmcs_hw_t *, data_type_t, char *, void *);
+void pmcs_smhba_add_iport_prop(pmcs_iport_t *, data_type_t, char *, void *);
+void pmcs_smhba_add_tgt_prop(pmcs_xscsi_t *, data_type_t, char *, void *);
+
+void pmcs_smhba_set_scsi_device_props(pmcs_hw_t *, pmcs_phy_t *,
+ struct scsi_device *);
+void pmcs_smhba_set_phy_props(pmcs_iport_t *);
+
+/*
+ * Misc routines supporting SM-HBA
+ */
+void pmcs_smhba_log_sysevent(pmcs_hw_t *, char *, char *, pmcs_phy_t *);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _PMCS_SMHBA_H */
diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/smp_defs.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/smp_defs.h
new file mode 100644
index 0000000000..508d316bf2
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/smp_defs.h
@@ -0,0 +1,1100 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * This header file will only be used for pmcs driver temporarily.
+ * Will be deleted after smp_frames.h is updated.
+ */
+
+#ifndef _SYS_SCSI_GENERIC_SMP_FRAMES_H
+#define _SYS_SCSI_GENERIC_SMP_FRAMES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/sysmacros.h>
+
+/*
+ * The definitions of smp frame types and functions conforming to SAS-1.1 and
+ * SAS-2. Consumers are expected to determine protocol support by examining
+ * the response to the REPORT GENERAL function.
+ */
+
+/* Redefinition conflict with smp_frames.h. */
+
+/*
+ * typedef enum smp_frame_type {
+ * SMP_FRAME_TYPE_REQUEST = 0x40,
+ * SMP_FRAME_TYPE_RESPONSE = 0x41
+ * } smp_frame_type_t;
+ */
+
+typedef enum smp_function {
+ SMP_FUNC_REPORT_GENERAL = 0x00,
+ SMP_FUNC_REPORT_MANUFACTURER_INFO = 0x01,
+ SMP_FUNC_READ_GPIO_REGISTER = 0x02,
+ SMP_FUNC_REPORT_SELF_CONFIG_STATUS = 0x03,
+ SMP_FUNC_REPORT_ZONE_PERM_TABLE = 0x04,
+ SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD = 0x05,
+ SMP_FUNC_REPORT_BROADCAST = 0x06,
+ SMP_FUNC_DISCOVER = 0x10,
+ SMP_FUNC_REPORT_PHY_ERROR_LOG = 0x11,
+ SMP_FUNC_REPORT_PHY_SATA = 0x12,
+ SMP_FUNC_REPORT_ROUTE_INFO = 0x13,
+ SMP_FUNC_REPORT_PHY_EVENT = 0x14,
+ SMP_FUNC_DISCOVER_LIST = 0x20,
+ SMP_FUNC_REPORT_PHY_EVENT_LIST = 0x21,
+ SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST = 0x22,
+ SMP_FUNC_CONFIG_GENERAL = 0x80,
+ SMP_FUNC_ENABLE_DISABLE_ZONING = 0x81,
+ SMP_FUNC_WRITE_GPIO_REGISTER = 0x82,
+ SMP_FUNC_ZONED_BROADCAST = 0x85,
+ SMP_FUNC_ZONE_LOCK = 0x86,
+ SMP_FUNC_ZONE_ACTIVATE = 0x87,
+ SMP_FUNC_ZONE_UNLOCK = 0x88,
+ SMP_FUNC_CONFIG_ZONE_MANAGER_PASSWORD = 0x89,
+ SMP_FUNC_CONFIG_ZONE_PHY_INFO = 0x8A,
+ SMP_FUNC_CONFIG_ZONE_PERM_TABLE = 0x8B,
+ SMP_FUNC_CONFIG_ROUTE_INFO = 0x90,
+ SMP_FUNC_PHY_CONTROL = 0x91,
+ SMP_FUNC_PHY_TEST_FUNCTION = 0x92,
+ SMP_FUNC_CONFIG_PHY_EVENT = 0x93
+} smp_function_t;
+
+typedef enum smp_result {
+ SMP_RES_FUNCTION_ACCEPTED = 0x00,
+ SMP_RES_UNKNOWN_FUNCTION = 0x01,
+ SMP_RES_FUNCTION_FAILED = 0x02,
+ SMP_RES_INVALID_REQUEST_FRAME_LENGTH = 0x03,
+ SMP_RES_INVALID_EXPANDER_CHANGE_COUNT = 0x04,
+ SMP_RES_BUSY = 0x05,
+ SMP_RES_INCOMPLETE_DESCRIPTOR_LIST = 0x06,
+ SMP_RES_PHY_DOES_NOT_EXIST = 0x10,
+ SMP_RES_INDEX_DOES_NOT_EXIST = 0x11,
+ SMP_RES_PHY_DOES_NOT_SUPPORT_SATA = 0x12,
+ SMP_RES_UNKNOWN_PHY_OPERATION = 0x13,
+ SMP_RES_UNKNOWN_PHY_TEST_FUNCTION = 0x14,
+ SMP_RES_PHY_TEST_IN_PROGRESS = 0x15,
+ SMP_RES_PHY_VACANT = 0x16,
+ SMP_RES_UNKNOWN_PHY_EVENT_SOURCE = 0x17,
+ SMP_RES_UNKNOWN_DESCRIPTOR_TYPE = 0x18,
+ SMP_RES_UNKNOWN_PHY_FILTER = 0x19,
+ SMP_RES_AFFILIATION_VIOLATION = 0x1A,
+ SMP_RES_ZONE_VIOLATION = 0x20,
+ SMP_RES_NO_MANAGEMENT_ACCESS_RIGHTS = 0x21,
+ SMP_RES_UNKNOWN_ENABLE_DISABLE_ZONING = 0x22,
+ SMP_RES_ZONE_LOCK_VIOLATION = 0x23,
+ SMP_RES_NOT_ACTIVATED = 0x24,
+ SMP_RES_ZONE_GROUP_OUT_OF_RANGE = 0x25,
+ SMP_RES_NO_PHYSICAL_PRESENCE = 0x26,
+ SMP_RES_SAVING_NOT_SUPPORTED = 0x27,
+ SMP_RES_SOURCE_ZONE_GROUP_DNE = 0x28,
+ SMP_RES_NONE = -1
+} smp_result_t;
+
+/*
+ * SAS-2 10.4.3.2 request frame format
+ */
+typedef struct smp_request_frame {
+ uint8_t srf_frame_type;
+ uint8_t srf_function;
+ uint8_t srf_allocated_response_len; /* reserved in SAS-1 */
+ uint8_t srf_request_len;
+ uint8_t srf_data[1];
+} smp_request_frame_t;
+
+/*
+ * SAS-2 10.4.3.3 response frame format
+ */
+typedef struct smp_response_frame {
+ uint8_t srf_frame_type;
+ uint8_t srf_function;
+ uint8_t srf_result;
+ uint8_t srf_response_len; /* reserved in SAS-1 */
+ uint8_t srf_data[1];
+} smp_response_frame_t;
+
+typedef uint8_t smp_crc_t[4];
+
+#ifdef offsetof
+#define SMP_REQ_MINLEN \
+ (offsetof(smp_request_frame_t, srf_data[0]) + sizeof (smp_crc_t))
+#define SMP_RESP_MINLEN \
+ (offsetof(smp_response_frame_t, srf_data[0]) + sizeof (smp_crc_t))
+#endif /* offsetof */
+
+#pragma pack(1)
+
+/*
+ * SAS-2 10.4.3.4 REPORT GENERAL (no additional request bytes)
+ */
+typedef struct smp_report_general_resp {
+ uint16_t srgr_exp_change_count;
+ uint16_t srgr_exp_route_indexes;
+ DECL_BITFIELD2(
+ _reserved1 :7,
+ srgr_long_response :1);
+ uint8_t srgr_number_of_phys;
+ DECL_BITFIELD7(
+ srgr_externally_configurable_route_table :1,
+ srgr_configuring :1,
+ srgr_configures_others :1,
+ srgr_open_reject_retry_supported :1,
+ srgr_stp_continue_awt :1,
+ _reserved2 :2,
+ srgr_table_to_table_supported :1);
+ uint8_t _reserved3;
+ uint64_t srgr_enclosure_logical_identifier;
+ uint8_t _reserved4[8];
+ uint8_t _reserved5[2];
+ uint16_t srgr_stp_bus_inactivity_time_limit;
+ uint16_t srgr_stp_maximum_connect_time_limit;
+ uint16_t srgr_stp_smp_nexus_loss_time;
+ DECL_BITFIELD7(
+ srgr_zoning_enabled :1,
+ srgr_zoning_supported :1,
+ srgr_physical_presence_asserted :1,
+ srgr_physical_presence_supported :1,
+ srgr_zone_locked :1,
+ _reserved6 :1,
+ srgr_number_of_zone_grps :2);
+ DECL_BITFIELD6(
+ srgr_saving_zoning_enabled_supported :1,
+ srgr_saving_zone_perm_table_supported :1,
+ srgr_saving_zone_phy_info_supported :1,
+ srgr_saving_zone_mgr_password_supported :1,
+ srgr_saving :1,
+ _reserved7 :4);
+ uint16_t srgr_max_routed_sas_addrs;
+ uint64_t srgr_active_zm_sas_addr;
+ uint16_t srgr_zone_lock_inactivity_limit;
+ uint8_t _reserved8[2];
+ uint8_t _reserved9;
+ uint8_t srgr_first_encl_conn_elem_idx;
+ uint8_t srgr_number_encl_conn_elem_idxs;
+ uint8_t _reserved10;
+ DECL_BITFIELD2(
+ _reserved11 :7,
+ srgr_reduced_functionality :1);
+ uint8_t srgr_time_to_reduced_functionality;
+ uint8_t srgr_initial_time_to_reduced_functionality;
+ uint8_t srgr_max_reduced_functionality_time;
+ uint16_t srgr_last_self_conf_status_descr_idx;
+ uint16_t srgr_max_stored_self_config_status_descrs;
+ uint16_t srgr_last_phy_event_list_descr_idx;
+ uint16_t srgr_max_stored_phy_event_list_descrs;
+ uint16_t srgr_stp_reject_to_open_limit;
+ uint8_t _reserved12[2];
+} smp_report_general_resp_t;
+
+typedef enum smp_n_zone_grps {
+ SMP_ZONE_GROUPS_128 = 0x0,
+ SMP_ZONE_GROUPS_256 = 0x1
+} smp_n_zone_grps_t;
+
+/*
+ * SAS-2 10.4.3.5 REPORT MANUFACTURER INFORMATION (no additional request bytes)
+ */
+typedef struct smp_report_manufacturer_info_resp {
+ uint16_t srmir_exp_change_count;
+ uint8_t _reserved1[2];
+ DECL_BITFIELD2(
+ srmir_sas_1_1_format :1,
+ _reserved2 :7);
+ uint8_t _reserved3[3];
+ char srmir_vendor_identification[8];
+ char srmir_product_identification[16];
+ char srmir_product_revision_level[4];
+ char srmir_component_vendor_identification[8];
+ uint16_t srmir_component_id;
+ uint8_t srmir_component_revision_level;
+ uint8_t _reserved4;
+ uint8_t srmir_vs_52[8];
+} smp_report_manufacturer_info_resp_t;
+
+/*
+ * SAS-2 10.4.3.6 REPORT SELF_CONFIGURATION STATUS
+ */
+typedef struct smp_report_self_config_status_req {
+ uint8_t _reserved1[2];
+ uint16_t srscsr_starting_self_config_status_descr_idx;
+} smp_report_self_config_status_req_t;
+
+typedef struct smp_report_self_config_status_resp {
+ uint16_t srscsr_exp_change_count;
+ uint16_t srscsr_starting_self_config_status_descr_idx;
+ uint16_t srscsr_number_self_config_status_descrs;
+ uint16_t srscsr_last_self_config_status_descr_idx;
+ uint8_t srscsr_self_config_status_descr_len;
+ uint8_t _reserved1[3];
+ uint8_t srscsr_descrs[1];
+} smp_report_self_config_status_resp_t;
+
+typedef struct smp_self_config_status_descr {
+ uint8_t sscsd_status_type;
+ DECL_BITFIELD2(
+ sscsd_final :1,
+ _reserved1 :7);
+ uint8_t _reserved2;
+ uint8_t sscsd_phy_identifier;
+ uint8_t _reserved3[4];
+ uint64_t sscsd_sas_addr;
+} smp_self_config_status_descr_t;
+
+typedef enum smp_self_config_status_type {
+ SMP_SCST_NONSPECIFIC_ERROR = 0x01,
+ SMP_SCST_CONNECTION = 0x02,
+ SMP_SCST_ROUTE_TABLE_FULL = 0x03,
+ SMP_SCST_NOMEM = 0x04,
+ SMP_SCST_PHY_LAYER_ERROR = 0x20,
+ SMP_SCST_LOST_SYNC = 0x21,
+ SMP_SCST_LINK_LAYER_ERROR = 0x40,
+ SMP_SCST_OPEN_TIMEOUT = 0x41,
+ SMP_SCST_ABANDON_OPEN_REJECT = 0x42,
+ SMP_SCST_RETRY_OPEN_REJECTS = 0x43,
+ SMP_SCST_NEXUS_LOSS = 0x44,
+ SMP_SCST_BREAK = 0x45,
+ SMP_SCST_CRC_ERROR = 0x46,
+ SMP_SCST_PORT_LAYER_ERROR = 0x60,
+ SMP_SCST_RESPONSE_TIMEOUT = 0x61,
+ SMP_SCST_TRANSPORT_LAYER_ERROR = 0x80,
+ SMP_SCST_APP_LAYER_ERROR = 0xA0,
+ SMP_SCST_RESPONSE_TOO_SHORT = 0xA1,
+ SMP_SCST_UNSUPPORTED_VALUES = 0xA2,
+ SMP_SCST_INCONSISTENT = 0xA3,
+ SMP_SCST_CONFIGURING = 0xA4
+} smp_self_config_status_type_t;
+
+/*
+ * SAS-2 10.4.3.7 REPORT ZONE PERMISSION TABLE
+ */
+typedef struct smp_report_zone_perm_table_req {
+ DECL_BITFIELD2(
+ srzptr_report_type :2,
+ _reserved1 :6);
+ uint8_t _reserved2;
+ uint8_t srzptr_starting_src_zone_grp;
+ uint8_t srzptr_max_zone_perm_descrs;
+} smp_report_zone_perm_table_req_t;
+
+typedef enum smp_zone_perm_table_report_type {
+ SMP_ZPTRT_CURRENT = 0x0,
+ SMP_ZPTRT_SHADOW = 0x1,
+ SMP_ZPTRT_SAVED = 0x2,
+ SMP_ZPTRT_DEFAULT = 0x3
+} smp_zone_perm_table_report_type_t;
+
+typedef struct smp_report_zone_perm_table_resp {
+ uint16_t srzptr_exp_change_count;
+ DECL_BITFIELD3(
+ srzptr_report_type :2,
+ _reserved1 :5,
+ srzptr_zone_locked :1);
+ DECL_BITFIELD2(
+ _reserved2 :6,
+ srzptr_number_zone_grps :2);
+ uint8_t _reserved3[6];
+ uint8_t srzptr_starting_src_zone_grp;
+ uint8_t srzptr_number_zone_perm_descrs;
+ uint8_t srzptr_descrs[1];
+} smp_report_zone_perm_table_resp_t;
+
+typedef uint8_t smp_zone_perm_descr128_t[16];
+typedef uint8_t smp_zone_perm_descr256_t[32];
+
+#define SMP_ZONE_PERM_BIT128(__d, __z) \
+ ((__d)[15 - ((__z) >> 3)] & (1 << ((__z) & 7)))
+
+#define SMP_ZONE_PERM_SET128(__d, __z) \
+ ((__d)[15 - ((__z) >> 3)] |= (1 << ((__z) & 7)))
+
+#define SMP_ZONE_PERM_CLR128(__d, __z) \
+ ((__d)[15 - ((__z) >> 3)] &= ~(1 << ((__z) & 7)))
+
+#define SMP_ZONE_PERM_BIT256(__d, __z) \
+ ((__d)[31 - ((__z) >> 3)] & (1 << ((__z) & 7)))
+
+#define SMP_ZONE_PERM_SET256(__d, __z) \
+ ((__d)[31 - ((__z) >> 3)] |= (1 << ((__z) & 7)))
+
+#define SMP_ZONE_PERM_CLR256(__d, __z) \
+ ((__d)[31 - ((__z) >> 3)] &= ~(1 << ((__z) & 7)))
+
+/*
+ * SAS-2 10.4.3.8 REPORT ZONE MANAGER PASSWORD (no additional request bytes)
+ */
+typedef struct smp_report_zone_mgr_password_resp {
+ uint16_t srzmpr_exp_change_count;
+ uint8_t _reserved1[2];
+ uint8_t srzmpr_zone_mgr_password[32];
+} smp_report_zone_mgr_password_resp_t;
+
+/*
+ * SAS-2 10.4.3.9 REPORT BROADCAST
+ */
+typedef struct smp_report_broadcast_req {
+ DECL_BITFIELD2(
+ srbr_broadcast_type :4,
+ _reserved1 :4);
+ uint8_t _reserved2[3];
+} smp_report_broadcast_req_t;
+
+typedef enum smp_broadcast_type {
+ SMP_BROADCAST_CHANGE = 0x0,
+ SMP_BROADCAST_RESERVED_CHANGE_0 = 0x1,
+ SMP_BROADCAST_RESERVED_CHANGE_1 = 0x2,
+ SMP_BROADCAST_SES = 0x3,
+ SMP_BROADCAST_EXPANDER = 0x4,
+ SMP_BROADCAST_ASYNC_EVENT = 0x5,
+ SMP_BROADCAST_RESERVED_3 = 0x6,
+ SMP_BROADCAST_RESERVED_4 = 0x7,
+ SMP_BROADCAST_ZONE_ACTIVATE = 0x8
+} smp_broadcast_type_t;
+
+typedef struct smp_broadcast_descr {
+ DECL_BITFIELD2(
+ sbd_broadcast_type :4,
+ _reserved1 :4);
+ uint8_t sbd_phy_identifier;
+ DECL_BITFIELD2(
+ sbd_broadcast_reason :4,
+ _reserved2 :4);
+ uint16_t sbd_broadcast_count;
+ uint8_t _reserved3[10];
+} smp_broadcast_descr_t;
+
+typedef struct smp_report_broadcast_resp {
+ uint16_t srbr_exp_change_count;
+ DECL_BITFIELD2(
+ srbr_broadcast_type :4,
+ _reserved1 :4);
+ uint8_t srbr_number_broadcast_descrs;
+ smp_broadcast_descr_t srbr_descrs[1];
+} smp_report_broadcast_resp_t;
+
+/*
+ * SAS-2 10.4.3.10 DISCOVER
+ */
+typedef struct smp_discover_req {
+ uint8_t _reserved1[4];
+ DECL_BITFIELD2(
+ sdr_ignore_zone_grp :1,
+ _reserved2 :7);
+ uint8_t sdr_phy_identifier;
+ uint8_t _reserved3[2];
+} smp_discover_req_t;
+
+typedef struct smp_snw3_phy_cap {
+ DECL_BITFIELD4(
+ sspc_requested_logical_link_rate :4, /* smp_link_rate_t */
+ _reserved1 :2,
+ sspc_tx_ssc_type :1,
+ sspc_start :1);
+ DECL_BITFIELD7(
+ _reserved2 :2,
+ sspc_g3_ssc :1,
+ sspc_g3_no_ssc :1,
+ sspc_g2_ssc :1,
+ sspc_g2_no_ssc :1,
+ sspc_g1_ssc :1,
+ sspc_g1_no_ssc :1);
+ uint8_t _reserved3;
+ DECL_BITFIELD2(
+ sspc_parity :1,
+ _reserved4 :7);
+} smp_snw3_phy_cap_t;
+
+typedef struct smp_discover_resp {
+ uint16_t sdr_exp_change_count;
+ uint8_t _reserved1[3];
+ uint8_t sdr_phy_identifier;
+ uint8_t _reserved2[2];
+ DECL_BITFIELD3(
+ sdr_attached_reason :4,
+ sdr_attached_device_type :3,
+ _reserved3 :1);
+ DECL_BITFIELD2(
+ sdr_negotiated_logical_link_rate :4, /* smp_link_rate_t */
+ _reserved4 :4);
+ DECL_BITFIELD5(
+ sdr_attached_sata_host :1,
+ sdr_attached_smp_initiator :1,
+ sdr_attached_stp_initiator :1,
+ sdr_attached_ssp_initiator :1,
+ _reserved5 :4);
+ DECL_BITFIELD6(
+ sdr_attached_sata_device :1,
+ sdr_attached_smp_target :1,
+ sdr_attached_stp_target :1,
+ sdr_attached_ssp_target :1,
+ _reserved6 :3,
+ sdr_attached_sata_port_selector :1);
+ uint64_t sdr_sas_addr;
+ uint64_t sdr_attached_sas_addr;
+ uint8_t sdr_attached_phy_identifier;
+ DECL_BITFIELD4(
+ sdr_attached_break_reply_capable :1,
+ sdr_attached_requested_inside_zpsds :1,
+ sdr_attached_inside_zpsds_persistent :1,
+ _reserved7 :5);
+ uint8_t _reserved8[6];
+ DECL_BITFIELD2(
+ sdr_hw_min_phys_link_rate :4, /* smp_link_rate_t */
+ sdr_prog_min_phys_link_rate :4); /* smp_link_rate_t */
+ DECL_BITFIELD2(
+ sdr_hw_max_phys_link_rate :4, /* smp_link_rate_t */
+ sdr_prog_max_phys_link_rate :4); /* smp_link_rate_t */
+ uint8_t sdr_phy_change_count;
+ DECL_BITFIELD3(
+ sdr_partial_pwy_timeout :4,
+ _reserved9 :3,
+ sdr_virtual_phy :1);
+ DECL_BITFIELD2(
+ sdr_routing_attr :4, /* smp_routing_attr_t */
+ _reserved10 :4);
+ DECL_BITFIELD2(
+ sdr_connector_type :7,
+ _reserved11 :1);
+ uint8_t sdr_connector_element_index;
+ uint8_t sdr_connector_physical_link;
+ uint8_t _reserved12[2];
+ uint8_t sdr_vendor[2];
+ uint64_t sdr_attached_device_name;
+ DECL_BITFIELD8(
+ sdr_zoning_enabled :1,
+ sdr_inside_zpsds :1,
+ sdr_zone_group_persistent :1,
+ _reserved13 :1,
+ sdr_requested_inside_zpsds :1,
+ sdr_inside_zpsds_persistent :1,
+ sdr_requested_inside_zpsds_changed_by_exp :1,
+ _reserved14 :1);
+ uint8_t _reserved15[2];
+ uint8_t sdr_zone_group;
+ uint8_t sdr_self_config_status;
+ uint8_t sdr_self_config_levels_completed;
+ uint8_t _reserved16[2];
+ uint64_t sdr_self_config_sas_addr;
+ smp_snw3_phy_cap_t sdr_prog_phy_cap;
+ smp_snw3_phy_cap_t sdr_current_phy_cap;
+ smp_snw3_phy_cap_t sdr_attached_phy_cap;
+ uint8_t _reserved17[6];
+ DECL_BITFIELD2(
+ sdr_negotiated_phys_link_rate :4, /* smp_link_rate_t */
+ sdr_reason :4);
+ DECL_BITFIELD3(
+ sdr_hw_muxing_supported :1,
+ sdr_negotiated_ssc :1,
+ _reserved18 :6);
+ DECL_BITFIELD7(
+ sdr_default_zoning_enabled :1,
+ _reserved19 :1,
+ sdr_default_zone_group_persistent :1,
+ _reserved20 :1,
+ sdr_default_requested_inside_zpsds :1,
+ sdr_default_inside_zpsds_persistent :1,
+ _reserved21 :2);
+ uint8_t _reserved22[2];
+ uint8_t sdr_default_zone_group;
+ DECL_BITFIELD7(
+ sdr_saved_zoning_enabled :1,
+ _reserved23 :1,
+ sdr_saved_zone_group_persistent :1,
+ _reserved24 :1,
+ sdr_saved_requested_inside_zpsds :1,
+ sdr_saved_inside_zpsds_persistent :1,
+ _reserved25 :2);
+ uint8_t _reserved26[2];
+ uint8_t saved_zone_group;
+ DECL_BITFIELD6(
+ _reserved27 :2,
+ sdr_shadow_zone_group_persistent :1,
+ _reserved28 :1,
+ sdr_shadow_requested_inside_zpsds :1,
+ sdr_shadow_inside_zpsds_persistent :1,
+ _reserved29 :2);
+ uint8_t _reserved30[2];
+ uint8_t sdr_shadow_zone_group;
+} smp_discover_resp_t;
+
+typedef enum smp_link_rate {
+ SMP_LINK_RATE_NO_CHANGE = 0x0,
+ SMP_LINK_RATE_DISABLED = 0x1,
+ SMP_LINK_RATE_RESET_PROBLEM = 0x2,
+ SMP_LINK_RATE_SPINUP_HOLD = 0x3,
+ SMP_LINK_RATE_PORT_SELECTOR = 0x4,
+ SMP_LINK_RATE_RESET = 0x5,
+ SMP_LINK_RATE_UNSUPPORTED = 0x6,
+ SMP_LINK_RATE_1_5 = 0x8,
+ SMP_LINK_RATE_3 = 0x9,
+ SMP_LINK_RATE_6 = 0xA
+} smp_link_rate_t;
+
+typedef enum smp_device_type {
+ SMP_DEV_NONE = 0x0,
+ SMP_DEV_SAS_SATA = 0x1,
+ SMP_DEV_EXPANDER = 0x2,
+ SMP_DEV_EXPANDER_OLD = 0x3
+} smp_device_type_t;
+
+typedef enum smp_routing_attr {
+ SMP_ROUTING_DIRECT = 0x0,
+ SMP_ROUTING_SUBTRACTIVE = 0x1,
+ SMP_ROUTING_TABLE = 0x2
+} smp_routing_attr_t;
+
+/*
+ * SAS-2 10.4.3.11 REPORT PHY ERROR LOG
+ */
+typedef struct smp_report_phy_error_log_req {
+ uint8_t _reserved1[5];
+ uint8_t srpelr_phy_identifier;
+ uint8_t _reserved2[2];
+} smp_report_phy_error_log_req_t;
+
+typedef struct smp_report_phy_error_log_resp {
+ uint16_t srpelr_exp_change_count;
+ uint8_t _reserved1[3];
+ uint8_t srpelr_phy_identifier;
+ uint8_t _reserved2[2];
+ uint32_t srpelr_invalid_dword_count;
+ uint32_t srpelr_running_disparity_error_count;
+ uint32_t srpelr_loss_dword_sync_count;
+ uint32_t srpelr_phy_reset_problem_count;
+} smp_report_phy_error_log_resp_t;
+
+/*
+ * SAS-2 10.4.3.12 REPORT PHY SATA
+ */
+typedef struct smp_report_phy_sata_req {
+ uint8_t _reserved1[5];
+ uint8_t srpsr_phy_identifier;
+ uint8_t srpsr_affiliation_context;
+ uint8_t _reserved2;
+} smp_report_phy_sata_req_t;
+
+typedef struct smp_report_phy_sata_resp {
+ uint16_t srpsr_exp_change_count;
+ uint8_t _reserved1[3];
+ uint8_t srpsr_phy_identifier;
+ uint8_t _reserved2;
+ DECL_BITFIELD4(
+ srpsr_affiliation_valid :1,
+ srpsr_affiliations_supported :1,
+ srpsr_stp_nexus_loss :1,
+ _reserved3 :5);
+ uint8_t _reserved4[4];
+ uint64_t srpsr_stp_sas_addr;
+ uint8_t srpsr_register_device_host_fis[20];
+ uint8_t _reserved5[4];
+ uint64_t srpsr_affiliated_stp_init_sas_addr;
+ uint64_t srpsr_stp_nexus_loss_sas_addr;
+ uint8_t _reserved6;
+ uint8_t srpsr_affiliation_context;
+ uint8_t srpsr_current_affiliation_contexts;
+ uint8_t srpsr_max_affiliation_contexts;
+} smp_report_phy_sata_resp_t;
+
+/*
+ * SAS-2 10.4.3.13 REPORT ROUTE INFORMATION
+ */
+typedef struct smp_report_route_info_req {
+ uint8_t _reserved1[2];
+ uint16_t srrir_exp_route_index;
+ uint8_t _reserved2;
+ uint8_t srrir_phy_identifier;
+ uint8_t _reserved3[2];
+} smp_report_route_info_req_t;
+
+typedef struct smp_report_route_info_resp {
+ uint16_t srrir_exp_change_count;
+ uint16_t srrir_exp_route_index;
+ uint8_t _reserved1;
+ uint8_t srrir_phy_identifier;
+ uint8_t _reserved2[2];
+ DECL_BITFIELD2(
+ _reserved3 :7,
+ srrir_exp_route_entry_disabled :1);
+ uint8_t _reserved4[3];
+ uint64_t srrir_routed_sas_addr;
+ uint8_t _reserved5[16];
+} smp_report_route_info_resp_t;
+
+/*
+ * SAS-2 10.4.3.14 SAS-2 REPORT PHY EVENT
+ */
+typedef struct smp_report_phy_event_req {
+ uint8_t _reserved1;
+ uint8_t _reserved2[4];
+ uint8_t srper_phy_identifier;
+ uint8_t _reserved3[2];
+} smp_report_phy_event_req_t;
+
+typedef struct smp_phy_event_report_descr {
+ uint8_t _reserved1[3];
+ uint8_t sped_phy_event_source;
+ uint32_t sped_phy_event;
+ uint32_t sped_peak_detector_threshold;
+} smp_phy_event_report_descr_t;
+
+typedef struct smp_report_phy_event_resp {
+ uint16_t srper_exp_change_count;
+ uint8_t _reserved1[3];
+ uint8_t srper_phy_identifier;
+ uint8_t _reserved2[5];
+ uint8_t srper_n_phy_event_descrs;
+ smp_phy_event_report_descr_t srper_phy_event_descrs[1];
+} smp_report_phy_event_resp_t;
+
+/*
+ * SAS-2 10.4.3.15 SAS-2 DISCOVER LIST
+ */
+typedef struct smp_discover_list_req {
+ uint8_t _reserved1[4];
+ uint8_t sdlr_starting_phy_identifier;
+ uint8_t sdlr_max_descrs;
+ DECL_BITFIELD3(
+ sdlr_phy_filter :4,
+ _reserved2 :3,
+ sdlr_ignore_zone_group :1);
+ DECL_BITFIELD2(
+ sdlr_descr_type :4,
+ _reserved3 :4);
+ uint8_t _reserved4[4];
+ uint8_t sdlr_vendor[12];
+} smp_discover_list_req_t;
+
+typedef struct smp_discover_short_descr {
+ uint8_t sdsd_phy_identifier;
+ uint8_t sdsd_function_result;
+ DECL_BITFIELD3(
+ sdsd_attached_reason :4,
+ sdsd_attached_device_type :3,
+ _restricted1 :1);
+ DECL_BITFIELD2(
+ sdsd_negotiated_logical_link_rate :4, /* smp_link_rate_t */
+ _restricted2 :4);
+ DECL_BITFIELD5(
+ sdsd_attached_sata_host :1,
+ sdsd_attached_smp_initiator :1,
+ sdsd_attached_stp_initiator :1,
+ sdsd_attached_ssp_initiator :1,
+ _restricted3 :4);
+ DECL_BITFIELD6(
+ sdsd_attached_sata_device :1,
+ sdsd_attached_smp_target :1,
+ sdsd_attached_stp_target :1,
+ sdsd_attached_ssp_target :1,
+ _restricted4 :3,
+ sdsd_attached_sata_port_selector :1);
+ DECL_BITFIELD3(
+ sdsd_routing_attribute :4, /* smp_routing_attr_t */
+ _reserved1 :3,
+ sdsd_virtual_phy :1);
+ DECL_BITFIELD2(
+ _reserved2 :4,
+ sdsd_reason :4);
+ uint8_t sdsd_zone_group;
+ DECL_BITFIELD7(
+ _reserved3 :1,
+ sdsd_inside_zpsds :1,
+ sdsd_zone_group_persistent :1,
+ _reserved4 :1,
+ sdsd_requested_insize_zpsds :1,
+ sdsd_inside_zpsds_persistent :1,
+ _restricted5 :2);
+ uint8_t sdsd_attached_phy_identifier;
+ uint8_t sdsd_phy_change_count;
+ uint64_t sdsd_attached_sas_addr;
+ uint8_t _reserved5[4];
+} smp_discover_short_descr_t;
+
+typedef struct smp_discover_long_descr {
+ uint8_t _reserved1[2];
+ uint8_t sdld_function_result;
+ uint8_t _reserved2[1];
+ smp_discover_resp_t sdld_response;
+} smp_discover_long_descr_t;
+
+#define SMP_DISCOVER_RESP(_ld) \
+ (((smp_discover_long_descr_t *)(_ld))->sdld_function_result == \
+ SMP_FUNCTION_ACCEPTED ? \
+ &((smp_discover_long_descr_t *)(_ld))->sdld_response : \
+ NULL)
+
+typedef struct smp_discover_list_resp {
+ uint16_t sdlr_exp_change_count;
+ uint8_t _reserved1[2];
+ uint8_t sdlr_starting_phy_identifier;
+ uint8_t sdlr_n_descrs;
+ DECL_BITFIELD2(
+ sdlr_phy_filter :4,
+ _reserved2 :4);
+ DECL_BITFIELD2(
+ sdlr_descr_type :4,
+ _reserved3 :4);
+ uint8_t sdlr_descr_length;
+ uint8_t _reserved4[3];
+ DECL_BITFIELD5(
+ sdlr_externally_configurable_route_table :1,
+ sdlr_configuring :1,
+ _reserved5 :4,
+ sdlr_zoning_enabled :1,
+ sdlr_zoning_supported :1);
+ uint8_t _reserved6;
+ uint16_t sdlr_last_sc_status_descr_index;
+ uint16_t sdlr_last_phy_event_list_descr_index;
+ uint8_t _reserved7[10];
+ uint8_t sdlr_vendor[16];
+ uint8_t sdlr_descrs[1]; /* short or long format */
+} smp_discover_list_resp_t;
+
+/*
+ * SAS-2 10.4.3.16 REPORT PHY EVENT LIST
+ */
+typedef struct smp_report_phy_event_list_req {
+ uint8_t _reserved1[2];
+ uint16_t srpelr_starting_descr_index;
+} smp_report_phy_event_list_req_t;
+
+typedef struct smp_phy_event_list_descr {
+ uint8_t _reserved1[2];
+ uint8_t speld_phy_identifier;
+ uint8_t speld_phy_event_source;
+ uint32_t speld_phy_event;
+ uint32_t speld_peak_detector_threshold;
+} smp_phy_event_list_descr_t;
+
+typedef struct smp_report_phy_event_list_resp {
+ uint16_t srpelr_exp_change_count;
+ uint16_t srpelr_starting_descr_index;
+ uint16_t srpelr_last_descr_index;
+ uint8_t srpelr_phy_event_list_descr_length;
+ uint8_t _reserved1[3];
+ uint8_t srpelr_n_descrs;
+ smp_phy_event_list_descr_t srpelr_descrs[1];
+} smp_report_phy_event_list_resp_t;
+
+/*
+ * SAS-2 10.4.3.17 REPORT EXPANDER ROUTE TABLE LIST
+ */
+typedef struct smp_report_exp_route_table_list_req {
+ uint8_t _reserved1[4];
+ uint16_t srertlr_max_descrs;
+ uint16_t srertlr_starting_routed_sas_addr_index;
+ uint8_t _reserved2[7];
+ uint8_t srertlr_starting_phy_identifier;
+ uint8_t _reserved3[8];
+} smp_report_exp_route_table_list_req_t;
+
+typedef struct smp_route_table_descr {
+ uint64_t srtd_routed_sas_addr;
+ uint8_t srtd_phy_bitmap[6];
+ DECL_BITFIELD2(
+ _reserved1 :7,
+ srtd_zone_group_valid :1);
+ uint8_t srtd_zone_group;
+} smp_route_table_descr_t;
+
+#define SMP_ROUTE_PHY(_d, _s, _i) \
+ ((_d)->srtd_phy_bitmap[(48 - (_i) + (_s)) >> 3] & \
+ (1 << ((48 - (_i) + (_s)) & 7)))
+
+typedef struct smp_report_exp_route_table_list_resp {
+ uint16_t srertlr_exp_change_count;
+ uint16_t srertlr_route_table_change_count;
+ DECL_BITFIELD3(
+ _reserved1 :1,
+ srertlr_configuring :1,
+ _reserved2 :6);
+ uint8_t _reserved3;
+ uint16_t srertlr_n_descrs;
+ uint16_t srertlr_first_routed_sas_addr_index;
+ uint16_t srertlr_last_routed_sas_addr_index;
+ uint8_t _reserved4[3];
+ uint8_t srertlr_starting_phy_identifier;
+ uint8_t _reserved5[12];
+ smp_route_table_descr_t srertlr_descrs[1];
+} smp_report_exp_route_table_list_resp_t;
+
+/*
+ * SAS-2 10.4.3.18 CONFIGURE GENERAL (no additional response)
+ */
+typedef struct smp_config_general_req {
+ uint16_t scgr_expected_exp_change_count;
+ uint8_t _reserved1[2];
+ DECL_BITFIELD6(
+ scgr_update_stp_bus_inactivity :1,
+ scgr_update_stp_max_conn :1,
+ scgr_update_stp_smp_nexus_loss :1,
+ scgr_update_initial_time_to_reduced_functionality :1,
+ scgr_update_stp_reject_to_open :1,
+ _reserved2 :3);
+ uint8_t _reserved3;
+ uint16_t scgr_stp_bus_inactivity;
+ uint16_t scgr_stp_max_conn;
+ uint16_t scgr_stp_smp_nexus_loss;
+ uint8_t scgr_initial_time_to_reduced_functionality;
+ uint8_t _reserved4;
+ uint16_t scgr_stp_reject_to_open;
+} smp_config_general_req_t;
+
+/*
+ * SAS-2 10.4.3.19 ENABLE DISABLE ZONING (no additional response)
+ */
+typedef struct smp_enable_disable_zoning_req {
+ uint16_t sedzr_expected_exp_change_count;
+ DECL_BITFIELD2(
+ sedzr_save :2, /* smp_zoning_save_t */
+ _reserved1 :6);
+ uint8_t _reserved2;
+ DECL_BITFIELD2(
+ sedzr_enable_disable_zoning :2,
+ _reserved3 :6);
+ uint8_t _reserved4[3];
+} smp_enable_disable_zoning_req_t;
+
+typedef enum smp_zoning_save {
+ SMP_ZONING_SAVE_CURRENT = 0x0,
+ SMP_ZONING_SAVE_SAVED = 0x1,
+ SMP_ZONING_SAVE_BOTH_IF_SUPP = 0x2,
+ SMP_ZONING_SAVE_BOTH = 0x3
+} smp_zoning_save_t;
+
+typedef enum smp_zoning_enable_op {
+ SMP_ZONING_ENABLE_OP_NONE = 0x0,
+ SMP_ZONING_ENABLE_OP_ENABLE = 0x1,
+ SMP_ZONING_ENABLE_OP_DISABLE = 0x2
+} smp_zoning_enable_op_t;
+
+/*
+ * SAS-2 10.4.3.20 ZONED BROADCAST (no additional response)
+ */
+typedef struct smp_zoned_broadcast_req {
+ uint8_t _restricted1[2];
+ DECL_BITFIELD2(
+ szbr_broadcast_type :4,
+ _reserved :4);
+ uint8_t szbr_n_broadcast_source_zone_groups;
+ uint8_t szbr_broadcast_source_zone_groups[1];
+} smp_zoned_broadcast_req_t;
+
+/*
+ * SAS-2 10.4.3.21 ZONE LOCK
+ */
+typedef struct smp_zone_lock_req {
+ uint16_t szlr_expected_exp_change_count;
+ uint16_t szlr_zone_lock_inactivity_timeout;
+ uint8_t szlr_zone_manager_password[32];
+} smp_zone_lock_req_t;
+
+typedef struct smp_zone_lock_resp {
+ uint8_t _reserved1[4];
+ uint64_t szlr_active_zone_manager_sas_addr;
+} smp_zone_lock_resp_t;
+
+/*
+ * SAS-2 10.4.3.22 ZONE ACTIVATE (no additional response)
+ */
+typedef struct smp_zone_activate_req {
+ uint16_t szar_expected_exp_change_count;
+ uint8_t _reserved1[2];
+} smp_zone_activate_req_t;
+
+/*
+ * SAS-2 10.4.3.23 ZONE UNLOCK (no additional response)
+ */
+typedef struct smp_zone_unlock_req {
+ uint8_t _restricted1[2];
+ DECL_BITFIELD2(
+ szur_activate_required :1,
+ _reserved1 :7);
+ uint8_t _reserved2;
+} smp_zone_unlock_req_t;
+
+/*
+ * SAS-2 10.4.3.24 CONFIGURE ZONE MANAGER PASSWORD (no additional response)
+ */
+typedef struct smp_config_zone_manager_password_req {
+ uint16_t sczmpr_expected_exp_change_count;
+ DECL_BITFIELD2(
+ sczmpr_save :2, /* smp_zoning_save_t */
+ _reserved1 :6);
+ uint8_t _reserved2;
+ uint8_t sczmpr_zone_manager_password[32];
+ uint8_t sczmpr_new_zone_manager_password[32];
+} smp_config_zone_manager_password_req_t;
+
+/*
+ * SAS-2 10.4.3.25 CONFIGURE ZONE PHY INFORMATION (no additional response)
+ */
+typedef struct smp_zone_phy_config_descr {
+ uint8_t szpcd_phy_identifier;
+ DECL_BITFIELD6(
+ _reserved1 :2,
+ szpcd_zone_group_persistent :1,
+ _reserved2 :1,
+ szpcd_requested_inside_zpsds :1,
+ szpcd_inside_zpsds_persistent :1,
+ _reserved3 :2);
+ uint8_t _reserved4;
+ uint8_t szpcd_zone_group;
+} smp_zone_phy_config_descr_t;
+
+typedef struct smp_config_zone_phy_info_req {
+ uint16_t sczpir_expected_exp_change_count;
+ DECL_BITFIELD2(
+ sczpir_save :2, /* smp_zoning_save_t */
+ _reserved1 :6);
+ uint8_t sczpir_n_descrs;
+ smp_zone_phy_config_descr_t sczpir_descrs[1];
+} smp_config_zone_phy_info_req_t;
+
+/*
+ * SAS-2 10.4.3.26 CONFIGURE ZONE PERMISSION TABLE (no additional response)
+ */
+typedef struct smp_config_zone_perm_table_req {
+ uint16_t sczptr_expected_exp_change_count;
+ uint8_t sczptr_starting_source_zone_group;
+ uint8_t sczptr_n_descrs;
+ DECL_BITFIELD3(
+ sczptr_save :2, /* smp_zoning_save_t */
+ _reserved1 :4,
+ sczptr_n_zone_groups :2); /* smp_n_zone_grps_t */
+ uint8_t _reserved2[7];
+ uint8_t sczptr_descrs[1]; /* smp_zone_perm_descrXXX_t */
+} smp_config_zone_perm_table_req_t;
+
+/*
+ * SAS-2 10.4.3.27 CONFIGURE ROUTE INFORMATION (no additional response)
+ */
+typedef struct smp_config_route_info_req {
+ uint16_t scrir_expected_exp_change_count;
+ uint16_t scrir_exp_route_index;
+ uint8_t _reserved1;
+ uint8_t scrir_phy_identifier;
+ uint8_t _reserved2[2];
+ DECL_BITFIELD2(
+ _reserved3 :7,
+ scrir_disable_exp_route_entry :1);
+ uint8_t _reserved4[3];
+ uint64_t scrir_routed_sas_addr;
+ uint8_t _reserved5[16];
+} smp_config_route_info_req_t;
+
+/*
+ * SAS-2 10.4.3.28 PHY CONTROL (no additional response)
+ */
+typedef struct smp_phy_control_req {
+ uint16_t spcr_expected_exp_change_count;
+ uint8_t _reserved1[3];
+ uint8_t spcr_phy_identifier;
+ uint8_t spcr_phy_operation;
+ DECL_BITFIELD2(
+ spcr_update_partial_pwy_timeout :1,
+ _reserved2 :7);
+ uint8_t _reserved3[12];
+ uint64_t spcr_attached_device_name;
+ DECL_BITFIELD2(
+ _reserved4 :4,
+ spcr_prog_min_phys_link_rate :4); /* smp_link_rate_t */
+ DECL_BITFIELD2(
+ _reserved5 :4,
+ spcr_prog_max_phys_link_rate :4); /* smp_link_rate_t */
+ uint8_t _reserved6[2];
+ DECL_BITFIELD2(
+ spcr_partial_pwy_timeout :4,
+ _reserved7 :4);
+ uint8_t _reserved8[3];
+} smp_phy_control_req_t;
+
+typedef enum smp_phy_op {
+ SMP_PHY_OP_NOP = 0x00,
+ SMP_PHY_OP_LINK_RESET = 0x01,
+ SMP_PHY_OP_HARD_RESET = 0x02,
+ SMP_PHY_OP_DISABLE = 0x03,
+ SMP_PHY_OP_CLEAR_ERROR_LOG = 0x05,
+ SMP_PHY_OP_CLEAR_AFFILIATION = 0x06,
+ SMP_PHY_OP_TRANSMIT_SATA_PORT_SELECTION_SIGNAL = 0x07,
+ SMP_PHY_OP_CLEAR_STP_NEXUS_LOSS = 0x08,
+ SMP_PHY_OP_SET_ATTACHED_DEVICE_NAME = 0x09
+} smp_phy_op_t;
+
+/*
+ * SAS-2 10.4.3.29 PHY TEST FUNCTION (no additional response)
+ */
+typedef struct smp_phy_test_function_req {
+ uint16_t sptfr_expected_exp_change_count;
+ uint8_t _reserved1[3];
+ uint8_t sptfr_phy_identifier;
+ uint8_t sptfr_phy_test_function;
+ uint8_t sptfr_phy_test_pattern; /* smp_phy_test_function_t */
+ uint8_t _reserved2[3];
+ DECL_BITFIELD4(
+ sptfr_test_pattern_phys_link_rate :4, /* smp_link_rate_t */
+ sptfr_test_pattern_ssc :2,
+ sptfr_test_pattern_sata :1,
+ _reserved3 :1);
+ uint8_t _reserved4[3];
+ uint8_t sptfr_phy_test_pattern_dwords_ctl;
+ uint8_t sptfr_phy_test_pattern_dwords[8];
+ uint8_t _reserved5[12];
+} smp_phy_test_function_req_t;
+
+typedef enum smp_phy_test_function {
+ SMP_PHY_TEST_FN_STOP = 0x00,
+ SMP_PHY_TEST_FN_TRANSMIT_PATTERN = 0x01
+} smp_phy_test_function_t;
+
+/*
+ * SAS-2 10.4.3.30 CONFIGURE PHY EVENT (no additional response)
+ */
+typedef struct smp_phy_event_config_descr {
+ uint8_t _reserved1[3];
+ uint8_t specd_phy_event_source;
+ uint32_t specd_peak_value_detector_threshold;
+} smp_phy_event_config_descr_t;
+
+typedef struct smp_config_phy_event_req {
+ uint16_t scper_expected_exp_change_count;
+ DECL_BITFIELD2(
+ scper_clear_peaks :1,
+ _reserved1 :7);
+ uint8_t _reserved2[2];
+ uint8_t scper_phy_identifier;
+ uint8_t _reserved3;
+ uint8_t scper_n_descrs;
+ smp_phy_event_config_descr_t scper_descrs[1];
+} smp_config_phy_event_req_t;
+
+#pragma pack()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_SCSI_GENERIC_SMP_FRAMES_H */
diff --git a/usr/src/uts/common/sys/scsi/conf/autoconf.h b/usr/src/uts/common/sys/scsi/conf/autoconf.h
index 757732cb09..8d0903dee5 100644
--- a/usr/src/uts/common/sys/scsi/conf/autoconf.h
+++ b/usr/src/uts/common/sys/scsi/conf/autoconf.h
@@ -19,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_SCSI_CONF_AUTOCONF_H
#define _SYS_SCSI_CONF_AUTOCONF_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -75,6 +73,9 @@ extern "C" {
#define SCSI_OPTIONS_NLUNS_8 0x20000
#define SCSI_OPTIONS_NLUNS_16 0x30000
#define SCSI_OPTIONS_NLUNS_32 0x40000
+#define SCSI_OPTIONS_NLUNS_64 0x50000
+#define SCSI_OPTIONS_NLUNS_128 0x60000
+#define SCSI_OPTIONS_NLUNS_256 0x70000
#define SCSI_OPTIONS_NLUNS(n) ((n) & SCSI_OPTIONS_NLUNS_MASK)
@@ -153,14 +154,41 @@ extern "C" {
#define SCSI_DEFAULT_SELECTION_TIMEOUT 250
/*
- * Kernel references
+ * SCSI subsystem scsi_enumeration options.
+ *
+ * Knob for SPI (SCSI Parallel Intrconnect) enumeration. Unless an HBA defines
+ * it's own tran_bus_config, SPI enumeration is used. The "scsi_enumeration"
+ * knob determines how SPI enumeration is performed.
+ *
+ * The global variable "scsi_enumeration" is used as the default value of the
+ * "scsi-enumeration" property. In addition to enabling/disabling enumeration
+ * (bit 0), target and lun threading can be specified. Having things
+ * multi-threaded does not guarantee reduce configuration time, however when
+ * the bus is marginal multi-threading can substaintaly reduce configuration
+ * time because targets negotiate to stable transfer speeds in parallel - so
+ * all targets have stabalized by the time the sequential attach(9E) operations
+ * begin. Running multi-threaded also helps verification of framework and HBA
+ * locking: a BUS_CONFIG_ALL is equivalent to every target and lun combination
+ * getting a BUS_CONFIG_ONE from a separate thread at the same time. A disable
+ * mechanism is provided to accomidate buggy HBAs (set scsi-enumeration=7
+ * driver.conf). Values are:
+ *
+ * 0 driver.conf enumeration
+ * 1 dynamic enumeration with target and lun multi-threading.
+ * 3 dynamic enumeration with lun multi-threading disabled.
+ * 5 dynamic enumeration with target multi-threading disabled;
+ * 7 dynamic enumeration with target/lun multi-threading disabled.
*/
+#define SCSI_ENUMERATION_ENABLE 0x1
+#define SCSI_ENUMERATION_MT_LUN_DISABLE 0x2
+#define SCSI_ENUMERATION_MT_TARGET_DISABLE 0x4
#ifdef _KERNEL
/*
* Global SCSI config variables / options
*/
extern int scsi_options;
+extern int scsi_enumeration;
extern unsigned int scsi_reset_delay; /* specified in milli seconds */
extern int scsi_tag_age_limit;
extern int scsi_watchdog_tick;
diff --git a/usr/src/uts/common/sys/scsi/conf/device.h b/usr/src/uts/common/sys/scsi/conf/device.h
index 305e595807..9fce4669d8 100644
--- a/usr/src/uts/common/sys/scsi/conf/device.h
+++ b/usr/src/uts/common/sys/scsi/conf/device.h
@@ -141,6 +141,13 @@ struct scsi_device {
void *sd_pathinfo;
/*
+ * Counter that prevents demotion of DS_INITIALIZED node (esp loss of
+ * devi_addr) by causing DDI_CTLOPS_UNINITCHILD failure - devi_ref
+ * will not protect demotion of DS_INITIALIZED node.
+ */
+ int sd_uninit_prevent;
+
+ /*
* The 'sd_tran_safe' field is a grotty hack that allows direct-access
* (non-scsa) drivers (like chs, ata, and mlx - which all make cmdk
* children) to *illegally* put their own vector in the scsi_address(9S)
diff --git a/usr/src/uts/common/sys/scsi/generic/sas.h b/usr/src/uts/common/sys/scsi/generic/sas.h
new file mode 100644
index 0000000000..61ba710e19
--- /dev/null
+++ b/usr/src/uts/common/sys/scsi/generic/sas.h
@@ -0,0 +1,199 @@
+/*
+ * 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 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * SAS Common Structures and Definitions
+ * sas2r14, simplified/reduced
+ */
+#ifndef _SAS_H
+#define _SAS_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/sysmacros.h>
+/*
+ * SAS Address Frames
+ * Trailing 4 byte CRC not included.
+ */
+typedef struct {
+ DECL_BITFIELD3(
+ address_frame_type :4,
+ device_type :3,
+ reserved0 :1);
+ DECL_BITFIELD2(
+ reason :4,
+ reserved1 :4);
+ DECL_BITFIELD5(
+ restricted0 :1,
+ smp_ini_port :1,
+ stp_ini_port :1,
+ ssp_ini_port :1,
+ reserved2 :4);
+ DECL_BITFIELD5(
+ restricted1 :1,
+ smp_tgt_port :1,
+ stp_tgt_port :1,
+ ssp_tgt_port :1,
+ reserved3 :4);
+ uint8_t device_name[8];
+ uint8_t sas_address[8];
+ uint8_t phy_identifier;
+ DECL_BITFIELD4(
+ break_reply_capable :1,
+ requested_inside_zpsds :1,
+ inside_zpsds_persistent :1,
+ reserved4 :5);
+ uint8_t reserved5[6];
+} sas_identify_af_t;
+
+typedef struct {
+ DECL_BITFIELD3(
+ address_frame_type :4,
+ protocol :3,
+ ini_port :1);
+ DECL_BITFIELD2(
+ connection_rate :4,
+ features :4);
+ uint16_t itag; /* initiator connection tag */
+ uint8_t sas_dst[8]; /* destination sas address */
+ uint8_t sas_src[8]; /* source sas address */
+ uint8_t src_zone_group; /* source zone group */
+ uint8_t path_block_count; /* pathway blocked count */
+ uint16_t arb_wait_time; /* arbitration wait time */
+ uint8_t compat[4]; /* 'more' compatible features */
+} sas_open_af_t;
+
+#define SAS_AF_IDENTIFY 0
+#define SAS_AF_OPEN 1
+
+#define SAS_IF_DTYPE_ENDPOINT 1
+#define SAS_IF_DTYPE_EDGE 2
+#define SAS_IF_DTYPE_FANOUT 3 /* obsolete */
+
+#define SAS_OF_PROTO_SMP 0
+#define SAS_OF_PROTO_SSP 1
+#define SAS_OF_PROTO_STP 2
+
+#define SAS_SSP_SUPPORT 0x8
+#define SAS_STP_SUPPORT 0x4
+#define SAS_SMP_SUPPORT 0x2
+
+
+#define SAS_CONNRATE_1_5_GBPS 0x8
+#define SAS_CONNRATE_3_0_GBPS 0x9
+#define SAS_CONNRATE_6_0_GBPS 0xA
+
+#define SAS_SATA_SUPPORT 0x1
+#define SAS_ATTACHED_NAME_OFFSET 52 /* SAS-2 only */
+
+/*
+ * SSP Definitions
+ */
+typedef struct {
+ uint8_t lun[8];
+ uint8_t reserved0;
+ DECL_BITFIELD3(
+ task_attribute :2,
+ command_priority :4,
+ enable_first_burst :1);
+ uint8_t reserved1;
+ DECL_BITFIELD2(
+ reserved2 :2,
+ addi_cdb_len :6);
+ uint8_t cdb[16];
+ /* additional cdb bytes go here, followed by 4 byte CRC */
+} sas_ssp_cmd_iu_t;
+
+#define SAS_CMD_TASK_ATTR_SIMPLE 0x00
+#define SAS_CMD_TASK_ATTR_HEAD 0x01
+#define SAS_CMD_TASK_ATTR_ORDERED 0x02
+#define SAS_CMD_TASK_ATTR_ACA 0x04
+
+typedef struct {
+ uint8_t reserved0[8];
+ uint16_t status_qualifier;
+ DECL_BITFIELD2(
+ datapres :2,
+ reserved1 :6);
+ uint8_t status;
+ uint8_t reserved2[4];
+ uint32_t sense_data_length;
+ uint32_t response_data_length;
+ uint8_t rspd[];
+ /* response data followed by sense data goes here */
+} sas_ssp_rsp_iu_t;
+
+/* length of bytes up to response data */
+#define SAS_RSP_HDR_SIZE 24
+
+#define SAS_RSP_DATAPRES_NO_DATA 0x00
+#define SAS_RSP_DATAPRES_RESPONSE_DATA 0x01
+#define SAS_RSP_DATAPRES_SENSE_DATA 0x02
+
+/*
+ * When the RSP IU is type RESPONSE_DATA,
+ * the first 4 bytes of response data should
+ * be a Big Endian representation of one of
+ * these codes.
+ */
+#define SAS_RSP_TMF_COMPLETE 0x00
+#define SAS_RSP_INVALID_FRAME 0x02
+#define SAS_RSP_TMF_NOT_SUPPORTED 0x04
+#define SAS_RSP_TMF_FAILED 0x05
+#define SAS_RSP_TMF_SUCCEEDED 0x08
+#define SAS_RSP_TMF_INCORRECT_LUN 0x09
+#define SAS_RSP_OVERLAPPED_OIPTTA 0x0A
+
+/*
+ * Task Management Functions- should be in a SAM definition file
+ */
+#define SAS_ABORT_TASK 0x01
+#define SAS_ABORT_TASK_SET 0x02
+#define SAS_CLEAR_TASK_SET 0x04
+#define SAS_LOGICAL_UNIT_RESET 0x08
+#define SAS_I_T_NEXUS_RESET 0x10
+#define SAS_CLEAR_ACA 0x40
+#define SAS_QUERY_TASK 0x80
+#define SAS_QUERY_TASK_SET 0x81
+#define SAS_QUERY_UNIT_ATTENTION 0x82
+
+/*
+ * PHY size changed from SAS1.1 to SAS2.
+ */
+#define SAS_PHYNUM_MAX 127
+#define SAS_PHYNUM_MASK 0x7f
+
+#define SAS2_PHYNUM_MAX 254
+#define SAS2_PHYNUM_MASK 0xff
+
+
+/*
+ * Maximum SMP payload size, including CRC
+ */
+#define SAS_SMP_MAX_PAYLOAD 1032
+#ifdef __cplusplus
+}
+#endif
+#endif /* _SAS_H */
diff --git a/usr/src/uts/common/sys/scsi/generic/smp_frames.h b/usr/src/uts/common/sys/scsi/generic/smp_frames.h
index 5c2fa17d9f..dd79a19b33 100644
--- a/usr/src/uts/common/sys/scsi/generic/smp_frames.h
+++ b/usr/src/uts/common/sys/scsi/generic/smp_frames.h
@@ -20,14 +20,12 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#ifndef _SYS_SCSI_IMPL_SMP_FRAME_H
-#define _SYS_SCSI_IMPL_SMP_FRAME_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+#ifndef _SYS_SCSI_GENERIC_SMP_FRAMES_H
+#define _SYS_SCSI_GENERIC_SMP_FRAMES_H
#ifdef __cplusplus
extern "C" {
@@ -36,86 +34,1058 @@ extern "C" {
#include <sys/sysmacros.h>
/*
- * The definitions of smp frame types and functions conforming to SAS v1.1.
- * The SAS v2.0 will be supported in the future when it is publicly released.
+ * The definitions of smp frame types and functions conforming to SAS-1.1 and
+ * SAS-2. Consumers are expected to determine protocol support by examining
+ * the response to the REPORT GENERAL function.
*/
-typedef enum {
+typedef enum smp_frame_type {
SMP_FRAME_TYPE_REQUEST = 0x40,
SMP_FRAME_TYPE_RESPONSE = 0x41
-} smp_frame_types;
+} smp_frame_type_t;
+
+typedef enum smp_function {
+ SMP_FUNC_REPORT_GENERAL = 0x00,
+ SMP_FUNC_REPORT_MANUFACTURER_INFO = 0x01,
+ SMP_FUNC_READ_GPIO_REGISTER = 0x02,
+ SMP_FUNC_REPORT_SELF_CONFIG_STATUS = 0x03,
+ SMP_FUNC_REPORT_ZONE_PERM_TABLE = 0x04,
+ SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD = 0x05,
+ SMP_FUNC_REPORT_BROADCAST = 0x06,
+ SMP_FUNC_DISCOVER = 0x10,
+ SMP_FUNC_REPORT_PHY_ERROR_LOG = 0x11,
+ SMP_FUNC_REPORT_PHY_SATA = 0x12,
+ SMP_FUNC_REPORT_ROUTE_INFO = 0x13,
+ SMP_FUNC_REPORT_PHY_EVENT = 0x14,
+ SMP_FUNC_DISCOVER_LIST = 0x20,
+ SMP_FUNC_REPORT_PHY_EVENT_LIST = 0x21,
+ SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST = 0x22,
+ SMP_FUNC_CONFIG_GENERAL = 0x80,
+ SMP_FUNC_ENABLE_DISABLE_ZONING = 0x81,
+ SMP_FUNC_WRITE_GPIO_REGISTER = 0x82,
+ SMP_FUNC_ZONED_BROADCAST = 0x85,
+ SMP_FUNC_ZONE_LOCK = 0x86,
+ SMP_FUNC_ZONE_ACTIVATE = 0x87,
+ SMP_FUNC_ZONE_UNLOCK = 0x88,
+ SMP_FUNC_CONFIG_ZONE_MANAGER_PASSWORD = 0x89,
+ SMP_FUNC_CONFIG_ZONE_PHY_INFO = 0x8A,
+ SMP_FUNC_CONFIG_ZONE_PERM_TABLE = 0x8B,
+ SMP_FUNC_CONFIG_ROUTE_INFO = 0x90,
+ SMP_FUNC_PHY_CONTROL = 0x91,
+ SMP_FUNC_PHY_TEST_FUNCTION = 0x92,
+ SMP_FUNC_CONFIG_PHY_EVENT = 0x93
+} smp_function_t;
-typedef enum {
- SMP_REPORT_GENERAL = 0x00,
- SMP_REPORT_MANUFACTURER_INFO = 0x01,
- SMP_DISCOVER = 0x10,
- SMP_REPORT_PHY_ERROR_LOG = 0x11,
- SMP_PHY_SATA = 0x12,
- SMP_REPORT_ROUTE_INFORMATION = 0x13,
- SMP_CONFIG_ROUTE_INFORMATION = 0x90,
- SMP_PHY_CONTROL = 0x91,
- SMP_PHY_TEST_FUNCTION = 0x92
-} smp_func_types;
+typedef enum smp_result {
+ SMP_RES_FUNCTION_ACCEPTED = 0x00,
+ SMP_RES_UNKNOWN_FUNCTION = 0x01,
+ SMP_RES_FUNCTION_FAILED = 0x02,
+ SMP_RES_INVALID_REQUEST_FRAME_LENGTH = 0x03,
+ SMP_RES_INVALID_EXPANDER_CHANGE_COUNT = 0x04,
+ SMP_RES_BUSY = 0x05,
+ SMP_RES_INCOMPLETE_DESCRIPTOR_LIST = 0x06,
+ SMP_RES_PHY_DOES_NOT_EXIST = 0x10,
+ SMP_RES_INDEX_DOES_NOT_EXIST = 0x11,
+ SMP_RES_PHY_DOES_NOT_SUPPORT_SATA = 0x12,
+ SMP_RES_UNKNOWN_PHY_OPERATION = 0x13,
+ SMP_RES_UNKNOWN_PHY_TEST_FUNCTION = 0x14,
+ SMP_RES_PHY_TEST_IN_PROGRESS = 0x15,
+ SMP_RES_PHY_VACANT = 0x16,
+ SMP_RES_UNKNOWN_PHY_EVENT_SOURCE = 0x17,
+ SMP_RES_UNKNOWN_DESCRIPTOR_TYPE = 0x18,
+ SMP_RES_UNKNOWN_PHY_FILTER = 0x19,
+ SMP_RES_AFFILIATION_VIOLATION = 0x1A,
+ SMP_RES_ZONE_VIOLATION = 0x20,
+ SMP_RES_NO_MANAGEMENT_ACCESS_RIGHTS = 0x21,
+ SMP_RES_UNKNOWN_ENABLE_DISABLE_ZONING = 0x22,
+ SMP_RES_ZONE_LOCK_VIOLATION = 0x23,
+ SMP_RES_NOT_ACTIVATED = 0x24,
+ SMP_RES_ZONE_GROUP_OUT_OF_RANGE = 0x25,
+ SMP_RES_NO_PHYSICAL_PRESENCE = 0x26,
+ SMP_RES_SAVING_NOT_SUPPORTED = 0x27,
+ SMP_RES_SOURCE_ZONE_GROUP_DNE = 0x28,
+ SMP_RES_NONE = -1
+} smp_result_t;
+
+#pragma pack(1)
/*
- * The reqsize and rspsize in usmp_req and usmp_rsp are reserved in
- * SAS v1.1, and the fields should be zero if target device is SAS v1.1
- * compliant.
+ * SAS-2 10.4.3.2 request frame format
*/
+typedef struct smp_request_frame {
+ uint8_t srf_frame_type;
+ uint8_t srf_function;
+ uint8_t srf_allocated_response_len; /* reserved in SAS-1 */
+ uint8_t srf_request_len;
+ uint8_t srf_data[1];
+} smp_request_frame_t;
-#pragma pack(1)
-typedef struct usmp_req {
- uint8_t smpo_frametype;
- uint8_t smpo_function;
- uint8_t smpo_reserved;
- uint8_t smpo_reqsize;
- uint8_t smpo_msgframe[1];
-} usmp_req_t;
-
-typedef struct usmp_rsp {
- uint8_t smpi_frametype;
- uint8_t smpi_function;
- uint8_t smpi_result;
- uint8_t smpi_rspsize;
- uint8_t smpi_msgframe[1];
-} usmp_rsp_t;
-
-struct smp_crc {
- uint8_t code[4];
-};
-
-struct smp_report_general_req {
- uint8_t frametype;
- uint8_t function;
- uint8_t reserved_byte2;
- uint8_t reqsize;
- struct smp_crc crc;
-};
-
-struct smp_report_general_rsp {
- uint8_t frametype;
- uint8_t function;
- uint8_t result;
- uint8_t rspsize;
- uint8_t expand_change_count1;
- uint8_t expand_change_count0;
- uint8_t expand_route_index1;
- uint8_t expand_route_index0;
- uint8_t reserved_byte8;
- uint8_t num_of_phy;
+/*
+ * SAS-2 10.4.3.3 response frame format
+ */
+typedef struct smp_response_frame {
+ uint8_t srf_frame_type;
+ uint8_t srf_function;
+ uint8_t srf_result;
+ uint8_t srf_response_len; /* reserved in SAS-1 */
+ uint8_t srf_data[1];
+} smp_response_frame_t;
+
+typedef uint8_t smp_crc_t[4];
+
+#ifdef offsetof
+#define SMP_REQ_MINLEN \
+ (offsetof(smp_request_frame_t, srf_data[0]) + sizeof (smp_crc_t))
+#define SMP_RESP_MINLEN \
+ (offsetof(smp_response_frame_t, srf_data[0]) + sizeof (smp_crc_t))
+#endif /* offsetof */
+
+/*
+ * SAS-2 10.4.3.4 REPORT GENERAL (no additional request bytes)
+ */
+typedef struct smp_report_general_resp {
+ uint16_t srgr_exp_change_count;
+ uint16_t srgr_exp_route_indexes;
+ DECL_BITFIELD2(
+ _reserved1 :7,
+ srgr_long_response :1);
+ uint8_t srgr_number_of_phys;
+ DECL_BITFIELD7(
+ srgr_externally_configurable_route_table :1,
+ srgr_configuring :1,
+ srgr_configures_others :1,
+ srgr_open_reject_retry_supported :1,
+ srgr_stp_continue_awt :1,
+ _reserved2 :2,
+ srgr_table_to_table_supported :1);
+ uint8_t _reserved3;
+ uint64_t srgr_enclosure_logical_identifier;
+ uint8_t _reserved4[8];
+ uint8_t _reserved5[2];
+ uint16_t srgr_stp_bus_inactivity_time_limit;
+ uint16_t srgr_stp_maximum_connect_time_limit;
+ uint16_t srgr_stp_smp_nexus_loss_time;
+ DECL_BITFIELD7(
+ srgr_zoning_enabled :1,
+ srgr_zoning_supported :1,
+ srgr_physical_presence_asserted :1,
+ srgr_physical_presence_supported :1,
+ srgr_zone_locked :1,
+ _reserved6 :1,
+ srgr_number_of_zone_grps :2);
+ DECL_BITFIELD6(
+ srgr_saving_zoning_enabled_supported :1,
+ srgr_saving_zone_perm_table_supported :1,
+ srgr_saving_zone_phy_info_supported :1,
+ srgr_saving_zone_mgr_password_supported :1,
+ srgr_saving :1,
+ _reserved7 :4);
+ uint16_t srgr_max_routed_sas_addrs;
+ uint64_t srgr_active_zm_sas_addr;
+ uint16_t srgr_zone_lock_inactivity_limit;
+ uint8_t _reserved8[2];
+ uint8_t _reserved9;
+ uint8_t srgr_first_encl_conn_elem_idx;
+ uint8_t srgr_number_encl_conn_elem_idxs;
+ uint8_t _reserved10;
+ DECL_BITFIELD2(
+ _reserved11 :7,
+ srgr_reduced_functionality :1);
+ uint8_t srgr_time_to_reduced_functionality;
+ uint8_t srgr_initial_time_to_reduced_functionality;
+ uint8_t srgr_max_reduced_functionality_time;
+ uint16_t srgr_last_self_conf_status_descr_idx;
+ uint16_t srgr_max_stored_self_config_status_descrs;
+ uint16_t srgr_last_phy_event_list_descr_idx;
+ uint16_t srgr_max_stored_phy_event_list_descrs;
+ uint16_t srgr_stp_reject_to_open_limit;
+ uint8_t _reserved12[2];
+} smp_report_general_resp_t;
+
+typedef enum smp_n_zone_grps {
+ SMP_ZONE_GROUPS_128 = 0x0,
+ SMP_ZONE_GROUPS_256 = 0x1
+} smp_n_zone_grps_t;
+
+/*
+ * SAS-2 10.4.3.5 REPORT MANUFACTURER INFORMATION (no additional request bytes)
+ */
+typedef struct smp_report_manufacturer_info_resp {
+ uint16_t srmir_exp_change_count;
+ uint8_t _reserved1[2];
+ DECL_BITFIELD2(
+ srmir_sas_1_1_format :1,
+ _reserved2 :7);
+ uint8_t _reserved3[3];
+ char srmir_vendor_identification[8];
+ char srmir_product_identification[16];
+ char srmir_product_revision_level[4];
+ char srmir_component_vendor_identification[8];
+ uint16_t srmir_component_id;
+ uint8_t srmir_component_revision_level;
+ uint8_t _reserved4;
+ uint8_t srmir_vs_52[8];
+} smp_report_manufacturer_info_resp_t;
+
+/*
+ * SAS-2 10.4.3.6 REPORT SELF_CONFIGURATION STATUS
+ */
+typedef struct smp_report_self_config_status_req {
+ uint8_t _reserved1[2];
+ uint16_t srscsr_starting_self_config_status_descr_idx;
+} smp_report_self_config_status_req_t;
+
+typedef struct smp_report_self_config_status_resp {
+ uint16_t srscsr_exp_change_count;
+ uint16_t srscsr_starting_self_config_status_descr_idx;
+ uint16_t srscsr_number_self_config_status_descrs;
+ uint16_t srscsr_last_self_config_status_descr_idx;
+ uint8_t srscsr_self_config_status_descr_len;
+ uint8_t _reserved1[3];
+ uint8_t srscsr_descrs[1];
+} smp_report_self_config_status_resp_t;
+
+typedef struct smp_self_config_status_descr {
+ uint8_t sscsd_status_type;
+ DECL_BITFIELD2(
+ sscsd_final :1,
+ _reserved1 :7);
+ uint8_t _reserved2;
+ uint8_t sscsd_phy_identifier;
+ uint8_t _reserved3[4];
+ uint64_t sscsd_sas_addr;
+} smp_self_config_status_descr_t;
+
+typedef enum smp_self_config_status_type {
+ SMP_SCST_NONSPECIFIC_ERROR = 0x01,
+ SMP_SCST_CONNECTION = 0x02,
+ SMP_SCST_ROUTE_TABLE_FULL = 0x03,
+ SMP_SCST_NOMEM = 0x04,
+ SMP_SCST_PHY_LAYER_ERROR = 0x20,
+ SMP_SCST_LOST_SYNC = 0x21,
+ SMP_SCST_LINK_LAYER_ERROR = 0x40,
+ SMP_SCST_OPEN_TIMEOUT = 0x41,
+ SMP_SCST_ABANDON_OPEN_REJECT = 0x42,
+ SMP_SCST_RETRY_OPEN_REJECTS = 0x43,
+ SMP_SCST_NEXUS_LOSS = 0x44,
+ SMP_SCST_BREAK = 0x45,
+ SMP_SCST_CRC_ERROR = 0x46,
+ SMP_SCST_PORT_LAYER_ERROR = 0x60,
+ SMP_SCST_RESPONSE_TIMEOUT = 0x61,
+ SMP_SCST_TRANSPORT_LAYER_ERROR = 0x80,
+ SMP_SCST_APP_LAYER_ERROR = 0xA0,
+ SMP_SCST_RESPONSE_TOO_SHORT = 0xA1,
+ SMP_SCST_UNSUPPORTED_VALUES = 0xA2,
+ SMP_SCST_INCONSISTENT = 0xA3,
+ SMP_SCST_CONFIGURING = 0xA4
+} smp_self_config_status_type_t;
+
+/*
+ * SAS-2 10.4.3.7 REPORT ZONE PERMISSION TABLE
+ */
+typedef struct smp_report_zone_perm_table_req {
+ DECL_BITFIELD2(
+ srzptr_report_type :2,
+ _reserved1 :6);
+ uint8_t _reserved2;
+ uint8_t srzptr_starting_src_zone_grp;
+ uint8_t srzptr_max_zone_perm_descrs;
+} smp_report_zone_perm_table_req_t;
+
+typedef enum smp_zone_perm_table_report_type {
+ SMP_ZPTRT_CURRENT = 0x0,
+ SMP_ZPTRT_SHADOW = 0x1,
+ SMP_ZPTRT_SAVED = 0x2,
+ SMP_ZPTRT_DEFAULT = 0x3
+} smp_zone_perm_table_report_type_t;
+
+typedef struct smp_report_zone_perm_table_resp {
+ uint16_t srzptr_exp_change_count;
DECL_BITFIELD3(
- crt :1,
- configuring :1,
- reserved_byte10 :6);
- uint8_t reserved_byte11;
- uint64_t identifier;
- uint8_t reserved_byte20[8];
- struct smp_crc crc;
-};
+ srzptr_report_type :2,
+ _reserved1 :5,
+ srzptr_zone_locked :1);
+ DECL_BITFIELD2(
+ _reserved2 :6,
+ srzptr_number_zone_grps :2);
+ uint8_t _reserved3[6];
+ uint8_t srzptr_starting_src_zone_grp;
+ uint8_t srzptr_number_zone_perm_descrs;
+ uint8_t srzptr_descrs[1];
+} smp_report_zone_perm_table_resp_t;
+
+typedef uint8_t smp_zone_perm_descr128_t[16];
+typedef uint8_t smp_zone_perm_descr256_t[32];
+
+#define SMP_ZONE_PERM_BIT128(__d, __z) \
+ ((__d)[15 - ((__z) >> 3)] & (1 << ((__z) & 7)))
+
+#define SMP_ZONE_PERM_SET128(__d, __z) \
+ ((__d)[15 - ((__z) >> 3)] |= (1 << ((__z) & 7)))
+
+#define SMP_ZONE_PERM_CLR128(__d, __z) \
+ ((__d)[15 - ((__z) >> 3)] &= ~(1 << ((__z) & 7)))
+
+#define SMP_ZONE_PERM_BIT256(__d, __z) \
+ ((__d)[31 - ((__z) >> 3)] & (1 << ((__z) & 7)))
+
+#define SMP_ZONE_PERM_SET256(__d, __z) \
+ ((__d)[31 - ((__z) >> 3)] |= (1 << ((__z) & 7)))
+
+#define SMP_ZONE_PERM_CLR256(__d, __z) \
+ ((__d)[31 - ((__z) >> 3)] &= ~(1 << ((__z) & 7)))
+
+/*
+ * SAS-2 10.4.3.8 REPORT ZONE MANAGER PASSWORD (no additional request bytes)
+ */
+typedef struct smp_report_zone_mgr_password_resp {
+ uint16_t srzmpr_exp_change_count;
+ uint8_t _reserved1[2];
+ uint8_t srzmpr_zone_mgr_password[32];
+} smp_report_zone_mgr_password_resp_t;
+
+/*
+ * SAS-2 10.4.3.9 REPORT BROADCAST
+ */
+typedef struct smp_report_broadcast_req {
+ DECL_BITFIELD2(
+ srbr_broadcast_type :4,
+ _reserved1 :4);
+ uint8_t _reserved2[3];
+} smp_report_broadcast_req_t;
+
+typedef enum smp_broadcast_type {
+ SMP_BROADCAST_CHANGE = 0x0,
+ SMP_BROADCAST_RESERVED_CHANGE_0 = 0x1,
+ SMP_BROADCAST_RESERVED_CHANGE_1 = 0x2,
+ SMP_BROADCAST_SES = 0x3,
+ SMP_BROADCAST_EXPANDER = 0x4,
+ SMP_BROADCAST_ASYNC_EVENT = 0x5,
+ SMP_BROADCAST_RESERVED_3 = 0x6,
+ SMP_BROADCAST_RESERVED_4 = 0x7,
+ SMP_BROADCAST_ZONE_ACTIVATE = 0x8
+} smp_broadcast_type_t;
+
+typedef struct smp_broadcast_descr {
+ DECL_BITFIELD2(
+ sbd_broadcast_type :4,
+ _reserved1 :4);
+ uint8_t sbd_phy_identifier;
+ DECL_BITFIELD2(
+ sbd_broadcast_reason :4,
+ _reserved2 :4);
+ uint16_t sbd_broadcast_count;
+ uint8_t _reserved3[10];
+} smp_broadcast_descr_t;
+
+typedef struct smp_report_broadcast_resp {
+ uint16_t srbr_exp_change_count;
+ DECL_BITFIELD2(
+ srbr_broadcast_type :4,
+ _reserved1 :4);
+ uint8_t srbr_number_broadcast_descrs;
+ smp_broadcast_descr_t srbr_descrs[1];
+} smp_report_broadcast_resp_t;
+
+/*
+ * SAS-2 10.4.3.10 DISCOVER
+ */
+typedef struct smp_discover_req {
+ uint8_t _reserved1[4];
+ DECL_BITFIELD2(
+ sdr_ignore_zone_grp :1,
+ _reserved2 :7);
+ uint8_t sdr_phy_identifier;
+ uint8_t _reserved3[2];
+} smp_discover_req_t;
+
+typedef struct smp_snw3_phy_cap {
+ DECL_BITFIELD4(
+ sspc_requested_logical_link_rate :4, /* smp_link_rate_t */
+ _reserved1 :2,
+ sspc_tx_ssc_type :1,
+ sspc_start :1);
+ DECL_BITFIELD7(
+ _reserved2 :2,
+ sspc_g3_ssc :1,
+ sspc_g3_no_ssc :1,
+ sspc_g2_ssc :1,
+ sspc_g2_no_ssc :1,
+ sspc_g1_ssc :1,
+ sspc_g1_no_ssc :1);
+ uint8_t _reserved3;
+ DECL_BITFIELD2(
+ sspc_parity :1,
+ _reserved4 :7);
+} smp_snw3_phy_cap_t;
+
+typedef struct smp_discover_resp {
+ uint16_t sdr_exp_change_count;
+ uint8_t _reserved1[3];
+ uint8_t sdr_phy_identifier;
+ uint8_t _reserved2[2];
+ DECL_BITFIELD3(
+ sdr_attached_reason :4,
+ sdr_attached_device_type :3,
+ _reserved3 :1);
+ DECL_BITFIELD2(
+ sdr_negotiated_logical_link_rate :4, /* smp_link_rate_t */
+ _reserved4 :4);
+ DECL_BITFIELD5(
+ sdr_attached_sata_host :1,
+ sdr_attached_smp_initiator :1,
+ sdr_attached_stp_initiator :1,
+ sdr_attached_ssp_initiator :1,
+ _reserved5 :4);
+ DECL_BITFIELD6(
+ sdr_attached_sata_device :1,
+ sdr_attached_smp_target :1,
+ sdr_attached_stp_target :1,
+ sdr_attached_ssp_target :1,
+ _reserved6 :3,
+ sdr_attached_sata_port_selector :1);
+ uint64_t sdr_sas_addr;
+ uint64_t sdr_attached_sas_addr;
+ uint8_t sdr_attached_phy_identifier;
+ DECL_BITFIELD4(
+ sdr_attached_break_reply_capable :1,
+ sdr_attached_requested_inside_zpsds :1,
+ sdr_attached_inside_zpsds_persistent :1,
+ _reserved7 :5);
+ uint8_t _reserved8[6];
+ DECL_BITFIELD2(
+ sdr_hw_min_phys_link_rate :4, /* smp_link_rate_t */
+ sdr_prog_min_phys_link_rate :4); /* smp_link_rate_t */
+ DECL_BITFIELD2(
+ sdr_hw_max_phys_link_rate :4, /* smp_link_rate_t */
+ sdr_prog_max_phys_link_rate :4); /* smp_link_rate_t */
+ uint8_t sdr_phy_change_count;
+ DECL_BITFIELD3(
+ sdr_partial_pwy_timeout :4,
+ _reserved9 :3,
+ sdr_virtual_phy :1);
+ DECL_BITFIELD2(
+ sdr_routing_attr :4, /* smp_routing_attr_t */
+ _reserved10 :4);
+ DECL_BITFIELD2(
+ sdr_connector_type :7,
+ _reserved11 :1);
+ uint8_t sdr_connector_element_index;
+ uint8_t sdr_connector_physical_link;
+ uint8_t _reserved12[2];
+ uint8_t sdr_vendor[2];
+ uint64_t sdr_attached_device_name;
+ DECL_BITFIELD8(
+ sdr_zoning_enabled :1,
+ sdr_inside_zpsds :1,
+ sdr_zone_group_persistent :1,
+ _reserved13 :1,
+ sdr_requested_inside_zpsds :1,
+ sdr_inside_zpsds_persistent :1,
+ sdr_requested_inside_zpsds_changed_by_exp :1,
+ _reserved14 :1);
+ uint8_t _reserved15[2];
+ uint8_t sdr_zone_group;
+ uint8_t sdr_self_config_status;
+ uint8_t sdr_self_config_levels_completed;
+ uint8_t _reserved16[2];
+ uint64_t sdr_self_config_sas_addr;
+ smp_snw3_phy_cap_t sdr_prog_phy_cap;
+ smp_snw3_phy_cap_t sdr_current_phy_cap;
+ smp_snw3_phy_cap_t sdr_attached_phy_cap;
+ uint8_t _reserved17[6];
+ DECL_BITFIELD2(
+ sdr_negotiated_phys_link_rate :4, /* smp_link_rate_t */
+ sdr_reason :4);
+ DECL_BITFIELD3(
+ sdr_hw_muxing_supported :1,
+ sdr_negotiated_ssc :1,
+ _reserved18 :6);
+ DECL_BITFIELD7(
+ sdr_default_zoning_enabled :1,
+ _reserved19 :1,
+ sdr_default_zone_group_persistent :1,
+ _reserved20 :1,
+ sdr_default_requested_inside_zpsds :1,
+ sdr_default_inside_zpsds_persistent :1,
+ _reserved21 :2);
+ uint8_t _reserved22[2];
+ uint8_t sdr_default_zone_group;
+ DECL_BITFIELD7(
+ sdr_saved_zoning_enabled :1,
+ _reserved23 :1,
+ sdr_saved_zone_group_persistent :1,
+ _reserved24 :1,
+ sdr_saved_requested_inside_zpsds :1,
+ sdr_saved_inside_zpsds_persistent :1,
+ _reserved25 :2);
+ uint8_t _reserved26[2];
+ uint8_t saved_zone_group;
+ DECL_BITFIELD6(
+ _reserved27 :2,
+ sdr_shadow_zone_group_persistent :1,
+ _reserved28 :1,
+ sdr_shadow_requested_inside_zpsds :1,
+ sdr_shadow_inside_zpsds_persistent :1,
+ _reserved29 :2);
+ uint8_t _reserved30[2];
+ uint8_t sdr_shadow_zone_group;
+} smp_discover_resp_t;
+
+typedef enum smp_link_rate {
+ SMP_LINK_RATE_NO_CHANGE = 0x0,
+ SMP_LINK_RATE_DISABLED = 0x1,
+ SMP_LINK_RATE_RESET_PROBLEM = 0x2,
+ SMP_LINK_RATE_SPINUP_HOLD = 0x3,
+ SMP_LINK_RATE_PORT_SELECTOR = 0x4,
+ SMP_LINK_RATE_RESET = 0x5,
+ SMP_LINK_RATE_UNSUPPORTED = 0x6,
+ SMP_LINK_RATE_1_5 = 0x8,
+ SMP_LINK_RATE_3 = 0x9,
+ SMP_LINK_RATE_6 = 0xA
+} smp_link_rate_t;
+
+typedef enum smp_device_type {
+ SMP_DEV_NONE = 0x0,
+ SMP_DEV_SAS_SATA = 0x1,
+ SMP_DEV_EXPANDER = 0x2,
+ SMP_DEV_EXPANDER_OLD = 0x3
+} smp_device_type_t;
+
+typedef enum smp_routing_attr {
+ SMP_ROUTING_DIRECT = 0x0,
+ SMP_ROUTING_SUBTRACTIVE = 0x1,
+ SMP_ROUTING_TABLE = 0x2
+} smp_routing_attr_t;
+
+/*
+ * SAS-2 10.4.3.11 REPORT PHY ERROR LOG
+ */
+typedef struct smp_report_phy_error_log_req {
+ uint8_t _reserved1[5];
+ uint8_t srpelr_phy_identifier;
+ uint8_t _reserved2[2];
+} smp_report_phy_error_log_req_t;
+
+typedef struct smp_report_phy_error_log_resp {
+ uint16_t srpelr_exp_change_count;
+ uint8_t _reserved1[3];
+ uint8_t srpelr_phy_identifier;
+ uint8_t _reserved2[2];
+ uint32_t srpelr_invalid_dword_count;
+ uint32_t srpelr_running_disparity_error_count;
+ uint32_t srpelr_loss_dword_sync_count;
+ uint32_t srpelr_phy_reset_problem_count;
+} smp_report_phy_error_log_resp_t;
+
+/*
+ * SAS-2 10.4.3.12 REPORT PHY SATA
+ */
+typedef struct smp_report_phy_sata_req {
+ uint8_t _reserved1[5];
+ uint8_t srpsr_phy_identifier;
+ uint8_t srpsr_affiliation_context;
+ uint8_t _reserved2;
+} smp_report_phy_sata_req_t;
+
+typedef struct smp_report_phy_sata_resp {
+ uint16_t srpsr_exp_change_count;
+ uint8_t _reserved1[3];
+ uint8_t srpsr_phy_identifier;
+ uint8_t _reserved2;
+ DECL_BITFIELD4(
+ srpsr_affiliation_valid :1,
+ srpsr_affiliations_supported :1,
+ srpsr_stp_nexus_loss :1,
+ _reserved3 :5);
+ uint8_t _reserved4[4];
+ uint64_t srpsr_stp_sas_addr;
+ uint8_t srpsr_register_device_host_fis[20];
+ uint8_t _reserved5[4];
+ uint64_t srpsr_affiliated_stp_init_sas_addr;
+ uint64_t srpsr_stp_nexus_loss_sas_addr;
+ uint8_t _reserved6;
+ uint8_t srpsr_affiliation_context;
+ uint8_t srpsr_current_affiliation_contexts;
+ uint8_t srpsr_max_affiliation_contexts;
+} smp_report_phy_sata_resp_t;
+
+/*
+ * SAS-2 10.4.3.13 REPORT ROUTE INFORMATION
+ */
+typedef struct smp_report_route_info_req {
+ uint8_t _reserved1[2];
+ uint16_t srrir_exp_route_index;
+ uint8_t _reserved2;
+ uint8_t srrir_phy_identifier;
+ uint8_t _reserved3[2];
+} smp_report_route_info_req_t;
+
+typedef struct smp_report_route_info_resp {
+ uint16_t srrir_exp_change_count;
+ uint16_t srrir_exp_route_index;
+ uint8_t _reserved1;
+ uint8_t srrir_phy_identifier;
+ uint8_t _reserved2[2];
+ DECL_BITFIELD2(
+ _reserved3 :7,
+ srrir_exp_route_entry_disabled :1);
+ uint8_t _reserved4[3];
+ uint64_t srrir_routed_sas_addr;
+ uint8_t _reserved5[16];
+} smp_report_route_info_resp_t;
+
+/*
+ * SAS-2 10.4.3.14 SAS-2 REPORT PHY EVENT
+ */
+typedef struct smp_report_phy_event_req {
+ uint8_t _reserved1;
+ uint8_t _reserved2[4];
+ uint8_t srper_phy_identifier;
+ uint8_t _reserved3[2];
+} smp_report_phy_event_req_t;
+
+typedef struct smp_phy_event_report_descr {
+ uint8_t _reserved1[3];
+ uint8_t sped_phy_event_source;
+ uint32_t sped_phy_event;
+ uint32_t sped_peak_detector_threshold;
+} smp_phy_event_report_descr_t;
+
+typedef struct smp_report_phy_event_resp {
+ uint16_t srper_exp_change_count;
+ uint8_t _reserved1[3];
+ uint8_t srper_phy_identifier;
+ uint8_t _reserved2[5];
+ uint8_t srper_n_phy_event_descrs;
+ smp_phy_event_report_descr_t srper_phy_event_descrs[1];
+} smp_report_phy_event_resp_t;
+
+/*
+ * SAS-2 10.4.3.15 SAS-2 DISCOVER LIST
+ */
+typedef struct smp_discover_list_req {
+ uint8_t _reserved1[4];
+ uint8_t sdlr_starting_phy_identifier;
+ uint8_t sdlr_max_descrs;
+ DECL_BITFIELD3(
+ sdlr_phy_filter :4,
+ _reserved2 :3,
+ sdlr_ignore_zone_group :1);
+ DECL_BITFIELD2(
+ sdlr_descr_type :4,
+ _reserved3 :4);
+ uint8_t _reserved4[4];
+ uint8_t sdlr_vendor[12];
+} smp_discover_list_req_t;
+
+typedef struct smp_discover_short_descr {
+ uint8_t sdsd_phy_identifier;
+ uint8_t sdsd_function_result;
+ DECL_BITFIELD3(
+ sdsd_attached_reason :4,
+ sdsd_attached_device_type :3,
+ _restricted1 :1);
+ DECL_BITFIELD2(
+ sdsd_negotiated_logical_link_rate :4, /* smp_link_rate_t */
+ _restricted2 :4);
+ DECL_BITFIELD5(
+ sdsd_attached_sata_host :1,
+ sdsd_attached_smp_initiator :1,
+ sdsd_attached_stp_initiator :1,
+ sdsd_attached_ssp_initiator :1,
+ _restricted3 :4);
+ DECL_BITFIELD6(
+ sdsd_attached_sata_device :1,
+ sdsd_attached_smp_target :1,
+ sdsd_attached_stp_target :1,
+ sdsd_attached_ssp_target :1,
+ _restricted4 :3,
+ sdsd_attached_sata_port_selector :1);
+ DECL_BITFIELD3(
+ sdsd_routing_attribute :4, /* smp_routing_attr_t */
+ _reserved1 :3,
+ sdsd_virtual_phy :1);
+ DECL_BITFIELD2(
+ _reserved2 :4,
+ sdsd_reason :4);
+ uint8_t sdsd_zone_group;
+ DECL_BITFIELD7(
+ _reserved3 :1,
+ sdsd_inside_zpsds :1,
+ sdsd_zone_group_persistent :1,
+ _reserved4 :1,
+ sdsd_requested_insize_zpsds :1,
+ sdsd_inside_zpsds_persistent :1,
+ _restricted5 :2);
+ uint8_t sdsd_attached_phy_identifier;
+ uint8_t sdsd_phy_change_count;
+ uint64_t sdsd_attached_sas_addr;
+ uint8_t _reserved5[4];
+} smp_discover_short_descr_t;
+
+typedef struct smp_discover_long_descr {
+ uint8_t _reserved1[2];
+ uint8_t sdld_function_result;
+ uint8_t _reserved2[1];
+ smp_discover_resp_t sdld_response;
+} smp_discover_long_descr_t;
+
+#define SMP_DISCOVER_RESP(_ld) \
+ (((smp_discover_long_descr_t *)(_ld))->sdld_function_result == \
+ SMP_FUNCTION_ACCEPTED ? \
+ &((smp_discover_long_descr_t *)(_ld))->sdld_response : \
+ NULL)
+
+typedef struct smp_discover_list_resp {
+ uint16_t sdlr_exp_change_count;
+ uint8_t _reserved1[2];
+ uint8_t sdlr_starting_phy_identifier;
+ uint8_t sdlr_n_descrs;
+ DECL_BITFIELD2(
+ sdlr_phy_filter :4,
+ _reserved2 :4);
+ DECL_BITFIELD2(
+ sdlr_descr_type :4,
+ _reserved3 :4);
+ uint8_t sdlr_descr_length;
+ uint8_t _reserved4[3];
+ DECL_BITFIELD5(
+ sdlr_externally_configurable_route_table :1,
+ sdlr_configuring :1,
+ _reserved5 :4,
+ sdlr_zoning_enabled :1,
+ sdlr_zoning_supported :1);
+ uint8_t _reserved6;
+ uint16_t sdlr_last_sc_status_descr_index;
+ uint16_t sdlr_last_phy_event_list_descr_index;
+ uint8_t _reserved7[10];
+ uint8_t sdlr_vendor[16];
+ uint8_t sdlr_descrs[1]; /* short or long format */
+} smp_discover_list_resp_t;
+
+/*
+ * SAS-2 10.4.3.16 REPORT PHY EVENT LIST
+ */
+typedef struct smp_report_phy_event_list_req {
+ uint8_t _reserved1[2];
+ uint16_t srpelr_starting_descr_index;
+} smp_report_phy_event_list_req_t;
+
+typedef struct smp_phy_event_list_descr {
+ uint8_t _reserved1[2];
+ uint8_t speld_phy_identifier;
+ uint8_t speld_phy_event_source;
+ uint32_t speld_phy_event;
+ uint32_t speld_peak_detector_threshold;
+} smp_phy_event_list_descr_t;
+
+typedef struct smp_report_phy_event_list_resp {
+ uint16_t srpelr_exp_change_count;
+ uint16_t srpelr_starting_descr_index;
+ uint16_t srpelr_last_descr_index;
+ uint8_t srpelr_phy_event_list_descr_length;
+ uint8_t _reserved1[3];
+ uint8_t srpelr_n_descrs;
+ smp_phy_event_list_descr_t srpelr_descrs[1];
+} smp_report_phy_event_list_resp_t;
+
+/*
+ * SAS-2 10.4.3.17 REPORT EXPANDER ROUTE TABLE LIST
+ */
+typedef struct smp_report_exp_route_table_list_req {
+ uint8_t _reserved1[4];
+ uint16_t srertlr_max_descrs;
+ uint16_t srertlr_starting_routed_sas_addr_index;
+ uint8_t _reserved2[7];
+ uint8_t srertlr_starting_phy_identifier;
+ uint8_t _reserved3[8];
+} smp_report_exp_route_table_list_req_t;
+
+typedef struct smp_route_table_descr {
+ uint64_t srtd_routed_sas_addr;
+ uint8_t srtd_phy_bitmap[6];
+ DECL_BITFIELD2(
+ _reserved1 :7,
+ srtd_zone_group_valid :1);
+ uint8_t srtd_zone_group;
+} smp_route_table_descr_t;
+
+#define SMP_ROUTE_PHY(_d, _s, _i) \
+ ((_d)->srtd_phy_bitmap[(48 - (_i) + (_s)) >> 3] & \
+ (1 << ((48 - (_i) + (_s)) & 7)))
+
+typedef struct smp_report_exp_route_table_list_resp {
+ uint16_t srertlr_exp_change_count;
+ uint16_t srertlr_route_table_change_count;
+ DECL_BITFIELD3(
+ _reserved1 :1,
+ srertlr_configuring :1,
+ _reserved2 :6);
+ uint8_t _reserved3;
+ uint16_t srertlr_n_descrs;
+ uint16_t srertlr_first_routed_sas_addr_index;
+ uint16_t srertlr_last_routed_sas_addr_index;
+ uint8_t _reserved4[3];
+ uint8_t srertlr_starting_phy_identifier;
+ uint8_t _reserved5[12];
+ smp_route_table_descr_t srertlr_descrs[1];
+} smp_report_exp_route_table_list_resp_t;
+
+/*
+ * SAS-2 10.4.3.18 CONFIGURE GENERAL (no additional response)
+ */
+typedef struct smp_config_general_req {
+ uint16_t scgr_expected_exp_change_count;
+ uint8_t _reserved1[2];
+ DECL_BITFIELD6(
+ scgr_update_stp_bus_inactivity :1,
+ scgr_update_stp_max_conn :1,
+ scgr_update_stp_smp_nexus_loss :1,
+ scgr_update_initial_time_to_reduced_functionality :1,
+ scgr_update_stp_reject_to_open :1,
+ _reserved2 :3);
+ uint8_t _reserved3;
+ uint16_t scgr_stp_bus_inactivity;
+ uint16_t scgr_stp_max_conn;
+ uint16_t scgr_stp_smp_nexus_loss;
+ uint8_t scgr_initial_time_to_reduced_functionality;
+ uint8_t _reserved4;
+ uint16_t scgr_stp_reject_to_open;
+} smp_config_general_req_t;
+
+/*
+ * SAS-2 10.4.3.19 ENABLE DISABLE ZONING (no additional response)
+ */
+typedef struct smp_enable_disable_zoning_req {
+ uint16_t sedzr_expected_exp_change_count;
+ DECL_BITFIELD2(
+ sedzr_save :2, /* smp_zoning_save_t */
+ _reserved1 :6);
+ uint8_t _reserved2;
+ DECL_BITFIELD2(
+ sedzr_enable_disable_zoning :2,
+ _reserved3 :6);
+ uint8_t _reserved4[3];
+} smp_enable_disable_zoning_req_t;
+
+typedef enum smp_zoning_save {
+ SMP_ZONING_SAVE_CURRENT = 0x0,
+ SMP_ZONING_SAVE_SAVED = 0x1,
+ SMP_ZONING_SAVE_BOTH_IF_SUPP = 0x2,
+ SMP_ZONING_SAVE_BOTH = 0x3
+} smp_zoning_save_t;
+
+typedef enum smp_zoning_enable_op {
+ SMP_ZONING_ENABLE_OP_NONE = 0x0,
+ SMP_ZONING_ENABLE_OP_ENABLE = 0x1,
+ SMP_ZONING_ENABLE_OP_DISABLE = 0x2
+} smp_zoning_enable_op_t;
+
+/*
+ * SAS-2 10.4.3.20 ZONED BROADCAST (no additional response)
+ */
+typedef struct smp_zoned_broadcast_req {
+ uint8_t _restricted1[2];
+ DECL_BITFIELD2(
+ szbr_broadcast_type :4,
+ _reserved :4);
+ uint8_t szbr_n_broadcast_source_zone_groups;
+ uint8_t szbr_broadcast_source_zone_groups[1];
+} smp_zoned_broadcast_req_t;
+
+/*
+ * SAS-2 10.4.3.21 ZONE LOCK
+ */
+typedef struct smp_zone_lock_req {
+ uint16_t szlr_expected_exp_change_count;
+ uint16_t szlr_zone_lock_inactivity_timeout;
+ uint8_t szlr_zone_manager_password[32];
+} smp_zone_lock_req_t;
+
+typedef struct smp_zone_lock_resp {
+ uint8_t _reserved1[4];
+ uint64_t szlr_active_zone_manager_sas_addr;
+} smp_zone_lock_resp_t;
+
+/*
+ * SAS-2 10.4.3.22 ZONE ACTIVATE (no additional response)
+ */
+typedef struct smp_zone_activate_req {
+ uint16_t szar_expected_exp_change_count;
+ uint8_t _reserved1[2];
+} smp_zone_activate_req_t;
+
+/*
+ * SAS-2 10.4.3.23 ZONE UNLOCK (no additional response)
+ */
+typedef struct smp_zone_unlock_req {
+ uint8_t _restricted1[2];
+ DECL_BITFIELD2(
+ szur_activate_required :1,
+ _reserved1 :7);
+ uint8_t _reserved2;
+} smp_zone_unlock_req_t;
+
+/*
+ * SAS-2 10.4.3.24 CONFIGURE ZONE MANAGER PASSWORD (no additional response)
+ */
+typedef struct smp_config_zone_manager_password_req {
+ uint16_t sczmpr_expected_exp_change_count;
+ DECL_BITFIELD2(
+ sczmpr_save :2, /* smp_zoning_save_t */
+ _reserved1 :6);
+ uint8_t _reserved2;
+ uint8_t sczmpr_zone_manager_password[32];
+ uint8_t sczmpr_new_zone_manager_password[32];
+} smp_config_zone_manager_password_req_t;
+
+/*
+ * SAS-2 10.4.3.25 CONFIGURE ZONE PHY INFORMATION (no additional response)
+ */
+typedef struct smp_zone_phy_config_descr {
+ uint8_t szpcd_phy_identifier;
+ DECL_BITFIELD6(
+ _reserved1 :2,
+ szpcd_zone_group_persistent :1,
+ _reserved2 :1,
+ szpcd_requested_inside_zpsds :1,
+ szpcd_inside_zpsds_persistent :1,
+ _reserved3 :2);
+ uint8_t _reserved4;
+ uint8_t szpcd_zone_group;
+} smp_zone_phy_config_descr_t;
+
+typedef struct smp_config_zone_phy_info_req {
+ uint16_t sczpir_expected_exp_change_count;
+ DECL_BITFIELD2(
+ sczpir_save :2, /* smp_zoning_save_t */
+ _reserved1 :6);
+ uint8_t sczpir_n_descrs;
+ smp_zone_phy_config_descr_t sczpir_descrs[1];
+} smp_config_zone_phy_info_req_t;
+
+/*
+ * SAS-2 10.4.3.26 CONFIGURE ZONE PERMISSION TABLE (no additional response)
+ */
+typedef struct smp_config_zone_perm_table_req {
+ uint16_t sczptr_expected_exp_change_count;
+ uint8_t sczptr_starting_source_zone_group;
+ uint8_t sczptr_n_descrs;
+ DECL_BITFIELD3(
+ sczptr_save :2, /* smp_zoning_save_t */
+ _reserved1 :4,
+ sczptr_n_zone_groups :2); /* smp_n_zone_grps_t */
+ uint8_t _reserved2[7];
+ uint8_t sczptr_descrs[1]; /* smp_zone_perm_descrXXX_t */
+} smp_config_zone_perm_table_req_t;
+
+/*
+ * SAS-2 10.4.3.27 CONFIGURE ROUTE INFORMATION (no additional response)
+ */
+typedef struct smp_config_route_info_req {
+ uint16_t scrir_expected_exp_change_count;
+ uint16_t scrir_exp_route_index;
+ uint8_t _reserved1;
+ uint8_t scrir_phy_identifier;
+ uint8_t _reserved2[2];
+ DECL_BITFIELD2(
+ _reserved3 :7,
+ scrir_disable_exp_route_entry :1);
+ uint8_t _reserved4[3];
+ uint64_t scrir_routed_sas_addr;
+ uint8_t _reserved5[16];
+} smp_config_route_info_req_t;
+
+/*
+ * SAS-2 10.4.3.28 PHY CONTROL (no additional response)
+ */
+typedef struct smp_phy_control_req {
+ uint16_t spcr_expected_exp_change_count;
+ uint8_t _reserved1[3];
+ uint8_t spcr_phy_identifier;
+ uint8_t spcr_phy_operation;
+ DECL_BITFIELD2(
+ spcr_update_partial_pwy_timeout :1,
+ _reserved2 :7);
+ uint8_t _reserved3[12];
+ uint64_t spcr_attached_device_name;
+ DECL_BITFIELD2(
+ _reserved4 :4,
+ spcr_prog_min_phys_link_rate :4); /* smp_link_rate_t */
+ DECL_BITFIELD2(
+ _reserved5 :4,
+ spcr_prog_max_phys_link_rate :4); /* smp_link_rate_t */
+ uint8_t _reserved6[2];
+ DECL_BITFIELD2(
+ spcr_partial_pwy_timeout :4,
+ _reserved7 :4);
+ uint8_t _reserved8[3];
+} smp_phy_control_req_t;
+
+typedef enum smp_phy_op {
+ SMP_PHY_OP_NOP = 0x00,
+ SMP_PHY_OP_LINK_RESET = 0x01,
+ SMP_PHY_OP_HARD_RESET = 0x02,
+ SMP_PHY_OP_DISABLE = 0x03,
+ SMP_PHY_OP_CLEAR_ERROR_LOG = 0x05,
+ SMP_PHY_OP_CLEAR_AFFILIATION = 0x06,
+ SMP_PHY_OP_TRANSMIT_SATA_PORT_SELECTION_SIGNAL = 0x07,
+ SMP_PHY_OP_CLEAR_STP_NEXUS_LOSS = 0x08,
+ SMP_PHY_OP_SET_ATTACHED_DEVICE_NAME = 0x09
+} smp_phy_op_t;
+
+/*
+ * SAS-2 10.4.3.29 PHY TEST FUNCTION (no additional response)
+ */
+typedef struct smp_phy_test_function_req {
+ uint16_t sptfr_expected_exp_change_count;
+ uint8_t _reserved1[3];
+ uint8_t sptfr_phy_identifier;
+ uint8_t sptfr_phy_test_function;
+ uint8_t sptfr_phy_test_pattern; /* smp_phy_test_function_t */
+ uint8_t _reserved2[3];
+ DECL_BITFIELD4(
+ sptfr_test_pattern_phys_link_rate :4, /* smp_link_rate_t */
+ sptfr_test_pattern_ssc :2,
+ sptfr_test_pattern_sata :1,
+ _reserved3 :1);
+ uint8_t _reserved4[3];
+ uint8_t sptfr_phy_test_pattern_dwords_ctl;
+ uint8_t sptfr_phy_test_pattern_dwords[8];
+ uint8_t _reserved5[12];
+} smp_phy_test_function_req_t;
+
+typedef enum smp_phy_test_function {
+ SMP_PHY_TEST_FN_STOP = 0x00,
+ SMP_PHY_TEST_FN_TRANSMIT_PATTERN = 0x01
+} smp_phy_test_function_t;
+
+/*
+ * SAS-2 10.4.3.30 CONFIGURE PHY EVENT (no additional response)
+ */
+typedef struct smp_phy_event_config_descr {
+ uint8_t _reserved1[3];
+ uint8_t specd_phy_event_source;
+ uint32_t specd_peak_value_detector_threshold;
+} smp_phy_event_config_descr_t;
+
+typedef struct smp_config_phy_event_req {
+ uint16_t scper_expected_exp_change_count;
+ DECL_BITFIELD2(
+ scper_clear_peaks :1,
+ _reserved1 :7);
+ uint8_t _reserved2[2];
+ uint8_t scper_phy_identifier;
+ uint8_t _reserved3;
+ uint8_t scper_n_descrs;
+ smp_phy_event_config_descr_t scper_descrs[1];
+} smp_config_phy_event_req_t;
+
#pragma pack()
#ifdef __cplusplus
}
#endif
-#endif /* _SYS_SCSI_IMPL_SMP_FRAME_H */
+#endif /* _SYS_SCSI_GENERIC_SMP_FRAMES_H */
diff --git a/usr/src/uts/common/sys/scsi/impl/sas_transport.h b/usr/src/uts/common/sys/scsi/impl/sas_transport.h
index a592fe6308..43d55c28ad 100644
--- a/usr/src/uts/common/sys/scsi/impl/sas_transport.h
+++ b/usr/src/uts/common/sys/scsi/impl/sas_transport.h
@@ -67,7 +67,8 @@ typedef struct smp_pkt {
size_t pkt_reqsize;
size_t pkt_rspsize;
int pkt_timeout;
- uchar_t pkt_reason; /* code from errno.h */
+ uchar_t pkt_reason; /* code from errno.h */
+ uchar_t pkt_will_retry; /* will retry on EAGAIN */
sas_addr_t *pkt_address;
} smp_pkt_t;
@@ -87,22 +88,234 @@ struct sas_hba_tran {
int (*tran_smp_start)(
struct smp_pkt *pkt);
+ int (*tran_smp_init)(
+ dev_info_t *self,
+ dev_info_t *child,
+ sas_hba_tran_t *tran,
+ smp_device_t *smp);
+
+ void (*tran_smp_free)(
+ dev_info_t *self,
+ dev_info_t *child,
+ sas_hba_tran_t *tran,
+ smp_device_t *smp);
};
-extern sas_hba_tran_t *sas_hba_tran_alloc(dev_info_t *dip, int flags);
+extern sas_hba_tran_t *sas_hba_tran_alloc(dev_info_t *dip);
extern int sas_hba_attach_setup(dev_info_t *dip, sas_hba_tran_t *smp);
extern int sas_hba_detach(dev_info_t *self);
extern void sas_hba_tran_free(sas_hba_tran_t *smp);
+extern int smp_hba_bus_config(dev_info_t *, char *, dev_info_t **);
+extern int smp_hba_bus_config_taddr(dev_info_t *, char *);
+
+
extern int sas_smp_transport(struct smp_pkt *pkt);
extern int sas_ifgetcap(struct sas_addr *ap, char *cap);
extern int sas_hba_probe_smp(struct smp_device *smp_devp);
extern int sas_hba_lookup_capstr(char *capstr);
+/*
+ * Phymap support
+ */
+typedef struct __sas_phymap sas_phymap_t;
+typedef enum { PHYMAP_MODE_SIMPLE } sas_phymap_mode_t;
+typedef void (*sas_phymap_activate_cb_t)
+ (void *phymap_priv, char *ua, void **ua_privp);
+typedef void (*sas_phymap_deactivate_cb_t)
+ (void *phymap_priv, char *ua, void *ua_priv);
+
+extern int sas_phymap_create(dev_info_t *hba_dip,
+ clock_t settle_us,
+ sas_phymap_mode_t mode,
+ void *mode_argument,
+ void *phymap_priv,
+ sas_phymap_activate_cb_t activate_cb,
+ sas_phymap_deactivate_cb_t deactivate_cb,
+ sas_phymap_t **phymapp);
+
+void sas_phymap_destroy(sas_phymap_t *phymap);
+
+extern int sas_phymap_phy_add(sas_phymap_t *phymap,
+ int phy,
+ uint64_t local_sas_address,
+ uint64_t remote_sas_address);
+
+extern int sas_phymap_phy_rem(sas_phymap_t *phymap,
+ int phy);
+
+extern char *sas_phymap_lookup_ua(sas_phymap_t *phymap,
+ uint64_t local_sas_address,
+ uint64_t remote_sas_address);
+
+extern void *sas_phymap_lookup_uapriv(sas_phymap_t *phymap,
+ char *ua);
+
+extern int sas_phymap_uahasphys(sas_phymap_t *phymap,
+ char *ua);
+
+typedef struct __sas_phymap_phys sas_phymap_phys_t;
+extern sas_phymap_phys_t *sas_phymap_ua2phys(sas_phymap_t *, char *ua);
+extern int sas_phymap_phys_next(sas_phymap_phys_t *);
+void sas_phymap_phys_free(sas_phymap_phys_t *);
+
+extern char *sas_phymap_phy2ua(sas_phymap_t *, int);
+void sas_phymap_ua_free(char *);
+
+
#endif /* defined(_KERNEL) */
+#define KSTAT_SAS_PHY_CLASS "SAS_phy_stat"
+
+/*
+ * Format of the ks_name field for SAS Phy Stat
+ *
+ * driver_name.initiator_port_SAS_address.initiator_port_instance_number.phyid
+ * Example: pmcs.5000c50000d756aa.2.0
+ *
+ * driver_name:
+ * driver name from di_driver_name() on SAS initiator port devinfo node.
+ * initiator_port_SAS_address:
+ * SAS address of the initiator port that phy stat is reported for.
+ * initiator_port_instance_number:
+ * instance number of the initiator port that phy stat is reported for.
+ * phyid:
+ * prop phyIdentifier under initiator port node.
+ */
+
+/* Port Protocol - kstat structure definition */
+
+typedef struct sas_port_protocol_stats {
+ kstat_named_t seconds_since_last_reset;
+ kstat_named_t input_requests;
+ kstat_named_t output_requests;
+ kstat_named_t control_requests;
+ kstat_named_t input_megabytes;
+ kstat_named_t output_megabytes;
+} sas_port_protocol_stats_t;
+
+/* Port - kstat structure definition */
+
+typedef struct sas_port_stats {
+ kstat_named_t seconds_since_last_reset;
+ kstat_named_t tx_frames;
+ kstat_named_t tx_words;
+ kstat_named_t rx_frames;
+ kstat_named_t rx_words;
+} sas_port_stats_t;
+
+/* PHY - kstat structure definition */
+
+typedef struct sas_phy_stats {
+ kstat_named_t seconds_since_last_reset;
+ kstat_named_t tx_frames;
+ kstat_named_t tx_words;
+ kstat_named_t rx_frames;
+ kstat_named_t rx_words;
+ kstat_named_t invalid_dword_count;
+ kstat_named_t running_disparity_error_count;
+ kstat_named_t loss_of_dword_sync_count;
+ kstat_named_t phy_reset_problem_count;
+} sas_phy_stats_t;
+
+
+/*
+ * Supported Protocol property
+ */
+#define SAS_PROTOCOL_SSP 0x00000001
+#define SAS_PROTOCOL_STP 0x00000010
+#define SAS_PROTOCOL_SMP 0x00000100
+#define SAS_PROTOCOL_SATA 0x00001000
+
+
+/*
+ * Definition - Negotiated Physical Link Rate
+ * Based on Table 288 (Section 10.4.3.10) of the spec (SAS-2 r-15), these
+ * constants represent "Negotiated physical link rate"
+ * (and implicitly the State of the phy).
+ */
+
+#define SAS_LINK_RATE_UNKNOWN 0x0 /* Phy is enabled. */
+ /* Speed is unknown */
+#define SAS_LINK_RATE_DISABLED 0x1 /* Phy is disabled. */
+ /* Speed is undefined */
+#define SAS_LINK_RATE_FAILED 0x2 /* Phy is enabled. */
+ /* Failed speed negotiation. */
+#define SAS_LINK_RATE_SATASPINUP 0x3 /* Phy is enabled. */
+ /* Detected a SATA device and */
+ /* entered the SATA Spinup hold */
+ /* state */
+#define SAS_LINK_RATE_SATAPORTSEL 0x4 /* Phy enabled. */
+ /* The phy is attached to a */
+ /* Port Selector (SATA-2.6). */
+#define SAS_LINK_RATE_RESET_IN_PROGRESS 0x5 /* Phy is enabled. */
+ /* Expander is performing SMP */
+ /* PHY CONTROL Link/Hard Reset */
+#define SAS_LINK_RATE_PHY_UNSUPPORTED 0x6 /* Phy is enabled. */
+ /* Unsupported phy settings */
+#define SAS_LINK_RATE_RESERVED 0x7 /* Undefined. Reserved. */
+#define SAS_LINK_RATE_1_5GBIT 0x8 /* Phy enabled at 1.5 GBit/sec */
+#define SAS_LINK_RATE_3GBIT 0x9 /* Phy enabled at 3 GBit/sec */
+#define SAS_LINK_RATE_6GBIT 0xA /* Phy enabled at 6 GBit/sec. */
+
+
+/*
+ * Definition - "phy-info" property
+ *
+ * The property is an nvlist_array that represents an array of the
+ * nvlists on a per HBA basis. The individual elements of the array
+ * (the nvlists) represent the following properties for each phy of the HBA
+ */
+#define SAS_PHY_INFO "phy-info" /* Phy property name */
+#define SAS_PHY_INFO_NVL "phy-info-nvl" /* NVL array name */
+
+#define SAS_PHY_ID "PhyIdentifier" /* DATA_TYPE_UINT8 */
+#define SAS_NEG_LINK_RATE "NegotiatedLinkRate" /* DATA_TYPE_INT8 */
+#define SAS_PROG_MIN_LINK_RATE "ProgrammedMinLinkRate" /* DATA_TYPE_INT8 */
+#define SAS_HW_MIN_LINK_RATE "HardwareMinLinkRate" /* DATA_TYPE_INT8 */
+#define SAS_PROG_MAX_LINK_RATE "ProgrammedMaxLinkRate" /* DATA_TYPE_INT8 */
+#define SAS_HW_MAX_LINK_RATE "HardwareMaxLinkRate" /* DATA_TYPE_INT8 */
+
+
+/*
+ * Event definitions
+ */
+/* Event Class */
+#define EC_HBA "EC_hba"
+
+/* Event Sub-Class */
+#define ESC_SAS_HBA_PORT_BROADCAST "ESC_sas_hba_port_broadcast"
+
+/* Event Types for above Subclass */
+#define SAS_PORT_BROADCAST_CHANGE "port_broadcast_change"
+#define SAS_PORT_BROADCAST_SES "port_broadcast_ses"
+#define SAS_PORT_BROADCAST_D24_0 "port_broadcast_d24_0"
+#define SAS_PORT_BROADCAST_D27_4 "port_broadcast_d27_4"
+#define SAS_PORT_BROADCAST_D01_4 "port_broadcast_d01_4"
+#define SAS_PORT_BROADCAST_D04_7 "port_broadcast_d04_7"
+#define SAS_PORT_BROADCAST_D16_7 "port_broadcast_d16_7"
+#define SAS_PORT_BROADCAST_D29_7 "port_broadcast_d29_7"
+
+/* Event Sub-Class */
+#define ESC_SAS_PHY_EVENT "ESC_sas_phy_event"
+
+/* Event Types for above Subclass */
+#define SAS_PHY_ONLINE "port_online"
+#define SAS_PHY_OFFLINE "port_offline"
+#define SAS_PHY_REMOVE "port_remove"
+
+/* Event Payload Names */
+#define SAS_DRV_INST "driver_instance"
+#define SAS_PORT_ADDR "port_address"
+#define SAS_DEVFS_PATH "devfs_path"
+#define SAS_EVENT_TYPE "event_type"
+#define SAS_LINK_RATE "link_rate"
+/* SAS_PHY_ID - Defined Above */
+
+
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/common/sys/scsi/impl/transport.h b/usr/src/uts/common/sys/scsi/impl/transport.h
index 77820c9f43..7a7bb66590 100644
--- a/usr/src/uts/common/sys/scsi/impl/transport.h
+++ b/usr/src/uts/common/sys/scsi/impl/transport.h
@@ -39,6 +39,12 @@ extern "C" {
#ifdef _KERNEL
/*
+ * Opaque handles to address maps
+ */
+typedef struct __scsi_iportmap scsi_hba_iportmap_t;
+typedef struct __scsi_tgtmap scsi_hba_tgtmap_t;
+
+/*
* SCSI transport structures
*
* As each Host Adapter makes itself known to the system,
@@ -54,7 +60,9 @@ typedef struct scsi_hba_tran scsi_hba_tran_t;
struct scsi_hba_tran {
/*
- * Ptr to the device info structure for this particular HBA.
+ * Ptr to the device info structure for this particular HBA. If a SCSA
+ * HBA driver separates initiator port function from HBA function,
+ * this field still refers to the HBA and is used to manage DMA.
*/
dev_info_t *tran_hba_dip;
@@ -64,8 +72,8 @@ struct scsi_hba_tran {
void *tran_hba_private; /* HBA softstate */
/*
- * The following two fields are only used in the SCSI_HBA_TRAN_CLONE
- * case. Consider using SCSI_HBA_ADDR_COMPLEX instead.
+ * The following two fields are only used in the deprecated
+ * SCSI_HBA_TRAN_CLONE case. Use SCSI_HBA_ADDR_COMPLEX instead.
*/
void *tran_tgt_private;
struct scsi_device *tran_sd;
@@ -215,8 +223,7 @@ struct scsi_hba_tran {
* open_flag: bit field indicating which minor nodes are open.
* 0 = closed, 1 = shared open, all bits 1 = excl open.
*
- * XXX Unused if hba driver chooses to implement own
- * xxopen(9e) entry point
+ * NOTE: Unused if HBA driver implements its own open(9e) entry point.
*/
kmutex_t tran_open_lock;
uint64_t tran_open_flag;
@@ -246,7 +253,7 @@ struct scsi_hba_tran {
void *result);
/*
- * Inter-Connect type of trasnport as defined in
+ * Inter-Connect type of transport as defined in
* usr/src/uts/common/sys/scsi/impl/services.h
*/
int tran_interconnect_type;
@@ -286,6 +293,16 @@ struct scsi_hba_tran {
*/
dev_info_t *tran_iport_dip;
+ /*
+ * map of initiator ports below HBA
+ */
+ scsi_hba_iportmap_t *tran_iportmap;
+
+ /*
+ * map of targets below initiator
+ */
+ scsi_hba_tgtmap_t *tran_tgtmap;
+
#ifdef SCSI_SIZE_CLEAN_VERIFY
/*
* Must be last: Building a driver with-and-without
@@ -306,7 +323,7 @@ _NOTE(SCHEME_PROTECTS_DATA("stable data",
scsi_hba_tran::tran_open_flag
scsi_hba_tran::tran_pkt_cache_ptr))
/*
- * we only modify the dma atributes (like dma_attr_granular) upon
+ * we only modify the dma attributes (like dma_attr_granular) upon
* attach and in response to a setcap. It is also up to the target
* driver to not have any outstanding I/Os when it is changing the
* capabilities of the transport.
@@ -373,7 +390,22 @@ int scsi_hba_probe(
struct scsi_device *sd,
int (*callback)(void));
-char *scsi_get_device_type_string(
+int scsi_hba_probe_pi(
+ struct scsi_device *sd,
+ int (*callback)(void),
+ int pi);
+
+int scsi_hba_ua_get_reportdev(
+ struct scsi_device *sd,
+ char *ba,
+ int len);
+
+int scsi_hba_ua_get(
+ struct scsi_device *sd,
+ char *ua,
+ int len);
+
+char *scsi_get_device_type_string(
char *prop_name,
dev_info_t *hba_dip,
struct scsi_device *sd);
@@ -443,8 +475,7 @@ void scsi_hba_nodename_compatible_free(
char *nodename,
char **compatible);
-
-int scsi_hba_prop_update_inqstring(
+int scsi_device_prop_update_inqstring(
struct scsi_device *sd,
char *name,
char *data,
@@ -453,8 +484,12 @@ int scsi_hba_prop_update_inqstring(
void scsi_hba_pkt_comp(
struct scsi_pkt *pkt);
+int scsi_device_identity(
+ struct scsi_device *sd,
+ int (*callback)(void));
+
char *scsi_hba_iport_unit_address(
- dev_info_t *self);
+ dev_info_t *dip);
int scsi_hba_iport_register(
dev_info_t *dip,
@@ -466,6 +501,8 @@ int scsi_hba_iport_exist(
dev_info_t *scsi_hba_iport_find(
dev_info_t *pdip,
char *portnm);
+
+
/*
* Flags for scsi_hba_attach
*
@@ -496,8 +533,8 @@ dev_info_t *scsi_hba_iport_find(
* same driver. The driver can distinguish context
* by calling scsi_hba_iport_unit_address().
*
- * SCSI_HBA_TRAN_CLONE Consider using SCSI_HBA_ADDR_COMPLEX instead.
- * SCSI_HBA_TRAN_CLONE is a KLUDGE to address
+ * ::SCSI_HBA_TRAN_CLONE Deprecated: use SCSI_HBA_ADDR_COMPLEX instead.
+ * SCSI_HBA_TRAN_CLONE was a KLUDGE to address
* limitations of the scsi_address(9S) structure
* via duplication of scsi_hba_tran(9S) and
* use of tran_tgt_private.
@@ -507,10 +544,10 @@ dev_info_t *scsi_hba_iport_find(
#define SCSI_HBA_TRAN_PHCI 0x02 /* treat HBA as mpxio 'pHCI' */
#define SCSI_HBA_TRAN_CDB 0x04 /* allocate cdb */
#define SCSI_HBA_TRAN_SCB 0x08 /* allocate sense */
+#define SCSI_HBA_HBA 0x10 /* all HBA children are iports */
#define SCSI_HBA_ADDR_SPI 0x20 /* scsi_address in SPI form */
#define SCSI_HBA_ADDR_COMPLEX 0x40 /* scsi_address is COMPLEX */
-#define SCSI_HBA_HBA 0x80 /* all HBA children are iport */
/* upper bits used to record SCSA configuration state */
#define SCSI_HBA_SCSA_PHCI 0x10000 /* need mdi_phci_unregister */
@@ -526,8 +563,8 @@ dev_info_t *scsi_hba_iport_find(
* Support extra flavors for SCSA children
*/
#define SCSA_FLAVOR_SCSI_DEVICE NDI_FLAVOR_VANILLA
-#define SCSA_FLAVOR_IPORT 1
-#define SCSA_FLAVOR_SMP 2
+#define SCSA_FLAVOR_SMP 1
+#define SCSA_FLAVOR_IPORT 2
#define SCSA_NFLAVORS 3
/*
@@ -536,6 +573,80 @@ dev_info_t *scsi_hba_iport_find(
#define SCSI_HBA_MAX_IPORTS 32
/*
+ * SCSI iport map interfaces
+ */
+int scsi_hba_iportmap_create(
+ dev_info_t *hba_dip,
+ clock_t stable_ms,
+ int n_entries,
+ scsi_hba_iportmap_t **iportmapp);
+
+int scsi_hba_iportmap_iport_add(
+ scsi_hba_iportmap_t *iportmap,
+ char *iport_addr,
+ void *iport_priv);
+
+int scsi_hba_iportmap_iport_remove(
+ scsi_hba_iportmap_t *iportmap,
+ char *iport_addr);
+
+void scsi_hba_iportmap_destroy(scsi_hba_iportmap_t *iportmap);
+
+/*
+ * SCSI target map interfaces
+ */
+typedef enum { SCSI_TM_FULLSET = 0, SCSI_TM_PERADDR } scsi_tgtmap_mode_t;
+typedef enum {
+ SCSI_TGT_SCSI_DEVICE = 0, SCSI_TGT_SMP_DEVICE, SCSI_TGT_NTYPES
+} scsi_tgtmap_tgt_type_t;
+
+typedef void (*scsi_tgt_activate_cb_t)(
+ void *tgtmap_priv,
+ char *tgt_addr,
+ scsi_tgtmap_tgt_type_t tgt_type,
+ void **tgt_privp);
+typedef void (*scsi_tgt_deactivate_cb_t)(
+ void *tgtmap_priv,
+ char *tgt_addr,
+ scsi_tgtmap_tgt_type_t tgt_type,
+ void *tgt_priv);
+int scsi_hba_tgtmap_create(
+ dev_info_t *iport_dip,
+ scsi_tgtmap_mode_t rpt_mode,
+ clock_t stable_ms,
+ int n_entries,
+ void *tgtmap_priv,
+ scsi_tgt_activate_cb_t activate_cb,
+ scsi_tgt_deactivate_cb_t deactivate_cb,
+ scsi_hba_tgtmap_t **tgtmapp);
+
+int scsi_hba_tgtmap_set_begin(scsi_hba_tgtmap_t *tgtmap);
+
+int scsi_hba_tgtmap_set_add(
+ scsi_hba_tgtmap_t *tgtmap,
+ scsi_tgtmap_tgt_type_t tgt_type,
+ char *tgt_addr,
+ void *tgt_priv);
+
+int scsi_hba_tgtmap_set_end(
+ scsi_hba_tgtmap_t *tgtmap,
+ uint_t flags);
+
+int scsi_hba_tgtmap_tgt_add(
+ scsi_hba_tgtmap_t *tgtmap,
+ scsi_tgtmap_tgt_type_t tgt_type,
+ char *tgt_addr,
+ void *tgt_priv);
+
+int scsi_hba_tgtmap_tgt_remove(
+ scsi_hba_tgtmap_t *tgtmap,
+ scsi_tgtmap_tgt_type_t tgt_type,
+ char *tgt_addr);
+
+void scsi_hba_tgtmap_destroy(scsi_hba_tgtmap_t *tgt_map);
+
+
+/*
* For minor nodes created by the SCSA framework, minor numbers are
* formed by left-shifting instance by INST_MINOR_SHIFT and OR in a
* number less than 64.
diff --git a/usr/src/uts/common/sys/scsi/scsi_address.h b/usr/src/uts/common/sys/scsi/scsi_address.h
index ec70e72b78..36b5543dff 100644
--- a/usr/src/uts/common/sys/scsi/scsi_address.h
+++ b/usr/src/uts/common/sys/scsi/scsi_address.h
@@ -114,6 +114,10 @@ struct scsi_address {
#define SCSI_ADDR_PROP_LUN64 "lun64" /* int64 */
#define SCSI_ADDR_PROP_SFUNC "sfunc" /* int */
+#define SCSI_ADDR_PROP_IPORTUA "scsi-iport" /* string */
+
+#define SCSI_ADDR_PROP_SATA_PHY "sata-phy" /* int */
+
/*
* Addressing property names, values are in string form compatible
* with the SCSI_ADDR_PROP_TARGET_PORT part of the related
@@ -165,6 +169,7 @@ int scsi_wwnstr_to_wwn(const char *wwnstr, uint64_t *wwnp);
char *scsi_wwn_to_wwnstr(uint64_t wwn,
int unit_address_form, char *wwnstr);
void scsi_wwnstr_hexcase(char *wwnstr, int lower_case);
+const char *scsi_wwnstr_skip_ua_prefix(const char *wwnstr);
void scsi_free_wwnstr(char *wwnstr);
#endif /* _KERNEL */
diff --git a/usr/src/uts/common/sys/scsi/scsi_ctl.h b/usr/src/uts/common/sys/scsi/scsi_ctl.h
index 0498c30d7c..32b6f54029 100644
--- a/usr/src/uts/common/sys/scsi/scsi_ctl.h
+++ b/usr/src/uts/common/sys/scsi/scsi_ctl.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * 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.
@@ -20,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_SCSI_SCSI_CTL_H
#define _SYS_SCSI_SCSI_CTL_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/scsi/scsi_types.h>
#ifdef __cplusplus
@@ -56,12 +53,6 @@ extern "C" {
#define SCSI_RESET_CANCEL 0x02 /* cancel the reset notification */
/*
- * Define for scsi_get_bus_addr/scsi_get_name first argument.
- */
-#define SCSI_GET_INITIATOR_ID ((struct scsi_device *)NULL)
- /* return initiator-id */
-
-/*
* Define for scsi_get_name string length.
* This is needed because MAXNAMELEN is not part of DDI.
*/
@@ -98,9 +89,8 @@ int scsi_terminate_task(struct scsi_address *ap, struct scsi_pkt *pkt);
* Other functions
*/
int scsi_clear_aca(struct scsi_address *ap);
-int scsi_get_bus_addr(struct scsi_device *devp, char *name, int len);
-int scsi_get_name(struct scsi_device *devp, char *name, int len);
-
+int scsi_ua_get_reportdev(struct scsi_device *sd, char *ba, int len);
+int scsi_ua_get(struct scsi_device *sd, char *ua, int len);
#endif /* _KERNEL */
#ifdef __cplusplus
diff --git a/usr/src/uts/common/sys/scsi/scsi_pkt.h b/usr/src/uts/common/sys/scsi/scsi_pkt.h
index f7890fc548..88f1b98602 100644
--- a/usr/src/uts/common/sys/scsi/scsi_pkt.h
+++ b/usr/src/uts/common/sys/scsi/scsi_pkt.h
@@ -19,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_SCSI_SCSI_PKT_H
#define _SYS_SCSI_SCSI_PKT_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/scsi/scsi_types.h>
#ifdef __cplusplus
@@ -106,6 +104,9 @@ struct scsi_pkt {
/* private: iff scsi_pkt_allocated_correctly() */
int pkt_path_instance; /* pHCI transport path */
+ /* stage-temporary: iff scsi_pkt_allocated_correctly() */
+ void *pkt_stmp; /* temporary for current pkt stage */
+
#ifdef SCSI_SIZE_CLEAN_VERIFY
/*
* Must be last: Building a driver with-and-without
diff --git a/usr/src/uts/common/sys/scsi/scsi_types.h b/usr/src/uts/common/sys/scsi/scsi_types.h
index 82328afbd4..6aeb2bc0c5 100644
--- a/usr/src/uts/common/sys/scsi/scsi_types.h
+++ b/usr/src/uts/common/sys/scsi/scsi_types.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -57,6 +57,11 @@ typedef void *opaque_t;
#include <sys/cmn_err.h>
#include <sys/debug.h>
#include <sys/devops.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/stat.h>
+#include <sys/sunndi.h>
+#include <sys/devctl.h>
#endif /* _KERNEL */
/*
@@ -87,22 +92,9 @@ typedef void *opaque_t;
#include <sys/scsi/generic/message.h>
#include <sys/scsi/generic/mode.h>
-
/*
* Sun SCSI type definitions
*/
#include <sys/scsi/impl/types.h>
-/*
- * For drivers which do not include these - must be last
- */
-#ifdef _KERNEL
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/stat.h>
-#include <sys/sunndi.h>
-#include <sys/devctl.h>
-#include <sys/ddifm.h>
-#endif /* _KERNEL */
-
#endif /* _SYS_SCSI_SCSI_TYPES_H */
diff --git a/usr/src/uts/common/sys/scsi/targets/smp.h b/usr/src/uts/common/sys/scsi/targets/smp.h
index 9412662fd6..7ccfb7803f 100644
--- a/usr/src/uts/common/sys/scsi/targets/smp.h
+++ b/usr/src/uts/common/sys/scsi/targets/smp.h
@@ -20,15 +20,13 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_SCSI_TARGETS_SMP_H
#define _SYS_SCSI_TARGETS_SMP_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/scsi/scsi.h>
@@ -47,17 +45,19 @@ extern "C" {
#define SMP_EXOPENED 2
typedef struct smp_state {
- struct smp_device *smp_dev; /* pointer to smp_device */
- kmutex_t smp_mutex; /* mutex */
- uint32_t smp_open_flag; /* open flag */
+ struct smp_device *smp_dev; /* pointer to smp_device */
+ kmutex_t smp_mutex; /* mutex */
+ uint32_t smp_open_flag; /* open flag */
+ kcondvar_t smp_cv; /* condition variable */
+ uint32_t smp_busy; /* busy */
} smp_state_t;
#define SMP_ESTIMATED_NUM_DEVS 4 /* for soft-state allocation */
-#define SMP_DEFAULT_RETRY_TIMES 3
+#define SMP_DEFAULT_RETRY_TIMES 5
#define SMP_FLAG_REQBUF 0x1
#define SMP_FLAG_RSPBUF 0x2
-#define SMP_FLAG_XFER 0x4
+#define SMP_FLAG_XFER 0x4
#endif /* defined(_KERNEL) */
diff --git a/usr/src/uts/common/sys/sunddi.h b/usr/src/uts/common/sys/sunddi.h
index 5a390b4180..601601eaa6 100644
--- a/usr/src/uts/common/sys/sunddi.h
+++ b/usr/src/uts/common/sys/sunddi.h
@@ -116,6 +116,8 @@ extern "C" {
#define DEVI_PSEUDO_NODEID ((int)-1)
#define DEVI_SID_NODEID ((int)-2)
#define DEVI_SID_HIDDEN_NODEID ((int)-3)
+#define DEVI_SID_HP_NODEID ((int)-4)
+#define DEVI_SID_HP_HIDDEN_NODEID ((int)-5)
#define DEVI_PSEUDO_NEXNAME "pseudo"
#define DEVI_ISA_NEXNAME "isa"
@@ -1556,43 +1558,84 @@ int
ddi_fls(long mask);
/*
- * The next five routines comprise generic storage management utilities
- * for driver soft state structures.
+ * The ddi_soft_state* routines comprise generic storage management utilities
+ * for driver soft state structures. Two types of soft_state indexes are
+ * supported: 'integer index', and 'string index'.
*/
+typedef struct __ddi_soft_state_bystr ddi_soft_state_bystr;
/*
- * Allocate a set of pointers to 'n_items' objects of size 'size'
- * bytes. Each pointer is initialized to nil. 'n_items' is a hint i.e.
- * zero is allowed.
+ * Initialize a soft_state set, establishing the 'size' of soft state objects
+ * in the set.
+ *
+ * For an 'integer indexed' soft_state set, the initial set will accommodate
+ * 'n_items' objects - 'n_items' is a hint (i.e. zero is allowed), allocations
+ * that exceed 'n_items' have additional overhead.
+ *
+ * For a 'string indexed' soft_state set, 'n_items' should be the typical
+ * number of soft state objects in the set - 'n_items' is a hint, there may
+ * be additional overhead if the hint is too small (and wasted memory if the
+ * hint is too big).
*/
int
ddi_soft_state_init(void **state_p, size_t size, size_t n_items);
+int
+ddi_soft_state_bystr_init(ddi_soft_state_bystr **state_p,
+ size_t size, int n_items);
/*
- * Allocate a state structure of size 'size' to be associated
- * with item 'item'.
+ * Allocate a soft state object associated with either 'integer index' or
+ * 'string index' from a soft_state set.
*/
int
ddi_soft_state_zalloc(void *state, int item);
+int
+ddi_soft_state_bystr_zalloc(ddi_soft_state_bystr *state, const char *str);
/*
- * Fetch a pointer to the allocated soft state structure
- * corresponding to 'item.'
+ * Get the pointer to the allocated soft state object associated with
+ * either 'integer index' or 'string index'.
*/
void *
ddi_get_soft_state(void *state, int item);
+void *
+ddi_soft_state_bystr_get(ddi_soft_state_bystr *state, const char *str);
/*
- * Free the state structure corresponding to 'item.'
+ * Free the soft state object associated with either 'integer index'
+ * or 'string index'.
*/
void
ddi_soft_state_free(void *state, int item);
+void
+ddi_soft_state_bystr_free(ddi_soft_state_bystr *state, const char *str);
/*
- * Free the handle, and any associated soft state structures.
+ * Free the soft state set and any associated soft state objects.
*/
void
ddi_soft_state_fini(void **state_p);
+void
+ddi_soft_state_bystr_fini(ddi_soft_state_bystr **state_p);
+
+/*
+ * The ddi_strid_* routines provide string-to-index management utilities.
+ */
+typedef struct __ddi_strid ddi_strid;
+int
+ddi_strid_init(ddi_strid **strid_p, int n_items);
+id_t
+ddi_strid_alloc(ddi_strid *strid, char *str);
+id_t
+ddi_strid_fixed_alloc(ddi_strid *strid, char *str);
+id_t
+ddi_strid_str2id(ddi_strid *strid, char *str);
+char *
+ddi_strid_id2str(ddi_strid *strid, id_t id);
+void
+ddi_strid_free(ddi_strid *strid, id_t id);
+void
+ddi_strid_fini(ddi_strid **strid_p);
/*
* Set the addr field of the name in dip to name
diff --git a/usr/src/uts/common/sys/sunmdi.h b/usr/src/uts/common/sys/sunmdi.h
index 4aa687efa8..a670d0b2b8 100644
--- a/usr/src/uts/common/sys/sunmdi.h
+++ b/usr/src/uts/common/sys/sunmdi.h
@@ -87,7 +87,11 @@ typedef enum {
#define MDI_COMPONENT_CLIENT 0x4
/*
- * mdi_pathinfo node state utility definitions
+ * mdi_pathinfo node state utility definitions (bits in mdi_pathinfo_state_t)
+ *
+ * NOTE: having mdi_pathinfo_state_t contain both state and flags is error
+ * prone. For new flags, please consider using MDI_PATHINFO_FLAG_ (and
+ * moving existing EXT_STATE_MASK flags over would be good too).
*/
#define MDI_PATHINFO_STATE_TRANSIENT 0x00010000
#define MDI_PATHINFO_STATE_USER_DISABLE 0x00100000
@@ -96,6 +100,12 @@ typedef enum {
#define MDI_PATHINFO_STATE_MASK 0x0000FFFF
#define MDI_PATHINFO_EXT_STATE_MASK 0xFFF00000
+/*
+ * mdi_pathinfo flags definitions
+ */
+#define MDI_PATHINFO_FLAGS_HIDDEN 0x00000001
+#define MDI_PATHINFO_FLAGS_DEVICE_REMOVED 0x00000002
+
#define USER_DISABLE 1
#define DRIVER_DISABLE 2
#define DRIVER_DISABLE_TRANSIENT 3
@@ -191,6 +201,12 @@ int mdi_pi_enable(dev_info_t *, dev_info_t *, int);
int mdi_pi_disable_path(mdi_pathinfo_t *, int);
int mdi_pi_enable_path(mdi_pathinfo_t *, int);
+int mdi_pi_ishidden(mdi_pathinfo_t *);
+
+int mdi_pi_device_isremoved(mdi_pathinfo_t *);
+int mdi_pi_device_remove(mdi_pathinfo_t *);
+int mdi_pi_device_insert(mdi_pathinfo_t *);
+
/*
* MPxIO-PM stuff
*/
@@ -228,11 +244,14 @@ dev_info_t *mdi_pi_get_phci(mdi_pathinfo_t *);
char *mdi_pi_get_node_name(mdi_pathinfo_t *);
char *mdi_pi_get_addr(mdi_pathinfo_t *);
mdi_pathinfo_state_t mdi_pi_get_state(mdi_pathinfo_t *);
+uint_t mdi_pi_get_flags(mdi_pathinfo_t *);
int mdi_pi_get_path_instance(mdi_pathinfo_t *);
-char *mdi_pi_pathname_by_instance(int path_instance);
+char *mdi_pi_pathname_by_instance(int);
char *mdi_pi_pathname(mdi_pathinfo_t *);
char *mdi_pi_pathname_obp(mdi_pathinfo_t *, char *);
int mdi_pi_pathname_obp_set(mdi_pathinfo_t *, char *);
+char *mdi_pi_spathname_by_instance(int);
+char *mdi_pi_spathname(mdi_pathinfo_t *);
/*
* mdi_pathinfo Property handling functions
diff --git a/usr/src/uts/common/sys/sunndi.h b/usr/src/uts/common/sys/sunndi.h
index 80bbdca329..22e61db408 100644
--- a/usr/src/uts/common/sys/sunndi.h
+++ b/usr/src/uts/common/sys/sunndi.h
@@ -318,6 +318,7 @@ ndi_irm_destroy(ddi_irm_pool_t *poolp);
#define NDI_DRV_CONF_REPROBE 0x04000000 /* reprobe conf-enum'd nodes only */
#define NDI_DETACH_DRIVER 0x08000000 /* performing driver_detach */
#define NDI_MTC_OFF 0x10000000 /* disable multi-threading */
+#define NDI_USER_REQ 0x20000000 /* user requested operation */
/* ndi interface flag values */
#define NDI_SLEEP 0x000000
@@ -342,6 +343,26 @@ dev_info_t *
ndi_devi_findchild(dev_info_t *p, char *devname);
/*
+ * Find the child dev_info node of parent nexus 'p' whose name
+ * matches "dname"@"ua". If a child doesn't have a "ua"
+ * value, it calls the function "make_ua" to create it.
+ */
+dev_info_t *
+ndi_devi_findchild_by_callback(dev_info_t *p, char *dname, char *ua,
+ int (*make_ua)(dev_info_t *, char *, int));
+
+/*
+ * Maintain DEVI_DEVICE_REMOVED hotplug devi_state for remove/reinsert hotplug
+ * of open devices.
+ */
+int
+ndi_devi_device_isremoved(dev_info_t *dip);
+int
+ndi_devi_device_remove(dev_info_t *dip);
+int
+ndi_devi_device_insert(dev_info_t *dip);
+
+/*
* generate debug msg via NDI_DEVI_DEBUG flag
*/
#define NDI_DEBUG(flags, args) \
@@ -462,10 +483,10 @@ typedef struct ndi_event_definition {
} ndi_event_definition_t;
typedef struct ndi_event_cookie {
- ndi_event_definition_t *definition; /* Event Description */
+ ndi_event_definition_t *definition; /* Event Description */
dev_info_t *ddip; /* Devi defining this event */
ndi_event_callbacks_t *callback_list; /* Cb's reg'd to w/ this evt */
- struct ndi_event_cookie *next_cookie; /* Next cookie def'd in hdl */
+ struct ndi_event_cookie *next_cookie; /* Next cookie def'd in hdl */
} ndi_event_cookie_t;
@@ -522,7 +543,7 @@ ndi_event_unbind_set(ndi_event_hdl_t handle,
* get an event cookie
*/
int
-ndi_event_retrieve_cookie(ndi_event_hdl_t handle,
+ndi_event_retrieve_cookie(ndi_event_hdl_t handle,
dev_info_t *child_dip,
char *eventname,
ddi_eventcookie_t *cookiep,
@@ -532,7 +553,7 @@ ndi_event_retrieve_cookie(ndi_event_hdl_t handle,
* add an event callback info to the ndi event handle
*/
int
-ndi_event_add_callback(ndi_event_hdl_t handle,
+ndi_event_add_callback(ndi_event_hdl_t handle,
dev_info_t *child_dip,
ddi_eventcookie_t cookie,
void (*event_callback)
@@ -591,7 +612,7 @@ ndi_event_cookie_to_name(ndi_event_hdl_t handle,
* name given an event_tag
*/
char *
-ndi_event_tag_to_name(ndi_event_hdl_t handle, int event_tag);
+ndi_event_tag_to_name(ndi_event_hdl_t handle, int event_tag);
dev_info_t *
ndi_devi_config_vhci(char *, int);
@@ -635,9 +656,9 @@ typedef struct ndi_ra_request {
/* restricted to */
uint64_t ra_boundlen; /* Length of the area, starting */
- /* from ra_boundbase, for the */
+ /* from ra_boundbase, for the */
/* allocated resource to be */
- /* restricted to. */
+ /* restricted to. */
uint64_t ra_align_mask; /* Alignment mask used for */
/* allocated base address */
@@ -728,6 +749,11 @@ int ndi_dev_is_pseudo_node(dev_info_t *);
int ndi_dev_is_persistent_node(dev_info_t *);
/*
+ * ndi_dev_is_hotplug_node: Return non-zero if the node was created by hotplug.
+ */
+int ndi_dev_is_hotplug_node(dev_info_t *);
+
+/*
* ndi_dev_is_hidden_node: Return non-zero if the node is hidden.
*/
int ndi_dev_is_hidden_node(dev_info_t *);
@@ -761,8 +787,8 @@ void ndi_set_dma_fault(ddi_dma_handle_t dh);
void ndi_clr_dma_fault(ddi_dma_handle_t dh);
/* Driver.conf property merging */
-int ndi_merge_node(dev_info_t *, int (*)(dev_info_t *, char *, int));
-void ndi_merge_wildcard_node(dev_info_t *);
+int ndi_merge_node(dev_info_t *, int (*)(dev_info_t *, char *, int));
+void ndi_merge_wildcard_node(dev_info_t *);
/*
* Ndi 'flavor' support: These interfaces are to support a nexus driver
diff --git a/usr/src/uts/common/sys/systm.h b/usr/src/uts/common/sys/systm.h
index 5963460441..4e529b9cce 100644
--- a/usr/src/uts/common/sys/systm.h
+++ b/usr/src/uts/common/sys/systm.h
@@ -175,6 +175,7 @@ hrtime_t untimeout_generic(callout_id_t, int);
clock_t untimeout_default(callout_id_t, int);
void delay(clock_t);
int delay_sig(clock_t);
+void delay_random(clock_t);
int nodev();
int nulldev();
major_t getudev(void);