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