Date: Mon, 29 Jun 2009 08:17:03 GMT From: Alexander Motin <mav@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 165370 for review Message-ID: <200906290817.n5T8H3Lh074282@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=165370 Change 165370 by mav@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,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906290817.n5T8H3Lh074282>