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