PERFORCE change 165370 for review

Alexander Motin mav at FreeBSD.org
Mon Jun 29 08:17:04 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=165370

Change 165370 by mav at mav_mavbook on 2009/06/29 08:16:02

	Add ATA identify command support.

Affected files ...

.. //depot/projects/scottl-camlock/src/sbin/camcontrol/camcontrol.8#5 edit
.. //depot/projects/scottl-camlock/src/sbin/camcontrol/camcontrol.c#10 edit

Differences ...

==== //depot/projects/scottl-camlock/src/sbin/camcontrol/camcontrol.8#5 (text+ko) ====

@@ -27,7 +27,7 @@
 .\"
 .\" $FreeBSD: src/sbin/camcontrol/camcontrol.8,v 1.44 2007/09/08 20:24:12 ken Exp $
 .\"
-.Dd August 21, 2006
+.Dd June 29, 2009
 .Dt CAMCONTROL 8
 .Os
 .Sh NAME
@@ -59,6 +59,10 @@
 .Op Fl S
 .Op Fl R
 .Nm
+.Ic identify
+.Op device id
+.Op generic args
+.Nm
 .Ic reportluns
 .Op device id
 .Op generic args
@@ -283,6 +287,8 @@
 .It Fl R
 Print out transfer rate information.
 .El
+.It Ic identify
+Send a ATA identify command (0xec) to a device.
 .It Ic reportluns
 Send the SCSI REPORT LUNS (0xA0) command to the given device.
 By default,

==== //depot/projects/scottl-camlock/src/sbin/camcontrol/camcontrol.c#10 (text+ko) ====

@@ -32,6 +32,7 @@
 #include <sys/ioctl.h>
 #include <sys/stdint.h>
 #include <sys/types.h>
+#include <sys/endian.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -49,6 +50,7 @@
 #include <cam/scsi/scsi_da.h>
 #include <cam/scsi/scsi_pass.h>
 #include <cam/scsi/scsi_message.h>
+#include <cam/ata/ata_all.h>
 #include <camlib.h>
 #include "camcontrol.h"
 
@@ -71,7 +73,8 @@
 	CAM_CMD_RATE		= 0x0000000f,
 	CAM_CMD_DETACH		= 0x00000010,
 	CAM_CMD_REPORTLUNS	= 0x00000011,
-	CAM_CMD_READCAP		= 0x00000012
+	CAM_CMD_READCAP		= 0x00000012,
+	CAM_CMD_IDENTIFY	= 0x00000013
 } cam_cmdmask;
 
 typedef enum {
@@ -126,6 +129,7 @@
 #ifndef MINIMALISTIC
 	{"tur", CAM_CMD_TUR, CAM_ARG_NONE, NULL},
 	{"inquiry", CAM_CMD_INQUIRY, CAM_ARG_NONE, "DSR"},
+	{"identify", CAM_CMD_IDENTIFY, CAM_ARG_NONE, NULL},
 	{"start", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT, NULL},
 	{"stop", CAM_CMD_STARTSTOP, CAM_ARG_NONE, NULL},
 	{"load", CAM_CMD_STARTSTOP, CAM_ARG_START_UNIT | CAM_ARG_EJECT, NULL},
@@ -990,6 +994,224 @@
 
 	return(retval);
 }
