4 * Home page of code is: http://smartmontools.sourceforge.net
6 * Copyright (C) 2004-8 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.
21 #include <mach/mach.h>
22 #include <mach/mach_error.h>
23 #include <mach/mach_init.h>
24 #include <IOKit/IOCFPlugIn.h>
25 #include <IOKit/IOKitLib.h>
26 #include <IOKit/IOReturn.h>
27 #include <IOKit/IOBSD.h>
28 #include <IOKit/storage/IOBlockStorageDevice.h>
29 #include <IOKit/storage/IOStorageDeviceCharacteristics.h>
30 #include <IOKit/storage/IOMedia.h>
31 #include <IOKit/storage/ata/IOATAStorageDefines.h>
32 #include <IOKit/storage/ata/ATASMARTLib.h>
33 #include <CoreFoundation/CoreFoundation.h>
35 // No, I don't know why there isn't a header for this.
36 #define kIOATABlockStorageDeviceClass "IOATABlockStorageDevice"
44 #include "os_darwin.h"
46 // Needed by '-V' option (CVS versioning) of smartd/smartctl
47 const char *os_XXXX_c_cvsid
="$Id: os_darwin.cpp,v 1.20 2008/03/04 22:09:47 ballen4705 Exp $" \
48 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_DARWIN_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID
;
50 // Print examples for smartctl.
51 void print_smartctl_examples(){
52 printf("=================================================== SMARTCTL EXAMPLES =====\n\n");
54 " smartctl -a disk0 (Prints all SMART information)\n\n"
55 " smartctl -t long /dev/disk0 (Executes extended disk self-test)\n\n"
56 #ifdef HAVE_GETOPT_LONG
57 " smartctl --smart=on --saveauto=on /dev/rdisk0 (Enables SMART on first disk)\n\n"
58 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/disk0\n"
59 " (Prints Self-Test & Attribute errors)\n\n"
61 " smartctl -s on -S on /dev/rdisk0 (Enables SMART on first disk)\n\n"
62 " smartctl -A -l selftest -q errorsonly /dev/disk0\n"
63 " (Prints Self-Test & Attribute errors)\n\n"
65 " smartctl -a IOService:/MacRISC2PE/pci@f4000000/AppleMacRiscPCI/ata-6@D/AppleKauaiATA/ATADeviceNub@0/IOATABlockStorageDriver/IOATABlockStorageDevice\n"
66 " (You can use IOService: ...)\n\n"
67 " smartctl -c IODeviceTree:/pci@f4000000/ata-6@D/@0:0\n"
68 " (... Or IODeviceTree:)\n"
73 // tries to guess device type given the name (a path). See utility.h
75 int guess_device_type (const char* dev_name
) {
76 // Only ATA is supported right now, so that's what it'd better be.
77 dev_name
= dev_name
; // suppress unused warning.
78 return CONTROLLER_ATA
;
81 // Determine whether 'dev' is a SMART-capable device.
82 static bool is_smart_capable (io_object_t dev
) {
83 CFTypeRef smartCapableKey
;
84 CFDictionaryRef diskChars
;
86 // If the device has kIOPropertySMARTCapableKey, then it's capable,
87 // no matter what it looks like.
88 smartCapableKey
= IORegistryEntryCreateCFProperty
89 (dev
, CFSTR (kIOPropertySMARTCapableKey
),
90 kCFAllocatorDefault
, 0);
93 CFRelease (smartCapableKey
);
97 // If it's an kIOATABlockStorageDeviceClass then we're successful
98 // only if its ATA features indicate it supports SMART.
99 if (IOObjectConformsTo (dev
, kIOATABlockStorageDeviceClass
)
100 && (diskChars
= (CFDictionaryRef
)IORegistryEntryCreateCFProperty
101 (dev
, CFSTR (kIOPropertyDeviceCharacteristicsKey
),
102 kCFAllocatorDefault
, kNilOptions
)) != NULL
)
104 CFNumberRef diskFeatures
= NULL
;
105 UInt32 ataFeatures
= 0;
107 if (CFDictionaryGetValueIfPresent (diskChars
, CFSTR ("ATA Features"),
108 (const void **)&diskFeatures
))
109 CFNumberGetValue (diskFeatures
, kCFNumberLongType
,
111 CFRelease (diskChars
);
113 CFRelease (diskFeatures
);
115 return (ataFeatures
& kIOATAFeatureSMART
) != 0;
121 // makes a list of ATA or SCSI devices for the DEVICESCAN directive of
122 // smartd. Returns number N of devices, or -1 if out of
123 // memory. Allocates N+1 arrays: one of N pointers (devlist); the
124 // other N arrays each contain null-terminated character strings. In
125 // the case N==0, no arrays are allocated because the array of 0
126 // pointers has zero length, equivalent to calling malloc(0).
127 int make_device_names (char*** devlist
, const char* name
) {
130 io_object_t device
= MACH_PORT_NULL
;
134 // We treat all devices as ATA so long as they support SMARTLib.
135 if (strcmp (name
, "ATA") != 0)
138 err
= IOServiceGetMatchingServices
139 (kIOMasterPortDefault
, IOServiceMatching (kIOBlockStorageDeviceClass
), &i
);
140 if (err
!= kIOReturnSuccess
)
143 // Count the devices.
145 while ((device
= IOIteratorNext (i
)) != MACH_PORT_NULL
) {
146 if (is_smart_capable (device
))
148 IOObjectRelease (device
);
151 // Create an array of service names.
153 *devlist
= (char**)Calloc (result
, sizeof (char *));
157 while ((device
= IOIteratorNext (i
)) != MACH_PORT_NULL
) {
158 if (is_smart_capable (device
))
161 IORegistryEntryGetPath(device
, kIOServicePlane
, devName
);
162 (*devlist
)[index
] = CustomStrDup (devName
, true, __LINE__
, __FILE__
);
163 if (! (*devlist
)[index
])
167 IOObjectRelease (device
);
174 if (device
!= MACH_PORT_NULL
)
175 IOObjectRelease (device
);
179 for (index
= 0; index
< result
; index
++)
180 if ((*devlist
)[index
])
181 FreeNonZero ((*devlist
)[index
], 0, __LINE__
, __FILE__
);
182 FreeNonZero (*devlist
, result
* sizeof (char *), __LINE__
, __FILE__
);
187 // Information that we keep about each device.
191 IOCFPlugInInterface
**plugin
;
192 IOATASMARTInterface
**smartIf
;
195 // Like open(). Return non-negative integer handle, only used by the
196 // functions below. type=="ATA" or "SCSI". The return value is
197 // an index into the devices[] array. If the device can't be opened,
198 // sets errno and returns -1.
199 // Acceptable device names are:
205 int deviceopen(const char *pathname
, char *type
){
210 if (strcmp (type
, "ATA") != 0)
216 // Find a free device number.
217 for (devnum
= 0; devnum
< sizeof (devices
) / sizeof (devices
[0]); devnum
++)
218 if (! devices
[devnum
].ioob
)
220 if (devnum
== sizeof (devices
) / sizeof (devices
[0]))
227 if (strncmp (pathname
, "/dev/rdisk", 10) == 0)
228 devname
= pathname
+ 6;
229 else if (strncmp (pathname
, "/dev/disk", 9) == 0)
230 devname
= pathname
+ 5;
231 else if (strncmp (pathname
, "disk", 4) == 0)
232 // allow user to just say 'disk0'
238 CFMutableDictionaryRef matcher
;
239 matcher
= IOBSDNameMatching (kIOMasterPortDefault
, 0, devname
);
240 disk
= IOServiceGetMatchingService (kIOMasterPortDefault
, matcher
);
244 disk
= IORegistryEntryFromPath (kIOMasterPortDefault
, pathname
);
253 // Find a SMART-capable driver which is a parent of this device.
254 while (! is_smart_capable (disk
))
257 io_object_t prevdisk
= disk
;
259 // Find this device's parent and try again.
260 err
= IORegistryEntryGetParentEntry (disk
, kIOServicePlane
, &disk
);
261 if (err
!= kIOReturnSuccess
|| ! disk
)
264 IOObjectRelease (prevdisk
);
269 devices
[devnum
].ioob
= disk
;
274 devices
[devnum
].plugin
= NULL
;
275 devices
[devnum
].smartIf
= NULL
;
277 // Create an interface to the ATA SMART library.
278 if (IOCreatePlugInInterfaceForService (disk
,
279 kIOATASMARTUserClientTypeID
,
280 kIOCFPlugInInterfaceID
,
281 &devices
[devnum
].plugin
,
282 &dummy
) == kIOReturnSuccess
)
283 (*devices
[devnum
].plugin
)->QueryInterface
284 (devices
[devnum
].plugin
,
285 CFUUIDGetUUIDBytes ( kIOATASMARTInterfaceID
),
286 (void **)&devices
[devnum
].smartIf
);
292 // Like close(). Acts only on integer handles returned by
293 // deviceopen() above.
294 int deviceclose(int fd
){
295 if (devices
[fd
].smartIf
)
296 (*devices
[fd
].smartIf
)->Release (devices
[fd
].smartIf
);
297 if (devices
[fd
].plugin
)
298 IODestroyPlugInInterface (devices
[fd
].plugin
);
299 IOObjectRelease (devices
[fd
].ioob
);
300 devices
[fd
].ioob
= MACH_PORT_NULL
;
304 // Interface to ATA devices. See os_linux.cpp for the cannonical example.
305 // DETAILED DESCRIPTION OF ARGUMENTS
306 // device: is the integer handle provided by deviceopen()
307 // command: defines the different operations, see atacmds.h
308 // select: additional input data IF NEEDED (which log, which type of
310 // data: location to write output data, IF NEEDED (1 or 512 bytes).
311 // Note: not all commands use all arguments.
312 // RETURN VALUES (for all commands BUT command==STATUS_CHECK)
313 // -1 if the command failed
314 // 0 if the command succeeded,
315 // RETURN VALUES if command==STATUS_CHECK
316 // -1 if the command failed OR the disk SMART status can't be determined
317 // 0 if the command succeeded and disk SMART status is "OK"
318 // 1 if the command succeeded and disk SMART status is "FAILING"
320 // Things that aren't available in the Darwin interfaces:
321 // - Tests other than short and extended (in particular, can't run
322 // an immediate offline test)
323 // - Captive-mode tests, aborting tests
324 // - ability to switch automatic offline testing on or off
326 // Note that some versions of Darwin, at least 7H63 and earlier,
327 // have a buggy library that treats the boolean value in
328 // SMARTEnableDisableOperations, SMARTEnableDisableAutosave, and
329 // SMARTExecuteOffLineImmediate as always being true.
331 ata_command_interface(int fd
, smart_command_set command
,
332 int select
, char *data
)
334 IOATASMARTInterface
**ifp
= devices
[fd
].smartIf
;
335 IOATASMARTInterface
*smartIf
;
337 int timeoutCount
= 5;
351 err
= smartIf
->SMARTReturnStatus (ifp
, &is_failing
);
352 if (err
== kIOReturnSuccess
&& is_failing
)
358 err
= smartIf
->SMARTEnableDisableOperations (ifp
, command
== ENABLE
);
361 err
= smartIf
->SMARTEnableDisableAutosave (ifp
, select
!= 0);
363 case IMMEDIATE_OFFLINE
:
364 if (select
!= SHORT_SELF_TEST
&& select
!= EXTEND_SELF_TEST
)
369 err
= smartIf
->SMARTExecuteOffLineImmediate (ifp
,
370 select
== EXTEND_SELF_TEST
);
373 err
= smartIf
->SMARTReadData (ifp
, (ATASMARTData
*)data
);
375 case READ_THRESHOLDS
:
376 err
= smartIf
->SMARTReadDataThresholds (ifp
,
377 (ATASMARTDataThresholds
*)data
);
380 err
= smartIf
->SMARTReadLogAtAddress (ifp
, select
, data
, 512);
383 err
= smartIf
->SMARTWriteLogAtAddress (ifp
, select
, data
, 512);
388 err
= smartIf
->GetATAIdentifyData (ifp
, data
, 512, &dummy
);
389 if (err
!= kIOReturnSuccess
&& err
!= kIOReturnTimeout
390 && err
!= kIOReturnNotResponding
)
391 printf ("identify failed: %#x\n", (unsigned) err
);
392 if (err
== kIOReturnSuccess
&& isbigendian())
395 /* The system has already byte-swapped, undo it. */
396 for (i
= 0; i
< 256; i
+=2)
401 case CHECK_POWER_MODE
:
402 // The information is right there in the device registry, but how
403 // to get to it portably?
408 /* This bit is a bit strange. Apparently, when the drive is spun
409 down, the intended behaviour of these calls is that they fail,
410 return kIOReturnTimeout and then power the drive up. So if
411 you get a timeout, you have to try again to get the actual
412 command run, but the drive is already powering up so you can't
413 use this for CHECK_POWER_MODE. */
414 if (err
== kIOReturnTimeout
|| err
== kIOReturnNotResponding
)
416 } while ((err
== kIOReturnTimeout
|| err
== kIOReturnNotResponding
)
417 && timeoutCount
-- > 0);
418 if (err
== kIOReturnExclusiveAccess
)
420 return err
== kIOReturnSuccess
? 0 : -1;
423 // There's no special handling needed for hidden devices, the kernel
424 // must deal with them.
425 int escalade_command_interface(int fd
, int escalade_port
, int escalade_type
,
426 smart_command_set command
, int select
,
430 escalade_port
= escalade_port
;
431 escalade_type
= escalade_type
;
438 int marvell_command_interface(int fd
, smart_command_set command
,
439 int select
, char *data
)
448 int highpoint_command_interface(int fd
, smart_command_set command
, int select
, char *data
)
457 // Interface to SCSI devices. See os_linux.c
458 int do_scsi_cmnd_io(int fd
, struct scsi_cmnd_io
* iop
, int report
) {