| 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 | |