]> git.proxmox.com Git - mirror_smartmontools-debian.git/blob - os_win32.cpp
Imported smartmontools-5.27.cvs20061002
[mirror_smartmontools-debian.git] / os_win32.cpp
1 /*
2 * os_win32.cpp
3 *
4 * Home page of code is: http://smartmontools.sourceforge.net
5 *
6 * Copyright (C) 2004-6 Christian Franke <smartmontools-support@lists.sourceforge.net>
7 *
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)
11 * any later version.
12 *
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.
16 *
17 */
18
19 #include "config.h"
20 #include "int64.h"
21 #include "atacmds.h"
22 #include "extern.h"
23 extern smartmonctrl * con; // con->permissive,reportataioctl
24 #include "scsicmds.h"
25 #include "utility.h"
26 extern int64_t bytes; // malloc() byte count
27
28 #include <errno.h>
29 #ifdef _DEBUG
30 #include <assert.h>
31 #else
32 #define assert(x) /**/
33 #endif
34 #define WIN32_LEAN_AND_MEAN
35 #include <windows.h>
36 #include <stddef.h> // offsetof()
37 #include <io.h> // access()
38
39 #define ARGUSED(x) ((void)(x))
40
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]
46
47
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;
51
52
53 #ifndef HAVE_GET_OS_VERSION_STR
54 #error define of HAVE_GET_OS_VERSION_STR missing in config.h
55 #endif
56
57 // Return build host and OS version as static string
58 const char * get_os_version_str()
59 {
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);
63
64 OSVERSIONINFOEXA vi;
65 const char * w;
66
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));
71
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))
78 return vstr;
79 }
80
81 if (vi.dwPlatformId > 0xff || vi.dwMajorVersion > 0xff || vi.dwMinorVersion > 0xff)
82 return vstr;
83
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"
96 : "xp-mc"); break;
97 case VER_PLATFORM_WIN32_NT <<16|0x0500| 2:
98 w = (!GetSystemMetrics(89/*SM_SERVERR2*/) ? "2003"
99 : "2003r2"); break;
100 case VER_PLATFORM_WIN32_NT <<16|0x0600| 0: w = "vista"; break;
101 default: w = 0; break;
102 }
103
104 if (!w)
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);
112 else
113 snprintf(vptr, vlen, "-%s", w);
114 return vstr;
115 }
116
117
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);
122
123 static int aspi_open(unsigned adapter, unsigned id);
124 static void aspi_close(int fd);
125 static int aspi_scan(unsigned long * drives);
126
127
128 static int is_permissive()
129 {
130 if (!con->permissive) {
131 pout("To continue, add one or more '-T permissive' options.\n");
132 return 0;
133 }
134 con->permissive--;
135 return 1;
136 }
137
138 static const char * skipdev(const char * s)
139 {
140 return (!strncmp(s, "/dev/", 5) ? s + 5 : s);
141 }
142
143
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)
147 {
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;
154 }
155
156
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)
162 {
163 unsigned long drives[3];
164 int rdriveno[2];
165 unsigned long rdrives[2];
166 int i, j, n, nmax, sz;
167 const char * path;
168
169 drives[0] = drives[1] = drives[2] = 0;
170 rdriveno[0] = rdriveno[1] = -1;
171 rdrives[0] = rdrives[1] = 0;
172
173 if (!strcmp(type, "ATA")) {
174 // bit i set => drive i present
175 n = ata_scan(drives, rdriveno, rdrives);
176 path = "/dev/hda";
177 nmax = 10;
178 }
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";
183 nmax = 10*8;
184 }
185 else
186 return -1;
187
188 if (n <= 0)
189 return 0;
190
191 // Alloc devlist
192 sz = n * sizeof(char **);
193 *devlist = (char **)malloc(sz); bytes += sz;
194
195 // Add devices
196 for (i = j = 0; i < n; ) {
197 while (j < nmax && !(drives[j >> 5] & (1L << (j & 0x1f))))
198 j++;
199 assert(j < nmax);
200
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)))
206 continue;
207 char rpath[20];
208 sprintf(rpath, "/dev/hd%c,%u", 'a'+j, pi);
209 sz = strlen(rpath)+1;
210 char * s = (char *)malloc(sz); bytes += sz;
211 strcpy(s, rpath);
212 (*devlist)[i++] = s;
213 }
214 }
215 else {
216 sz = strlen(path)+1;
217 char * s = (char *)malloc(sz); bytes += sz;
218 strcpy(s, path);
219
220 if (nmax <= 10) {
221 assert(j <= 9);
222 s[sz-2] += j; // /dev/hd[a-j]
223 }
224 else {
225 assert((j >> 3) <= 9);
226 s[sz-3] += (j >> 3); // /dev/scsi[0-9].....
227 s[sz-2] += (j & 0x7); // .....[0-7]
228 }
229 (*devlist)[i++] = s;
230 }
231 j++;
232 }
233
234 return n;
235 }
236
237
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)
243 {
244 int len;
245 pathname = skipdev(pathname);
246 len = strlen(pathname);
247
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);
254 }
255 // hd[a-j],N => Physical drive 0-9, RAID port N
256 drive[0] = 0; options[0] = 0; n1 = -1; n2 = -1;
257 unsigned port = ~0;
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);
261 }
262 }
263
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);
269 }
270 }
271
272 errno = EINVAL;
273 return -1;
274 }
275
276
277 // Like close(). Acts only on handles returned by above function.
278 // (Never called in smartctl!)
279 int deviceclose(int fd)
280 {
281 if ((fd & 0xff00) != 0x0100) {
282 ata_close(fd);
283 }
284 else {
285 aspi_close(fd);
286 }
287 return 0;
288 }
289
290
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"
301 #else
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"
306 #endif
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"
311 "\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()
317 );
318 }
319
320
321 /////////////////////////////////////////////////////////////////////////////
322 // ATA Interface
323 /////////////////////////////////////////////////////////////////////////////
324
325 // SMART_* IOCTLs, also known as DFP_* (Disk Fault Protection)
326
327 // Deklarations from:
328 // http://cvs.sourceforge.net/viewcvs.py/mingw/w32api/include/ddk/ntdddisk.h?rev=1.3
329
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))
334
335 #define FILE_DEVICE_DISK 7
336 #define IOCTL_DISK_BASE FILE_DEVICE_DISK
337
338 #define SMART_GET_VERSION \
339 CTL_CODE(IOCTL_DISK_BASE, 0x0020, METHOD_BUFFERED, FILE_READ_ACCESS)
340
341 #define SMART_SEND_DRIVE_COMMAND \
342 CTL_CODE(IOCTL_DISK_BASE, 0x0021, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
343
344 #define SMART_RCV_DRIVE_DATA \
345 CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
346
347 ASSERT_CONST(SMART_GET_VERSION , 0x074080);
348 ASSERT_CONST(SMART_SEND_DRIVE_COMMAND, 0x07c084);
349 ASSERT_CONST(SMART_RCV_DRIVE_DATA , 0x07c088);
350
351 #define SMART_CYL_LOW 0x4F
352 #define SMART_CYL_HI 0xC2
353
354
355 #pragma pack(1)
356
357 typedef struct _GETVERSIONOUTPARAMS {
358 UCHAR bVersion;
359 UCHAR bRevision;
360 UCHAR bReserved;
361 UCHAR bIDEDeviceMap;
362 ULONG fCapabilities;
363 ULONG dwReserved[4];
364 } GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;
365
366 ASSERT_SIZEOF(GETVERSIONOUTPARAMS, 24);
367
368
369 #define SMART_VENDOR_3WARE 0x13C1 // identifies 3ware specific parameters
370
371 typedef struct _GETVERSIONINPARAMS_EX {
372 BYTE bVersion;
373 BYTE bRevision;
374 BYTE bReserved;
375 BYTE bIDEDeviceMap;
376 DWORD fCapabilities;
377 DWORD dwDeviceMapEx; // 3ware specific: RAID drive bit map
378 WORD wIdentifier; // Vendor specific identifier
379 WORD wControllerId; // 3ware specific: Controller ID (0,1,...)
380 ULONG dwReserved[2];
381 } GETVERSIONINPARAMS_EX, *PGETVERSIONINPARAMS_EX, *LPGETVERSIONINPARAMS_EX;
382
383 ASSERT_SIZEOF(GETVERSIONINPARAMS_EX, sizeof(GETVERSIONOUTPARAMS));
384
385
386 typedef struct _IDEREGS {
387 UCHAR bFeaturesReg;
388 UCHAR bSectorCountReg;
389 UCHAR bSectorNumberReg;
390 UCHAR bCylLowReg;
391 UCHAR bCylHighReg;
392 UCHAR bDriveHeadReg;
393 UCHAR bCommandReg;
394 UCHAR bReserved;
395 } IDEREGS, *PIDEREGS, *LPIDEREGS;
396
397 typedef struct _SENDCMDINPARAMS {
398 ULONG cBufferSize;
399 IDEREGS irDriveRegs;
400 UCHAR bDriveNumber;
401 UCHAR bReserved[3];
402 ULONG dwReserved[4];
403 UCHAR bBuffer[1];
404 } SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
405
406 ASSERT_SIZEOF(SENDCMDINPARAMS, 32+1);
407
408 typedef struct _SENDCMDINPARAMS_EX {
409 DWORD cBufferSize;
410 IDEREGS irDriveRegs;
411 BYTE bDriveNumber;
412 BYTE bPortNumber; // 3ware specific: port number
413 WORD wIdentifier; // Vendor specific identifier
414 DWORD dwReserved[4];
415 BYTE bBuffer[1];
416 } SENDCMDINPARAMS_EX, *PSENDCMDINPARAMS_EX, *LPSENDCMDINPARAMS_EX;
417
418 ASSERT_SIZEOF(SENDCMDINPARAMS_EX, sizeof(SENDCMDINPARAMS));
419
420
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
433 */
434
435 typedef struct _DRIVERSTATUS {
436 UCHAR bDriverError;
437 UCHAR bIDEError;
438 UCHAR bReserved[2];
439 ULONG dwReserved[2];
440 } DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;
441
442 typedef struct _SENDCMDOUTPARAMS {
443 ULONG cBufferSize;
444 DRIVERSTATUS DriverStatus;
445 UCHAR bBuffer[1];
446 } SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
447
448 ASSERT_SIZEOF(SENDCMDOUTPARAMS, 16+1);
449
450 #pragma pack()
451
452
453 /////////////////////////////////////////////////////////////////////////////
454
455 static void print_ide_regs(const IDEREGS * r, int out)
456 {
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);
460 }
461
462 static void print_ide_regs_io(const IDEREGS * ri, const IDEREGS * ro)
463 {
464 pout(" Input : "); print_ide_regs(ri, 0);
465 if (ro) {
466 pout(" Output: "); print_ide_regs(ro, 1);
467 }
468 }
469
470 /////////////////////////////////////////////////////////////////////////////
471
472 // call SMART_GET_VERSION, return device map or -1 on error
473
474 static int smart_get_version(HANDLE hdevice, unsigned long * portmap = 0)
475 {
476 GETVERSIONOUTPARAMS vers;
477 const GETVERSIONINPARAMS_EX & vers_ex = (const GETVERSIONINPARAMS_EX &)vers;
478 DWORD num_out;
479
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());
485 errno = ENOSYS;
486 return -1;
487 }
488 assert(num_out == sizeof(GETVERSIONOUTPARAMS));
489
490 if (portmap) {
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);
495 errno = ENOENT;
496 return -1;
497 }
498 *portmap = vers_ex.dwDeviceMapEx;
499 }
500
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);
509 }
510
511 // TODO: Check vers.fCapabilities here?
512 return vers.bIDEDeviceMap;
513 }
514
515
516 // call SMART_* ioctl
517
518 static int smart_ioctl(HANDLE hdevice, int drive, IDEREGS * regs, char * data, unsigned datasize, int port)
519 {
520 SENDCMDINPARAMS inpar;
521 SENDCMDINPARAMS_EX & inpar_ex = (SENDCMDINPARAMS_EX &)inpar;
522
523 unsigned char outbuf[sizeof(SENDCMDOUTPARAMS)-1 + 512];
524 const SENDCMDOUTPARAMS * outpar;
525 DWORD code, num_out;
526 unsigned int size_out;
527 const char * name;
528
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;
534
535 if (port >= 0) {
536 // Set RAID port
537 inpar_ex.wIdentifier = SMART_VENDOR_3WARE;
538 inpar_ex.bPortNumber = port;
539 }
540
541 assert(datasize == 0 || datasize == 512);
542 if (datasize) {
543 code = SMART_RCV_DRIVE_DATA; name = "SMART_RCV_DRIVE_DATA";
544 inpar.cBufferSize = size_out = 512;
545 }
546 else {
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;
552 }
553 else
554 size_out = 0;
555 }
556
557 memset(&outbuf, 0, sizeof(outbuf));
558
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);
566 }
567 errno = ( err == ERROR_INVALID_FUNCTION /*9x*/
568 || err == ERROR_INVALID_PARAMETER/*NT/2K/XP*/ ? ENOSYS : EIO);
569 return -1;
570 }
571 // NOTE: On Win9x, inpar.irDriveRegs now contains the returned regs
572
573 outpar = (const SENDCMDOUTPARAMS *)outbuf;
574
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);
580 }
581 errno = (!outpar->DriverStatus.bIDEError ? ENOSYS : EIO);
582 return -1;
583 }
584
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));
590 }
591
592 if (datasize)
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;
601 }
602 }
603
604 return 0;
605 }
606
607
608 /////////////////////////////////////////////////////////////////////////////
609
610 // IDE PASS THROUGH (2000, XP, undocumented)
611 //
612 // Based on WinATA.cpp, 2002 c't/Matthias Withopf
613 // ftp://ftp.heise.de/pub/ct/listings/0207-218.zip
614
615 #define FILE_DEVICE_CONTROLLER 4
616 #define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER
617
618 #define IOCTL_IDE_PASS_THROUGH \
619 CTL_CODE(IOCTL_SCSI_BASE, 0x040A, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
620
621 ASSERT_CONST(IOCTL_IDE_PASS_THROUGH, 0x04d028);
622
623 #pragma pack(1)
624
625 typedef struct {
626 IDEREGS IdeReg;
627 ULONG DataBufferSize;
628 UCHAR DataBuffer[1];
629 } ATA_PASS_THROUGH;
630
631 ASSERT_SIZEOF(ATA_PASS_THROUGH, 12+1);
632
633 #pragma pack()
634
635
636 /////////////////////////////////////////////////////////////////////////////
637
638 static int ide_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, unsigned datasize)
639 {
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);
642 DWORD num_out;
643 const unsigned char magic = 0xcf;
644
645 if (!buf) {
646 errno = ENOMEM;
647 return -1;
648 }
649
650 buf->IdeReg = *regs;
651 buf->DataBufferSize = datasize;
652 if (datasize)
653 buf->DataBuffer[0] = magic;
654
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);
661 }
662 VirtualFree(buf, 0, MEM_RELEASE);
663 errno = (err == ERROR_INVALID_FUNCTION ? ENOSYS : EIO);
664 return -1;
665 }
666
667 // Check ATA status
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);
672 }
673 VirtualFree(buf, 0, MEM_RELEASE);
674 errno = EIO;
675 return -1;
676 }
677
678 // Check and copy data
679 if (datasize) {
680 if ( num_out != size
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);
686 }
687 VirtualFree(buf, 0, MEM_RELEASE);
688 errno = EIO;
689 return -1;
690 }
691 memcpy(data, buf->DataBuffer, datasize);
692 }
693
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);
698 }
699 *regs = buf->IdeReg;
700
701 // Caution: VirtualFree() fails if parameter "dwSize" is nonzero
702 VirtualFree(buf, 0, MEM_RELEASE);
703 return 0;
704 }
705
706
707 /////////////////////////////////////////////////////////////////////////////
708
709 // ATA PASS THROUGH (Win2003, XP SP2)
710
711 #define IOCTL_ATA_PASS_THROUGH \
712 CTL_CODE(IOCTL_SCSI_BASE, 0x040B, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
713
714 ASSERT_CONST(IOCTL_ATA_PASS_THROUGH, 0x04d02c);
715
716 typedef struct _ATA_PASS_THROUGH_EX {
717 USHORT Length;
718 USHORT AtaFlags;
719 UCHAR PathId;
720 UCHAR TargetId;
721 UCHAR Lun;
722 UCHAR ReservedAsUchar;
723 ULONG DataTransferLength;
724 ULONG TimeOutValue;
725 ULONG ReservedAsUlong;
726 ULONG/*_PTR*/ DataBufferOffset;
727 UCHAR PreviousTaskFile[8];
728 UCHAR CurrentTaskFile[8];
729 } ATA_PASS_THROUGH_EX, *PATA_PASS_THROUGH_EX;
730
731 ASSERT_SIZEOF(ATA_PASS_THROUGH_EX, 40);
732
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
737
738
739 /////////////////////////////////////////////////////////////////////////////
740
741 static int ata_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, int datasize)
742 {
743 typedef struct {
744 ATA_PASS_THROUGH_EX apt;
745 ULONG Filler;
746 UCHAR ucDataBuf[512];
747 } ATA_PASS_THROUGH_EX_WITH_BUFFERS;
748
749 ATA_PASS_THROUGH_EX_WITH_BUFFERS ab;
750 IDEREGS * ctfregs;
751 unsigned int size;
752 DWORD num_out;
753 const unsigned char magic = 0xcf;
754
755 memset(&ab, 0, sizeof(ab));
756 ab.apt.Length = sizeof(ATA_PASS_THROUGH_EX);
757 //ab.apt.PathId = 0;
758 //ab.apt.TargetId = 0;
759 //ab.apt.Lun = 0;
760 ab.apt.TimeOutValue = 10;
761 size = offsetof(ATA_PASS_THROUGH_EX_WITH_BUFFERS, ucDataBuf);
762 ab.apt.DataBufferOffset = size;
763
764 if (datasize) {
765 if (!(0 <= datasize && datasize <= (int)sizeof(ab.ucDataBuf))) {
766 errno = EINVAL;
767 return -1;
768 }
769 ab.apt.AtaFlags = ATA_FLAGS_DATA_IN;
770 ab.apt.DataTransferLength = datasize;
771 size += datasize;
772 ab.ucDataBuf[0] = magic;
773 }
774 else {
775 //ab.apt.AtaFlags = 0;
776 //ab.apt.DataTransferLength = 0;
777 }
778
779 assert(sizeof(ab.apt.CurrentTaskFile) == sizeof(IDEREGS));
780 ctfregs = (IDEREGS *)ab.apt.CurrentTaskFile;
781 *ctfregs = *regs;
782
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);
789 }
790 errno = (err == ERROR_INVALID_FUNCTION ? ENOSYS : EIO);
791 return -1;
792 }
793
794 // Check and copy data
795 if (datasize) {
796 if ( num_out != size
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);
801 }
802 errno = EIO;
803 return -1;
804 }
805 memcpy(data, ab.ucDataBuf, datasize);
806 }
807
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);
811 }
812 *regs = *ctfregs;
813
814 return 0;
815 }
816
817
818 /////////////////////////////////////////////////////////////////////////////
819
820 // ATA PASS THROUGH via SCSI PASS THROUGH (WinNT4 only)
821
822 // Declarations from:
823 // http://cvs.sourceforge.net/viewcvs.py/mingw/w32api/include/ddk/ntddscsi.h?rev=1.2
824
825 #define IOCTL_SCSI_PASS_THROUGH \
826 CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
827
828 ASSERT_CONST(IOCTL_SCSI_PASS_THROUGH, 0x04d004);
829
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
835
836 typedef struct _SCSI_PASS_THROUGH {
837 USHORT Length;
838 UCHAR ScsiStatus;
839 UCHAR PathId;
840 UCHAR TargetId;
841 UCHAR Lun;
842 UCHAR CdbLength;
843 UCHAR SenseInfoLength;
844 UCHAR DataIn;
845 ULONG DataTransferLength;
846 ULONG TimeOutValue;
847 ULONG/*_PTR*/ DataBufferOffset;
848 ULONG SenseInfoOffset;
849 UCHAR Cdb[16];
850 } SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH;
851
852 ASSERT_SIZEOF(SCSI_PASS_THROUGH, 44);
853
854
855 /////////////////////////////////////////////////////////////////////////////
856
857 static int ata_via_scsi_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, unsigned datasize)
858 {
859 typedef struct {
860 SCSI_PASS_THROUGH spt;
861 ULONG Filler;
862 UCHAR ucSenseBuf[32];
863 UCHAR ucDataBuf[512];
864 } SCSI_PASS_THROUGH_WITH_BUFFERS;
865
866 SCSI_PASS_THROUGH_WITH_BUFFERS sb;
867 IDEREGS * cdbregs;
868 unsigned int size;
869 DWORD num_out;
870 const unsigned char magic = 0xcf;
871
872 memset(&sb, 0, sizeof(sb));
873 sb.spt.Length = sizeof(SCSI_PASS_THROUGH);
874 //sb.spt.PathId = 0;
875 sb.spt.TargetId = 1;
876 //sb.spt.Lun = 0;
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;
882
883 if (datasize) {
884 if (datasize > sizeof(sb.ucDataBuf)) {
885 errno = EINVAL;
886 return -1;
887 }
888 sb.spt.DataIn = SCSI_IOCTL_DATA_IN;
889 sb.spt.DataTransferLength = datasize;
890 size += datasize;
891 sb.ucDataBuf[0] = magic;
892 }
893 else {
894 sb.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED;
895 //sb.spt.DataTransferLength = 0;
896 }
897
898 // Use pseudo SCSI command followed by registers
899 sb.spt.Cdb[0] = SCSIOP_ATA_PASSTHROUGH;
900 cdbregs = (IDEREGS *)(sb.spt.Cdb+2);
901 *cdbregs = *regs;
902
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);
909 return -1;
910 }
911
912 // Cannot check ATA status, because command does not return IDEREGS
913
914 // Check and copy data
915 if (datasize) {
916 if ( num_out != size
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);
921 }
922 errno = EIO;
923 return -1;
924 }
925 memcpy(data, sb.ucDataBuf, datasize);
926 }
927
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);
931 }
932 return 0;
933 }
934
935 /////////////////////////////////////////////////////////////////////////////
936
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)
940
941 static int get_device_power_state(HANDLE hdevice)
942 {
943 static HINSTANCE h_kernel_dll = 0;
944 #ifdef __CYGWIN__
945 static DWORD kernel_dll_pid = 0;
946 #endif
947 static BOOL (WINAPI * GetDevicePowerState_p)(HANDLE, BOOL *) = 0;
948
949 BOOL state = TRUE;
950
951 if (!GetDevicePowerState_p
952 #ifdef __CYGWIN__
953 || kernel_dll_pid != GetCurrentProcessId() // detect fork()
954 #endif
955 ) {
956 if (h_kernel_dll == INVALID_HANDLE_VALUE) {
957 errno = ENOSYS;
958 return -1;
959 }
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;
963 errno = ENOSYS;
964 return -1;
965 }
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;
972 errno = ENOSYS;
973 return -1;
974 }
975 #ifdef __CYGWIN__
976 kernel_dll_pid = GetCurrentProcessId();
977 #endif
978 }
979
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.
987 return -1;
988 }
989
990 if (con->reportataioctl > 1)
991 pout(" GetDevicePowerState() succeeded, state=%d\n", state);
992 return state;
993 }
994
995
996 /////////////////////////////////////////////////////////////////////////////
997
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
1004
1005 // Print SMARTVSD error message, return errno
1006
1007 static int smartvsd_error()
1008 {
1009 char path[MAX_PATH];
1010 unsigned len;
1011 if (!(5 <= (len = GetSystemDirectoryA(path, MAX_PATH)) && len < MAX_PATH/2))
1012 return ENOENT;
1013 // SMARTVSD.VXD present?
1014 strcpy(path+len, "\\IOSUBSYS\\SMARTVSD.VXD");
1015 if (!access(path, 0)) {
1016 // Yes, standard IDE driver used?
1017 HANDLE h;
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");
1023 return ENOENT;
1024 }
1025 else {
1026 if (h != INVALID_HANDLE_VALUE) // should not happen
1027 CloseHandle(h);
1028 pout("SMART driver SMARTVSD.VXD is installed, but not loaded.\n");
1029 return ENOSYS;
1030 }
1031 }
1032 else {
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).
1037 path[len] = 0;
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);
1041 }
1042 else {
1043 // Some Windows versions do not provide SMARTVSD.VXD
1044 // (http://support.microsoft.com/kb/199886/en-us).
1045 path[len] = 0;
1046 pout("SMARTVSD.VXD is missing in folder \"%s\\IOSUBSYS\".\n", path);
1047 }
1048 return ENOSYS;
1049 }
1050 }
1051
1052
1053 // Get default ATA device options
1054
1055 static const char * ata_get_def_options()
1056 {
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
1064 }
1065
1066
1067 // Open ATA device
1068
1069 static int ata_open(int drive, const char * options, int port)
1070 {
1071 int win9x;
1072 char devpath[30];
1073 int devmap;
1074
1075 // TODO: This version does not allow to open more than 1 ATA devices
1076 if (h_ata_ioctl) {
1077 errno = ENFILE;
1078 return -1;
1079 }
1080
1081 win9x = ((GetVersion() & 0x80000000) != 0);
1082
1083 if (!(0 <= drive && drive <= (win9x ? 7 : 9))) {
1084 errno = ENOENT;
1085 return -1;
1086 }
1087
1088 // path depends on Windows Version
1089 if (win9x)
1090 // Use patched "smartvse.vxd" for drives 4-7, see INSTALL file for details
1091 strcpy(devpath, (drive <= 3 ? "\\\\.\\SMARTVSD" : "\\\\.\\SMARTVSE"));
1092 else
1093 snprintf(devpath, sizeof(devpath)-1, "\\\\.\\PhysicalDrive%d", drive);
1094
1095 // Open device
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) {
1104 if (!win9x)
1105 pout("Administrator rights are necessary to access physical drives.\n");
1106 errno = EACCES;
1107 }
1108 else
1109 errno = EIO;
1110 h_ata_ioctl = 0;
1111 return -1;
1112 }
1113
1114 if (con->reportataioctl > 1)
1115 pout("%s: successfully opened\n", devpath);
1116
1117 // Save options
1118 if (!*options) {
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
1123 }
1124 ata_cur_options = strdup(options);
1125
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)
1129 return 0;
1130
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));
1135 if (devmap < 0) {
1136 if (!is_permissive()) {
1137 ata_close(0);
1138 errno = ENOSYS;
1139 return -1;
1140 }
1141 devmap = 0x0f;
1142 }
1143 ata_smartver_state[drive] = 1;
1144
1145 if (port >= 0) {
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()) {
1150 ata_close(0);
1151 errno = ENOENT;
1152 return -1;
1153 }
1154 }
1155 // Encode port into pseudo fd
1156 return (0x0200 | port);
1157 }
1158
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()) {
1168 ata_close(0);
1169 errno = (atapi ? ENOSYS : ENOENT);
1170 return -1;
1171 }
1172 }
1173 // Use drive number as fd for ioctl
1174 return (drive & 0x3);
1175 }
1176
1177
1178 static void ata_close(int fd)
1179 {
1180 ARGUSED(fd);
1181 CloseHandle(h_ata_ioctl);
1182 h_ata_ioctl = 0;
1183 if (ata_cur_options) {
1184 free(ata_cur_options);
1185 ata_cur_options = 0;
1186 }
1187 }
1188
1189
1190 // Scan for ATA drives, fill bitmask of drives present, return #drives
1191
1192 static int ata_scan(unsigned long * drives, int * rdriveno, unsigned long * rdrives)
1193 {
1194 int win9x = ((GetVersion() & 0x80000000) != 0);
1195 int cnt = 0, i;
1196
1197 for (i = 0; i <= 9; i++) {
1198 char devpath[30];
1199 GETVERSIONOUTPARAMS vers;
1200 const GETVERSIONINPARAMS_EX & vers_ex = (const GETVERSIONINPARAMS_EX &)vers;
1201 DWORD num_out;
1202 HANDLE h;
1203 if (win9x)
1204 strcpy(devpath, "\\\\.\\SMARTVSD");
1205 else
1206 snprintf(devpath, sizeof(devpath)-1, "\\\\.\\PhysicalDrive%d", i);
1207
1208 // Open device
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());
1214 if (win9x)
1215 break; // SMARTVSD.VXD missing or no ATA devices
1216 continue; // Disk not found or access denied (break;?)
1217 }
1218
1219 // Get drive map
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());
1225 CloseHandle(h);
1226 if (win9x)
1227 break; // Should not happen
1228 continue; // Non ATA disk or no SMART ioctl support (possibly SCSI disk)
1229 }
1230 CloseHandle(h);
1231
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);
1240 }
1241
1242 if (win9x) {
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);
1246 break;
1247 }
1248
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)
1252 continue;
1253 assert(rdrives[vers_ex.wControllerId] == 0);
1254 // Count physical drives
1255 int pcnt = 0;
1256 for (int pi = 0; pi < 32; pi++) {
1257 if (vers_ex.dwDeviceMapEx & (1L << pi))
1258 pcnt++;
1259 }
1260 if (!pcnt)
1261 continue; // Should not happen
1262 rdrives[vers_ex.wControllerId] = vers_ex.dwDeviceMapEx;
1263 rdriveno[vers_ex.wControllerId] = i;
1264 cnt += pcnt-1;
1265 }
1266
1267 // ATA drive exists and driver supports SMART ioctl
1268 drives[0] |= (1L << i);
1269 cnt++;
1270 }
1271
1272 return cnt;
1273 }
1274
1275
1276 /////////////////////////////////////////////////////////////////////////////
1277
1278 // Interface to ATA devices. See os_linux.c
1279 int ata_command_interface(int fd, smart_command_set command, int select, char * data)
1280 {
1281 IDEREGS regs;
1282 int datasize;
1283 const char * valid_options;
1284 int i;
1285
1286 int port = -1;
1287 if ((fd & ~0x1f) == 0x0200) {
1288 // RAID Port encoded into pseudo fd
1289 port = fd & 0x1f;
1290 fd = 0;
1291 }
1292
1293 if (!(0 <= fd && fd <= 3)) {
1294 errno = EBADF;
1295 return -1;
1296 }
1297
1298 // CMD,CYL default to SMART, changed by P?IDENTIFY and CHECK_POWER_MODE
1299 memset(&regs, 0, sizeof(regs));
1300 regs.bCommandReg = ATA_SMART_CMD;
1301 regs.bCylHighReg = SMART_CYL_HI; regs.bCylLowReg = SMART_CYL_LOW;
1302 datasize = 0;
1303
1304 // Try all IOCTLS by default: SMART_*, ATA_, IDE_, SCSI_PASS_THROUGH
1305 valid_options = "saic";
1306
1307 switch (command) {
1308 case WRITE_LOG:
1309 // TODO. Requires DATA OUT support
1310 errno = ENOSYS;
1311 return -1;
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]
1318 break;
1319 case READ_VALUES:
1320 regs.bFeaturesReg = ATA_SMART_READ_VALUES;
1321 regs.bSectorNumberReg = regs.bSectorCountReg = 1;
1322 datasize = 512;
1323 break;
1324 case READ_THRESHOLDS:
1325 regs.bFeaturesReg = ATA_SMART_READ_THRESHOLDS;
1326 regs.bSectorNumberReg = regs.bSectorCountReg = 1;
1327 datasize = 512;
1328 break;
1329 case READ_LOG:
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
1334 datasize = 512;
1335 break;
1336 case IDENTIFY:
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;
1342 datasize = 512;
1343 break;
1344 case PIDENTIFY:
1345 regs.bCommandReg = ATA_IDENTIFY_PACKET_DEVICE;
1346 regs.bCylLowReg = regs.bCylHighReg = 0;
1347 regs.bSectorCountReg = 1;
1348 datasize = 512;
1349 break;
1350 case ENABLE:
1351 regs.bFeaturesReg = ATA_SMART_ENABLE;
1352 regs.bSectorNumberReg = 1;
1353 break;
1354 case DISABLE:
1355 regs.bFeaturesReg = ATA_SMART_DISABLE;
1356 regs.bSectorNumberReg = 1;
1357 break;
1358 case STATUS_CHECK:
1359 valid_options = "sai"; // Needs IDE register return
1360 case STATUS:
1361 regs.bFeaturesReg = ATA_SMART_STATUS;
1362 break;
1363 case AUTO_OFFLINE:
1364 regs.bFeaturesReg = ATA_SMART_AUTO_OFFLINE;
1365 regs.bSectorCountReg = select; // YET NOTE - THIS IS A NON-DATA COMMAND!!
1366 break;
1367 case AUTOSAVE:
1368 regs.bFeaturesReg = ATA_SMART_AUTOSAVE;
1369 regs.bSectorCountReg = select; // YET NOTE - THIS IS A NON-DATA COMMAND!!
1370 break;
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
1375 break;
1376 default:
1377 pout("Unrecognized command %d in win32_ata_command_interface()\n"
1378 "Please contact " PACKAGE_BUGREPORT "\n", command);
1379 errno = ENOSYS;
1380 return -1;
1381 }
1382
1383 // Try all valid ioctls in the order specified in dev_ioctls;
1384 for (i = 0; ; i++) {
1385 char opt = ata_cur_options[i];
1386 int rc;
1387
1388 if (!opt) {
1389 // No IOCTL found
1390 errno = ENOSYS;
1391 return -1;
1392 }
1393 if (!strchr(valid_options, opt))
1394 // Invalid for this command
1395 continue;
1396
1397 errno = 0;
1398 assert(datasize == 0 || datasize == 512);
1399 switch (opt) {
1400 default: assert(0);
1401 case 's':
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;
1406 break;
1407 }
1408 if (!ata_smartver_state[ata_driveno]) {
1409 assert(port == -1);
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;
1416 break;
1417 }
1418 con->permissive--;
1419 }
1420 ata_smartver_state[ata_driveno] = 1;
1421 }
1422 rc = smart_ioctl(h_ata_ioctl, fd, &regs, data, datasize, port);
1423 break;
1424 case 'a':
1425 rc = ata_pass_through_ioctl(h_ata_ioctl, &regs, data, datasize);
1426 break;
1427 case 'i':
1428 rc = ide_pass_through_ioctl(h_ata_ioctl, &regs, data, datasize);
1429 break;
1430 case 'c':
1431 rc = ata_via_scsi_pass_through_ioctl(h_ata_ioctl, &regs, data, datasize);
1432 break;
1433 case 'p':
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*/);
1438 rc = 0;
1439 }
1440 break;
1441 }
1442
1443 if (!rc)
1444 // Working ioctl found
1445 break;
1446
1447 if (errno != ENOSYS)
1448 // Abort on I/O error
1449 return -1;
1450
1451 // CAUTION: *_ioctl() MUST NOT change "regs" Parameter in the ENOSYS case
1452 }
1453
1454 switch (command) {
1455 case CHECK_POWER_MODE:
1456 // Return power mode from SectorCountReg in data[0]
1457 data[0] = regs.bSectorCountReg;
1458 return 0;
1459
1460 case STATUS_CHECK:
1461 // Cyl low and Cyl high unchanged means "Good SMART status"
1462 if (regs.bCylHighReg == SMART_CYL_HI && regs.bCylLowReg == SMART_CYL_LOW)
1463 return 0;
1464
1465 // These values mean "Bad SMART status"
1466 if (regs.bCylHighReg == 0x2c && regs.bCylLowReg == 0xf4)
1467 return 1;
1468
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(&regs, 1);
1473 errno = EIO;
1474 return -1;
1475
1476 default:
1477 return 0;
1478 }
1479 /*NOTREACHED*/
1480 }
1481
1482
1483 #ifndef HAVE_ATA_IDENTIFY_IS_CACHED
1484 #error define of HAVE_ATA_IDENTIFY_IS_CACHED missing in config.h
1485 #endif
1486
1487 // Return true if OS caches the ATA identify sector
1488 int ata_identify_is_cached(int fd)
1489 {
1490 // Not RAID and WinNT4/2000/XP => true, RAID or Win9x/ME => false
1491 return (!(fd & 0xff00) && (GetVersion() & 0x80000000) == 0);
1492 }
1493
1494
1495 // Print not implemeted warning once
1496 static void pr_not_impl(const char * what, int * warned)
1497 {
1498 if (*warned)
1499 return;
1500 pout(
1501 "#######################################################################\n"
1502 "%s\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"
1507 "\n", what
1508 );
1509 *warned = 1;
1510 }
1511
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)
1514 {
1515 static int warned = 0;
1516 ARGUSED(fd); ARGUSED(escalade_type); ARGUSED(command); ARGUSED(select); ARGUSED(data);
1517 if (!warned) {
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);
1521 warned = 1;
1522 }
1523 errno = ENOSYS;
1524 return -1;
1525 }
1526
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)
1529 {
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);
1533 errno = ENOSYS;
1534 return -1;
1535 }
1536
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)
1539 {
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);
1543 errno = ENOSYS;
1544 return -1;
1545 }
1546
1547
1548 /////////////////////////////////////////////////////////////////////////////
1549 // ASPI Interface
1550 /////////////////////////////////////////////////////////////////////////////
1551
1552 #pragma pack(1)
1553
1554 #define ASPI_SENSE_SIZE 18
1555
1556 // ASPI SCSI Request block header
1557
1558 typedef struct {
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
1564 } ASPI_SRB_HEAD;
1565
1566 // SRB for host adapter inquiry
1567
1568 typedef struct {
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
1575 } ASPI_SRB_INQUIRY;
1576
1577 // SRB for get device type
1578
1579 typedef struct {
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
1585 } ASPI_SRB_DEVTYPE;
1586
1587 // SRB for SCSI I/O
1588
1589 typedef struct {
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];
1603 } ASPI_SRB_IO;
1604
1605 // Macro to retrieve start of sense information
1606 #define ASPI_SRB_SENSE(srb,cdbsz) ((srb)->cdb + 16)
1607
1608 // SRB union
1609
1610 typedef union {
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
1615 } ASPI_SRB;
1616
1617 #pragma pack()
1618
1619 // ASPI commands
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
1624
1625 // Request flags
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
1630
1631 // ASPI status
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
1641
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
1649
1650 // Target status
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
1655
1656
1657 static HINSTANCE h_aspi_dll; // DLL handle
1658 static UINT (* aspi_entry)(ASPI_SRB * srb); // ASPI entrypoint
1659 static unsigned num_aspi_adapters;
1660
1661 #ifdef __CYGWIN__
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()))
1665 #else
1666 #define aspi_entry_valid() (!!aspi_entry)
1667 #endif
1668
1669
1670 static int aspi_call(ASPI_SRB * srb)
1671 {
1672 int i;
1673 aspi_entry(srb);
1674 i = 0;
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);
1678 aspi_entry = 0;
1679 h_aspi_dll = (HINSTANCE)INVALID_HANDLE_VALUE;
1680 errno = EIO;
1681 return -1;
1682 }
1683 if (con->reportscsiioctl > 1)
1684 pout("ASPI Adapter %u: Waiting (%d) ...\n", srb->h.adapter, i);
1685 Sleep(100);
1686 }
1687 return 0;
1688 }
1689
1690
1691 // Get ASPI entrypoint from wnaspi32.dll
1692
1693 static FARPROC aspi_get_address(const char * name, int verbose)
1694 {
1695 FARPROC addr;
1696 assert(h_aspi_dll && h_aspi_dll != INVALID_HANDLE_VALUE);
1697
1698 if (!(addr = GetProcAddress(h_aspi_dll, name))) {
1699 if (verbose)
1700 pout("Missing %s() in WNASPI32.DLL\n", name);
1701 aspi_entry = 0;
1702 FreeLibrary(h_aspi_dll);
1703 h_aspi_dll = (HINSTANCE)INVALID_HANDLE_VALUE;
1704 errno = ENOSYS;
1705 return 0;
1706 }
1707 return addr;
1708 }
1709
1710
1711 static int aspi_open_dll(int verbose)
1712 {
1713 UINT (*aspi_info)(void);
1714 UINT info, rc;
1715
1716 assert(!aspi_entry_valid());
1717
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);
1729
1730 if (h_aspi_dll == INVALID_HANDLE_VALUE) {
1731 // do not retry
1732 errno = ENOENT;
1733 return -1;
1734 }
1735
1736 // Load ASPI DLL
1737 if (!(h_aspi_dll = LoadLibraryA("WNASPI32.DLL"))) {
1738 if (verbose)
1739 pout("Cannot load WNASPI32.DLL, Error=%ld\n", GetLastError());
1740 h_aspi_dll = (HINSTANCE)INVALID_HANDLE_VALUE;
1741 errno = ENOENT;
1742 return -1;
1743 }
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);
1750 }
1751
1752 // Get ASPI entrypoints
1753 if (!(aspi_info = (UINT (*)(void))aspi_get_address("GetASPI32SupportInfo", verbose)))
1754 return -1;
1755 if (!(aspi_entry = (UINT (*)(ASPI_SRB *))aspi_get_address("SendASPI32Command", verbose)))
1756 return -1;
1757
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;
1765 }
1766 else if (rc == ASPI_STATUS_NO_ERROR) {
1767 num_aspi_adapters = info & 0xff;
1768 }
1769 else {
1770 if (verbose)
1771 pout("Got strange 0x%04x from GetASPI32SupportInfo()\n", info);
1772 aspi_entry = 0;
1773 FreeLibrary(h_aspi_dll);
1774 h_aspi_dll = (HINSTANCE)INVALID_HANDLE_VALUE;
1775 errno = ENOENT;
1776 return -1;
1777 }
1778
1779 if (con->reportscsiioctl)
1780 pout("%u ASPI Adapter%s detected\n",num_aspi_adapters, (num_aspi_adapters!=1?"s":""));
1781
1782 #ifdef __CYGWIN__
1783 // save PID to detect fork() in aspi_entry_valid()
1784 aspi_dll_pid = GetCurrentProcessId();
1785 #endif
1786 assert(aspi_entry_valid());
1787 return 0;
1788 }
1789
1790
1791 static int aspi_io_call(ASPI_SRB * srb, unsigned timeout)
1792 {
1793 HANDLE event;
1794 // Create event
1795 if (!(event = CreateEventA(NULL, FALSE, FALSE, NULL))) {
1796 pout("CreateEvent(): Error=%ld\n", GetLastError()); return -EIO;
1797 }
1798 srb->i.event_handle = event;
1799 srb->h.flags |= ASPI_REQFLAG_EVENT_NOTIFY;
1800 // Start ASPI request
1801 aspi_entry(srb);
1802 if (((volatile ASPI_SRB *)srb)->h.status == ASPI_STATUS_IN_PROGRESS) {
1803 // Wait for event
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);
1809 }
1810 else {
1811 pout("WaitForSingleObject(%lx) = 0x%lx,%ld, Error=%ld\n",
1812 (unsigned long)event, rc, rc, GetLastError());
1813 }
1814 // TODO: ASPI_ABORT_IO command
1815 aspi_entry = 0;
1816 h_aspi_dll = (HINSTANCE)INVALID_HANDLE_VALUE;
1817 return -EIO;
1818 }
1819 }
1820 CloseHandle(event);
1821 return 0;
1822 }
1823
1824
1825 static int aspi_open(unsigned adapter, unsigned id)
1826 {
1827 ASPI_SRB srb;
1828 if (!(adapter <= 9 && id < 16)) {
1829 errno = ENOENT;
1830 return -1;
1831 }
1832
1833 if (!aspi_entry_valid()) {
1834 if (aspi_open_dll(1/*verbose*/))
1835 return -1;
1836 }
1837
1838 // Adapter OK?
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()) {
1843 errno = ENOENT;
1844 return -1;
1845 }
1846 }
1847
1848 // Device present ?
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)) {
1853 errno = EIO;
1854 return -1;
1855 }
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);
1860 return -1;
1861 }
1862 }
1863 else if (con->reportscsiioctl)
1864 pout("ASPI Adapter %u, ID %u: Device Type=0x%02x\n", adapter, id, srb.t.devtype);
1865
1866 return (0x0100 | ((adapter & 0xf)<<4) | (id & 0xf));
1867 }
1868
1869
1870 static void aspi_close(int fd)
1871 {
1872 // No FreeLibrary(h_aspi_dll) to prevent problems with ASPI threads
1873 ARGUSED(fd);
1874 }
1875
1876
1877 // Scan for SCSI drives, fill bitmask [adapter:0-9][id:0-7] of drives present,
1878 // return #drives
1879
1880 static int aspi_scan(unsigned long * drives)
1881 {
1882 int cnt = 0;
1883 unsigned ad;
1884
1885 if (!aspi_entry_valid()) {
1886 if (aspi_open_dll(con->reportscsiioctl/*default is quiet*/))
1887 return 0;
1888 }
1889
1890 for (ad = 0; ad < num_aspi_adapters; ad++) {
1891 ASPI_SRB srb; unsigned id;
1892
1893 if (ad > 9) {
1894 if (con->reportscsiioctl)
1895 pout(" ASPI Adapter %u: Ignored\n", ad);
1896 continue;
1897 }
1898
1899 // Get adapter name
1900 memset(&srb, 0, sizeof(srb));
1901 srb.h.cmd = ASPI_CMD_ADAPTER_INQUIRE;
1902 srb.h.adapter = ad;
1903 if (aspi_call(&srb))
1904 return 0;
1905
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);
1909 continue;
1910 }
1911
1912 if (con->reportscsiioctl) {
1913 int i;
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);
1918 }
1919
1920 bool ignore = !strnicmp(srb.q.adapter_id, "3ware", 5);
1921
1922 for (id = 0; id <= 7; id++) {
1923 // Get device type
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))
1928 return 0;
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);
1932 continue;
1933 }
1934
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));
1939 cnt++;
1940 }
1941 else if (con->reportscsiioctl)
1942 pout(" ID %u: Device Type=0x%02x (ignored)\n", id, srb.t.devtype);
1943 }
1944 }
1945 return cnt;
1946 }
1947
1948
1949 /////////////////////////////////////////////////////////////////////////////
1950
1951 // Interface to SCSI devices. See os_linux.c
1952 int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
1953 {
1954 ASPI_SRB srb;
1955
1956 if (!aspi_entry_valid())
1957 return -EBADF;
1958 if (!((fd & ~0xff) == 0x100))
1959 return -EBADF;
1960
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");
1963 return -EINVAL;
1964 }
1965
1966 if (report > 0) {
1967 // From os_linux.c
1968 int k, j;
1969 const unsigned char * ucp = iop->cmnd;
1970 const char * np;
1971 char buff[256];
1972 const int sz = (int)sizeof(buff);
1973
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]);
1978 if ((report > 1) &&
1979 (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
1980 int trunc = (iop->dxfer_len > 256) ? 1 : 0;
1981
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);
1986 }
1987 else
1988 j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");
1989 pout(buff);
1990 }
1991
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);
1996 //srb.i.lun = 0;
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);
2000
2001 switch (iop->dxfer_dir) {
2002 case DXFER_NONE:
2003 srb.h.flags = ASPI_REQFLAG_DIR_NO_XFER;
2004 break;
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;
2009 break;
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;
2014 break;
2015 default:
2016 pout("do_scsi_cmnd_io: bad dxfer_dir\n");
2017 return -EINVAL;
2018 }
2019
2020 iop->resp_sense_len = 0;
2021 iop->scsi_status = 0;
2022 iop->resid = 0;
2023
2024 if (aspi_io_call(&srb, (iop->timeout ? iop->timeout : 60))) {
2025 // Timeout
2026 return -EIO;
2027 }
2028
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) {
2033 // Sense valid
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;
2040 if (report > 1) {
2041 pout(" >>> Sense buffer, len=%d:\n", (int)len);
2042 dStrHex(iop->sensep, len , 1);
2043 }
2044 }
2045 if (report) {
2046 pout(" sense_key=%x asc=%x ascq=%x\n",
2047 sense[2] & 0xf, sense[12], sense[13]);
2048 }
2049 return 0;
2050 }
2051 else {
2052 if (report)
2053 pout(" ASPI call failed, (0x%02x,0x%02x,0x%02x)\n", srb.h.status, srb.i.host_status, srb.i.target_status);
2054 return -EIO;
2055 }
2056 }
2057
2058 if (report > 0)
2059 pout(" OK\n");
2060
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);
2066 }
2067
2068 return 0;
2069 }