--- /dev/null
+Allow smartd 'DEVICESCAN -d sat'
+--- a/os_linux.cpp
++++ b/os_linux.cpp
+@@ -831,17 +831,22 @@ class linux_scsi_device
+ public /*extends*/ linux_smart_device
+ {
+ public:
+- linux_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type);
++ linux_scsi_device(smart_interface * intf, const char * dev_name,
++ const char * req_type, bool scanning = false);
+
+ virtual smart_device * autodetect_open();
+
+ virtual bool scsi_pass_through(scsi_cmnd_io * iop);
++
++private:
++ bool m_scanning; ///< true if created within scan_smart_devices
+ };
+
+ linux_scsi_device::linux_scsi_device(smart_interface * intf,
+- const char * dev_name, const char * req_type)
++ const char * dev_name, const char * req_type, bool scanning /*= false*/)
+ : smart_device(intf, dev_name, "scsi", req_type),
+- linux_smart_device(O_RDWR | O_NONBLOCK, O_RDONLY | O_NONBLOCK)
++ linux_smart_device(O_RDWR | O_NONBLOCK, O_RDONLY | O_NONBLOCK),
++ m_scanning(scanning)
+ {
+ }
+
+@@ -2646,8 +2651,13 @@ smart_device * linux_scsi_device::autode
+ return this;
+
+ // No Autodetection if device type was specified by user
+- if (*get_req_type())
+- return this;
++ bool sat_only = false;
++ if (*get_req_type()) {
++ // Detect SAT if device object was created by scan_smart_devices().
++ if (!(m_scanning && !strcmp(get_req_type(), "sat")))
++ return this;
++ sat_only = true;
++ }
+
+ // The code below is based on smartd.cpp:SCSIFilterKnown()
+
+@@ -2668,36 +2678,43 @@ smart_device * linux_scsi_device::autode
+
+ int avail_len = req_buff[4] + 5;
+ int len = (avail_len < req_len ? avail_len : req_len);
+- if (len < 36)
++ if (len < 36) {
++ if (sat_only) {
++ close();
++ set_err(EIO, "INQUIRY too short for SAT");
++ }
+ return this;
++ }
+
+ // Use INQUIRY to detect type
++ if (!sat_only) {
+
+- // 3ware ?
+- if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4)) {
+- close();
+- set_err(EINVAL, "AMCC/3ware controller, please try adding '-d 3ware,N',\n"
+- "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name());
+- return this;
+- }
++ // 3ware ?
++ if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4)) {
++ close();
++ set_err(EINVAL, "AMCC/3ware controller, please try adding '-d 3ware,N',\n"
++ "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name());
++ return this;
++ }
+
+- // DELL?
+- if (!memcmp(req_buff + 8, "DELL PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8)) {
+- close();
+- set_err(EINVAL, "DELL or MegaRaid controller, please try adding '-d megaraid,N'");
+- return this;
+- }
++ // DELL?
++ if (!memcmp(req_buff + 8, "DELL PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8)) {
++ close();
++ set_err(EINVAL, "DELL or MegaRaid controller, please try adding '-d megaraid,N'");
++ return this;
++ }
+
+- // Marvell ?
+- if (len >= 42 && !memcmp(req_buff + 36, "MVSATA", 6)) {
+- //pout("Device %s: using '-d marvell' for ATA disk with Marvell driver\n", get_dev_name());
+- close();
+- smart_device_auto_ptr newdev(
+- new linux_marvell_device(smi(), get_dev_name(), get_req_type())
+- );
+- newdev->open(); // TODO: Can possibly pass open fd
+- delete this;
+- return newdev.release();
++ // Marvell ?
++ if (len >= 42 && !memcmp(req_buff + 36, "MVSATA", 6)) {
++ //pout("Device %s: using '-d marvell' for ATA disk with Marvell driver\n", get_dev_name());
++ close();
++ smart_device_auto_ptr newdev(
++ new linux_marvell_device(smi(), get_dev_name(), get_req_type())
++ );
++ newdev->open(); // TODO: Can possibly pass open fd
++ delete this;
++ return newdev.release();
++ }
+ }
+
+ // SAT or USB ?
+@@ -2709,6 +2726,11 @@ smart_device * linux_scsi_device::autode
+ }
+
+ // Nothing special found
++
++ if (sat_only) {
++ close();
++ set_err(EIO, "Not a SAT device");
++ }
+ return this;
+ }
+
+@@ -2891,7 +2913,7 @@ bool linux_smart_interface::get_dev_list
+ if (autodetect)
+ dev = autodetect_smart_device(name);
+ else if (is_scsi)
+- dev = new linux_scsi_device(this, name, req_type);
++ dev = new linux_scsi_device(this, name, req_type, true /*scanning*/);
+ else
+ dev = new linux_ata_device(this, name, req_type);
+ if (dev) // autodetect_smart_device() may return nullptr.
+@@ -2917,7 +2939,8 @@ bool linux_smart_interface::scan_smart_d
+ type = "";
+
+ bool scan_ata = (!*type || !strcmp(type, "ata" ));
+- bool scan_scsi = (!*type || !strcmp(type, "scsi"));
++ // "sat" detection will be later handled in linux_scsi_device::autodetect_open()
++ bool scan_scsi = (!*type || !strcmp(type, "scsi") || !strcmp(type, "sat"));
+ if (!(scan_ata || scan_scsi))
+ return true;
+