smartmontools  SVN Rev 4115
Utility to control and monitor storage systems with "S.M.A.R.T."
os_win32.cpp
Go to the documentation of this file.
1 /*
2  * os_win32.cpp
3  *
4  * Home page of code is: http://smartmontools.sourceforge.net
5  *
6  * Copyright (C) 2004-15 Christian Franke
7  *
8  * Original AACRaid code:
9  * Copyright (C) 2015 Nidhi Malhotra <nidhi.malhotra@pmcs.com>
10  *
11  * Original Areca code:
12  * Copyright (C) 2012 Hank Wu <hank@areca.com.tw>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2, or (at your option)
17  * any later version.
18  *
19  * You should have received a copy of the GNU General Public License
20  * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23 
24 #include "config.h"
25 #define WINVER 0x0502
26 #define _WIN32_WINNT WINVER
27 
28 #include "int64.h"
29 #include "atacmds.h"
30 #include "scsicmds.h"
31 #include "utility.h"
32 #include "smartctl.h" // TODO: Do not use smartctl only variables here
33 
34 #include "dev_interface.h"
35 #include "dev_ata_cmd_set.h"
36 #include "dev_areca.h"
37 
38 #include "os_win32/wmiquery.h"
39 
40 #include <errno.h>
41 
42 #ifdef _DEBUG
43 #include <assert.h>
44 #else
45 #undef assert
46 #define assert(x) /* */
47 #endif
48 
49 #include <stddef.h> // offsetof()
50 #include <io.h> // access()
51 
52 // WIN32_LEAN_AND_MEAN may be required to prevent inclusion of <winioctl.h>
53 #define WIN32_LEAN_AND_MEAN
54 #include <windows.h>
55 
56 #if HAVE_NTDDDISK_H
57 // i686-pc-cygwin, i686-w64-mingw32, x86_64-w64-mingw32
58 // (Missing: FILE_DEVICE_SCSI)
59 #include <devioctl.h>
60 #include <ntdddisk.h>
61 #include <ntddscsi.h>
62 #include <ntddstor.h>
63 #elif HAVE_DDK_NTDDDISK_H
64 // older i686-pc-cygwin, i686-pc-mingw32, i586-mingw32msvc
65 // (Missing: IOCTL_IDE_PASS_THROUGH, IOCTL_ATA_PASS_THROUGH, FILE_DEVICE_SCSI)
66 #include <ddk/ntdddisk.h>
67 #include <ddk/ntddscsi.h>
68 #include <ddk/ntddstor.h>
69 #else
70 // MSVC10, older MinGW
71 // (Missing: IOCTL_SCSI_MINIPORT_*)
72 #include <ntddscsi.h>
73 #include <winioctl.h>
74 #endif
75 
76 #ifndef _WIN32
77 // csmisas.h and aacraid.h require _WIN32 but w32api-headers no longer define it on Cygwin
78 // (aacraid.h also checks for _WIN64 which is also set on Cygwin x64)
79 #define _WIN32
80 #endif
81 
82 // CSMI support
83 #include "csmisas.h"
84 
85 // aacraid support
86 #include "aacraid.h"
87 
88 // Silence -Wunused-local-typedefs warning from g++ >= 4.8
89 #if __GNUC__ >= 4
90 #define ATTR_UNUSED __attribute__((unused))
91 #else
92 #define ATTR_UNUSED /**/
93 #endif
94 
95 // Macro to check constants at compile time using a dummy typedef
96 #define ASSERT_CONST(c, n) \
97  typedef char assert_const_##c[((c) == (n)) ? 1 : -1] ATTR_UNUSED
98 #define ASSERT_SIZEOF(t, n) \
99  typedef char assert_sizeof_##t[(sizeof(t) == (n)) ? 1 : -1] ATTR_UNUSED
100 
101 #ifndef _WIN64
102 #define SELECT_WIN_32_64(x32, x64) (x32)
103 #else
104 #define SELECT_WIN_32_64(x32, x64) (x64)
105 #endif
106 
107 // Cygwin does no longer provide strn?icmp() compatibility macros
108 // MSVCRT does not provide strn?casecmp()
109 #if defined(__CYGWIN__) && !defined(stricmp)
110 #define stricmp strcasecmp
111 #define strnicmp strncasecmp
112 #endif
113 
114 const char * os_win32_cpp_cvsid = "$Id: os_win32.cpp 4098 2015-05-30 16:37:37Z chrfranke $";
115 
116 /////////////////////////////////////////////////////////////////////////////
117 // Windows I/O-controls, some declarations are missing in the include files
118 
119 extern "C" {
120 
121 // SMART_* IOCTLs, also known as DFP_* (Disk Fault Protection)
122 
123 ASSERT_CONST(SMART_GET_VERSION, 0x074080);
124 ASSERT_CONST(SMART_SEND_DRIVE_COMMAND, 0x07c084);
125 ASSERT_CONST(SMART_RCV_DRIVE_DATA, 0x07c088);
126 ASSERT_SIZEOF(GETVERSIONINPARAMS, 24);
127 ASSERT_SIZEOF(SENDCMDINPARAMS, 32+1);
128 ASSERT_SIZEOF(SENDCMDOUTPARAMS, 16+1);
129 
130 
131 // IDE PASS THROUGH (2000, XP, undocumented)
132 
133 #ifndef IOCTL_IDE_PASS_THROUGH
134 
135 #define IOCTL_IDE_PASS_THROUGH \
136  CTL_CODE(IOCTL_SCSI_BASE, 0x040A, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
137 
138 #endif // IOCTL_IDE_PASS_THROUGH
139 
140 #pragma pack(1)
141 
142 typedef struct {
145  UCHAR DataBuffer[1];
147 
148 #pragma pack()
149 
152 
153 
154 // ATA PASS THROUGH (Win2003, XP SP2)
155 
156 #ifndef IOCTL_ATA_PASS_THROUGH
157 
158 #define IOCTL_ATA_PASS_THROUGH \
159  CTL_CODE(IOCTL_SCSI_BASE, 0x040B, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
160 
161 typedef struct _ATA_PASS_THROUGH_EX {
162  USHORT Length;
163  USHORT AtaFlags;
164  UCHAR PathId;
165  UCHAR TargetId;
166  UCHAR Lun;
171  ULONG_PTR DataBufferOffset;
173  UCHAR CurrentTaskFile[8];
175 
176 #define ATA_FLAGS_DRDY_REQUIRED 0x01
177 #define ATA_FLAGS_DATA_IN 0x02
178 #define ATA_FLAGS_DATA_OUT 0x04
179 #define ATA_FLAGS_48BIT_COMMAND 0x08
180 #define ATA_FLAGS_USE_DMA 0x10
181 #define ATA_FLAGS_NO_MULTIPLE 0x20 // Vista
182 
183 #endif // IOCTL_ATA_PASS_THROUGH
184 
187 
188 
189 // IOCTL_SCSI_PASS_THROUGH[_DIRECT]
190 
191 ASSERT_CONST(IOCTL_SCSI_PASS_THROUGH, 0x04d004);
192 ASSERT_CONST(IOCTL_SCSI_PASS_THROUGH_DIRECT, 0x04d014);
193 ASSERT_SIZEOF(SCSI_PASS_THROUGH, SELECT_WIN_32_64(44, 56));
194 ASSERT_SIZEOF(SCSI_PASS_THROUGH_DIRECT, SELECT_WIN_32_64(44, 56));
195 
196 
197 // SMART IOCTL via SCSI MINIPORT ioctl
198 
199 #ifndef FILE_DEVICE_SCSI
200 #define FILE_DEVICE_SCSI 0x001b
201 #endif
202 
203 #ifndef IOCTL_SCSI_MINIPORT_SMART_VERSION
204 
205 #define IOCTL_SCSI_MINIPORT_SMART_VERSION ((FILE_DEVICE_SCSI << 16) + 0x0500)
206 #define IOCTL_SCSI_MINIPORT_IDENTIFY ((FILE_DEVICE_SCSI << 16) + 0x0501)
207 #define IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS ((FILE_DEVICE_SCSI << 16) + 0x0502)
208 #define IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS ((FILE_DEVICE_SCSI << 16) + 0x0503)
209 #define IOCTL_SCSI_MINIPORT_ENABLE_SMART ((FILE_DEVICE_SCSI << 16) + 0x0504)
210 #define IOCTL_SCSI_MINIPORT_DISABLE_SMART ((FILE_DEVICE_SCSI << 16) + 0x0505)
211 #define IOCTL_SCSI_MINIPORT_RETURN_STATUS ((FILE_DEVICE_SCSI << 16) + 0x0506)
212 #define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE ((FILE_DEVICE_SCSI << 16) + 0x0507)
213 #define IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES ((FILE_DEVICE_SCSI << 16) + 0x0508)
214 #define IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS ((FILE_DEVICE_SCSI << 16) + 0x0509)
215 #define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE ((FILE_DEVICE_SCSI << 16) + 0x050a)
216 #define IOCTL_SCSI_MINIPORT_READ_SMART_LOG ((FILE_DEVICE_SCSI << 16) + 0x050b)
217 #define IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG ((FILE_DEVICE_SCSI << 16) + 0x050c)
218 
219 #endif // IOCTL_SCSI_MINIPORT_SMART_VERSION
220 
221 ASSERT_CONST(IOCTL_SCSI_MINIPORT, 0x04d008);
222 ASSERT_SIZEOF(SRB_IO_CONTROL, 28);
223 
224 
225 // IOCTL_STORAGE_QUERY_PROPERTY
226 
227 #ifndef IOCTL_STORAGE_QUERY_PROPERTY
228 
229 #define IOCTL_STORAGE_QUERY_PROPERTY \
230  CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)
231 
233  ULONG Version;
234  ULONG Size;
235  UCHAR DeviceType;
237  BOOLEAN RemovableMedia;
243  STORAGE_BUS_TYPE BusType;
247 
248 typedef enum _STORAGE_QUERY_TYPE {
254 
255 typedef enum _STORAGE_PROPERTY_ID {
264 
265 typedef struct _STORAGE_PROPERTY_QUERY {
270 
271 #endif // IOCTL_STORAGE_QUERY_PROPERTY
272 
276 
277 
278 // IOCTL_STORAGE_PREDICT_FAILURE
279 
280 ASSERT_CONST(IOCTL_STORAGE_PREDICT_FAILURE, 0x002d1100);
281 ASSERT_SIZEOF(STORAGE_PREDICT_FAILURE, 4+512);
282 
283 
284 // 3ware specific versions of SMART ioctl structs
285 
286 #define SMART_VENDOR_3WARE 0x13C1 // identifies 3ware specific parameters
287 
288 #pragma pack(1)
289 
290 typedef struct _GETVERSIONINPARAMS_EX {
291  BYTE bVersion;
292  BYTE bRevision;
293  BYTE bReserved;
296  DWORD dwDeviceMapEx; // 3ware specific: RAID drive bit map
297  WORD wIdentifier; // Vendor specific identifier
298  WORD wControllerId; // 3ware specific: Controller ID (0,1,...)
299  ULONG dwReserved[2];
301 
302 typedef struct _SENDCMDINPARAMS_EX {
303  DWORD cBufferSize;
306  BYTE bPortNumber; // 3ware specific: port number
307  WORD wIdentifier; // Vendor specific identifier
308  DWORD dwReserved[4];
309  BYTE bBuffer[1];
311 
312 #pragma pack()
313 
314 ASSERT_SIZEOF(GETVERSIONINPARAMS_EX, sizeof(GETVERSIONINPARAMS));
315 ASSERT_SIZEOF(SENDCMDINPARAMS_EX, sizeof(SENDCMDINPARAMS));
316 
317 
318 // CSMI structs
319 
320 ASSERT_SIZEOF(IOCTL_HEADER, sizeof(SRB_IO_CONTROL));
324 
325 // aacraid struct
326 
327 ASSERT_SIZEOF(SCSI_REQUEST_BLOCK, SELECT_WIN_32_64(64, 88));
328 
329 } // extern "C"
330 
331 /////////////////////////////////////////////////////////////////////////////
332 
333 namespace os_win32 { // no need to publish anything, name provided for Doxygen
334 
335 #ifdef _MSC_VER
336 #pragma warning(disable:4250)
337 #endif
338 
340 : virtual public /*implements*/ smart_device
341 {
342 public:
345  m_fh(INVALID_HANDLE_VALUE)
346  { }
347 
348  virtual ~win_smart_device() throw();
349 
350  virtual bool is_open() const;
351 
352  virtual bool close();
353 
354 protected:
355  /// Set handle for open() in derived classes.
356  void set_fh(HANDLE fh)
357  { m_fh = fh; }
358 
359  /// Return handle for derived classes.
360  HANDLE get_fh() const
361  { return m_fh; }
362 
363 private:
364  HANDLE m_fh; ///< File handle
365 };
366 
367 
368 /////////////////////////////////////////////////////////////////////////////
369 
371 : public /*implements*/ ata_device,
372  public /*extends*/ win_smart_device
373 {
374 public:
375  win_ata_device(smart_interface * intf, const char * dev_name, const char * req_type);
376 
377  virtual ~win_ata_device() throw();
378 
379  virtual bool open();
380 
381  virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
382 
383  virtual bool ata_identify_is_cached() const;
384 
385 private:
386  bool open(int phydrive, int logdrive, const char * options, int port);
387 
388  std::string m_options;
389  bool m_usr_options; // options set by user?
390  bool m_admin; // open with admin access?
391  int m_phydrive; // PhysicalDriveN or -1
392  bool m_id_is_cached; // ata_identify_is_cached() return value.
393  bool m_is_3ware; // LSI/3ware controller detected?
394  int m_port; // LSI/3ware port
396 };
397 
398 
399 /////////////////////////////////////////////////////////////////////////////
400 
402 : public /*implements*/ scsi_device,
403  virtual public /*extends*/ win_smart_device
404 {
405 public:
406  win_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type);
407 
408  virtual bool open();
409 
410  virtual bool scsi_pass_through(scsi_cmnd_io * iop);
411 
412 private:
413  bool open(int pd_num, int ld_num, int tape_num, int sub_addr);
414 };
415 
416 
417 /////////////////////////////////////////////////////////////////////////////
418 
420 : virtual public /*extends*/ smart_device
421 {
422 public:
423  /// Get bitmask of used ports
424  unsigned get_ports_used();
425 
426 protected:
429  { memset(&m_phy_ent, 0, sizeof(m_phy_ent)); }
430 
431  /// Get phy info
432  bool get_phy_info(CSMI_SAS_PHY_INFO & phy_info);
433 
434  /// Select physical drive
435  bool select_port(int port);
436 
437  /// Get info for selected physical drive
439  { return m_phy_ent; }
440 
441  /// Call platform-specific CSMI ioctl
442  virtual bool csmi_ioctl(unsigned code, IOCTL_HEADER * csmi_buffer,
443  unsigned csmi_bufsiz) = 0;
444 
445 private:
446  CSMI_SAS_PHY_ENTITY m_phy_ent; ///< CSMI info for this phy
447 };
448 
449 
451 : virtual public /*extends*/ csmi_device,
452  virtual public /*implements*/ ata_device
453 {
454 public:
455  virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
456 
457 protected:
460 };
461 
462 
463 //////////////////////////////////////////////////////////////////////
464 
466 : public /*implements*/ csmi_ata_device
467 {
468 public:
469  win_csmi_device(smart_interface * intf, const char * dev_name,
470  const char * req_type);
471 
472  virtual ~win_csmi_device() throw();
473 
474  virtual bool open();
475 
476  virtual bool close();
477 
478  virtual bool is_open() const;
479 
480  bool open_scsi();
481 
482 protected:
483  virtual bool csmi_ioctl(unsigned code, IOCTL_HEADER * csmi_buffer,
484  unsigned csmi_bufsiz);
485 
486 private:
487  HANDLE m_fh; ///< Controller device handle
488  int m_port; ///< Port number
489 };
490 
491 
492 //////////////////////////////////////////////////////////////////////
493 
495 : public /*implements*/ ata_device_with_command_set
496 {
497 public:
498  win_tw_cli_device(smart_interface * intf, const char * dev_name, const char * req_type);
499 
500  virtual bool is_open() const;
501 
502  virtual bool open();
503 
504  virtual bool close();
505 
506 protected:
507  virtual int ata_command_interface(smart_command_set command, int select, char * data);
508 
509 private:
513 };
514 
515 /////////////////////////////////////////////////////////////////////////////
516 //// PMC aacraid Support
517 
519 :public /*implements*/ scsi_device,
520 public /*extends*/ win_smart_device
521 {
522 public:
523  win_aacraid_device(smart_interface *intf, const char *dev_name,unsigned int ctrnum, unsigned int target, unsigned int lun);
524 
525  virtual ~win_aacraid_device() throw();
526 
527  virtual bool open();
528 
529  virtual bool scsi_pass_through(struct scsi_cmnd_io *iop);
530 
531 private:
532  //Device Host number
533  int m_ctrnum;
534 
535  //Channel(Lun) of the device
536  int m_lun;
537 
538  //Id of the device
539  int m_target;
540 };
541 
542 
543 
544 /////////////////////////////////////////////////////////////////////////////
545 /// Areca RAID support
546 
547 ///////////////////////////////////////////////////////////////////
548 // SATA(ATA) device behind Areca RAID Controller
550 : public /*implements*/ areca_ata_device,
551  public /*extends*/ win_smart_device
552 {
553 public:
554  win_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
555  virtual bool open();
556  virtual smart_device * autodetect_open();
557  virtual bool arcmsr_lock();
558  virtual bool arcmsr_unlock();
559  virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop);
560 
561 private:
562  HANDLE m_mutex;
563 };
564 
565 ///////////////////////////////////////////////////////////////////
566 // SAS(SCSI) device behind Areca RAID Controller
568 : public /*implements*/ areca_scsi_device,
569  public /*extends*/ win_smart_device
570 {
571 public:
572  win_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
573  virtual bool open();
574  virtual smart_device * autodetect_open();
575  virtual bool arcmsr_lock();
576  virtual bool arcmsr_unlock();
577  virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop);
578 
579 private:
580  HANDLE m_mutex;
581 };
582 
583 
584 //////////////////////////////////////////////////////////////////////
585 // Platform specific interface
586 
588 : public /*implements part of*/ smart_interface
589 {
590 public:
591  virtual std::string get_os_version_str();
592 
593  virtual std::string get_app_examples(const char * appname);
594 
595 #ifndef __CYGWIN__
596  virtual int64_t get_timer_usec();
597 #endif
598 
599  virtual bool disable_system_auto_standby(bool disable);
600 
601  virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
602  const char * pattern = 0);
603 
604 protected:
605  virtual ata_device * get_ata_device(const char * name, const char * type);
606 
607  virtual scsi_device * get_scsi_device(const char * name, const char * type);
608 
609  virtual smart_device * autodetect_smart_device(const char * name);
610 
611  virtual smart_device * get_custom_smart_device(const char * name, const char * type);
612 
613  virtual std::string get_valid_custom_dev_types_str();
614 };
615 
616 
617 //////////////////////////////////////////////////////////////////////
618 
619 #ifndef _WIN64
620 // Running on 64-bit Windows as 32-bit app ?
621 static bool is_wow64()
622 {
623  BOOL (WINAPI * IsWow64Process_p)(HANDLE, PBOOL) =
624  (BOOL (WINAPI *)(HANDLE, PBOOL))
625  GetProcAddress(GetModuleHandleA("kernel32.dll"), "IsWow64Process");
626  if (!IsWow64Process_p)
627  return false;
628  BOOL w64 = FALSE;
629  if (!IsWow64Process_p(GetCurrentProcess(), &w64))
630  return false;
631  return !!w64;
632 }
633 #endif // _WIN64
634 
635 // Return info string about build host and OS version
637 {
638  char vstr[sizeof(SMARTMONTOOLS_BUILD_HOST)-1+sizeof("-2003r2(64)-sp2.1")+13]
639  = SMARTMONTOOLS_BUILD_HOST;
640  if (vstr[1] < '6')
641  vstr[1] = '6';
642  char * const vptr = vstr+sizeof(SMARTMONTOOLS_BUILD_HOST)-1;
643  const int vlen = sizeof(vstr)-sizeof(SMARTMONTOOLS_BUILD_HOST);
644  assert(vptr == vstr+strlen(vstr) && vptr+vlen+1 == vstr+sizeof(vstr));
645 
646  OSVERSIONINFOEXA vi; memset(&vi, 0, sizeof(vi));
647  vi.dwOSVersionInfoSize = sizeof(vi);
648  if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
649  memset(&vi, 0, sizeof(vi));
650  vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
651  if (!GetVersionExA((OSVERSIONINFOA *)&vi))
652  return vstr;
653  }
654 
655  const char * w = 0;
656  if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
657 
658  if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) {
659  // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the
660  // actual OS version, see:
661  // http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
662 
663  ULONGLONG major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
664  for (unsigned major = vi.dwMajorVersion; major <= 9; major++) {
665  OSVERSIONINFOEXA vi2; memset(&vi2, 0, sizeof(vi2));
666  vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMajorVersion = major;
667  if (!VerifyVersionInfo(&vi2, VER_MAJORVERSION, major_equal))
668  continue;
669  if (vi.dwMajorVersion < major) {
670  vi.dwMajorVersion = major; vi.dwMinorVersion = 0;
671  }
672 
673  ULONGLONG minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
674  for (unsigned minor = vi.dwMinorVersion; minor <= 9; minor++) {
675  memset(&vi2, 0, sizeof(vi2)); vi2.dwOSVersionInfoSize = sizeof(vi2);
676  vi2.dwMinorVersion = minor;
677  if (!VerifyVersionInfo(&vi2, VER_MINORVERSION, minor_equal))
678  continue;
679  vi.dwMinorVersion = minor;
680  break;
681  }
682 
683  break;
684  }
685  }
686 
687  if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) {
688  bool ws = (vi.wProductType <= VER_NT_WORKSTATION);
689  switch (vi.dwMajorVersion << 4 | vi.dwMinorVersion) {
690  case 0x50: w = "2000"; break;
691  case 0x51: w = "xp"; break;
692  case 0x52: w = (!GetSystemMetrics(89/*SM_SERVERR2*/)
693  ? "2003" : "2003r2"); break;
694  case 0x60: w = (ws ? "vista" : "2008" ); break;
695  case 0x61: w = (ws ? "win7" : "2008r2"); break;
696  case 0x62: w = (ws ? "win8" : "2012" ); break;
697  case 0x63: w = (ws ? "win8.1": "2012r2"); break;
698  case 0x64: w = (ws ? "win10" : "w10srv"); break;
699  }
700  }
701  }
702 
703  const char * w64 = "";
704 #ifndef _WIN64
705  if (is_wow64())
706  w64 = "(64)";
707 #endif
708 
709  if (!w)
710  snprintf(vptr, vlen, "-%s%u.%u%s",
711  (vi.dwPlatformId==VER_PLATFORM_WIN32_NT ? "nt" : "??"),
712  (unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, w64);
713  else if (vi.wServicePackMinor)
714  snprintf(vptr, vlen, "-%s%s-sp%u.%u", w, w64, vi.wServicePackMajor, vi.wServicePackMinor);
715  else if (vi.wServicePackMajor)
716  snprintf(vptr, vlen, "-%s%s-sp%u", w, w64, vi.wServicePackMajor);
717  else
718  snprintf(vptr, vlen, "-%s%s", w, w64);
719  return vstr;
720 }
721 
722 #ifndef __CYGWIN__
723 // MSVCRT only provides ftime() which uses GetSystemTime()
724 // This provides only ~15ms resolution by default.
725 // Use QueryPerformanceCounter instead (~300ns).
726 // (Cygwin provides CLOCK_MONOTONIC which has the same effect)
728 {
729  static int64_t freq = 0;
730 
731  LARGE_INTEGER t;
732  if (freq == 0)
733  freq = (QueryPerformanceFrequency(&t) ? t.QuadPart : -1);
734  if (freq <= 0)
736 
737  if (!QueryPerformanceCounter(&t))
738  return -1;
739  if (!(0 <= t.QuadPart && t.QuadPart <= (int64_t)(~(uint64_t)0 >> 1)/1000000))
740  return -1;
741 
742  return (t.QuadPart * 1000000LL) / freq;
743 }
744 #endif // __CYGWIN__
745 
746 
747 // Return value for device detection functions
749 
750 static win_dev_type get_phy_drive_type(int drive);
751 static win_dev_type get_phy_drive_type(int drive, GETVERSIONINPARAMS_EX * ata_version_ex);
752 static win_dev_type get_log_drive_type(int drive);
753 static bool get_usb_id(int drive, unsigned short & vendor_id,
754  unsigned short & product_id);
755 
756 static const char * ata_get_def_options(void);
757 
758 
759 static int is_permissive()
760 {
761  if (!failuretest_permissive) {
762  pout("To continue, add one or more '-T permissive' options.\n");
763  return 0;
764  }
766  return 1;
767 }
768 
769 // return number for drive letter, -1 on error
770 // "[A-Za-z]:([/\\][.]?)?" => 0-25
771 // Accepts trailing '"' to fix broken "X:\" parameter passing from .bat files
772 static int drive_letter(const char * s)
773 {
774  return ( (('A' <= s[0] && s[0] <= 'Z') || ('a' <= s[0] && s[0] <= 'z'))
775  && s[1] == ':'
776  && (!s[2] || ( strchr("/\\\"", s[2])
777  && (!s[3] || (s[3] == '.' && !s[4]))) ) ?
778  (s[0] & 0x1f) - 1 : -1);
779 }
780 
781 // Skip trailing "/dev/", do not allow "/dev/X:"
782 static const char * skipdev(const char * s)
783 {
784  return (!strncmp(s, "/dev/", 5) && drive_letter(s+5) < 0 ? s+5 : s);
785 }
786 
787 ata_device * win_smart_interface::get_ata_device(const char * name, const char * type)
788 {
789  const char * testname = skipdev(name);
790  if (!strncmp(testname, "csmi", 4))
791  return new win_csmi_device(this, name, type);
792  if (!strncmp(testname, "tw_cli", 6))
793  return new win_tw_cli_device(this, name, type);
794  return new win_ata_device(this, name, type);
795 }
796 
797 scsi_device * win_smart_interface::get_scsi_device(const char * name, const char * type)
798 {
799  return new win_scsi_device(this, name, type);
800 }
801 
802 static int sdxy_to_phydrive(const char (& xy)[2+1])
803 {
804  int phydrive = xy[0] - 'a';
805  if (xy[1])
806  phydrive = (phydrive + 1) * ('z' - 'a' + 1) + (xy[1] - 'a');
807  return phydrive;
808 }
809 
810 static win_dev_type get_dev_type(const char * name, int & phydrive)
811 {
812  phydrive = -1;
813  name = skipdev(name);
814  if (!strncmp(name, "st", 2))
815  return DEV_SCSI;
816  if (!strncmp(name, "nst", 3))
817  return DEV_SCSI;
818  if (!strncmp(name, "tape", 4))
819  return DEV_SCSI;
820 
821  int logdrive = drive_letter(name);
822  if (logdrive >= 0) {
823  win_dev_type type = get_log_drive_type(logdrive);
824  return (type != DEV_UNKNOWN ? type : DEV_SCSI);
825  }
826 
827  char drive[2+1] = "";
828  if (sscanf(name, "sd%2[a-z]", drive) == 1) {
829  phydrive = sdxy_to_phydrive(drive);
830  return get_phy_drive_type(phydrive);
831  }
832 
833  phydrive = -1;
834  if (sscanf(name, "pd%d", &phydrive) == 1 && phydrive >= 0)
835  return get_phy_drive_type(phydrive);
836  return DEV_UNKNOWN;
837 }
838 
839 smart_device * win_smart_interface::get_custom_smart_device(const char * name, const char * type)
840 {
841  // Areca?
842  int disknum = -1, n1 = -1, n2 = -1;
843  int encnum = 1;
844  char devpath[32];
845 
846  if (sscanf(type, "areca,%n%d/%d%n", &n1, &disknum, &encnum, &n2) >= 1 || n1 == 6) {
847  if (!(1 <= disknum && disknum <= 128)) {
848  set_err(EINVAL, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum);
849  return 0;
850  }
851  if (!(1 <= encnum && encnum <= 8)) {
852  set_err(EINVAL, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum);
853  return 0;
854  }
855 
856  name = skipdev(name);
857 #define ARECA_MAX_CTLR_NUM 16
858  n1 = -1;
859  int ctlrindex = 0;
860  if (sscanf(name, "arcmsr%d%n", &ctlrindex, &n1) >= 1 && n1 == (int)strlen(name)) {
861  /*
862  1. scan from "\\\\.\\scsi[0]:" up to "\\\\.\\scsi[ARECA_MAX_CTLR_NUM]:" and
863  2. map arcmsrX into "\\\\.\\scsiX"
864  */
865  for (int idx = 0; idx < ARECA_MAX_CTLR_NUM; idx++) {
866  memset(devpath, 0, sizeof(devpath));
867  snprintf(devpath, sizeof(devpath), "\\\\.\\scsi%d:", idx);
868  win_areca_ata_device *arcdev = new win_areca_ata_device(this, devpath, disknum, encnum);
869  if(arcdev->arcmsr_probe()) {
870  if(ctlrindex-- == 0) {
871  return arcdev;
872  }
873  }
874  delete arcdev;
875  }
876  set_err(ENOENT, "No Areca controller found");
877  }
878  else
879  set_err(EINVAL, "Option -d areca,N/E requires device name /dev/arcmsrX");
880  return 0;
881  }
882 
883  // aacraid?
884  unsigned ctrnum, lun, target;
885  n1 = -1;
886 
887  if ( sscanf(type, "aacraid,%u,%u,%u%n", &ctrnum, &lun, &target, &n1) >= 3
888  && n1 == (int)strlen(type)) {
889 #define aacraid_MAX_CTLR_NUM 16
890  if (ctrnum >= aacraid_MAX_CTLR_NUM) {
891  set_err(EINVAL, "aacraid: invalid host number %u", ctrnum);
892  return 0;
893  }
894 
895  /*
896  1. scan from "\\\\.\\scsi[0]:" up to "\\\\.\\scsi[AACRAID_MAX_CTLR_NUM]:" and
897  2. map ARCX into "\\\\.\\scsiX"
898  */
899  memset(devpath, 0, sizeof(devpath));
900  unsigned ctlrindex = 0;
901  for (int portNum = 0; portNum < aacraid_MAX_CTLR_NUM; portNum++){
902  char subKey[63];
903  snprintf(subKey, sizeof(subKey), "HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port %d", portNum);
904  HKEY hScsiKey = 0;
905  long regStatus = RegOpenKeyExA(HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hScsiKey);
906  if (regStatus == ERROR_SUCCESS){
907  char driverName[20];
908  DWORD driverNameSize = sizeof(driverName);
909  DWORD regType = 0;
910  regStatus = RegQueryValueExA(hScsiKey, "Driver", NULL, &regType, (LPBYTE) driverName, &driverNameSize);
911  if (regStatus == ERROR_SUCCESS){
912  if (regType == REG_SZ){
913  if (stricmp(driverName, "arcsas") == 0){
914  if(ctrnum == ctlrindex){
915  snprintf(devpath, sizeof(devpath), "\\\\.\\Scsi%d:", portNum);
916  return get_sat_device("sat,auto",
917  new win_aacraid_device(this, devpath, ctrnum, target, lun));
918  }
919  ctlrindex++;
920  }
921  }
922  }
923  RegCloseKey(hScsiKey);
924  }
925  }
926 
927  set_err(EINVAL, "aacraid: host %u not found", ctrnum);
928  return 0;
929  }
930 
931  return 0;
932 }
933 
935 {
936  return "aacraid,H,L,ID, areca,N[/E]";
937 }
938 
939 
941 {
942  const char * testname = skipdev(name);
943  if (str_starts_with(testname, "hd"))
944  return new win_ata_device(this, name, "");
945 
946  if (str_starts_with(testname, "tw_cli"))
947  return new win_tw_cli_device(this, name, "");
948 
949  if (str_starts_with(testname, "csmi"))
950  return new win_csmi_device(this, name, "");
951 
952  int phydrive = -1;
953  win_dev_type type = get_dev_type(name, phydrive);
954 
955  if (type == DEV_ATA)
956  return new win_ata_device(this, name, "");
957 
958  if (type == DEV_SCSI)
959  return new win_scsi_device(this, name, "");
960 
961  if (type == DEV_SAT)
962  return get_sat_device("sat", new win_scsi_device(this, name, ""));
963 
964  if (type == DEV_USB) {
965  // Get USB bridge ID
966  unsigned short vendor_id = 0, product_id = 0;
967  if (!(phydrive >= 0 && get_usb_id(phydrive, vendor_id, product_id))) {
968  set_err(EINVAL, "Unable to read USB device ID");
969  return 0;
970  }
971  // Get type name for this ID
972  const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id);
973  if (!usbtype)
974  return 0;
975  // Return SAT/USB device for this type
976  return get_sat_device(usbtype, new win_scsi_device(this, name, ""));
977  }
978 
979  return 0;
980 }
981 
982 
983 // Scan for devices
984 
986  const char * type, const char * pattern /* = 0*/)
987 {
988  if (pattern) {
989  set_err(EINVAL, "DEVICESCAN with pattern not implemented yet");
990  return false;
991  }
992 
993  // Check for "[*,]pd" type
994  bool pd = false;
995  char type2[16+1] = "";
996  if (type) {
997  int nc = -1;
998  if (!strcmp(type, "pd")) {
999  pd = true;
1000  type = 0;
1001  }
1002  else if (sscanf(type, "%16[^,],pd%n", type2, &nc) == 1 &&
1003  nc == (int)strlen(type)) {
1004  pd = true;
1005  type = type2;
1006  }
1007  }
1008 
1009  // Set valid types
1010  bool ata, scsi, sat, usb, csmi;
1011  if (!type) {
1012  ata = scsi = usb = sat = csmi = true;
1013  }
1014  else {
1015  ata = scsi = usb = sat = csmi = false;
1016  if (!strcmp(type, "ata"))
1017  ata = true;
1018  else if (!strcmp(type, "scsi"))
1019  scsi = true;
1020  else if (!strcmp(type, "sat"))
1021  sat = true;
1022  else if (!strcmp(type, "usb"))
1023  usb = true;
1024  else if (!strcmp(type, "csmi"))
1025  csmi = true;
1026  else {
1027  set_err(EINVAL,
1028  "Invalid type '%s', valid arguments are: ata[,pd], scsi[,pd], sat[,pd], usb[,pd], csmi, pd",
1029  type);
1030  return false;
1031  }
1032  }
1033 
1034  char name[20];
1035 
1036  if (ata || scsi || sat || usb) {
1037  // Scan up to 128 drives and 2 3ware controllers
1038  const int max_raid = 2;
1039  bool raid_seen[max_raid] = {false, false};
1040 
1041  for (int i = 0; i < 128; i++) {
1042  if (pd)
1043  snprintf(name, sizeof(name), "/dev/pd%d", i);
1044  else if (i + 'a' <= 'z')
1045  snprintf(name, sizeof(name), "/dev/sd%c", i + 'a');
1046  else
1047  snprintf(name, sizeof(name), "/dev/sd%c%c",
1048  i / ('z'-'a'+1) - 1 + 'a',
1049  i % ('z'-'a'+1) + 'a');
1050 
1051  GETVERSIONINPARAMS_EX vers_ex;
1052 
1053  switch (get_phy_drive_type(i, (ata ? &vers_ex : 0))) {
1054  case DEV_ATA:
1055  // Driver supports SMART_GET_VERSION or STORAGE_QUERY_PROPERTY returned ATA/SATA
1056  if (!ata)
1057  continue;
1058 
1059  // Interpret RAID drive map if present
1060  if (vers_ex.wIdentifier == SMART_VENDOR_3WARE) {
1061  // Skip if too many controllers or logical drive from this controller already seen
1062  if (!(vers_ex.wControllerId < max_raid && !raid_seen[vers_ex.wControllerId]))
1063  continue;
1064  raid_seen[vers_ex.wControllerId] = true;
1065  // Add physical drives
1066  int len = strlen(name);
1067  for (int pi = 0; pi < 32; pi++) {
1068  if (vers_ex.dwDeviceMapEx & (1L << pi)) {
1069  snprintf(name+len, sizeof(name)-1-len, ",%u", pi);
1070  devlist.push_back( new win_ata_device(this, name, "ata") );
1071  }
1072  }
1073  }
1074  else {
1075  devlist.push_back( new win_ata_device(this, name, "ata") );
1076  }
1077  break;
1078 
1079  case DEV_SCSI:
1080  // STORAGE_QUERY_PROPERTY returned SCSI/SAS/...
1081  if (!scsi)
1082  continue;
1083  devlist.push_back( new win_scsi_device(this, name, "scsi") );
1084  break;
1085 
1086  case DEV_SAT:
1087  // STORAGE_QUERY_PROPERTY returned VendorId "ATA "
1088  if (!sat)
1089  continue;
1090  devlist.push_back( get_sat_device("sat", new win_scsi_device(this, name, "")) );
1091  break;
1092 
1093  case DEV_USB:
1094  // STORAGE_QUERY_PROPERTY returned USB
1095  if (!usb)
1096  continue;
1097  {
1098  // TODO: Use common function for this and autodetect_smart_device()
1099  // Get USB bridge ID
1100  unsigned short vendor_id = 0, product_id = 0;
1101  if (!get_usb_id(i, vendor_id, product_id))
1102  continue;
1103  // Get type name for this ID
1104  const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id);
1105  if (!usbtype)
1106  continue;
1107  // Return SAT/USB device for this type
1108  ata_device * dev = get_sat_device(usbtype, new win_scsi_device(this, name, ""));
1109  if (!dev)
1110  continue;
1111  devlist.push_back(dev);
1112  }
1113  break;
1114 
1115  default:
1116  // Unknown type
1117  break;
1118  }
1119  }
1120  }
1121 
1122  if (csmi) {
1123  // Scan CSMI devices
1124  for (int i = 0; i <= 9; i++) {
1125  snprintf(name, sizeof(name)-1, "/dev/csmi%d,0", i);
1126  win_csmi_device test_dev(this, name, "");
1127  if (!test_dev.open_scsi())
1128  continue;
1129 
1130  unsigned ports_used = test_dev.get_ports_used();
1131  if (!ports_used)
1132  continue;
1133 
1134  for (int pi = 0; pi < 32; pi++) {
1135  if (!(ports_used & (1 << pi)))
1136  continue;
1137  snprintf(name, sizeof(name)-1, "/dev/csmi%d,%d", i, pi);
1138  devlist.push_back( new win_csmi_device(this, name, "ata") );
1139  }
1140  }
1141  }
1142  return true;
1143 }
1144 
1145 
1146 // get examples for smartctl
1147 std::string win_smart_interface::get_app_examples(const char * appname)
1148 {
1149  if (strcmp(appname, "smartctl"))
1150  return "";
1151  return "=================================================== SMARTCTL EXAMPLES =====\n\n"
1152  " smartctl -a /dev/sda (Prints all SMART information)\n\n"
1153  " smartctl --smart=on --offlineauto=on --saveauto=on /dev/sda\n"
1154  " (Enables SMART on first disk)\n\n"
1155  " smartctl -t long /dev/sda (Executes extended disk self-test)\n\n"
1156  " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/sda\n"
1157  " (Prints Self-Test & Attribute errors)\n"
1158  " smartctl -a /dev/sda\n"
1159  " (Prints all information for disk on PhysicalDrive 0)\n"
1160  " smartctl -a /dev/pd3\n"
1161  " (Prints all information for disk on PhysicalDrive 3)\n"
1162  " smartctl -a /dev/tape1\n"
1163  " (Prints all information for SCSI tape on Tape 1)\n"
1164  " smartctl -A /dev/hdb,3\n"
1165  " (Prints Attributes for physical drive 3 on 3ware 9000 RAID)\n"
1166  " smartctl -A /dev/tw_cli/c0/p1\n"
1167  " (Prints Attributes for 3ware controller 0, port 1 using tw_cli)\n"
1168  " smartctl --all --device=areca,3/1 /dev/arcmsr0\n"
1169  " (Prints all SMART info for 3rd ATA disk of the 1st enclosure\n"
1170  " on 1st Areca RAID controller)\n"
1171  "\n"
1172  " ATA SMART access methods and ordering may be specified by modifiers\n"
1173  " following the device name: /dev/hdX:[saicm], where\n"
1174  " 's': SMART_* IOCTLs, 'a': IOCTL_ATA_PASS_THROUGH,\n"
1175  " 'i': IOCTL_IDE_PASS_THROUGH, 'f': IOCTL_STORAGE_*,\n"
1176  " 'm': IOCTL_SCSI_MINIPORT_*.\n"
1177  + strprintf(
1178  " The default on this system is /dev/sdX:%s\n", ata_get_def_options()
1179  );
1180 }
1181 
1182 
1184 {
1185  if (disable) {
1186  SYSTEM_POWER_STATUS ps;
1187  if (!GetSystemPowerStatus(&ps))
1188  return set_err(ENOSYS, "Unknown power status");
1189  if (ps.ACLineStatus != 1) {
1190  SetThreadExecutionState(ES_CONTINUOUS);
1191  if (ps.ACLineStatus == 0)
1192  set_err(EIO, "AC offline");
1193  else
1194  set_err(EIO, "Unknown AC line status");
1195  return false;
1196  }
1197  }
1198 
1199  if (!SetThreadExecutionState(ES_CONTINUOUS | (disable ? ES_SYSTEM_REQUIRED : 0)))
1200  return set_err(ENOSYS);
1201  return true;
1202 }
1203 
1204 
1205 /////////////////////////////////////////////////////////////////////////////
1206 // ATA Interface
1207 /////////////////////////////////////////////////////////////////////////////
1208 
1209 #define SMART_CYL_LOW 0x4F
1210 #define SMART_CYL_HI 0xC2
1211 
1212 static void print_ide_regs(const IDEREGS * r, int out)
1213 {
1214  pout("%s=0x%02x,%s=0x%02x, SC=0x%02x, SN=0x%02x, CL=0x%02x, CH=0x%02x, SEL=0x%02x\n",
1215  (out?"STS":"CMD"), r->bCommandReg, (out?"ERR":" FR"), r->bFeaturesReg,
1217 }
1218 
1219 static void print_ide_regs_io(const IDEREGS * ri, const IDEREGS * ro)
1220 {
1221  pout(" Input : "); print_ide_regs(ri, 0);
1222  if (ro) {
1223  pout(" Output: "); print_ide_regs(ro, 1);
1224  }
1225 }
1226 
1227 /////////////////////////////////////////////////////////////////////////////
1228 
1229 // call SMART_GET_VERSION, return device map or -1 on error
1230 
1231 static int smart_get_version(HANDLE hdevice, GETVERSIONINPARAMS_EX * ata_version_ex = 0)
1232 {
1233  GETVERSIONINPARAMS vers; memset(&vers, 0, sizeof(vers));
1234  const GETVERSIONINPARAMS_EX & vers_ex = (const GETVERSIONINPARAMS_EX &)vers;
1235  DWORD num_out;
1236 
1237  if (!DeviceIoControl(hdevice, SMART_GET_VERSION,
1238  NULL, 0, &vers, sizeof(vers), &num_out, NULL)) {
1239  if (ata_debugmode)
1240  pout(" SMART_GET_VERSION failed, Error=%u\n", (unsigned)GetLastError());
1241  errno = ENOSYS;
1242  return -1;
1243  }
1244  assert(num_out == sizeof(GETVERSIONINPARAMS));
1245 
1246  if (ata_debugmode > 1) {
1247  pout(" SMART_GET_VERSION suceeded, bytes returned: %u\n"
1248  " Vers = %d.%d, Caps = 0x%x, DeviceMap = 0x%02x\n",
1249  (unsigned)num_out, vers.bVersion, vers.bRevision,
1250  (unsigned)vers.fCapabilities, vers.bIDEDeviceMap);
1251  if (vers_ex.wIdentifier == SMART_VENDOR_3WARE)
1252  pout(" Identifier = %04x(3WARE), ControllerId=%u, DeviceMapEx = 0x%08x\n",
1253  vers_ex.wIdentifier, vers_ex.wControllerId, (unsigned)vers_ex.dwDeviceMapEx);
1254  }
1255 
1256  if (ata_version_ex)
1257  *ata_version_ex = vers_ex;
1258 
1259  // TODO: Check vers.fCapabilities here?
1260  return vers.bIDEDeviceMap;
1261 }
1262 
1263 
1264 // call SMART_* ioctl
1265 
1266 static int smart_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, unsigned datasize, int port)
1267 {
1268  SENDCMDINPARAMS inpar;
1269  SENDCMDINPARAMS_EX & inpar_ex = (SENDCMDINPARAMS_EX &)inpar;
1270 
1271  unsigned char outbuf[sizeof(SENDCMDOUTPARAMS)-1 + 512];
1272  const SENDCMDOUTPARAMS * outpar;
1273  DWORD code, num_out;
1274  unsigned int size_out;
1275  const char * name;
1276 
1277  memset(&inpar, 0, sizeof(inpar));
1278  inpar.irDriveRegs = *regs;
1279 
1280  // Older drivers may require bits 5 and 7 set
1281  // ATA-3: bits shall be set, ATA-4 and later: bits are obsolete
1282  inpar.irDriveRegs.bDriveHeadReg |= 0xa0;
1283 
1284  // Drive number 0-3 was required on Win9x/ME only
1285  //inpar.irDriveRegs.bDriveHeadReg |= (drive & 1) << 4;
1286  //inpar.bDriveNumber = drive;
1287 
1288  if (port >= 0) {
1289  // Set RAID port
1290  inpar_ex.wIdentifier = SMART_VENDOR_3WARE;
1291  inpar_ex.bPortNumber = port;
1292  }
1293 
1294  if (datasize == 512) {
1295  code = SMART_RCV_DRIVE_DATA; name = "SMART_RCV_DRIVE_DATA";
1296  inpar.cBufferSize = size_out = 512;
1297  }
1298  else if (datasize == 0) {
1299  code = SMART_SEND_DRIVE_COMMAND; name = "SMART_SEND_DRIVE_COMMAND";
1300  if (regs->bFeaturesReg == ATA_SMART_STATUS)
1301  size_out = sizeof(IDEREGS); // ioctl returns new IDEREGS as data
1302  // Note: cBufferSize must be 0 on Win9x
1303  else
1304  size_out = 0;
1305  }
1306  else {
1307  errno = EINVAL;
1308  return -1;
1309  }
1310 
1311  memset(&outbuf, 0, sizeof(outbuf));
1312 
1313  if (!DeviceIoControl(hdevice, code, &inpar, sizeof(SENDCMDINPARAMS)-1,
1314  outbuf, sizeof(SENDCMDOUTPARAMS)-1 + size_out, &num_out, NULL)) {
1315  // CAUTION: DO NOT change "regs" Parameter in this case, see win_ata_device::ata_pass_through()
1316  long err = GetLastError();
1317  if (ata_debugmode && (err != ERROR_INVALID_PARAMETER || ata_debugmode > 1)) {
1318  pout(" %s failed, Error=%ld\n", name, err);
1319  print_ide_regs_io(regs, NULL);
1320  }
1321  errno = ( err == ERROR_INVALID_FUNCTION/*9x*/
1322  || err == ERROR_INVALID_PARAMETER/*NT/2K/XP*/
1323  || err == ERROR_NOT_SUPPORTED ? ENOSYS : EIO);
1324  return -1;
1325  }
1326  // NOTE: On Win9x, inpar.irDriveRegs now contains the returned regs
1327 
1328  outpar = (const SENDCMDOUTPARAMS *)outbuf;
1329 
1330  if (outpar->DriverStatus.bDriverError) {
1331  if (ata_debugmode) {
1332  pout(" %s failed, DriverError=0x%02x, IDEError=0x%02x\n", name,
1333  outpar->DriverStatus.bDriverError, outpar->DriverStatus.bIDEError);
1334  print_ide_regs_io(regs, NULL);
1335  }
1336  errno = (!outpar->DriverStatus.bIDEError ? ENOSYS : EIO);
1337  return -1;
1338  }
1339 
1340  if (ata_debugmode > 1) {
1341  pout(" %s suceeded, bytes returned: %u (buffer %u)\n", name,
1342  (unsigned)num_out, (unsigned)outpar->cBufferSize);
1344  (const IDEREGS *)(outpar->bBuffer) : NULL));
1345  }
1346 
1347  if (datasize)
1348  memcpy(data, outpar->bBuffer, 512);
1349  else if (regs->bFeaturesReg == ATA_SMART_STATUS) {
1350  if (nonempty(outpar->bBuffer, sizeof(IDEREGS)))
1351  memcpy(regs, outpar->bBuffer, sizeof(IDEREGS));
1352  else { // Workaround for driver not returning regs
1353  if (ata_debugmode)
1354  pout(" WARNING: driver does not return ATA registers in output buffer!\n");
1355  *regs = inpar.irDriveRegs;
1356  }
1357  }
1358 
1359  return 0;
1360 }
1361 
1362 
1363 /////////////////////////////////////////////////////////////////////////////
1364 // IDE PASS THROUGH (2000, XP, undocumented)
1365 //
1366 // Based on WinATA.cpp, 2002 c't/Matthias Withopf
1367 // ftp://ftp.heise.de/pub/ct/listings/0207-218.zip
1368 
1369 static int ide_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, unsigned datasize)
1370 {
1371  if (datasize > 512) {
1372  errno = EINVAL;
1373  return -1;
1374  }
1375  unsigned int size = sizeof(ATA_PASS_THROUGH)-1 + datasize;
1376  ATA_PASS_THROUGH * buf = (ATA_PASS_THROUGH *)VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
1377  DWORD num_out;
1378  const unsigned char magic = 0xcf;
1379 
1380  if (!buf) {
1381  errno = ENOMEM;
1382  return -1;
1383  }
1384 
1385  buf->IdeReg = *regs;
1386  buf->DataBufferSize = datasize;
1387  if (datasize)
1388  buf->DataBuffer[0] = magic;
1389 
1390  if (!DeviceIoControl(hdevice, IOCTL_IDE_PASS_THROUGH,
1391  buf, size, buf, size, &num_out, NULL)) {
1392  long err = GetLastError();
1393  if (ata_debugmode) {
1394  pout(" IOCTL_IDE_PASS_THROUGH failed, Error=%ld\n", err);
1395  print_ide_regs_io(regs, NULL);
1396  }
1397  VirtualFree(buf, 0, MEM_RELEASE);
1398  errno = (err == ERROR_INVALID_FUNCTION || err == ERROR_NOT_SUPPORTED ? ENOSYS : EIO);
1399  return -1;
1400  }
1401 
1402  // Check ATA status
1403  if (buf->IdeReg.bCommandReg/*Status*/ & 0x01) {
1404  if (ata_debugmode) {
1405  pout(" IOCTL_IDE_PASS_THROUGH command failed:\n");
1406  print_ide_regs_io(regs, &buf->IdeReg);
1407  }
1408  VirtualFree(buf, 0, MEM_RELEASE);
1409  errno = EIO;
1410  return -1;
1411  }
1412 
1413  // Check and copy data
1414  if (datasize) {
1415  if ( num_out != size
1416  || (buf->DataBuffer[0] == magic && !nonempty(buf->DataBuffer+1, datasize-1))) {
1417  if (ata_debugmode) {
1418  pout(" IOCTL_IDE_PASS_THROUGH output data missing (%u, %u)\n",
1419  (unsigned)num_out, (unsigned)buf->DataBufferSize);
1420  print_ide_regs_io(regs, &buf->IdeReg);
1421  }
1422  VirtualFree(buf, 0, MEM_RELEASE);
1423  errno = EIO;
1424  return -1;
1425  }
1426  memcpy(data, buf->DataBuffer, datasize);
1427  }
1428 
1429  if (ata_debugmode > 1) {
1430  pout(" IOCTL_IDE_PASS_THROUGH suceeded, bytes returned: %u (buffer %u)\n",
1431  (unsigned)num_out, (unsigned)buf->DataBufferSize);
1432  print_ide_regs_io(regs, &buf->IdeReg);
1433  }
1434  *regs = buf->IdeReg;
1435 
1436  // Caution: VirtualFree() fails if parameter "dwSize" is nonzero
1437  VirtualFree(buf, 0, MEM_RELEASE);
1438  return 0;
1439 }
1440 
1441 
1442 /////////////////////////////////////////////////////////////////////////////
1443 // ATA PASS THROUGH (Win2003, XP SP2)
1444 
1445 // Warning:
1446 // IOCTL_ATA_PASS_THROUGH[_DIRECT] can only handle one interrupt/DRQ data
1447 // transfer per command. Therefore, multi-sector transfers are only supported
1448 // for the READ/WRITE MULTIPLE [EXT] commands. Other commands like READ/WRITE SECTORS
1449 // or READ/WRITE LOG EXT work only with single sector transfers.
1450 // The latter are supported on Vista (only) through new ATA_FLAGS_NO_MULTIPLE.
1451 // See:
1452 // http://social.msdn.microsoft.com/Forums/en-US/storageplatformata/thread/eb408507-f221-455b-9bbb-d1069b29c4da
1453 
1454 static int ata_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, IDEREGS * prev_regs, char * data, int datasize)
1455 {
1456  const int max_sectors = 32; // TODO: Allocate dynamic buffer
1457 
1458  typedef struct {
1459  ATA_PASS_THROUGH_EX apt;
1460  ULONG Filler;
1461  UCHAR ucDataBuf[max_sectors * 512];
1462  } ATA_PASS_THROUGH_EX_WITH_BUFFERS;
1463 
1464  const unsigned char magic = 0xcf;
1465 
1466  ATA_PASS_THROUGH_EX_WITH_BUFFERS ab; memset(&ab, 0, sizeof(ab));
1467  ab.apt.Length = sizeof(ATA_PASS_THROUGH_EX);
1468  //ab.apt.PathId = 0;
1469  //ab.apt.TargetId = 0;
1470  //ab.apt.Lun = 0;
1471  ab.apt.TimeOutValue = 10;
1472  unsigned size = offsetof(ATA_PASS_THROUGH_EX_WITH_BUFFERS, ucDataBuf);
1473  ab.apt.DataBufferOffset = size;
1474 
1475  if (datasize > 0) {
1476  if (datasize > (int)sizeof(ab.ucDataBuf)) {
1477  errno = EINVAL;
1478  return -1;
1479  }
1480  ab.apt.AtaFlags = ATA_FLAGS_DATA_IN;
1481  ab.apt.DataTransferLength = datasize;
1482  size += datasize;
1483  ab.ucDataBuf[0] = magic;
1484  }
1485  else if (datasize < 0) {
1486  if (-datasize > (int)sizeof(ab.ucDataBuf)) {
1487  errno = EINVAL;
1488  return -1;
1489  }
1490  ab.apt.AtaFlags = ATA_FLAGS_DATA_OUT;
1491  ab.apt.DataTransferLength = -datasize;
1492  size += -datasize;
1493  memcpy(ab.ucDataBuf, data, -datasize);
1494  }
1495  else {
1496  assert(ab.apt.AtaFlags == 0);
1497  assert(ab.apt.DataTransferLength == 0);
1498  }
1499 
1500  assert(sizeof(ab.apt.CurrentTaskFile) == sizeof(IDEREGS));
1501  IDEREGS * ctfregs = (IDEREGS *)ab.apt.CurrentTaskFile;
1502  IDEREGS * ptfregs = (IDEREGS *)ab.apt.PreviousTaskFile;
1503  *ctfregs = *regs;
1504 
1505  if (prev_regs) {
1506  *ptfregs = *prev_regs;
1507  ab.apt.AtaFlags |= ATA_FLAGS_48BIT_COMMAND;
1508  }
1509 
1510  DWORD num_out;
1511  if (!DeviceIoControl(hdevice, IOCTL_ATA_PASS_THROUGH,
1512  &ab, size, &ab, size, &num_out, NULL)) {
1513  long err = GetLastError();
1514  if (ata_debugmode) {
1515  pout(" IOCTL_ATA_PASS_THROUGH failed, Error=%ld\n", err);
1516  print_ide_regs_io(regs, NULL);
1517  }
1518  errno = (err == ERROR_INVALID_FUNCTION || err == ERROR_NOT_SUPPORTED ? ENOSYS : EIO);
1519  return -1;
1520  }
1521 
1522  // Check ATA status
1523  if (ctfregs->bCommandReg/*Status*/ & (0x01/*Err*/|0x08/*DRQ*/)) {
1524  if (ata_debugmode) {
1525  pout(" IOCTL_ATA_PASS_THROUGH command failed:\n");
1526  print_ide_regs_io(regs, ctfregs);
1527  }
1528  errno = EIO;
1529  return -1;
1530  }
1531 
1532  // Check and copy data
1533  if (datasize > 0) {
1534  if ( num_out != size
1535  || (ab.ucDataBuf[0] == magic && !nonempty(ab.ucDataBuf+1, datasize-1))) {
1536  if (ata_debugmode) {
1537  pout(" IOCTL_ATA_PASS_THROUGH output data missing (%u)\n", (unsigned)num_out);
1538  print_ide_regs_io(regs, ctfregs);
1539  }
1540  errno = EIO;
1541  return -1;
1542  }
1543  memcpy(data, ab.ucDataBuf, datasize);
1544  }
1545 
1546  if (ata_debugmode > 1) {
1547  pout(" IOCTL_ATA_PASS_THROUGH suceeded, bytes returned: %u\n", (unsigned)num_out);
1548  print_ide_regs_io(regs, ctfregs);
1549  }
1550  *regs = *ctfregs;
1551  if (prev_regs)
1552  *prev_regs = *ptfregs;
1553 
1554  return 0;
1555 }
1556 
1557 
1558 /////////////////////////////////////////////////////////////////////////////
1559 // SMART IOCTL via SCSI MINIPORT ioctl
1560 
1561 // This function is handled by ATAPI port driver (atapi.sys) or by SCSI
1562 // miniport driver (via SCSI port driver scsiport.sys).
1563 // It can be used to skip the missing or broken handling of some SMART
1564 // command codes (e.g. READ_LOG) in the disk class driver (disk.sys)
1565 
1566 static int ata_via_scsi_miniport_smart_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, int datasize)
1567 {
1568  // Select code
1569  DWORD code = 0; const char * name = 0;
1570  if (regs->bCommandReg == ATA_IDENTIFY_DEVICE) {
1571  code = IOCTL_SCSI_MINIPORT_IDENTIFY; name = "IDENTIFY";
1572  }
1573  else if (regs->bCommandReg == ATA_SMART_CMD) switch (regs->bFeaturesReg) {
1574  case ATA_SMART_READ_VALUES:
1575  code = IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS; name = "READ_SMART_ATTRIBS"; break;
1577  code = IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS; name = "READ_SMART_THRESHOLDS"; break;
1578  case ATA_SMART_ENABLE:
1579  code = IOCTL_SCSI_MINIPORT_ENABLE_SMART; name = "ENABLE_SMART"; break;
1580  case ATA_SMART_DISABLE:
1581  code = IOCTL_SCSI_MINIPORT_DISABLE_SMART; name = "DISABLE_SMART"; break;
1582  case ATA_SMART_STATUS:
1583  code = IOCTL_SCSI_MINIPORT_RETURN_STATUS; name = "RETURN_STATUS"; break;
1584  case ATA_SMART_AUTOSAVE:
1585  code = IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE; name = "ENABLE_DISABLE_AUTOSAVE"; break;
1586  //case ATA_SMART_SAVE: // obsolete since ATA-6, not used by smartmontools
1587  // code = IOCTL_SCSI_MINIPORT_SAVE_ATTRIBUTE_VALUES; name = "SAVE_ATTRIBUTE_VALUES"; break;
1589  code = IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS; name = "EXECUTE_OFFLINE_DIAGS"; break;
1591  code = IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE; name = "ENABLE_DISABLE_AUTO_OFFLINE"; break;
1593  code = IOCTL_SCSI_MINIPORT_READ_SMART_LOG; name = "READ_SMART_LOG"; break;
1595  code = IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG; name = "WRITE_SMART_LOG"; break;
1596  }
1597  if (!code) {
1598  errno = ENOSYS;
1599  return -1;
1600  }
1601 
1602  // Set SRB
1603  struct {
1604  SRB_IO_CONTROL srbc;
1605  union {
1606  SENDCMDINPARAMS in;
1607  SENDCMDOUTPARAMS out;
1608  } params;
1609  char space[512-1];
1610  } sb;
1611  ASSERT_SIZEOF(sb, sizeof(SRB_IO_CONTROL)+sizeof(SENDCMDINPARAMS)-1+512);
1612  memset(&sb, 0, sizeof(sb));
1613 
1614  unsigned size;
1615  if (datasize > 0) {
1616  if (datasize > (int)sizeof(sb.space)+1) {
1617  errno = EINVAL;
1618  return -1;
1619  }
1620  size = datasize;
1621  }
1622  else if (datasize < 0) {
1623  if (-datasize > (int)sizeof(sb.space)+1) {
1624  errno = EINVAL;
1625  return -1;
1626  }
1627  size = -datasize;
1628  memcpy(sb.params.in.bBuffer, data, size);
1629  }
1630  else if (code == IOCTL_SCSI_MINIPORT_RETURN_STATUS)
1631  size = sizeof(IDEREGS);
1632  else
1633  size = 0;
1634  sb.srbc.HeaderLength = sizeof(SRB_IO_CONTROL);
1635  memcpy(sb.srbc.Signature, "SCSIDISK", 8); // atapi.sys
1636  sb.srbc.Timeout = 60; // seconds
1637  sb.srbc.ControlCode = code;
1638  //sb.srbc.ReturnCode = 0;
1639  sb.srbc.Length = sizeof(SENDCMDINPARAMS)-1 + size;
1640  sb.params.in.irDriveRegs = *regs;
1641  sb.params.in.cBufferSize = size;
1642 
1643  // Call miniport ioctl
1644  size += sizeof(SRB_IO_CONTROL) + sizeof(SENDCMDINPARAMS)-1;
1645  DWORD num_out;
1646  if (!DeviceIoControl(hdevice, IOCTL_SCSI_MINIPORT,
1647  &sb, size, &sb, size, &num_out, NULL)) {
1648  long err = GetLastError();
1649  if (ata_debugmode) {
1650  pout(" IOCTL_SCSI_MINIPORT_%s failed, Error=%ld\n", name, err);
1651  print_ide_regs_io(regs, NULL);
1652  }
1653  errno = (err == ERROR_INVALID_FUNCTION || err == ERROR_NOT_SUPPORTED ? ENOSYS : EIO);
1654  return -1;
1655  }
1656 
1657  // Check result
1658  if (sb.srbc.ReturnCode) {
1659  if (ata_debugmode) {
1660  pout(" IOCTL_SCSI_MINIPORT_%s failed, ReturnCode=0x%08x\n", name, (unsigned)sb.srbc.ReturnCode);
1661  print_ide_regs_io(regs, NULL);
1662  }
1663  errno = EIO;
1664  return -1;
1665  }
1666 
1667  if (sb.params.out.DriverStatus.bDriverError) {
1668  if (ata_debugmode) {
1669  pout(" IOCTL_SCSI_MINIPORT_%s failed, DriverError=0x%02x, IDEError=0x%02x\n", name,
1670  sb.params.out.DriverStatus.bDriverError, sb.params.out.DriverStatus.bIDEError);
1671  print_ide_regs_io(regs, NULL);
1672  }
1673  errno = (!sb.params.out.DriverStatus.bIDEError ? ENOSYS : EIO);
1674  return -1;
1675  }
1676 
1677  if (ata_debugmode > 1) {
1678  pout(" IOCTL_SCSI_MINIPORT_%s suceeded, bytes returned: %u (buffer %u)\n", name,
1679  (unsigned)num_out, (unsigned)sb.params.out.cBufferSize);
1681  (const IDEREGS *)(sb.params.out.bBuffer) : 0));
1682  }
1683 
1684  if (datasize > 0)
1685  memcpy(data, sb.params.out.bBuffer, datasize);
1686  else if (datasize == 0 && code == IOCTL_SCSI_MINIPORT_RETURN_STATUS)
1687  memcpy(regs, sb.params.out.bBuffer, sizeof(IDEREGS));
1688 
1689  return 0;
1690 }
1691 
1692 
1693 /////////////////////////////////////////////////////////////////////////////
1694 
1695 // ATA PASS THROUGH via 3ware specific SCSI MINIPORT ioctl
1696 
1697 static int ata_via_3ware_miniport_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, int datasize, int port)
1698 {
1699  struct {
1700  SRB_IO_CONTROL srbc;
1701  IDEREGS regs;
1702  UCHAR buffer[512];
1703  } sb;
1704  ASSERT_SIZEOF(sb, sizeof(SRB_IO_CONTROL)+sizeof(IDEREGS)+512);
1705 
1706  if (!(0 <= datasize && datasize <= (int)sizeof(sb.buffer) && port >= 0)) {
1707  errno = EINVAL;
1708  return -1;
1709  }
1710  memset(&sb, 0, sizeof(sb));
1711  strncpy((char *)sb.srbc.Signature, "<3ware>", sizeof(sb.srbc.Signature));
1712  sb.srbc.HeaderLength = sizeof(SRB_IO_CONTROL);
1713  sb.srbc.Timeout = 60; // seconds
1714  sb.srbc.ControlCode = 0xA0000000;
1715  sb.srbc.ReturnCode = 0;
1716  sb.srbc.Length = sizeof(IDEREGS) + (datasize > 0 ? datasize : 1);
1717  sb.regs = *regs;
1718  sb.regs.bReserved = port;
1719 
1720  DWORD num_out;
1721  if (!DeviceIoControl(hdevice, IOCTL_SCSI_MINIPORT,
1722  &sb, sizeof(sb), &sb, sizeof(sb), &num_out, NULL)) {
1723  long err = GetLastError();
1724  if (ata_debugmode) {
1725  pout(" ATA via IOCTL_SCSI_MINIPORT failed, Error=%ld\n", err);
1726  print_ide_regs_io(regs, NULL);
1727  }
1728  errno = (err == ERROR_INVALID_FUNCTION ? ENOSYS : EIO);
1729  return -1;
1730  }
1731 
1732  if (sb.srbc.ReturnCode) {
1733  if (ata_debugmode) {
1734  pout(" ATA via IOCTL_SCSI_MINIPORT failed, ReturnCode=0x%08x\n", (unsigned)sb.srbc.ReturnCode);
1735  print_ide_regs_io(regs, NULL);
1736  }
1737  errno = EIO;
1738  return -1;
1739  }
1740 
1741  // Copy data
1742  if (datasize > 0)
1743  memcpy(data, sb.buffer, datasize);
1744 
1745  if (ata_debugmode > 1) {
1746  pout(" ATA via IOCTL_SCSI_MINIPORT suceeded, bytes returned: %u\n", (unsigned)num_out);
1747  print_ide_regs_io(regs, &sb.regs);
1748  }
1749  *regs = sb.regs;
1750 
1751  return 0;
1752 }
1753 
1754 
1755 /////////////////////////////////////////////////////////////////////////////
1756 
1757 // 3ware specific call to update the devicemap returned by SMART_GET_VERSION.
1758 // 3DM/CLI "Rescan Controller" function does not to always update it.
1759 
1760 static int update_3ware_devicemap_ioctl(HANDLE hdevice)
1761 {
1762  SRB_IO_CONTROL srbc;
1763  memset(&srbc, 0, sizeof(srbc));
1764  strncpy((char *)srbc.Signature, "<3ware>", sizeof(srbc.Signature));
1765  srbc.HeaderLength = sizeof(SRB_IO_CONTROL);
1766  srbc.Timeout = 60; // seconds
1767  srbc.ControlCode = 0xCC010014;
1768  srbc.ReturnCode = 0;
1769  srbc.Length = 0;
1770 
1771  DWORD num_out;
1772  if (!DeviceIoControl(hdevice, IOCTL_SCSI_MINIPORT,
1773  &srbc, sizeof(srbc), &srbc, sizeof(srbc), &num_out, NULL)) {
1774  long err = GetLastError();
1775  if (ata_debugmode)
1776  pout(" UPDATE DEVICEMAP via IOCTL_SCSI_MINIPORT failed, Error=%ld\n", err);
1777  errno = (err == ERROR_INVALID_FUNCTION ? ENOSYS : EIO);
1778  return -1;
1779  }
1780  if (srbc.ReturnCode) {
1781  if (ata_debugmode)
1782  pout(" UPDATE DEVICEMAP via IOCTL_SCSI_MINIPORT failed, ReturnCode=0x%08x\n", (unsigned)srbc.ReturnCode);
1783  errno = EIO;
1784  return -1;
1785  }
1786  if (ata_debugmode > 1)
1787  pout(" UPDATE DEVICEMAP via IOCTL_SCSI_MINIPORT suceeded\n");
1788  return 0;
1789 }
1790 
1791 
1792 
1793 /////////////////////////////////////////////////////////////////////////////
1794 
1795 // Routines for pseudo device /dev/tw_cli/*
1796 // Parses output of 3ware "tw_cli /cx/py show all" or 3DM SMART data window
1797 
1798 
1799 // Get clipboard data
1800 
1801 static int get_clipboard(char * data, int datasize)
1802 {
1803  if (!OpenClipboard(NULL))
1804  return -1;
1805  HANDLE h = GetClipboardData(CF_TEXT);
1806  if (!h) {
1807  CloseClipboard();
1808  return 0;
1809  }
1810  const void * p = GlobalLock(h);
1811  int n = GlobalSize(h);
1812  if (n > datasize)
1813  n = datasize;
1814  memcpy(data, p, n);
1815  GlobalFree(h);
1816  CloseClipboard();
1817  return n;
1818 }
1819 
1820 
1821 // Run a command, write stdout to dataout
1822 // TODO: Combine with daemon_win32.cpp:daemon_spawn()
1823 
1824 static int run_cmd(const char * cmd, char * dataout, int outsize)
1825 {
1826  // Create stdout pipe
1827  SECURITY_ATTRIBUTES sa = {sizeof(sa), 0, TRUE};
1828  HANDLE pipe_out_w, h;
1829  if (!CreatePipe(&h, &pipe_out_w, &sa/*inherit*/, outsize))
1830  return -1;
1831  HANDLE self = GetCurrentProcess();
1832  HANDLE pipe_out_r;
1833  if (!DuplicateHandle(self, h, self, &pipe_out_r,
1834  GENERIC_READ, FALSE/*!inherit*/, DUPLICATE_CLOSE_SOURCE)) {
1835  CloseHandle(pipe_out_w);
1836  return -1;
1837  }
1838  HANDLE pipe_err_w;
1839  if (!DuplicateHandle(self, pipe_out_w, self, &pipe_err_w,
1840  0, TRUE/*inherit*/, DUPLICATE_SAME_ACCESS)) {
1841  CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
1842  return -1;
1843  }
1844 
1845  // Create process
1846  STARTUPINFO si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
1847  si.hStdInput = INVALID_HANDLE_VALUE;
1848  si.hStdOutput = pipe_out_w; si.hStdError = pipe_err_w;
1849  si.dwFlags = STARTF_USESTDHANDLES;
1850  PROCESS_INFORMATION pi;
1851  if (!CreateProcess(
1852  NULL, const_cast<char *>(cmd),
1853  NULL, NULL, TRUE/*inherit*/,
1854  CREATE_NO_WINDOW/*do not create a new console window*/,
1855  NULL, NULL, &si, &pi)) {
1856  CloseHandle(pipe_err_w); CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
1857  return -1;
1858  }
1859  CloseHandle(pi.hThread);
1860  CloseHandle(pipe_err_w); CloseHandle(pipe_out_w);
1861 
1862  // Copy stdout to output buffer
1863  int i = 0;
1864  while (i < outsize) {
1865  DWORD num_read;
1866  if (!ReadFile(pipe_out_r, dataout+i, outsize-i, &num_read, NULL) || num_read == 0)
1867  break;
1868  i += num_read;
1869  }
1870  CloseHandle(pipe_out_r);
1871  // Wait for process
1872  WaitForSingleObject(pi.hProcess, INFINITE);
1873  CloseHandle(pi.hProcess);
1874  return i;
1875 }
1876 
1877 
1878 static const char * findstr(const char * str, const char * sub)
1879 {
1880  const char * s = strstr(str, sub);
1881  return (s ? s+strlen(sub) : "");
1882 }
1883 
1884 
1885 static void copy_swapped(unsigned char * dest, const char * src, int destsize)
1886 {
1887  int srclen = strcspn(src, "\r\n");
1888  int i;
1889  for (i = 0; i < destsize-1 && i < srclen-1; i+=2) {
1890  dest[i] = src[i+1]; dest[i+1] = src[i];
1891  }
1892  if (i < destsize-1 && i < srclen)
1893  dest[i+1] = src[i];
1894 }
1895 
1896 
1897 // TODO: This is OS independent
1898 
1899 win_tw_cli_device::win_tw_cli_device(smart_interface * intf, const char * dev_name, const char * req_type)
1900 : smart_device(intf, dev_name, "tw_cli", req_type),
1901  m_ident_valid(false), m_smart_valid(false)
1902 {
1903  memset(&m_ident_buf, 0, sizeof(m_ident_buf));
1904  memset(&m_smart_buf, 0, sizeof(m_smart_buf));
1905 }
1906 
1907 
1909 {
1910  return (m_ident_valid || m_smart_valid);
1911 }
1912 
1913 
1915 {
1916  m_ident_valid = m_smart_valid = false;
1917  const char * name = skipdev(get_dev_name());
1918  // Read tw_cli or 3DM browser output into buffer
1919  char buffer[4096];
1920  int size = -1, n1 = -1, n2 = -1;
1921  if (!strcmp(name, "tw_cli/clip")) { // read clipboard
1922  size = get_clipboard(buffer, sizeof(buffer));
1923  }
1924  else if (!strcmp(name, "tw_cli/stdin")) { // read stdin
1925  size = fread(buffer, 1, sizeof(buffer), stdin);
1926  }
1927  else if (sscanf(name, "tw_cli/%nc%*u/p%*u%n", &n1, &n2) >= 0 && n2 == (int)strlen(name)) {
1928  // tw_cli/cx/py => read output from "tw_cli /cx/py show all"
1929  char cmd[100];
1930  snprintf(cmd, sizeof(cmd), "tw_cli /%s show all", name+n1);
1931  if (ata_debugmode > 1)
1932  pout("%s: Run: \"%s\"\n", name, cmd);
1933  size = run_cmd(cmd, buffer, sizeof(buffer));
1934  }
1935  else {
1936  return set_err(EINVAL);
1937  }
1938 
1939  if (ata_debugmode > 1)
1940  pout("%s: Read %d bytes\n", name, size);
1941  if (size <= 0)
1942  return set_err(ENOENT);
1943  if (size >= (int)sizeof(buffer))
1944  return set_err(EIO);
1945 
1946  buffer[size] = 0;
1947  if (ata_debugmode > 1)
1948  pout("[\n%.100s%s\n]\n", buffer, (size>100?"...":""));
1949 
1950  // Fake identify sector
1953  memset(id, 0, sizeof(*id));
1954  copy_swapped(id->model , findstr(buffer, " Model = " ), sizeof(id->model));
1955  copy_swapped(id->fw_rev , findstr(buffer, " Firmware Version = "), sizeof(id->fw_rev));
1956  copy_swapped(id->serial_no, findstr(buffer, " Serial = " ), sizeof(id->serial_no));
1957  unsigned long nblocks = 0; // "Capacity = N.N GB (N Blocks)"
1958  sscanf(findstr(buffer, "Capacity = "), "%*[^(\r\n](%lu", &nblocks);
1959  if (nblocks) {
1960  id->words047_079[49-47] = 0x0200; // size valid
1961  id->words047_079[60-47] = (unsigned short)(nblocks ); // secs_16
1962  id->words047_079[61-47] = (unsigned short)(nblocks>>16); // secs_32
1963  }
1964  id->command_set_1 = 0x0001; id->command_set_2 = 0x4000; // SMART supported, words 82,83 valid
1965  id->cfs_enable_1 = 0x0001; id->csf_default = 0x4000; // SMART enabled, words 85,87 valid
1966 
1967  // Parse smart data hex dump
1968  const char * s = findstr(buffer, "Drive Smart Data:");
1969  if (!*s)
1970  s = findstr(buffer, "Drive SMART Data:"); // tw_cli from 9.5.x
1971  if (!*s) {
1972  s = findstr(buffer, "S.M.A.R.T. (Controller"); // from 3DM browser window
1973  if (*s) {
1974  const char * s1 = findstr(s, "<td class"); // html version
1975  if (*s1)
1976  s = s1;
1977  s += strcspn(s, "\r\n");
1978  }
1979  else
1980  s = buffer; // try raw hex dump without header
1981  }
1982  unsigned char * sd = (unsigned char *)&m_smart_buf;
1983  int i = 0;
1984  for (;;) {
1985  unsigned x = ~0; int n = -1;
1986  if (!(sscanf(s, "%x %n", &x, &n) == 1 && !(x & ~0xff)))
1987  break;
1988  sd[i] = (unsigned char)x;
1989  if (!(++i < 512 && n > 0))
1990  break;
1991  s += n;
1992  if (*s == '<') // "<br>"
1993  s += strcspn(s, "\r\n");
1994  }
1995  if (i < 512) {
1996  if (!id->model[1]) {
1997  // No useful data found
1998  char * err = strstr(buffer, "Error:");
1999  if (!err)
2000  err = strstr(buffer, "error :");
2001  if (err && (err = strchr(err, ':'))) {
2002  // Show tw_cli error message
2003  err++;
2004  err[strcspn(err, "\r\n")] = 0;
2005  return set_err(EIO, "%s", err);
2006  }
2007  return set_err(EIO);
2008  }
2009  sd = 0;
2010  }
2011 
2012  m_ident_valid = true;
2013  m_smart_valid = !!sd;
2014  return true;
2015 }
2016 
2017 
2019 {
2020  m_ident_valid = m_smart_valid = false;
2021  return true;
2022 }
2023 
2024 
2026 {
2027  switch (command) {
2028  case IDENTIFY:
2029  if (!m_ident_valid)
2030  break;
2031  memcpy(data, &m_ident_buf, 512);
2032  return 0;
2033  case READ_VALUES:
2034  if (!m_smart_valid)
2035  break;
2036  memcpy(data, &m_smart_buf, 512);
2037  return 0;
2038  case ENABLE:
2039  case STATUS:
2040  case STATUS_CHECK: // Fake "good" SMART status
2041  return 0;
2042  default:
2043  break;
2044  }
2045  // Arrive here for all unsupported commands
2046  set_err(ENOSYS);
2047  return -1;
2048 }
2049 
2050 
2051 /////////////////////////////////////////////////////////////////////////////
2052 // IOCTL_STORAGE_QUERY_PROPERTY
2053 
2056  char raw[256];
2057 };
2058 
2059 // Get STORAGE_DEVICE_DESCRIPTOR_DATA for device.
2060 // (This works without admin rights)
2061 
2063 {
2065  memset(data, 0, sizeof(*data));
2066 
2067  DWORD num_out;
2068  if (!DeviceIoControl(hdevice, IOCTL_STORAGE_QUERY_PROPERTY,
2069  &query, sizeof(query), data, sizeof(*data), &num_out, NULL)) {
2070  if (ata_debugmode > 1 || scsi_debugmode > 1)
2071  pout(" IOCTL_STORAGE_QUERY_PROPERTY failed, Error=%u\n", (unsigned)GetLastError());
2072  errno = ENOSYS;
2073  return -1;
2074  }
2075 
2076  if (ata_debugmode > 1 || scsi_debugmode > 1) {
2077  pout(" IOCTL_STORAGE_QUERY_PROPERTY returns:\n"
2078  " Vendor: \"%s\"\n"
2079  " Product: \"%s\"\n"
2080  " Revision: \"%s\"\n"
2081  " Removable: %s\n"
2082  " BusType: 0x%02x\n",
2083  (data->desc.VendorIdOffset ? data->raw+data->desc.VendorIdOffset : "(null)"),
2084  (data->desc.ProductIdOffset ? data->raw+data->desc.ProductIdOffset : "(null)"),
2085  (data->desc.ProductRevisionOffset ? data->raw+data->desc.ProductRevisionOffset : "(null)"),
2086  (data->desc.RemovableMedia? "Yes":"No"), data->desc.BusType
2087  );
2088  }
2089  return 0;
2090 }
2091 
2092 
2093 /////////////////////////////////////////////////////////////////////////////
2094 // IOCTL_STORAGE_PREDICT_FAILURE
2095 
2096 // Call IOCTL_STORAGE_PREDICT_FAILURE, return PredictFailure value
2097 // or -1 on error, opionally return VendorSpecific data.
2098 // (This works without admin rights)
2099 
2100 static int storage_predict_failure_ioctl(HANDLE hdevice, char * data = 0)
2101 {
2102  STORAGE_PREDICT_FAILURE pred;
2103  memset(&pred, 0, sizeof(pred));
2104 
2105  DWORD num_out;
2106  if (!DeviceIoControl(hdevice, IOCTL_STORAGE_PREDICT_FAILURE,
2107  0, 0, &pred, sizeof(pred), &num_out, NULL)) {
2108  if (ata_debugmode > 1)
2109  pout(" IOCTL_STORAGE_PREDICT_FAILURE failed, Error=%u\n", (unsigned)GetLastError());
2110  errno = ENOSYS;
2111  return -1;
2112  }
2113 
2114  if (ata_debugmode > 1) {
2115  pout(" IOCTL_STORAGE_PREDICT_FAILURE returns:\n"
2116  " PredictFailure: 0x%08x\n"
2117  " VendorSpecific: 0x%02x,0x%02x,0x%02x,...,0x%02x\n",
2118  (unsigned)pred.PredictFailure,
2119  pred.VendorSpecific[0], pred.VendorSpecific[1], pred.VendorSpecific[2],
2120  pred.VendorSpecific[sizeof(pred.VendorSpecific)-1]
2121  );
2122  }
2123  if (data)
2124  memcpy(data, pred.VendorSpecific, sizeof(pred.VendorSpecific));
2125  return (!pred.PredictFailure ? 0 : 1);
2126 }
2127 
2128 
2129 /////////////////////////////////////////////////////////////////////////////
2130 
2131 // Return true if ATA drive behind a SAT layer
2133 {
2134  if (!data->desc.VendorIdOffset)
2135  return false;
2136  if (strcmp(data->raw + data->desc.VendorIdOffset, "ATA "))
2137  return false;
2138  return true;
2139 }
2140 
2141 // Return true if Intel ICHxR RAID volume
2143 {
2144  if (!(data->desc.VendorIdOffset && data->desc.ProductIdOffset))
2145  return false;
2146  const char * vendor = data->raw + data->desc.VendorIdOffset;
2147  if (!(!strnicmp(vendor, "Intel", 5) && strspn(vendor+5, " ") == strlen(vendor+5)))
2148  return false;
2149  if (strnicmp(data->raw + data->desc.ProductIdOffset, "Raid ", 5))
2150  return false;
2151  return true;
2152 }
2153 
2154 // get DEV_* for open handle
2155 static win_dev_type get_controller_type(HANDLE hdevice, bool admin, GETVERSIONINPARAMS_EX * ata_version_ex)
2156 {
2157  // Get BusType from device descriptor
2159  if (storage_query_property_ioctl(hdevice, &data))
2160  return DEV_UNKNOWN;
2161 
2162  // Newer BusType* values are missing in older includes
2163  switch ((int)data.desc.BusType) {
2164  case BusTypeAta:
2165  case 0x0b: // BusTypeSata
2166  // Certain Intel AHCI drivers (C600+/C220+) have broken
2167  // IOCTL_ATA_PASS_THROUGH support and a working SAT layer
2168  if (is_sat(&data))
2169  return DEV_SAT;
2170 
2171  if (ata_version_ex)
2172  memset(ata_version_ex, 0, sizeof(*ata_version_ex));
2173  return DEV_ATA;
2174 
2175  case BusTypeScsi:
2176  case BusTypeRAID:
2177  if (is_sat(&data))
2178  return DEV_SAT;
2179 
2180  // Intel ICHxR RAID volume: reports SMART_GET_VERSION but does not support SMART_*
2181  if (is_intel_raid_volume(&data))
2182  return DEV_SCSI;
2183  // LSI/3ware RAID volume: supports SMART_*
2184  if (admin && smart_get_version(hdevice, ata_version_ex) >= 0)
2185  return DEV_ATA;
2186 
2187  return DEV_SCSI;
2188 
2189  case 0x09: // BusTypeiScsi
2190  case 0x0a: // BusTypeSas
2191  if (is_sat(&data))
2192  return DEV_SAT;
2193 
2194  return DEV_SCSI;
2195 
2196  case BusTypeUsb:
2197  return DEV_USB;
2198 
2199  default:
2200  return DEV_UNKNOWN;
2201  }
2202  /*NOTREACHED*/
2203 }
2204 
2205 // get DEV_* for device path
2206 static win_dev_type get_controller_type(const char * path, GETVERSIONINPARAMS_EX * ata_version_ex = 0)
2207 {
2208  bool admin = true;
2209  HANDLE h = CreateFileA(path, GENERIC_READ|GENERIC_WRITE,
2210  FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
2211  if (h == INVALID_HANDLE_VALUE) {
2212  admin = false;
2213  h = CreateFileA(path, 0,
2214  FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
2215  if (h == INVALID_HANDLE_VALUE)
2216  return DEV_UNKNOWN;
2217  }
2218  if (ata_debugmode > 1 || scsi_debugmode > 1)
2219  pout(" %s: successfully opened%s\n", path, (!admin ? " (without admin rights)" :""));
2220  win_dev_type type = get_controller_type(h, admin, ata_version_ex);
2221  CloseHandle(h);
2222  return type;
2223 }
2224 
2225 // get DEV_* for physical drive number
2226 static win_dev_type get_phy_drive_type(int drive, GETVERSIONINPARAMS_EX * ata_version_ex)
2227 {
2228  char path[30];
2229  snprintf(path, sizeof(path)-1, "\\\\.\\PhysicalDrive%d", drive);
2230  return get_controller_type(path, ata_version_ex);
2231 }
2232 
2234 {
2235  return get_phy_drive_type(drive, 0);
2236 }
2237 
2238 // get DEV_* for logical drive number
2240 {
2241  char path[30];
2242  snprintf(path, sizeof(path)-1, "\\\\.\\%c:", 'A'+drive);
2243  return get_controller_type(path);
2244 }
2245 
2246 // Build IDENTIFY information from STORAGE_DEVICE_DESCRIPTOR
2248 {
2250  if (storage_query_property_ioctl(hdevice, &data))
2251  return -1;
2252 
2253  memset(id, 0, sizeof(*id));
2254 
2255  // Some drivers split ATA model string into VendorId and ProductId,
2256  // others return it as ProductId only.
2257  char model[sizeof(id->model) + 1] = "";
2258 
2259  unsigned i = 0;
2260  if (data.desc.VendorIdOffset) {
2261  for ( ;i < sizeof(model)-1 && data.raw[data.desc.VendorIdOffset+i]; i++)
2262  model[i] = data.raw[data.desc.VendorIdOffset+i];
2263  }
2264 
2265  if (data.desc.ProductIdOffset) {
2266  while (i > 1 && model[i-2] == ' ') // Keep last blank from VendorId
2267  i--;
2268  // Ignore VendorId "ATA"
2269  if (i <= 4 && !strncmp(model, "ATA", 3) && (i == 3 || model[3] == ' '))
2270  i = 0;
2271  for (unsigned j = 0; i < sizeof(model)-1 && data.raw[data.desc.ProductIdOffset+j]; i++, j++)
2272  model[i] = data.raw[data.desc.ProductIdOffset+j];
2273  }
2274 
2275  while (i > 0 && model[i-1] == ' ')
2276  i--;
2277  model[i] = 0;
2278  copy_swapped(id->model, model, sizeof(id->model));
2279 
2280  if (data.desc.ProductRevisionOffset)
2281  copy_swapped(id->fw_rev, data.raw+data.desc.ProductRevisionOffset, sizeof(id->fw_rev));
2282 
2283  id->command_set_1 = 0x0001; id->command_set_2 = 0x4000; // SMART supported, words 82,83 valid
2284  id->cfs_enable_1 = 0x0001; id->csf_default = 0x4000; // SMART enabled, words 85,87 valid
2285  return 0;
2286 }
2287 
2288 // Get Serial Number in IDENTIFY from WMI
2289 static bool get_serial_from_wmi(int drive, ata_identify_device * id)
2290 {
2291  bool debug = (ata_debugmode > 1);
2292 
2293  wbem_services ws;
2294  if (!ws.connect()) {
2295  if (debug)
2296  pout("WMI connect failed\n");
2297  return false;
2298  }
2299 
2300  wbem_object wo;
2301  if (!ws.query1(wo, "SELECT Model,SerialNumber FROM Win32_DiskDrive WHERE "
2302  "DeviceID=\"\\\\\\\\.\\\\PHYSICALDRIVE%d\"", drive))
2303  return false;
2304 
2305  std::string serial = wo.get_str("SerialNumber");
2306  if (debug)
2307  pout(" WMI:PhysicalDrive%d: \"%s\", S/N:\"%s\"\n", drive, wo.get_str("Model").c_str(), serial.c_str());
2308 
2309  copy_swapped(id->serial_no, serial.c_str(), sizeof(id->serial_no));
2310  return true;
2311 }
2312 
2313 
2314 /////////////////////////////////////////////////////////////////////////////
2315 // USB ID detection using WMI
2316 
2317 // Get USB ID for a physical drive number
2318 static bool get_usb_id(int drive, unsigned short & vendor_id, unsigned short & product_id)
2319 {
2320  bool debug = (scsi_debugmode > 1);
2321 
2322  wbem_services ws;
2323  if (!ws.connect()) {
2324  if (debug)
2325  pout("WMI connect failed\n");
2326  return false;
2327  }
2328 
2329  // Get device name
2330  wbem_object wo;
2331  if (!ws.query1(wo, "SELECT Model FROM Win32_DiskDrive WHERE DeviceID=\"\\\\\\\\.\\\\PHYSICALDRIVE%d\"", drive))
2332  return false;
2333 
2334  std::string name = wo.get_str("Model");
2335  if (debug)
2336  pout("PhysicalDrive%d, \"%s\":\n", drive, name.c_str());
2337 
2338  // Get USB_CONTROLLER -> DEVICE associations
2339  wbem_enumerator we;
2340  if (!ws.query(we, "SELECT Antecedent,Dependent FROM Win32_USBControllerDevice"))
2341  return false;
2342 
2343  unsigned short usb_venid = 0, prev_usb_venid = 0;
2344  unsigned short usb_proid = 0, prev_usb_proid = 0;
2345  std::string prev_usb_ant;
2346  std::string prev_ant, ant, dep;
2347 
2348  const regular_expression regex("^.*PnPEntity\\.DeviceID=\"([^\"]*)\"", REG_EXTENDED);
2349 
2350  while (we.next(wo)) {
2351  prev_ant = ant;
2352  // Find next 'USB_CONTROLLER, DEVICE' pair
2353  ant = wo.get_str("Antecedent");
2354  dep = wo.get_str("Dependent");
2355 
2356  if (debug && ant != prev_ant)
2357  pout(" %s:\n", ant.c_str());
2358 
2359  // Extract DeviceID
2360  regmatch_t match[2];
2361  if (!(regex.execute(dep.c_str(), 2, match) && match[1].rm_so >= 0)) {
2362  if (debug)
2363  pout(" | (\"%s\")\n", dep.c_str());
2364  continue;
2365  }
2366 
2367  std::string devid(dep.c_str()+match[1].rm_so, match[1].rm_eo-match[1].rm_so);
2368 
2369  if (str_starts_with(devid, "USB\\\\VID_")) {
2370  // USB bridge entry, save CONTROLLER, ID
2371  int nc = -1;
2372  if (!(sscanf(devid.c_str(), "USB\\\\VID_%4hx&PID_%4hx%n",
2373  &prev_usb_venid, &prev_usb_proid, &nc) == 2 && nc == 9+4+5+4)) {
2374  prev_usb_venid = prev_usb_proid = 0;
2375  }
2376  prev_usb_ant = ant;
2377  if (debug)
2378  pout(" +-> \"%s\" [0x%04x:0x%04x]\n", devid.c_str(), prev_usb_venid, prev_usb_proid);
2379  continue;
2380  }
2381  else if (str_starts_with(devid, "USBSTOR\\\\")) {
2382  // USBSTOR device found
2383  if (debug)
2384  pout(" +--> \"%s\"\n", devid.c_str());
2385 
2386  // Retrieve name
2387  wbem_object wo2;
2388  if (!ws.query1(wo2, "SELECT Name FROM Win32_PnPEntity WHERE DeviceID=\"%s\"", devid.c_str()))
2389  continue;
2390  std::string name2 = wo2.get_str("Name");
2391 
2392  // Continue if not name of physical disk drive
2393  if (name2 != name) {
2394  if (debug)
2395  pout(" +---> (\"%s\")\n", name2.c_str());
2396  continue;
2397  }
2398 
2399  // Fail if previous USB bridge is associated to other controller or ID is unknown
2400  if (!(ant == prev_usb_ant && prev_usb_venid)) {
2401  if (debug)
2402  pout(" +---> \"%s\" (Error: No USB bridge found)\n", name2.c_str());
2403  return false;
2404  }
2405 
2406  // Handle multiple devices with same name
2407  if (usb_venid) {
2408  // Fail if multiple devices with same name have different USB bridge types
2409  if (!(usb_venid == prev_usb_venid && usb_proid == prev_usb_proid)) {
2410  if (debug)
2411  pout(" +---> \"%s\" (Error: More than one USB ID found)\n", name2.c_str());
2412  return false;
2413  }
2414  }
2415 
2416  // Found
2417  usb_venid = prev_usb_venid;
2418  usb_proid = prev_usb_proid;
2419  if (debug)
2420  pout(" +===> \"%s\" [0x%04x:0x%04x]\n", name2.c_str(), usb_venid, usb_proid);
2421 
2422  // Continue to check for duplicate names ...
2423  }
2424  else {
2425  if (debug)
2426  pout(" | \"%s\"\n", devid.c_str());
2427  }
2428  }
2429 
2430  if (!usb_venid)
2431  return false;
2432 
2433  vendor_id = usb_venid;
2434  product_id = usb_proid;
2435 
2436  return true;
2437 }
2438 
2439 
2440 /////////////////////////////////////////////////////////////////////////////
2441 
2442 // Call GetDevicePowerState()
2443 // returns: 1=active, 0=standby, -1=error
2444 // (This would also work for SCSI drives)
2445 
2446 static int get_device_power_state(HANDLE hdevice)
2447 {
2448  BOOL state = TRUE;
2449  if (!GetDevicePowerState(hdevice, &state)) {
2450  long err = GetLastError();
2451  if (ata_debugmode)
2452  pout(" GetDevicePowerState() failed, Error=%ld\n", err);
2453  errno = (err == ERROR_INVALID_FUNCTION ? ENOSYS : EIO);
2454  // TODO: This may not work as expected on transient errors,
2455  // because smartd interprets -1 as SLEEP mode regardless of errno.
2456  return -1;
2457  }
2458 
2459  if (ata_debugmode > 1)
2460  pout(" GetDevicePowerState() succeeded, state=%d\n", state);
2461  return state;
2462 }
2463 
2464 
2465 /////////////////////////////////////////////////////////////////////////////
2466 
2467 // Get default ATA device options
2468 
2469 static const char * ata_get_def_options()
2470 {
2471  return "pasifm"; // GetDevicePowerState(), ATA_, SMART_*, IDE_PASS_THROUGH,
2472  // STORAGE_*, SCSI_MINIPORT_*
2473 }
2474 
2475 
2476 // Common routines for devices with HANDLEs
2477 
2479 {
2480  if (m_fh != INVALID_HANDLE_VALUE)
2481  ::CloseHandle(m_fh);
2482 }
2483 
2485 {
2486  return (m_fh != INVALID_HANDLE_VALUE);
2487 }
2488 
2490 {
2491  if (m_fh == INVALID_HANDLE_VALUE)
2492  return true;
2493  BOOL rc = ::CloseHandle(m_fh);
2494  m_fh = INVALID_HANDLE_VALUE;
2495  return !!rc;
2496 }
2497 
2498 // ATA
2499 
2500 win_ata_device::win_ata_device(smart_interface * intf, const char * dev_name, const char * req_type)
2501 : smart_device(intf, dev_name, "ata", req_type),
2502  m_usr_options(false),
2503  m_admin(false),
2504  m_phydrive(-1),
2505  m_id_is_cached(false),
2506  m_is_3ware(false),
2507  m_port(-1),
2508  m_smartver_state(0)
2509 {
2510 }
2511 
2513 {
2514 }
2515 
2516 
2517 // Open ATA device
2518 
2520 {
2521  const char * name = skipdev(get_dev_name()); int len = strlen(name);
2522  // [sh]d[a-z]([a-z])?(:[saicmfp]+)? => Physical drive 0-701, with options
2523  char drive[2+1] = "", options[8+1] = ""; int n1 = -1, n2 = -1;
2524  if ( sscanf(name, "%*[sh]d%2[a-z]%n:%6[saimfp]%n", drive, &n1, options, &n2) >= 1
2525  && ((n1 == len && !options[0]) || n2 == len) ) {
2526  return open(sdxy_to_phydrive(drive), -1, options, -1);
2527  }
2528  // [sh]d[a-z],N(:[saicmfp3]+)? => Physical drive 0-701, RAID port N, with options
2529  drive[0] = 0; options[0] = 0; n1 = -1; n2 = -1;
2530  unsigned port = ~0;
2531  if ( sscanf(name, "%*[sh]d%2[a-z],%u%n:%7[saimfp3]%n", drive, &port, &n1, options, &n2) >= 2
2532  && port < 32 && ((n1 == len && !options[0]) || n2 == len) ) {
2533  return open(sdxy_to_phydrive(drive), -1, options, port);
2534  }
2535  // pd<m>,N => Physical drive <m>, RAID port N
2536  int phydrive = -1; port = ~0; n1 = -1; n2 = -1;
2537  if ( sscanf(name, "pd%d%n,%u%n", &phydrive, &n1, &port, &n2) >= 1
2538  && phydrive >= 0 && ((n1 == len && (int)port < 0) || (n2 == len && port < 32))) {
2539  return open(phydrive, -1, "", (int)port);
2540  }
2541  // [a-zA-Z]: => Physical drive behind logical drive 0-25
2542  int logdrive = drive_letter(name);
2543  if (logdrive >= 0) {
2544  return open(-1, logdrive, "", -1);
2545  }
2546 
2547  return set_err(EINVAL);
2548 }
2549 
2550 
2551 bool win_ata_device::open(int phydrive, int logdrive, const char * options, int port)
2552 {
2553  m_phydrive = -1;
2554  char devpath[30];
2555  if (0 <= phydrive && phydrive <= 255)
2556  snprintf(devpath, sizeof(devpath)-1, "\\\\.\\PhysicalDrive%d", (m_phydrive = phydrive));
2557  else if (0 <= logdrive && logdrive <= 'Z'-'A')
2558  snprintf(devpath, sizeof(devpath)-1, "\\\\.\\%c:", 'A'+logdrive);
2559  else
2560  return set_err(ENOENT);
2561 
2562  // Open device
2563  HANDLE h = INVALID_HANDLE_VALUE;
2564  if (!(*options && !options[strspn(options, "fp")])) {
2565  // Open with admin rights
2566  m_admin = true;
2567  h = CreateFileA(devpath, GENERIC_READ|GENERIC_WRITE,
2568  FILE_SHARE_READ|FILE_SHARE_WRITE,
2569  NULL, OPEN_EXISTING, 0, 0);
2570  }
2571  if (h == INVALID_HANDLE_VALUE) {
2572  // Open without admin rights
2573  m_admin = false;
2574  h = CreateFileA(devpath, 0,
2575  FILE_SHARE_READ|FILE_SHARE_WRITE,
2576  NULL, OPEN_EXISTING, 0, 0);
2577  }
2578  if (h == INVALID_HANDLE_VALUE) {
2579  long err = GetLastError();
2580  if (err == ERROR_FILE_NOT_FOUND)
2581  set_err(ENOENT, "%s: not found", devpath);
2582  else if (err == ERROR_ACCESS_DENIED)
2583  set_err(EACCES, "%s: access denied", devpath);
2584  else
2585  set_err(EIO, "%s: Error=%ld", devpath, err);
2586  return false;
2587  }
2588  set_fh(h);
2589 
2590  // Warn once if admin rights are missing
2591  if (!m_admin) {
2592  static bool noadmin_warning = false;
2593  if (!noadmin_warning) {
2594  pout("Warning: Limited functionality due to missing admin rights\n");
2595  noadmin_warning = true;
2596  }
2597  }
2598 
2599  if (ata_debugmode > 1)
2600  pout("%s: successfully opened%s\n", devpath, (!m_admin ? " (without admin rights)" :""));
2601 
2602  m_usr_options = false;
2603  if (*options) {
2604  // Save user options
2605  m_options = options; m_usr_options = true;
2606  }
2607  else if (port >= 0)
2608  // RAID: SMART_* and SCSI_MINIPORT
2609  m_options = "s3";
2610  else {
2611  // Set default options according to Windows version
2612  static const char * def_options = ata_get_def_options();
2613  m_options = def_options;
2614  }
2615 
2616  // SMART_GET_VERSION may spin up disk, so delay until first real SMART_* call
2617  m_port = port;
2618  if (port < 0)
2619  return true;
2620 
2621  // 3ware RAID: Get port map
2622  GETVERSIONINPARAMS_EX vers_ex;
2623  int devmap = smart_get_version(h, &vers_ex);
2624 
2625  // 3ware RAID if vendor id present
2626  m_is_3ware = (vers_ex.wIdentifier == SMART_VENDOR_3WARE);
2627 
2628  unsigned long portmap = 0;
2629  if (port >= 0 && devmap >= 0) {
2630  // 3ware RAID: check vendor id
2631  if (!m_is_3ware) {
2632  pout("SMART_GET_VERSION returns unknown Identifier = 0x%04x\n"
2633  "This is no 3ware 9000 controller or driver has no SMART support.\n",
2634  vers_ex.wIdentifier);
2635  devmap = -1;
2636  }
2637  else
2638  portmap = vers_ex.dwDeviceMapEx;
2639  }
2640  if (devmap < 0) {
2641  pout("%s: ATA driver has no SMART support\n", devpath);
2642  if (!is_permissive()) {
2643  close();
2644  return set_err(ENOSYS);
2645  }
2646  devmap = 0x0f;
2647  }
2648  m_smartver_state = 1;
2649 
2650  {
2651  // 3ware RAID: update devicemap first
2652 
2653  if (!update_3ware_devicemap_ioctl(h)) {
2654  if ( smart_get_version(h, &vers_ex) >= 0
2655  && vers_ex.wIdentifier == SMART_VENDOR_3WARE )
2656  portmap = vers_ex.dwDeviceMapEx;
2657  }
2658  // Check port existence
2659  if (!(portmap & (1L << port))) {
2660  if (!is_permissive()) {
2661  close();
2662  return set_err(ENOENT, "%s: Port %d is empty or does not exist", devpath, port);
2663  }
2664  }
2665  }
2666 
2667  return true;
2668 }
2669 
2670 
2671 /////////////////////////////////////////////////////////////////////////////
2672 
2673 // Interface to ATA devices
2675 {
2676  // No multi-sector support for now, see above
2677  // warning about IOCTL_ATA_PASS_THROUGH
2678  if (!ata_cmd_is_supported(in,
2682  )
2683  return false;
2684 
2685  // 3ware RAID: SMART DISABLE without port number disables SMART functions
2686  if ( m_is_3ware && m_port < 0
2687  && in.in_regs.command == ATA_SMART_CMD
2689  return set_err(ENOSYS, "SMART DISABLE requires 3ware port number");
2690 
2691  // Determine ioctl functions valid for this ATA cmd
2692  const char * valid_options = 0;
2693 
2694  switch (in.in_regs.command) {
2695  case ATA_IDENTIFY_DEVICE:
2697  // SMART_*, ATA_, IDE_, SCSI_PASS_THROUGH, STORAGE_PREDICT_FAILURE
2698  // and SCSI_MINIPORT_* if requested by user
2699  valid_options = (m_usr_options ? "saimf" : "saif");
2700  break;
2701 
2702  case ATA_CHECK_POWER_MODE:
2703  // Try GetDevicePowerState() first, ATA/IDE_PASS_THROUGH may spin up disk
2704  valid_options = "pai3";
2705  break;
2706 
2707  case ATA_SMART_CMD:
2708  switch (in.in_regs.features) {
2709  case ATA_SMART_READ_VALUES:
2711  case ATA_SMART_AUTOSAVE:
2712  case ATA_SMART_ENABLE:
2713  case ATA_SMART_DISABLE:
2715  // SMART_*, ATA_, IDE_, SCSI_PASS_THROUGH, STORAGE_PREDICT_FAILURE
2716  // and SCSI_MINIPORT_* if requested by user
2717  valid_options = (m_usr_options ? "saimf" : "saif");
2718  break;
2719 
2721  // SMART_SEND_DRIVE_COMMAND does not support ABORT_SELF_TEST
2722  valid_options = (m_usr_options || in.in_regs.lba_low != 127/*ABORT*/ ?
2723  "saim3" : "aim3");
2724  break;
2725 
2727  // SMART_RCV_DRIVE_DATA does not support READ_LOG
2728  // Try SCSI_MINIPORT also to skip buggy class driver
2729  // SMART functions do not support multi sector I/O.
2730  if (in.size == 512)
2731  valid_options = (m_usr_options ? "saim3" : "aim3");
2732  else
2733  valid_options = "a";
2734  break;
2735 
2737  // ATA_PASS_THROUGH, SCSI_MINIPORT, others don't support DATA_OUT
2738  // but SCSI_MINIPORT_* only if requested by user and single sector.
2739  valid_options = (in.size == 512 && m_usr_options ? "am" : "a");
2740  break;
2741 
2742  case ATA_SMART_STATUS:
2743  valid_options = (m_usr_options ? "saimf" : "saif");
2744  break;
2745 
2746  default:
2747  // Unknown SMART command, handle below
2748  break;
2749  }
2750  break;
2751 
2752  default:
2753  // Other ATA command, handle below
2754  break;
2755  }
2756 
2757  if (!valid_options) {
2758  // No special ATA command found above, select a generic pass through ioctl.
2759  if (!( in.direction == ata_cmd_in::no_data
2760  || (in.direction == ata_cmd_in::data_in && in.size == 512))
2761  || in.in_regs.is_48bit_cmd() )
2762  // DATA_OUT, more than one sector, 48-bit command: ATA_PASS_THROUGH only
2763  valid_options = "a";
2764  else
2765  // ATA/IDE_PASS_THROUGH
2766  valid_options = "ai";
2767  }
2768 
2769  if (!m_admin) {
2770  // Restrict to IOCTL_STORAGE_*
2771  if (strchr(valid_options, 'f'))
2772  valid_options = "f";
2773  else if (strchr(valid_options, 'p'))
2774  valid_options = "p";
2775  else
2776  return set_err(ENOSYS, "Function requires admin rights");
2777  }
2778 
2779  // Set IDEREGS
2780  IDEREGS regs, prev_regs;
2781  {
2782  const ata_in_regs & lo = in.in_regs;
2783  regs.bFeaturesReg = lo.features;
2784  regs.bSectorCountReg = lo.sector_count;
2785  regs.bSectorNumberReg = lo.lba_low;
2786  regs.bCylLowReg = lo.lba_mid;
2787  regs.bCylHighReg = lo.lba_high;
2788  regs.bDriveHeadReg = lo.device;
2789  regs.bCommandReg = lo.command;
2790  regs.bReserved = 0;
2791  }
2792  if (in.in_regs.is_48bit_cmd()) {
2793  const ata_in_regs & hi = in.in_regs.prev;
2794  prev_regs.bFeaturesReg = hi.features;
2795  prev_regs.bSectorCountReg = hi.sector_count;
2796  prev_regs.bSectorNumberReg = hi.lba_low;
2797  prev_regs.bCylLowReg = hi.lba_mid;
2798  prev_regs.bCylHighReg = hi.lba_high;
2799  prev_regs.bDriveHeadReg = hi.device;
2800  prev_regs.bCommandReg = hi.command;
2801  prev_regs.bReserved = 0;
2802  }
2803 
2804  // Set data direction
2805  int datasize = 0;
2806  char * data = 0;
2807  switch (in.direction) {
2808  case ata_cmd_in::no_data:
2809  break;
2810  case ata_cmd_in::data_in:
2811  datasize = (int)in.size;
2812  data = (char *)in.buffer;
2813  break;
2814  case ata_cmd_in::data_out:
2815  datasize = -(int)in.size;
2816  data = (char *)in.buffer;
2817  break;
2818  default:
2819  return set_err(EINVAL, "win_ata_device::ata_pass_through: invalid direction=%d",
2820  (int)in.direction);
2821  }
2822 
2823 
2824  // Try all valid ioctls in the order specified in m_options
2825  bool powered_up = false;
2826  bool out_regs_set = false;
2827  bool id_is_cached = false;
2828  const char * options = m_options.c_str();
2829 
2830  for (int i = 0; ; i++) {
2831  char opt = options[i];
2832 
2833  if (!opt) {
2834  if (in.in_regs.command == ATA_CHECK_POWER_MODE && powered_up) {
2835  // Power up reported by GetDevicePowerState() and no ioctl available
2836  // to detect the actual mode of the drive => simulate ATA result ACTIVE/IDLE.
2837  regs.bSectorCountReg = 0xff;
2838  out_regs_set = true;
2839  break;
2840  }
2841  // No IOCTL found
2842  return set_err(ENOSYS);
2843  }
2844  if (!strchr(valid_options, opt))
2845  // Invalid for this command
2846  continue;
2847 
2848  errno = 0;
2849  assert( datasize == 0 || datasize == 512
2850  || (datasize == -512 && strchr("am", opt))
2851  || (datasize > 512 && opt == 'a'));
2852  int rc;
2853  switch (opt) {
2854  default: assert(0);
2855  case 's':
2856  // call SMART_GET_VERSION once for each drive
2857  if (m_smartver_state > 1) {
2858  rc = -1; errno = ENOSYS;
2859  break;
2860  }
2861  if (!m_smartver_state) {
2862  assert(m_port == -1);
2863  GETVERSIONINPARAMS_EX vers_ex;
2864  if (smart_get_version(get_fh(), &vers_ex) < 0) {
2865  if (!failuretest_permissive) {
2866  m_smartver_state = 2;
2867  rc = -1; errno = ENOSYS;
2868  break;
2869  }
2871  }
2872  else {
2873  // 3ware RAID if vendor id present
2874  m_is_3ware = (vers_ex.wIdentifier == SMART_VENDOR_3WARE);
2875  }
2876 
2877  m_smartver_state = 1;
2878  }
2879  rc = smart_ioctl(get_fh(), &regs, data, datasize, m_port);
2880  out_regs_set = (in.in_regs.features == ATA_SMART_STATUS);
2881  id_is_cached = (m_port < 0); // Not cached by 3ware driver
2882  break;
2883  case 'm':
2884  rc = ata_via_scsi_miniport_smart_ioctl(get_fh(), &regs, data, datasize);
2885  id_is_cached = (m_port < 0);
2886  break;
2887  case 'a':
2888  rc = ata_pass_through_ioctl(get_fh(), &regs,
2889  (in.in_regs.is_48bit_cmd() ? &prev_regs : 0),
2890  data, datasize);
2891  out_regs_set = true;
2892  break;
2893  case 'i':
2894  rc = ide_pass_through_ioctl(get_fh(), &regs, data, datasize);
2895  out_regs_set = true;
2896  break;
2897  case 'f':
2898  if (in.in_regs.command == ATA_IDENTIFY_DEVICE) {
2900  if (rc == 0 && m_phydrive >= 0)
2902  id_is_cached = true;
2903  }
2904  else if (in.in_regs.command == ATA_SMART_CMD) switch (in.in_regs.features) {
2905  case ATA_SMART_READ_VALUES:
2906  rc = storage_predict_failure_ioctl(get_fh(), data);
2907  if (rc > 0)
2908  rc = 0;
2909  break;
2910  case ATA_SMART_ENABLE:
2911  rc = 0;
2912  break;
2913  case ATA_SMART_STATUS:
2915  if (rc == 0) {
2916  // Good SMART status
2917  out.out_regs.lba_high = 0xc2; out.out_regs.lba_mid = 0x4f;
2918  }
2919  else if (rc > 0) {
2920  // Bad SMART status
2921  out.out_regs.lba_high = 0x2c; out.out_regs.lba_mid = 0xf4;
2922  rc = 0;
2923  }
2924  break;
2925  default:
2926  errno = ENOSYS; rc = -1;
2927  }
2928  else {
2929  errno = ENOSYS; rc = -1;
2930  }
2931  break;
2932  case '3':
2933  rc = ata_via_3ware_miniport_ioctl(get_fh(), &regs, data, datasize, m_port);
2934  out_regs_set = true;
2935  break;
2936  case 'p':
2937  assert(in.in_regs.command == ATA_CHECK_POWER_MODE && in.size == 0);
2939  if (rc == 0) {
2940  // Power down reported by GetDevicePowerState(), using a passthrough ioctl would
2941  // spin up the drive => simulate ATA result STANDBY.
2942  regs.bSectorCountReg = 0x00;
2943  out_regs_set = true;
2944  }
2945  else if (rc > 0) {
2946  // Power up reported by GetDevicePowerState(), but this reflects the actual mode
2947  // only if it is selected by the device driver => try a passthrough ioctl to get the
2948  // actual mode, if none available simulate ACTIVE/IDLE.
2949  powered_up = true;
2950  rc = -1; errno = ENOSYS;
2951  }
2952  break;
2953  }
2954 
2955  if (!rc)
2956  // Working ioctl found
2957  break;
2958 
2959  if (errno != ENOSYS)
2960  // Abort on I/O error
2961  return set_err(errno);
2962 
2963  out_regs_set = false;
2964  // CAUTION: *_ioctl() MUST NOT change "regs" Parameter in the ENOSYS case
2965  }
2966 
2967  // Return IDEREGS if set
2968  if (out_regs_set) {
2969  ata_out_regs & lo = out.out_regs;
2970  lo.error = regs.bFeaturesReg;
2971  lo.sector_count = regs.bSectorCountReg;
2972  lo.lba_low = regs.bSectorNumberReg;
2973  lo.lba_mid = regs.bCylLowReg;
2974  lo.lba_high = regs.bCylHighReg;
2975  lo.device = regs.bDriveHeadReg;
2976  lo.status = regs.bCommandReg;
2977  if (in.in_regs.is_48bit_cmd()) {
2978  ata_out_regs & hi = out.out_regs.prev;
2979  hi.sector_count = prev_regs.bSectorCountReg;
2980  hi.lba_low = prev_regs.bSectorNumberReg;
2981  hi.lba_mid = prev_regs.bCylLowReg;
2982  hi.lba_high = prev_regs.bCylHighReg;
2983  }
2984  }
2985 
2988  // Update ata_identify_is_cached() result according to ioctl used.
2989  m_id_is_cached = id_is_cached;
2990 
2991  return true;
2992 }
2993 
2994 // Return true if OS caches the ATA identify sector
2996 {
2997  return m_id_is_cached;
2998 }
2999 
3000 
3001 //////////////////////////////////////////////////////////////////////
3002 // csmi_ata_device
3003 
3005 {
3006  // Get driver info to check CSMI support
3007  CSMI_SAS_DRIVER_INFO_BUFFER driver_info_buf;
3008  memset(&driver_info_buf, 0, sizeof(driver_info_buf));
3009  if (!csmi_ioctl(CC_CSMI_SAS_GET_DRIVER_INFO, &driver_info_buf.IoctlHeader, sizeof(driver_info_buf)))
3010  return false;
3011 
3012  if (scsi_debugmode > 1) {
3013  const CSMI_SAS_DRIVER_INFO & driver_info = driver_info_buf.Information;
3014  pout("CSMI_SAS_DRIVER_INFO:\n");
3015  pout(" Name: \"%.81s\"\n", driver_info.szName);
3016  pout(" Description: \"%.81s\"\n", driver_info.szDescription);
3017  pout(" Revision: %d.%d\n", driver_info.usMajorRevision, driver_info.usMinorRevision);
3018  }
3019 
3020  // Get Phy info
3021  CSMI_SAS_PHY_INFO_BUFFER phy_info_buf;
3022  memset(&phy_info_buf, 0, sizeof(phy_info_buf));
3023  if (!csmi_ioctl(CC_CSMI_SAS_GET_PHY_INFO, &phy_info_buf.IoctlHeader, sizeof(phy_info_buf)))
3024  return false;
3025 
3026  phy_info = phy_info_buf.Information;
3027 
3028  const int max_number_of_phys = sizeof(phy_info.Phy) / sizeof(phy_info.Phy[0]);
3029  if (phy_info.bNumberOfPhys > max_number_of_phys)
3030  return set_err(EIO, "CSMI_SAS_PHY_INFO: Bogus NumberOfPhys=%d", phy_info.bNumberOfPhys);
3031 
3032  if (scsi_debugmode > 1) {
3033  pout("CSMI_SAS_PHY_INFO: NumberOfPhys=%d\n", phy_info.bNumberOfPhys);
3034  for (int i = 0; i < max_number_of_phys; i++) {
3035  const CSMI_SAS_PHY_ENTITY & pe = phy_info.Phy[i];
3036  const CSMI_SAS_IDENTIFY & id = pe.Identify, & at = pe.Attached;
3037  if (id.bDeviceType == CSMI_SAS_NO_DEVICE_ATTACHED)
3038  continue;
3039 
3040  pout("Phy[%d] Port: 0x%02x\n", i, pe.bPortIdentifier);
3041  pout(" Type: 0x%02x, 0x%02x\n", id.bDeviceType, at.bDeviceType);
3042  pout(" InitProto: 0x%02x, 0x%02x\n", id.bInitiatorPortProtocol, at.bInitiatorPortProtocol);
3043  pout(" TargetProto: 0x%02x, 0x%02x\n", id.bTargetPortProtocol, at.bTargetPortProtocol);
3044  pout(" PhyIdent: 0x%02x, 0x%02x\n", id.bPhyIdentifier, at.bPhyIdentifier);
3045  const unsigned char * b = id.bSASAddress;
3046  pout(" SASAddress: %02x %02x %02x %02x %02x %02x %02x %02x, ",
3047  b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
3048  b = at.bSASAddress;
3049  pout( "%02x %02x %02x %02x %02x %02x %02x %02x\n",
3050  b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
3051  }
3052  }
3053 
3054  return true;
3055 }
3056 
3058 {
3059  CSMI_SAS_PHY_INFO phy_info;
3060  if (!get_phy_info(phy_info))
3061  return 0;
3062 
3063  unsigned ports_used = 0;
3064  for (unsigned i = 0; i < sizeof(phy_info.Phy) / sizeof(phy_info.Phy[0]); i++) {
3065  const CSMI_SAS_PHY_ENTITY & pe = phy_info.Phy[i];
3067  continue;
3069  continue;
3070  switch (pe.Attached.bTargetPortProtocol) {
3072  case CSMI_SAS_PROTOCOL_STP:
3073  break;
3074  default:
3075  continue;
3076  }
3077 
3078  if (pe.bPortIdentifier == 0xff)
3079  // Older (<= 9.*) Intel RST driver
3080  ports_used |= (1 << i);
3081  else
3082  ports_used |= (1 << pe.bPortIdentifier);
3083  }
3084 
3085  return ports_used;
3086 }
3087 
3088 
3090 {
3091  CSMI_SAS_PHY_INFO phy_info;
3092  if (!get_phy_info(phy_info))
3093  return false;
3094 
3095  // Find port
3096  int max_port = -1, port_index = -1;
3097  for (unsigned i = 0; i < sizeof(phy_info.Phy) / sizeof(phy_info.Phy[0]); i++) {
3098  const CSMI_SAS_PHY_ENTITY & pe = phy_info.Phy[i];
3100  continue;
3101 
3102  if (pe.bPortIdentifier == 0xff) {
3103  // Older (<= 9.*) Intel RST driver
3104  max_port = phy_info.bNumberOfPhys - 1;
3105  if (i >= phy_info.bNumberOfPhys)
3106  break;
3107  if ((int)i != port)
3108  continue;
3109  }
3110  else {
3111  if (pe.bPortIdentifier > max_port)
3112  max_port = pe.bPortIdentifier;
3113  if (pe.bPortIdentifier != port)
3114  continue;
3115  }
3116 
3117  port_index = i;
3118  break;
3119  }
3120 
3121  if (port_index < 0) {
3122  if (port <= max_port)
3123  return set_err(ENOENT, "Port %d is disabled", port);
3124  else
3125  return set_err(ENOENT, "Port %d does not exist (#ports: %d)", port,
3126  max_port + 1);
3127  }
3128 
3129  const CSMI_SAS_PHY_ENTITY & phy_ent = phy_info.Phy[port_index];
3131  return set_err(ENOENT, "No device on port %d", port);
3132 
3133  switch (phy_ent.Attached.bTargetPortProtocol) {
3135  case CSMI_SAS_PROTOCOL_STP:
3136  break;
3137  default:
3138  return set_err(ENOENT, "No SATA device on port %d (protocol: %d)",
3139  port, phy_ent.Attached.bTargetPortProtocol);
3140  }
3141 
3142  m_phy_ent = phy_ent;
3143  return true;
3144 }
3145 
3146 
3148 {
3149  if (!ata_cmd_is_supported(in,
3154  "CMSI")
3155  )
3156  return false;
3157 
3158  // Create buffer with appropriate size
3159  raw_buffer pthru_raw_buf(sizeof(CSMI_SAS_STP_PASSTHRU_BUFFER) + in.size);
3160  CSMI_SAS_STP_PASSTHRU_BUFFER * pthru_buf = (CSMI_SAS_STP_PASSTHRU_BUFFER *)pthru_raw_buf.data();
3161 
3162  // Set addresses from Phy info
3163  CSMI_SAS_STP_PASSTHRU & pthru = pthru_buf->Parameters;
3164  const CSMI_SAS_PHY_ENTITY & phy_ent = get_phy_ent();
3165  pthru.bPhyIdentifier = phy_ent.Identify.bPhyIdentifier;
3166  pthru.bPortIdentifier = phy_ent.bPortIdentifier;
3167  memcpy(pthru.bDestinationSASAddress, phy_ent.Attached.bSASAddress,
3168  sizeof(pthru.bDestinationSASAddress));
3170 
3171  // Set transfer mode
3172  switch (in.direction) {
3173  case ata_cmd_in::no_data:
3175  break;
3176  case ata_cmd_in::data_in:
3178  pthru.uDataLength = in.size;
3179  break;
3180  case ata_cmd_in::data_out:
3182  pthru.uDataLength = in.size;
3183  memcpy(pthru_buf->bDataBuffer, in.buffer, in.size);
3184  break;
3185  default:
3186  return set_err(EINVAL, "csmi_ata_device::ata_pass_through: invalid direction=%d",
3187  (int)in.direction);
3188  }
3189 
3190  // Set host-to-device FIS
3191  {
3192  unsigned char * fis = pthru.bCommandFIS;
3193  const ata_in_regs & lo = in.in_regs;
3194  const ata_in_regs & hi = in.in_regs.prev;
3195  fis[ 0] = 0x27; // Type: host-to-device FIS
3196  fis[ 1] = 0x80; // Bit7: Update command register
3197  fis[ 2] = lo.command;
3198  fis[ 3] = lo.features;
3199  fis[ 4] = lo.lba_low;
3200  fis[ 5] = lo.lba_mid;
3201  fis[ 6] = lo.lba_high;
3202  fis[ 7] = lo.device;
3203  fis[ 8] = hi.lba_low;
3204  fis[ 9] = hi.lba_mid;
3205  fis[10] = hi.lba_high;
3206  fis[11] = hi.features;
3207  fis[12] = lo.sector_count;
3208  fis[13] = hi.sector_count;
3209  }
3210 
3211  // Call ioctl
3212  if (!csmi_ioctl(CC_CSMI_SAS_STP_PASSTHRU, &pthru_buf->IoctlHeader, pthru_raw_buf.size())) {
3213  return false;
3214  }
3215 
3216  // Get device-to-host FIS
3217  {
3218  const unsigned char * fis = pthru_buf->Status.bStatusFIS;
3219  ata_out_regs & lo = out.out_regs;
3220  lo.status = fis[ 2];
3221  lo.error = fis[ 3];
3222  lo.lba_low = fis[ 4];
3223  lo.lba_mid = fis[ 5];
3224  lo.lba_high = fis[ 6];
3225  lo.device = fis[ 7];
3226  lo.sector_count = fis[12];
3227  if (in.in_regs.is_48bit_cmd()) {
3228  ata_out_regs & hi = out.out_regs.prev;
3229  hi.lba_low = fis[ 8];
3230  hi.lba_mid = fis[ 9];
3231  hi.lba_high = fis[10];
3232  hi.sector_count = fis[13];
3233  }
3234  }
3235 
3236  // Get data
3237  if (in.direction == ata_cmd_in::data_in)
3238  // TODO: Check ptru_buf->Status.uDataBytes
3239  memcpy(in.buffer, pthru_buf->bDataBuffer, in.size);
3240 
3241  return true;
3242 }
3243 
3244 
3245 //////////////////////////////////////////////////////////////////////
3246 // win_csmi_device
3247 
3249  const char * req_type)
3250 : smart_device(intf, dev_name, "ata", req_type),
3251  m_fh(INVALID_HANDLE_VALUE), m_port(-1)
3252 {
3253 }
3254 
3256 {
3257  if (m_fh != INVALID_HANDLE_VALUE)
3258  CloseHandle(m_fh);
3259 }
3260 
3262 {
3263  return (m_fh != INVALID_HANDLE_VALUE);
3264 }
3265 
3267 {
3268  if (m_fh == INVALID_HANDLE_VALUE)
3269  return true;
3270  BOOL rc = CloseHandle(m_fh);
3271  m_fh = INVALID_HANDLE_VALUE;
3272  return !!rc;
3273 }
3274 
3275 
3277 {
3278  // Parse name
3279  unsigned contr_no = ~0, port = ~0; int nc = -1;
3280  const char * name = skipdev(get_dev_name());
3281  if (!( sscanf(name, "csmi%u,%u%n", &contr_no, &port, &nc) >= 0
3282  && nc == (int)strlen(name) && contr_no <= 9 && port < 32) )
3283  return set_err(EINVAL);
3284 
3285  // Open controller handle
3286  char devpath[30];
3287  snprintf(devpath, sizeof(devpath)-1, "\\\\.\\Scsi%u:", contr_no);
3288 
3289  HANDLE h = CreateFileA(devpath, GENERIC_READ|GENERIC_WRITE,
3290  FILE_SHARE_READ|FILE_SHARE_WRITE,
3291  (SECURITY_ATTRIBUTES *)0, OPEN_EXISTING, 0, 0);
3292 
3293  if (h == INVALID_HANDLE_VALUE) {
3294  long err = GetLastError();
3295  if (err == ERROR_FILE_NOT_FOUND)
3296  set_err(ENOENT, "%s: not found", devpath);
3297  else if (err == ERROR_ACCESS_DENIED)
3298  set_err(EACCES, "%s: access denied", devpath);
3299  else
3300  set_err(EIO, "%s: Error=%ld", devpath, err);
3301  return false;
3302  }
3303 
3304  if (scsi_debugmode > 1)
3305  pout(" %s: successfully opened\n", devpath);
3306 
3307  m_fh = h;
3308  m_port = port;
3309  return true;
3310 }
3311 
3312 
3314 {
3315  if (!open_scsi())
3316  return false;
3317 
3318  // Get Phy info for this drive
3319  if (!select_port(m_port)) {
3320  close();
3321  return false;
3322  }
3323 
3324  return true;
3325 }
3326 
3327 
3328 bool win_csmi_device::csmi_ioctl(unsigned code, IOCTL_HEADER * csmi_buffer,
3329  unsigned csmi_bufsiz)
3330 {
3331  // Determine signature
3332  const char * sig;
3333  switch (code) {
3334  case CC_CSMI_SAS_GET_DRIVER_INFO:
3335  sig = CSMI_ALL_SIGNATURE; break;
3336  case CC_CSMI_SAS_GET_PHY_INFO:
3337  case CC_CSMI_SAS_STP_PASSTHRU:
3338  sig = CSMI_SAS_SIGNATURE; break;
3339  default:
3340  return set_err(ENOSYS, "Unknown CSMI code=%u", code);
3341  }
3342 
3343  // Set header
3344  csmi_buffer->HeaderLength = sizeof(IOCTL_HEADER);
3345  strncpy((char *)csmi_buffer->Signature, sig, sizeof(csmi_buffer->Signature));
3346  csmi_buffer->Timeout = CSMI_SAS_TIMEOUT;
3347  csmi_buffer->ControlCode = code;
3348  csmi_buffer->ReturnCode = 0;
3349  csmi_buffer->Length = csmi_bufsiz - sizeof(IOCTL_HEADER);
3350 
3351  // Call function
3352  DWORD num_out = 0;
3353  if (!DeviceIoControl(m_fh, IOCTL_SCSI_MINIPORT,
3354  csmi_buffer, csmi_bufsiz, csmi_buffer, csmi_bufsiz, &num_out, (OVERLAPPED*)0)) {
3355  long err = GetLastError();
3356  if (scsi_debugmode)
3357  pout(" IOCTL_SCSI_MINIPORT(CC_CSMI_%u) failed, Error=%ld\n", code, err);
3358  if ( err == ERROR_INVALID_FUNCTION
3359  || err == ERROR_NOT_SUPPORTED
3360  || err == ERROR_DEV_NOT_EXIST)
3361  return set_err(ENOSYS, "CSMI is not supported (Error=%ld)", err);
3362  else
3363  return set_err(EIO, "CSMI(%u) failed with Error=%ld", code, err);
3364  }
3365 
3366  // Check result
3367  if (csmi_buffer->ReturnCode) {
3368  if (scsi_debugmode) {
3369  pout(" IOCTL_SCSI_MINIPORT(CC_CSMI_%u) failed, ReturnCode=%u\n",
3370  code, (unsigned)csmi_buffer->ReturnCode);
3371  }
3372  return set_err(EIO, "CSMI(%u) failed with ReturnCode=%u", code, (unsigned)csmi_buffer->ReturnCode);
3373  }
3374 
3375  if (scsi_debugmode > 1)
3376  pout(" IOCTL_SCSI_MINIPORT(CC_CSMI_%u) succeeded, bytes returned: %u\n", code, (unsigned)num_out);
3377 
3378  return true;
3379 }
3380 
3381 
3382 /////////////////////////////////////////////////////////////////////////////
3383 // SPT Interface (for SCSI devices and ATA devices behind SATLs)
3384 // Only supported in NT and later
3385 /////////////////////////////////////////////////////////////////////////////
3386 
3388  const char * dev_name, const char * req_type)
3389 : smart_device(intf, dev_name, "scsi", req_type)
3390 {
3391 }
3392 
3394 {
3395  const char * name = skipdev(get_dev_name()); int len = strlen(name);
3396  // sd[a-z]([a-z])?,N => Physical drive 0-701, RAID port N
3397  char drive[2+1] = ""; int sub_addr = -1; int n1 = -1; int n2 = -1;
3398  if ( sscanf(name, "sd%2[a-z]%n,%d%n", drive, &n1, &sub_addr, &n2) >= 1
3399  && ((n1 == len && sub_addr == -1) || (n2 == len && sub_addr >= 0)) ) {
3400  return open(sdxy_to_phydrive(drive), -1, -1, sub_addr);
3401  }
3402  // pd<m>,N => Physical drive <m>, RAID port N
3403  int pd_num = -1; sub_addr = -1; n1 = -1; n2 = -1;
3404  if ( sscanf(name, "pd%d%n,%d%n", &pd_num, &n1, &sub_addr, &n2) >= 1
3405  && pd_num >= 0 && ((n1 == len && sub_addr == -1) || (n2 == len && sub_addr >= 0))) {
3406  return open(pd_num, -1, -1, sub_addr);
3407  }
3408  // [a-zA-Z]: => Physical drive behind logical drive 0-25
3409  int logdrive = drive_letter(name);
3410  if (logdrive >= 0) {
3411  return open(-1, logdrive, -1, -1);
3412  }
3413  // n?st<m> => tape drive <m> (same names used in Cygwin's /dev emulation)
3414  int tape_num = -1; n1 = -1;
3415  if (sscanf(name, "st%d%n", &tape_num, &n1) == 1 && tape_num >= 0 && n1 == len) {
3416  return open(-1, -1, tape_num, -1);
3417  }
3418  tape_num = -1; n1 = -1;
3419  if (sscanf(name, "nst%d%n", &tape_num, &n1) == 1 && tape_num >= 0 && n1 == len) {
3420  return open(-1, -1, tape_num, -1);
3421  }
3422  // tape<m> => tape drive <m>
3423  tape_num = -1; n1 = -1;
3424  if (sscanf(name, "tape%d%n", &tape_num, &n1) == 1 && tape_num >= 0 && n1 == len) {
3425  return open(-1, -1, tape_num, -1);
3426  }
3427 
3428  return set_err(EINVAL);
3429 }
3430 
3431 bool win_scsi_device::open(int pd_num, int ld_num, int tape_num, int /*sub_addr*/)
3432 {
3433  char b[128];
3434  b[sizeof(b) - 1] = '\0';
3435  if (pd_num >= 0)
3436  snprintf(b, sizeof(b) - 1, "\\\\.\\PhysicalDrive%d", pd_num);
3437  else if (ld_num >= 0)
3438  snprintf(b, sizeof(b) - 1, "\\\\.\\%c:", 'A' + ld_num);
3439  else if (tape_num >= 0)
3440  snprintf(b, sizeof(b) - 1, "\\\\.\\TAPE%d", tape_num);
3441  else {
3442  set_err(EINVAL);
3443  return false;
3444  }
3445 
3446  // Open device
3447  HANDLE h = CreateFileA(b, GENERIC_READ|GENERIC_WRITE,
3448  FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
3449  OPEN_EXISTING, 0, 0);
3450  if (h == INVALID_HANDLE_VALUE) {
3451  set_err(ENODEV, "%s: Open failed, Error=%u", b, (unsigned)GetLastError());
3452  return false;
3453  }
3454  set_fh(h);
3455  return true;
3456 }
3457 
3458 
3459 typedef struct {
3460  SCSI_PASS_THROUGH_DIRECT spt;
3461  ULONG Filler;
3462  UCHAR ucSenseBuf[64];
3464 
3465 
3466 // Issue command via IOCTL_SCSI_PASS_THROUGH instead of *_DIRECT.
3467 // Used if DataTransferLength not supported by *_DIRECT.
3468 static long scsi_pass_through_indirect(HANDLE h,
3470 {
3471  struct SCSI_PASS_THROUGH_WITH_BUFFERS {
3472  SCSI_PASS_THROUGH spt;
3473  ULONG Filler;
3474  UCHAR ucSenseBuf[sizeof(sbd->ucSenseBuf)];
3475  UCHAR ucDataBuf[512];
3476  };
3477 
3478  SCSI_PASS_THROUGH_WITH_BUFFERS sb;
3479  memset(&sb, 0, sizeof(sb));
3480 
3481  // DATA_OUT not implemented yet
3482  if (!( sbd->spt.DataIn == SCSI_IOCTL_DATA_IN
3483  && sbd->spt.DataTransferLength <= sizeof(sb.ucDataBuf)))
3484  return ERROR_INVALID_PARAMETER;
3485 
3486  sb.spt.Length = sizeof(sb.spt);
3487  sb.spt.CdbLength = sbd->spt.CdbLength;
3488  memcpy(sb.spt.Cdb, sbd->spt.Cdb, sizeof(sb.spt.Cdb));
3489  sb.spt.SenseInfoLength = sizeof(sb.ucSenseBuf);
3490  sb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucSenseBuf);
3491  sb.spt.DataIn = sbd->spt.DataIn;
3492  sb.spt.DataTransferLength = sbd->spt.DataTransferLength;
3493  sb.spt.DataBufferOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucDataBuf);
3494  sb.spt.TimeOutValue = sbd->spt.TimeOutValue;
3495 
3496  DWORD num_out;
3497  if (!DeviceIoControl(h, IOCTL_SCSI_PASS_THROUGH,
3498  &sb, sizeof(sb), &sb, sizeof(sb), &num_out, 0))
3499  return GetLastError();
3500 
3501  sbd->spt.ScsiStatus = sb.spt.ScsiStatus;
3502  if (sb.spt.ScsiStatus & SCSI_STATUS_CHECK_CONDITION)
3503  memcpy(sbd->ucSenseBuf, sb.ucSenseBuf, sizeof(sbd->ucSenseBuf));
3504 
3505  sbd->spt.DataTransferLength = sb.spt.DataTransferLength;
3506  if (sbd->spt.DataIn == SCSI_IOCTL_DATA_IN && sb.spt.DataTransferLength > 0)
3507  memcpy(sbd->spt.DataBuffer, sb.ucDataBuf, sb.spt.DataTransferLength);
3508  return 0;
3509 }
3510 
3511 
3512 // Interface to SPT SCSI devices. See scsicmds.h and os_linux.c
3514 {
3515  int report = scsi_debugmode; // TODO
3516 
3517  if (report > 0) {
3518  int k, j;
3519  const unsigned char * ucp = iop->cmnd;
3520  const char * np;
3521  char buff[256];
3522  const int sz = (int)sizeof(buff);
3523 
3524  np = scsi_get_opcode_name(ucp[0]);
3525  j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");
3526  for (k = 0; k < (int)iop->cmnd_len; ++k)
3527  j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]);
3528  if ((report > 1) &&
3529  (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
3530  int trunc = (iop->dxfer_len > 256) ? 1 : 0;
3531 
3532  j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n Outgoing "
3533  "data, len=%d%s:\n", (int)iop->dxfer_len,
3534  (trunc ? " [only first 256 bytes shown]" : ""));
3535  dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
3536  }
3537  else
3538  j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");
3539  pout("%s", buff);
3540  }
3541 
3543  if (iop->cmnd_len > (int)sizeof(sb.spt.Cdb)) {
3544  set_err(EINVAL, "cmnd_len too large");
3545  return false;
3546  }
3547 
3548  memset(&sb, 0, sizeof(sb));
3549  sb.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
3550  sb.spt.CdbLength = iop->cmnd_len;
3551  memcpy(sb.spt.Cdb, iop->cmnd, iop->cmnd_len);
3552  sb.spt.SenseInfoLength = sizeof(sb.ucSenseBuf);
3553  sb.spt.SenseInfoOffset =
3554  offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf);
3555  sb.spt.TimeOutValue = (iop->timeout ? iop->timeout : 60);
3556 
3557  bool direct = true;
3558  switch (iop->dxfer_dir) {
3559  case DXFER_NONE:
3560  sb.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED;
3561  break;
3562  case DXFER_FROM_DEVICE:
3563  sb.spt.DataIn = SCSI_IOCTL_DATA_IN;
3564  sb.spt.DataTransferLength = iop->dxfer_len;
3565  sb.spt.DataBuffer = iop->dxferp;
3566  // IOCTL_SCSI_PASS_THROUGH_DIRECT does not support single byte
3567  // transfers (needed for SMART STATUS check of JMicron USB bridges)
3568  if (sb.spt.DataTransferLength == 1)
3569  direct = false;
3570  break;
3571  case DXFER_TO_DEVICE:
3572  sb.spt.DataIn = SCSI_IOCTL_DATA_OUT;
3573  sb.spt.DataTransferLength = iop->dxfer_len;
3574  sb.spt.DataBuffer = iop->dxferp;
3575  break;
3576  default:
3577  set_err(EINVAL, "bad dxfer_dir");
3578  return false;
3579  }
3580 
3581  long err = 0;
3582  if (direct) {
3583  DWORD num_out;
3584  if (!DeviceIoControl(get_fh(), IOCTL_SCSI_PASS_THROUGH_DIRECT,
3585  &sb, sizeof(sb), &sb, sizeof(sb), &num_out, 0))
3586  err = GetLastError();
3587  }
3588  else
3589  err = scsi_pass_through_indirect(get_fh(), &sb);
3590 
3591  if (err)
3592  return set_err((err == ERROR_INVALID_FUNCTION ? ENOSYS : EIO),
3593  "IOCTL_SCSI_PASS_THROUGH%s failed, Error=%ld",
3594  (direct ? "_DIRECT" : ""), err);
3595 
3596  iop->scsi_status = sb.spt.ScsiStatus;
3598  int slen = sb.ucSenseBuf[7] + 8;
3599 
3600  if (slen > (int)sizeof(sb.ucSenseBuf))
3601  slen = sizeof(sb.ucSenseBuf);
3602  if (slen > (int)iop->max_sense_len)
3603  slen = iop->max_sense_len;
3604  memcpy(iop->sensep, sb.ucSenseBuf, slen);
3605  iop->resp_sense_len = slen;
3606  if (report) {
3607  if (report > 1) {
3608  pout(" >>> Sense buffer, len=%d:\n", slen);
3609  dStrHex(iop->sensep, slen , 1);
3610  }
3611  if ((iop->sensep[0] & 0x7f) > 0x71)
3612  pout(" status=%x: [desc] sense_key=%x asc=%x ascq=%x\n",
3613  iop->scsi_status, iop->sensep[1] & 0xf,
3614  iop->sensep[2], iop->sensep[3]);
3615  else
3616  pout(" status=%x: sense_key=%x asc=%x ascq=%x\n",
3617  iop->scsi_status, iop->sensep[2] & 0xf,
3618  iop->sensep[12], iop->sensep[13]);
3619  }
3620  } else
3621  iop->resp_sense_len = 0;
3622 
3623  if (iop->dxfer_len > sb.spt.DataTransferLength)
3624  iop->resid = iop->dxfer_len - sb.spt.DataTransferLength;
3625  else
3626  iop->resid = 0;
3627 
3628  if ((iop->dxfer_dir == DXFER_FROM_DEVICE) && (report > 1)) {
3629  int trunc = (iop->dxfer_len > 256) ? 1 : 0;
3630  pout(" Incoming data, len=%d, resid=%d%s:\n", (int)iop->dxfer_len, iop->resid,
3631  (trunc ? " [only first 256 bytes shown]" : ""));
3632  dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
3633  }
3634  return true;
3635 }
3636 
3637 // Interface to SPT SCSI devices. See scsicmds.h and os_linux.c
3638 static long scsi_pass_through_direct(HANDLE fd, UCHAR targetid, struct scsi_cmnd_io * iop)
3639 {
3640  int report = scsi_debugmode; // TODO
3641 
3642  if (report > 0) {
3643  int k, j;
3644  const unsigned char * ucp = iop->cmnd;
3645  const char * np;
3646  char buff[256];
3647  const int sz = (int)sizeof(buff);
3648 
3649  np = scsi_get_opcode_name(ucp[0]);
3650  j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");
3651  for (k = 0; k < (int)iop->cmnd_len; ++k)
3652  j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]);
3653  if ((report > 1) &&
3654  (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
3655  int trunc = (iop->dxfer_len > 256) ? 1 : 0;
3656 
3657  j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n Outgoing "
3658  "data, len=%d%s:\n", (int)iop->dxfer_len,
3659  (trunc ? " [only first 256 bytes shown]" : ""));
3660  dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
3661  }
3662  else
3663  j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");
3664  pout("%s", buff);
3665  }
3666 
3668  if (iop->cmnd_len > (int)sizeof(sb.spt.Cdb)) {
3669  return EINVAL;
3670  }
3671 
3672  memset(&sb, 0, sizeof(sb));
3673  sb.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
3674  //sb.spt.PathId = 0;
3675  sb.spt.TargetId = targetid;
3676  //sb.spt.Lun = 0;
3677  sb.spt.CdbLength = iop->cmnd_len;
3678  memcpy(sb.spt.Cdb, iop->cmnd, iop->cmnd_len);
3679  sb.spt.SenseInfoLength = sizeof(sb.ucSenseBuf);
3680  sb.spt.SenseInfoOffset =
3681  offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf);
3682  sb.spt.TimeOutValue = (iop->timeout ? iop->timeout : 60);
3683 
3684  bool direct = true;
3685  switch (iop->dxfer_dir) {
3686  case DXFER_NONE:
3687  sb.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED;
3688  break;
3689  case DXFER_FROM_DEVICE:
3690  sb.spt.DataIn = SCSI_IOCTL_DATA_IN;
3691  sb.spt.DataTransferLength = iop->dxfer_len;
3692  sb.spt.DataBuffer = iop->dxferp;
3693  // IOCTL_SCSI_PASS_THROUGH_DIRECT does not support single byte
3694  // transfers (needed for SMART STATUS check of JMicron USB bridges)
3695  if (sb.spt.DataTransferLength == 1)
3696  direct = false;
3697  break;
3698  case DXFER_TO_DEVICE:
3699  sb.spt.DataIn = SCSI_IOCTL_DATA_OUT;
3700  sb.spt.DataTransferLength = iop->dxfer_len;
3701  sb.spt.DataBuffer = iop->dxferp;
3702  break;
3703  default:
3704  return EINVAL;
3705  }
3706 
3707  long err = 0;
3708  if (direct) {
3709  DWORD num_out;
3710  if (!DeviceIoControl(fd, IOCTL_SCSI_PASS_THROUGH_DIRECT,
3711  &sb, sizeof(sb), &sb, sizeof(sb), &num_out, 0))
3712  err = GetLastError();
3713  }
3714  else
3715  err = scsi_pass_through_indirect(fd, &sb);
3716 
3717  if (err)
3718  {
3719  return err;
3720  }
3721 
3722  iop->scsi_status = sb.spt.ScsiStatus;
3724  int slen = sb.ucSenseBuf[7] + 8;
3725 
3726  if (slen > (int)sizeof(sb.ucSenseBuf))
3727  slen = sizeof(sb.ucSenseBuf);
3728  if (slen > (int)iop->max_sense_len)
3729  slen = iop->max_sense_len;
3730  memcpy(iop->sensep, sb.ucSenseBuf, slen);
3731  iop->resp_sense_len = slen;
3732  if (report) {
3733  if (report > 1) {
3734  pout(" >>> Sense buffer, len=%d:\n", slen);
3735  dStrHex(iop->sensep, slen , 1);
3736  }
3737  if ((iop->sensep[0] & 0x7f) > 0x71)
3738  pout(" status=%x: [desc] sense_key=%x asc=%x ascq=%x\n",
3739  iop->scsi_status, iop->sensep[1] & 0xf,
3740  iop->sensep[2], iop->sensep[3]);
3741  else
3742  pout(" status=%x: sense_key=%x asc=%x ascq=%x\n",
3743  iop->scsi_status, iop->sensep[2] & 0xf,
3744  iop->sensep[12], iop->sensep[13]);
3745  }
3746  } else
3747  iop->resp_sense_len = 0;
3748 
3749  if (iop->dxfer_len > sb.spt.DataTransferLength)
3750  iop->resid = iop->dxfer_len - sb.spt.DataTransferLength;
3751  else
3752  iop->resid = 0;
3753 
3754  if ((iop->dxfer_dir == DXFER_FROM_DEVICE) && (report > 1)) {
3755  int trunc = (iop->dxfer_len > 256) ? 1 : 0;
3756  pout(" Incoming data, len=%d, resid=%d%s:\n", (int)iop->dxfer_len, iop->resid,
3757  (trunc ? " [only first 256 bytes shown]" : ""));
3758  dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
3759  }
3760 
3761  return 0;
3762 }
3763 
3764 // Areca RAID Controller(SAS Device)
3765 win_areca_scsi_device::win_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
3766 : smart_device(intf, dev_name, "areca", "areca")
3767 {
3768  set_fh(INVALID_HANDLE_VALUE);
3769  set_disknum(disknum);
3770  set_encnum(encnum);
3771  set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
3772 }
3773 
3775 {
3776  HANDLE hFh;
3777 
3778  if( is_open() )
3779  {
3780  return true;
3781  }
3782  hFh = CreateFile( get_dev_name(),
3783  GENERIC_READ|GENERIC_WRITE,
3784  FILE_SHARE_READ|FILE_SHARE_WRITE,
3785  NULL,
3786  OPEN_EXISTING,
3787  0,
3788  NULL );
3789  if(hFh == INVALID_HANDLE_VALUE)
3790  {
3791  return false;
3792  }
3793 
3794  set_fh(hFh);
3795  return true;
3796 }
3797 
3799 {
3800  return this;
3801 }
3802 
3804 {
3805  int ioctlreturn = 0;
3806 
3807  ioctlreturn = scsi_pass_through_direct(get_fh(), 16, iop);
3808  if ( ioctlreturn || iop->scsi_status )
3809  {
3810  ioctlreturn = scsi_pass_through_direct(get_fh(), 127, iop);
3811  if ( ioctlreturn || iop->scsi_status )
3812  {
3813  // errors found
3814  return -1;
3815  }
3816  }
3817 
3818  return ioctlreturn;
3819 }
3820 
3822 {
3823 #define SYNCOBJNAME "Global\\SynIoctlMutex"
3824  int ctlrnum = -1;
3825  char mutexstr[64];
3826 
3827  if (sscanf(get_dev_name(), "\\\\.\\scsi%d:", &ctlrnum) < 1)
3828  return set_err(EINVAL, "unable to parse device name");
3829 
3830  snprintf(mutexstr, sizeof(mutexstr), "%s%d", SYNCOBJNAME, ctlrnum);
3831  m_mutex = CreateMutex(NULL, FALSE, mutexstr);
3832  if ( m_mutex == NULL )
3833  {
3834  return set_err(EIO, "CreateMutex failed");
3835  }
3836 
3837  // atomic access to driver
3838  WaitForSingleObject(m_mutex, INFINITE);
3839 
3840  return true;
3841 }
3842 
3843 
3845 {
3846  if( m_mutex != NULL)
3847  {
3848  ReleaseMutex(m_mutex);
3849  CloseHandle(m_mutex);
3850  }
3851 
3852  return true;
3853 }
3854 
3855 
3856 // Areca RAID Controller(SATA Disk)
3857 win_areca_ata_device::win_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
3858 : smart_device(intf, dev_name, "areca", "areca")
3859 {
3860  set_fh(INVALID_HANDLE_VALUE);
3861  set_disknum(disknum);
3862  set_encnum(encnum);
3863  set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
3864 }
3865 
3867 {
3868  HANDLE hFh;
3869 
3870  if( is_open() )
3871  {
3872  return true;
3873  }
3874  hFh = CreateFile( get_dev_name(),
3875  GENERIC_READ|GENERIC_WRITE,
3876  FILE_SHARE_READ|FILE_SHARE_WRITE,
3877  NULL,
3878  OPEN_EXISTING,
3879  0,
3880  NULL );
3881  if(hFh == INVALID_HANDLE_VALUE)
3882  {
3883  return false;
3884  }
3885 
3886  set_fh(hFh);
3887  return true;
3888 }
3889 
3891 {
3892  int is_ata = 1;
3893 
3894  // autodetect device type
3895  is_ata = arcmsr_get_dev_type();
3896  if(is_ata < 0)
3897  {
3898  set_err(EIO);
3899  return this;
3900  }
3901 
3902  if(is_ata == 1)
3903  {
3904  // SATA device
3905  return this;
3906  }
3907 
3908  // SAS device
3910  close();
3911  delete this;
3912  newdev->open(); // TODO: Can possibly pass open fd
3913 
3914  return newdev.release();
3915 }
3916 
3918 {
3919  int ioctlreturn = 0;
3920 
3921  ioctlreturn = scsi_pass_through_direct(get_fh(), 16, iop);
3922  if ( ioctlreturn || iop->scsi_status )
3923  {
3924  ioctlreturn = scsi_pass_through_direct(get_fh(), 127, iop);
3925  if ( ioctlreturn || iop->scsi_status )
3926  {
3927  // errors found
3928  return -1;
3929  }
3930  }
3931 
3932  return ioctlreturn;
3933 }
3934 
3936 {
3937 #define SYNCOBJNAME "Global\\SynIoctlMutex"
3938  int ctlrnum = -1;
3939  char mutexstr[64];
3940 
3941  if (sscanf(get_dev_name(), "\\\\.\\scsi%d:", &ctlrnum) < 1)
3942  return set_err(EINVAL, "unable to parse device name");
3943 
3944  snprintf(mutexstr, sizeof(mutexstr), "%s%d", SYNCOBJNAME, ctlrnum);
3945  m_mutex = CreateMutex(NULL, FALSE, mutexstr);
3946  if ( m_mutex == NULL )
3947  {
3948  return set_err(EIO, "CreateMutex failed");
3949  }
3950 
3951  // atomic access to driver
3952  WaitForSingleObject(m_mutex, INFINITE);
3953 
3954  return true;
3955 }
3956 
3957 
3959 {
3960  if( m_mutex != NULL)
3961  {
3962  ReleaseMutex(m_mutex);
3963  CloseHandle(m_mutex);
3964  }
3965 
3966  return true;
3967 }
3968 
3969 // AACRAID
3971  const char *dev_name, unsigned ctrnum, unsigned target, unsigned lun)
3972 : smart_device(intf, dev_name, "aacraid", "aacraid"),
3973  m_ctrnum(ctrnum), m_lun(lun), m_target(target)
3974 {
3975  set_info().info_name = strprintf("%s [aacraid_disk_%02d_%02d_%d]", dev_name, m_ctrnum, m_lun, m_target);
3976  set_info().dev_type = strprintf("aacraid,%d,%d,%d", m_ctrnum, m_lun, m_target);
3977 }
3978 
3980 {
3981 }
3982 
3984 {
3985  if (is_open())
3986  return true;
3987 
3988  HANDLE hFh = CreateFile( get_dev_name(),
3989  GENERIC_READ|GENERIC_WRITE,
3990  FILE_SHARE_READ|FILE_SHARE_WRITE,
3991  NULL,
3992  OPEN_EXISTING,
3993  0,
3994  0);
3995  if (hFh == INVALID_HANDLE_VALUE)
3996  return set_err(ENODEV, "Open failed, Error=%u", (unsigned)GetLastError());
3997 
3998  set_fh(hFh);
3999  return true;
4000 }
4001 
4003 {
4004  int report = scsi_debugmode;
4005  if (report > 0)
4006  {
4007  int k, j;
4008  const unsigned char * ucp = iop->cmnd;
4009  const char * np;
4010  char buff[256];
4011  const int sz = (int)sizeof(buff);
4012  np = scsi_get_opcode_name(ucp[0]);
4013  j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");
4014  for (k = 0; k < (int)iop->cmnd_len; ++k)
4015  j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]);
4016  if ((report > 1) &&
4017  (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
4018  int trunc = (iop->dxfer_len > 256) ? 1 : 0;
4019 
4020  j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n Outgoing "
4021  "data, len=%d%s:\n", (int)iop->dxfer_len,
4022  (trunc ? " [only first 256 bytes shown]" : ""));
4023  dStrHex((const char *)iop->dxferp,
4024  (trunc ? 256 : (int)iop->dxfer_len) , 1);
4025  }
4026  else
4027  j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");
4028  pout("buff %s\n",buff);
4029  }
4030 
4031  char ioBuffer[1000];
4032  SRB_IO_CONTROL * pSrbIO = (SRB_IO_CONTROL *) ioBuffer;
4033  SCSI_REQUEST_BLOCK * pScsiIO = (SCSI_REQUEST_BLOCK *) (ioBuffer + sizeof(SRB_IO_CONTROL));
4034  DWORD scsiRequestBlockSize = sizeof(SCSI_REQUEST_BLOCK);
4035  char *pRequestSenseIO = (char *) (ioBuffer + sizeof(SRB_IO_CONTROL) + scsiRequestBlockSize);
4036  DWORD dataOffset = (sizeof(SRB_IO_CONTROL) + scsiRequestBlockSize + 7) & 0xfffffff8;
4037  char *pDataIO = (char *) (ioBuffer + dataOffset);
4038  memset(pScsiIO, 0, scsiRequestBlockSize);
4039  pScsiIO->Length = (USHORT) scsiRequestBlockSize;
4040  pScsiIO->Function = SRB_FUNCTION_EXECUTE_SCSI;
4041  pScsiIO->PathId = 0;
4042  pScsiIO->TargetId = m_target;
4043  pScsiIO->Lun = m_lun;
4044  pScsiIO->CdbLength = (int)iop->cmnd_len;
4045  switch(iop->dxfer_dir){
4046  case DXFER_NONE:
4047  pScsiIO->SrbFlags = SRB_NoDataXfer;
4048  break;
4049  case DXFER_FROM_DEVICE:
4050  pScsiIO->SrbFlags |= SRB_DataIn;
4051  break;
4052  case DXFER_TO_DEVICE:
4053  pScsiIO->SrbFlags |= SRB_DataOut;
4054  break;
4055  default:
4056  pout("aacraid: bad dxfer_dir\n");
4057  return set_err(EINVAL, "aacraid: bad dxfer_dir\n");
4058  }
4059  pScsiIO->DataTransferLength = (ULONG)iop->dxfer_len;
4060  pScsiIO->TimeOutValue = iop->timeout;
4061  UCHAR *pCdb = (UCHAR *) pScsiIO->Cdb;
4062  memcpy(pCdb, iop->cmnd, 16);
4063  if (iop->max_sense_len){
4064  memset(pRequestSenseIO, 0, iop->max_sense_len);
4065  }
4066  if (pScsiIO->SrbFlags & SRB_FLAGS_DATA_OUT){
4067  memcpy(pDataIO, iop->dxferp, iop->dxfer_len);
4068  }
4069  else if (pScsiIO->SrbFlags & SRB_FLAGS_DATA_IN){
4070  memset(pDataIO, 0, iop->dxfer_len);
4071  }
4072 
4073  DWORD bytesReturned = 0;
4074  memset(pSrbIO, 0, sizeof(SRB_IO_CONTROL));
4075  pSrbIO->HeaderLength = sizeof(SRB_IO_CONTROL);
4076  memcpy(pSrbIO->Signature, "AACAPI", 7);
4077  pSrbIO->ControlCode = ARCIOCTL_SEND_RAW_SRB;
4078  pSrbIO->Length = (dataOffset + iop->dxfer_len - sizeof(SRB_IO_CONTROL) + 7) & 0xfffffff8;
4079  pSrbIO->Timeout = 3*60;
4080 
4081  if (!DeviceIoControl(
4082  get_fh(),
4083  IOCTL_SCSI_MINIPORT,
4084  ioBuffer,
4085  sizeof(SRB_IO_CONTROL) + pSrbIO->Length,
4086  ioBuffer,
4087  sizeof(SRB_IO_CONTROL) + pSrbIO->Length,
4088  &bytesReturned,
4089  NULL)
4090  ) {
4091  return set_err(EIO, "ARCIOCTL_SEND_RAW_SRB failed, Error=%u", (unsigned)GetLastError());
4092  }
4093 
4094  iop->scsi_status = pScsiIO->ScsiStatus;
4096  int slen = sizeof(pRequestSenseIO) + 8;
4097  if (slen > (int)sizeof(pRequestSenseIO))
4098  slen = sizeof(pRequestSenseIO);
4099  if (slen > (int)iop->max_sense_len)
4100  slen = (int)iop->max_sense_len;
4101  memcpy(iop->sensep, pRequestSenseIO, slen);
4102  iop->resp_sense_len = slen;
4103  if (report) {
4104  if (report > 1) {
4105  pout(" >>> Sense buffer, len=%d:\n", slen);
4106  dStrHex(iop->sensep, slen , 1);
4107  }
4108  if ((iop->sensep[0] & 0x7f) > 0x71)
4109  pout(" status=%x: [desc] sense_key=%x asc=%x ascq=%x\n",
4110  iop->scsi_status, iop->sensep[1] & 0xf,
4111  iop->sensep[2], iop->sensep[3]);
4112  else
4113  pout(" status=%x: sense_key=%x asc=%x ascq=%x\n",
4114  iop->scsi_status, iop->sensep[2] & 0xf,
4115  iop->sensep[12], iop->sensep[13]);
4116  }
4117  }
4118  else {
4119  iop->resp_sense_len = 0;
4120  }
4121 
4122  if (iop->dxfer_dir == DXFER_FROM_DEVICE){
4123  memcpy(iop->dxferp,pDataIO, iop->dxfer_len);
4124  }
4125  if((iop->dxfer_dir == DXFER_FROM_DEVICE) && (report > 1)){
4126  int trunc = (iop->dxfer_len > 256) ? 1 : 0;
4127  pout(" Incoming data, len=%d, resid=%d%s:\n", (int)iop->dxfer_len, iop->resid,
4128  (trunc ? " [only first 256 bytes shown]" : ""));
4129  dStrHex((CHAR*)pDataIO, (trunc ? 256 : (int)(iop->dxfer_len)) , 1);
4130  }
4131  return true;
4132 }
4133 
4134 //////////////////////////////////////////////////////////////////////////////////////////////////
4135 
4136 
4137 } // namespace
4138 
4139 /////////////////////////////////////////////////////////////////////////////
4140 
4141 // Initialize platform interface and register with smi()
4142 void smart_interface::init()
4143 {
4144  {
4145  // Remove "." from DLL search path if supported
4146  // to prevent DLL preloading attacks
4147  BOOL (WINAPI * SetDllDirectoryA_p)(LPCSTR) = (BOOL (WINAPI *)(LPCSTR))
4148  GetProcAddress(GetModuleHandleA("kernel32.dll"), "SetDllDirectoryA");
4149  if (SetDllDirectoryA_p)
4150  SetDllDirectoryA_p("");
4151  }
4152 
4153  static os_win32::win_smart_interface the_win_interface;
4154  smart_interface::set(&the_win_interface);
4155 }
4156 
4157 
4158 #ifndef __CYGWIN__
4159 
4160 // Get exe directory
4161 // (prototype in utiliy.h)
4162 std::string get_exe_dir()
4163 {
4164  char path[MAX_PATH];
4165  // Get path of this exe
4166  if (!GetModuleFileNameA(GetModuleHandleA(0), path, sizeof(path)))
4167  throw std::runtime_error("GetModuleFileName() failed");
4168  // Replace backslash by slash
4169  int sl = -1;
4170  for (int i = 0; path[i]; i++)
4171  if (path[i] == '\\') {
4172  path[i] = '/'; sl = i;
4173  }
4174  // Remove filename
4175  if (sl >= 0)
4176  path[sl] = 0;
4177  return path;
4178 }
4179 
4180 #endif
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: aacraid.h:48
virtual bool open()
Open device, return false on error.
Definition: os_win32.cpp:3313
#define ATA_SMART_READ_LOG_SECTOR
Definition: atacmds.h:100
virtual int64_t get_timer_usec()
Get microseconds since some unspecified starting point.
#define ATA_SMART_WRITE_LOG_SECTOR
Definition: atacmds.h:101
virtual bool open()
Open device, return false on error.
Definition: os_win32.cpp:3983
#define CSMI_SAS_STP_UNSPECIFIED
Definition: csmisas.h:859
static const char * skipdev(const char *s)
Definition: os_win32.cpp:782
virtual bool ata_identify_is_cached() const
Return true if OS caches ATA identify sector.
Definition: os_win32.cpp:2995
UCHAR bReserved
Definition: os_os2.cpp:57
const CSMI_SAS_PHY_ENTITY & get_phy_ent() const
Get info for selected physical drive.
Definition: os_win32.cpp:438
#define IOCTL_SCSI_MINIPORT_READ_SMART_LOG
Definition: os_win32.cpp:216
u16 s[6]
Definition: megaraid.h:97
#define assert(x)
Definition: os_win32.cpp:46
virtual int64_t get_timer_usec()
Get microseconds since some unspecified starting point.
Definition: os_win32.cpp:727
virtual std::string get_valid_custom_dev_types_str()
Return valid 'type' args accepted by above.
Definition: os_win32.cpp:934
virtual bool csmi_ioctl(unsigned code, IOCTL_HEADER *csmi_buffer, unsigned csmi_bufsiz)
Call platform-specific CSMI ioctl.
Definition: os_win32.cpp:3328
u32 size
Definition: megaraid.h:79
#define SCSI_STATUS_CHECK_CONDITION
Definition: scsicmds.h:260
UINT8 * sensep
Definition: scsicmds.h:124
void set_disknum(int disknum)
Definition: dev_areca.h:125
UCHAR bSectorNumberReg
Definition: os_os2.cpp:52
_STORAGE_QUERY_TYPE
Definition: os_win32.cpp:248
virtual smart_device * get_custom_smart_device(const char *name, const char *type)
Return device for platform specific 'type'.
Definition: os_win32.cpp:839
virtual ata_device * get_sat_device(const char *type, scsi_device *scsidev)
Return ATA->SCSI filter for SAT or USB.
Definition: scsiata.cpp:1476
ata_in_regs prev
"previous content"
ata_identify_device m_ident_buf
Definition: os_win32.cpp:511
ata_register error
__u8 szDescription[81]
Definition: csmisas.h:1014
#define ATA_SMART_CMD
Definition: atacmds.h:75
static win_dev_type get_controller_type(HANDLE hdevice, bool admin, GETVERSIONINPARAMS_EX *ata_version_ex)
Definition: os_win32.cpp:2155
ata_register lba_mid
static bool is_wow64()
Definition: os_win32.cpp:621
static int update_3ware_devicemap_ioctl(HANDLE hdevice)
Definition: os_win32.cpp:1760
virtual bool is_open() const
Return true if device is open.
Definition: os_win32.cpp:1908
struct _SENDCMDINPARAMS_EX SENDCMDINPARAMS_EX
#define DXFER_FROM_DEVICE
Definition: scsicmds.h:113
bool str_starts_with(const char *str, const char *prefix)
Definition: utility.h:57
bool execute(const char *str, unsigned nmatch, regmatch_t *pmatch, int flags=0) const
Return true if substring matches pattern, fill regmatch_t array.
Definition: utility.h:278
#define CSMI_SAS_STP_READ
Definition: csmisas.h:857
virtual bool disable_system_auto_standby(bool disable)
Disable/Enable system auto standby/sleep mode.
Definition: os_win32.cpp:1183
Smart pointer class for device pointers.
unsigned size() const
Definition: utility.h:163
#define CSMI_SAS_SIGNATURE
Definition: csmisas.h:714
#define SRB_DataIn
Definition: aacraid.h:50
static long scsi_pass_through_direct(HANDLE fd, UCHAR targetid, struct scsi_cmnd_io *iop)
Definition: os_win32.cpp:3638
ULONG DataBufferSize
Definition: os_win32.cpp:144
ata_register device
const char * scsi_get_opcode_name(UINT8 opcode)
Definition: scsicmds.cpp:176
static int ide_pass_through_ioctl(HANDLE hdevice, IDEREGS *regs, char *data, unsigned datasize)
Definition: os_win32.cpp:1369
#define SYNCOBJNAME
int m_port
Port number.
Definition: os_win32.cpp:488
CSMI_SAS_IDENTIFY Attached
Definition: csmisas.h:1539
ata_register sector_count
ULONG_PTR DataBufferOffset
Definition: os_win32.cpp:171
#define CSMI_SAS_NO_DEVICE_ATTACHED
Definition: csmisas.h:725
#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTOSAVE
Definition: os_win32.cpp:212
unsigned timeout
Definition: scsicmds.h:127
#define ATA_SMART_DISABLE
Definition: atacmds.h:104
virtual bool close()
Close device, return false on error.
Definition: os_win32.cpp:3266
#define ARECA_MAX_CTLR_NUM
Adapter class to implement new ATA pass through old interface.
ATA Input registers (for 28-bit commands)
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out)
ATA pass through.
Definition: os_win32.cpp:2674
#define CSMI_SAS_TIMEOUT
Definition: csmisas.h:719
win_tw_cli_device(smart_interface *intf, const char *dev_name, const char *req_type)
Definition: os_win32.cpp:1899
#define ATA_SMART_AUTOSAVE
Definition: atacmds.h:97
virtual std::string get_os_version_str()
Return info string about build host and/or OS version.
Definition: os_win32.cpp:636
device_info & set_info()
R/W access to device info struct.
#define snprintf
Definition: utility.h:68
virtual int arcmsr_get_dev_type()
Definition: dev_areca.cpp:350
#define IOCTL_SCSI_MINIPORT_READ_SMART_ATTRIBS
Definition: os_win32.cpp:207
const char * os_win32_cpp_cvsid
Definition: os_win32.cpp:114
virtual bool is_open() const
Return true if device is open.
Definition: os_win32.cpp:3261
UCHAR bSectorCountReg
Definition: os_os2.cpp:51
void * buffer
Pointer to data buffer.
HANDLE get_fh() const
Return handle for derived classes.
Definition: os_win32.cpp:360
unsigned char ata_debugmode
Definition: atacmds.cpp:42
static int smart_get_version(HANDLE hdevice, GETVERSIONINPARAMS_EX *ata_version_ex=0)
Definition: os_win32.cpp:1231
virtual bool scsi_pass_through(scsi_cmnd_io *iop)
SCSI pass through.
Definition: os_win32.cpp:3513
size_t resp_sense_len
Definition: scsicmds.h:128
#define IOCTL_SCSI_MINIPORT_DISABLE_SMART
Definition: os_win32.cpp:210
UCHAR PreviousTaskFile[8]
Definition: os_win32.cpp:172
void push_back(smart_device *dev)
#define IOCTL_ATA_PASS_THROUGH
Definition: os_win32.cpp:158
#define ATA_IDENTIFY_DEVICE
Definition: atacmds.h:72
virtual ata_device * get_ata_device(const char *name, const char *type)
Return standard ATA device.
Definition: os_win32.cpp:787
ata_register lba_mid
virtual bool open()
Open device, return false on error.
Definition: os_win32.cpp:3393
bool get_phy_info(CSMI_SAS_PHY_INFO &phy_info)
Get phy info.
Definition: os_win32.cpp:3004
bool nonempty(const void *data, int size)
Definition: utility.cpp:695
struct _ATA_PASS_THROUGH_EX ATA_PASS_THROUGH_EX
#define ATA_IDENTIFY_PACKET_DEVICE
Definition: atacmds.h:73
win_csmi_device(smart_interface *intf, const char *dev_name, const char *req_type)
Definition: os_win32.cpp:3248
virtual std::string get_app_examples(const char *appname)
Return example string for program 'appname'.
Definition: os_win32.cpp:1147
struct _STORAGE_DEVICE_DESCRIPTOR STORAGE_DEVICE_DESCRIPTOR
bool ata_cmd_is_supported(const ata_cmd_in &in, unsigned flags, const char *type=0)
Check command input parameters.
#define SELECT_WIN_32_64(x32, x64)
Definition: os_win32.cpp:102
ata_in_regs_48bit in_regs
Input registers.
UINT8 * dxferp
Definition: scsicmds.h:122
std::string get_exe_dir()
Definition: os_win32.cpp:4162
Definition: scsiata.cpp:102
#define aacraid_MAX_CTLR_NUM
UCHAR DataBuffer[1]
Definition: os_win32.cpp:145
ata_out_regs_48bit out_regs
Output registers.
std::string dev_type
Actual device type.
Definition: dev_interface.h:53
UINT8 * cmnd
Definition: scsicmds.h:118
enum _STORAGE_PROPERTY_ID STORAGE_PROPERTY_ID
ptr_t data
Definition: megaraid.h:94
static int drive_letter(const char *s)
Definition: os_win32.cpp:772
static bool match(const char *pattern, const char *str)
static int run_cmd(const char *cmd, char *dataout, int outsize)
Definition: os_win32.cpp:1824
List of devices for DEVICESCAN.
enum ata_cmd_in::@27 direction
I/O direction.
device_type * release()
Return the pointer and release ownership.
#define ATA_CHECK_POWER_MODE
Definition: atacmds.h:71
ata_out_regs prev
read with HOB=1
struct _STORAGE_PROPERTY_QUERY STORAGE_PROPERTY_QUERY
struct _IDEREGS IDEREGS
static void init()
Initialize platform interface and register with smi().
Definition: dev_legacy.cpp:338
#define IOCTL_STORAGE_QUERY_PROPERTY
Definition: os_win32.cpp:229
The platform interface abstraction.
static const char * ata_get_def_options(void)
Definition: os_win32.cpp:2469
static int get_device_power_state(HANDLE hdevice)
Definition: os_win32.cpp:2446
CSMI_SAS_DRIVER_INFO Information
Definition: csmisas.h:1026
static bool is_sat(const STORAGE_DEVICE_DESCRIPTOR_DATA *data)
Definition: os_win32.cpp:2132
static void set(smart_interface *intf)
Set interface to use, must be called from init().
static int smart_ioctl(HANDLE hdevice, IDEREGS *regs, char *data, unsigned datasize, int port)
Definition: os_win32.cpp:1266
static int is_permissive()
Definition: os_win32.cpp:759
win_areca_ata_device(smart_interface *intf, const char *dev_name, int disknum, int encnum=1)
Definition: os_win32.cpp:3857
__u8 bDestinationSASAddress[8]
Definition: csmisas.h:1679
long long int64_t
Definition: int64.h:51
static win_dev_type get_phy_drive_type(int drive)
Definition: os_win32.cpp:2233
#define ATA_FLAGS_DATA_OUT
Definition: os_win32.cpp:178
static int ata_via_scsi_miniport_smart_ioctl(HANDLE hdevice, IDEREGS *regs, char *data, int datasize)
Definition: os_win32.cpp:1566
void dStrHex(const char *str, int len, int no_ascii)
Definition: scsicmds.cpp:91
unsigned char failuretest_permissive
Definition: smartctl.cpp:1114
#define CSMI_ALL_SIGNATURE
Definition: csmisas.h:403
UCHAR bDriveHeadReg
Definition: os_os2.cpp:55
unsigned char scsi_debugmode
Definition: scsicmds.cpp:56
#define IOCTL_SCSI_MINIPORT_ENABLE_SMART
Definition: os_win32.cpp:209
mega_passthru pthru
Definition: megaraid.h:93
bool is_ata() const
Return true if ATA device.
Definition: dev_interface.h:92
void pout(const char *fmt,...)
Definition: smartctl.cpp:1095
size_t max_sense_len
Definition: scsicmds.h:126
virtual bool close()
Close device, return false on error.
Definition: os_win32.cpp:2489
static bool get_usb_id(int drive, unsigned short &vendor_id, unsigned short &product_id)
Definition: os_win32.cpp:2318
HANDLE m_fh
Controller device handle.
Definition: os_win32.cpp:487
unsigned char fw_rev[8]
Definition: atacmds.h:133
ptr_t buffer
Definition: megaraid.h:89
#define CSMI_SAS_PROTOCOL_SATA
Definition: csmisas.h:733
#define SRB_DataOut
Definition: aacraid.h:51
#define ASSERT_CONST(c, n)
Definition: os_win32.cpp:96
UCHAR bCommandReg
Definition: os_os2.cpp:56
ata_register status
int dxfer_dir
Definition: scsicmds.h:120
IOCTL_HEADER IoctlHeader
Definition: csmisas.h:1551
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
#define IOCTL_IDE_PASS_THROUGH
Definition: os_win32.cpp:135
virtual int ata_command_interface(smart_command_set command, int select, char *data)
Old ATA interface called by ata_pass_through()
Definition: os_win32.cpp:2025
#define ATA_SMART_READ_VALUES
Definition: atacmds.h:95
void set_encnum(int encnum)
Definition: dev_areca.h:128
unsigned size
Size of buffer.
static int sdxy_to_phydrive(const char(&xy)[2+1])
Definition: os_win32.cpp:802
Wrapper class for regex(3).
Definition: utility.h:235
win_areca_scsi_device(smart_interface *intf, const char *dev_name, int disknum, int encnum=1)
Definition: os_win32.cpp:3765
ata_register lba_low
virtual bool open()
Open device, return false on error.
Definition: os_win32.cpp:1914
SCSI device access.
Definition: atacmds.h:55
ata_register features
u8 b[12]
Definition: megaraid.h:96
#define DXFER_NONE
Definition: scsicmds.h:112
#define IOCTL_SCSI_MINIPORT_IDENTIFY
Definition: os_win32.cpp:206
#define SRB_NoDataXfer
Definition: aacraid.h:52
#define ATA_SMART_AUTO_OFFLINE
Definition: atacmds.h:108
CSMI_SAS_IDENTIFY Identify
Definition: csmisas.h:1530
static int storage_predict_failure_ioctl(HANDLE hdevice, char *data=0)
Definition: os_win32.cpp:2100
virtual bool scan_smart_devices(smart_device_list &devlist, const char *type, const char *pattern=0)
Fill 'devlist' with devices of some 'type' with device names specified by some optional 'pattern'...
Definition: os_win32.cpp:985
smart_command_set
Definition: atacmds.h:48
virtual smart_device * autodetect_open()
Open device with autodetection support.
Definition: os_win32.cpp:3890
#define CSMI_SAS_PROTOCOL_STP
Definition: csmisas.h:735
u32 w[3]
Definition: megaraid.h:98
UCHAR bCylLowReg
Definition: os_os2.cpp:53
#define DXFER_TO_DEVICE
Definition: scsicmds.h:114
virtual bool is_open() const
Return true if device is open.
Definition: os_win32.cpp:2484
STORAGE_BUS_TYPE BusType
Definition: os_win32.cpp:243
virtual bool arcmsr_probe()
Definition: dev_areca.cpp:264
#define ATA_SMART_READ_THRESHOLDS
Definition: atacmds.h:96
bool is_48bit_cmd() const
Return true if 48-bit command.
virtual scsi_device * get_scsi_device(const char *name, const char *type)
Return standard SCSI device.
Definition: os_win32.cpp:797
virtual const char * get_usb_dev_type_by_id(int vendor_id, int product_id, int version=-1)
Get type name for USB device with known VENDOR:PRODUCT ID.
Definition: scsiata.cpp:1572
#define ASSERT_SIZEOF(t, n)
Definition: os_win32.cpp:98
u8 lun
Definition: megaraid.h:86
enum _STORAGE_QUERY_TYPE STORAGE_QUERY_TYPE
ata_register device
Base class for all devices.
Definition: dev_interface.h:38
virtual smart_device * autodetect_open()
Open device with autodetection support.
Definition: os_win32.cpp:3798
ata_register lba_high
#define CSMI_SAS_LINK_RATE_NEGOTIATED
Definition: csmisas.h:804
#define IOCTL_SCSI_MINIPORT_WRITE_SMART_LOG
Definition: os_win32.cpp:217
bool select_port(int port)
Select physical drive.
Definition: os_win32.cpp:3089
static win_dev_type get_log_drive_type(int drive)
Definition: os_win32.cpp:2239
#define IOCTL_SCSI_MINIPORT_RETURN_STATUS
Definition: os_win32.cpp:211
size_t cmnd_len
Definition: scsicmds.h:119
UCHAR bFeaturesReg
Definition: os_os2.cpp:50
ATA device access.
ata_register sector_count
#define ATA_SMART_IMMEDIATE_OFFLINE
Definition: atacmds.h:99
#define ATA_FLAGS_48BIT_COMMAND
Definition: os_win32.cpp:179
win_aacraid_device(smart_interface *intf, const char *dev_name, unsigned int ctrnum, unsigned int target, unsigned int lun)
Definition: os_win32.cpp:3970
static int storage_query_property_ioctl(HANDLE hdevice, STORAGE_DEVICE_DESCRIPTOR_DATA *data)
Definition: os_win32.cpp:2062
unsigned char serial_no[20]
Definition: atacmds.h:131
STORAGE_QUERY_TYPE QueryType
Definition: os_win32.cpp:267
unsigned char * data()
Definition: utility.h:166
unsigned long long uint64_t
Definition: int64.h:54
__u8 bTargetPortProtocol
Definition: csmisas.h:1520
_STORAGE_PROPERTY_ID
Definition: os_win32.cpp:255
static bool is_intel_raid_volume(const STORAGE_DEVICE_DESCRIPTOR_DATA *data)
Definition: os_win32.cpp:2142
virtual bool open()
Open device, return false on error.
Definition: os_win32.cpp:2519
UCHAR CurrentTaskFile[8]
Definition: os_win32.cpp:173
static int ata_pass_through_ioctl(HANDLE hdevice, IDEREGS *regs, IDEREGS *prev_regs, char *data, int datasize)
Definition: os_win32.cpp:1454
CSMI_SAS_STP_PASSTHRU_STATUS Status
Definition: csmisas.h:1699
ata_register command
__u8 bSASAddress[8]
Definition: csmisas.h:1522
static long scsi_pass_through_indirect(HANDLE h, SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER *sbd)
Definition: os_win32.cpp:3468
static const char * findstr(const char *str, const char *sub)
Definition: os_win32.cpp:1878
HANDLE m_fh
File handle.
Definition: os_win32.cpp:364
UINT8 scsi_status
Definition: scsicmds.h:129
Areca RAID support.
Definition: os_win32.cpp:549
UCHAR bCylHighReg
Definition: os_os2.cpp:54
ata_smart_values m_smart_buf
Definition: os_win32.cpp:512
ATA pass through input parameters.
static int get_clipboard(char *data, int datasize)
Definition: os_win32.cpp:1801
#define CSMI_SAS_STP_WRITE
Definition: csmisas.h:858
static win_dev_type get_dev_type(const char *name, int &phydrive)
Definition: os_win32.cpp:810
STORAGE_PROPERTY_ID PropertyId
Definition: os_win32.cpp:266
#define ATA_SMART_ENABLE
Definition: atacmds.h:103
CSMI_SAS_STP_PASSTHRU Parameters
Definition: csmisas.h:1698
CSMI_SAS_PHY_INFO Information
Definition: csmisas.h:1552
virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io *iop)
Definition: os_win32.cpp:3917
virtual bool close()
Close device, return false on error.
Definition: os_win32.cpp:2018
#define SMART_VENDOR_3WARE
Definition: os_win32.cpp:286
virtual bool csmi_ioctl(unsigned code, IOCTL_HEADER *csmi_buffer, unsigned csmi_bufsiz)=0
Call platform-specific CSMI ioctl.
std::string strprintf(const char *fmt,...)
Definition: utility.cpp:787
UCHAR AdditionalParameters[1]
Definition: os_win32.cpp:268
STORAGE_DEVICE_DESCRIPTOR desc
Definition: os_win32.cpp:2055
virtual bool scsi_pass_through(struct scsi_cmnd_io *iop)
SCSI pass through.
Definition: os_win32.cpp:4002
static bool get_serial_from_wmi(int drive, ata_identify_device *id)
Definition: os_win32.cpp:2289
#define CSMI_SAS_STP_PIO
Definition: csmisas.h:860
#define IOCTL_SCSI_MINIPORT_READ_SMART_THRESHOLDS
Definition: os_win32.cpp:208
ata_register lba_low
unsigned char model[40]
Definition: atacmds.h:134
virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io *iop)
Definition: os_win32.cpp:3803
#define IOCTL_SCSI_MINIPORT_ENABLE_DISABLE_AUTO_OFFLINE
Definition: os_win32.cpp:215
static void copy_swapped(unsigned char *dest, const char *src, int destsize)
Definition: os_win32.cpp:1885
#define ATA_FLAGS_DATA_IN
Definition: os_win32.cpp:177
static int get_identify_from_device_property(HANDLE hdevice, ata_identify_device *id)
Definition: os_win32.cpp:2247
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out)
ATA pass through.
Definition: os_win32.cpp:3147
ata_register lba_high
struct _GETVERSIONINPARAMS_EX GETVERSIONINPARAMS_EX
u8 cmd
Definition: megaraid.h:80
smart_interface * smi()
Get interface which produced this object.
unsigned get_ports_used()
Get bitmask of used ports.
Definition: os_win32.cpp:3057
CSMI_SAS_PHY_ENTITY Phy[32]
Definition: csmisas.h:1546
size_t dxfer_len
Definition: scsicmds.h:123
const char * get_dev_name() const
Get device (path)name.
Definition: atacmds.h:50
std::string info_name
Informal name.
Definition: dev_interface.h:52
win_scsi_device(smart_interface *intf, const char *dev_name, const char *req_type)
Definition: os_win32.cpp:3387
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
static int ata_via_3ware_miniport_ioctl(HANDLE hdevice, IDEREGS *regs, char *data, int datasize, int port)
Definition: os_win32.cpp:1697
ATA Output registers (for 28-bit commands)
static void print_ide_regs(const IDEREGS *r, int out)
Definition: os_win32.cpp:1212
virtual bool open()
Open device, return false on error.
Definition: os_win32.cpp:3774
static void print_ide_regs_io(const IDEREGS *ri, const IDEREGS *ro)
Definition: os_win32.cpp:1219
win_ata_device(smart_interface *intf, const char *dev_name, const char *req_type)
Definition: os_win32.cpp:2500
virtual bool open()
Open device, return false on error.
Definition: os_win32.cpp:3866
ATA pass through output parameters.
void set_fh(HANDLE fh)
Set handle for open() in derived classes.
Definition: os_win32.cpp:356
CSMI_SAS_PHY_ENTITY m_phy_ent
CSMI info for this phy.
Definition: os_win32.cpp:446
#define IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS
Definition: os_win32.cpp:214
virtual smart_device * autodetect_smart_device(const char *name)
Autodetect device if no device type specified.
Definition: os_win32.cpp:940
#define ATA_SMART_STATUS
Definition: atacmds.h:105