+
+static void
+atacapprint(struct ata_params *parm)
+{
+	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
+				((u_int32_t)parm->lba_size_2 << 16);
+
+	u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
+				((u_int64_t)parm->lba_size48_2 << 16) |
+				((u_int64_t)parm->lba_size48_3 << 32) |
+				((u_int64_t)parm->lba_size48_4 << 48);
+
+	printf("\n");
+	printf("Protocol              ");
+	if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
+		if (parm->satacapabilities & ATA_SATA_GEN2)
+			printf("SATA revision 2.x\n");
+		else if (parm->satacapabilities & ATA_SATA_GEN1)
+			printf("SATA revision 1.x\n");
+		else
+			printf("Unknown SATA revision\n");
+	}
+	else
+		printf("ATA/ATAPI revision %d\n", ata_version(parm->version_major));
+	printf("device model          %.40s\n", parm->model);
+	printf("serial number         %.20s\n", parm->serial);
+	printf("firmware revision     %.8s\n", parm->revision);
+
+	printf("cylinders             %d\n", parm->cylinders);
+	printf("heads                 %d\n", parm->heads);
+	printf("sectors/track         %d\n", parm->sectors);
+
+	if (parm->config == ATA_PROTO_CFA ||
+	    (parm->support.command2 & ATA_SUPPORT_CFA))
+		printf("CFA supported\n");
+
+	printf("lba%ssupported         ",
+		parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
+	if (lbasize)
+		printf("%d sectors\n", lbasize);
+	else
+		printf("\n");
+
+	printf("lba48%ssupported       ",
+		parm->support.command2 & ATA_SUPPORT_ADDRESS48 ? " " : " not ");
+	if (lbasize48)
+		printf("%ju sectors\n", (uintmax_t)lbasize48);
+	else
+		printf("\n");
+
+	printf("dma%ssupported\n",
+		parm->capabilities1 & ATA_SUPPORT_DMA ? " " : " not ");
+
+	printf("overlap%ssupported\n",
+		parm->capabilities1 & ATA_SUPPORT_OVERLAP ? " " : " not ");
+
+	printf("\nFeature                      "
+		"Support  Enable    Value           Vendor\n");
+
+	printf("write cache                    %s	%s\n",
+		parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
+		parm->enabled.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no");
+
+	printf("read ahead                     %s	%s\n",
+		parm->support.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no",
+		parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
+
+	if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
+		printf("Native Command Queuing (NCQ)   %s	%s"
+			"	%d/0x%02X\n",
+			parm->satacapabilities & ATA_SUPPORT_NCQ ?
+				"yes" : "no", " -",
+			(parm->satacapabilities & ATA_SUPPORT_NCQ) ?
+				ATA_QUEUE_LEN(parm->queue) : 0,
+			(parm->satacapabilities & ATA_SUPPORT_NCQ) ?
+				ATA_QUEUE_LEN(parm->queue) : 0);
+	}
+	printf("Tagged Command Queuing (TCQ)   %s	%s	%d/0x%02X\n",
+		parm->support.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
+		parm->enabled.command2 & ATA_SUPPORT_QUEUED ? "yes" : "no",
+		ATA_QUEUE_LEN(parm->queue), ATA_QUEUE_LEN(parm->queue));
+
+	printf("SMART                          %s	%s\n",
+		parm->support.command1 & ATA_SUPPORT_SMART ? "yes" : "no",
+		parm->enabled.command1 & ATA_SUPPORT_SMART ? "yes" : "no");
+
+	printf("microcode download             %s	%s\n",
+		parm->support.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no",
+		parm->enabled.command2 & ATA_SUPPORT_MICROCODE ? "yes" : "no");
+
+	printf("security                       %s	%s\n",
+		parm->support.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no",
+		parm->enabled.command1 & ATA_SUPPORT_SECURITY ? "yes" : "no");
+
+	printf("power management               %s	%s\n",
+		parm->support.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no",
+		parm->enabled.command1 & ATA_SUPPORT_POWERMGT ? "yes" : "no");
+
+	printf("advanced power management      %s	%s	%d/0x%02X\n",
+		parm->support.command2 & ATA_SUPPORT_APM ? "yes" : "no",
+		parm->enabled.command2 & ATA_SUPPORT_APM ? "yes" : "no",
+		parm->apm_value, parm->apm_value);
+
+	printf("automatic acoustic management  %s	%s	"
+		"%d/0x%02X	%d/0x%02X\n",
+		parm->support.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
+		parm->enabled.command2 & ATA_SUPPORT_AUTOACOUSTIC ? "yes" :"no",
+		ATA_ACOUSTIC_CURRENT(parm->acoustic),
+		ATA_ACOUSTIC_CURRENT(parm->acoustic),
+		ATA_ACOUSTIC_VENDOR(parm->acoustic),
+		ATA_ACOUSTIC_VENDOR(parm->acoustic));
+}
+
+
+static int
+ataidentify(struct cam_device *device, int retry_count, int timeout)
+{
+	union ccb *ccb;
+	struct ata_params *ident_buf;
+	int error = 0;
+	int16_t *ptr;
+	
+	ccb = cam_getccb(device);
+
+	if (ccb == NULL) {
+		warnx("couldn't allocate CCB");
+		return(1);
+	}
+
+	/* cam_getccb cleans up the header, caller has to zero the payload */
+	bzero(&(&ccb->ccb_h)[1],
+	      sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
+
+	ident_buf = (struct ata_params *)malloc(
+		sizeof(struct ata_params));
+
+	if (ident_buf == NULL) {
+		cam_freeccb(ccb);
+		warnx("can't malloc memory for identify\n");
+		return(1);
+	}
+	bzero(ident_buf, sizeof(*ident_buf));
+
+	cam_fill_ataio(&ccb->ataio,
+		      retry_count,
+		      NULL,
+		      /*flags*/CAM_DIR_IN,
+		      MSG_SIMPLE_Q_TAG,
+		      /*data_ptr*/(u_int8_t *)ident_buf,
+		      /*dxfer_len*/sizeof(struct ata_params),
+		      timeout ? timeout : 30 * 1000);
+//	if (periph->path->device->protocol == PROTO_ATA)
+		ata_36bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
+//	else
+//		ata_36bit_cmd(&ccb->ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
+
+	/* Disable freezing the device queue */
+	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
+
+	if (arglist & CAM_ARG_ERR_RECOVER)
+		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
+
+	if (cam_send_ccb(device, ccb) < 0) {
+		perror("error sending ATA identify");
+
+		if (arglist & CAM_ARG_VERBOSE) {
+			cam_error_print(device, ccb, CAM_ESF_ALL,
+					CAM_EPF_ALL, stderr);
+		}
+
+		cam_freeccb(ccb);
+		return(1);
+	}
+
+	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+		error = 1;
+
+		if (arglist & CAM_ARG_VERBOSE) {
+			cam_error_print(device, ccb, CAM_ESF_ALL,
+					CAM_EPF_ALL, stderr);
+		}
+	}
+
+	cam_freeccb(ccb);
+
+	if (error != 0) {
+		free(ident_buf);
+		return(error);
+	}
+
+	for (ptr = (int16_t *)ident_buf;
+	     ptr < (int16_t *)ident_buf + sizeof(struct ata_params)/2; ptr++) {
+		*ptr = le16toh(*ptr);
+	}
+	if (strncmp(ident_buf->model, "FX", 2) &&
+	    strncmp(ident_buf->model, "NEC", 3) &&
+	    strncmp(ident_buf->model, "Pioneer", 7) &&
+	    strncmp(ident_buf->model, "SHARP", 5)) {
+		ata_bswap(ident_buf->model, sizeof(ident_buf->model));
+		ata_bswap(ident_buf->revision, sizeof(ident_buf->revision));
+		ata_bswap(ident_buf->serial, sizeof(ident_buf->serial));
+	}
+	ata_btrim(ident_buf->model, sizeof(ident_buf->model));
+	ata_bpack(ident_buf->model, ident_buf->model, sizeof(ident_buf->model));
+	ata_btrim(ident_buf->revision, sizeof(ident_buf->revision));
+	ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
+	ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
+	ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
+
+	fprintf(stdout, "%s%d: ", device->device_name,
+		device->dev_unit_num);
+	ata_print_ident(ident_buf);
+	atacapprint(ident_buf);
+
+	free(ident_buf);
+
+	return(0);
+}
 #endif /* MINIMALISTIC */
 
 /*
@@ -3691,6 +3913,7 @@
 "        camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
 "        camcontrol tur        [dev_id][generic args]\n"
 "        camcontrol inquiry    [dev_id][generic args] [-D] [-S] [-R]\n"
+"        camcontrol identify   [dev_id][generic args]\n"
 "        camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
 "        camcontrol readcap    [dev_id][generic args] [-b] [-h] [-H] [-N]\n"
 "                              [-q] [-s]\n"
@@ -3726,6 +3949,7 @@
 "periphlist  list all CAM peripheral drivers attached to a device\n"
 "tur         send a test unit ready to the named device\n"
 "inquiry     send a SCSI inquiry command to the named device\n"
+"identify    send a ATA identify command to the named device\n"
 "reportluns  send a SCSI report luns command to the device\n"
 "readcap     send a SCSI read capacity command to the device\n"
 "start       send a Start Unit command to the device\n"
@@ -4051,6 +4275,9 @@
 			error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
 					      retry_count, timeout);
 			break;
+		case CAM_CMD_IDENTIFY:
+			error = ataidentify(cam_dev, retry_count, timeout);
+			break;
 		case CAM_CMD_STARTSTOP:
 			error = scsistart(cam_dev, arglist & CAM_ARG_START_UNIT,
 					  arglist & CAM_ARG_EJECT, retry_count,


More information about the p4-projects mailing list