svn commit: r350793 - in stable/11/sys: cam/scsi dev/ahci
Alexander Motin
mav at FreeBSD.org
Thu Aug 8 21:46:39 UTC 2019
Author: mav
Date: Thu Aug 8 21:46:36 2019
New Revision: 350793
URL: https://svnweb.freebsd.org/changeset/base/350793
Log:
MFC r349321: Improve AHCI Enclosure Management and SES interoperation.
Since SES specs do not define mechanism to map enclosure slots to SATA
disks, AHCI EM code I written many years ago appeared quite useless,
that always bugged me. I was thinking whether it was a good idea, but
if LSI HBAs do that, why I shouldn't?
This change introduces simple non-standard mechanism for the mapping
into both AHCI EM and SES code, that makes AHCI EM on capable controllers
(most of Intel's) a first-class SES citizen, allowing it to report disk
physical path to GEOM, show devices inserted into each enclosure slot in
`sesutil map` and `getencstat`, control locate and fault LEDs for specific
devices with `sesutil locate adaX on` and `sesutil fault adaX on`, etc.
I've successfully tested this on Supermicro X10DRH-i motherboard connected
with sideband cable of its S-SATA Mini-SAS connector to SAS815TQ backplane.
It can indicate with LEDs Locate, Fault and Rebuild/Remap SES statuses for
each disk identical to real SES of Supermicro SAS2 backplanes.
Modified:
stable/11/sys/cam/scsi/scsi_all.c
stable/11/sys/cam/scsi/scsi_enc.c
stable/11/sys/cam/scsi/scsi_enc.h
stable/11/sys/cam/scsi/scsi_enc_internal.h
stable/11/sys/cam/scsi/scsi_enc_safte.c
stable/11/sys/cam/scsi/scsi_enc_ses.c
stable/11/sys/cam/scsi/scsi_ses.h
stable/11/sys/dev/ahci/ahci.c
stable/11/sys/dev/ahci/ahci.h
stable/11/sys/dev/ahci/ahciem.c
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/cam/scsi/scsi_all.c
==============================================================================
--- stable/11/sys/cam/scsi/scsi_all.c Thu Aug 8 21:44:37 2019 (r350792)
+++ stable/11/sys/cam/scsi/scsi_all.c Thu Aug 8 21:46:36 2019 (r350793)
@@ -5559,6 +5559,7 @@ scsi_devid_is_naa_ieee_reg(uint8_t *bufp)
{
struct scsi_vpd_id_descriptor *descr;
struct scsi_vpd_id_naa_basic *naa;
+ int n;
descr = (struct scsi_vpd_id_descriptor *)bufp;
naa = (struct scsi_vpd_id_naa_basic *)descr->identifier;
@@ -5566,7 +5567,8 @@ scsi_devid_is_naa_ieee_reg(uint8_t *bufp)
return 0;
if (descr->length < sizeof(struct scsi_vpd_id_naa_ieee_reg))
return 0;
- if ((naa->naa >> SVPD_ID_NAA_NAA_SHIFT) != SVPD_ID_NAA_IEEE_REG)
+ n = naa->naa >> SVPD_ID_NAA_NAA_SHIFT;
+ if (n != SVPD_ID_NAA_LOCAL_REG && n != SVPD_ID_NAA_IEEE_REG)
return 0;
return 1;
}
Modified: stable/11/sys/cam/scsi/scsi_enc.c
==============================================================================
--- stable/11/sys/cam/scsi/scsi_enc.c Thu Aug 8 21:44:37 2019 (r350792)
+++ stable/11/sys/cam/scsi/scsi_enc.c Thu Aug 8 21:46:36 2019 (r350793)
@@ -88,6 +88,9 @@ int enc_verbose = 0;
SYSCTL_INT(_kern_cam_enc, OID_AUTO, verbose, CTLFLAG_RWTUN,
&enc_verbose, 0, "Enable verbose logging");
+const char *elm_type_names[] = ELM_TYPE_NAMES;
+CTASSERT(nitems(elm_type_names) - 1 == ELMTYP_LAST);
+
static struct periph_driver encdriver = {
enc_init, "ses",
TAILQ_HEAD_INITIALIZER(encdriver.units), /* generation */ 0
@@ -239,13 +242,19 @@ enc_async(void *callback_arg, uint32_t code, struct ca
struct enc_softc *softc;
softc = (struct enc_softc *)periph->softc;
- if (xpt_path_path_id(periph->path) != path_id
- || softc == NULL
- || (softc->enc_flags & ENC_FLAG_INITIALIZED)
- == 0
- || softc->enc_vec.device_found == NULL)
+
+ /* Check this SEP is ready. */
+ if (softc == NULL || (softc->enc_flags &
+ ENC_FLAG_INITIALIZED) == 0 ||
+ softc->enc_vec.device_found == NULL)
continue;
+ /* Check this SEP may manage this device. */
+ if (xpt_path_path_id(periph->path) != path_id &&
+ (softc->enc_type != ENC_SEMB_SES ||
+ cgd->protocol != PROTO_ATA))
+ continue;
+
softc->enc_vec.device_found(softc);
}
xpt_unlock_buses();
@@ -439,7 +448,7 @@ enc_ioctl(struct cdev *dev, u_long cmd, caddr_t arg_ad
encioc_element_t kelm;
kelm.elm_idx = i;
kelm.elm_subenc_id = cache->elm_map[i].subenclosure;
- kelm.elm_type = cache->elm_map[i].enctype;
+ kelm.elm_type = cache->elm_map[i].elm_type;
error = copyout(&kelm, &uelm[i], sizeof(kelm));
if (error)
break;
Modified: stable/11/sys/cam/scsi/scsi_enc.h
==============================================================================
--- stable/11/sys/cam/scsi/scsi_enc.h Thu Aug 8 21:44:37 2019 (r350792)
+++ stable/11/sys/cam/scsi/scsi_enc.h Thu Aug 8 21:46:36 2019 (r350793)
@@ -118,9 +118,41 @@ typedef enum {
ELMTYP_SCSI_INI = 0x15,
ELMTYP_SUBENC = 0x16,
ELMTYP_ARRAY_DEV = 0x17,
- ELMTYP_SAS_EXP = 0x18, /* SAS expander */
- ELMTYP_SAS_CONN = 0x19 /* SAS connector */
+ ELMTYP_SAS_EXP = 0x18, /* SAS Expander */
+ ELMTYP_SAS_CONN = 0x19, /* SAS Connector */
+ ELMTYP_LAST = ELMTYP_SAS_CONN
} elm_type_t;
+
+#define ELM_TYPE_NAMES { \
+ "Unspecified", \
+ "Device Slot", \
+ "Power Supply", \
+ "Cooling", \
+ "Temperature Sensors", \
+ "Door", \
+ "Audible alarm", \
+ "Enclosure Services Controller Electronics", \
+ "SCC Controller Electronics", \
+ "Nonvolatile Cache", \
+ "Invalid Operation Reason", \
+ "Uninterruptible Power Supply", \
+ "Display", \
+ "Key Pad Entry", \
+ "Enclosure", \
+ "SCSI Port/Transceiver", \
+ "Language", \
+ "Communication Port", \
+ "Voltage Sensor", \
+ "Current Sensor", \
+ "SCSI Target Port", \
+ "SCSI Initiator Port", \
+ "Simple Subenclosure", \
+ "Array Device Slot", \
+ "SAS Expander", \
+ "SAS Connector" \
+}
+
+extern const char *elm_type_names[];
typedef struct encioc_element {
/* Element Index */
Modified: stable/11/sys/cam/scsi/scsi_enc_internal.h
==============================================================================
--- stable/11/sys/cam/scsi/scsi_enc_internal.h Thu Aug 8 21:44:37 2019 (r350792)
+++ stable/11/sys/cam/scsi/scsi_enc_internal.h Thu Aug 8 21:46:36 2019 (r350793)
@@ -37,16 +37,12 @@
#include <sys/sysctl.h>
typedef struct enc_element {
- uint32_t
- enctype : 8, /* enclosure type */
- subenclosure : 8, /* subenclosure id */
- svalid : 1, /* enclosure information valid */
- overall_status_elem: 1,/*
- * This object represents generic
- * status about all objects of this
- * type.
- */
- priv : 14; /* private data, per object */
+ uint8_t elm_idx; /* index of element */
+ uint8_t elm_type; /* element type */
+ uint8_t subenclosure; /* subenclosure id */
+ uint8_t type_elm_idx; /* index of element within type */
+ uint8_t svalid; /* enclosure information valid */
+ uint16_t priv; /* private data, per object */
uint8_t encstat[4]; /* state && stats */
uint8_t *physical_path; /* Device physical path data. */
u_int physical_path_len; /* Length of device path data. */
Modified: stable/11/sys/cam/scsi/scsi_enc_safte.c
==============================================================================
--- stable/11/sys/cam/scsi/scsi_enc_safte.c Thu Aug 8 21:44:37 2019 (r350792)
+++ stable/11/sys/cam/scsi/scsi_enc_safte.c Thu Aug 8 21:46:36 2019 (r350793)
@@ -299,21 +299,21 @@ safte_process_config(enc_softc_t *enc, struct enc_fsm_
* in later fetches of status.
*/
for (i = 0; i < cfg->Nfans; i++)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_FAN;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_FAN;
cfg->pwroff = (uint8_t) r;
for (i = 0; i < cfg->Npwr; i++)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_POWER;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_POWER;
for (i = 0; i < cfg->DoorLock; i++)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_DOORLOCK;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_DOORLOCK;
if (cfg->Nspkrs > 0)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_ALARM;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_ALARM;
for (i = 0; i < cfg->Ntherm; i++)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_THERM;
for (i = 0; i <= cfg->Ntstats; i++)
- enc->enc_cache.elm_map[r++].enctype = ELMTYP_THERM;
+ enc->enc_cache.elm_map[r++].elm_type = ELMTYP_THERM;
cfg->slotoff = (uint8_t) r;
for (i = 0; i < cfg->Nslots; i++)
- enc->enc_cache.elm_map[r++].enctype =
+ enc->enc_cache.elm_map[r++].elm_type =
emulate_array_devices ? ELMTYP_ARRAY_DEV :
ELMTYP_DEVICE;
@@ -503,7 +503,7 @@ safte_process_status(enc_softc_t *enc, struct enc_fsm_
*/
for (i = 0; i < cfg->Nslots; i++) {
SAFT_BAIL(r, xfer_len);
- if (cache->elm_map[cfg->slotoff + i].enctype == ELMTYP_DEVICE)
+ if (cache->elm_map[cfg->slotoff + i].elm_type == ELMTYP_DEVICE)
cache->elm_map[cfg->slotoff + i].encstat[1] = buf[r];
r++;
}
@@ -676,7 +676,7 @@ safte_process_slotstatus(enc_softc_t *enc, struct enc_
oid = cfg->slotoff;
for (r = i = 0; i < cfg->Nslots; i++, r += 4) {
SAFT_BAIL(r+3, xfer_len);
- if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV)
+ if (cache->elm_map[oid].elm_type == ELMTYP_ARRAY_DEV)
cache->elm_map[oid].encstat[1] = 0;
cache->elm_map[oid].encstat[2] &= SESCTL_RQSID;
cache->elm_map[oid].encstat[3] = 0;
@@ -703,7 +703,7 @@ safte_process_slotstatus(enc_softc_t *enc, struct enc_
cache->elm_map[oid].encstat[3] |= SESCTL_RQSFLT;
if (buf[r+0] & 0x40)
cache->elm_map[oid].encstat[0] |= SESCTL_PRDFAIL;
- if (cache->elm_map[oid].enctype == ELMTYP_ARRAY_DEV) {
+ if (cache->elm_map[oid].elm_type == ELMTYP_ARRAY_DEV) {
if (buf[r+0] & 0x01)
cache->elm_map[oid].encstat[1] |= 0x80;
if (buf[r+0] & 0x04)
@@ -769,7 +769,7 @@ safte_fill_control_request(enc_softc_t *enc, struct en
} else {
ep = &enc->enc_cache.elm_map[idx];
- switch (ep->enctype) {
+ switch (ep->elm_type) {
case ELMTYP_DEVICE:
case ELMTYP_ARRAY_DEV:
switch (cfg->current_request_stage) {
@@ -779,7 +779,7 @@ safte_fill_control_request(enc_softc_t *enc, struct en
ep->priv |= 0x40;
if (req->elm_stat[3] & SESCTL_RQSFLT)
ep->priv |= 0x02;
- if (ep->enctype == ELMTYP_ARRAY_DEV) {
+ if (ep->elm_type == ELMTYP_ARRAY_DEV) {
if (req->elm_stat[1] & 0x01)
ep->priv |= 0x200;
if (req->elm_stat[1] & 0x02)
@@ -968,7 +968,7 @@ safte_process_control_request(enc_softc_t *enc, struct
if (idx == SES_SETSTATUS_ENC_IDX)
type = -1;
else
- type = enc->enc_cache.elm_map[idx].enctype;
+ type = enc->enc_cache.elm_map[idx].elm_type;
if (type == ELMTYP_DEVICE || type == ELMTYP_ARRAY_DEV)
enc_update_request(enc, SAFTE_UPDATE_READSLOTSTATUS);
else
Modified: stable/11/sys/cam/scsi/scsi_enc_ses.c
==============================================================================
--- stable/11/sys/cam/scsi/scsi_enc_ses.c Thu Aug 8 21:44:37 2019 (r350792)
+++ stable/11/sys/cam/scsi/scsi_enc_ses.c Thu Aug 8 21:46:36 2019 (r350793)
@@ -100,6 +100,7 @@ typedef struct ses_addl_status {
union {
union ses_fcobj_hdr *fc;
union ses_elm_sas_hdr *sas;
+ struct ses_elm_ata_hdr *ata;
} proto_hdr;
union ses_addl_data proto_data; /* array sizes stored in header */
} ses_add_status_t;
@@ -823,14 +824,6 @@ ses_devids_iter(enc_softc_t *enc, enc_element_t *elm,
elmpriv = elm->elm_private;
addl = &(elmpriv->addl);
- /*
- * Don't assume this object has additional status information, or
- * that it is a SAS device, or that it is a device slot device.
- */
- if (addl->hdr == NULL || addl->proto_hdr.sas == NULL
- || addl->proto_data.sasdev_phys == NULL)
- return;
-
devid_record_size = SVPD_DEVICE_ID_DESC_HDR_LEN
+ sizeof(struct scsi_vpd_id_naa_ieee_reg);
for (i = 0; i < addl->proto_hdr.sas->base_hdr.num_phys; i++) {
@@ -948,11 +941,40 @@ static void
ses_paths_iter(enc_softc_t *enc, enc_element_t *elm,
ses_path_callback_t *callback, void *callback_arg)
{
- ses_path_iter_args_t args;
+ ses_element_t *elmpriv;
+ struct ses_addl_status *addl;
- args.callback = callback;
- args.callback_arg = callback_arg;
- ses_devids_iter(enc, elm, ses_path_iter_devid_callback, &args);
+ elmpriv = elm->elm_private;
+ addl = &(elmpriv->addl);
+
+ if (addl->hdr == NULL)
+ return;
+
+ if (addl->proto_hdr.sas != NULL &&
+ addl->proto_data.sasdev_phys != NULL) {
+ ses_path_iter_args_t args;
+
+ args.callback = callback;
+ args.callback_arg = callback_arg;
+ ses_devids_iter(enc, elm, ses_path_iter_devid_callback, &args);
+ } else if (addl->proto_hdr.ata != NULL) {
+ struct cam_path *path;
+ struct ccb_getdev cgd;
+
+ if (xpt_create_path(&path, /*periph*/NULL,
+ scsi_4btoul(addl->proto_hdr.ata->bus),
+ scsi_4btoul(addl->proto_hdr.ata->target), 0)
+ != CAM_REQ_CMP)
+ return;
+
+ xpt_setup_ccb(&cgd.ccb_h, path, CAM_PRIORITY_NORMAL);
+ cgd.ccb_h.func_code = XPT_GDEV_TYPE;
+ xpt_action((union ccb *)&cgd);
+ if (cgd.ccb_h.status == CAM_REQ_CMP)
+ callback(enc, elm, path, callback_arg);
+
+ xpt_free_path(path);
+ }
}
/**
@@ -1057,6 +1079,10 @@ ses_set_physpath(enc_softc_t *enc, enc_element_t *elm,
ret = EIO;
devid = NULL;
+ elmpriv = elm->elm_private;
+ if (elmpriv->addl.hdr == NULL)
+ goto out;
+
/*
* Assemble the components of the physical path starting with
* the device ID of the enclosure itself.
@@ -1089,7 +1115,6 @@ ses_set_physpath(enc_softc_t *enc, enc_element_t *elm,
scsi_8btou64(idd->identifier), iter->type_index,
iter->type_element_index);
/* Append the element descriptor if one exists */
- elmpriv = elm->elm_private;
if (elmpriv->descr != NULL && elmpriv->descr_len > 0) {
sbuf_cat(&sb, "/elmdesc@");
for (i = 0, c = elmpriv->descr; i < elmpriv->descr_len;
@@ -1455,9 +1480,10 @@ ses_process_config(enc_softc_t *enc, struct enc_fsm_st
iter.global_element_index, iter.type_index, nelm,
iter.type_element_index);
thdr = ses_cache->ses_types[iter.type_index].hdr;
+ element->elm_idx = iter.global_element_index;
+ element->elm_type = thdr->etype_elm_type;
element->subenclosure = thdr->etype_subenc;
- element->enctype = thdr->etype_elm_type;
- element->overall_status_elem = iter.type_element_index == 0;
+ element->type_elm_idx = iter.type_element_index;
element->elm_private = malloc(sizeof(ses_element_t),
M_SCSIENC, M_WAITOK|M_ZERO);
ENC_DLOG(enc, "%s: creating elmpriv %d(%d,%d) subenc %d "
@@ -1661,6 +1687,8 @@ static int ses_get_elm_addlstatus_fc(enc_softc_t *, en
uint8_t *, int);
static int ses_get_elm_addlstatus_sas(enc_softc_t *, enc_cache_t *, uint8_t *,
int, int, int, int);
+static int ses_get_elm_addlstatus_ata(enc_softc_t *, enc_cache_t *, uint8_t *,
+ int, int, int, int);
/**
* \brief Parse the additional status element data for each object.
@@ -1816,7 +1844,6 @@ badindex:
}
}
elmpriv = element->elm_private;
- elmpriv->addl.hdr = elm_hdr;
ENC_DLOG(enc, "%s: global element index=%d, type index=%d "
"type element index=%d, offset=0x%x, "
"byte0=0x%x, length=0x%x\n", __func__,
@@ -1840,6 +1867,7 @@ badindex:
offset += elm_hdr->length;
continue;
}
+ elmpriv->addl.hdr = elm_hdr;
/* Advance to the protocol data, skipping eip bytes if needed */
offset += (eip * SES_EIP_HDR_EXTRA_LEN);
@@ -1863,6 +1891,13 @@ badindex:
eip, iter.type_index,
iter.global_element_index);
break;
+ case SPSP_PROTO_ATA:
+ ses_get_elm_addlstatus_ata(enc, enc_cache,
+ &buf[offset],
+ proto_info_len,
+ eip, iter.type_index,
+ iter.global_element_index);
+ break;
default:
ENC_VLOG(enc, "Element %d: Unknown Additional Element "
"Protocol 0x%x\n", iter.global_element_index,
@@ -2191,18 +2226,16 @@ ses_get_elm_addlstatus_fc(enc_softc_t *enc, enc_cache_
}
#define SES_PRINT_PORTS(p, type) do { \
- sbuf_printf(sbp, " %s(", type); \
- if (((p) & SES_SASOBJ_DEV_PHY_PROTOMASK) == 0) \
- sbuf_printf(sbp, " None"); \
- else { \
+ if (((p) & SES_SASOBJ_DEV_PHY_PROTOMASK) != 0) { \
+ sbuf_printf(sbp, " %s (", type); \
if ((p) & SES_SASOBJ_DEV_PHY_SMP) \
sbuf_printf(sbp, " SMP"); \
if ((p) & SES_SASOBJ_DEV_PHY_STP) \
sbuf_printf(sbp, " STP"); \
if ((p) & SES_SASOBJ_DEV_PHY_SSP) \
sbuf_printf(sbp, " SSP"); \
+ sbuf_printf(sbp, " )"); \
} \
- sbuf_printf(sbp, " )"); \
} while(0)
/**
@@ -2212,11 +2245,10 @@ ses_get_elm_addlstatus_fc(enc_softc_t *enc, enc_cache_
* \param sesname SES device name associated with the object.
* \param sbp Sbuf to print to.
* \param obj The object to print the data for.
- * \param periph_name Peripheral string associated with the object.
*/
static void
ses_print_addl_data_sas_type0(char *sesname, struct sbuf *sbp,
- enc_element_t *obj, char *periph_name)
+ enc_element_t *obj)
{
int i;
ses_element_t *elmpriv;
@@ -2225,16 +2257,12 @@ ses_print_addl_data_sas_type0(char *sesname, struct sb
elmpriv = obj->elm_private;
addl = &(elmpriv->addl);
- if (addl->proto_hdr.sas == NULL)
- return;
- sbuf_printf(sbp, "%s: %s: SAS Device Slot Element:",
- sesname, periph_name);
- sbuf_printf(sbp, " %d Phys", addl->proto_hdr.sas->base_hdr.num_phys);
+ sbuf_printf(sbp, ", SAS Slot: %d%s phys",
+ addl->proto_hdr.sas->base_hdr.num_phys,
+ ses_elm_sas_type0_not_all_phys(addl->proto_hdr.sas) ? "+" : "");
if (ses_elm_addlstatus_eip(addl->hdr))
- sbuf_printf(sbp, " at Slot %d",
+ sbuf_printf(sbp, " at slot %d",
addl->proto_hdr.sas->type0_eip.dev_slot_num);
- if (ses_elm_sas_type0_not_all_phys(addl->proto_hdr.sas))
- sbuf_printf(sbp, ", Not All Phys");
sbuf_printf(sbp, "\n");
if (addl->proto_data.sasdev_phys == NULL)
return;
@@ -2245,9 +2273,8 @@ ses_print_addl_data_sas_type0(char *sesname, struct sb
/* Spec says all other fields are specific values */
sbuf_printf(sbp, " SATA device\n");
else {
- sbuf_printf(sbp, " SAS device type %d id %d\n",
+ sbuf_printf(sbp, " SAS device type %d phy %d",
ses_elm_sas_dev_phy_dev_type(phy), phy->phy_id);
- sbuf_printf(sbp, "%s: phy %d: protocols:", sesname, i);
SES_PRINT_PORTS(phy->initiator_ports, "Initiator");
SES_PRINT_PORTS(phy->target_ports, "Target");
sbuf_printf(sbp, "\n");
@@ -2261,32 +2288,16 @@ ses_print_addl_data_sas_type0(char *sesname, struct sb
#undef SES_PRINT_PORTS
/**
- * \brief Report whether a given enclosure object is an expander.
- *
- * \param enc SES softc associated with object.
- * \param obj Enclosure object to report for.
- *
- * \return 1 if true, 0 otherwise.
- */
-static int
-ses_obj_is_expander(enc_softc_t *enc, enc_element_t *obj)
-{
- return (obj->enctype == ELMTYP_SAS_EXP);
-}
-
-/**
* \brief Print the additional element status data for this object, for SAS
* type 1 objects. See SES2 r20 Sections 6.1.13.3.3 and 6.1.13.3.4.
*
- * \param enc SES enclosure, needed for type identification.
* \param sesname SES device name associated with the object.
* \param sbp Sbuf to print to.
* \param obj The object to print the data for.
- * \param periph_name Peripheral string associated with the object.
*/
static void
-ses_print_addl_data_sas_type1(enc_softc_t *enc, char *sesname,
- struct sbuf *sbp, enc_element_t *obj, char *periph_name)
+ses_print_addl_data_sas_type1(char *sesname, struct sbuf *sbp,
+ enc_element_t *obj)
{
int i, num_phys;
ses_element_t *elmpriv;
@@ -2296,12 +2307,10 @@ ses_print_addl_data_sas_type1(enc_softc_t *enc, char *
elmpriv = obj->elm_private;
addl = &(elmpriv->addl);
- if (addl->proto_hdr.sas == NULL)
- return;
- sbuf_printf(sbp, "%s: %s: SAS ", sesname, periph_name);
- if (ses_obj_is_expander(enc, obj)) {
+ sbuf_printf(sbp, ", SAS ");
+ if (obj->elm_type == ELMTYP_SAS_EXP) {
num_phys = addl->proto_hdr.sas->base_hdr.num_phys;
- sbuf_printf(sbp, "Expander: %d Phys", num_phys);
+ sbuf_printf(sbp, "Expander: %d phys", num_phys);
if (addl->proto_data.sasexp_phys == NULL)
return;
for (i = 0;i < num_phys;i++) {
@@ -2312,7 +2321,7 @@ ses_print_addl_data_sas_type1(enc_softc_t *enc, char *
}
} else {
num_phys = addl->proto_hdr.sas->base_hdr.num_phys;
- sbuf_printf(sbp, "Port: %d Phys", num_phys);
+ sbuf_printf(sbp, "Port: %d phys", num_phys);
if (addl->proto_data.sasport_phys == NULL)
return;
for (i = 0;i < num_phys;i++) {
@@ -2328,6 +2337,24 @@ ses_print_addl_data_sas_type1(enc_softc_t *enc, char *
}
/**
+ * \brief Print the additional element status data for this object, for
+ * ATA objects.
+ *
+ * \param sbp Sbuf to print to.
+ * \param obj The object to print the data for.
+ */
+static void
+ses_print_addl_data_ata(struct sbuf *sbp, enc_element_t *obj)
+{
+ ses_element_t *elmpriv = obj->elm_private;
+ struct ses_addl_status *addl = &elmpriv->addl;
+ struct ses_elm_ata_hdr *ata = addl->proto_hdr.ata;
+
+ sbuf_printf(sbp, ", SATA Slot: scbus%d target %d\n",
+ scsi_4btoul(ata->bus), scsi_4btoul(ata->target));
+}
+
+/**
* \brief Print the additional element status data for this object.
*
* \param enc SES softc associated with the object.
@@ -2358,27 +2385,45 @@ ses_print_addl_data(enc_softc_t *enc, enc_element_t *o
sbuf_printf(&sesname, "%s%d", enc->periph->periph_name,
enc->periph->unit_number);
sbuf_finish(&sesname);
+ sbuf_printf(&out, "%s: %s in ", sbuf_data(&sesname), sbuf_data(&name));
if (elmpriv->descr != NULL)
- sbuf_printf(&out, "%s: %s: Element descriptor: '%s'\n",
- sbuf_data(&sesname), sbuf_data(&name), elmpriv->descr);
+ sbuf_printf(&out, "'%s'", elmpriv->descr);
+ else {
+ if (obj->elm_type <= ELMTYP_LAST)
+ sbuf_cat(&out, elm_type_names[obj->elm_type]);
+ else
+ sbuf_printf(&out, "<Type 0x%02x>", obj->elm_type);
+ sbuf_printf(&out, " %d", obj->type_elm_idx);
+ if (obj->subenclosure != 0)
+ sbuf_printf(&out, " of subenc %d", obj->subenclosure);
+ }
switch(ses_elm_addlstatus_proto(addl->hdr)) {
+ case SPSP_PROTO_FC:
+ goto noaddl; /* stubbed for now */
case SPSP_PROTO_SAS:
+ if (addl->proto_hdr.sas == NULL)
+ goto noaddl;
switch(ses_elm_sas_descr_type(addl->proto_hdr.sas)) {
case SES_SASOBJ_TYPE_SLOT:
ses_print_addl_data_sas_type0(sbuf_data(&sesname),
- &out, obj, sbuf_data(&name));
+ &out, obj);
break;
case SES_SASOBJ_TYPE_OTHER:
- ses_print_addl_data_sas_type1(enc, sbuf_data(&sesname),
- &out, obj, sbuf_data(&name));
+ ses_print_addl_data_sas_type1(sbuf_data(&sesname),
+ &out, obj);
break;
default:
- break;
+ goto noaddl;
}
break;
- case SPSP_PROTO_FC: /* stubbed for now */
+ case SPSP_PROTO_ATA:
+ if (addl->proto_hdr.ata == NULL)
+ goto noaddl;
+ ses_print_addl_data_ata(&out, obj);
break;
default:
+noaddl:
+ sbuf_cat(&out, "\n");
break;
}
sbuf_finish(&out);
@@ -2483,7 +2528,7 @@ ses_get_elm_addlstatus_sas_type1(enc_softc_t *enc, enc
goto out;
/* Process expanders differently from other type1 cases */
- if (ses_obj_is_expander(enc, obj)) {
+ if (obj->elm_type == ELMTYP_SAS_EXP) {
offset += sizeof(struct ses_elm_sas_type1_expander_hdr);
physz = addl->proto_hdr.sas->base_hdr.num_phys *
sizeof(struct ses_elm_sas_expander_phy);
@@ -2586,6 +2631,53 @@ ses_get_elm_addlstatus_sas(enc_softc_t *enc, enc_cache
err = ENODEV;
break;
}
+
+out:
+ return (err);
+}
+
+/**
+ * \brief Update the softc with the additional element status data for this
+ * object, for ATA objects.
+ *
+ * \param enc SES softc to be updated.
+ * \param buf The additional element status response buffer.
+ * \param bufsiz Size of the response buffer.
+ * \param eip The EIP bit value.
+ * \param tidx Type index for this object.
+ * \param nobj Number of objects attached to the SES softc.
+ *
+ * \return 0 on success, errno otherwise.
+ */
+static int
+ses_get_elm_addlstatus_ata(enc_softc_t *enc, enc_cache_t *enc_cache,
+ uint8_t *buf, int bufsiz, int eip, int tidx,
+ int nobj)
+{
+ int err;
+ ses_cache_t *ses_cache;
+
+ if (bufsiz < sizeof(struct ses_elm_ata_hdr)) {
+ err = EIO;
+ goto out;
+ }
+
+ ses_cache = enc_cache->private;
+ switch(ses_cache->ses_types[tidx].hdr->etype_elm_type) {
+ case ELMTYP_DEVICE:
+ case ELMTYP_ARRAY_DEV:
+ break;
+ default:
+ ENC_VLOG(enc, "Element %d has Additional Status, "
+ "invalid for SES element type 0x%x\n", nobj,
+ ses_cache->ses_types[tidx].hdr->etype_elm_type);
+ err = ENODEV;
+ goto out;
+ }
+
+ ((ses_element_t *)enc_cache->elm_map[nobj].elm_private)
+ ->addl.proto_hdr.ata = (struct ses_elm_ata_hdr *)buf;
+ err = 0;
out:
return (err);
Modified: stable/11/sys/cam/scsi/scsi_ses.h
==============================================================================
--- stable/11/sys/cam/scsi/scsi_ses.h Thu Aug 8 21:44:37 2019 (r350792)
+++ stable/11/sys/cam/scsi/scsi_ses.h Thu Aug 8 21:46:36 2019 (r350793)
@@ -2179,15 +2179,27 @@ struct ses_status_page_hdr {
#define SESCTL_DISABLE 0x20
#define SESCTL_RSTSWAP 0x10
-
-/* Control bits, Device Elements, byte 2 */
-#define SESCTL_DRVLCK 0x40 /* "DO NOT REMOVE" */
+/* Control bits, Array Device Slot Elements, byte 1 */
+#define SESCTL_RQSOK 0x80 /* RQST OK */
+#define SESCTL_RQSRSV 0x40 /* RQST RSVD DEVICE */
+#define SESCTL_RQSSPR 0x20 /* RQST HOT SPARE */
+#define SESCTL_RQSCCH 0x10 /* RQST CONS CHECK */
+#define SESCTL_RQSCRA 0x08 /* RQST IN CRIT ARRAY */
+#define SESCTL_RQSFAA 0x04 /* RQST IN FAILED ARRAY */
+#define SESCTL_RQSRR 0x02 /* RQST REBUI/REMAP */
+#define SESCTL_RQSRRA 0x01 /* RQST R/R ABORT */
+/* Control bits, [Array] Device Slot Elements, byte 2 */
+#define SESCTL_RQSACT 0x80 /* RQST ACTIVE */
+#define SESCTL_DRVLCK 0x40 /* DO NOT REMOVE */
+#define SESCTL_RQSMSN 0x10 /* RQST MISSING */
#define SESCTL_RQSINS 0x08 /* RQST INSERT */
#define SESCTL_RQSRMV 0x04 /* RQST REMOVE */
#define SESCTL_RQSID 0x02 /* RQST IDENT */
-/* Control bits, Device Elements, byte 3 */
+/* Control bits, [Array] Device Slot Elements, byte 3 */
#define SESCTL_RQSFLT 0x20 /* RQST FAULT */
#define SESCTL_DEVOFF 0x10 /* DEVICE OFF */
+#define SESCTL_ENBYPA 0x08 /* ENABLE BYP A */
+#define SESCTL_ENBYPB 0x04 /* ENABLE BYP B */
/* Control bits, Generic, byte 3 */
#define SESCTL_RQSTFAIL 0x40
@@ -2396,6 +2408,17 @@ union ses_elm_sas_hdr {
};
int ses_elm_sas_type0_not_all_phys(union ses_elm_sas_hdr *);
int ses_elm_sas_descr_type(union ses_elm_sas_hdr *);
+
+/*
+ * This structure for SPSP_PROTO_ATA is not defined by SES specs,
+ * but purely my own design to make AHCI EM interoperate with SES.
+ * Since no other software I know can talk to SEMB, and we do not
+ * expose this this outside, it should be safe to do what we want.
+ */
+struct ses_elm_ata_hdr {
+ uint8_t bus[4];
+ uint8_t target[4];
+};
struct ses_elm_addlstatus_base_hdr {
uint8_t byte0;
Modified: stable/11/sys/dev/ahci/ahci.c
==============================================================================
--- stable/11/sys/dev/ahci/ahci.c Thu Aug 8 21:44:37 2019 (r350792)
+++ stable/11/sys/dev/ahci/ahci.c Thu Aug 8 21:46:36 2019 (r350793)
@@ -184,6 +184,7 @@ ahci_attach(device_t dev)
ctlr->ccc = 0;
resource_int_value(device_get_name(dev),
device_get_unit(dev), "ccc", &ctlr->ccc);
+ mtx_init(&ctlr->ch_mtx, "AHCI channels lock", NULL, MTX_DEF);
/* Setup our own memory management for channels. */
ctlr->sc_iomem.rm_start = rman_get_start(ctlr->r_mem);
@@ -376,6 +377,7 @@ ahci_detach(device_t dev)
/* Free memory. */
rman_fini(&ctlr->sc_iomem);
ahci_free_mem(dev);
+ mtx_destroy(&ctlr->ch_mtx);
return (0);
}
@@ -663,6 +665,50 @@ ahci_get_dma_tag(device_t dev, device_t child)
return (ctlr->dma_tag);
}
+void
+ahci_attached(device_t dev, struct ahci_channel *ch)
+{
+ struct ahci_controller *ctlr = device_get_softc(dev);
+
+ mtx_lock(&ctlr->ch_mtx);
+ ctlr->ch[ch->unit] = ch;
+ mtx_unlock(&ctlr->ch_mtx);
+}
+
+void
+ahci_detached(device_t dev, struct ahci_channel *ch)
+{
+ struct ahci_controller *ctlr = device_get_softc(dev);
+
+ mtx_lock(&ctlr->ch_mtx);
+ mtx_lock(&ch->mtx);
+ ctlr->ch[ch->unit] = NULL;
+ mtx_unlock(&ch->mtx);
+ mtx_unlock(&ctlr->ch_mtx);
+}
+
+struct ahci_channel *
+ahci_getch(device_t dev, int n)
+{
+ struct ahci_controller *ctlr = device_get_softc(dev);
+ struct ahci_channel *ch;
+
+ KASSERT(n >= 0 && n < AHCI_MAX_PORTS, ("Bad channel number %d", n));
+ mtx_lock(&ctlr->ch_mtx);
+ ch = ctlr->ch[n];
+ if (ch != NULL)
+ mtx_lock(&ch->mtx);
+ mtx_unlock(&ctlr->ch_mtx);
+ return (ch);
+}
+
+void
+ahci_putch(struct ahci_channel *ch)
+{
+
+ mtx_unlock(&ch->mtx);
+}
+
static int
ahci_ch_probe(device_t dev)
{
@@ -821,6 +867,7 @@ ahci_ch_attach(device_t dev)
ahci_ch_pm, ch);
}
mtx_unlock(&ch->mtx);
+ ahci_attached(device_get_parent(dev), ch);
ctx = device_get_sysctl_ctx(dev);
tree = device_get_sysctl_tree(dev);
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "disable_phy",
@@ -846,6 +893,7 @@ ahci_ch_detach(device_t dev)
{
struct ahci_channel *ch = device_get_softc(dev);
+ ahci_detached(device_get_parent(dev), ch);
mtx_lock(&ch->mtx);
xpt_async(AC_LOST_DEVICE, ch->path, NULL);
/* Forget about reset. */
Modified: stable/11/sys/dev/ahci/ahci.h
==============================================================================
--- stable/11/sys/dev/ahci/ahci.h Thu Aug 8 21:44:37 2019 (r350792)
+++ stable/11/sys/dev/ahci/ahci.h Thu Aug 8 21:46:36 2019 (r350793)
@@ -521,6 +521,8 @@ struct ahci_controller {
void *argument;
} interrupt[AHCI_MAX_PORTS];
void (*ch_start)(struct ahci_channel *);
+ struct mtx ch_mtx; /* Lock for attached channels */
+ struct ahci_channel *ch[AHCI_MAX_PORTS]; /* Attached channels */
};
enum ahci_err_type {
@@ -648,6 +650,12 @@ bus_dma_tag_t ahci_get_dma_tag(device_t dev, device_t
int ahci_ctlr_reset(device_t dev);
int ahci_ctlr_setup(device_t dev);
void ahci_free_mem(device_t dev);
+
+/* Functions to allow AHCI EM to access other channels. */
+void ahci_attached(device_t dev, struct ahci_channel *ch);
+void ahci_detached(device_t dev, struct ahci_channel *ch);
+struct ahci_channel * ahci_getch(device_t dev, int n);
+void ahci_putch(struct ahci_channel *ch);
extern devclass_t ahci_devclass;
Modified: stable/11/sys/dev/ahci/ahciem.c
==============================================================================
--- stable/11/sys/dev/ahci/ahciem.c Thu Aug 8 21:44:37 2019 (r350792)
+++ stable/11/sys/dev/ahci/ahciem.c Thu Aug 8 21:46:36 2019 (r350793)
@@ -292,14 +292,14 @@ ahci_em_setleds(device_t dev, int c)
enc = device_get_softc(dev);
val = 0;
- if (enc->status[c][2] & 0x80) /* Activity */
+ if (enc->status[c][2] & SESCTL_RQSACT) /* Activity */
val |= (1 << 0);
- if (enc->status[c][2] & SESCTL_RQSID) /* Identification */
+ if (enc->status[c][1] & SESCTL_RQSRR) /* Rebuild */
+ val |= (1 << 6) | (1 << 3);
+ else if (enc->status[c][2] & SESCTL_RQSID) /* Identification */
val |= (1 << 3);
else if (enc->status[c][3] & SESCTL_RQSFLT) /* Fault */
val |= (1 << 6);
- else if (enc->status[c][1] & 0x02) /* Rebuild */
- val |= (1 << 6) | (1 << 3);
timeout = 10000;
while (ATA_INL(enc->r_memc, 0) & (AHCI_EM_TM | AHCI_EM_RST) &&
@@ -364,9 +364,12 @@ static void
ahci_em_emulate_ses_on_led(device_t dev, union ccb *ccb)
{
struct ahci_enclosure *enc;
+ struct ahci_channel *ch;
struct ses_status_page *page;
struct ses_status_array_dev_slot *ads, *ads0;
struct ses_elm_desc_hdr *elmd;
+ struct ses_elm_addlstatus_eip_hdr *elma;
+ struct ses_elm_ata_hdr *elmb;
uint8_t *buf;
int i;
@@ -389,7 +392,7 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *cc
strncpy(&buf[3], device_get_nameunit(dev), 7);
strncpy(&buf[10], "AHCI ", SID_VENDOR_SIZE);
strncpy(&buf[18], "SGPIO Enclosure ", SID_PRODUCT_SIZE);
- strncpy(&buf[34], "1.00", SID_REVISION_SIZE);
+ strncpy(&buf[34], "2.00", SID_REVISION_SIZE);
strncpy(&buf[39], "0001", 4);
strncpy(&buf[43], "S-E-S ", 6);
strncpy(&buf[49], "2.00", 4);
@@ -401,14 +404,15 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *cc
page = (struct ses_status_page *)buf;
if (ccb->ataio.cmd.lba_low == 0x02 &&
ccb->ataio.cmd.features == 0x00 &&
- ccb->ataio.cmd.sector_count >= 2) {
+ ccb->ataio.cmd.sector_count >= 3) {
bzero(buf, ccb->ataio.dxfer_len);
page->hdr.page_code = 0;
- scsi_ulto2b(4, page->hdr.length);
- buf[4] = 0;
- buf[5] = 1;
- buf[6] = 2;
- buf[7] = 7;
+ scsi_ulto2b(5, page->hdr.length);
+ buf[4] = 0x00;
+ buf[5] = 0x01;
+ buf[6] = 0x02;
+ buf[7] = 0x07;
+ buf[8] = 0x0a;
ccb->ccb_h.status = CAM_REQ_CMP;
goto out;
}
@@ -416,26 +420,30 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *cc
/* SEMB RECEIVE DIAGNOSTIC RESULT (1) */
if (ccb->ataio.cmd.lba_low == 0x02 &&
ccb->ataio.cmd.features == 0x01 &&
- ccb->ataio.cmd.sector_count >= 13) {
+ ccb->ataio.cmd.sector_count >= 16) {
struct ses_enc_desc *ed;
struct ses_elm_type_desc *td;
bzero(buf, ccb->ataio.dxfer_len);
page->hdr.page_code = 0x01;
- scsi_ulto2b(4 + 4 + 36 + 4, page->hdr.length);
+ scsi_ulto2b(4 + sizeof(*ed) + sizeof(*td) + 11,
+ page->hdr.length);
ed = (struct ses_enc_desc *)&buf[8];
ed->byte0 = 0x11;
ed->subenc_id = 0;
ed->num_types = 1;
ed->length = 36;
+ ed->logical_id[0] = 0x30; /* NAA Locally Assigned. */
+ strncpy(&ed->logical_id[1], device_get_nameunit(dev), 7);
strncpy(ed->vendor_id, "AHCI ", SID_VENDOR_SIZE);
strncpy(ed->product_id, "SGPIO Enclosure ", SID_PRODUCT_SIZE);
- strncpy(ed->product_rev, " ", SID_REVISION_SIZE);
+ strncpy(ed->product_rev, "2.00", SID_REVISION_SIZE);
td = (struct ses_elm_type_desc *)ses_enc_desc_next(ed);
td->etype_elm_type = 0x17;
td->etype_maxelt = enc->channels;
td->etype_subenc = 0;
- td->etype_txt_len = 0;
+ td->etype_txt_len = 11;
+ snprintf((char *)(td + 1), 12, "Drive Slots");
ccb->ccb_h.status = CAM_REQ_CMP;
goto out;
}
@@ -451,10 +459,22 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *cc
for (i = 0; i < enc->channels; i++) {
ads = &page->elements[i + 1].array_dev_slot;
memcpy(ads, enc->status[i], 4);
- ads->common.bytes[0] |=
- (enc->ichannels & (1 << i)) ?
- SES_OBJSTAT_UNKNOWN :
- SES_OBJSTAT_NOTINSTALLED;
+ ch = ahci_getch(device_get_parent(dev), i);
+ if (ch == NULL) {
+ ads->common.bytes[0] |= SES_OBJSTAT_UNKNOWN;
+ continue;
+ }
+ if (ch->pm_present)
+ ads->common.bytes[0] |= SES_OBJSTAT_UNKNOWN;
+ else if (ch->devices)
+ ads->common.bytes[0] |= SES_OBJSTAT_OK;
+ else if (ch->disablephy)
+ ads->common.bytes[0] |= SES_OBJSTAT_NOTAVAIL;
+ else
+ ads->common.bytes[0] |= SES_OBJSTAT_NOTINSTALLED;
+ if (ch->disablephy)
+ ads->common.bytes[3] |= SESCTL_DEVOFF;
+ ahci_putch(ch);
}
ccb->ccb_h.status = CAM_REQ_CMP;
goto out;
@@ -469,21 +489,21 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *cc
ads = &page->elements[i + 1].array_dev_slot;
if (ads->common.bytes[0] & SESCTL_CSEL) {
enc->status[i][0] = 0;
- enc->status[i][1] =
- ads->bytes[0] & 0x02;
- enc->status[i][2] =
- ads->bytes[1] & (0x80 | SESCTL_RQSID);
- enc->status[i][3] =
- ads->bytes[2] & SESCTL_RQSFLT;
+ enc->status[i][1] = ads->bytes[0] &
+ SESCTL_RQSRR;
+ enc->status[i][2] = ads->bytes[1] &
+ (SESCTL_RQSACT | SESCTL_RQSID);
+ enc->status[i][3] = ads->bytes[2] &
+ SESCTL_RQSFLT;
ahci_em_setleds(dev, i);
} else if (ads0->common.bytes[0] & SESCTL_CSEL) {
enc->status[i][0] = 0;
- enc->status[i][1] =
- ads0->bytes[0] & 0x02;
- enc->status[i][2] =
- ads0->bytes[1] & (0x80 | SESCTL_RQSID);
- enc->status[i][3] =
- ads0->bytes[2] & SESCTL_RQSFLT;
+ enc->status[i][1] = ads0->bytes[0] &
+ SESCTL_RQSRR;
+ enc->status[i][2] = ads0->bytes[1] &
+ (SESCTL_RQSACT | SESCTL_RQSID);
+ enc->status[i][3] = ads0->bytes[2] &
+ SESCTL_RQSFLT;
ahci_em_setleds(dev, i);
}
}
@@ -494,15 +514,48 @@ ahci_em_emulate_ses_on_led(device_t dev, union ccb *cc
/* SEMB RECEIVE DIAGNOSTIC RESULT (7) */
if (ccb->ataio.cmd.lba_low == 0x02 &&
ccb->ataio.cmd.features == 0x07 &&
- ccb->ataio.cmd.sector_count >= (3 + 3 * enc->channels)) {
+ ccb->ataio.cmd.sector_count >= (6 + 3 * enc->channels)) {
bzero(buf, ccb->ataio.dxfer_len);
page->hdr.page_code = 0x07;
- scsi_ulto2b(4 + 4 + 12 * enc->channels,
+ scsi_ulto2b(4 + 15 + 11 * enc->channels, page->hdr.length);
+ elmd = (struct ses_elm_desc_hdr *)&buf[8];
+ scsi_ulto2b(11, elmd->length);
+ snprintf((char *)(elmd + 1), 12, "Drive Slots");
+ for (i = 0; i < enc->channels; i++) {
+ elmd = (struct ses_elm_desc_hdr *)&buf[8 + 15 + 11 * i];
+ scsi_ulto2b(7, elmd->length);
+ snprintf((char *)(elmd + 1), 8, "Slot %02d", i);
+ }
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ goto out;
+ }
+
+ /* SEMB RECEIVE DIAGNOSTIC RESULT (a) */
+ if (ccb->ataio.cmd.lba_low == 0x02 &&
+ ccb->ataio.cmd.features == 0x0a &&
+ ccb->ataio.cmd.sector_count >= (2 + 3 * enc->channels)) {
+ bzero(buf, ccb->ataio.dxfer_len);
+ page->hdr.page_code = 0x0a;
+ scsi_ulto2b(4 + (sizeof(*elma) + sizeof(*elmb)) * enc->channels,
page->hdr.length);
for (i = 0; i < enc->channels; i++) {
- elmd = (struct ses_elm_desc_hdr *)&buf[8 + 4 + 12 * i];
- scsi_ulto2b(8, elmd->length);
- snprintf((char *)(elmd + 1), 9, "SLOT %03d", i);
+ elma = (struct ses_elm_addlstatus_eip_hdr *)&buf[
+ 8 + (sizeof(*elma) + sizeof(*elmb)) * i];
+ elma->base.byte0 = 0x10 | SPSP_PROTO_ATA;
+ elma->base.length = 2 + sizeof(*elmb);
+ elma->byte2 = 0x01;
+ elma->element_index = 1 + i;
+ ch = ahci_getch(device_get_parent(dev), i);
+ if (ch == NULL) {
+ elma->base.byte0 |= 0x80;
+ continue;
+ }
+ if (ch->devices == 0 || ch->pm_present)
+ elma->base.byte0 |= 0x80;
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable-11
mailing list