Ticket #1315: ticket1315-scsinvme.patch

File ticket1315-scsinvme.patch, 3.9 KB (added by Christian Franke, 4 years ago)

Proposed patch

  • scsinvme.cpp

     
    11/*
    22 * scsinvme.cpp
    33 *
    4  * Home page of code is: http://www.smartmontools.org
     4 * Home page of code is: https://www.smartmontools.org
    55 *
     6 * Copyright (C) 2020 Christian Franke
    67 * Copyright (C) 2018 Harry Mallon <hjmallon@gmail.com>
    78 *
    89 * SPDX-License-Identifier: GPL-2.0-or-later
     
    1314
    1415#include "dev_interface.h"
    1516#include "dev_tunnelled.h"
     17#include "nvmecmds.h"
    1618#include "scsicmds.h"
    1719#include "sg_unaligned.h"
    1820#include "utility.h"
     
    2224// SNT (SCSI NVMe Translation) namespace and prefix
    2325namespace snt {
    2426
     27/////////////////////////////////////////////////////////////////////////////
     28// sntjmicron_device
     29
    2530#define SNT_JMICRON_NVME_SIGNATURE 0x454d564eu // 'NVME' reversed (little endian)
    2631#define SNT_JMICRON_CDB_LEN 12
    2732#define SNT_JMICRON_NVM_CMD_LEN 512
     
    218223  return true;
    219224}
    220225
     226/////////////////////////////////////////////////////////////////////////////
     227// sntjmicron_device
     228
     229class sntrealtek_device
     230: public tunnelled_device<
     231    /*implements*/ nvme_device,
     232    /*by tunnelling through a*/ scsi_device
     233  >
     234{
     235public:
     236  sntrealtek_device(smart_interface * intf, scsi_device * scsidev,
     237                    const char * req_type, unsigned nsid);
     238
     239  virtual ~sntrealtek_device() throw();
     240
     241  virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out);
     242};
     243
     244sntrealtek_device::sntrealtek_device(smart_interface * intf, scsi_device * scsidev,
     245                                     const char * req_type, unsigned nsid)
     246: smart_device(intf, scsidev->get_dev_name(), "sntrealtek", req_type),
     247  tunnelled_device<nvme_device, scsi_device>(scsidev, nsid)
     248{
     249  set_info().info_name = strprintf("%s [USB NVMe Realtek]", scsidev->get_info_name());
     250}
     251
     252sntrealtek_device::~sntrealtek_device() throw()
     253{
     254}
     255
     256bool sntrealtek_device::nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & /* out */)
     257{
     258  switch (in.opcode) {
     259    case smartmontools::nvme_admin_identify:
     260      if (in.cdw10 == 0x0000001) // Identify controller
     261        break;
     262      if (in.cdw10 == 0x0000000) { // Identify namespace
     263        if (in.nsid == 1)
     264          break;
     265        return set_err(ENOSYS, "NVMe Identify Namespace 0x%02x not supported", in.nsid);
     266      }
     267      return set_err(ENOSYS, "NVMe Identify with CDW10=0x%08x not supported", in.cdw10);
     268    case smartmontools::nvme_admin_get_log_page:
     269      if (in.nsid == 0xffffffff || !in.nsid)
     270        break;
     271      return set_err(ENOSYS, "NVMe Get Log Page with NSID=0x%02x not supported", in.nsid);
     272    default:
     273      return set_err(ENOSYS, "NVMe admin command 0x%02x not supported", in.opcode);
     274    break;
     275  }
     276  if (in.cdw11 || in.cdw12 || in.cdw13 || in.cdw14 || in.cdw15)
     277    return set_err(ENOSYS, "Nonzero NVMe command dwords 11-15 not supported");
     278
     279  uint8_t cdb[16] = {0, };
     280  cdb[0] = 0xe4;
     281  sg_put_unaligned_le16(in.size, cdb+1);
     282  cdb[3] = in.opcode;
     283  cdb[4] = (uint8_t)in.cdw10;
     284
     285  scsi_cmnd_io io_hdr; memset(&io_hdr, 0, sizeof(io_hdr));
     286  io_hdr.cmnd = cdb;
     287  io_hdr.cmnd_len = sizeof(cdb);
     288  io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
     289  io_hdr.dxferp = (uint8_t *)in.buffer;
     290  io_hdr.dxfer_len = in.size;
     291
     292  scsi_device * scsidev = get_tunnel_dev();
     293  if (!scsidev->scsi_pass_through_and_check(&io_hdr, "sntrealtek_device::nvme_pass_through: "))
     294    return set_err(scsidev->get_err());
     295
     296  //out.result = ?; // TODO
     297  return true;
     298}
     299
     300
    221301} // namespace snt
    222302
    223303using namespace snt;
     
    248328    }
    249329    sntdev = new sntjmicron_device(this, scsidev, type, nsid);
    250330  }
     331
     332  else if (!strcmp(type, "sntrealtek")) {
     333    // No namespace supported
     334    sntdev = new sntrealtek_device(this, scsidev, type, 0xffffffff);
     335  }
     336
    251337  else {
    252338    set_err(EINVAL, "Unknown SNT device type '%s'", type);
    253339    return 0;