| | 226 | ///////////////////////////////////////////////////////////////////////////// |
| | 227 | // sntjmicron_device |
| | 228 | |
| | 229 | class sntrealtek_device |
| | 230 | : public tunnelled_device< |
| | 231 | /*implements*/ nvme_device, |
| | 232 | /*by tunnelling through a*/ scsi_device |
| | 233 | > |
| | 234 | { |
| | 235 | public: |
| | 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 | |
| | 244 | sntrealtek_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 | |
| | 252 | sntrealtek_device::~sntrealtek_device() throw() |
| | 253 | { |
| | 254 | } |
| | 255 | |
| | 256 | bool 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 | |