4 * Home page of code is: http://smartmontools.sourceforge.net
6 * Copyright (C) 2004-6 Christian Franke <smartmontools-support@lists.sourceforge.net>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
13 * You should have received a copy of the GNU General Public License
14 * (for example COPYING); if not, write to the Free
15 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 extern smartmonctrl
* con
; // con->permissive,reportataioctl
26 extern int64_t bytes
; // malloc() byte count
32 #define assert(x) /**/
34 #define WIN32_LEAN_AND_MEAN
36 #include <stddef.h> // offsetof()
37 #include <io.h> // access()
39 #define ARGUSED(x) ((void)(x))
41 // Macro to check constants at compile time using a dummy typedef
42 #define ASSERT_CONST(c, n) \
43 typedef char assert_const_##c[((c) == (n)) ? 1 : -1]
44 #define ASSERT_SIZEOF(t, n) \
45 typedef char assert_sizeof_##t[(sizeof(t) == (n)) ? 1 : -1]
48 // Needed by '-V' option (CVS versioning) of smartd/smartctl
49 const char *os_XXXX_c_cvsid
="$Id: os_win32.cpp,v 1.42 2006/09/27 21:42:03 chrfranke Exp $"
50 ATACMDS_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID
;
53 #ifndef HAVE_GET_OS_VERSION_STR
54 #error define of HAVE_GET_OS_VERSION_STR missing in config.h
57 // Return build host and OS version as static string
58 const char * get_os_version_str()
60 static char vstr
[sizeof(SMARTMONTOOLS_BUILD_HOST
)-3-1+sizeof("-2003r2-sp2.1")+13];
61 char * const vptr
= vstr
+sizeof(SMARTMONTOOLS_BUILD_HOST
)-3-1;
62 const int vlen
= sizeof(vstr
)-(sizeof(SMARTMONTOOLS_BUILD_HOST
)-3);
67 // remove "-pc" to avoid long lines
68 assert(!strncmp(SMARTMONTOOLS_BUILD_HOST
+5, "pc-", 3));
69 strcpy(vstr
, "i686-"); strcpy(vstr
+5, SMARTMONTOOLS_BUILD_HOST
+5+3);
70 assert(vptr
== vstr
+strlen(vstr
) && vptr
+vlen
+1 == vstr
+sizeof(vstr
));
72 memset(&vi
, 0, sizeof(vi
));
73 vi
.dwOSVersionInfoSize
= sizeof(vi
);
74 if (!GetVersionExA((OSVERSIONINFOA
*)&vi
)) {
75 memset(&vi
, 0, sizeof(vi
));
76 vi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
77 if (!GetVersionExA((OSVERSIONINFOA
*)&vi
))
81 if (vi
.dwPlatformId
> 0xff || vi
.dwMajorVersion
> 0xff || vi
.dwMinorVersion
> 0xff)
84 switch (vi
.dwPlatformId
<< 16 | vi
.dwMajorVersion
<< 8 | vi
.dwMinorVersion
) {
85 case VER_PLATFORM_WIN32_WINDOWS
<<16|0x0400| 0:
86 w
= (vi
.szCSDVersion
[1] == 'B' ||
87 vi
.szCSDVersion
[1] == 'C' ? "95-osr2" : "95"); break;
88 case VER_PLATFORM_WIN32_WINDOWS
<<16|0x0400|10:
89 w
= (vi
.szCSDVersion
[1] == 'A' ? "98se" : "98"); break;
90 case VER_PLATFORM_WIN32_WINDOWS
<<16|0x0400|90: w
= "me"; break;
91 //case VER_PLATFORM_WIN32_NT <<16|0x0300|51: w = "nt3.51"; break;
92 case VER_PLATFORM_WIN32_NT
<<16|0x0400| 0: w
= "nt4"; break;
93 case VER_PLATFORM_WIN32_NT
<<16|0x0500| 0: w
= "2000"; break;
94 case VER_PLATFORM_WIN32_NT
<<16|0x0500| 1:
95 w
= (!GetSystemMetrics(87/*SM_MEDIACENTER*/) ? "xp"
97 case VER_PLATFORM_WIN32_NT
<<16|0x0500| 2:
98 w
= (!GetSystemMetrics(89/*SM_SERVERR2*/) ? "2003"
100 case VER_PLATFORM_WIN32_NT
<<16|0x0600| 0: w
= "vista"; break;
101 default: w
= 0; break;
105 snprintf(vptr
, vlen
, "-%s%lu.%lu",
106 (vi
.dwPlatformId
==VER_PLATFORM_WIN32_NT
? "nt" : "9x"),
107 vi
.dwMajorVersion
, vi
.dwMinorVersion
);
108 else if (vi
.wServicePackMinor
)
109 snprintf(vptr
, vlen
, "-%s-sp%u.%u", w
, vi
.wServicePackMajor
, vi
.wServicePackMinor
);
110 else if (vi
.wServicePackMajor
)
111 snprintf(vptr
, vlen
, "-%s-sp%u", w
, vi
.wServicePackMajor
);
113 snprintf(vptr
, vlen
, "-%s", w
);
118 static int ata_open(int drive
, const char * options
, int port
);
119 static void ata_close(int fd
);
120 static int ata_scan(unsigned long * drives
, int * rdriveno
, unsigned long * rdrives
);
121 static const char * ata_get_def_options(void);
123 static int aspi_open(unsigned adapter
, unsigned id
);
124 static void aspi_close(int fd
);
125 static int aspi_scan(unsigned long * drives
);
128 static int is_permissive()
130 if (!con
->permissive
) {
131 pout("To continue, add one or more '-T permissive' options.\n");
138 static const char * skipdev(const char * s
)
140 return (!strncmp(s
, "/dev/", 5) ? s
+ 5 : s
);
144 // tries to guess device type given the name (a path). See utility.h
145 // for return values.
146 int guess_device_type (const char * dev_name
)
148 dev_name
= skipdev(dev_name
);
149 if (!strncmp(dev_name
, "hd", 2))
150 return CONTROLLER_ATA
;
151 if (!strncmp(dev_name
, "scsi", 4))
152 return CONTROLLER_SCSI
;
153 return CONTROLLER_UNKNOWN
;
157 // makes a list of ATA or SCSI devices for the DEVICESCAN directive of
158 // smartd. Returns number N of devices, or -1 if out of
159 // memory. Allocates N+1 arrays: one of N pointers (devlist), the
160 // others each contain null-terminated character strings.
161 int make_device_names (char*** devlist
, const char* type
)
163 unsigned long drives
[3];
165 unsigned long rdrives
[2];
166 int i
, j
, n
, nmax
, sz
;
169 drives
[0] = drives
[1] = drives
[2] = 0;
170 rdriveno
[0] = rdriveno
[1] = -1;
171 rdrives
[0] = rdrives
[1] = 0;
173 if (!strcmp(type
, "ATA")) {
174 // bit i set => drive i present
175 n
= ata_scan(drives
, rdriveno
, rdrives
);
179 else if (!strcmp(type
, "SCSI")) {
180 // bit i set => drive with ID (i & 0x7) on adapter (i >> 3) present
181 n
= aspi_scan(drives
);
182 path
= "/dev/scsi00";
192 sz
= n
* sizeof(char **);
193 *devlist
= (char **)malloc(sz
); bytes
+= sz
;
196 for (i
= j
= 0; i
< n
; ) {
197 while (j
< nmax
&& !(drives
[j
>> 5] & (1L << (j
& 0x1f))))
201 if (j
== rdriveno
[0] || j
== rdriveno
[1]) {
202 // Add physical drives behind this logical drive
203 int ci
= (j
== rdriveno
[0] ? 0 : 1);
204 for (int pi
= 0; pi
< 32 && i
< n
; pi
++) {
205 if (!(rdrives
[ci
] & (1L << pi
)))
208 sprintf(rpath
, "/dev/hd%c,%u", 'a'+j
, pi
);
209 sz
= strlen(rpath
)+1;
210 char * s
= (char *)malloc(sz
); bytes
+= sz
;
217 char * s
= (char *)malloc(sz
); bytes
+= sz
;
222 s
[sz
-2] += j
; // /dev/hd[a-j]
225 assert((j
>> 3) <= 9);
226 s
[sz
-3] += (j
>> 3); // /dev/scsi[0-9].....
227 s
[sz
-2] += (j
& 0x7); // .....[0-7]
238 // Like open(). Return positive integer handle, only used by
239 // functions below. type="ATA" or "SCSI". If you need to store extra
240 // information about your devices, create a private internal array
241 // within this file (see os_freebsd.cpp for an example).
242 int deviceopen(const char * pathname
, char *type
)
245 pathname
= skipdev(pathname
);
246 len
= strlen(pathname
);
248 if (!strcmp(type
, "ATA")) {
249 // hd[a-j](:[saic]+)? => ATA 0-9 with options
250 char drive
[1+1] = "", options
[5+1] = ""; int n1
= -1, n2
= -1;
251 if ( sscanf(pathname
, "hd%1[a-j]%n:%5[saicp]%n", drive
, &n1
, options
, &n2
) >= 1
252 && ((n1
== len
&& !options
[0]) || n2
== len
) ) {
253 return ata_open(drive
[0] - 'a', options
, -1);
255 // hd[a-j],N => Physical drive 0-9, RAID port N
256 drive
[0] = 0; options
[0] = 0; n1
= -1; n2
= -1;
258 if ( sscanf(pathname
, "hd%1[a-j],%u%n:%5[saicp]%n", drive
, &port
, &n1
, options
, &n2
) >= 2
259 && port
< 32 && ((n1
== len
&& !options
[0]) || n2
== len
) ) {
260 return ata_open(drive
[0] - 'a', options
, port
);
264 else if (!strcmp(type
, "SCSI")) {
265 // scsi[0-9][0-f] => SCSI Adapter 0-9, ID 0-15, LUN 0
266 unsigned adapter
= ~0, id
= ~0; int n
= -1;
267 if (sscanf(pathname
,"scsi%1u%1x%n", &adapter
, &id
, &n
) == 2 && n
== len
) {
268 return aspi_open(adapter
, id
);
277 // Like close(). Acts only on handles returned by above function.
278 // (Never called in smartctl!)
279 int deviceclose(int fd
)
281 if ((fd
& 0xff00) != 0x0100) {
291 // print examples for smartctl
292 void print_smartctl_examples(){
293 printf("=================================================== SMARTCTL EXAMPLES =====\n\n"
294 " smartctl -a /dev/hda (Prints all SMART information)\n\n"
295 #ifdef HAVE_GETOPT_LONG
296 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/hda\n"
297 " (Enables SMART on first disk)\n\n"
298 " smartctl -t long /dev/hda (Executes extended disk self-test)\n\n"
299 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/hda\n"
300 " (Prints Self-Test & Attribute errors)\n"
302 " smartctl -s on -o on -S on /dev/hda (Enables SMART on first disk)\n"
303 " smartctl -t long /dev/hda (Executes extended disk self-test)\n"
304 " smartctl -A -l selftest -q errorsonly /dev/hda\n"
305 " (Prints Self-Test & Attribute errors)\n"
307 " smartctl -a /dev/scsi21\n"
308 " (Prints all information for SCSI disk on ASPI adapter 2, ID 1)\n"
309 " smartctl -A /dev/hdb,3\n"
310 " (Prints Attributes for physical drive 3 on 3ware 9000 RAID)\n"
312 " ATA SMART access methods and ordering may be specified by modifiers\n"
313 " following the device name: /dev/hdX:[saic], where\n"
314 " 's': SMART_* IOCTLs, 'a': IOCTL_ATA_PASS_THROUGH,\n"
315 " 'i': IOCTL_IDE_PASS_THROUGH, 'c': ATA via IOCTL_SCSI_PASS_THROUGH.\n"
316 " The default on this system is /dev/hdX:%s\n", ata_get_def_options()
321 /////////////////////////////////////////////////////////////////////////////
323 /////////////////////////////////////////////////////////////////////////////
325 // SMART_* IOCTLs, also known as DFP_* (Disk Fault Protection)
327 // Deklarations from:
328 // http://cvs.sourceforge.net/viewcvs.py/mingw/w32api/include/ddk/ntdddisk.h?rev=1.3
330 #define FILE_READ_ACCESS 0x0001
331 #define FILE_WRITE_ACCESS 0x0002
332 #define METHOD_BUFFERED 0
333 #define CTL_CODE(DeviceType, Function, Method, Access) (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
335 #define FILE_DEVICE_DISK 7
336 #define IOCTL_DISK_BASE FILE_DEVICE_DISK
338 #define SMART_GET_VERSION \
339 CTL_CODE(IOCTL_DISK_BASE, 0x0020, METHOD_BUFFERED, FILE_READ_ACCESS)
341 #define SMART_SEND_DRIVE_COMMAND \
342 CTL_CODE(IOCTL_DISK_BASE, 0x0021, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
344 #define SMART_RCV_DRIVE_DATA \
345 CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
347 ASSERT_CONST(SMART_GET_VERSION
, 0x074080);
348 ASSERT_CONST(SMART_SEND_DRIVE_COMMAND
, 0x07c084);
349 ASSERT_CONST(SMART_RCV_DRIVE_DATA
, 0x07c088);
351 #define SMART_CYL_LOW 0x4F
352 #define SMART_CYL_HI 0xC2
357 typedef struct _GETVERSIONOUTPARAMS
{
364 } GETVERSIONOUTPARAMS
, *PGETVERSIONOUTPARAMS
, *LPGETVERSIONOUTPARAMS
;
366 ASSERT_SIZEOF(GETVERSIONOUTPARAMS
, 24);
369 #define SMART_VENDOR_3WARE 0x13C1 // identifies 3ware specific parameters
371 typedef struct _GETVERSIONINPARAMS_EX
{
377 DWORD dwDeviceMapEx
; // 3ware specific: RAID drive bit map
378 WORD wIdentifier
; // Vendor specific identifier
379 WORD wControllerId
; // 3ware specific: Controller ID (0,1,...)
381 } GETVERSIONINPARAMS_EX
, *PGETVERSIONINPARAMS_EX
, *LPGETVERSIONINPARAMS_EX
;
383 ASSERT_SIZEOF(GETVERSIONINPARAMS_EX
, sizeof(GETVERSIONOUTPARAMS
));
386 typedef struct _IDEREGS
{
388 UCHAR bSectorCountReg
;
389 UCHAR bSectorNumberReg
;
395 } IDEREGS
, *PIDEREGS
, *LPIDEREGS
;
397 typedef struct _SENDCMDINPARAMS
{
404 } SENDCMDINPARAMS
, *PSENDCMDINPARAMS
, *LPSENDCMDINPARAMS
;
406 ASSERT_SIZEOF(SENDCMDINPARAMS
, 32+1);
408 typedef struct _SENDCMDINPARAMS_EX
{
412 BYTE bPortNumber
; // 3ware specific: port number
413 WORD wIdentifier
; // Vendor specific identifier
416 } SENDCMDINPARAMS_EX
, *PSENDCMDINPARAMS_EX
, *LPSENDCMDINPARAMS_EX
;
418 ASSERT_SIZEOF(SENDCMDINPARAMS_EX
, sizeof(SENDCMDINPARAMS
));
421 /* DRIVERSTATUS.bDriverError constants (just for info, not used)
422 #define SMART_NO_ERROR 0
423 #define SMART_IDE_ERROR 1
424 #define SMART_INVALID_FLAG 2
425 #define SMART_INVALID_COMMAND 3
426 #define SMART_INVALID_BUFFER 4
427 #define SMART_INVALID_DRIVE 5
428 #define SMART_INVALID_IOCTL 6
429 #define SMART_ERROR_NO_MEM 7
430 #define SMART_INVALID_REGISTER 8
431 #define SMART_NOT_SUPPORTED 9
432 #define SMART_NO_IDE_DEVICE 10
435 typedef struct _DRIVERSTATUS
{
440 } DRIVERSTATUS
, *PDRIVERSTATUS
, *LPDRIVERSTATUS
;
442 typedef struct _SENDCMDOUTPARAMS
{
444 DRIVERSTATUS DriverStatus
;
446 } SENDCMDOUTPARAMS
, *PSENDCMDOUTPARAMS
, *LPSENDCMDOUTPARAMS
;
448 ASSERT_SIZEOF(SENDCMDOUTPARAMS
, 16+1);
453 /////////////////////////////////////////////////////////////////////////////
455 static void print_ide_regs(const IDEREGS
* r
, int out
)
457 pout("%s=0x%02x,%s=0x%02x, SC=0x%02x, NS=0x%02x, CL=0x%02x, CH=0x%02x, SEL=0x%02x\n",
458 (out
?"STS":"CMD"), r
->bCommandReg
, (out
?"ERR":" FR"), r
->bFeaturesReg
,
459 r
->bSectorCountReg
, r
->bSectorNumberReg
, r
->bCylLowReg
, r
->bCylHighReg
, r
->bDriveHeadReg
);
462 static void print_ide_regs_io(const IDEREGS
* ri
, const IDEREGS
* ro
)
464 pout(" Input : "); print_ide_regs(ri
, 0);
466 pout(" Output: "); print_ide_regs(ro
, 1);
470 /////////////////////////////////////////////////////////////////////////////
472 // call SMART_GET_VERSION, return device map or -1 on error
474 static int smart_get_version(HANDLE hdevice
, unsigned long * portmap
= 0)
476 GETVERSIONOUTPARAMS vers
;
477 const GETVERSIONINPARAMS_EX
& vers_ex
= (const GETVERSIONINPARAMS_EX
&)vers
;
480 memset(&vers
, 0, sizeof(vers
));
481 if (!DeviceIoControl(hdevice
, SMART_GET_VERSION
,
482 NULL
, 0, &vers
, sizeof(vers
), &num_out
, NULL
)) {
483 if (con
->reportataioctl
)
484 pout(" SMART_GET_VERSION failed, Error=%ld\n", GetLastError());
488 assert(num_out
== sizeof(GETVERSIONOUTPARAMS
));
491 // Return bitmask of valid RAID ports
492 if (vers_ex
.wIdentifier
!= SMART_VENDOR_3WARE
) {
493 pout(" SMART_GET_VERSION returns unknown Identifier = %04x\n"
494 " This is no 3ware 9000 controller or driver has no SMART support.\n", vers_ex
.wIdentifier
);
498 *portmap
= vers_ex
.dwDeviceMapEx
;
501 if (con
->reportataioctl
> 1) {
502 pout(" SMART_GET_VERSION suceeded, bytes returned: %lu\n"
503 " Vers = %d.%d, Caps = 0x%lx, DeviceMap = 0x%02x\n",
504 num_out
, vers
.bVersion
, vers
.bRevision
,
505 vers
.fCapabilities
, vers
.bIDEDeviceMap
);
506 if (vers_ex
.wIdentifier
== SMART_VENDOR_3WARE
)
507 pout(" Identifier = %04x(3WARE), ControllerId=%u, DeviceMapEx = 0x%08lx\n",
508 vers_ex
.wIdentifier
, vers_ex
.wControllerId
, vers_ex
.dwDeviceMapEx
);
511 // TODO: Check vers.fCapabilities here?
512 return vers
.bIDEDeviceMap
;
516 // call SMART_* ioctl
518 static int smart_ioctl(HANDLE hdevice
, int drive
, IDEREGS
* regs
, char * data
, unsigned datasize
, int port
)
520 SENDCMDINPARAMS inpar
;
521 SENDCMDINPARAMS_EX
& inpar_ex
= (SENDCMDINPARAMS_EX
&)inpar
;
523 unsigned char outbuf
[sizeof(SENDCMDOUTPARAMS
)-1 + 512];
524 const SENDCMDOUTPARAMS
* outpar
;
526 unsigned int size_out
;
529 memset(&inpar
, 0, sizeof(inpar
));
530 inpar
.irDriveRegs
= *regs
;
531 // drive is set to 0-3 on Win9x only
532 inpar
.irDriveRegs
.bDriveHeadReg
= 0xA0 | ((drive
& 1) << 4);
533 inpar
.bDriveNumber
= drive
;
537 inpar_ex
.wIdentifier
= SMART_VENDOR_3WARE
;
538 inpar_ex
.bPortNumber
= port
;
541 assert(datasize
== 0 || datasize
== 512);
543 code
= SMART_RCV_DRIVE_DATA
; name
= "SMART_RCV_DRIVE_DATA";
544 inpar
.cBufferSize
= size_out
= 512;
547 code
= SMART_SEND_DRIVE_COMMAND
; name
= "SMART_SEND_DRIVE_COMMAND";
548 if (regs
->bFeaturesReg
== ATA_SMART_STATUS
) {
549 size_out
= sizeof(IDEREGS
); // ioctl returns new IDEREGS as data
550 // Note: cBufferSize must be 0 on Win9x
551 inpar
.cBufferSize
= size_out
;
557 memset(&outbuf
, 0, sizeof(outbuf
));
559 if (!DeviceIoControl(hdevice
, code
, &inpar
, sizeof(SENDCMDINPARAMS
)-1,
560 outbuf
, sizeof(SENDCMDOUTPARAMS
)-1 + size_out
, &num_out
, NULL
)) {
561 // CAUTION: DO NOT change "regs" Parameter in this case, see ata_command_interface()
562 long err
= GetLastError();
563 if (con
->reportataioctl
&& (err
!= ERROR_INVALID_PARAMETER
|| con
->reportataioctl
> 1)) {
564 pout(" %s failed, Error=%ld\n", name
, err
);
565 print_ide_regs_io(regs
, NULL
);
567 errno
= ( err
== ERROR_INVALID_FUNCTION
/*9x*/
568 || err
== ERROR_INVALID_PARAMETER
/*NT/2K/XP*/ ? ENOSYS
: EIO
);
571 // NOTE: On Win9x, inpar.irDriveRegs now contains the returned regs
573 outpar
= (const SENDCMDOUTPARAMS
*)outbuf
;
575 if (outpar
->DriverStatus
.bDriverError
) {
576 if (con
->reportataioctl
) {
577 pout(" %s failed, DriverError=0x%02x, IDEError=0x%02x\n", name
,
578 outpar
->DriverStatus
.bDriverError
, outpar
->DriverStatus
.bIDEError
);
579 print_ide_regs_io(regs
, NULL
);
581 errno
= (!outpar
->DriverStatus
.bIDEError
? ENOSYS
: EIO
);
585 if (con
->reportataioctl
> 1) {
586 pout(" %s suceeded, bytes returned: %lu (buffer %lu)\n", name
,
587 num_out
, outpar
->cBufferSize
);
588 print_ide_regs_io(regs
, (regs
->bFeaturesReg
== ATA_SMART_STATUS
?
589 (const IDEREGS
*)(outpar
->bBuffer
) : NULL
));
593 memcpy(data
, outpar
->bBuffer
, 512);
594 else if (regs
->bFeaturesReg
== ATA_SMART_STATUS
) {
595 if (nonempty(const_cast<unsigned char *>(outpar
->bBuffer
), sizeof(IDEREGS
)))
596 *regs
= *(const IDEREGS
*)(outpar
->bBuffer
);
597 else { // Workaround for driver not returning regs
598 if (con
->reportataioctl
)
599 pout(" WARNING: driver does not return ATA registers in output buffer!\n");
600 *regs
= inpar
.irDriveRegs
;
608 /////////////////////////////////////////////////////////////////////////////
610 // IDE PASS THROUGH (2000, XP, undocumented)
612 // Based on WinATA.cpp, 2002 c't/Matthias Withopf
613 // ftp://ftp.heise.de/pub/ct/listings/0207-218.zip
615 #define FILE_DEVICE_CONTROLLER 4
616 #define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER
618 #define IOCTL_IDE_PASS_THROUGH \
619 CTL_CODE(IOCTL_SCSI_BASE, 0x040A, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
621 ASSERT_CONST(IOCTL_IDE_PASS_THROUGH
, 0x04d028);
627 ULONG DataBufferSize
;
631 ASSERT_SIZEOF(ATA_PASS_THROUGH
, 12+1);
636 /////////////////////////////////////////////////////////////////////////////
638 static int ide_pass_through_ioctl(HANDLE hdevice
, IDEREGS
* regs
, char * data
, unsigned datasize
)
640 unsigned int size
= sizeof(ATA_PASS_THROUGH
)-1 + datasize
;
641 ATA_PASS_THROUGH
* buf
= (ATA_PASS_THROUGH
*)VirtualAlloc(NULL
, size
, MEM_COMMIT
, PAGE_READWRITE
);
643 const unsigned char magic
= 0xcf;
651 buf
->DataBufferSize
= datasize
;
653 buf
->DataBuffer
[0] = magic
;
655 if (!DeviceIoControl(hdevice
, IOCTL_IDE_PASS_THROUGH
,
656 buf
, size
, buf
, size
, &num_out
, NULL
)) {
657 long err
= GetLastError();
658 if (con
->reportataioctl
) {
659 pout(" IOCTL_IDE_PASS_THROUGH failed, Error=%ld\n", err
);
660 print_ide_regs_io(regs
, NULL
);
662 VirtualFree(buf
, 0, MEM_RELEASE
);
663 errno
= (err
== ERROR_INVALID_FUNCTION
? ENOSYS
: EIO
);
668 if (buf
->IdeReg
.bCommandReg
/*Status*/ & 0x01) {
669 if (con
->reportataioctl
) {
670 pout(" IOCTL_IDE_PASS_THROUGH command failed:\n");
671 print_ide_regs_io(regs
, &buf
->IdeReg
);
673 VirtualFree(buf
, 0, MEM_RELEASE
);
678 // Check and copy data
681 || (buf
->DataBuffer
[0] == magic
&& !nonempty(buf
->DataBuffer
+1, datasize
-1))) {
682 if (con
->reportataioctl
) {
683 pout(" IOCTL_IDE_PASS_THROUGH output data missing (%lu, %lu)\n",
684 num_out
, buf
->DataBufferSize
);
685 print_ide_regs_io(regs
, &buf
->IdeReg
);
687 VirtualFree(buf
, 0, MEM_RELEASE
);
691 memcpy(data
, buf
->DataBuffer
, datasize
);
694 if (con
->reportataioctl
> 1) {
695 pout(" IOCTL_IDE_PASS_THROUGH suceeded, bytes returned: %lu (buffer %lu)\n",
696 num_out
, buf
->DataBufferSize
);
697 print_ide_regs_io(regs
, &buf
->IdeReg
);
701 // Caution: VirtualFree() fails if parameter "dwSize" is nonzero
702 VirtualFree(buf
, 0, MEM_RELEASE
);
707 /////////////////////////////////////////////////////////////////////////////
709 // ATA PASS THROUGH (Win2003, XP SP2)
711 #define IOCTL_ATA_PASS_THROUGH \
712 CTL_CODE(IOCTL_SCSI_BASE, 0x040B, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
714 ASSERT_CONST(IOCTL_ATA_PASS_THROUGH
, 0x04d02c);
716 typedef struct _ATA_PASS_THROUGH_EX
{
722 UCHAR ReservedAsUchar
;
723 ULONG DataTransferLength
;
725 ULONG ReservedAsUlong
;
726 ULONG
/*_PTR*/ DataBufferOffset
;
727 UCHAR PreviousTaskFile
[8];
728 UCHAR CurrentTaskFile
[8];
729 } ATA_PASS_THROUGH_EX
, *PATA_PASS_THROUGH_EX
;
731 ASSERT_SIZEOF(ATA_PASS_THROUGH_EX
, 40);
733 #define ATA_FLAGS_DRDY_REQUIRED 0x01
734 #define ATA_FLAGS_DATA_IN 0x02
735 #define ATA_FLAGS_DATA_OUT 0x04
736 #define ATA_FLAGS_48BIT_COMMAND 0x08
739 /////////////////////////////////////////////////////////////////////////////
741 static int ata_pass_through_ioctl(HANDLE hdevice
, IDEREGS
* regs
, char * data
, int datasize
)
744 ATA_PASS_THROUGH_EX apt
;
746 UCHAR ucDataBuf
[512];
747 } ATA_PASS_THROUGH_EX_WITH_BUFFERS
;
749 ATA_PASS_THROUGH_EX_WITH_BUFFERS ab
;
753 const unsigned char magic
= 0xcf;
755 memset(&ab
, 0, sizeof(ab
));
756 ab
.apt
.Length
= sizeof(ATA_PASS_THROUGH_EX
);
758 //ab.apt.TargetId = 0;
760 ab
.apt
.TimeOutValue
= 10;
761 size
= offsetof(ATA_PASS_THROUGH_EX_WITH_BUFFERS
, ucDataBuf
);
762 ab
.apt
.DataBufferOffset
= size
;
765 if (!(0 <= datasize
&& datasize
<= (int)sizeof(ab
.ucDataBuf
))) {
769 ab
.apt
.AtaFlags
= ATA_FLAGS_DATA_IN
;
770 ab
.apt
.DataTransferLength
= datasize
;
772 ab
.ucDataBuf
[0] = magic
;
775 //ab.apt.AtaFlags = 0;
776 //ab.apt.DataTransferLength = 0;
779 assert(sizeof(ab
.apt
.CurrentTaskFile
) == sizeof(IDEREGS
));
780 ctfregs
= (IDEREGS
*)ab
.apt
.CurrentTaskFile
;
783 if (!DeviceIoControl(hdevice
, IOCTL_ATA_PASS_THROUGH
,
784 &ab
, size
, &ab
, size
, &num_out
, NULL
)) {
785 long err
= GetLastError();
786 if (con
->reportataioctl
) {
787 pout(" IOCTL_ATA_PASS_THROUGH_EX failed, Error=%ld\n", err
);
788 print_ide_regs_io(regs
, NULL
);
790 errno
= (err
== ERROR_INVALID_FUNCTION
? ENOSYS
: EIO
);
794 // Check and copy data
797 || (ab
.ucDataBuf
[0] == magic
&& !nonempty(ab
.ucDataBuf
+1, datasize
-1))) {
798 if (con
->reportataioctl
) {
799 pout(" IOCTL_ATA_PASS_THROUGH_EX output data missing (%lu)\n", num_out
);
800 print_ide_regs_io(regs
, ctfregs
);
805 memcpy(data
, ab
.ucDataBuf
, datasize
);
808 if (con
->reportataioctl
> 1) {
809 pout(" IOCTL_ATA_PASS_THROUGH_EX suceeded, bytes returned: %lu\n", num_out
);
810 print_ide_regs_io(regs
, ctfregs
);
818 /////////////////////////////////////////////////////////////////////////////
820 // ATA PASS THROUGH via SCSI PASS THROUGH (WinNT4 only)
822 // Declarations from:
823 // http://cvs.sourceforge.net/viewcvs.py/mingw/w32api/include/ddk/ntddscsi.h?rev=1.2
825 #define IOCTL_SCSI_PASS_THROUGH \
826 CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
828 ASSERT_CONST(IOCTL_SCSI_PASS_THROUGH
, 0x04d004);
830 #define SCSI_IOCTL_DATA_OUT 0
831 #define SCSI_IOCTL_DATA_IN 1
832 #define SCSI_IOCTL_DATA_UNSPECIFIED 2
833 // undocumented SCSI opcode to for ATA passthrough
834 #define SCSIOP_ATA_PASSTHROUGH 0xCC
836 typedef struct _SCSI_PASS_THROUGH
{
843 UCHAR SenseInfoLength
;
845 ULONG DataTransferLength
;
847 ULONG
/*_PTR*/ DataBufferOffset
;
848 ULONG SenseInfoOffset
;
850 } SCSI_PASS_THROUGH
, *PSCSI_PASS_THROUGH
;
852 ASSERT_SIZEOF(SCSI_PASS_THROUGH
, 44);
855 /////////////////////////////////////////////////////////////////////////////
857 static int ata_via_scsi_pass_through_ioctl(HANDLE hdevice
, IDEREGS
* regs
, char * data
, unsigned datasize
)
860 SCSI_PASS_THROUGH spt
;
862 UCHAR ucSenseBuf
[32];
863 UCHAR ucDataBuf
[512];
864 } SCSI_PASS_THROUGH_WITH_BUFFERS
;
866 SCSI_PASS_THROUGH_WITH_BUFFERS sb
;
870 const unsigned char magic
= 0xcf;
872 memset(&sb
, 0, sizeof(sb
));
873 sb
.spt
.Length
= sizeof(SCSI_PASS_THROUGH
);
877 sb
.spt
.CdbLength
= 10; sb
.spt
.SenseInfoLength
= 24;
878 sb
.spt
.TimeOutValue
= 10;
879 sb
.spt
.SenseInfoOffset
= offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS
, ucSenseBuf
);
880 size
= offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS
, ucDataBuf
);
881 sb
.spt
.DataBufferOffset
= size
;
884 if (datasize
> sizeof(sb
.ucDataBuf
)) {
888 sb
.spt
.DataIn
= SCSI_IOCTL_DATA_IN
;
889 sb
.spt
.DataTransferLength
= datasize
;
891 sb
.ucDataBuf
[0] = magic
;
894 sb
.spt
.DataIn
= SCSI_IOCTL_DATA_UNSPECIFIED
;
895 //sb.spt.DataTransferLength = 0;
898 // Use pseudo SCSI command followed by registers
899 sb
.spt
.Cdb
[0] = SCSIOP_ATA_PASSTHROUGH
;
900 cdbregs
= (IDEREGS
*)(sb
.spt
.Cdb
+2);
903 if (!DeviceIoControl(hdevice
, IOCTL_SCSI_PASS_THROUGH
,
904 &sb
, size
, &sb
, size
, &num_out
, NULL
)) {
905 long err
= GetLastError();
906 if (con
->reportataioctl
)
907 pout(" ATA via IOCTL_SCSI_PASS_THROUGH failed, Error=%ld\n", err
);
908 errno
= (err
== ERROR_INVALID_FUNCTION
? ENOSYS
: EIO
);
912 // Cannot check ATA status, because command does not return IDEREGS
914 // Check and copy data
917 || (sb
.ucDataBuf
[0] == magic
&& !nonempty(sb
.ucDataBuf
+1, datasize
-1))) {
918 if (con
->reportataioctl
) {
919 pout(" ATA via IOCTL_SCSI_PASS_THROUGH output data missing (%lu)\n", num_out
);
920 print_ide_regs_io(regs
, NULL
);
925 memcpy(data
, sb
.ucDataBuf
, datasize
);
928 if (con
->reportataioctl
> 1) {
929 pout(" ATA via IOCTL_SCSI_PASS_THROUGH suceeded, bytes returned: %lu\n", num_out
);
930 print_ide_regs_io(regs
, NULL
);
935 /////////////////////////////////////////////////////////////////////////////
937 // Call GetDevicePowerState() if available (Win98/ME/2000/XP/2003)
938 // returns: 1=active, 0=standby, -1=error
939 // (This would also work for SCSI drives)
941 static int get_device_power_state(HANDLE hdevice
)
943 static HINSTANCE h_kernel_dll
= 0;
945 static DWORD kernel_dll_pid
= 0;
947 static BOOL (WINAPI
* GetDevicePowerState_p
)(HANDLE
, BOOL
*) = 0;
951 if (!GetDevicePowerState_p
953 || kernel_dll_pid
!= GetCurrentProcessId() // detect fork()
956 if (h_kernel_dll
== INVALID_HANDLE_VALUE
) {
960 if (!(h_kernel_dll
= LoadLibraryA("KERNEL32.DLL"))) {
961 pout("Cannot load KERNEL32.DLL, Error=%ld\n", GetLastError());
962 h_kernel_dll
= (HINSTANCE
)INVALID_HANDLE_VALUE
;
966 if (!(GetDevicePowerState_p
= (BOOL (WINAPI
*)(HANDLE
, BOOL
*))
967 GetProcAddress(h_kernel_dll
, "GetDevicePowerState"))) {
968 if (con
->reportataioctl
)
969 pout(" GetDevicePowerState() not found, Error=%ld\n", GetLastError());
970 FreeLibrary(h_kernel_dll
);
971 h_kernel_dll
= (HINSTANCE
)INVALID_HANDLE_VALUE
;
976 kernel_dll_pid
= GetCurrentProcessId();
980 if (!GetDevicePowerState_p(hdevice
, &state
)) {
981 long err
= GetLastError();
982 if (con
->reportataioctl
)
983 pout(" GetDevicePowerState() failed, Error=%ld\n", err
);
984 errno
= (err
== ERROR_INVALID_FUNCTION
? ENOSYS
: EIO
);
985 // TODO: This may not work as expected on transient errors,
986 // because smartd interprets -1 as SLEEP mode regardless of errno.
990 if (con
->reportataioctl
> 1)
991 pout(" GetDevicePowerState() succeeded, state=%d\n", state
);
996 /////////////////////////////////////////////////////////////////////////////
998 // TODO: Put in a struct indexed by fd (or better a C++ object of course ;-)
999 static HANDLE h_ata_ioctl
= 0;
1000 static const char * ata_def_options
;
1001 static char * ata_cur_options
;
1002 static int ata_driveno
; // Drive number
1003 static char ata_smartver_state
[10]; // SMART_GET_VERSION: 0=unknown, 1=OK, 2=failed
1005 // Print SMARTVSD error message, return errno
1007 static int smartvsd_error()
1009 char path
[MAX_PATH
];
1011 if (!(5 <= (len
= GetSystemDirectoryA(path
, MAX_PATH
)) && len
< MAX_PATH
/2))
1013 // SMARTVSD.VXD present?
1014 strcpy(path
+len
, "\\IOSUBSYS\\SMARTVSD.VXD");
1015 if (!access(path
, 0)) {
1016 // Yes, standard IDE driver used?
1018 if ( (h
= CreateFileA("\\\\.\\ESDI_506",
1019 GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1020 NULL
, OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
1021 && GetLastError() == ERROR_FILE_NOT_FOUND
) {
1022 pout("Standard IDE driver ESDI_506.PDR not used, or no IDE/ATA drives present.\n");
1026 if (h
!= INVALID_HANDLE_VALUE
) // should not happen
1028 pout("SMART driver SMARTVSD.VXD is installed, but not loaded.\n");
1033 strcpy(path
+len
, "\\SMARTVSD.VXD");
1034 if (!access(path
, 0)) {
1035 // Some Windows versions install SMARTVSD.VXD in SYSTEM directory
1036 // (http://support.microsoft.com/kb/265854/en-us).
1038 pout("SMART driver is not properly installed,\n"
1039 " move SMARTVSD.VXD from \"%s\" to \"%s\\IOSUBSYS\"\n"
1040 " and reboot Windows.\n", path
, path
);
1043 // Some Windows versions do not provide SMARTVSD.VXD
1044 // (http://support.microsoft.com/kb/199886/en-us).
1046 pout("SMARTVSD.VXD is missing in folder \"%s\\IOSUBSYS\".\n", path
);
1053 // Get default ATA device options
1055 static const char * ata_get_def_options()
1057 DWORD ver
= GetVersion();
1058 if ((ver
& 0x80000000) || (ver
& 0xff) < 4) // Win9x/ME
1059 return "s"; // SMART_* only
1060 else if ((ver
& 0xff) == 4) // WinNT4
1061 return "sc"; // SMART_*, SCSI_PASS_THROUGH
1062 else // WinXP, 2003, Vista
1063 return "psai"; // GetDevicePowerState(), SMART_*, ATA_, IDE_PASS_THROUGH
1069 static int ata_open(int drive
, const char * options
, int port
)
1075 // TODO: This version does not allow to open more than 1 ATA devices
1081 win9x
= ((GetVersion() & 0x80000000) != 0);
1083 if (!(0 <= drive
&& drive
<= (win9x
? 7 : 9))) {
1088 // path depends on Windows Version
1090 // Use patched "smartvse.vxd" for drives 4-7, see INSTALL file for details
1091 strcpy(devpath
, (drive
<= 3 ? "\\\\.\\SMARTVSD" : "\\\\.\\SMARTVSE"));
1093 snprintf(devpath
, sizeof(devpath
)-1, "\\\\.\\PhysicalDrive%d", drive
);
1096 if ((h_ata_ioctl
= CreateFileA(devpath
,
1097 GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1098 NULL
, OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
) {
1099 long err
= GetLastError();
1100 pout("Cannot open device %s, Error=%ld\n", devpath
, err
);
1101 if (err
== ERROR_FILE_NOT_FOUND
)
1102 errno
= (win9x
&& drive
<= 3 ? smartvsd_error() : ENOENT
);
1103 else if (err
== ERROR_ACCESS_DENIED
) {
1105 pout("Administrator rights are necessary to access physical drives.\n");
1114 if (con
->reportataioctl
> 1)
1115 pout("%s: successfully opened\n", devpath
);
1119 // Set default options according to Windows version
1120 if (!ata_def_options
)
1121 ata_def_options
= ata_get_def_options();
1122 options
= (port
< 0 ? ata_def_options
: "s"); // RAID: SMART_* only
1124 ata_cur_options
= strdup(options
);
1126 // NT4/2000/XP: SMART_GET_VERSION may spin up disk, so delay until first real SMART_* call
1127 ata_driveno
= drive
;
1128 if (!win9x
&& port
< 0)
1131 // Win9X/ME: Get drive map
1132 // RAID: Get port map
1133 unsigned long portmap
= 0;
1134 devmap
= smart_get_version(h_ata_ioctl
, (port
>= 0 ? &portmap
: 0));
1136 if (!is_permissive()) {
1143 ata_smartver_state
[drive
] = 1;
1146 // RAID: Check port existence
1147 if (!(portmap
& (1L << port
))) {
1148 pout("%s: Port %d is empty or does not exist\n", devpath
, port
);
1149 if (!is_permissive()) {
1155 // Encode port into pseudo fd
1156 return (0x0200 | port
);
1159 // Win9x/ME: Check device presence & type
1160 if (((devmap
>> (drive
& 0x3)) & 0x11) != 0x01) {
1161 unsigned char atapi
= (devmap
>> (drive
& 0x3)) & 0x10;
1162 pout("%s: Drive %d %s (IDEDeviceMap=0x%02x).\n", devpath
,
1163 drive
, (atapi
?"is an ATAPI device":"does not exist"), devmap
);
1164 // Win9x drive existence check may not work as expected
1165 // The atapi.sys driver incorrectly fills in the bIDEDeviceMap with 0x01
1166 // (The related KB Article Q196120 is no longer available)
1167 if (!is_permissive()) {
1169 errno
= (atapi
? ENOSYS
: ENOENT
);
1173 // Use drive number as fd for ioctl
1174 return (drive
& 0x3);
1178 static void ata_close(int fd
)
1181 CloseHandle(h_ata_ioctl
);
1183 if (ata_cur_options
) {
1184 free(ata_cur_options
);
1185 ata_cur_options
= 0;
1190 // Scan for ATA drives, fill bitmask of drives present, return #drives
1192 static int ata_scan(unsigned long * drives
, int * rdriveno
, unsigned long * rdrives
)
1194 int win9x
= ((GetVersion() & 0x80000000) != 0);
1197 for (i
= 0; i
<= 9; i
++) {
1199 GETVERSIONOUTPARAMS vers
;
1200 const GETVERSIONINPARAMS_EX
& vers_ex
= (const GETVERSIONINPARAMS_EX
&)vers
;
1204 strcpy(devpath
, "\\\\.\\SMARTVSD");
1206 snprintf(devpath
, sizeof(devpath
)-1, "\\\\.\\PhysicalDrive%d", i
);
1209 if ((h
= CreateFileA(devpath
,
1210 GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
,
1211 NULL
, OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
) {
1212 if (con
->reportataioctl
> 1)
1213 pout(" %s: Open failed, Error=%ld\n", devpath
, GetLastError());
1215 break; // SMARTVSD.VXD missing or no ATA devices
1216 continue; // Disk not found or access denied (break;?)
1220 memset(&vers
, 0, sizeof(vers
));
1221 if (!DeviceIoControl(h
, SMART_GET_VERSION
,
1222 NULL
, 0, &vers
, sizeof(vers
), &num_out
, NULL
)) {
1223 if (con
->reportataioctl
)
1224 pout(" %s: SMART_GET_VERSION failed, Error=%ld\n", devpath
, GetLastError());
1227 break; // Should not happen
1228 continue; // Non ATA disk or no SMART ioctl support (possibly SCSI disk)
1232 if (con
->reportataioctl
) {
1233 pout(" %s: SMART_GET_VERSION (%ld bytes):\n"
1234 " Vers = %d.%d, Caps = 0x%lx, DeviceMap = 0x%02x\n",
1235 devpath
, num_out
, vers
.bVersion
, vers
.bRevision
,
1236 vers
.fCapabilities
, vers
.bIDEDeviceMap
);
1237 if (vers_ex
.wIdentifier
== SMART_VENDOR_3WARE
)
1238 pout(" Identifier = %04x(3WARE), ControllerId=%u, DeviceMapEx = 0x%08lx\n",
1239 vers_ex
.wIdentifier
, vers_ex
.wControllerId
, vers_ex
.dwDeviceMapEx
);
1243 // Check ATA device presence, remove ATAPI devices
1244 drives
[0] = (vers
.bIDEDeviceMap
& 0xf) & ~((vers
.bIDEDeviceMap
>> 4) & 0xf);
1245 cnt
= (drives
[0]&1) + ((drives
[0]>>1)&1) + ((drives
[0]>>2)&1) + ((drives
[0]>>3)&1);
1249 if (vers_ex
.wIdentifier
== SMART_VENDOR_3WARE
) {
1250 // Skip if more than 2 controllers or logical drive from this controller already seen
1251 if (vers_ex
.wControllerId
>= 2 || rdriveno
[vers_ex
.wControllerId
] >= 0)
1253 assert(rdrives
[vers_ex
.wControllerId
] == 0);
1254 // Count physical drives
1256 for (int pi
= 0; pi
< 32; pi
++) {
1257 if (vers_ex
.dwDeviceMapEx
& (1L << pi
))
1261 continue; // Should not happen
1262 rdrives
[vers_ex
.wControllerId
] = vers_ex
.dwDeviceMapEx
;
1263 rdriveno
[vers_ex
.wControllerId
] = i
;
1267 // ATA drive exists and driver supports SMART ioctl
1268 drives
[0] |= (1L << i
);
1276 /////////////////////////////////////////////////////////////////////////////
1278 // Interface to ATA devices. See os_linux.c
1279 int ata_command_interface(int fd
, smart_command_set command
, int select
, char * data
)
1283 const char * valid_options
;
1287 if ((fd
& ~0x1f) == 0x0200) {
1288 // RAID Port encoded into pseudo fd
1293 if (!(0 <= fd
&& fd
<= 3)) {
1298 // CMD,CYL default to SMART, changed by P?IDENTIFY and CHECK_POWER_MODE
1299 memset(®s
, 0, sizeof(regs
));
1300 regs
.bCommandReg
= ATA_SMART_CMD
;
1301 regs
.bCylHighReg
= SMART_CYL_HI
; regs
.bCylLowReg
= SMART_CYL_LOW
;
1304 // Try all IOCTLS by default: SMART_*, ATA_, IDE_, SCSI_PASS_THROUGH
1305 valid_options
= "saic";
1309 // TODO. Requires DATA OUT support
1312 case CHECK_POWER_MODE
:
1313 // Not a SMART command, needs IDE register return
1314 regs
.bCommandReg
= ATA_CHECK_POWER_MODE
;
1315 regs
.bCylLowReg
= regs
.bCylHighReg
= 0;
1316 valid_options
= "pai"; // Try GetDevicePowerState() first, ATA/IDE_PASS_THROUGH may spin up disk
1317 // Note: returns SectorCountReg in data[0]
1320 regs
.bFeaturesReg
= ATA_SMART_READ_VALUES
;
1321 regs
.bSectorNumberReg
= regs
.bSectorCountReg
= 1;
1324 case READ_THRESHOLDS
:
1325 regs
.bFeaturesReg
= ATA_SMART_READ_THRESHOLDS
;
1326 regs
.bSectorNumberReg
= regs
.bSectorCountReg
= 1;
1330 regs
.bFeaturesReg
= ATA_SMART_READ_LOG_SECTOR
;
1331 regs
.bSectorNumberReg
= select
;
1332 regs
.bSectorCountReg
= 1;
1333 // Note: SMART_RCV_DRIVE_DATA supports this only on Win9x/ME
1337 // Note: WinNT4/2000/XP return identify data cached during boot
1338 // (true for SMART_RCV_DRIVE_DATA and IOCTL_IDE_PASS_THROUGH)
1339 regs
.bCommandReg
= ATA_IDENTIFY_DEVICE
;
1340 regs
.bCylLowReg
= regs
.bCylHighReg
= 0;
1341 regs
.bSectorCountReg
= 1;
1345 regs
.bCommandReg
= ATA_IDENTIFY_PACKET_DEVICE
;
1346 regs
.bCylLowReg
= regs
.bCylHighReg
= 0;
1347 regs
.bSectorCountReg
= 1;
1351 regs
.bFeaturesReg
= ATA_SMART_ENABLE
;
1352 regs
.bSectorNumberReg
= 1;
1355 regs
.bFeaturesReg
= ATA_SMART_DISABLE
;
1356 regs
.bSectorNumberReg
= 1;
1359 valid_options
= "sai"; // Needs IDE register return
1361 regs
.bFeaturesReg
= ATA_SMART_STATUS
;
1364 regs
.bFeaturesReg
= ATA_SMART_AUTO_OFFLINE
;
1365 regs
.bSectorCountReg
= select
; // YET NOTE - THIS IS A NON-DATA COMMAND!!
1368 regs
.bFeaturesReg
= ATA_SMART_AUTOSAVE
;
1369 regs
.bSectorCountReg
= select
; // YET NOTE - THIS IS A NON-DATA COMMAND!!
1371 case IMMEDIATE_OFFLINE
:
1372 regs
.bFeaturesReg
= ATA_SMART_IMMEDIATE_OFFLINE
;
1373 regs
.bSectorNumberReg
= select
;
1374 // Note: SMART_SEND_DRIVE_COMMAND supports ABORT_SELF_TEST only on Win9x/ME
1377 pout("Unrecognized command %d in win32_ata_command_interface()\n"
1378 "Please contact " PACKAGE_BUGREPORT
"\n", command
);
1383 // Try all valid ioctls in the order specified in dev_ioctls;
1384 for (i
= 0; ; i
++) {
1385 char opt
= ata_cur_options
[i
];
1393 if (!strchr(valid_options
, opt
))
1394 // Invalid for this command
1398 assert(datasize
== 0 || datasize
== 512);
1402 // call SMART_GET_VERSION once for each drive
1403 assert(0 <= ata_driveno
&& ata_driveno
< sizeof(ata_smartver_state
));
1404 if (ata_smartver_state
[ata_driveno
] > 1) {
1405 rc
= -1; errno
= ENOSYS
;
1408 if (!ata_smartver_state
[ata_driveno
]) {
1410 if (smart_get_version(h_ata_ioctl
) < 0) {
1411 if (!con
->permissive
) {
1412 pout("ATA/SATA driver is possibly a SCSI class driver not supporting SMART.\n");
1413 pout("If this is a SCSI disk, try \"scsi<adapter><id>\".\n");
1414 ata_smartver_state
[ata_driveno
] = 2;
1415 rc
= -1; errno
= ENOSYS
;
1420 ata_smartver_state
[ata_driveno
] = 1;
1422 rc
= smart_ioctl(h_ata_ioctl
, fd
, ®s
, data
, datasize
, port
);
1425 rc
= ata_pass_through_ioctl(h_ata_ioctl
, ®s
, data
, datasize
);
1428 rc
= ide_pass_through_ioctl(h_ata_ioctl
, ®s
, data
, datasize
);
1431 rc
= ata_via_scsi_pass_through_ioctl(h_ata_ioctl
, ®s
, data
, datasize
);
1434 assert(command
== CHECK_POWER_MODE
&& datasize
== 0);
1435 rc
= get_device_power_state(h_ata_ioctl
);
1436 if (rc
>= 0) { // Simulate ATA command result
1437 regs
.bSectorCountReg
= (rc
? 0xff/*ACTIVE/IDLE*/ : 0x00/*STANDBY*/);
1444 // Working ioctl found
1447 if (errno
!= ENOSYS
)
1448 // Abort on I/O error
1451 // CAUTION: *_ioctl() MUST NOT change "regs" Parameter in the ENOSYS case
1455 case CHECK_POWER_MODE
:
1456 // Return power mode from SectorCountReg in data[0]
1457 data
[0] = regs
.bSectorCountReg
;
1461 // Cyl low and Cyl high unchanged means "Good SMART status"
1462 if (regs
.bCylHighReg
== SMART_CYL_HI
&& regs
.bCylLowReg
== SMART_CYL_LOW
)
1465 // These values mean "Bad SMART status"
1466 if (regs
.bCylHighReg
== 0x2c && regs
.bCylLowReg
== 0xf4)
1469 // We haven't gotten output that makes sense; print out some debugging info
1470 syserror("Error SMART Status command failed");
1471 pout("Please get assistance from %s\n", PACKAGE_HOMEPAGE
);
1472 print_ide_regs(®s
, 1);
1483 #ifndef HAVE_ATA_IDENTIFY_IS_CACHED
1484 #error define of HAVE_ATA_IDENTIFY_IS_CACHED missing in config.h
1487 // Return true if OS caches the ATA identify sector
1488 int ata_identify_is_cached(int fd
)
1490 // Not RAID and WinNT4/2000/XP => true, RAID or Win9x/ME => false
1491 return (!(fd
& 0xff00) && (GetVersion() & 0x80000000) == 0);
1495 // Print not implemeted warning once
1496 static void pr_not_impl(const char * what
, int * warned
)
1501 "#######################################################################\n"
1503 "NOT IMPLEMENTED under Win32.\n"
1504 "Please contact " PACKAGE_BUGREPORT
" if\n"
1505 "you want to help in porting smartmontools to Win32.\n"
1506 "#######################################################################\n"
1512 // Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c
1513 int escalade_command_interface(int fd
, int disknum
, int escalade_type
, smart_command_set command
, int select
, char *data
)
1515 static int warned
= 0;
1516 ARGUSED(fd
); ARGUSED(escalade_type
); ARGUSED(command
); ARGUSED(select
); ARGUSED(data
);
1518 pout("Option '-d 3ware,%d' does not work on Windows.\n"
1519 "Controller port can be specified in the device name: '/dev/hd%c,%d'.\n\n",
1520 disknum
, 'a'+ata_driveno
, disknum
);
1527 // Interface to ATA devices behind Marvell chip-set based controllers. See os_linux.c
1528 int marvell_command_interface(int fd
, smart_command_set command
, int select
, char * data
)
1530 static int warned
= 0;
1531 ARGUSED(fd
); ARGUSED(command
); ARGUSED(select
); ARGUSED(data
);
1532 pr_not_impl("Marvell chip-set command routine marvell_command_interface()", &warned
);
1537 // Interface to ATA devices behind HighPoint Raid controllers. See os_linux.c
1538 int highpoint_command_interface(int fd
, smart_command_set command
, int select
, char * data
)
1540 static int warned
= 0;
1541 ARGUSED(fd
); ARGUSED(command
); ARGUSED(select
); ARGUSED(data
);
1542 pr_not_impl("HighPoint raid controller command routine highpoint_command_interface()", &warned
);
1548 /////////////////////////////////////////////////////////////////////////////
1550 /////////////////////////////////////////////////////////////////////////////
1554 #define ASPI_SENSE_SIZE 18
1556 // ASPI SCSI Request block header
1559 unsigned char cmd
; // 00: Command code
1560 unsigned char status
; // 01: ASPI status
1561 unsigned char adapter
; // 02: Host adapter number
1562 unsigned char flags
; // 03: Request flags
1563 unsigned char reserved
[4]; // 04: 0
1566 // SRB for host adapter inquiry
1569 ASPI_SRB_HEAD h
; // 00: Header
1570 unsigned char adapters
; // 08: Number of adapters
1571 unsigned char target_id
; // 09: Target ID ?
1572 char manager_id
[16]; // 10: SCSI manager ID
1573 char adapter_id
[16]; // 26: Host adapter ID
1574 unsigned char parameters
[16]; // 42: Host adapter unique parmameters
1577 // SRB for get device type
1580 ASPI_SRB_HEAD h
; // 00: Header
1581 unsigned char target_id
; // 08: Target ID
1582 unsigned char lun
; // 09: LUN
1583 unsigned char devtype
; // 10: Device type
1584 unsigned char reserved
; // 11: Reserved
1590 ASPI_SRB_HEAD h
; // 00: Header
1591 unsigned char target_id
; // 08: Target ID
1592 unsigned char lun
; // 09: LUN
1593 unsigned char reserved
[2]; // 10: Reserved
1594 unsigned long data_size
; // 12: Data alloc. lenght
1595 void * data_addr
; // 16: Data buffer pointer
1596 unsigned char sense_size
; // 20: Sense alloc. length
1597 unsigned char cdb_size
; // 21: CDB length
1598 unsigned char host_status
; // 22: Host status
1599 unsigned char target_status
; // 23: Target status
1600 void * event_handle
; // 24: Event handle
1601 unsigned char workspace
[20]; // 28: ASPI workspace
1602 unsigned char cdb
[16+ASPI_SENSE_SIZE
];
1605 // Macro to retrieve start of sense information
1606 #define ASPI_SRB_SENSE(srb,cdbsz) ((srb)->cdb + 16)
1611 ASPI_SRB_HEAD h
; // Common header
1612 ASPI_SRB_INQUIRY q
; // Inquiry
1613 ASPI_SRB_DEVTYPE t
; // Device type
1614 ASPI_SRB_IO i
; // I/O
1620 #define ASPI_CMD_ADAPTER_INQUIRE 0x00
1621 #define ASPI_CMD_GET_DEVICE_TYPE 0x01
1622 #define ASPI_CMD_EXECUTE_IO 0x02
1623 #define ASPI_CMD_ABORT_IO 0x03
1626 #define ASPI_REQFLAG_DIR_TO_HOST 0x08
1627 #define ASPI_REQFLAG_DIR_TO_TARGET 0x10
1628 #define ASPI_REQFLAG_DIR_NO_XFER 0x18
1629 #define ASPI_REQFLAG_EVENT_NOTIFY 0x40
1632 #define ASPI_STATUS_IN_PROGRESS 0x00
1633 #define ASPI_STATUS_NO_ERROR 0x01
1634 #define ASPI_STATUS_ABORTED 0x02
1635 #define ASPI_STATUS_ABORT_ERR 0x03
1636 #define ASPI_STATUS_ERROR 0x04
1637 #define ASPI_STATUS_INVALID_COMMAND 0x80
1638 #define ASPI_STATUS_INVALID_ADAPTER 0x81
1639 #define ASPI_STATUS_INVALID_TARGET 0x82
1640 #define ASPI_STATUS_NO_ADAPTERS 0xE8
1642 // Adapter (host) status
1643 #define ASPI_HSTATUS_NO_ERROR 0x00
1644 #define ASPI_HSTATUS_SELECTION_TIMEOUT 0x11
1645 #define ASPI_HSTATUS_DATA_OVERRUN 0x12
1646 #define ASPI_HSTATUS_BUS_FREE 0x13
1647 #define ASPI_HSTATUS_BUS_PHASE_ERROR 0x14
1648 #define ASPI_HSTATUS_BAD_SGLIST 0x1A
1651 #define ASPI_TSTATUS_NO_ERROR 0x00
1652 #define ASPI_TSTATUS_CHECK_CONDITION 0x02
1653 #define ASPI_TSTATUS_BUSY 0x08
1654 #define ASPI_TSTATUS_RESERV_CONFLICT 0x18
1657 static HINSTANCE h_aspi_dll
; // DLL handle
1658 static UINT (* aspi_entry
)(ASPI_SRB
* srb
); // ASPI entrypoint
1659 static unsigned num_aspi_adapters
;
1662 // h_aspi_dll+aspi_entry is not inherited by Cygwin's fork()
1663 static DWORD aspi_dll_pid
; // PID of DLL owner to detect fork()
1664 #define aspi_entry_valid() (aspi_entry && (aspi_dll_pid == GetCurrentProcessId()))
1666 #define aspi_entry_valid() (!!aspi_entry)
1670 static int aspi_call(ASPI_SRB
* srb
)
1675 while (((volatile ASPI_SRB
*)srb
)->h
.status
== ASPI_STATUS_IN_PROGRESS
) {
1676 if (++i
> 100/*10sek*/) {
1677 pout("ASPI Adapter %u: Timed out\n", srb
->h
.adapter
);
1679 h_aspi_dll
= (HINSTANCE
)INVALID_HANDLE_VALUE
;
1683 if (con
->reportscsiioctl
> 1)
1684 pout("ASPI Adapter %u: Waiting (%d) ...\n", srb
->h
.adapter
, i
);
1691 // Get ASPI entrypoint from wnaspi32.dll
1693 static FARPROC
aspi_get_address(const char * name
, int verbose
)
1696 assert(h_aspi_dll
&& h_aspi_dll
!= INVALID_HANDLE_VALUE
);
1698 if (!(addr
= GetProcAddress(h_aspi_dll
, name
))) {
1700 pout("Missing %s() in WNASPI32.DLL\n", name
);
1702 FreeLibrary(h_aspi_dll
);
1703 h_aspi_dll
= (HINSTANCE
)INVALID_HANDLE_VALUE
;
1711 static int aspi_open_dll(int verbose
)
1713 UINT (*aspi_info
)(void);
1716 assert(!aspi_entry_valid());
1718 // Check structure layout
1719 assert(sizeof(ASPI_SRB_HEAD
) == 8);
1720 assert(sizeof(ASPI_SRB_INQUIRY
) == 58);
1721 assert(sizeof(ASPI_SRB_DEVTYPE
) == 12);
1722 assert(sizeof(ASPI_SRB_IO
) == 64+ASPI_SENSE_SIZE
);
1723 assert(offsetof(ASPI_SRB
,h
.cmd
) == 0);
1724 assert(offsetof(ASPI_SRB
,h
.flags
) == 3);
1725 assert(offsetof(ASPI_SRB_IO
,lun
) == 9);
1726 assert(offsetof(ASPI_SRB_IO
,data_addr
) == 16);
1727 assert(offsetof(ASPI_SRB_IO
,workspace
) == 28);
1728 assert(offsetof(ASPI_SRB_IO
,cdb
) == 48);
1730 if (h_aspi_dll
== INVALID_HANDLE_VALUE
) {
1737 if (!(h_aspi_dll
= LoadLibraryA("WNASPI32.DLL"))) {
1739 pout("Cannot load WNASPI32.DLL, Error=%ld\n", GetLastError());
1740 h_aspi_dll
= (HINSTANCE
)INVALID_HANDLE_VALUE
;
1744 if (con
->reportscsiioctl
> 1) {
1745 // Print full path of WNASPI32.DLL
1746 char path
[MAX_PATH
];
1747 if (!GetModuleFileName(h_aspi_dll
, path
, sizeof(path
)))
1748 strcpy(path
, "*unknown*");
1749 pout("Using ASPI interface \"%s\"\n", path
);
1752 // Get ASPI entrypoints
1753 if (!(aspi_info
= (UINT (*)(void))aspi_get_address("GetASPI32SupportInfo", verbose
)))
1755 if (!(aspi_entry
= (UINT (*)(ASPI_SRB
*))aspi_get_address("SendASPI32Command", verbose
)))
1758 // Init ASPI manager and get number of adapters
1759 info
= (aspi_info
)();
1760 if (con
->reportscsiioctl
> 1)
1761 pout("GetASPI32SupportInfo() returns 0x%04x\n", info
);
1762 rc
= (info
>> 8) & 0xff;
1763 if (rc
== ASPI_STATUS_NO_ADAPTERS
) {
1764 num_aspi_adapters
= 0;
1766 else if (rc
== ASPI_STATUS_NO_ERROR
) {
1767 num_aspi_adapters
= info
& 0xff;
1771 pout("Got strange 0x%04x from GetASPI32SupportInfo()\n", info
);
1773 FreeLibrary(h_aspi_dll
);
1774 h_aspi_dll
= (HINSTANCE
)INVALID_HANDLE_VALUE
;
1779 if (con
->reportscsiioctl
)
1780 pout("%u ASPI Adapter%s detected\n",num_aspi_adapters
, (num_aspi_adapters
!=1?"s":""));
1783 // save PID to detect fork() in aspi_entry_valid()
1784 aspi_dll_pid
= GetCurrentProcessId();
1786 assert(aspi_entry_valid());
1791 static int aspi_io_call(ASPI_SRB
* srb
, unsigned timeout
)
1795 if (!(event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
))) {
1796 pout("CreateEvent(): Error=%ld\n", GetLastError()); return -EIO
;
1798 srb
->i
.event_handle
= event
;
1799 srb
->h
.flags
|= ASPI_REQFLAG_EVENT_NOTIFY
;
1800 // Start ASPI request
1802 if (((volatile ASPI_SRB
*)srb
)->h
.status
== ASPI_STATUS_IN_PROGRESS
) {
1804 DWORD rc
= WaitForSingleObject(event
, timeout
*1000L);
1805 if (rc
!= WAIT_OBJECT_0
) {
1806 if (rc
== WAIT_TIMEOUT
) {
1807 pout("ASPI Adapter %u, ID %u: Timed out after %u seconds\n",
1808 srb
->h
.adapter
, srb
->i
.target_id
, timeout
);
1811 pout("WaitForSingleObject(%lx) = 0x%lx,%ld, Error=%ld\n",
1812 (unsigned long)event
, rc
, rc
, GetLastError());
1814 // TODO: ASPI_ABORT_IO command
1816 h_aspi_dll
= (HINSTANCE
)INVALID_HANDLE_VALUE
;
1825 static int aspi_open(unsigned adapter
, unsigned id
)
1828 if (!(adapter
<= 9 && id
< 16)) {
1833 if (!aspi_entry_valid()) {
1834 if (aspi_open_dll(1/*verbose*/))
1839 if (adapter
>= num_aspi_adapters
) {
1840 pout("ASPI Adapter %u does not exist (%u Adapter%s detected).\n",
1841 adapter
, num_aspi_adapters
, (num_aspi_adapters
!=1?"s":""));
1842 if (!is_permissive()) {
1849 memset(&srb
, 0, sizeof(srb
));
1850 srb
.h
.cmd
= ASPI_CMD_GET_DEVICE_TYPE
;
1851 srb
.h
.adapter
= adapter
; srb
.i
.target_id
= id
;
1852 if (aspi_call(&srb
)) {
1856 if (srb
.h
.status
!= ASPI_STATUS_NO_ERROR
) {
1857 pout("ASPI Adapter %u, ID %u: No such device (Status=0x%02x)\n", adapter
, id
, srb
.h
.status
);
1858 if (!is_permissive()) {
1859 errno
= (srb
.h
.status
== ASPI_STATUS_INVALID_TARGET
? ENOENT
: EIO
);
1863 else if (con
->reportscsiioctl
)
1864 pout("ASPI Adapter %u, ID %u: Device Type=0x%02x\n", adapter
, id
, srb
.t
.devtype
);
1866 return (0x0100 | ((adapter
& 0xf)<<4) | (id
& 0xf));
1870 static void aspi_close(int fd
)
1872 // No FreeLibrary(h_aspi_dll) to prevent problems with ASPI threads
1877 // Scan for SCSI drives, fill bitmask [adapter:0-9][id:0-7] of drives present,
1880 static int aspi_scan(unsigned long * drives
)
1885 if (!aspi_entry_valid()) {
1886 if (aspi_open_dll(con
->reportscsiioctl
/*default is quiet*/))
1890 for (ad
= 0; ad
< num_aspi_adapters
; ad
++) {
1891 ASPI_SRB srb
; unsigned id
;
1894 if (con
->reportscsiioctl
)
1895 pout(" ASPI Adapter %u: Ignored\n", ad
);
1900 memset(&srb
, 0, sizeof(srb
));
1901 srb
.h
.cmd
= ASPI_CMD_ADAPTER_INQUIRE
;
1903 if (aspi_call(&srb
))
1906 if (srb
.h
.status
!= ASPI_STATUS_NO_ERROR
) {
1907 if (con
->reportscsiioctl
)
1908 pout(" ASPI Adapter %u: Status=0x%02x\n", ad
, srb
.h
.status
);
1912 if (con
->reportscsiioctl
) {
1914 for (i
= 1; i
< 16 && srb
.q
.adapter_id
[i
]; i
++)
1915 if (!(' ' <= srb
.q
.adapter_id
[i
] && srb
.q
.adapter_id
[i
] <= '~'))
1916 srb
.q
.adapter_id
[i
] = '?';
1917 pout(" ASPI Adapter %u (\"%.16s\"):\n", ad
, srb
.q
.adapter_id
);
1920 bool ignore
= !strnicmp(srb
.q
.adapter_id
, "3ware", 5);
1922 for (id
= 0; id
<= 7; id
++) {
1924 memset(&srb
, 0, sizeof(srb
));
1925 srb
.h
.cmd
= ASPI_CMD_GET_DEVICE_TYPE
;
1926 srb
.h
.adapter
= ad
; srb
.i
.target_id
= id
;
1927 if (aspi_call(&srb
))
1929 if (srb
.h
.status
!= ASPI_STATUS_NO_ERROR
) {
1930 if (con
->reportscsiioctl
> 1)
1931 pout(" ID %u: No such device (Status=0x%02x)\n", id
, srb
.h
.status
);
1935 if (!ignore
&& srb
.t
.devtype
== 0x00/*HDD*/) {
1936 if (con
->reportscsiioctl
)
1937 pout(" ID %u: Device Type=0x%02x\n", id
, srb
.t
.devtype
);
1938 drives
[ad
>> 2] |= (1L << (((ad
& 0x3) << 3) + id
));
1941 else if (con
->reportscsiioctl
)
1942 pout(" ID %u: Device Type=0x%02x (ignored)\n", id
, srb
.t
.devtype
);
1949 /////////////////////////////////////////////////////////////////////////////
1951 // Interface to SCSI devices. See os_linux.c
1952 int do_scsi_cmnd_io(int fd
, struct scsi_cmnd_io
* iop
, int report
)
1956 if (!aspi_entry_valid())
1958 if (!((fd
& ~0xff) == 0x100))
1961 if (!(iop
->cmnd_len
== 6 || iop
->cmnd_len
== 10 || iop
->cmnd_len
== 12 || iop
->cmnd_len
== 16)) {
1962 pout("do_scsi_cmnd_io: bad CDB length\n");
1969 const unsigned char * ucp
= iop
->cmnd
;
1972 const int sz
= (int)sizeof(buff
);
1974 np
= scsi_get_opcode_name(ucp
[0]);
1975 j
= snprintf(buff
, sz
, " [%s: ", np
? np
: "<unknown opcode>");
1976 for (k
= 0; k
< (int)iop
->cmnd_len
; ++k
)
1977 j
+= snprintf(&buff
[j
], (sz
> j
? (sz
- j
) : 0), "%02x ", ucp
[k
]);
1979 (DXFER_TO_DEVICE
== iop
->dxfer_dir
) && (iop
->dxferp
)) {
1980 int trunc
= (iop
->dxfer_len
> 256) ? 1 : 0;
1982 j
+= snprintf(&buff
[j
], (sz
> j
? (sz
- j
) : 0), "]\n Outgoing "
1983 "data, len=%d%s:\n", (int)iop
->dxfer_len
,
1984 (trunc
? " [only first 256 bytes shown]" : ""));
1985 dStrHex(iop
->dxferp
, (trunc
? 256 : iop
->dxfer_len
) , 1);
1988 j
+= snprintf(&buff
[j
], (sz
> j
? (sz
- j
) : 0), "]\n");
1992 memset(&srb
, 0, sizeof(srb
));
1993 srb
.h
.cmd
= ASPI_CMD_EXECUTE_IO
;
1994 srb
.h
.adapter
= ((fd
>> 4) & 0xf);
1995 srb
.i
.target_id
= (fd
& 0xf);
1997 srb
.i
.sense_size
= ASPI_SENSE_SIZE
;
1998 srb
.i
.cdb_size
= iop
->cmnd_len
;
1999 memcpy(srb
.i
.cdb
, iop
->cmnd
, iop
->cmnd_len
);
2001 switch (iop
->dxfer_dir
) {
2003 srb
.h
.flags
= ASPI_REQFLAG_DIR_NO_XFER
;
2005 case DXFER_FROM_DEVICE
:
2006 srb
.h
.flags
= ASPI_REQFLAG_DIR_TO_HOST
;
2007 srb
.i
.data_size
= iop
->dxfer_len
;
2008 srb
.i
.data_addr
= iop
->dxferp
;
2010 case DXFER_TO_DEVICE
:
2011 srb
.h
.flags
= ASPI_REQFLAG_DIR_TO_TARGET
;
2012 srb
.i
.data_size
= iop
->dxfer_len
;
2013 srb
.i
.data_addr
= iop
->dxferp
;
2016 pout("do_scsi_cmnd_io: bad dxfer_dir\n");
2020 iop
->resp_sense_len
= 0;
2021 iop
->scsi_status
= 0;
2024 if (aspi_io_call(&srb
, (iop
->timeout
? iop
->timeout
: 60))) {
2029 if (srb
.h
.status
!= ASPI_STATUS_NO_ERROR
) {
2030 if ( srb
.h
.status
== ASPI_STATUS_ERROR
2031 && srb
.i
.host_status
== ASPI_HSTATUS_NO_ERROR
2032 && srb
.i
.target_status
== ASPI_TSTATUS_CHECK_CONDITION
) {
2034 const unsigned char * sense
= ASPI_SRB_SENSE(&srb
.i
, iop
->cmnd_len
);
2035 int len
= (ASPI_SENSE_SIZE
< iop
->max_sense_len
? ASPI_SENSE_SIZE
: iop
->max_sense_len
);
2036 iop
->scsi_status
= SCSI_STATUS_CHECK_CONDITION
;
2037 if (len
> 0 && iop
->sensep
) {
2038 memcpy(iop
->sensep
, sense
, len
);
2039 iop
->resp_sense_len
= len
;
2041 pout(" >>> Sense buffer, len=%d:\n", (int)len
);
2042 dStrHex(iop
->sensep
, len
, 1);
2046 pout(" sense_key=%x asc=%x ascq=%x\n",
2047 sense
[2] & 0xf, sense
[12], sense
[13]);
2053 pout(" ASPI call failed, (0x%02x,0x%02x,0x%02x)\n", srb
.h
.status
, srb
.i
.host_status
, srb
.i
.target_status
);
2061 if (iop
->dxfer_dir
== DXFER_FROM_DEVICE
&& report
> 1) {
2062 int trunc
= (iop
->dxfer_len
> 256) ? 1 : 0;
2063 pout(" Incoming data, len=%d%s:\n", (int)iop
->dxfer_len
,
2064 (trunc
? " [only first 256 bytes shown]" : ""));
2065 dStrHex(iop
->dxferp
, (trunc
? 256 : iop
->dxfer_len
) , 1);