Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 28 Apr 2026 19:04:00 +0000
From:      Chuck Tuffli <chuck@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: e139a49b5d8e - main - Revert "Vendor import of smart at 1.0.2"
Message-ID:  <69f104a0.27812.208ed91f@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by chuck:

URL: https://cgit.FreeBSD.org/src/commit/?id=e139a49b5d8e9385b4d42ea1ec3850bc80d7f989

commit e139a49b5d8e9385b4d42ea1ec3850bc80d7f989
Author:     Chuck Tuffli <chuck@FreeBSD.org>
AuthorDate: 2026-04-28 18:49:22 +0000
Commit:     Chuck Tuffli <chuck@FreeBSD.org>
CommitDate: 2026-04-28 19:03:38 +0000

    Revert "Vendor import of smart at 1.0.2"
    
    This reverts commit 68e5b71517e947b4e3f349c970af362b47b45f27.
---
 contrib/smart/Changelog       |   37 --
 contrib/smart/LICENSE         |   13 -
 contrib/smart/Makefile        |   26 -
 contrib/smart/freebsd_dev.c   |  828 -------------------------
 contrib/smart/libsmart.c      | 1359 -----------------------------------------
 contrib/smart/libsmart.h      |  174 ------
 contrib/smart/libsmart_desc.c |  158 -----
 contrib/smart/libsmart_dev.h  |   60 --
 contrib/smart/libsmart_priv.h |   83 ---
 contrib/smart/smart.8         |  245 --------
 contrib/smart/smart.c         |  334 ----------
 packages/Makefile             |    1 -
 packages/smart/Makefile       |    4 -
 packages/smart/smart.ucl      |   30 -
 usr.sbin/Makefile             |    1 -
 usr.sbin/smart/Makefile       |    8 -
 16 files changed, 3361 deletions(-)

