4 * Home page of code is: http://smartmontools.sourceforge.net
6 * Copyright (C) 2004-6 Geoffrey Keating <geoffk@geoffk.org>
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.
20 #include <mach/mach.h>
21 #include <mach/mach_error.h>
22 #include <mach/mach_init.h>
23 #include <IOKit/IOCFPlugIn.h>
24 #include <IOKit/IOKitLib.h>
25 #include <IOKit/IOReturn.h>
26 #include <IOKit/IOBSD.h>
27 #include <IOKit/storage/IOBlockStorageDevice.h>
28 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
29 #include <IOKit/storage/IOMedia.h>
30 #include <IOKit/storage/ata/IOATAStorageDefines.h>
31 #include <IOKit/storage/ata/ATASMARTLib.h>
32 #include <CoreFoundation/CoreFoundation.h>
34 // No, I don't know why there isn't a header for this.
35 #define kIOATABlockStorageDeviceClass "IOATABlockStorageDevice"
43 #include "os_darwin.h"
45 // Needed by '-V' option (CVS versioning) of smartd/smartctl
46 const char *os_XXXX_c_cvsid
="$Id: os_darwin.cpp,v 1.18 2006/09/20 16:17:31 shattered Exp $" \
47 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_DARWIN_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID
;
49 // Print examples for smartctl.
50 void print_smartctl_examples(){
51 printf("=================================================== SMARTCTL EXAMPLES =====\n\n");
53 " smartctl -a disk0 (Prints all SMART information)\n\n"
54 " smartctl -t long /dev/disk0 (Executes extended disk self-test)\n\n"
55 #ifdef HAVE_GETOPT_LONG
56 " smartctl --smart=on --saveauto=on /dev/rdisk0 (Enables SMART on first disk)\n\n"
57 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/disk0\n"
58 " (Prints Self-Test & Attribute errors)\n\n"
60 " smartctl -s on -S on /dev/rdisk0 (Enables SMART on first disk)\n\n"
61 " smartctl -A -l selftest -q errorsonly /dev/disk0\n"
62 " (Prints Self-Test & Attribute errors)\n\n"
64 " smartctl -a IOService:/MacRISC2PE/pci@f4000000/AppleMacRiscPCI/ata-6@D/AppleKauaiATA/ATADeviceNub@0/IOATABlockStorageDriver/IOATABlockStorageDevice\n"
65 " (You can use IOService: ...)\n\n"
66 " smartctl -c IODeviceTree:/pci@f4000000/ata-6@D/@0:0\n"
67 " (... Or IODeviceTree:)\n"
72 // tries to guess device type given the name (a path). See utility.h
74 int guess_device_type (const char* dev_name
) {
75 // Only ATA is supported right now, so that's what it'd better be.
76 dev_name
= dev_name
; // suppress unused warning.
77 return CONTROLLER_ATA
;
80 // Determine whether 'dev' is a SMART-capable device.
81 static bool is_smart_capable (io_object_t dev
) {
82 CFTypeRef smartCapableKey
;
83 CFDictionaryRef diskChars
;
85 // If the device has kIOPropertySMARTCapableKey, then it's capable,
86 // no matter what it looks like.
87 smartCapableKey
= IORegistryEntryCreateCFProperty
88 (dev
, CFSTR (kIOPropertySMARTCapableKey
),
89 kCFAllocatorDefault
, 0);
92 CFRelease (smartCapableKey
);
96 // If it's an kIOATABlockStorageDeviceClass then we're successful
97 // only if its ATA features indicate it supports SMART.
98 if (IOObjectConformsTo (dev
, kIOATABlockStorageDeviceClass
)
99 && (diskChars
= (CFDictionaryRef
)IORegistryEntryCreateCFProperty
100 (dev
, CFSTR (kIOPropertyDeviceCharacteristicsKey
),
101 kCFAllocatorDefault
, kNilOptions
)) != NULL
)
103 CFNumberRef diskFeatures
= NULL
;
104 UInt32 ataFeatures
= 0;
106 if (CFDictionaryGetValueIfPresent (diskChars
, CFSTR ("ATA Features"),
107 (const void **)&diskFeatures
))
108 CFNumberGetValue (diskFeatures
, kCFNumberLongType
,
110 CFRelease (diskChars
);
112 CFRelease (diskFeatures
);
114 return (ataFeatures
& kIOATAFeatureSMART
) != 0;
120 // makes a list of ATA or SCSI devices for the DEVICESCAN directive of
121 // smartd. Returns number N of devices, or -1 if out of
122 // memory. Allocates N+1 arrays: one of N pointers (devlist); the
123 // other N arrays each contain null-terminated character strings. In
124 // the case N==0, no arrays are allocated because the array of 0
125 // pointers has zero length, equivalent to calling malloc(0).
126 int make_device_names (char*** devlist
, const char* name
) {
129 io_object_t device
= MACH_PORT_NULL
;
133 // We treat all devices as ATA so long as they support SMARTLib.
134 if (strcmp (name
, "ATA") != 0)
137 err
= IOServiceGetMatchingServices
138 (kIOMasterPortDefault
, IOServiceMatching (kIOBlockStorageDeviceClass
), &i
);
139 if (err
!= kIOReturnSuccess
)
142 // Count the devices.
144 while ((device
= IOIteratorNext (i
)) != MACH_PORT_NULL
) {
145 if (is_smart_capable (device
))
147 IOObjectRelease (device
);
150 // Create an array of service names.
152 *devlist
= (char**)Calloc (result
, sizeof (char *));
156 while ((device
= IOIteratorNext (i
)) != MACH_PORT_NULL
) {
157 if (is_smart_capable (device
))
160 IORegistryEntryGetPath(device
, kIOServicePlane
, devName
);
161 (*devlist
)[index
] = CustomStrDup (devName
, true, __LINE__
, __FILE__
);
162 if (! (*devlist
)[index
])
166 IOObjectRelease (device
);
173 if (device
!= MACH_PORT_NULL
)
174 IOObjectRelease (device
);
178 for (index
= 0; index
< result
; index
++)
179 if ((*devlist
)[index
])
180 FreeNonZero ((*devlist
)[index
], 0, __LINE__
, __FILE__
);
181 FreeNonZero (*devlist
, result
* sizeof (char *), __LINE__
, __FILE__
);
186 // Information that we keep about each device.
190 IOCFPlugInInterface
**plugin
;
191 IOATASMARTInterface
**smartIf
;
194 // Like open(). Return non-negative integer handle, only used by the
195 // functions below. type=="ATA" or "SCSI". The return value is
196 // an index into the devices[] array. If the device can't be opened,
197 // sets errno and returns -1.
198 // Acceptable device names are:
204 int deviceopen(const char *pathname
, char *type
){
209 if (strcmp (type
, "ATA") != 0)
215 // Find a free device number.
216 for (devnum
= 0; devnum
< sizeof (devices
) / sizeof (devices
[0]); devnum
++)
217 if (! devices
[devnum
].ioob
)
219 if (devnum
== sizeof (devices
) / sizeof (devices
[0]))
226 if (strncmp (pathname
, "/dev/rdisk", 10) == 0)
227 devname
= pathname
+ 6;
228 else if (strncmp (pathname
, "/dev/disk", 9) == 0)
229 devname
= pathname
+ 5;
230 else if (strncmp (pathname
, "disk", 4) == 0)
231 // allow user to just say 'disk0'
237 CFMutableDictionaryRef matcher
;
238 matcher
= IOBSDNameMatching (kIOMasterPortDefault
, 0, devname
);
239 disk
= IOServiceGetMatchingService (kIOMasterPortDefault
, matcher
);
243 disk
= IORegistryEntryFromPath (kIOMasterPortDefault
, pathname
);
252 // Find a SMART-capable driver which is a parent of this device.
253 while (! is_smart_capable (disk
))
256 io_object_t prevdisk
= disk
;
258 // Find this device's parent and try again.
259 err
= IORegistryEntryGetParentEntry (disk
, kIOServicePlane
, &disk
);
260 if (err
!= kIOReturnSuccess
|| ! disk
)
263 IOObjectRelease (prevdisk
);
268 devices
[devnum
].ioob
= disk
;
273 devices
[devnum
].plugin
= NULL
;
274 devices
[devnum
].smartIf
= NULL
;
276 // Create an interface to the ATA SMART library.
277 if (IOCreatePlugInInterfaceForService (disk
,
278 kIOATASMARTUserClientTypeID
,
279 kIOCFPlugInInterfaceID
,
280 &devices
[devnum
].plugin
,
281 &dummy
) == kIOReturnSuccess
)
282 (*devices
[devnum
].plugin
)->QueryInterface
283 (devices
[devnum
].plugin
,
284 CFUUIDGetUUIDBytes ( kIOATASMARTInterfaceID
),
285 (void **)&devices
[devnum
].smartIf
);
291 // Like close(). Acts only on integer handles returned by
292 // deviceopen() above.
293 int deviceclose(int fd
){
294 if (devices
[fd
].smartIf
)
295 (*devices
[fd
].smartIf
)->Release (devices
[fd
].smartIf
);
296 if (devices
[fd
].plugin
)
297 IODestroyPlugInInterface (devices
[fd
].plugin
);
298 IOObjectRelease (devices
[fd
].ioob
);
299 devices
[fd
].ioob
= MACH_PORT_NULL
;
303 // Interface to ATA devices. See os_linux.cpp for the cannonical example.
304 // DETAILED DESCRIPTION OF ARGUMENTS
305 // device: is the integer handle provided by deviceopen()
306 // command: defines the different operations, see atacmds.h
307 // select: additional input data IF NEEDED (which log, which type of
309 // data: location to write output data, IF NEEDED (1 or 512 bytes).
310 // Note: not all commands use all arguments.
311 // RETURN VALUES (for all commands BUT command==STATUS_CHECK)
312 // -1 if the command failed
313 // 0 if the command succeeded,
314 // RETURN VALUES if command==STATUS_CHECK
315 // -1 if the command failed OR the disk SMART status can't be determined
316 // 0 if the command succeeded and disk SMART status is "OK"
317 // 1 if the command succeeded and disk SMART status is "FAILING"
319 // Things that aren't available in the Darwin interfaces:
320 // - Tests other than short and extended (in particular, can't run
321 // an immediate offline test)
322 // - Captive-mode tests, aborting tests
323 // - ability to switch automatic offline testing on or off
325 // Note that some versions of Darwin, at least 7H63 and earlier,
326 // have a buggy library that treats the boolean value in
327 // SMARTEnableDisableOperations, SMARTEnableDisableAutosave, and
328 // SMARTExecuteOffLineImmediate as always being true.
330 ata_command_interface(int fd
, smart_command_set command
,
331 int select
, char *data
)
333 IOATASMARTInterface
**ifp
= devices
[fd
].smartIf
;
334 IOATASMARTInterface
*smartIf
;
336 int timeoutCount
= 2;
350 err
= smartIf
->SMARTReturnStatus (ifp
, &is_failing
);
351 if (err
== kIOReturnSuccess
&& is_failing
)
357 err
= smartIf
->SMARTEnableDisableOperations (ifp
, command
== ENABLE
);
360 err
= smartIf
->SMARTEnableDisableAutosave (ifp
, select
!= 0);
362 case IMMEDIATE_OFFLINE
:
363 if (select
!= SHORT_SELF_TEST
&& select
!= EXTEND_SELF_TEST
)
368 err
= smartIf
->SMARTExecuteOffLineImmediate (ifp
,
369 select
== EXTEND_SELF_TEST
);
372 err
= smartIf
->SMARTReadData (ifp
, (ATASMARTData
*)data
);
374 case READ_THRESHOLDS
:
375 err
= smartIf
->SMARTReadDataThresholds (ifp
,
376 (ATASMARTDataThresholds
*)data
);
379 err
= smartIf
->SMARTReadLogAtAddress (ifp
, select
, data
, 512);
382 err
= smartIf
->SMARTWriteLogAtAddress (ifp
, select
, data
, 512);
387 err
= smartIf
->GetATAIdentifyData (ifp
, data
, 512, &dummy
);
388 if (err
!= kIOReturnSuccess
)
389 printf ("identify failed: %d\n", (int) err
);
390 if (err
== kIOReturnSuccess
&& isbigendian())
393 /* The system has already byte-swapped, undo it. */
394 for (i
= 0; i
< 256; i
+=2)
399 case CHECK_POWER_MODE
:
400 // The information is right there in the device registry, but how
401 // to get to it portably?
406 /* This bit is a bit strange. Apparently, when the drive is spun
407 down, the intended behaviour of these calls is that they fail,
408 return kIOReturnTimeout and then power the drive up. So if
409 you get a timeout, you have to try again to get the actual
410 command run, but the drive is already powering up so you can't
411 use this for CHECK_POWER_MODE. */
412 } while (err
== kIOReturnTimeout
&& timeoutCount
-- > 0);
413 if (err
== kIOReturnExclusiveAccess
)
415 return err
== kIOReturnSuccess
? 0 : -1;
418 // There's no special handling needed for hidden devices, the kernel
419 // must deal with them.
420 int escalade_command_interface(int fd
, int escalade_port
, int escalade_type
,
421 smart_command_set command
, int select
,
425 escalade_port
= escalade_port
;
426 escalade_type
= escalade_type
;
433 int marvell_command_interface(int fd
, smart_command_set command
,
434 int select
, char *data
)
443 int highpoint_command_interface(int fd
, smart_command_set command
, int select
, char *data
)
452 // Interface to SCSI devices. See os_linux.c
453 int do_scsi_cmnd_io(int fd
, struct scsi_cmnd_io
* iop
, int report
) {