svn commit: r225024 - in projects/zfsd/head: sbin/camcontrol
sys/cam sys/cam/ata sys/cam/scsi sys/sys
Alexander Motin
mav at FreeBSD.org
Sat Aug 20 09:31:52 UTC 2011
Author: mav
Date: Sat Aug 20 09:31:52 2011
New Revision: 225024
URL: http://svn.freebsd.org/changeset/base/225024
Log:
Add support for SATA Enclosure Management Bridge (SEMB).
Modified:
projects/zfsd/head/sbin/camcontrol/camcontrol.c
projects/zfsd/head/sys/cam/ata/ata_all.c
projects/zfsd/head/sys/cam/ata/ata_all.h
projects/zfsd/head/sys/cam/ata/ata_da.c
projects/zfsd/head/sys/cam/ata/ata_xpt.c
projects/zfsd/head/sys/cam/cam_ccb.h
projects/zfsd/head/sys/cam/cam_xpt.c
projects/zfsd/head/sys/cam/scsi/scsi_all.h
projects/zfsd/head/sys/cam/scsi/scsi_enc.c
projects/zfsd/head/sys/cam/scsi/scsi_enc_internal.h
projects/zfsd/head/sys/cam/scsi/scsi_enc_ses.c
projects/zfsd/head/sys/sys/ata.h
Modified: projects/zfsd/head/sbin/camcontrol/camcontrol.c
==============================================================================
--- projects/zfsd/head/sbin/camcontrol/camcontrol.c Sat Aug 20 08:20:10 2011 (r225023)
+++ projects/zfsd/head/sbin/camcontrol/camcontrol.c Sat Aug 20 09:31:52 2011 (r225024)
@@ -456,7 +456,7 @@ getdevtree(void)
case DEV_MATCH_DEVICE: {
struct device_match_result *dev_result;
char vendor[16], product[48], revision[16];
- char tmpstr[256];
+ char fw[5], tmpstr[256];
dev_result =
&ccb.cdm.matches[i].result.device_result;
@@ -495,6 +495,25 @@ getdevtree(void)
sizeof(revision));
sprintf(tmpstr, "<%s %s>", product,
revision);
+ } else if (dev_result->protocol == PROTO_SEMB) {
+ struct sep_identify_data *sid;
+
+ sid = (struct sep_identify_data *)
+ &dev_result->ident_data;
+ cam_strvis(vendor, sid->vendor_id,
+ sizeof(sid->vendor_id),
+ sizeof(vendor));
+ cam_strvis(product, sid->product_id,
+ sizeof(sid->product_id),
+ sizeof(product));
+ cam_strvis(revision, sid->product_rev,
+ sizeof(sid->product_rev),
+ sizeof(revision));
+ cam_strvis(fw, sid->firmware_rev,
+ sizeof(sid->firmware_rev),
+ sizeof(fw));
+ sprintf(tmpstr, "<%s %s %s %s>",
+ vendor, product, revision, fw);
} else {
sprintf(tmpstr, "<>");
}
@@ -1131,7 +1150,7 @@ atacapprint(struct ata_params *parm)
printf("firmware revision %.8s\n", parm->revision);
printf("serial number %.20s\n", parm->serial);
if (parm->enabled.extension & ATA_SUPPORT_64BITWWN) {
- printf("WWN %02x%02x%02x%02x\n",
+ printf("WWN %04x%04x%04x%04x\n",
parm->wwn[0], parm->wwn[1], parm->wwn[2], parm->wwn[3]);
}
if (parm->enabled.extension & ATA_SUPPORT_MEDIASN) {
Modified: projects/zfsd/head/sys/cam/ata/ata_all.c
==============================================================================
--- projects/zfsd/head/sys/cam/ata/ata_all.c Sat Aug 20 08:20:10 2011 (r225023)
+++ projects/zfsd/head/sys/cam/ata/ata_all.c Sat Aug 20 09:31:52 2011 (r225024)
@@ -108,6 +108,16 @@ ata_op_string(struct ata_cmd *cmd)
case 0x51: return ("CONFIGURE_STREAM");
case 0x60: return ("READ_FPDMA_QUEUED");
case 0x61: return ("WRITE_FPDMA_QUEUED");
+ case 0x67:
+ if (cmd->features == 0xec)
+ return ("SEP_ATTN IDENTIFY");
+ switch (cmd->lba_low) {
+ case 0x00: return ("SEP_ATTN READ BUFFER");
+ case 0x02: return ("SEP_ATTN RECEIVE DIAGNOSTIC RESULTS");
+ case 0x80: return ("SEP_ATTN WRITE BUFFER");
+ case 0x82: return ("SEP_ATTN SEND DIAGNOSTIC");
+ }
+ return ("SEP_ATTN");
case 0x70: return ("SEEK");
case 0x87: return ("CFA_TRANSLATE_SECTOR");
case 0x90: return ("EXECUTE_DEVICE_DIAGNOSTIC");
@@ -286,6 +296,21 @@ ata_print_ident(struct ata_params *ident
printf(" device\n");
}
+void
+semb_print_ident(struct sep_identify_data *ident_data)
+{
+ char vendor[9], product[17], revision[5], fw[5], in[7], ins[5];
+
+ cam_strvis(vendor, ident_data->vendor_id, 8, sizeof(vendor));
+ cam_strvis(product, ident_data->product_id, 16, sizeof(product));
+ cam_strvis(revision, ident_data->product_rev, 4, sizeof(revision));
+ cam_strvis(fw, ident_data->firmware_rev, 4, sizeof(fw));
+ cam_strvis(in, ident_data->interface_id, 6, sizeof(in));
+ cam_strvis(ins, ident_data->interface_rev, 4, sizeof(ins));
+ printf("<%s %s %s %s> SEMB %s %s device\n",
+ vendor, product, revision, fw, in, ins);
+}
+
uint32_t
ata_logical_sector_size(struct ata_params *ident_data)
{
@@ -695,3 +720,45 @@ ata_static_identify_match(caddr_t identb
}
return (-1);
}
+
+void
+semb_receive_diagnostic_results(struct ccb_ataio *ataio,
+ u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*),
+ uint8_t tag_action, int pcv, uint8_t page_code,
+ uint8_t *data_ptr, uint16_t length, uint32_t timeout)
+{
+
+ length = min(length, 1020);
+ length = (length + 3) & ~3;
+ cam_fill_ataio(ataio,
+ retries,
+ cbfcnp,
+ /*flags*/CAM_DIR_IN,
+ tag_action,
+ data_ptr,
+ length,
+ timeout);
+ ata_28bit_cmd(ataio, ATA_SEP_ATTN,
+ pcv ? page_code : 0, 0x02, length / 4);
+}
+
+void
+semb_send_diagnostic(struct ccb_ataio *ataio,
+ u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint8_t tag_action, uint8_t *data_ptr, uint16_t length, uint32_t timeout)
+{
+
+ length = min(length, 1020);
+ length = (length + 3) & ~3;
+ cam_fill_ataio(ataio,
+ retries,
+ cbfcnp,
+ /*flags*/length ? CAM_DIR_OUT : CAM_DIR_NONE,
+ tag_action,
+ data_ptr,
+ length,
+ timeout);
+ ata_28bit_cmd(ataio, ATA_SEP_ATTN,
+ length > 0 ? data_ptr[0] : 0, 0x82, length / 4);
+}
+
Modified: projects/zfsd/head/sys/cam/ata/ata_all.h
==============================================================================
--- projects/zfsd/head/sys/cam/ata/ata_all.h Sat Aug 20 08:20:10 2011 (r225023)
+++ projects/zfsd/head/sys/cam/ata/ata_all.h Sat Aug 20 09:31:52 2011 (r225024)
@@ -83,6 +83,20 @@ struct ata_res {
u_int8_t sector_count_exp;
};
+struct sep_identify_data {
+ uint8_t length; /* Enclosure descriptor length */
+ uint8_t subenc_id; /* Sub-enclosure identifier */
+ uint8_t logical_id[8]; /* Enclosure logical identifier (WWN) */
+ uint8_t vendor_id[8]; /* Vendor identification string */
+ uint8_t product_id[16]; /* Product identification string */
+ uint8_t product_rev[4]; /* Product revision string */
+ uint8_t channel_id; /* Channel identifier */
+ uint8_t firmware_rev[4];/* Firmware revision */
+ uint8_t interface_id[6];/* Interface spec ("S-E-S "/"SAF-TE")*/
+ uint8_t interface_rev[4];/* Interface spec revision */
+ uint8_t vend_spec[11]; /* Vendor specific information */
+};
+
int ata_version(int ver);
char * ata_op_string(struct ata_cmd *cmd);
@@ -126,4 +140,16 @@ int ata_speed2revision(u_int speed);
int ata_identify_match(caddr_t identbuffer, caddr_t table_entry);
int ata_static_identify_match(caddr_t identbuffer, caddr_t table_entry);
+void semb_print_ident(struct sep_identify_data *ident_data);
+
+void semb_receive_diagnostic_results(struct ccb_ataio *ataio,
+ u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*),
+ uint8_t tag_action, int pcv, uint8_t page_code,
+ uint8_t *data_ptr, uint16_t allocation_length, uint32_t timeout);
+
+void semb_send_diagnostic(struct ccb_ataio *ataio,
+ u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint8_t tag_action, uint8_t *data_ptr, uint16_t param_list_length,
+ uint32_t timeout);
+
#endif
Modified: projects/zfsd/head/sys/cam/ata/ata_da.c
==============================================================================
--- projects/zfsd/head/sys/cam/ata/ata_da.c Sat Aug 20 08:20:10 2011 (r225023)
+++ projects/zfsd/head/sys/cam/ata/ata_da.c Sat Aug 20 09:31:52 2011 (r225024)
@@ -754,6 +754,20 @@ adaasync(void *callback_arg, u_int32_t c
"due to status 0x%x\n", status);
break;
}
+ case AC_ADVINFO_CHANGED:
+ {
+ uintptr_t buftype;
+
+ buftype = (uintptr_t)arg;
+ if (buftype == CDAI_TYPE_PHYS_PATH) {
+ struct ada_softc *softc;
+
+ softc = periph->softc;
+ disk_attr_changed(softc->disk, "GEOM::physpath",
+ M_NOWAIT);
+ }
+ break;
+ }
case AC_SENT_BDR:
case AC_BUS_RESET:
{
@@ -1066,8 +1080,8 @@ adaregister(struct cam_periph *periph, v
* them and the only alternative would be to
* not attach the device on failure.
*/
- xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE,
- adaasync, periph, periph->path);
+ xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE |
+ AC_ADVINFO_CHANGED, adaasync, periph, periph->path);
/*
* Schedule a periodic event to occasionally send an
Modified: projects/zfsd/head/sys/cam/ata/ata_xpt.c
==============================================================================
--- projects/zfsd/head/sys/cam/ata/ata_xpt.c Sat Aug 20 08:20:10 2011 (r225023)
+++ projects/zfsd/head/sys/cam/ata/ata_xpt.c Sat Aug 20 09:31:52 2011 (r225024)
@@ -93,6 +93,8 @@ typedef enum {
PROBE_FULL_INQUIRY,
PROBE_PM_PID,
PROBE_PM_PRV,
+ PROBE_IDENTIFY_SES,
+ PROBE_IDENTIFY_SAFTE,
PROBE_INVALID
} probe_action;
@@ -110,6 +112,8 @@ static char *probe_action_text[] = {
"PROBE_FULL_INQUIRY",
"PROBE_PM_PID",
"PROBE_PM_PRV",
+ "PROBE_IDENTIFY_SES",
+ "PROBE_IDENTIFY_SAFTE",
"PROBE_INVALID"
};
@@ -260,7 +264,8 @@ probeschedule(struct cam_periph *periph)
ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs);
if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) ||
- periph->path->device->protocol == PROTO_SATAPM)
+ periph->path->device->protocol == PROTO_SATAPM ||
+ periph->path->device->protocol == PROTO_SEMB)
PROBE_SET_ACTION(softc, PROBE_RESET);
else
PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
@@ -294,7 +299,8 @@ probestart(struct cam_periph *periph, un
if (softc->restart) {
softc->restart = 0;
if ((path->device->flags & CAM_DEV_UNCONFIGURED) ||
- path->device->protocol == PROTO_SATAPM)
+ path->device->protocol == PROTO_SATAPM ||
+ path->device->protocol == PROTO_SEMB)
softc->action = PROBE_RESET;
else
softc->action = PROBE_IDENTIFY;
@@ -609,6 +615,30 @@ negotiate:
10 * 1000);
ata_pm_read_cmd(ataio, 1, 15);
break;
+ case PROBE_IDENTIFY_SES:
+ cam_fill_ataio(ataio,
+ 1,
+ probedone,
+ /*flags*/CAM_DIR_IN,
+ 0,
+ /*data_ptr*/(u_int8_t *)&softc->ident_data,
+ /*dxfer_len*/sizeof(softc->ident_data),
+ 30 * 1000);
+ ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x02,
+ sizeof(softc->ident_data) / 4);
+ break;
+ case PROBE_IDENTIFY_SAFTE:
+ cam_fill_ataio(ataio,
+ 1,
+ probedone,
+ /*flags*/CAM_DIR_IN,
+ 0,
+ /*data_ptr*/(u_int8_t *)&softc->ident_data,
+ /*dxfer_len*/sizeof(softc->ident_data),
+ 30 * 1000);
+ ata_28bit_cmd(ataio, ATA_SEP_ATTN, 0xEC, 0x00,
+ sizeof(softc->ident_data) / 4);
+ break;
case PROBE_INVALID:
CAM_DEBUG(path, CAM_DEBUG_INFO,
("probestart: invalid action state\n"));
@@ -745,12 +775,16 @@ probedone(struct cam_periph *periph, uni
{
struct ccb_trans_settings cts;
struct ata_params *ident_buf;
+ struct scsi_inquiry_data *inq_buf;
probe_softc *softc;
struct cam_path *path;
cam_status status;
u_int32_t priority;
u_int caps;
- int found = 1;
+ int changed = 1, found = 1;
+ static const uint8_t fake_device_id_hdr[8] =
+ {0, SVPD_DEVICE_ID, 0, 12,
+ SVPD_ID_CODESET_BINARY, SVPD_ID_TYPE_NAA, 0, 8};
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n"));
@@ -758,6 +792,7 @@ probedone(struct cam_periph *periph, uni
path = done_ccb->ccb_h.path;
priority = done_ccb->ccb_h.pinfo.priority;
ident_buf = &path->device->ident_data;
+ inq_buf = &path->device->inq_data;
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
if (softc->restart) {
@@ -806,6 +841,18 @@ probedone(struct cam_periph *periph, uni
} else if (softc->action == PROBE_SETDMAAA &&
status == CAM_ATA_STATUS_ERROR) {
goto noerror;
+
+ /*
+ * SES and SAF-TE SEPs have different IDENTIFY commands,
+ * but SATA specification doesn't tell how to identify them.
+ * Until better way found, just try another if first fail.
+ */
+ } else if (softc->action == PROBE_IDENTIFY_SES &&
+ status == CAM_ATA_STATUS_ERROR) {
+ PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SAFTE);
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, priority);
+ return;
}
/*
@@ -849,6 +896,10 @@ noerror:
xpt_action((union ccb *)&cts);
path->device->protocol = PROTO_SATAPM;
PROBE_SET_ACTION(softc, PROBE_PM_PID);
+ } else if (sign == 0xc33c &&
+ done_ccb->ccb_h.target_id != 15) {
+ path->device->protocol = PROTO_SEMB;
+ PROBE_SET_ACTION(softc, PROBE_IDENTIFY_SES);
} else if (sign == 0xeb14 &&
done_ccb->ccb_h.target_id != 15) {
path->device->protocol = PROTO_SCSI;
@@ -868,7 +919,6 @@ noerror:
{
struct ccb_pathinq cpi;
int16_t *ptr;
- int changed = 1;
ident_buf = &softc->ident_data;
for (ptr = (int16_t *)ident_buf;
@@ -923,6 +973,11 @@ noerror:
path->device->serial_num = NULL;
path->device->serial_num_len = 0;
}
+ if (path->device->device_id != NULL) {
+ free(path->device->device_id, M_CAMXPT);
+ path->device->device_id = NULL;
+ path->device->device_id_len = 0;
+ }
path->device->serial_num =
(u_int8_t *)malloc((sizeof(ident_buf->serial) + 1),
M_CAMXPT, M_NOWAIT);
@@ -935,6 +990,18 @@ noerror:
path->device->serial_num_len =
strlen(path->device->serial_num);
}
+ if (ident_buf->enabled.extension &
+ ATA_SUPPORT_64BITWWN) {
+ path->device->device_id =
+ malloc(16, M_CAMXPT, M_NOWAIT);
+ if (path->device->device_id != NULL) {
+ path->device->device_id_len = 16;
+ bcopy(&fake_device_id_hdr,
+ path->device->device_id, 8);
+ bcopy(ident_buf->wwn,
+ path->device->device_id + 8, 8);
+ }
+ }
path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID;
}
@@ -1079,11 +1146,9 @@ notsata:
case PROBE_INQUIRY:
case PROBE_FULL_INQUIRY:
{
- struct scsi_inquiry_data *inq_buf;
u_int8_t periph_qual, len;
path->device->flags |= CAM_DEV_INQUIRY_DATA_VALID;
- inq_buf = &path->device->inq_data;
periph_qual = SID_QUAL(inq_buf);
@@ -1187,6 +1252,48 @@ notsata:
xpt_async(AC_SCSI_AEN, done_ccb->ccb_h.path, done_ccb);
}
break;
+ case PROBE_IDENTIFY_SES:
+ case PROBE_IDENTIFY_SAFTE:
+ if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) {
+ /* Check that it is the same device. */
+ if (bcmp(&softc->ident_data, ident_buf, 53)) {
+ /* Device changed. */
+ xpt_async(AC_LOST_DEVICE, path, NULL);
+ } else {
+ bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params));
+ changed = 0;
+ }
+ }
+ if (changed) {
+ bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params));
+ /* Clean up from previous instance of this device */
+ if (path->device->device_id != NULL) {
+ free(path->device->device_id, M_CAMXPT);
+ path->device->device_id = NULL;
+ path->device->device_id_len = 0;
+ }
+ path->device->device_id =
+ malloc(16, M_CAMXPT, M_NOWAIT);
+ if (path->device->device_id != NULL) {
+ path->device->device_id_len = 16;
+ bcopy(&fake_device_id_hdr,
+ path->device->device_id, 8);
+ bcopy(((uint8_t*)ident_buf) + 2,
+ path->device->device_id + 8, 8);
+ }
+
+ path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID;
+ }
+
+ if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) {
+ path->device->flags &= ~CAM_DEV_UNCONFIGURED;
+ xpt_acquire_device(path->device);
+ done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
+ xpt_action(done_ccb);
+ xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path,
+ done_ccb);
+ }
+ break;
case PROBE_INVALID:
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_INFO,
("probedone: invalid action state\n"));
@@ -1611,10 +1718,20 @@ ata_dev_advinfo(union ccb *start_ccb)
device = start_ccb->ccb_h.path->device;
cdai = &start_ccb->cdai;
switch(cdai->buftype) {
- case CDAI_TYPE_SERIAL_NUM:
+ case CDAI_TYPE_SCSI_DEVID:
if (cdai->flags & CDAI_FLAG_STORE)
+ return;
+ cdai->provsiz = device->device_id_len;
+ if (device->device_id_len == 0)
break;
- start_ccb->ccb_h.status = CAM_REQ_CMP;
+ amt = device->device_id_len;
+ if (cdai->provsiz > cdai->bufsiz)
+ amt = cdai->bufsiz;
+ memcpy(cdai->buf, device->device_id, amt);
+ break;
+ case CDAI_TYPE_SERIAL_NUM:
+ if (cdai->flags & CDAI_FLAG_STORE)
+ return;
cdai->provsiz = device->serial_num_len;
if (device->serial_num_len == 0)
break;
@@ -1623,8 +1740,45 @@ ata_dev_advinfo(union ccb *start_ccb)
amt = cdai->bufsiz;
memcpy(cdai->buf, device->serial_num, amt);
break;
- default:
+ case CDAI_TYPE_PHYS_PATH:
+ if (cdai->flags & CDAI_FLAG_STORE) {
+ if (device->physpath != NULL)
+ free(device->physpath, M_CAMXPT);
+ device->physpath_len = cdai->bufsiz;
+ /* Clear existing buffer if zero length */
+ if (cdai->bufsiz == 0)
+ break;
+ device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT);
+ if (device->physpath == NULL) {
+ start_ccb->ccb_h.status = CAM_REQ_ABORTED;
+ return;
+ }
+ memcpy(device->physpath, cdai->buf, cdai->bufsiz);
+ } else {
+ cdai->provsiz = device->physpath_len;
+ if (device->physpath_len == 0)
+ break;
+ amt = device->physpath_len;
+ if (cdai->provsiz > cdai->bufsiz)
+ amt = cdai->bufsiz;
+ memcpy(cdai->buf, device->physpath, amt);
+ }
break;
+ default:
+ return;
+ }
+ start_ccb->ccb_h.status = CAM_REQ_CMP;
+
+ if (cdai->flags & CDAI_FLAG_STORE) {
+ int owned;
+
+ owned = mtx_owned(start_ccb->ccb_h.path->bus->sim->mtx);
+ if (owned == 0)
+ mtx_lock(start_ccb->ccb_h.path->bus->sim->mtx);
+ xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path,
+ (void *)(uintptr_t)cdai->buftype);
+ if (owned == 0)
+ mtx_unlock(start_ccb->ccb_h.path->bus->sim->mtx);
}
}
Modified: projects/zfsd/head/sys/cam/cam_ccb.h
==============================================================================
--- projects/zfsd/head/sys/cam/cam_ccb.h Sat Aug 20 08:20:10 2011 (r225023)
+++ projects/zfsd/head/sys/cam/cam_ccb.h Sat Aug 20 09:31:52 2011 (r225024)
@@ -242,6 +242,7 @@ typedef enum {
PROTO_ATA, /* AT Attachment */
PROTO_ATAPI, /* AT Attachment Packetized Interface */
PROTO_SATAPM, /* SATA Port Multiplier */
+ PROTO_SEMB, /* SATA Enclosure Management Bridge */
} cam_proto;
typedef enum {
Modified: projects/zfsd/head/sys/cam/cam_xpt.c
==============================================================================
--- projects/zfsd/head/sys/cam/cam_xpt.c Sat Aug 20 08:20:10 2011 (r225023)
+++ projects/zfsd/head/sys/cam/cam_xpt.c Sat Aug 20 09:31:52 2011 (r225024)
@@ -1081,6 +1081,9 @@ xpt_announce_periph(struct cam_periph *p
else if (path->device->protocol == PROTO_ATA ||
path->device->protocol == PROTO_SATAPM)
ata_print_ident(&path->device->ident_data);
+ else if (path->device->protocol == PROTO_SEMB)
+ semb_print_ident(
+ (struct sep_identify_data *)&path->device->ident_data);
else
printf("Unknown protocol device\n");
if (bootverbose && path->device->serial_num_len > 0) {
Modified: projects/zfsd/head/sys/cam/scsi/scsi_all.h
==============================================================================
--- projects/zfsd/head/sys/cam/scsi/scsi_all.h Sat Aug 20 08:20:10 2011 (r225023)
+++ projects/zfsd/head/sys/cam/scsi/scsi_all.h Sat Aug 20 09:31:52 2011 (r225024)
@@ -869,6 +869,8 @@ struct scsi_vpd_id_descriptor
#define SCSI_PROTO_RDMA 0x04
#define SCSI_PROTO_iSCSI 0x05
#define SCSI_PROTO_SAS 0x06
+#define SCSI_PROTO_ADT 0x07
+#define SCSI_PROTO_ATA 0x08
#define SVPD_ID_PROTO_SHIFT 4
#define SVPD_ID_CODESET_BINARY 0x01
#define SVPD_ID_CODESET_ASCII 0x02
Modified: projects/zfsd/head/sys/cam/scsi/scsi_enc.c
==============================================================================
--- projects/zfsd/head/sys/cam/scsi/scsi_enc.c Sat Aug 20 08:20:10 2011 (r225023)
+++ projects/zfsd/head/sys/cam/scsi/scsi_enc.c Sat Aug 20 09:31:52 2011 (r225024)
@@ -74,7 +74,7 @@ static periph_dtor_t enc_dtor;
static periph_start_t enc_start;
static void enc_async(void *, uint32_t, struct cam_path *, void *);
-static enctyp enc_type(void *, int);
+static enctyp enc_type(struct ccb_getdev *);
static struct periph_driver encdriver = {
enc_init, "enc",
@@ -183,7 +183,6 @@ enc_async(void *callback_arg, uint32_t c
{
struct ccb_getdev *cgd;
cam_status status;
- int inq_len;
path_id_t path_id;
cgd = (struct ccb_getdev *)arg;
@@ -191,23 +190,7 @@ enc_async(void *callback_arg, uint32_t c
break;
}
- if (cgd->protocol != PROTO_SCSI)
- break;
-
- inq_len = cgd->inq_data.additional_length + 4;
-
- /*
- * PROBLEM: WE NEED TO LOOK AT BYTES 48-53 TO SEE IF THIS
- * PROBLEM: IS A SAF-TE DEVICE.
- */
- switch (enc_type(&cgd->inq_data, inq_len)) {
- case ENC_SES:
- case ENC_SES_SCSI2:
- case ENC_SES_PASSTHROUGH:
- case ENC_SEN:
- case ENC_SAFT:
- break;
- default:
+ if (enc_type(cgd) == ENC_NONE) {
/*
* Schedule announcement of the ENC bindings for
* this device if it is managed by a SEP.
@@ -564,7 +547,7 @@ enc_ioctl(struct cdev *dev, u_long cmd,
int
enc_runcmd(struct enc_softc *enc, char *cdb, int cdbl, char *dptr, int *dlenp)
{
- int error, dlen;
+ int error, dlen, tdlen;
ccb_flags ddf;
union ccb *ccb;
@@ -587,9 +570,32 @@ enc_runcmd(struct enc_softc *enc, char *
}
ccb = cam_periph_getccb(enc->periph, 1);
- cam_fill_csio(&ccb->csio, 0, enc_done, ddf, MSG_SIMPLE_Q_TAG, dptr,
- dlen, sizeof (struct scsi_sense_data), cdbl, 60 * 1000);
- bcopy(cdb, ccb->csio.cdb_io.cdb_bytes, cdbl);
+ if (enc->enc_type == ENC_SEMB_SES || enc->enc_type == ENC_SEMB_SAFT) {
+ tdlen = min(dlen, 1020);
+ tdlen = (tdlen + 3) & ~3;
+ cam_fill_ataio(&ccb->ataio, 0, enc_done, ddf, 0, dptr, tdlen,
+ 30 * 1000);
+ if (cdb[0] == RECEIVE_DIAGNOSTIC)
+ ata_28bit_cmd(&ccb->ataio,
+ ATA_SEP_ATTN, cdb[2], 0x02, tdlen / 4);
+ else if (cdb[0] == SEND_DIAGNOSTIC)
+ ata_28bit_cmd(&ccb->ataio,
+ ATA_SEP_ATTN, dlen > 0 ? dptr[0] : 0,
+ 0x82, tdlen / 4);
+ else if (cdb[0] == READ_BUFFER)
+ ata_28bit_cmd(&ccb->ataio,
+ ATA_SEP_ATTN, cdb[2], 0x00, tdlen / 4);
+ else
+ ata_28bit_cmd(&ccb->ataio,
+ ATA_SEP_ATTN, dlen > 0 ? dptr[0] : 0,
+ 0x80, tdlen / 4);
+ } else {
+ tdlen = dlen;
+ cam_fill_csio(&ccb->csio, 0, enc_done, ddf, MSG_SIMPLE_Q_TAG,
+ dptr, dlen, sizeof (struct scsi_sense_data), cdbl,
+ 60 * 1000);
+ bcopy(cdb, ccb->csio.cdb_io.cdb_bytes, cdbl);
+ }
error = cam_periph_runccb(ccb, enc_error, ENC_CFLAGS, ENC_FLAGS, NULL);
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
@@ -600,7 +606,11 @@ enc_runcmd(struct enc_softc *enc, char *
}
} else {
if (dptr) {
- *dlenp = ccb->csio.resid;
+ if (ccb->ccb_h.func_code == XPT_ATA_IO)
+ *dlenp = ccb->ataio.resid;
+ else
+ *dlenp = ccb->csio.resid;
+ *dlenp += tdlen - dlen;
}
}
xpt_release_ccb(ccb);
@@ -639,10 +649,25 @@ enc_log(struct enc_softc *enc, const cha
#define SAFTE_LEN SAFTE_END-SAFTE_START
static enctyp
-enc_type(void *buf, int buflen)
+enc_type(struct ccb_getdev *cgd)
{
- unsigned char *iqd = buf;
+ int buflen;
+ unsigned char *iqd;
+ if (cgd->protocol == PROTO_SEMB) {
+ iqd = (unsigned char *)&cgd->ident_data;
+ if (STRNCMP(iqd + 43, "S-E-S", 5) == 0)
+ return (ENC_SEMB_SES);
+ else if (STRNCMP(iqd + 43, "SAF-TE", 6) == 0)
+ return (ENC_SEMB_SAFT);
+ return (ENC_NONE);
+
+ } else if (cgd->protocol != PROTO_SCSI)
+ return (ENC_NONE);
+
+ iqd = (unsigned char *)&cgd->inq_data;
+ buflen = min(sizeof(cgd->inq_data),
+ SID_ADDITIONAL_LENGTH(&cgd->inq_data));
if (buflen < 8+SEN_ID_LEN)
return (ENC_NONE);
@@ -743,14 +768,18 @@ enc_fsm_step(enc_softc_t *enc)
if (error == 0) {
- uint32_t resid;
+ uint32_t len;
- resid = 0;
- if (ccb != NULL)
- resid = ccb->csio.dxfer_len - ccb->csio.resid;
+ len = 0;
+ if (ccb != NULL) {
+ if (ccb->ccb_h.func_code == XPT_ATA_IO)
+ len = ccb->ataio.dxfer_len - ccb->ataio.resid;
+ else
+ len = ccb->csio.dxfer_len - ccb->csio.resid;
+ }
cam_periph_unlock(enc->periph);
- cur_state->done(enc, cur_state, ccb, &buf, resid);
+ cur_state->done(enc, cur_state, ccb, &buf, len);
cam_periph_lock(enc->periph);
}
@@ -880,16 +909,18 @@ enc_ctor(struct cam_periph *periph, void
enc->periph = periph;
enc->current_action = ENC_UPDATE_NONE;
- enc->enc_type = enc_type(&cgd->inq_data, sizeof (cgd->inq_data));
+ enc->enc_type = enc_type(cgd);
sx_init(&enc->enc_cache_lock, "enccache");
switch (enc->enc_type) {
case ENC_SES:
case ENC_SES_SCSI2:
case ENC_SES_PASSTHROUGH:
+ case ENC_SEMB_SES:
err = ses_softc_init(enc, 1);
break;
case ENC_SAFT:
+ case ENC_SEMB_SAFT:
err = safte_softc_init(enc, 1);
break;
case ENC_SEN:
@@ -963,6 +994,12 @@ enc_ctor(struct cam_periph *periph, void
case ENC_SAFT:
tname = "SAF-TE Compliant Device";
break;
+ case ENC_SEMB_SES:
+ tname = "SEMB SES Device";
+ break;
+ case ENC_SEMB_SAFT:
+ tname = "SEMB SAF-TE Device";
+ break;
}
xpt_announce_periph(periph, tname);
status = CAM_REQ_CMP;
Modified: projects/zfsd/head/sys/cam/scsi/scsi_enc_internal.h
==============================================================================
--- projects/zfsd/head/sys/cam/scsi/scsi_enc_internal.h Sat Aug 20 08:20:10 2011 (r225023)
+++ projects/zfsd/head/sys/cam/scsi/scsi_enc_internal.h Sat Aug 20 09:31:52 2011 (r225024)
@@ -55,7 +55,9 @@ typedef enum {
ENC_SES,
ENC_SES_PASSTHROUGH,
ENC_SEN,
- ENC_SAFT
+ ENC_SAFT,
+ ENC_SEMB_SES,
+ ENC_SEMB_SAFT
} enctyp;
/* Platform Independent Driver Internal Definitions for enclosure devices. */
Modified: projects/zfsd/head/sys/cam/scsi/scsi_enc_ses.c
==============================================================================
--- projects/zfsd/head/sys/cam/scsi/scsi_enc_ses.c Sat Aug 20 08:20:10 2011 (r225023)
+++ projects/zfsd/head/sys/cam/scsi/scsi_enc_ses.c Sat Aug 20 09:31:52 2011 (r225024)
@@ -251,7 +251,7 @@ static enc_softc_cleanup_t ses_softc_cle
#define SCSZ 0x8000
-static fsm_fill_handler_t ses_fill_rcv_diag_csio;
+static fsm_fill_handler_t ses_fill_rcv_diag_io;
static fsm_fill_handler_t ses_fill_control_request;
static fsm_done_handler_t ses_process_config;
static fsm_done_handler_t ses_process_status;
@@ -269,7 +269,7 @@ struct enc_fsm_state enc_fsm_states[SES_
SesConfigPage,
SCSZ,
60 * 1000,
- ses_fill_rcv_diag_csio,
+ ses_fill_rcv_diag_io,
ses_process_config,
enc_error
},
@@ -278,7 +278,7 @@ struct enc_fsm_state enc_fsm_states[SES_
SesStatusPage,
SCSZ,
60 * 1000,
- ses_fill_rcv_diag_csio,
+ ses_fill_rcv_diag_io,
ses_process_status,
enc_error
},
@@ -287,7 +287,7 @@ struct enc_fsm_state enc_fsm_states[SES_
SesElementDescriptor,
SCSZ,
60 * 1000,
- ses_fill_rcv_diag_csio,
+ ses_fill_rcv_diag_io,
ses_process_elm_descs,
enc_error
},
@@ -296,7 +296,7 @@ struct enc_fsm_state enc_fsm_states[SES_
SesAddlElementStatus,
SCSZ,
60 * 1000,
- ses_fill_rcv_diag_csio,
+ ses_fill_rcv_diag_io,
ses_process_elm_addlstatus,
enc_error
},
@@ -1898,13 +1898,21 @@ out:
}
static int
-ses_fill_rcv_diag_csio(enc_softc_t *enc, struct enc_fsm_state *state,
+ses_fill_rcv_diag_io(enc_softc_t *enc, struct enc_fsm_state *state,
union ccb *ccb, uint8_t *buf)
{
- scsi_receive_diagnostic_results(&ccb->csio, /*retries*/5,
+
+ if (enc->enc_type == ENC_SEMB_SES) {
+ semb_receive_diagnostic_results(&ccb->ataio, /*retries*/5,
+ enc_done, MSG_SIMPLE_Q_TAG, /*pcv*/1,
+ state->page_code, buf, state->buf_size,
+ state->timeout);
+ } else {
+ scsi_receive_diagnostic_results(&ccb->csio, /*retries*/5,
enc_done, MSG_SIMPLE_Q_TAG, /*pcv*/1,
state->page_code, buf, state->buf_size,
SSD_FULL_SIZE, state->timeout);
+ }
return (0);
}
@@ -2018,12 +2026,19 @@ ses_fill_control_request(enc_softc_t *en
return (ENOENT);
/* Fill out the ccb */
- scsi_send_diagnostic(&ccb->csio, /*retries*/5, enc_done,
+ if (enc->enc_type == ENC_SEMB_SES) {
+ semb_send_diagnostic(&ccb->ataio, /*retries*/5, enc_done,
+ MSG_SIMPLE_Q_TAG,
+ buf, ses_page_length(&ses_cache->status_page->hdr),
+ state->timeout);
+ } else {
+ scsi_send_diagnostic(&ccb->csio, /*retries*/5, enc_done,
MSG_SIMPLE_Q_TAG, /*unit_offline*/0,
/*device_offline*/0, /*self_test*/0,
/*page_format*/1, /*self_test_code*/0,
buf, ses_page_length(&ses_cache->status_page->hdr),
SSD_FULL_SIZE, state->timeout);
+ }
return (0);
}
Modified: projects/zfsd/head/sys/sys/ata.h
==============================================================================
--- projects/zfsd/head/sys/sys/ata.h Sat Aug 20 08:20:10 2011 (r225023)
+++ projects/zfsd/head/sys/sys/ata.h Sat Aug 20 09:31:52 2011 (r225024)
@@ -318,6 +318,7 @@ struct ata_params {
#define ATA_READ_VERIFY48 0x42
#define ATA_READ_FPDMA_QUEUED 0x60 /* read DMA NCQ */
#define ATA_WRITE_FPDMA_QUEUED 0x61 /* write DMA NCQ */
+#define ATA_SEP_ATTN 0x67 /* SEP request */
#define ATA_SEEK 0x70 /* seek */
#define ATA_PACKET_CMD 0xa0 /* packet command */
#define ATA_ATAPI_IDENTIFY 0xa1 /* get ATAPI params*/
More information about the svn-src-projects
mailing list