Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 20 Aug 2011 09:31:52 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r225024 - in projects/zfsd/head: sbin/camcontrol sys/cam sys/cam/ata sys/cam/scsi sys/sys
Message-ID:  <201108200931.p7K9VqxA042741@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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*/



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201108200931.p7K9VqxA042741>