diff --git a/contrib/smart/Changelog b/contrib/smart/Changelog
deleted file mode 100644
index 42b79bc34070..000000000000
--- a/contrib/smart/Changelog
+++ /dev/null
@@ -1,37 +0,0 @@
-This file documents changes for smart releases
-
-version 1.0.2
- - Bring man page up to snuff
- - Fix various complier warnings
-
-version 1.0.1
- - Fix don't print attribute ID with description
-
-version 1.0.0
- - Fix ATA threshold output (gh-10). This is a breaking change as it
-   reduces the output from 4 fields to 3 (drops the "reserved" byte
-   from threshold).
- - Fix the ATA raw output. This is a breaking change as it increase the
-   output from 6 bytes to 7 (i.e., includes the "reserved" byte). Note
-   that while some attributes use this byte, most do not.
- - Fix direct debug output (--debug) to standard error
- - Use POSIX memcpy and memset instead of older bXXX equivalents
-
-version 0.4.2
- - Update README contents
-
-version 0.4.1
-  - Allow a comma-separated list of attributes
-  - Code refactor + update code comments
-
-version 0.3.0
-
-  - Reclaim the -d option from debug
-  - Change field separator from spaces to tab
-  - Add textual descriptions of attribute IDs for ATA, NVMe, and SCSI
-  - Add a manual page
-  - Fixes
-     * libxo structure for attribute and attributes
-     * simplify LIBXO ifdef sprawl
-     * display of threshold values
-     * display of long values
diff --git a/contrib/smart/LICENSE b/contrib/smart/LICENSE
deleted file mode 100644
index 8b0a0bf6a4a6..000000000000
--- a/contrib/smart/LICENSE
+++ /dev/null
@@ -1,13 +0,0 @@
-Copyright (c) 2016-2026 Chuck Tuffli <chuck@tuffli.net>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/contrib/smart/Makefile b/contrib/smart/Makefile
deleted file mode 100644
index 64cab720e08f..000000000000
--- a/contrib/smart/Makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Copyright (c) 2016-2021 Chuck Tuffli <chuck@tuffli.net>
-#
-# Permission to use, copy, modify, and distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-PROG=	smart
-SRCS=	smart.c libsmart.c libsmart_desc.c
-SRCS+=	freebsd_dev.c
-LIBADD= cam xo
-MAN=smart.8
-MLINKS=	smart.8 diskhealth.8
-#CFLAGS+= -ggdb -O0
-CFLAGS+= -DLIBXO
-LINKS= ${BINDIR}/smart ${BINDIR}/diskhealth
-
-.include <bsd.prog.mk>
diff --git a/contrib/smart/freebsd_dev.c b/contrib/smart/freebsd_dev.c
deleted file mode 100644
index d1dda2289742..000000000000
--- a/contrib/smart/freebsd_dev.c
+++ /dev/null
@@ -1,828 +0,0 @@
-/*
- * Copyright (c) 2016-2021 Chuck Tuffli <chuck@tuffli.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <string.h>
-#include <err.h>
-#include <errno.h>
-#include <camlib.h>
-#include <cam/scsi/scsi_message.h>
-
-#include "libsmart.h"
-#include "libsmart_priv.h"
-#include "libsmart_dev.h"
-
-/* Provide compatibility for FreeBSD 11.0 */
-#if (__FreeBSD_version < 1101000)
-
-struct scsi_log_informational_exceptions {
-        struct scsi_log_param_header hdr;
-#define SLP_IE_GEN                      0x0000
-        uint8_t ie_asc;
-        uint8_t ie_ascq;
-        uint8_t temperature;
-};
-
-#endif
-
-struct fbsd_smart {
-	smart_t	common;
-	struct cam_device *camdev;
-};
-
-static smart_protocol_e __device_get_proto(struct fbsd_smart *);
-static bool __device_proto_tunneled(struct fbsd_smart *);
-static int32_t __device_get_info(struct fbsd_smart *);
-
-smart_h
-device_open(smart_protocol_e protocol, char *devname)
-{
-	struct fbsd_smart *h = NULL;
-
-	h = malloc(sizeof(struct fbsd_smart));
-	if (h == NULL)
-		return NULL;
-
-	memset(h, 0, sizeof(struct fbsd_smart));
-
-	h->common.protocol = SMART_PROTO_MAX;
-	h->camdev = cam_open_device(devname, O_RDWR);
-	if (h->camdev == NULL) {
-		printf("%s: error opening %s - %s\n",
-				__func__, devname,
-				cam_errbuf);
-		free(h);
-		h = NULL;
-	} else {
-		smart_protocol_e proto = __device_get_proto(h);
-
-		if ((protocol == SMART_PROTO_AUTO) ||
-				(protocol == proto)) {
-			h->common.protocol = proto;
-		} else {
-			printf("%s: protocol mismatch %d vs %d\n",
-					__func__, protocol, proto);
-		}
-
-		if (proto == SMART_PROTO_SCSI) {
-			if (__device_proto_tunneled(h)) {
-				h->common.protocol = SMART_PROTO_ATA;
-				h->common.info.tunneled = 1;
-			}
-		}
-
-		__device_get_info(h);
-	}
-
-	return h;
-}
-
-void
-device_close(smart_h h)
-{
-	struct fbsd_smart *fsmart = h;
-
-	if (fsmart != NULL) {
-		if (fsmart->camdev != NULL) {
-			cam_close_device(fsmart->camdev);
-		}
-
-		free(fsmart);
-	}
-}
-
-static const uint8_t smart_read_data[] = {
-	0xb0, 0xd0, 0x00, 0x4f, 0xc2, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static const uint8_t smart_return_status[] = {
-	0xb0, 0xda, 0x00, 0x4f, 0xc2, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static int32_t
-__device_read_ata(smart_h h, uint32_t page, void *buf, size_t bsize, union ccb *ccb)
-{
-	struct fbsd_smart *fsmart = h;
-	const uint8_t *smart_fis;
-	uint32_t smart_fis_size = 0;
-	uint32_t cam_flags = 0;
-	uint16_t sector_count = 0;
-	uint8_t protocol = 0;
-
-	switch (page) {
-	case PAGE_ID_ATA_SMART_READ_DATA: /* Support SMART READ DATA */
-		smart_fis = smart_read_data;
-		smart_fis_size = sizeof(smart_read_data);
-		cam_flags = CAM_DIR_IN;
-		sector_count = 1;
-		protocol = AP_PROTO_PIO_IN;
-		break;
-	case PAGE_ID_ATA_SMART_RET_STATUS: /* Support SMART RETURN STATUS */
-		smart_fis = smart_return_status;
-		smart_fis_size = sizeof(smart_return_status);
-		/* Command has no data but uses the return status */
-		cam_flags = CAM_DIR_NONE;
-		protocol = AP_PROTO_NON_DATA;
-		bsize = 0;
-		break;
-	default:
-		return EINVAL;
-	}
-
-	if (fsmart->common.info.tunneled) {
-		struct ata_pass_16 *cdb;
-		uint8_t cdb_flags;
-
-		if (bsize > 0) {
-			cdb_flags = AP_FLAG_TDIR_FROM_DEV |
-				AP_FLAG_BYT_BLOK_BLOCKS |
-				AP_FLAG_TLEN_SECT_CNT;
-		} else {
-			cdb_flags = AP_FLAG_CHK_COND |
-				AP_FLAG_TDIR_FROM_DEV |
-				AP_FLAG_BYT_BLOK_BLOCKS;
-		}
-
-		cdb = (struct ata_pass_16 *)ccb->csio.cdb_io.cdb_bytes;
-		memset(cdb, 0, sizeof(*cdb));
-
-		scsi_ata_pass_16(&ccb->csio,
-				/*retries*/	1,
-				/*cbfcnp*/	NULL,
-				/*flags*/	cam_flags,
-				/*tag_action*/	MSG_SIMPLE_Q_TAG,
-				/*protocol*/	protocol,
-				/*ata_flags*/	cdb_flags,
-				/*features*/	page,
-				/*sector_count*/sector_count,
-				/*lba*/		0,
-				/*command*/	ATA_SMART_CMD,
-				/*control*/	0,
-				/*data_ptr*/	buf,
-				/*dxfer_len*/	bsize,
-				/*sense_len*/	SSD_FULL_SIZE,
-				/*timeout*/	5000
-				);
-		cdb->lba_mid = 0x4f;
-		cdb->lba_high = 0xc2;
-		cdb->device = 0;	/* scsi_ata_pass_16() sets this */
-	} else {
-		memcpy(&ccb->ataio.cmd.command, smart_fis, smart_fis_size);
-
-		cam_fill_ataio(&ccb->ataio,
-				/* retries */1,
-				/* cbfcnp */NULL,
-				/* flags */cam_flags,
-				/* tag_action */0,
-				/* data_ptr */buf,
-				/* dxfer_len */bsize,
-				/* timeout */5000);
-		ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
-		ccb->ataio.cmd.control = 0;
-	}
-
-	return 0;
-}
-
-static int32_t
-__device_read_scsi(__attribute__((unused)) smart_h h, uint32_t page, void *buf, size_t bsize, union ccb *ccb)
-{
-
-	scsi_log_sense(&ccb->csio,
-			/* retries */1,
-			/* cbfcnp */NULL,
-			/* tag_action */0,
-			/* page_code */SLS_PAGE_CTRL_CUMULATIVE,
-			/* page */page,
-			/* save_pages */0,
-			/* ppc */0,
-			/* paramptr */0,
-			/* param_buf */buf,
-			/* param_len */bsize,
-			/* sense_len */0,
-			/* timeout */5000);
-
-	return 0;
-}
-
-static int32_t
-__device_read_nvme(__attribute__((unused)) smart_h h, uint32_t page, void *buf, size_t bsize, union ccb *ccb)
-{
-	struct ccb_nvmeio *nvmeio = &ccb->nvmeio;
-	uint32_t numd = 0;	/* number of dwords */
-
-	/*
-	 * NVME CAM passthru
-	 *    1200000 > version > 1101510 uses nvmeio->cmd.opc
-	 *    1200059 > version > 1200038 uses nvmeio->cmd.opc
-	 *    1200081 > version > 1200058 uses nvmeio->cmd.opc_fuse
-	 *                      > 1200080 uses nvmeio->cmd.opc
-	 * This code doesn't support the brief 'opc_fuse' period.
-	 */
-#if ((__FreeBSD_version > 1200038) || ((__FreeBSD_version > 1101510) && (__FreeBSD_version < 1200000)))
-	switch (page) {
-	case NVME_LOG_HEALTH_INFORMATION:
-		numd = (sizeof(struct nvme_health_information_page) / sizeof(uint32_t));
-		break;
-	default:
-		/* Unsupported log page */
-		return EINVAL;
-	}
-
-	/* Subtract 1 because NUMD is a zero based value */
-	numd--;
-
-	nvmeio->cmd.opc = NVME_OPC_GET_LOG_PAGE;
-	nvmeio->cmd.nsid = NVME_GLOBAL_NAMESPACE_TAG;
-	nvmeio->cmd.cdw10 = page | (numd << 16);
-
-	cam_fill_nvmeadmin(&ccb->nvmeio,
-			/* retries */1,
-			/* cbfcnp */NULL,
-			/* flags */CAM_DIR_IN,
-			/* data_ptr */buf,
-			/* dxfer_len */bsize,
-			/* timeout */5000);
-#endif
-	return 0;
-}
-
-/*
- * Retrieve the SMART RETURN STATUS
- *
- * SMART RETURN STATUS provides the reliability status of the
- * device and can be used as a high-level indication of health.
- */
-static int32_t
-__device_status_ata(smart_h h, union ccb *ccb)
-{
-	struct fbsd_smart *fsmart = h;
-	uint8_t *buf = NULL;
-	uint32_t page = 0;
-	uint8_t lba_high = 0, lba_mid = 0, device = 0, status = 0;
-
-	if (fsmart->common.info.tunneled) {
-		struct ata_res_pass16 {
-			u_int16_t reserved[5];
-			u_int8_t flags;
-			u_int8_t error;
-			u_int8_t sector_count_exp;
-			u_int8_t sector_count;
-			u_int8_t lba_low_exp;
-			u_int8_t lba_low;
-			u_int8_t lba_mid_exp;
-			u_int8_t lba_mid;
-			u_int8_t lba_high_exp;
-			u_int8_t lba_high;
-			u_int8_t device;
-			u_int8_t status;
-		} *res_pass16 = (struct ata_res_pass16 *)(uintptr_t)
-			    &ccb->csio.sense_data;
-
-		buf = ccb->csio.data_ptr;
-		page = ((struct ata_pass_16 *)ccb->csio.cdb_io.cdb_bytes)->features;
-		lba_high = res_pass16->lba_high;
-		lba_mid = res_pass16->lba_mid;
-		device = res_pass16->device;
-		status = res_pass16->status;
-
-		/*
-		 * Note that this generates an expected CHECK CONDITION.
-		 * Mask it so the outer function doesn't print an error
-		 * message.
-		 */
-		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
-		ccb->ccb_h.status |= CAM_REQ_CMP;
-	} else {
-		struct ccb_ataio *ataio = (struct ccb_ataio *)&ccb->ataio;
-
-		buf = ataio->data_ptr;
-		page = ataio->cmd.features;
-		lba_high = ataio->res.lba_high;
-		lba_mid = ataio->res.lba_mid;
-		device = ataio->res.device;
-		status = ataio->res.status;
-	}
-
-	switch (page) {
-	case PAGE_ID_ATA_SMART_RET_STATUS:
-		/*
-		 * Typically, SMART related log pages return data, but this
-		 * command is different in that the data is encoded in the
-		 * result registers.
-		 *
-		 * Handle this in a UNIX-like way by writing a 0 (no errors)
-		 * or 1 (threshold exceeded condition) to the output buffer.
-		 */
-		dprintf("SMART_RET_STATUS: lba mid=%#x high=%#x device=%#x status=%#x\n",
-				lba_mid,
-				lba_high,
-				device,
-				status);
-		if ((lba_high == 0x2c) && (lba_mid == 0xf4)) {
-			buf[0] = 1;
-		} else if ((lba_high == 0xc2) && (lba_mid == 0x4f)) {
-			buf[0] = 0;
-		} else {
-			/* Ruh-roh ... */
-			buf[0] = 255;
-		}
-		break;
-	default:
-		;
-	}
-
-	return 0;
-}
-
-int32_t
-device_read_log(smart_h h, uint32_t page, void *buf, size_t bsize)
-{
-	struct fbsd_smart *fsmart = h;
-	union ccb *ccb = NULL;
-	int rc = 0;
-
-	if (fsmart == NULL)
-		return EINVAL;
-
-	dprintf("read log page %#x\n", page);
-
-	ccb = cam_getccb(fsmart->camdev);
-	if (ccb == NULL)
-		return ENOMEM;
-
-	CCB_CLEAR_ALL_EXCEPT_HDR(ccb);
-
-	switch (fsmart->common.protocol) {
-	case SMART_PROTO_ATA:
-		rc = __device_read_ata(h, page, buf, bsize, ccb);
-		break;
-	case SMART_PROTO_SCSI:
-		rc = __device_read_scsi(h, page, buf, bsize, ccb);
-		break;
-	case SMART_PROTO_NVME:
-		rc = __device_read_nvme(h, page, buf, bsize, ccb);
-		break;
-	default:
-		warnx("unsupported protocol %d", fsmart->common.protocol);
-		cam_freeccb(ccb);
-		return ENODEV;
-	}
-
-	if (rc) {
-		if (rc == EINVAL)
-			warnx("unsupported page %#x", page);
-
-		return rc;
-	}
-
-	if (((rc = cam_send_ccb(fsmart->camdev, ccb)) < 0)
-			|| ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
-		if (rc < 0)
-			warn("error sending command");
-	}
-
-	/*
-	 * Most commands don't need any post-processing. But then there's
-	 * ATA. It's why we can't have nice things :(
-	 */
-	switch (fsmart->common.protocol) {
-	case SMART_PROTO_ATA:
-		__device_status_ata(h, ccb);
-		break;
-	default:
-		;
-	}
-
-	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
-		cam_error_print(fsmart->camdev, ccb, CAM_ESF_ALL,
-				CAM_EPF_ALL, stderr);
-	}
-
-	cam_freeccb(ccb);
-
-	return 0;
-}
-
-/*
- * The SCSI / ATA Translation (SAT) requires devices to support the ATA
- * Information VPD Page (T10/2126-D Revision 04). Use the existence of
- * this page to identify tunneled devices.
- */
-static bool
-__device_proto_tunneled(struct fbsd_smart *fsmart)
-{
-	union ccb *ccb = NULL;
-	struct scsi_vpd_supported_page_list supportedp;
-	uint32_t i;
-	bool is_tunneled = false;
-
-	if (fsmart->common.protocol != SMART_PROTO_SCSI) {
-		return false;
-	}
-
-	ccb = cam_getccb(fsmart->camdev);
-	if (!ccb) {
-		warn("Allocation failure ccb=%p", ccb);
-		goto __device_proto_tunneled_out;
-	}
-
-	scsi_inquiry(&ccb->csio,
-			3, // retries
-			NULL, // callback function
-			MSG_SIMPLE_Q_TAG, // tag action
-			(uint8_t *)&supportedp,
-			sizeof(struct scsi_vpd_supported_page_list),
-			1, // EVPD
-			SVPD_SUPPORTED_PAGE_LIST, // page code
-			SSD_FULL_SIZE, // sense length
-			5000); // timeout
-
-	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
-
-	if ((cam_send_ccb(fsmart->camdev, ccb) >= 0) &&
-			((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)) {
-		dprintf("Looking for page %#x (total = %u):\n", SVPD_ATA_INFORMATION,
-				supportedp.length);
-		for (i = 0; i < supportedp.length; i++) {
-			dprintf("\t[%u] = %#x\n", i, supportedp.list[i]);
-			if (supportedp.list[i] == SVPD_ATA_INFORMATION) {
-				is_tunneled = true;
-				break;
-			}
-		}
-	}
-
-	cam_freeccb(ccb);
-
-__device_proto_tunneled_out:
-	return is_tunneled;
-}
-
-/**
- * Retrieve the device protocol type via the transport settings
- *
- * @return protocol type or SMART_PROTO_MAX on error
- */
-static smart_protocol_e
-__device_get_proto(struct fbsd_smart *fsmart)
-{
-	smart_protocol_e proto = SMART_PROTO_MAX;
-	union ccb *ccb;
-
-	if (!fsmart || !fsmart->camdev) {
-		warn("Bad handle %p", fsmart);
-		return proto;
-	}
-
-	ccb = cam_getccb(fsmart->camdev);
-	if (ccb != NULL) {
-		CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->cts);
-
-		ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
-		ccb->cts.type = CTS_TYPE_CURRENT_SETTINGS;
-
-		if (cam_send_ccb(fsmart->camdev, ccb) >= 0) {
-			if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
-				struct ccb_trans_settings *cts = &ccb->cts;
-
-				switch (cts->protocol) {
-				case PROTO_ATA:
-					proto = SMART_PROTO_ATA;
-					break;
-				case PROTO_SCSI:
-					proto = SMART_PROTO_SCSI;
-					break;
-				case PROTO_NVME:
-					proto = SMART_PROTO_NVME;
-					break;
-				default:
-					printf("%s: unknown protocol %d\n",
-							__func__,
-							cts->protocol);
-				}
-			}
-		}
-
-		cam_freeccb(ccb);
-	}
-
-	return proto;
-}
-
-static int32_t
-__device_info_ata(struct fbsd_smart *fsmart, struct ccb_getdev *cgd)
-{
-	smart_info_t *sinfo = NULL;
-
-	if (!fsmart || !cgd) {
-		return -1;
-	}
-
-	sinfo = &fsmart->common.info;
-
-	sinfo->supported = cgd->ident_data.support.command1 &
-		ATA_SUPPORT_SMART;
-
-	dprintf("ATA command1 = %#x\n", cgd->ident_data.support.command1);
-
-	cam_strvis((uint8_t *)sinfo->device, cgd->ident_data.model,
-			sizeof(cgd->ident_data.model),
-			sizeof(sinfo->device));
-	cam_strvis((uint8_t *)sinfo->rev, cgd->ident_data.revision,
-			sizeof(cgd->ident_data.revision),
-			sizeof(sinfo->rev));
-	cam_strvis((uint8_t *)sinfo->serial, cgd->ident_data.serial,
-			sizeof(cgd->ident_data.serial),
-			sizeof(sinfo->serial));
-
-	return 0;
-}
-
-static int32_t
-__device_info_scsi(struct fbsd_smart *fsmart, struct ccb_getdev *cgd)
-{
-	smart_info_t *sinfo = NULL;
-	union ccb *ccb = NULL;
-	struct scsi_vpd_unit_serial_number *snum = NULL;
-	struct scsi_log_informational_exceptions ie = {0};
-
-	if (!fsmart || !cgd) {
-		return -1;
-	}
-
-	sinfo = &fsmart->common.info;
-
-	cam_strvis((uint8_t *)sinfo->vendor, (uint8_t *)cgd->inq_data.vendor,
-			sizeof(cgd->inq_data.vendor),
-			sizeof(sinfo->vendor));
-	cam_strvis((uint8_t *)sinfo->device, (uint8_t *)cgd->inq_data.product,
-			sizeof(cgd->inq_data.product),
-			sizeof(sinfo->device));
-	cam_strvis((uint8_t *)sinfo->rev, (uint8_t *)cgd->inq_data.revision,
-			sizeof(cgd->inq_data.revision),
-			sizeof(sinfo->rev));
-
-	ccb = cam_getccb(fsmart->camdev);
-	snum = malloc(sizeof(struct scsi_vpd_unit_serial_number));
-	if (!ccb || !snum) {
-		warn("Allocation failure ccb=%p snum=%p", ccb, snum);
-		goto __device_info_scsi_out;
-	}
-
-	/* Get the serial number */
-	CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
-
-	scsi_inquiry(&ccb->csio,
-			3, // retries
-			NULL, // callback function
-			MSG_SIMPLE_Q_TAG, // tag action
-			(uint8_t *)snum,
-			sizeof(struct scsi_vpd_unit_serial_number),
-			1, // EVPD
-			SVPD_UNIT_SERIAL_NUMBER, // page code
-			SSD_FULL_SIZE, // sense length
-			5000); // timeout
-
-	ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
-
-	if ((cam_send_ccb(fsmart->camdev, ccb) >= 0) &&
-			((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)) {
-		cam_strvis((uint8_t *)sinfo->serial, snum->serial_num,
-				snum->length,
-				sizeof(sinfo->serial));
-		sinfo->serial[sizeof(sinfo->serial) - 1] = '\0';
-	}
-
-	memset(ccb, 0, sizeof(*ccb));
-
-	scsi_log_sense(&ccb->csio,
-			/* retries */1,
-			/* cbfcnp */NULL,
-			/* tag_action */0,
-			/* page_code */SLS_PAGE_CTRL_CUMULATIVE,
-			/* page */SLS_IE_PAGE,
-			/* save_pages */0,
-			/* ppc */0,
-			/* paramptr */0,
-			/* param_buf */(uint8_t *)&ie,
-			/* param_len */sizeof(ie),
-			/* sense_len */0,
-			/* timeout */5000);
-
-	/*
-	 * Note: The existance of the Informational Exceptions (IE) log page
-	 *       appears to be the litmus test for SMART support in SCSI
-	 *       devices. Confusingly, smartctl will report SMART health
-	 *       status as 'OK' if the device doesn't support the IE page.
-	 *       For now, just report the facts.
-	 */
-	if ((cam_send_ccb(fsmart->camdev, ccb) >= 0) &&
-			((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)) {
-		if ((ie.hdr.param_len < 4) || ie.ie_asc || ie.ie_ascq) {
-			printf("Log Sense, Informational Exceptions failed "
-					"(length=%u asc=%#x ascq=%#x)\n",
-					ie.hdr.param_len, ie.ie_asc, ie.ie_ascq);
-		} else {
-			sinfo->supported = true;
-		}
-	}
-
-__device_info_scsi_out:
-	free(snum);
-	if (ccb)
-		cam_freeccb(ccb);
-
-	return 0;
-}
-
-static int32_t
-__device_info_nvme(struct fbsd_smart *fsmart, struct ccb_getdev *cgd)
-{
-	union ccb *ccb;
-	smart_info_t *sinfo = NULL;
-	struct nvme_controller_data cd;
-
-	if (!fsmart || !cgd) {
-		return -1;
-	}
-
-	sinfo = &fsmart->common.info;
-
-	sinfo->supported = true;
-
-	ccb = cam_getccb(fsmart->camdev);
-	if (ccb != NULL) {
-		struct ccb_dev_advinfo *cdai = &ccb->cdai;
-
-		CCB_CLEAR_ALL_EXCEPT_HDR(cdai);
-
-		cdai->ccb_h.func_code = XPT_DEV_ADVINFO;
-		cdai->ccb_h.flags = CAM_DIR_IN;
-		cdai->flags = CDAI_FLAG_NONE;
-#ifdef CDAI_TYPE_NVME_CNTRL
-		cdai->buftype = CDAI_TYPE_NVME_CNTRL;
-#else
-		cdai->buftype = 6;
-#endif
-		cdai->bufsiz = sizeof(struct nvme_controller_data);
-		cdai->buf = (uint8_t *)&cd;
-
-		if (cam_send_ccb(fsmart->camdev, ccb) >= 0) {
-			if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
-				cam_strvis((uint8_t *)sinfo->device, cd.mn,
-						sizeof(cd.mn),
-						sizeof(sinfo->device));
-				cam_strvis((uint8_t *)sinfo->rev, cd.fr,
-						sizeof(cd.fr),
-						sizeof(sinfo->rev));
-				cam_strvis((uint8_t *)sinfo->serial, cd.sn,
-						sizeof(cd.sn),
-						sizeof(sinfo->serial));
-			}
-		}
-
-		cam_freeccb(ccb);
-	}
-
-	return 0;
-}
-
-static int32_t
-__device_info_tunneled_ata(struct fbsd_smart *fsmart)
-{
-	struct ata_params ident_data;
-	union ccb *ccb = NULL;
-	struct ata_pass_16 *ata_pass_16;
-	struct ata_cmd ata_cmd;
-	int32_t rc = -1;
-
-	ccb = cam_getccb(fsmart->camdev);
-	if (ccb == NULL) {
-		goto __device_info_tunneled_ata_out;
-	}
-
-	memset(&ident_data, 0, sizeof(struct ata_params));
-
-	CCB_CLEAR_ALL_EXCEPT_HDR(ccb);
-
-	scsi_ata_pass_16(&ccb->csio,
-			/*retries*/	1,
-			/*cbfcnp*/	NULL,
-			/*flags*/	CAM_DIR_IN,
-			/*tag_action*/	MSG_SIMPLE_Q_TAG,
-			/*protocol*/	AP_PROTO_PIO_IN,
-			/*ata_flags*/	AP_FLAG_TLEN_SECT_CNT |
-					AP_FLAG_BYT_BLOK_BLOCKS |
-					AP_FLAG_TDIR_FROM_DEV,
-			/*features*/	0,
-			/*sector_count*/sizeof(struct ata_params),
-			/*lba*/		0,
-			/*command*/	ATA_ATA_IDENTIFY,
-			/*control*/	0,
-			/*data_ptr*/	(uint8_t *)&ident_data,
-			/*dxfer_len*/	sizeof(struct ata_params),
-			/*sense_len*/	SSD_FULL_SIZE,
-			/*timeout*/	5000
-			);
-
-	ata_pass_16 = (struct ata_pass_16 *)ccb->csio.cdb_io.cdb_bytes;
-	ata_cmd.command = ata_pass_16->command;
-	ata_cmd.control = ata_pass_16->control;
-	ata_cmd.features = ata_pass_16->features;
-
-	rc = cam_send_ccb(fsmart->camdev, ccb);
-	if (rc != 0) {
-		warnx("%s: scsi_ata_pass_16() failed (programmer error?)",
-				__func__);
-		goto __device_info_tunneled_ata_out;
-	}
-
-	fsmart->common.info.supported = ident_data.support.command1 &
-		ATA_SUPPORT_SMART;
-
-	dprintf("ATA command1 = %#x\n", ident_data.support.command1);
-
-__device_info_tunneled_ata_out:
-	if (ccb) {
-		cam_freeccb(ccb);
-	}
-
-	return rc;
-}
-
-/**
- * Retrieve the device information and use to populate the info structure
- */
-static int32_t
-__device_get_info(struct fbsd_smart *fsmart)
-{
-	union ccb *ccb;
-	int32_t rc = -1;
-
-	if (!fsmart || !fsmart->camdev) {
-		warn("Bad handle %p", fsmart);
-		return -1;
-	}
-
-	ccb = cam_getccb(fsmart->camdev);
-	if (ccb != NULL) {
-		struct ccb_getdev *cgd = &ccb->cgd;
-
-		CCB_CLEAR_ALL_EXCEPT_HDR(cgd);
-
-		/*
-		 * GDEV_TYPE doesn't support NVMe. What we do get is:
-		 *  - device (ata/model, scsi/product)
-		 *  - revision (ata, scsi)
-		 *  - serial (ata)
-		 *  - vendor (scsi)
-		 *  - supported (ata)
-		 *
-		 *  Serial # for all proto via ccb_dev_advinfo (buftype CDAI_TYPE_SERIAL_NUM)
-		 */
-		ccb->ccb_h.func_code = XPT_GDEV_TYPE;
-
-		if (cam_send_ccb(fsmart->camdev, ccb) >= 0) {
-			if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
-				switch (cgd->protocol) {
-				case PROTO_ATA:
-					rc = __device_info_ata(fsmart, cgd);
-					break;
-				case PROTO_SCSI:
-					rc = __device_info_scsi(fsmart, cgd);
-					if (!rc && fsmart->common.protocol == SMART_PROTO_ATA) {
-						rc = __device_info_tunneled_ata(fsmart);
-					}
-					break;
-				case PROTO_NVME:
-					rc = __device_info_nvme(fsmart, cgd);
-					break;
-				default:
-					printf("%s: unsupported protocol %d\n",
-							__func__, cgd->protocol);
-				}
-			}
-		}
-
-		cam_freeccb(ccb);
-	}
-
-	return rc;
-}
diff --git a/contrib/smart/libsmart.c b/contrib/smart/libsmart.c
deleted file mode 100644
index a1732de09ed9..000000000000
--- a/contrib/smart/libsmart.c
+++ /dev/null
@@ -1,1359 +0,0 @@
-/*
- * Copyright (c) 2016-2026 Chuck Tuffli <chuck@tuffli.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <assert.h>
-#include <err.h>
*** 2512 LINES SKIPPED ***


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69f104a0.27812.208ed91f>