The diff below enables smartmontools (smartctl & smartd) support for
NVMe disks on -current kernels with the latest nvme(4) passthrough
commits.

Obvious features tested and work for me on various amd64 boxes and my m1
macmini.

ian@ has also succesfully tested it.

Thoughts? OK?
--
.... Ken

Index: Makefile
===================================================================
RCS file: /cvs/ports/sysutils/smartmontools/Makefile,v
diff -u -p -u -p -r1.50 Makefile
--- Makefile    27 Sep 2023 17:16:34 -0000      1.50
+++ Makefile    26 May 2024 14:54:25 -0000
@@ -2,6 +2,7 @@ COMMENT=                control and monitor storage sy

 # XXX at update time check whether C++11 is actually needed
 DISTNAME=              smartmontools-7.4
+REVISION=              0
 CATEGORIES=            sysutils

 HOMEPAGE=              https://www.smartmontools.org/
Index: patches/patch-openbsd_nvme_ioctl_h
===================================================================
RCS file: patches/patch-openbsd_nvme_ioctl_h
diff -N patches/patch-openbsd_nvme_ioctl_h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-openbsd_nvme_ioctl_h  26 May 2024 14:54:25 -0000
@@ -0,0 +1,78 @@
+Index: openbsd_nvme_ioctl.h
+--- openbsd_nvme_ioctl.h.orig
++++ openbsd_nvme_ioctl.h
+@@ -0,0 +1,74 @@
++/*
++ * Copyright (c) 2024 Kenneth R Westerback <k...@openbsd.org>
++ *
++ * 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.
++ */
++
++#define       NVME_PASSTHROUGH_CMD            _IOWR('n', 0, struct 
nvme_pt_cmd)
++
++struct nvme_pt_status {
++      int                     ps_dv_unit;
++      int                     ps_nsid;
++      int                     ps_flags;
++#define NVME_CQE_SCT(_f)      ((_f) & (0x07 << 9))
++#define  NVME_CQE_SCT_GENERIC         (0x00 << 9)
++#define NVME_CQE_SC(_f)               ((_f) & (0xff << 1))
++#define  NVME_CQE_SC_SUCCESS          (0x00 << 1)
++      uint32_t                ps_csts;
++      uint32_t                ps_cc;
++};
++
++#define       BIO_MSG_COUNT   5
++#define       BIO_MSG_LEN     128
++
++struct bio_msg {
++      int             bm_type;
++      char            bm_msg[BIO_MSG_LEN];
++};
++
++struct bio_status {
++      char            bs_controller[16];
++      int             bs_status;
++      int             bs_msg_count;
++      struct bio_msg  bs_msgs[BIO_MSG_COUNT];
++};
++
++struct bio {
++      void                    *bio_cookie;
++      struct bio_status       bio_status;
++};
++
++struct nvme_pt_cmd {
++      /* Commands may arrive via /dev/bio. */
++      struct bio              pt_bio;
++
++      /* The sqe fields that the caller may specify. */
++      uint8_t                 pt_opcode;
++      uint32_t                pt_nsid;
++      uint32_t                pt_cdw10;
++      uint32_t                pt_cdw11;
++      uint32_t                pt_cdw12;
++      uint32_t                pt_cdw13;
++      uint32_t                pt_cdw14;
++      uint32_t                pt_cdw15;
++
++      caddr_t                 pt_status;
++      uint32_t                pt_statuslen;
++
++      caddr_t                 pt_databuf;     /* User space address. */
++      uint32_t                pt_databuflen;  /* Length of buffer. */
++};
++
++#define       nvme_completion_is_error(_flags)                                
\
++      ((NVME_CQE_SC(_flags) != NVME_CQE_SC_SUCCESS)                   \
++          || (NVME_CQE_SCT(_flags) != NVME_CQE_SCT_GENERIC))
Index: patches/patch-os_openbsd_cpp
===================================================================
RCS file: patches/patch-os_openbsd_cpp
diff -N patches/patch-os_openbsd_cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-os_openbsd_cpp        26 May 2024 14:54:25 -0000
@@ -0,0 +1,196 @@
+Index: os_openbsd.cpp
+--- os_openbsd.cpp.orig
++++ os_openbsd.cpp
+@@ -14,6 +14,7 @@
+
+ #include "atacmds.h"
+ #include "scsicmds.h"
++#include "nvmecmds.h"
+ #include "utility.h"
+ #include "os_openbsd.h"
+
+@@ -22,11 +23,29 @@
+ #include <sys/stat.h>
+ #include <util.h>
+
++// based on OpenBSD "/usr/include/dev/ic/nvmeio.h" && 
"/usr/include/dev/biovar.h"
++#include "openbsd_nvme_ioctl.h"       // NVME_PASSTHROUGH_CMD, 
nvme_completion_is_error
+ const char * os_openbsd_cpp_cvsid = "$Id: os_openbsd.cpp 5393 2022-05-29 
05:08:10Z dpgilbert $"
+   OS_OPENBSD_H_CVSID;
+
+ #define ARGUSED(x) ((void)(x))
+
++bool sd_is_nvme(const char *dev)
++{
++      struct nvme_pt_cmd pt;
++      memset(&pt, 0, sizeof(pt));
++      pt.pt_opcode = smartmontools::nvme_admin_identify;
++
++      int fd = ::open(dev, O_RDWR);
++      if (fd == -1)
++        return false;
++
++      int status = ioctl(fd, NVME_PASSTHROUGH_CMD, &pt);
++      close(fd);
++
++      return status != -1 || errno != ENOTTY;
++}
++
+ /////////////////////////////////////////////////////////////////////////////
+
+ namespace os_openbsd { // No need to publish anything, name provided for 
Doxygen
+@@ -209,6 +228,80 @@ bool openbsd_ata_device::ata_pass_through(const ata_cm
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
++/// NVMe support
++
++class openbsd_nvme_device
++: public /*implements*/ nvme_device,
++  public /*extends*/ openbsd_smart_device
++{
++public:
++  openbsd_nvme_device(smart_interface * intf, const char * dev_name,
++    const char * req_type, unsigned nsid);
++
++  virtual bool open() override;
++
++  virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out) 
override;
++};
++
++openbsd_nvme_device::openbsd_nvme_device(smart_interface * intf, const char * 
dev_name,
++  const char * req_type, unsigned nsid)
++: smart_device(intf, dev_name, "nvme", req_type),
++  nvme_device(nsid),
++  openbsd_smart_device()
++{
++}
++
++bool openbsd_nvme_device::open()
++{
++  const char *dev = get_dev_name();
++  int fd;
++
++  if ((fd = ::open(dev, O_RDWR)) == -1) {
++    set_err(errno, "can't open sd device");
++    return false;
++  }
++
++  set_fd(fd);
++
++  return true;
++}
++
++bool openbsd_nvme_device::nvme_pass_through(const nvme_cmd_in & in, 
nvme_cmd_out & out)
++{
++  struct nvme_pt_cmd pt;
++  struct nvme_pt_status ps;
++
++  memset(&ps, 0, sizeof(ps));
++  memset(&pt.pt_bio, 0, sizeof(pt.pt_bio));
++
++  pt.pt_opcode = in.opcode;
++  pt.pt_nsid = in.nsid;
++  pt.pt_databuf = (caddr_t)in.buffer;
++  pt.pt_databuflen = in.size;
++  pt.pt_cdw10 = in.cdw10;
++  pt.pt_cdw11 = in.cdw11;
++  pt.pt_cdw12 = in.cdw12;
++  pt.pt_cdw13 = in.cdw13;
++  pt.pt_cdw14 = in.cdw14;
++  pt.pt_cdw15 = in.cdw15;
++  pt.pt_status = (char *)&ps;
++  pt.pt_statuslen = sizeof(ps);
++
++  int status = ioctl(get_fd(), NVME_PASSTHROUGH_CMD, &pt);
++
++  if (status == -1)
++    return set_err(errno, "NVME_PASSTHROUGH_CMD: %s", strerror(errno));
++
++  out.result = 0; // cqe.cdw0 (Command specific result) is not provided
++
++  if (nvme_completion_is_error(ps.ps_flags))
++    return set_nvme_err(out, nvme_completion_is_error(ps.ps_flags));
++
++  return true;
++}
++
++
++/////////////////////////////////////////////////////////////////////////////
+ /// Standard SCSI support
+
+ class openbsd_scsi_device
+@@ -381,6 +474,9 @@ class openbsd_smart_interface (protected)
+
+   virtual scsi_device * get_scsi_device(const char * name, const char * type) 
override;
+
++  virtual nvme_device * get_nvme_device(const char * name, const char * type,
++    unsigned nsid) override;
++
+   virtual smart_device * autodetect_smart_device(const char * name) override;
+
+   virtual smart_device * get_custom_smart_device(const char * name, const 
char * type) override;
+@@ -434,6 +530,11 @@ scsi_device * openbsd_smart_interface::get_scsi_device
+   return new openbsd_scsi_device(this, name, type);
+ }
+
++nvme_device * openbsd_smart_interface::get_nvme_device(const char * name, 
const char * type, unsigned nsid)
++{
++  return new openbsd_nvme_device(this, name, type, nsid);
++}
++
+ int openbsd_smart_interface::get_dev_names(char ***names, const char *prefix)
+ {
+   char *disknames, *p, **mp;
+@@ -504,6 +605,7 @@ bool openbsd_smart_interface::scan_smart_devices(smart
+
+     bool scan_ata = !*type || !strcmp(type, "ata");
+     bool scan_scsi = !*type || !strcmp(type, "scsi") || !strcmp(type, "sat");
++    bool scan_nvme = !*type || !strcmp(type, "nvme");
+
+     // Make namelists
+     char * * atanames = 0; int numata = 0;
+@@ -517,7 +619,7 @@ bool openbsd_smart_interface::scan_smart_devices(smart
+
+     char * * scsinames = 0; int numscsi = 0;
+     char * * scsitapenames = 0; int numscsitape = 0;
+-    if (scan_scsi) {
++    if (scan_scsi || scan_nvme) {
+       numscsi = get_dev_names(&scsinames, net_dev_scsi_disk);
+       if (numscsi < 0) {
+         set_err(ENOMEM);
+@@ -541,9 +643,17 @@ bool openbsd_smart_interface::scan_smart_devices(smart
+     if(numata) free(atanames);
+
+     for (i = 0; i < numscsi; i++) {
+-      scsi_device * scsidev = new openbsd_scsi_device(this, scsinames[i], 
type, true /*scanning*/);
+-      if (scsidev)
+-        devlist.push_back(scsidev);
++      if (sd_is_nvme(scsinames[i])) {
++        if (scan_nvme) {
++          nvme_device * nvmedev = new openbsd_nvme_device(this, scsinames[i], 
type, true /*scanning*/);
++          if (nvmedev)
++            devlist.push_back(nvmedev);
++        }
++      } else if (scan_scsi) {
++        scsi_device * scsidev = new openbsd_scsi_device(this, scsinames[i], 
type, true /*scanning*/);
++        if (scsidev)
++          devlist.push_back(scsidev);
++      }
+       free(scsinames[i]);
+     }
+     if(numscsi) free(scsinames);
+@@ -588,8 +698,11 @@ smart_device * openbsd_smart_interface::autodetect_sma
+       // XXX get USB vendor ID, product ID and version from sd(4)/umass(4).
+       // XXX check sat device via get_usb_dev_type_by_id().
+
+-      // No USB bridge found, assume regular SCSI or SAT device
+-      return get_scsi_device(name, "");
++      // No USB bridge found, decide if it's NVME or regular SCSI or SAT 
device
++      if (sd_is_nvme(name))
++        return get_nvme_device(name, "nvme", 0);
++      else
++        return get_scsi_device(name, "");
+     }
+     if (!strncmp(net_dev_scsi_tape, test_name, strlen(net_dev_scsi_tape)))
+       return get_scsi_device(name, "scsi");
Index: patches/patch-smartctl_8_in
===================================================================
RCS file: patches/patch-smartctl_8_in
diff -N patches/patch-smartctl_8_in
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-smartctl_8_in 26 May 2024 14:54:25 -0000
@@ -0,0 +1,170 @@
+Index: smartctl.8.in
+--- smartctl.8.in.orig
++++ smartctl.8.in
+@@ -233,11 +233,11 @@ in the smartmontools database (see \*(Aq\-v\*(Aq optio
+ drive model family may also be printed.
+ If \*(Aq\-n\*(Aq (see below) is specified, the power mode of the drive is
+ printed.
+-.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %IF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .Sp
+ [NVMe] For NVMe devices the information is obtained from the Identify
+ Controller and the Identify Namespace data structure.
+-.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %ENDIF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .TP
+ .B \-\-identify[=[w][nvb]]
+ [ATA only] Prints an annotated table of the IDENTIFY DEVICE data.
+@@ -266,12 +266,12 @@ the SMART options which require support for 48-bit ATA
+ For SCSI, this is equivalent to
+ .br
+ \*(Aq\-H \-i \-A \-l error \-l selftest\*(Aq.
+-.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %IF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .Sp
+ For NVMe, this is equivalent to
+ .br
+ \*(Aq\-H \-i \-c \-A \-l error \-l selftest\*(Aq.
+-.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %ENDIF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .TP
+ .B \-x, \-\-xall
+ Prints all SMART and non-SMART information about the device.
+@@ -290,12 +290,12 @@ For SCSI disks, this is equivalent to
+ \-l defects \-l envrep \-l genstats \-l ssd \-l zdevstat\*(Aq
+ .br
+ and for SCSI tape drives and changers, add \*(Aq\-l tapedevstat\*(Aq.
+-.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %IF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .Sp
+ For NVMe, this is equivalent to
+ .br
+ \*(Aq\-H \-i \-c \-A \-l error \-l selftest\*(Aq.
+-.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %ENDIF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .TP
+ .B \-\-scan
+ Scans for devices and prints each device name, device type and protocol
+@@ -1184,11 +1184,11 @@ Prefailure SMART Attribute value is less than or equal
+ [SCSI tape drive or changer] The TapeAlert status is obtained by reading the
+ TapeAlert log page, but only if this option is given twice (see
+ \fBTAPE DRIVES\fP for the rationale).
+-.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %IF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .Sp
+ [NVMe] NVMe status is obtained by reading the "Critical Warning" byte from
+ the SMART/Health Information log.
+-.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %ENDIF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .TP
+ .B \-c, \-\-capabilities
+ [ATA] Prints only the generic SMART capabilities.  These
+@@ -1197,11 +1197,11 @@ respond to some of the different SMART commands.  For
+ shows if the device logs errors, if it supports offline surface
+ scanning, and so on.  If the device can carry out self-tests, this
+ option also shows the estimated time required to run those tests.
+-.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %IF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .Sp
+ [NVMe] Prints various NVMe device capabilities obtained from the Identify
+ Controller and the Identify Namespace data structure.
+-.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %ENDIF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .TP
+ .B \-A, \-\-attributes
+ [ATA] Prints only the vendor specific SMART Attributes.  The Attributes
+@@ -1298,11 +1298,11 @@ and start-stop cycle counter log pages.
+ Certain vendor specific attributes are listed if recognised.
+ The attributes are output in a relatively free format (compared with ATA
+ disk attributes).
+-.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %IF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .Sp
+ [NVMe] For NVMe devices the attributes are obtained from the SMART/Health
+ Information log.
+-.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %ENDIF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .TP
+ .B \-f FORMAT, \-\-format=FORMAT
+ [ATA only] Selects the output format of the attributes:
+@@ -1407,7 +1407,7 @@ receives a command which is not implemented or is not
+ \- [SCSI] prints the error counter log pages for reads, write and verifies.
+ The verify row is only output if it has an element other than zero.
+ .Sp
+-.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %IF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .I error[,NUM]
+ \- [NVMe] prints the NVMe Error Information log.
+ Only the 16 most recent log entries are printed by default.
+@@ -1419,7 +1419,7 @@ Note that the contents of this log is not preserved ac
+ controller resets, but the value of \*(AqError Information Log Entries\*(Aq
+ from SMART/Health Information log is.
+ .Sp
+-.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %ENDIF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .I xerror[,NUM][,error]
+ \- [ATA only] prints the Extended Comprehensive SMART error log
+ (General Purpose Log address 0x03).  Unlike the Summary SMART error
+@@ -1472,12 +1472,12 @@ If provided, the SCSI Sense Key (SK), Additional Sense
+ Additional Sense Code Qualifier (ASCQ) are also printed.  The self tests
+ can be run using the \*(Aq\-t\*(Aq option described below (using the ATA
+ test terminology).
+-.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %IF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .Sp
+ .I selftest
+ \- [NVMe: NEW EXPERIMENTAL SMARTCTL 7.4 FEATURE]
+ prints the NVMe self-test log.
+-.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %ENDIF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .Sp
+ .I xselftest[,NUM][,selftest]
+ \- [ATA only] prints the Extended SMART self-test log (General Purpose
+@@ -1663,7 +1663,7 @@ This command:
+ writes a binary representation of the one sector log 0x11
+ (SATA Phy Event Counters) to file log.bin.
+ .Sp
+-.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %IF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .I nvmelog,PAGE,SIZE
+ \- [NVMe only] prints a hex dump of the first SIZE bytes from the NVMe
+ log with identifier PAGE.
+@@ -1672,7 +1672,7 @@ SIZE is a hexadecimal number in the range from 0x4 to
+ \fBWARNING: Do not specify the identifier of an unknown log page.
+ Reading a log page may have undesirable side effects.\fP
+ .Sp
+-.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %ENDIF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .I ssd
+ \- [ATA] prints the Solid State Device Statistics log page.
+ This has the same effect as \*(Aq\-l devstat,7\*(Aq, see above.
+@@ -2130,12 +2130,12 @@ with other disks use the \*(Aq\-c\*(Aq option to monit
+ .Sp
+ .I short
+ \- [SCSI] runs the "Background short" self-test.
+-.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %IF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .Sp
+ .I short
+ \- [NVMe: NEW EXPERIMENTAL SMARTCTL 7.4 FEATURE]
+ runs the "Short" self-test for current namespace.
+-.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %ENDIF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .Sp
+ .I long
+ \- [ATA] runs SMART Extended Self Test (tens of minutes to several hours).
+@@ -2146,12 +2146,12 @@ below).
+ .Sp
+ .I long
+ \- [SCSI] runs the "Background long" self-test.
+-.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %IF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .Sp
+ .I long
+ \- [NVMe: NEW EXPERIMENTAL SMARTCTL 7.4 FEATURE]
+ runs the "Extended" self-test for current namespace.
+-.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %ENDIF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .Sp
+ .I conveyance
+ \- [ATA only] runs a SMART Conveyance Self Test (minutes).  This
Index: patches/patch-smartd_8_in
===================================================================
RCS file: patches/patch-smartd_8_in
diff -N patches/patch-smartd_8_in
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ patches/patch-smartd_8_in   26 May 2024 14:54:25 -0000
@@ -0,0 +1,17 @@
+Index: smartd.8.in
+--- smartd.8.in.orig
++++ smartd.8.in
+@@ -458,11 +458,11 @@ this option are:
+ .I scsiioctl
+ \- report only ioctl() transactions with SCSI devices.
+ .Sp
+-.\" %IF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %IF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ .I nvmeioctl
+ \- report only ioctl() transactions with NVMe devices.
+ .Sp
+-.\" %ENDIF OS Darwin FreeBSD Linux NetBSD Windows Cygwin
++.\" %ENDIF OS Darwin FreeBSD Linux NetBSD OpenBSD Windows Cygwin
+ Any argument may include a positive integer to specify the level of
+ detail that should be reported.  The argument should be followed by a
+ comma then the integer with no spaces.  For example, \fIataioctl,2\fP

Reply via email to