|
smartmontools SVN Rev 3317
Utility to control and monitor storage systems with "S.M.A.R.T."
|
00001 /* 00002 * os_linux.cpp 00003 * 00004 * Home page of code is: http://smartmontools.sourceforge.net 00005 * 00006 * Copyright (C) 2003-11 Bruce Allen <smartmontools-support@lists.sourceforge.net> 00007 * Copyright (C) 2003-11 Doug Gilbert <dgilbert@interlog.com> 00008 * Copyright (C) 2008-12 Hank Wu <hank@areca.com.tw> 00009 * Copyright (C) 2008 Oliver Bock <brevilo@users.sourceforge.net> 00010 * Copyright (C) 2008-12 Christian Franke <smartmontools-support@lists.sourceforge.net> 00011 * Copyright (C) 2008 Jordan Hargrave <jordan_hargrave@dell.com> 00012 * 00013 * Parts of this file are derived from code that was 00014 * 00015 * Written By: Adam Radford <linux@3ware.com> 00016 * Modifications By: Joel Jacobson <linux@3ware.com> 00017 * Arnaldo Carvalho de Melo <acme@conectiva.com.br> 00018 * Brad Strand <linux@3ware.com> 00019 * 00020 * Copyright (C) 1999-2003 3ware Inc. 00021 * 00022 * Kernel compatablity By: Andre Hedrick <andre@suse.com> 00023 * Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com> 00024 * 00025 * Other ars of this file are derived from code that was 00026 * 00027 * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org> 00028 * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org> 00029 * 00030 * This program is free software; you can redistribute it and/or modify 00031 * it under the terms of the GNU General Public License as published by 00032 * the Free Software Foundation; either version 2, or (at your option) 00033 * any later version. 00034 * 00035 * You should have received a copy of the GNU General Public License 00036 * (for example COPYING); If not, see <http://www.gnu.org/licenses/>. 00037 * 00038 * This code was originally developed as a Senior Thesis by Michael Cornwell 00039 * at the Concurrent Systems Laboratory (now part of the Storage Systems 00040 * Research Center), Jack Baskin School of Engineering, University of 00041 * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ 00042 * 00043 */ 00044 00045 // This file contains the linux-specific IOCTL parts of 00046 // smartmontools. It includes one interface routine for ATA devices, 00047 // one for SCSI devices, and one for ATA devices behind escalade 00048 // controllers. 00049 00050 #include "config.h" 00051 00052 #include <errno.h> 00053 #include <fcntl.h> 00054 #include <glob.h> 00055 00056 #include <scsi/scsi.h> 00057 #include <scsi/scsi_ioctl.h> 00058 #include <scsi/sg.h> 00059 #include <stdlib.h> 00060 #include <string.h> 00061 #include <sys/ioctl.h> 00062 #include <sys/stat.h> 00063 #include <sys/utsname.h> 00064 #include <unistd.h> 00065 #include <stddef.h> // for offsetof() 00066 #include <sys/uio.h> 00067 #include <sys/types.h> 00068 #include <dirent.h> 00069 #ifndef makedev // old versions of types.h do not include sysmacros.h 00070 #include <sys/sysmacros.h> 00071 #endif 00072 #ifdef WITH_SELINUX 00073 #include <selinux/selinux.h> 00074 #endif 00075 00076 #include "int64.h" 00077 #include "atacmds.h" 00078 #include "os_linux.h" 00079 #include "scsicmds.h" 00080 #include "utility.h" 00081 #include "cciss.h" 00082 #include "megaraid.h" 00083 00084 #include "dev_interface.h" 00085 #include "dev_ata_cmd_set.h" 00086 #include "dev_areca.h" 00087 00088 #ifndef ENOTSUP 00089 #define ENOTSUP ENOSYS 00090 #endif 00091 00092 #define ARGUSED(x) ((void)(x)) 00093 00094 const char * os_linux_cpp_cvsid = "$Id: os_linux.cpp 3738 2012-12-17 12:01:35Z samm2 $" 00095 OS_LINUX_H_CVSID; 00096 extern unsigned char failuretest_permissive; 00097 00098 namespace os_linux { // No need to publish anything, name provided for Doxygen 00099 00100 ///////////////////////////////////////////////////////////////////////////// 00101 /// Shared open/close routines 00102 00103 class linux_smart_device 00104 : virtual public /*implements*/ smart_device 00105 { 00106 public: 00107 explicit linux_smart_device(int flags, int retry_flags = -1) 00108 : smart_device(never_called), 00109 m_fd(-1), 00110 m_flags(flags), m_retry_flags(retry_flags) 00111 { } 00112 00113 virtual ~linux_smart_device() throw(); 00114 00115 virtual bool is_open() const; 00116 00117 virtual bool open(); 00118 00119 virtual bool close(); 00120 00121 protected: 00122 /// Return filedesc for derived classes. 00123 int get_fd() const 00124 { return m_fd; } 00125 00126 void set_fd(int fd) 00127 { m_fd = fd; } 00128 00129 private: 00130 int m_fd; ///< filedesc, -1 if not open. 00131 int m_flags; ///< Flags for ::open() 00132 int m_retry_flags; ///< Flags to retry ::open(), -1 if no retry 00133 }; 00134 00135 linux_smart_device::~linux_smart_device() throw() 00136 { 00137 if (m_fd >= 0) 00138 ::close(m_fd); 00139 } 00140 00141 bool linux_smart_device::is_open() const 00142 { 00143 return (m_fd >= 0); 00144 } 00145 00146 bool linux_smart_device::open() 00147 { 00148 m_fd = ::open(get_dev_name(), m_flags); 00149 00150 if (m_fd < 0 && errno == EROFS && m_retry_flags != -1) 00151 // Retry 00152 m_fd = ::open(get_dev_name(), m_retry_flags); 00153 00154 if (m_fd < 0) { 00155 if (errno == EBUSY && (m_flags & O_EXCL)) 00156 // device is locked 00157 return set_err(EBUSY, 00158 "The requested controller is used exclusively by another process!\n" 00159 "(e.g. smartctl or smartd)\n" 00160 "Please quit the impeding process or try again later..."); 00161 return set_err((errno==ENOENT || errno==ENOTDIR) ? ENODEV : errno); 00162 } 00163 00164 if (m_fd >= 0) { 00165 // sets FD_CLOEXEC on the opened device file descriptor. The 00166 // descriptor is otherwise leaked to other applications (mail 00167 // sender) which may be considered a security risk and may result 00168 // in AVC messages on SELinux-enabled systems. 00169 if (-1 == fcntl(m_fd, F_SETFD, FD_CLOEXEC)) 00170 // TODO: Provide an error printing routine in class smart_interface 00171 pout("fcntl(set FD_CLOEXEC) failed, errno=%d [%s]\n", errno, strerror(errno)); 00172 } 00173 00174 return true; 00175 } 00176 00177 // equivalent to close(file descriptor) 00178 bool linux_smart_device::close() 00179 { 00180 int fd = m_fd; m_fd = -1; 00181 if (::close(fd) < 0) 00182 return set_err(errno); 00183 return true; 00184 } 00185 00186 // examples for smartctl 00187 static const char smartctl_examples[] = 00188 "=================================================== SMARTCTL EXAMPLES =====\n\n" 00189 " smartctl --all /dev/hda (Prints all SMART information)\n\n" 00190 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/hda\n" 00191 " (Enables SMART on first disk)\n\n" 00192 " smartctl --test=long /dev/hda (Executes extended disk self-test)\n\n" 00193 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/hda\n" 00194 " (Prints Self-Test & Attribute errors)\n" 00195 " smartctl --all --device=3ware,2 /dev/sda\n" 00196 " smartctl --all --device=3ware,2 /dev/twe0\n" 00197 " smartctl --all --device=3ware,2 /dev/twa0\n" 00198 " smartctl --all --device=3ware,2 /dev/twl0\n" 00199 " (Prints all SMART info for 3rd ATA disk on 3ware RAID controller)\n" 00200 " smartctl --all --device=hpt,1/1/3 /dev/sda\n" 00201 " (Prints all SMART info for the SATA disk attached to the 3rd PMPort\n" 00202 " of the 1st channel on the 1st HighPoint RAID controller)\n" 00203 " smartctl --all --device=areca,3/1 /dev/sg2\n" 00204 " (Prints all SMART info for 3rd ATA disk of the 1st enclosure\n" 00205 " on Areca RAID controller)\n" 00206 ; 00207 00208 ///////////////////////////////////////////////////////////////////////////// 00209 /// Linux ATA support 00210 00211 class linux_ata_device 00212 : public /*implements*/ ata_device_with_command_set, 00213 public /*extends*/ linux_smart_device 00214 { 00215 public: 00216 linux_ata_device(smart_interface * intf, const char * dev_name, const char * req_type); 00217 00218 protected: 00219 virtual int ata_command_interface(smart_command_set command, int select, char * data); 00220 }; 00221 00222 linux_ata_device::linux_ata_device(smart_interface * intf, const char * dev_name, const char * req_type) 00223 : smart_device(intf, dev_name, "ata", req_type), 00224 linux_smart_device(O_RDONLY | O_NONBLOCK) 00225 { 00226 } 00227 00228 // PURPOSE 00229 // This is an interface routine meant to isolate the OS dependent 00230 // parts of the code, and to provide a debugging interface. Each 00231 // different port and OS needs to provide it's own interface. This 00232 // is the linux one. 00233 // DETAILED DESCRIPTION OF ARGUMENTS 00234 // device: is the file descriptor provided by open() 00235 // command: defines the different operations. 00236 // select: additional input data if needed (which log, which type of 00237 // self-test). 00238 // data: location to write output data, if needed (512 bytes). 00239 // Note: not all commands use all arguments. 00240 // RETURN VALUES 00241 // -1 if the command failed 00242 // 0 if the command succeeded, 00243 // STATUS_CHECK routine: 00244 // -1 if the command failed 00245 // 0 if the command succeeded and disk SMART status is "OK" 00246 // 1 if the command succeeded and disk SMART status is "FAILING" 00247 00248 #define BUFFER_LENGTH (4+512) 00249 00250 int linux_ata_device::ata_command_interface(smart_command_set command, int select, char * data) 00251 { 00252 unsigned char buff[BUFFER_LENGTH]; 00253 // positive: bytes to write to caller. negative: bytes to READ from 00254 // caller. zero: non-data command 00255 int copydata=0; 00256 00257 const int HDIO_DRIVE_CMD_OFFSET = 4; 00258 00259 // See struct hd_drive_cmd_hdr in hdreg.h. Before calling ioctl() 00260 // buff[0]: ATA COMMAND CODE REGISTER 00261 // buff[1]: ATA SECTOR NUMBER REGISTER == LBA LOW REGISTER 00262 // buff[2]: ATA FEATURES REGISTER 00263 // buff[3]: ATA SECTOR COUNT REGISTER 00264 00265 // Note that on return: 00266 // buff[2] contains the ATA SECTOR COUNT REGISTER 00267 00268 // clear out buff. Large enough for HDIO_DRIVE_CMD (4+512 bytes) 00269 memset(buff, 0, BUFFER_LENGTH); 00270 00271 buff[0]=ATA_SMART_CMD; 00272 switch (command){ 00273 case CHECK_POWER_MODE: 00274 buff[0]=ATA_CHECK_POWER_MODE; 00275 copydata=1; 00276 break; 00277 case READ_VALUES: 00278 buff[2]=ATA_SMART_READ_VALUES; 00279 buff[3]=1; 00280 copydata=512; 00281 break; 00282 case READ_THRESHOLDS: 00283 buff[2]=ATA_SMART_READ_THRESHOLDS; 00284 buff[1]=buff[3]=1; 00285 copydata=512; 00286 break; 00287 case READ_LOG: 00288 buff[2]=ATA_SMART_READ_LOG_SECTOR; 00289 buff[1]=select; 00290 buff[3]=1; 00291 copydata=512; 00292 break; 00293 case WRITE_LOG: 00294 break; 00295 case IDENTIFY: 00296 buff[0]=ATA_IDENTIFY_DEVICE; 00297 buff[3]=1; 00298 copydata=512; 00299 break; 00300 case PIDENTIFY: 00301 buff[0]=ATA_IDENTIFY_PACKET_DEVICE; 00302 buff[3]=1; 00303 copydata=512; 00304 break; 00305 case ENABLE: 00306 buff[2]=ATA_SMART_ENABLE; 00307 buff[1]=1; 00308 break; 00309 case DISABLE: 00310 buff[2]=ATA_SMART_DISABLE; 00311 buff[1]=1; 00312 break; 00313 case STATUS: 00314 // this command only says if SMART is working. It could be 00315 // replaced with STATUS_CHECK below. 00316 buff[2]=ATA_SMART_STATUS; 00317 break; 00318 case AUTO_OFFLINE: 00319 // NOTE: According to ATAPI 4 and UP, this command is obsolete 00320 // select == 241 for enable but no data transfer. Use TASK ioctl. 00321 buff[1]=ATA_SMART_AUTO_OFFLINE; 00322 buff[2]=select; 00323 break; 00324 case AUTOSAVE: 00325 // select == 248 for enable but no data transfer. Use TASK ioctl. 00326 buff[1]=ATA_SMART_AUTOSAVE; 00327 buff[2]=select; 00328 break; 00329 case IMMEDIATE_OFFLINE: 00330 buff[2]=ATA_SMART_IMMEDIATE_OFFLINE; 00331 buff[1]=select; 00332 break; 00333 case STATUS_CHECK: 00334 // This command uses HDIO_DRIVE_TASK and has different syntax than 00335 // the other commands. 00336 buff[1]=ATA_SMART_STATUS; 00337 break; 00338 default: 00339 pout("Unrecognized command %d in linux_ata_command_interface()\n" 00340 "Please contact " PACKAGE_BUGREPORT "\n", command); 00341 errno=ENOSYS; 00342 return -1; 00343 } 00344 00345 // This command uses the HDIO_DRIVE_TASKFILE ioctl(). This is the 00346 // only ioctl() that can be used to WRITE data to the disk. 00347 if (command==WRITE_LOG) { 00348 unsigned char task[sizeof(ide_task_request_t)+512]; 00349 ide_task_request_t *reqtask=(ide_task_request_t *) task; 00350 task_struct_t *taskfile=(task_struct_t *) reqtask->io_ports; 00351 int retval; 00352 00353 memset(task, 0, sizeof(task)); 00354 00355 taskfile->data = 0; 00356 taskfile->feature = ATA_SMART_WRITE_LOG_SECTOR; 00357 taskfile->sector_count = 1; 00358 taskfile->sector_number = select; 00359 taskfile->low_cylinder = 0x4f; 00360 taskfile->high_cylinder = 0xc2; 00361 taskfile->device_head = 0; 00362 taskfile->command = ATA_SMART_CMD; 00363 00364 reqtask->data_phase = TASKFILE_OUT; 00365 reqtask->req_cmd = IDE_DRIVE_TASK_OUT; 00366 reqtask->out_size = 512; 00367 reqtask->in_size = 0; 00368 00369 // copy user data into the task request structure 00370 memcpy(task+sizeof(ide_task_request_t), data, 512); 00371 00372 if ((retval=ioctl(get_fd(), HDIO_DRIVE_TASKFILE, task))) { 00373 if (retval==-EINVAL) 00374 pout("Kernel lacks HDIO_DRIVE_TASKFILE support; compile kernel with CONFIG_IDE_TASKFILE_IO set\n"); 00375 return -1; 00376 } 00377 return 0; 00378 } 00379 00380 // There are two different types of ioctls(). The HDIO_DRIVE_TASK 00381 // one is this: 00382 if (command==STATUS_CHECK || command==AUTOSAVE || command==AUTO_OFFLINE){ 00383 int retval; 00384 00385 // NOT DOCUMENTED in /usr/src/linux/include/linux/hdreg.h. You 00386 // have to read the IDE driver source code. Sigh. 00387 // buff[0]: ATA COMMAND CODE REGISTER 00388 // buff[1]: ATA FEATURES REGISTER 00389 // buff[2]: ATA SECTOR_COUNT 00390 // buff[3]: ATA SECTOR NUMBER 00391 // buff[4]: ATA CYL LO REGISTER 00392 // buff[5]: ATA CYL HI REGISTER 00393 // buff[6]: ATA DEVICE HEAD 00394 00395 unsigned const char normal_lo=0x4f, normal_hi=0xc2; 00396 unsigned const char failed_lo=0xf4, failed_hi=0x2c; 00397 buff[4]=normal_lo; 00398 buff[5]=normal_hi; 00399 00400 if ((retval=ioctl(get_fd(), HDIO_DRIVE_TASK, buff))) { 00401 if (retval==-EINVAL) { 00402 pout("Error SMART Status command via HDIO_DRIVE_TASK failed"); 00403 pout("Rebuild older linux 2.2 kernels with HDIO_DRIVE_TASK support added\n"); 00404 } 00405 else 00406 syserror("Error SMART Status command failed"); 00407 return -1; 00408 } 00409 00410 // Cyl low and Cyl high unchanged means "Good SMART status" 00411 if (buff[4]==normal_lo && buff[5]==normal_hi) 00412 return 0; 00413 00414 // These values mean "Bad SMART status" 00415 if (buff[4]==failed_lo && buff[5]==failed_hi) 00416 return 1; 00417 00418 // We haven't gotten output that makes sense; print out some debugging info 00419 syserror("Error SMART Status command failed"); 00420 pout("Please get assistance from " PACKAGE_HOMEPAGE "\n"); 00421 pout("Register values returned from SMART Status command are:\n"); 00422 pout("ST =0x%02x\n",(int)buff[0]); 00423 pout("ERR=0x%02x\n",(int)buff[1]); 00424 pout("NS =0x%02x\n",(int)buff[2]); 00425 pout("SC =0x%02x\n",(int)buff[3]); 00426 pout("CL =0x%02x\n",(int)buff[4]); 00427 pout("CH =0x%02x\n",(int)buff[5]); 00428 pout("SEL=0x%02x\n",(int)buff[6]); 00429 return -1; 00430 } 00431 00432 #if 1 00433 // Note to people doing ports to other OSes -- don't worry about 00434 // this block -- you can safely ignore it. I have put it here 00435 // because under linux when you do IDENTIFY DEVICE to a packet 00436 // device, it generates an ugly kernel syslog error message. This 00437 // is harmless but frightens users. So this block detects packet 00438 // devices and make IDENTIFY DEVICE fail "nicely" without a syslog 00439 // error message. 00440 // 00441 // If you read only the ATA specs, it appears as if a packet device 00442 // *might* respond to the IDENTIFY DEVICE command. This is 00443 // misleading - it's because around the time that SFF-8020 was 00444 // incorporated into the ATA-3/4 standard, the ATA authors were 00445 // sloppy. See SFF-8020 and you will see that ATAPI devices have 00446 // *always* had IDENTIFY PACKET DEVICE as a mandatory part of their 00447 // command set, and return 'Command Aborted' to IDENTIFY DEVICE. 00448 if (command==IDENTIFY || command==PIDENTIFY){ 00449 unsigned short deviceid[256]; 00450 // check the device identity, as seen when the system was booted 00451 // or the device was FIRST registered. This will not be current 00452 // if the user has subsequently changed some of the parameters. If 00453 // device is a packet device, swap the command interpretations. 00454 if (!ioctl(get_fd(), HDIO_GET_IDENTITY, deviceid) && (deviceid[0] & 0x8000)) 00455 buff[0]=(command==IDENTIFY)?ATA_IDENTIFY_PACKET_DEVICE:ATA_IDENTIFY_DEVICE; 00456 } 00457 #endif 00458 00459 // We are now doing the HDIO_DRIVE_CMD type ioctl. 00460 if ((ioctl(get_fd(), HDIO_DRIVE_CMD, buff))) 00461 return -1; 00462 00463 // CHECK POWER MODE command returns information in the Sector Count 00464 // register (buff[3]). Copy to return data buffer. 00465 if (command==CHECK_POWER_MODE) 00466 buff[HDIO_DRIVE_CMD_OFFSET]=buff[2]; 00467 00468 // if the command returns data then copy it back 00469 if (copydata) 00470 memcpy(data, buff+HDIO_DRIVE_CMD_OFFSET, copydata); 00471 00472 return 0; 00473 } 00474 00475 // >>>>>> Start of general SCSI specific linux code 00476 00477 /* Linux specific code. 00478 * Historically smartmontools (and smartsuite before it) used the 00479 * SCSI_IOCTL_SEND_COMMAND ioctl which is available to all linux device 00480 * nodes that use the SCSI subsystem. A better interface has been available 00481 * via the SCSI generic (sg) driver but this involves the extra step of 00482 * mapping disk devices (e.g. /dev/sda) to the corresponding sg device 00483 * (e.g. /dev/sg2). In the linux kernel 2.6 series most of the facilities of 00484 * the sg driver have become available via the SG_IO ioctl which is available 00485 * on all SCSI devices (on SCSI tape devices from lk 2.6.6). 00486 * So the strategy below is to find out if the SG_IO ioctl is available and 00487 * if so use it; failing that use the older SCSI_IOCTL_SEND_COMMAND ioctl. 00488 * Should work in 2.0, 2.2, 2.4 and 2.6 series linux kernels. */ 00489 00490 #define MAX_DXFER_LEN 1024 /* can be increased if necessary */ 00491 #define SEND_IOCTL_RESP_SENSE_LEN 16 /* ioctl limitation */ 00492 #define SG_IO_RESP_SENSE_LEN 64 /* large enough see buffer */ 00493 #define LSCSI_DRIVER_MASK 0xf /* mask out "suggestions" */ 00494 #define LSCSI_DRIVER_SENSE 0x8 /* alternate CHECK CONDITION indication */ 00495 #define LSCSI_DID_ERROR 0x7 /* Need to work around aacraid driver quirk */ 00496 #define LSCSI_DRIVER_TIMEOUT 0x6 00497 #define LSCSI_DID_TIME_OUT 0x3 00498 #define LSCSI_DID_BUS_BUSY 0x2 00499 #define LSCSI_DID_NO_CONNECT 0x1 00500 00501 #ifndef SCSI_IOCTL_SEND_COMMAND 00502 #define SCSI_IOCTL_SEND_COMMAND 1 00503 #endif 00504 00505 #define SG_IO_PRESENT_UNKNOWN 0 00506 #define SG_IO_PRESENT_YES 1 00507 #define SG_IO_PRESENT_NO 2 00508 00509 static int sg_io_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report, 00510 int unknown); 00511 static int sisc_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report); 00512 00513 static int sg_io_state = SG_IO_PRESENT_UNKNOWN; 00514 00515 /* Preferred implementation for issuing SCSI commands in linux. This 00516 * function uses the SG_IO ioctl. Return 0 if command issued successfully 00517 * (various status values should still be checked). If the SCSI command 00518 * cannot be issued then a negative errno value is returned. */ 00519 static int sg_io_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report, 00520 int unknown) 00521 { 00522 #ifndef SG_IO 00523 ARGUSED(dev_fd); ARGUSED(iop); ARGUSED(report); 00524 return -ENOTTY; 00525 #else 00526 struct sg_io_hdr io_hdr; 00527 00528 if (report > 0) { 00529 int k, j; 00530 const unsigned char * ucp = iop->cmnd; 00531 const char * np; 00532 char buff[256]; 00533 const int sz = (int)sizeof(buff); 00534 00535 np = scsi_get_opcode_name(ucp[0]); 00536 j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>"); 00537 for (k = 0; k < (int)iop->cmnd_len; ++k) 00538 j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]); 00539 if ((report > 1) && 00540 (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) { 00541 int trunc = (iop->dxfer_len > 256) ? 1 : 0; 00542 00543 j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n Outgoing " 00544 "data, len=%d%s:\n", (int)iop->dxfer_len, 00545 (trunc ? " [only first 256 bytes shown]" : "")); 00546 dStrHex((const char *)iop->dxferp, 00547 (trunc ? 256 : iop->dxfer_len) , 1); 00548 } 00549 else 00550 j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n"); 00551 pout("%s", buff); 00552 } 00553 memset(&io_hdr, 0, sizeof(struct sg_io_hdr)); 00554 io_hdr.interface_id = 'S'; 00555 io_hdr.cmd_len = iop->cmnd_len; 00556 io_hdr.mx_sb_len = iop->max_sense_len; 00557 io_hdr.dxfer_len = iop->dxfer_len; 00558 io_hdr.dxferp = iop->dxferp; 00559 io_hdr.cmdp = iop->cmnd; 00560 io_hdr.sbp = iop->sensep; 00561 /* sg_io_hdr interface timeout has millisecond units. Timeout of 0 00562 defaults to 60 seconds. */ 00563 io_hdr.timeout = ((0 == iop->timeout) ? 60 : iop->timeout) * 1000; 00564 switch (iop->dxfer_dir) { 00565 case DXFER_NONE: 00566 io_hdr.dxfer_direction = SG_DXFER_NONE; 00567 break; 00568 case DXFER_FROM_DEVICE: 00569 io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; 00570 break; 00571 case DXFER_TO_DEVICE: 00572 io_hdr.dxfer_direction = SG_DXFER_TO_DEV; 00573 break; 00574 default: 00575 pout("do_scsi_cmnd_io: bad dxfer_dir\n"); 00576 return -EINVAL; 00577 } 00578 iop->resp_sense_len = 0; 00579 iop->scsi_status = 0; 00580 iop->resid = 0; 00581 if (ioctl(dev_fd, SG_IO, &io_hdr) < 0) { 00582 if (report && (! unknown)) 00583 pout(" SG_IO ioctl failed, errno=%d [%s]\n", errno, 00584 strerror(errno)); 00585 return -errno; 00586 } 00587 iop->resid = io_hdr.resid; 00588 iop->scsi_status = io_hdr.status; 00589 if (report > 0) { 00590 pout(" scsi_status=0x%x, host_status=0x%x, driver_status=0x%x\n" 00591 " info=0x%x duration=%d milliseconds resid=%d\n", io_hdr.status, 00592 io_hdr.host_status, io_hdr.driver_status, io_hdr.info, 00593 io_hdr.duration, io_hdr.resid); 00594 if (report > 1) { 00595 if (DXFER_FROM_DEVICE == iop->dxfer_dir) { 00596 int trunc, len; 00597 00598 len = iop->dxfer_len - iop->resid; 00599 trunc = (len > 256) ? 1 : 0; 00600 if (len > 0) { 00601 pout(" Incoming data, len=%d%s:\n", len, 00602 (trunc ? " [only first 256 bytes shown]" : "")); 00603 dStrHex((const char*)iop->dxferp, (trunc ? 256 : len), 00604 1); 00605 } else 00606 pout(" Incoming data trimmed to nothing by resid\n"); 00607 } 00608 } 00609 } 00610 00611 if (io_hdr.info & SG_INFO_CHECK) { /* error or warning */ 00612 int masked_driver_status = (LSCSI_DRIVER_MASK & io_hdr.driver_status); 00613 00614 if (0 != io_hdr.host_status) { 00615 if ((LSCSI_DID_NO_CONNECT == io_hdr.host_status) || 00616 (LSCSI_DID_BUS_BUSY == io_hdr.host_status) || 00617 (LSCSI_DID_TIME_OUT == io_hdr.host_status)) 00618 return -ETIMEDOUT; 00619 else 00620 /* Check for DID_ERROR - workaround for aacraid driver quirk */ 00621 if (LSCSI_DID_ERROR != io_hdr.host_status) { 00622 return -EIO; /* catch all if not DID_ERR */ 00623 } 00624 } 00625 if (0 != masked_driver_status) { 00626 if (LSCSI_DRIVER_TIMEOUT == masked_driver_status) 00627 return -ETIMEDOUT; 00628 else if (LSCSI_DRIVER_SENSE != masked_driver_status) 00629 return -EIO; 00630 } 00631 if (LSCSI_DRIVER_SENSE == masked_driver_status) 00632 iop->scsi_status = SCSI_STATUS_CHECK_CONDITION; 00633 iop->resp_sense_len = io_hdr.sb_len_wr; 00634 if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) && 00635 iop->sensep && (iop->resp_sense_len > 0)) { 00636 if (report > 1) { 00637 pout(" >>> Sense buffer, len=%d:\n", 00638 (int)iop->resp_sense_len); 00639 dStrHex((const char *)iop->sensep, iop->resp_sense_len , 1); 00640 } 00641 } 00642 if (report) { 00643 if (SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) { 00644 if ((iop->sensep[0] & 0x7f) > 0x71) 00645 pout(" status=%x: [desc] sense_key=%x asc=%x ascq=%x\n", 00646 iop->scsi_status, iop->sensep[1] & 0xf, 00647 iop->sensep[2], iop->sensep[3]); 00648 else 00649 pout(" status=%x: sense_key=%x asc=%x ascq=%x\n", 00650 iop->scsi_status, iop->sensep[2] & 0xf, 00651 iop->sensep[12], iop->sensep[13]); 00652 } 00653 else 00654 pout(" status=0x%x\n", iop->scsi_status); 00655 } 00656 } 00657 return 0; 00658 #endif 00659 } 00660 00661 struct linux_ioctl_send_command 00662 { 00663 int inbufsize; 00664 int outbufsize; 00665 UINT8 buff[MAX_DXFER_LEN + 16]; 00666 }; 00667 00668 /* The Linux SCSI_IOCTL_SEND_COMMAND ioctl is primitive and it doesn't 00669 * support: CDB length (guesses it from opcode), resid and timeout. 00670 * Patches in Linux 2.4.21 and 2.5.70 to extend SEND DIAGNOSTIC timeout 00671 * to 2 hours in order to allow long foreground extended self tests. */ 00672 static int sisc_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report) 00673 { 00674 struct linux_ioctl_send_command wrk; 00675 int status, buff_offset; 00676 size_t len; 00677 00678 memcpy(wrk.buff, iop->cmnd, iop->cmnd_len); 00679 buff_offset = iop->cmnd_len; 00680 if (report > 0) { 00681 int k, j; 00682 const unsigned char * ucp = iop->cmnd; 00683 const char * np; 00684 char buff[256]; 00685 const int sz = (int)sizeof(buff); 00686 00687 np = scsi_get_opcode_name(ucp[0]); 00688 j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>"); 00689 for (k = 0; k < (int)iop->cmnd_len; ++k) 00690 j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]); 00691 if ((report > 1) && 00692 (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) { 00693 int trunc = (iop->dxfer_len > 256) ? 1 : 0; 00694 00695 j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n Outgoing " 00696 "data, len=%d%s:\n", (int)iop->dxfer_len, 00697 (trunc ? " [only first 256 bytes shown]" : "")); 00698 dStrHex((const char *)iop->dxferp, 00699 (trunc ? 256 : iop->dxfer_len) , 1); 00700 } 00701 else 00702 j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n"); 00703 pout("%s", buff); 00704 } 00705 switch (iop->dxfer_dir) { 00706 case DXFER_NONE: 00707 wrk.inbufsize = 0; 00708 wrk.outbufsize = 0; 00709 break; 00710 case DXFER_FROM_DEVICE: 00711 wrk.inbufsize = 0; 00712 if (iop->dxfer_len > MAX_DXFER_LEN) 00713 return -EINVAL; 00714 wrk.outbufsize = iop->dxfer_len; 00715 break; 00716 case DXFER_TO_DEVICE: 00717 if (iop->dxfer_len > MAX_DXFER_LEN) 00718 return -EINVAL; 00719 memcpy(wrk.buff + buff_offset, iop->dxferp, iop->dxfer_len); 00720 wrk.inbufsize = iop->dxfer_len; 00721 wrk.outbufsize = 0; 00722 break; 00723 default: 00724 pout("do_scsi_cmnd_io: bad dxfer_dir\n"); 00725 return -EINVAL; 00726 } 00727 iop->resp_sense_len = 0; 00728 iop->scsi_status = 0; 00729 iop->resid = 0; 00730 status = ioctl(dev_fd, SCSI_IOCTL_SEND_COMMAND, &wrk); 00731 if (-1 == status) { 00732 if (report) 00733 pout(" SCSI_IOCTL_SEND_COMMAND ioctl failed, errno=%d [%s]\n", 00734 errno, strerror(errno)); 00735 return -errno; 00736 } 00737 if (0 == status) { 00738 if (report > 0) 00739 pout(" status=0\n"); 00740 if (DXFER_FROM_DEVICE == iop->dxfer_dir) { 00741 memcpy(iop->dxferp, wrk.buff, iop->dxfer_len); 00742 if (report > 1) { 00743 int trunc = (iop->dxfer_len > 256) ? 1 : 0; 00744 00745 pout(" Incoming data, len=%d%s:\n", (int)iop->dxfer_len, 00746 (trunc ? " [only first 256 bytes shown]" : "")); 00747 dStrHex((const char*)iop->dxferp, 00748 (trunc ? 256 : iop->dxfer_len) , 1); 00749 } 00750 } 00751 return 0; 00752 } 00753 iop->scsi_status = status & 0x7e; /* bits 0 and 7 used to be for vendors */ 00754 if (LSCSI_DRIVER_SENSE == ((status >> 24) & 0xf)) 00755 iop->scsi_status = SCSI_STATUS_CHECK_CONDITION; 00756 len = (SEND_IOCTL_RESP_SENSE_LEN < iop->max_sense_len) ? 00757 SEND_IOCTL_RESP_SENSE_LEN : iop->max_sense_len; 00758 if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) && 00759 iop->sensep && (len > 0)) { 00760 memcpy(iop->sensep, wrk.buff, len); 00761 iop->resp_sense_len = len; 00762 if (report > 1) { 00763 pout(" >>> Sense buffer, len=%d:\n", (int)len); 00764 dStrHex((const char *)wrk.buff, len , 1); 00765 } 00766 } 00767 if (report) { 00768 if (SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) { 00769 pout(" status=%x: sense_key=%x asc=%x ascq=%x\n", status & 0xff, 00770 wrk.buff[2] & 0xf, wrk.buff[12], wrk.buff[13]); 00771 } 00772 else 00773 pout(" status=0x%x\n", status); 00774 } 00775 if (iop->scsi_status > 0) 00776 return 0; 00777 else { 00778 if (report > 0) 00779 pout(" ioctl status=0x%x but scsi status=0, fail with EIO\n", 00780 status); 00781 return -EIO; /* give up, assume no device there */ 00782 } 00783 } 00784 00785 /* SCSI command transmission interface function, linux version. 00786 * Returns 0 if SCSI command successfully launched and response 00787 * received. Even when 0 is returned the caller should check 00788 * scsi_cmnd_io::scsi_status for SCSI defined errors and warnings 00789 * (e.g. CHECK CONDITION). If the SCSI command could not be issued 00790 * (e.g. device not present or timeout) or some other problem 00791 * (e.g. timeout) then returns a negative errno value */ 00792 static int do_normal_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, 00793 int report) 00794 { 00795 int res; 00796 00797 /* implementation relies on static sg_io_state variable. If not 00798 * previously set tries the SG_IO ioctl. If that succeeds assume 00799 * that SG_IO ioctl functional. If it fails with an errno value 00800 * other than ENODEV (no device) or permission then assume 00801 * SCSI_IOCTL_SEND_COMMAND is the only option. */ 00802 switch (sg_io_state) { 00803 case SG_IO_PRESENT_UNKNOWN: 00804 /* ignore report argument */ 00805 if (0 == (res = sg_io_cmnd_io(dev_fd, iop, report, 1))) { 00806 sg_io_state = SG_IO_PRESENT_YES; 00807 return 0; 00808 } else if ((-ENODEV == res) || (-EACCES == res) || (-EPERM == res)) 00809 return res; /* wait until we see a device */ 00810 sg_io_state = SG_IO_PRESENT_NO; 00811 /* drop through by design */ 00812 case SG_IO_PRESENT_NO: 00813 return sisc_cmnd_io(dev_fd, iop, report); 00814 case SG_IO_PRESENT_YES: 00815 return sg_io_cmnd_io(dev_fd, iop, report, 0); 00816 default: 00817 pout(">>>> do_scsi_cmnd_io: bad sg_io_state=%d\n", sg_io_state); 00818 sg_io_state = SG_IO_PRESENT_UNKNOWN; 00819 return -EIO; /* report error and reset state */ 00820 } 00821 } 00822 00823 // >>>>>> End of general SCSI specific linux code 00824 00825 ///////////////////////////////////////////////////////////////////////////// 00826 /// Standard SCSI support 00827 00828 class linux_scsi_device 00829 : public /*implements*/ scsi_device, 00830 public /*extends*/ linux_smart_device 00831 { 00832 public: 00833 linux_scsi_device(smart_interface * intf, const char * dev_name, 00834 const char * req_type, bool scanning = false); 00835 00836 virtual smart_device * autodetect_open(); 00837 00838 virtual bool scsi_pass_through(scsi_cmnd_io * iop); 00839 00840 private: 00841 bool m_scanning; ///< true if created within scan_smart_devices 00842 }; 00843 00844 linux_scsi_device::linux_scsi_device(smart_interface * intf, 00845 const char * dev_name, const char * req_type, bool scanning /*= false*/) 00846 : smart_device(intf, dev_name, "scsi", req_type), 00847 // If opened with O_RDWR, a SATA disk in standby mode 00848 // may spin-up after device close(). 00849 linux_smart_device(O_RDONLY | O_NONBLOCK), 00850 m_scanning(scanning) 00851 { 00852 } 00853 00854 bool linux_scsi_device::scsi_pass_through(scsi_cmnd_io * iop) 00855 { 00856 int status = do_normal_scsi_cmnd_io(get_fd(), iop, scsi_debugmode); 00857 if (status < 0) 00858 return set_err(-status); 00859 return true; 00860 } 00861 00862 ///////////////////////////////////////////////////////////////////////////// 00863 /// LSI MegaRAID support 00864 00865 class linux_megaraid_device 00866 : public /* implements */ scsi_device, 00867 public /* extends */ linux_smart_device 00868 { 00869 public: 00870 linux_megaraid_device(smart_interface *intf, const char *name, 00871 unsigned int bus, unsigned int tgt); 00872 00873 virtual ~linux_megaraid_device() throw(); 00874 00875 virtual smart_device * autodetect_open(); 00876 00877 virtual bool open(); 00878 virtual bool close(); 00879 00880 virtual bool scsi_pass_through(scsi_cmnd_io *iop); 00881 00882 private: 00883 unsigned int m_disknum; 00884 unsigned int m_busnum; 00885 unsigned int m_hba; 00886 int m_fd; 00887 00888 bool (linux_megaraid_device::*pt_cmd)(int cdblen, void *cdb, int dataLen, void *data, 00889 int senseLen, void *sense, int report, int direction); 00890 bool megasas_cmd(int cdbLen, void *cdb, int dataLen, void *data, 00891 int senseLen, void *sense, int report, int direction); 00892 bool megadev_cmd(int cdbLen, void *cdb, int dataLen, void *data, 00893 int senseLen, void *sense, int report, int direction); 00894 }; 00895 00896 linux_megaraid_device::linux_megaraid_device(smart_interface *intf, 00897 const char *dev_name, unsigned int bus, unsigned int tgt) 00898 : smart_device(intf, dev_name, "megaraid", "megaraid"), 00899 linux_smart_device(O_RDWR | O_NONBLOCK), 00900 m_disknum(tgt), m_busnum(bus), m_hba(0), 00901 m_fd(-1), pt_cmd(0) 00902 { 00903 set_info().info_name = strprintf("%s [megaraid_disk_%02d]", dev_name, m_disknum); 00904 set_info().dev_type = strprintf("megaraid,%d", tgt); 00905 } 00906 00907 linux_megaraid_device::~linux_megaraid_device() throw() 00908 { 00909 if (m_fd >= 0) 00910 ::close(m_fd); 00911 } 00912 00913 smart_device * linux_megaraid_device::autodetect_open() 00914 { 00915 int report = scsi_debugmode; 00916 00917 // Open device 00918 if (!open()) 00919 return this; 00920 00921 // The code below is based on smartd.cpp:SCSIFilterKnown() 00922 if (strcmp(get_req_type(), "megaraid")) 00923 return this; 00924 00925 // Get INQUIRY 00926 unsigned char req_buff[64] = {0, }; 00927 int req_len = 36; 00928 if (scsiStdInquiry(this, req_buff, req_len)) { 00929 close(); 00930 set_err(EIO, "INQUIRY failed"); 00931 return this; 00932 } 00933 00934 int avail_len = req_buff[4] + 5; 00935 int len = (avail_len < req_len ? avail_len : req_len); 00936 if (len < 36) 00937 return this; 00938 00939 if (report) 00940 pout("Got MegaRAID inquiry.. %s\n", req_buff+8); 00941 00942 // Use INQUIRY to detect type 00943 { 00944 // SAT? 00945 ata_device * newdev = smi()->autodetect_sat_device(this, req_buff, len); 00946 if (newdev) // NOTE: 'this' is now owned by '*newdev' 00947 return newdev; 00948 } 00949 00950 // Nothing special found 00951 return this; 00952 } 00953 00954 bool linux_megaraid_device::open() 00955 { 00956 char line[128]; 00957 int mjr; 00958 int report = scsi_debugmode; 00959 00960 if(sscanf(get_dev_name(),"/dev/bus/%d", &m_hba) == 0) { 00961 if (!linux_smart_device::open()) 00962 return false; 00963 /* Get device HBA */ 00964 struct sg_scsi_id sgid; 00965 if (ioctl(get_fd(), SG_GET_SCSI_ID, &sgid) == 0) { 00966 m_hba = sgid.host_no; 00967 } 00968 else if (ioctl(get_fd(), SCSI_IOCTL_GET_BUS_NUMBER, &m_hba) != 0) { 00969 int err = errno; 00970 linux_smart_device::close(); 00971 return set_err(err, "can't get bus number"); 00972 } // we dont need this device anymore 00973 linux_smart_device::close(); 00974 } 00975 /* Perform mknod of device ioctl node */ 00976 FILE * fp = fopen("/proc/devices", "r"); 00977 while (fgets(line, sizeof(line), fp) != NULL) { 00978 int n1 = 0; 00979 if (sscanf(line, "%d megaraid_sas_ioctl%n", &mjr, &n1) == 1 && n1 == 22) { 00980 n1=mknod("/dev/megaraid_sas_ioctl_node", S_IFCHR, makedev(mjr, 0)); 00981 if(report > 0) 00982 pout("Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno); 00983 if (n1 >= 0 || errno == EEXIST) 00984 break; 00985 } 00986 else if (sscanf(line, "%d megadev%n", &mjr, &n1) == 1 && n1 == 11) { 00987 n1=mknod("/dev/megadev0", S_IFCHR, makedev(mjr, 0)); 00988 if(report > 0) 00989 pout("Creating /dev/megadev0 = %d\n", n1 >= 0 ? 0 : errno); 00990 if (n1 >= 0 || errno == EEXIST) 00991 break; 00992 } 00993 } 00994 fclose(fp); 00995 00996 /* Open Device IOCTL node */ 00997 if ((m_fd = ::open("/dev/megaraid_sas_ioctl_node", O_RDWR)) >= 0) { 00998 pt_cmd = &linux_megaraid_device::megasas_cmd; 00999 } 01000 else if ((m_fd = ::open("/dev/megadev0", O_RDWR)) >= 0) { 01001 pt_cmd = &linux_megaraid_device::megadev_cmd; 01002 } 01003 else { 01004 int err = errno; 01005 linux_smart_device::close(); 01006 return set_err(err, "cannot open /dev/megaraid_sas_ioctl_node or /dev/megadev0"); 01007 } 01008 set_fd(m_fd); 01009 return true; 01010 } 01011 01012 bool linux_megaraid_device::close() 01013 { 01014 if (m_fd >= 0) 01015 ::close(m_fd); 01016 m_fd = -1; m_hba = 0; pt_cmd = 0; 01017 set_fd(m_fd); 01018 return true; 01019 } 01020 01021 bool linux_megaraid_device::scsi_pass_through(scsi_cmnd_io *iop) 01022 { 01023 int report = scsi_debugmode; 01024 01025 if (report > 0) { 01026 int k, j; 01027 const unsigned char * ucp = iop->cmnd; 01028 const char * np; 01029 char buff[256]; 01030 const int sz = (int)sizeof(buff); 01031 01032 np = scsi_get_opcode_name(ucp[0]); 01033 j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>"); 01034 for (k = 0; k < (int)iop->cmnd_len; ++k) 01035 j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]); 01036 if ((report > 1) && 01037 (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) { 01038 int trunc = (iop->dxfer_len > 256) ? 1 : 0; 01039 01040 j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n Outgoing " 01041 "data, len=%d%s:\n", (int)iop->dxfer_len, 01042 (trunc ? " [only first 256 bytes shown]" : "")); 01043 dStrHex((const char *)iop->dxferp, 01044 (trunc ? 256 : iop->dxfer_len) , 1); 01045 } 01046 else 01047 j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n"); 01048 pout("%s", buff); 01049 } 01050 01051 // Controller rejects Test Unit Ready 01052 if (iop->cmnd[0] == 0x00) 01053 return true; 01054 01055 if (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 || iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16) { 01056 // Controller does not return ATA output registers in SAT sense data 01057 if (iop->cmnd[2] & (1 << 5)) // chk_cond 01058 return set_err(ENOSYS, "ATA return descriptor not supported by controller firmware"); 01059 } 01060 // SMART WRITE LOG SECTOR causing media errors 01061 if ((iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16 // SAT16 WRITE LOG 01062 && iop->cmnd[14] == ATA_SMART_CMD && iop->cmnd[3]==0 && iop->cmnd[4] == ATA_SMART_WRITE_LOG_SECTOR) || 01063 (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 // SAT12 WRITE LOG 01064 && iop->cmnd[9] == ATA_SMART_CMD && iop->cmnd[3] == ATA_SMART_WRITE_LOG_SECTOR)) 01065 { 01066 if(!failuretest_permissive) 01067 return set_err(ENOSYS, "SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force"); 01068 } 01069 if (pt_cmd == NULL) 01070 return false; 01071 return (this->*pt_cmd)(iop->cmnd_len, iop->cmnd, 01072 iop->dxfer_len, iop->dxferp, 01073 iop->max_sense_len, iop->sensep, report, iop->dxfer_dir); 01074 } 01075 01076 /* Issue passthrough scsi command to PERC5/6 controllers */ 01077 bool linux_megaraid_device::megasas_cmd(int cdbLen, void *cdb, 01078 int dataLen, void *data, 01079 int /*senseLen*/, void * /*sense*/, int /*report*/, int dxfer_dir) 01080 { 01081 struct megasas_pthru_frame *pthru; 01082 struct megasas_iocpacket uio; 01083 int rc; 01084 01085 memset(&uio, 0, sizeof(uio)); 01086 pthru = &uio.frame.pthru; 01087 pthru->cmd = MFI_CMD_PD_SCSI_IO; 01088 pthru->cmd_status = 0xFF; 01089 pthru->scsi_status = 0x0; 01090 pthru->target_id = m_disknum; 01091 pthru->lun = 0; 01092 pthru->cdb_len = cdbLen; 01093 pthru->timeout = 0; 01094 switch (dxfer_dir) { 01095 case DXFER_NONE: 01096 pthru->flags = MFI_FRAME_DIR_NONE; 01097 break; 01098 case DXFER_FROM_DEVICE: 01099 pthru->flags = MFI_FRAME_DIR_READ; 01100 break; 01101 case DXFER_TO_DEVICE: 01102 pthru->flags = MFI_FRAME_DIR_WRITE; 01103 break; 01104 default: 01105 pout("megasas_cmd: bad dxfer_dir\n"); 01106 return set_err(EINVAL, "megasas_cmd: bad dxfer_dir\n"); 01107 } 01108 01109 if (dataLen > 0) { 01110 pthru->sge_count = 1; 01111 pthru->data_xfer_len = dataLen; 01112 pthru->sgl.sge32[0].phys_addr = (intptr_t)data; 01113 pthru->sgl.sge32[0].length = (uint32_t)dataLen; 01114 } 01115 memcpy(pthru->cdb, cdb, cdbLen); 01116 01117 uio.host_no = m_hba; 01118 if (dataLen > 0) { 01119 uio.sge_count = 1; 01120 uio.sgl_off = offsetof(struct megasas_pthru_frame, sgl); 01121 uio.sgl[0].iov_base = data; 01122 uio.sgl[0].iov_len = dataLen; 01123 } 01124 01125 rc = 0; 01126 errno = 0; 01127 rc = ioctl(m_fd, MEGASAS_IOC_FIRMWARE, &uio); 01128 if (pthru->cmd_status || rc != 0) { 01129 if (pthru->cmd_status == 12) { 01130 return set_err(EIO, "megasas_cmd: Device %d does not exist\n", m_disknum); 01131 } 01132 return set_err((errno ? errno : EIO), "megasas_cmd result: %d.%d = %d/%d", 01133 m_hba, m_disknum, errno, 01134 pthru->cmd_status); 01135 } 01136 return true; 01137 } 01138 01139 /* Issue passthrough scsi commands to PERC2/3/4 controllers */ 01140 bool linux_megaraid_device::megadev_cmd(int cdbLen, void *cdb, 01141 int dataLen, void *data, 01142 int /*senseLen*/, void * /*sense*/, int /*report*/, int /* dir */) 01143 { 01144 struct uioctl_t uio; 01145 int rc; 01146 01147 /* Don't issue to the controller */ 01148 if (m_disknum == 7) 01149 return false; 01150 01151 memset(&uio, 0, sizeof(uio)); 01152 uio.inlen = dataLen; 01153 uio.outlen = dataLen; 01154 01155 memset(data, 0, dataLen); 01156 uio.ui.fcs.opcode = 0x80; // M_RD_IOCTL_CMD 01157 uio.ui.fcs.adapno = MKADAP(m_hba); 01158 01159 uio.data.pointer = (uint8_t *)data; 01160 01161 uio.mbox.cmd = MEGA_MBOXCMD_PASSTHRU; 01162 uio.mbox.xferaddr = (intptr_t)&uio.pthru; 01163 01164 uio.pthru.ars = 1; 01165 uio.pthru.timeout = 2; 01166 uio.pthru.channel = 0; 01167 uio.pthru.target = m_disknum; 01168 uio.pthru.cdblen = cdbLen; 01169 uio.pthru.reqsenselen = MAX_REQ_SENSE_LEN; 01170 uio.pthru.dataxferaddr = (intptr_t)data; 01171 uio.pthru.dataxferlen = dataLen; 01172 memcpy(uio.pthru.cdb, cdb, cdbLen); 01173 01174 rc=ioctl(m_fd, MEGAIOCCMD, &uio); 01175 if (uio.pthru.scsistatus || rc != 0) { 01176 return set_err((errno ? errno : EIO), "megadev_cmd result: %d.%d = %d/%d", 01177 m_hba, m_disknum, errno, 01178 uio.pthru.scsistatus); 01179 } 01180 return true; 01181 } 01182 01183 ///////////////////////////////////////////////////////////////////////////// 01184 /// CCISS RAID support 01185 01186 #ifdef HAVE_LINUX_CCISS_IOCTL_H 01187 01188 class linux_cciss_device 01189 : public /*implements*/ scsi_device, 01190 public /*extends*/ linux_smart_device 01191 { 01192 public: 01193 linux_cciss_device(smart_interface * intf, const char * name, unsigned char disknum); 01194 01195 virtual bool scsi_pass_through(scsi_cmnd_io * iop); 01196 01197 private: 01198 unsigned char m_disknum; ///< Disk number. 01199 }; 01200 01201 linux_cciss_device::linux_cciss_device(smart_interface * intf, 01202 const char * dev_name, unsigned char disknum) 01203 : smart_device(intf, dev_name, "cciss", "cciss"), 01204 linux_smart_device(O_RDWR | O_NONBLOCK), 01205 m_disknum(disknum) 01206 { 01207 set_info().info_name = strprintf("%s [cciss_disk_%02d]", dev_name, disknum); 01208 } 01209 01210 bool linux_cciss_device::scsi_pass_through(scsi_cmnd_io * iop) 01211 { 01212 int status = cciss_io_interface(get_fd(), m_disknum, iop, scsi_debugmode); 01213 if (status < 0) 01214 return set_err(-status); 01215 return true; 01216 } 01217 01218 #endif // HAVE_LINUX_CCISS_IOCTL_H 01219 01220 ///////////////////////////////////////////////////////////////////////////// 01221 /// AMCC/3ware RAID support 01222 01223 class linux_escalade_device 01224 : public /*implements*/ ata_device, 01225 public /*extends*/ linux_smart_device 01226 { 01227 public: 01228 enum escalade_type_t { 01229 AMCC_3WARE_678K, 01230 AMCC_3WARE_678K_CHAR, 01231 AMCC_3WARE_9000_CHAR, 01232 AMCC_3WARE_9700_CHAR 01233 }; 01234 01235 linux_escalade_device(smart_interface * intf, const char * dev_name, 01236 escalade_type_t escalade_type, int disknum); 01237 01238 virtual bool open(); 01239 01240 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); 01241 01242 private: 01243 escalade_type_t m_escalade_type; ///< Controller type 01244 int m_disknum; ///< Disk number. 01245 }; 01246 01247 linux_escalade_device::linux_escalade_device(smart_interface * intf, const char * dev_name, 01248 escalade_type_t escalade_type, int disknum) 01249 : smart_device(intf, dev_name, "3ware", "3ware"), 01250 linux_smart_device(O_RDONLY | O_NONBLOCK), 01251 m_escalade_type(escalade_type), m_disknum(disknum) 01252 { 01253 set_info().info_name = strprintf("%s [3ware_disk_%02d]", dev_name, disknum); 01254 } 01255 01256 /* This function will setup and fix device nodes for a 3ware controller. */ 01257 #define MAJOR_STRING_LENGTH 3 01258 #define DEVICE_STRING_LENGTH 32 01259 #define NODE_STRING_LENGTH 16 01260 static int setup_3ware_nodes(const char *nodename, const char *driver_name) 01261 { 01262 int tw_major = 0; 01263 int index = 0; 01264 char majorstring[MAJOR_STRING_LENGTH+1]; 01265 char device_name[DEVICE_STRING_LENGTH+1]; 01266 char nodestring[NODE_STRING_LENGTH]; 01267 struct stat stat_buf; 01268 FILE *file; 01269 int retval = 0; 01270 #ifdef WITH_SELINUX 01271 security_context_t orig_context = NULL; 01272 security_context_t node_context = NULL; 01273 int selinux_enabled = is_selinux_enabled(); 01274 int selinux_enforced = security_getenforce(); 01275 #endif 01276 01277 /* First try to open up /proc/devices */ 01278 if (!(file = fopen("/proc/devices", "r"))) { 01279 pout("Error opening /proc/devices to check/create 3ware device nodes\n"); 01280 syserror("fopen"); 01281 return 0; // don't fail here: user might not have /proc ! 01282 } 01283 01284 /* Attempt to get device major number */ 01285 while (EOF != fscanf(file, "%3s %32s", majorstring, device_name)) { 01286 majorstring[MAJOR_STRING_LENGTH]='\0'; 01287 device_name[DEVICE_STRING_LENGTH]='\0'; 01288 if (!strncmp(device_name, nodename, DEVICE_STRING_LENGTH)) { 01289 tw_major = atoi(majorstring); 01290 break; 01291 } 01292 } 01293 fclose(file); 01294 01295 /* See if we found a major device number */ 01296 if (!tw_major) { 01297 pout("No major number for /dev/%s listed in /proc/devices. Is the %s driver loaded?\n", nodename, driver_name); 01298 return 2; 01299 } 01300 #ifdef WITH_SELINUX 01301 /* Prepare a database of contexts for files in /dev 01302 * and save the current context */ 01303 if (selinux_enabled) { 01304 if (matchpathcon_init_prefix(NULL, "/dev") < 0) 01305 pout("Error initializing contexts database for /dev"); 01306 if (getfscreatecon(&orig_context) < 0) { 01307 pout("Error retrieving original SELinux fscreate context"); 01308 if (selinux_enforced) 01309 matchpathcon_fini(); 01310 return 6; 01311 } 01312 } 01313 #endif 01314 /* Now check if nodes are correct */ 01315 for (index=0; index<16; index++) { 01316 snprintf(nodestring, sizeof(nodestring), "/dev/%s%d", nodename, index); 01317 #ifdef WITH_SELINUX 01318 /* Get context of the node and set it as the default */ 01319 if (selinux_enabled) { 01320 if (matchpathcon(nodestring, S_IRUSR | S_IWUSR, &node_context) < 0) { 01321 pout("Could not retrieve context for %s", nodestring); 01322 if (selinux_enforced) { 01323 retval = 6; 01324 break; 01325 } 01326 } 01327 if (setfscreatecon(node_context) < 0) { 01328 pout ("Error setting default fscreate context"); 01329 if (selinux_enforced) { 01330 retval = 6; 01331 break; 01332 } 01333 } 01334 } 01335 #endif 01336 /* Try to stat the node */ 01337 if ((stat(nodestring, &stat_buf))) { 01338 pout("Node %s does not exist and must be created. Check the udev rules.\n", nodestring); 01339 /* Create a new node if it doesn't exist */ 01340 if (mknod(nodestring, S_IFCHR|0600, makedev(tw_major, index))) { 01341 pout("problem creating 3ware device nodes %s", nodestring); 01342 syserror("mknod"); 01343 retval = 3; 01344 break; 01345 } else { 01346 #ifdef WITH_SELINUX 01347 if (selinux_enabled && node_context) { 01348 freecon(node_context); 01349 node_context = NULL; 01350 } 01351 #endif 01352 continue; 01353 } 01354 } 01355 01356 /* See if nodes major and minor numbers are correct */ 01357 if ((tw_major != (int)(major(stat_buf.st_rdev))) || 01358 (index != (int)(minor(stat_buf.st_rdev))) || 01359 (!S_ISCHR(stat_buf.st_mode))) { 01360 pout("Node %s has wrong major/minor number and must be created anew." 01361 " Check the udev rules.\n", nodestring); 01362 /* Delete the old node */ 01363 if (unlink(nodestring)) { 01364 pout("problem unlinking stale 3ware device node %s", nodestring); 01365 syserror("unlink"); 01366 retval = 4; 01367 break; 01368 } 01369 01370 /* Make a new node */ 01371 if (mknod(nodestring, S_IFCHR|0600, makedev(tw_major, index))) { 01372 pout("problem creating 3ware device nodes %s", nodestring); 01373 syserror("mknod"); 01374 retval = 5; 01375 break; 01376 } 01377 } 01378 #ifdef WITH_SELINUX 01379 if (selinux_enabled && node_context) { 01380 freecon(node_context); 01381 node_context = NULL; 01382 } 01383 #endif 01384 } 01385 01386 #ifdef WITH_SELINUX 01387 if (selinux_enabled) { 01388 if(setfscreatecon(orig_context) < 0) { 01389 pout("Error re-setting original fscreate context"); 01390 if (selinux_enforced) 01391 retval = 6; 01392 } 01393 if(orig_context) 01394 freecon(orig_context); 01395 if(node_context) 01396 freecon(node_context); 01397 matchpathcon_fini(); 01398 } 01399 #endif 01400 return retval; 01401 } 01402 01403 bool linux_escalade_device::open() 01404 { 01405 if (m_escalade_type == AMCC_3WARE_9700_CHAR || m_escalade_type == AMCC_3WARE_9000_CHAR || 01406 m_escalade_type == AMCC_3WARE_678K_CHAR) { 01407 // the device nodes for these controllers are dynamically assigned, 01408 // so we need to check that they exist with the correct major 01409 // numbers and if not, create them 01410 const char * node = (m_escalade_type == AMCC_3WARE_9700_CHAR ? "twl" : 01411 m_escalade_type == AMCC_3WARE_9000_CHAR ? "twa" : 01412 "twe" ); 01413 const char * driver = (m_escalade_type == AMCC_3WARE_9700_CHAR ? "3w-sas" : 01414 m_escalade_type == AMCC_3WARE_9000_CHAR ? "3w-9xxx" : 01415 "3w-xxxx" ); 01416 if (setup_3ware_nodes(node, driver)) 01417 return set_err((errno ? errno : ENXIO), "setup_3ware_nodes(\"%s\", \"%s\") failed", node, driver); 01418 } 01419 // Continue with default open 01420 return linux_smart_device::open(); 01421 } 01422 01423 // TODO: Function no longer useful 01424 //void printwarning(smart_command_set command); 01425 01426 // PURPOSE 01427 // This is an interface routine meant to isolate the OS dependent 01428 // parts of the code, and to provide a debugging interface. Each 01429 // different port and OS needs to provide it's own interface. This 01430 // is the linux interface to the 3ware 3w-xxxx driver. It allows ATA 01431 // commands to be passed through the SCSI driver. 01432 // DETAILED DESCRIPTION OF ARGUMENTS 01433 // fd: is the file descriptor provided by open() 01434 // disknum is the disk number (0 to 15) in the RAID array 01435 // escalade_type indicates the type of controller type, and if scsi or char interface is used 01436 // command: defines the different operations. 01437 // select: additional input data if needed (which log, which type of 01438 // self-test). 01439 // data: location to write output data, if needed (512 bytes). 01440 // Note: not all commands use all arguments. 01441 // RETURN VALUES 01442 // -1 if the command failed 01443 // 0 if the command succeeded, 01444 // STATUS_CHECK routine: 01445 // -1 if the command failed 01446 // 0 if the command succeeded and disk SMART status is "OK" 01447 // 1 if the command succeeded and disk SMART status is "FAILING" 01448 01449 /* 512 is the max payload size: increase if needed */ 01450 #define BUFFER_LEN_678K ( sizeof(TW_Ioctl) ) // 1044 unpacked, 1041 packed 01451 #define BUFFER_LEN_678K_CHAR ( sizeof(TW_New_Ioctl)+512-1 ) // 1539 unpacked, 1536 packed 01452 #define BUFFER_LEN_9000 ( sizeof(TW_Ioctl_Buf_Apache)+512-1 ) // 2051 unpacked, 2048 packed 01453 #define TW_IOCTL_BUFFER_SIZE ( MAX(MAX(BUFFER_LEN_678K, BUFFER_LEN_9000), BUFFER_LEN_678K_CHAR) ) 01454 01455 bool linux_escalade_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) 01456 { 01457 if (!ata_cmd_is_ok(in, 01458 true, // data_out_support 01459 false, // TODO: multi_sector_support 01460 true) // ata_48bit_support 01461 ) 01462 return false; 01463 01464 // Used by both the SCSI and char interfaces 01465 TW_Passthru *passthru=NULL; 01466 char ioctl_buffer[TW_IOCTL_BUFFER_SIZE]; 01467 01468 // only used for SCSI device interface 01469 TW_Ioctl *tw_ioctl=NULL; 01470 TW_Output *tw_output=NULL; 01471 01472 // only used for 6000/7000/8000 char device interface 01473 TW_New_Ioctl *tw_ioctl_char=NULL; 01474 01475 // only used for 9000 character device interface 01476 TW_Ioctl_Buf_Apache *tw_ioctl_apache=NULL; 01477 01478 memset(ioctl_buffer, 0, TW_IOCTL_BUFFER_SIZE); 01479 01480 // TODO: Handle controller differences by different classes 01481 if (m_escalade_type == AMCC_3WARE_9700_CHAR || m_escalade_type == AMCC_3WARE_9000_CHAR) { 01482 tw_ioctl_apache = (TW_Ioctl_Buf_Apache *)ioctl_buffer; 01483 tw_ioctl_apache->driver_command.control_code = TW_IOCTL_FIRMWARE_PASS_THROUGH; 01484 tw_ioctl_apache->driver_command.buffer_length = 512; /* payload size */ 01485 passthru = (TW_Passthru *)&(tw_ioctl_apache->firmware_command.command.oldcommand); 01486 } 01487 else if (m_escalade_type==AMCC_3WARE_678K_CHAR) { 01488 tw_ioctl_char = (TW_New_Ioctl *)ioctl_buffer; 01489 tw_ioctl_char->data_buffer_length = 512; 01490 passthru = (TW_Passthru *)&(tw_ioctl_char->firmware_command); 01491 } 01492 else if (m_escalade_type==AMCC_3WARE_678K) { 01493 tw_ioctl = (TW_Ioctl *)ioctl_buffer; 01494 tw_ioctl->cdb[0] = TW_IOCTL; 01495 tw_ioctl->opcode = TW_ATA_PASSTHRU; 01496 tw_ioctl->input_length = 512; // correct even for non-data commands 01497 tw_ioctl->output_length = 512; // correct even for non-data commands 01498 tw_output = (TW_Output *)tw_ioctl; 01499 passthru = (TW_Passthru *)&(tw_ioctl->input_data); 01500 } 01501 else { 01502 return set_err(ENOSYS, 01503 "Unrecognized escalade_type %d in linux_3ware_command_interface(disk %d)\n" 01504 "Please contact " PACKAGE_BUGREPORT "\n", (int)m_escalade_type, m_disknum); 01505 } 01506 01507 // Same for (almost) all commands - but some reset below 01508 passthru->byte0.opcode = TW_OP_ATA_PASSTHRU; 01509 passthru->request_id = 0xFF; 01510 passthru->unit = m_disknum; 01511 passthru->status = 0; 01512 passthru->flags = 0x1; 01513 01514 // Set registers 01515 { 01516 const ata_in_regs_48bit & r = in.in_regs; 01517 passthru->features = r.features_16; 01518 passthru->sector_count = r.sector_count_16; 01519 passthru->sector_num = r.lba_low_16; 01520 passthru->cylinder_lo = r.lba_mid_16; 01521 passthru->cylinder_hi = r.lba_high_16; 01522 passthru->drive_head = r.device; 01523 passthru->command = r.command; 01524 } 01525 01526 // Is this a command that reads or returns 512 bytes? 01527 // passthru->param values are: 01528 // 0x0 - non data command without TFR write check, 01529 // 0x8 - non data command with TFR write check, 01530 // 0xD - data command that returns data to host from device 01531 // 0xF - data command that writes data from host to device 01532 // passthru->size values are 0x5 for non-data and 0x07 for data 01533 bool readdata = false; 01534 if (in.direction == ata_cmd_in::data_in) { 01535 readdata=true; 01536 passthru->byte0.sgloff = 0x5; 01537 passthru->size = 0x7; // TODO: Other value for multi-sector ? 01538 passthru->param = 0xD; 01539 // For 64-bit to work correctly, up the size of the command packet 01540 // in dwords by 1 to account for the 64-bit single sgl 'address' 01541 // field. Note that this doesn't agree with the typedefs but it's 01542 // right (agree with kernel driver behavior/typedefs). 01543 if ((m_escalade_type == AMCC_3WARE_9700_CHAR || m_escalade_type == AMCC_3WARE_9000_CHAR) 01544 && sizeof(long) == 8) 01545 passthru->size++; 01546 } 01547 else if (in.direction == ata_cmd_in::no_data) { 01548 // Non data command -- but doesn't use large sector 01549 // count register values. 01550 passthru->byte0.sgloff = 0x0; 01551 passthru->size = 0x5; 01552 passthru->param = 0x8; 01553 passthru->sector_count = 0x0; 01554 } 01555 else if (in.direction == ata_cmd_in::data_out) { 01556 if (m_escalade_type == AMCC_3WARE_9700_CHAR || m_escalade_type == AMCC_3WARE_9000_CHAR) 01557 memcpy(tw_ioctl_apache->data_buffer, in.buffer, in.size); 01558 else if (m_escalade_type == AMCC_3WARE_678K_CHAR) 01559 memcpy(tw_ioctl_char->data_buffer, in.buffer, in.size); 01560 else { 01561 // COMMAND NOT SUPPORTED VIA SCSI IOCTL INTERFACE 01562 // memcpy(tw_output->output_data, data, 512); 01563 // printwarning(command); // TODO: Parameter no longer valid 01564 return set_err(ENOTSUP, "DATA OUT not supported for this 3ware controller type"); 01565 } 01566 passthru->byte0.sgloff = 0x5; 01567 passthru->size = 0x7; // TODO: Other value for multi-sector ? 01568 passthru->param = 0xF; // PIO data write 01569 if ((m_escalade_type == AMCC_3WARE_9700_CHAR || m_escalade_type == AMCC_3WARE_9000_CHAR) 01570 && sizeof(long) == 8) 01571 passthru->size++; 01572 } 01573 else 01574 return set_err(EINVAL); 01575 01576 // Now send the command down through an ioctl() 01577 int ioctlreturn; 01578 if (m_escalade_type == AMCC_3WARE_9700_CHAR || m_escalade_type == AMCC_3WARE_9000_CHAR) 01579 ioctlreturn=ioctl(get_fd(), TW_IOCTL_FIRMWARE_PASS_THROUGH, tw_ioctl_apache); 01580 else if (m_escalade_type==AMCC_3WARE_678K_CHAR) 01581 ioctlreturn=ioctl(get_fd(), TW_CMD_PACKET_WITH_DATA, tw_ioctl_char); 01582 else 01583 ioctlreturn=ioctl(get_fd(), SCSI_IOCTL_SEND_COMMAND, tw_ioctl); 01584 01585 // Deal with the different error cases 01586 if (ioctlreturn) { 01587 if (AMCC_3WARE_678K==m_escalade_type 01588 && in.in_regs.command==ATA_SMART_CMD 01589 && ( in.in_regs.features == ATA_SMART_AUTO_OFFLINE 01590 || in.in_regs.features == ATA_SMART_AUTOSAVE ) 01591 && in.in_regs.lba_low) { 01592 // error here is probably a kernel driver whose version is too old 01593 // printwarning(command); // TODO: Parameter no longer valid 01594 return set_err(ENOTSUP, "Probably kernel driver too old"); 01595 } 01596 return set_err(EIO); 01597 } 01598 01599 // The passthru structure is valid after return from an ioctl if: 01600 // - we are using the character interface OR 01601 // - we are using the SCSI interface and this is a NON-READ-DATA command 01602 // For SCSI interface, note that we set passthru to a different 01603 // value after ioctl(). 01604 if (AMCC_3WARE_678K==m_escalade_type) { 01605 if (readdata) 01606 passthru=NULL; 01607 else 01608 passthru=(TW_Passthru *)&(tw_output->output_data); 01609 } 01610 01611 // See if the ATA command failed. Now that we have returned from 01612 // the ioctl() call, if passthru is valid, then: 01613 // - passthru->status contains the 3ware controller STATUS 01614 // - passthru->command contains the ATA STATUS register 01615 // - passthru->features contains the ATA ERROR register 01616 // 01617 // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS 01618 // If bit 0 (error bit) is set, then ATA ERROR register is valid. 01619 // While we *might* decode the ATA ERROR register, at the moment it 01620 // doesn't make much sense: we don't care in detail why the error 01621 // happened. 01622 01623 if (passthru && (passthru->status || (passthru->command & 0x21))) { 01624 return set_err(EIO); 01625 } 01626 01627 // If this is a read data command, copy data to output buffer 01628 if (readdata) { 01629 if (m_escalade_type == AMCC_3WARE_9700_CHAR || m_escalade_type == AMCC_3WARE_9000_CHAR) 01630 memcpy(in.buffer, tw_ioctl_apache->data_buffer, in.size); 01631 else if (m_escalade_type==AMCC_3WARE_678K_CHAR) 01632 memcpy(in.buffer, tw_ioctl_char->data_buffer, in.size); 01633 else 01634 memcpy(in.buffer, tw_output->output_data, in.size); 01635 } 01636 01637 // Return register values 01638 if (passthru) { 01639 ata_out_regs_48bit & r = out.out_regs; 01640 r.error = passthru->features; 01641 r.sector_count_16 = passthru->sector_count; 01642 r.lba_low_16 = passthru->sector_num; 01643 r.lba_mid_16 = passthru->cylinder_lo; 01644 r.lba_high_16 = passthru->cylinder_hi; 01645 r.device = passthru->drive_head; 01646 r.status = passthru->command; 01647 } 01648 01649 // look for nonexistent devices/ports 01650 if ( in.in_regs.command == ATA_IDENTIFY_DEVICE 01651 && !nonempty(in.buffer, in.size)) { 01652 return set_err(ENODEV, "No drive on port %d", m_disknum); 01653 } 01654 01655 return true; 01656 } 01657 01658 ///////////////////////////////////////////////////////////////////////////// 01659 /// Areca RAID support 01660 01661 /////////////////////////////////////////////////////////////////// 01662 // SATA(ATA) device behind Areca RAID Controller 01663 class linux_areca_ata_device 01664 : public /*implements*/ areca_ata_device, 01665 public /*extends*/ linux_smart_device 01666 { 01667 public: 01668 linux_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1); 01669 virtual smart_device * autodetect_open(); 01670 virtual bool arcmsr_lock(); 01671 virtual bool arcmsr_unlock(); 01672 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop); 01673 }; 01674 01675 /////////////////////////////////////////////////////////////////// 01676 // SAS(SCSI) device behind Areca RAID Controller 01677 class linux_areca_scsi_device 01678 : public /*implements*/ areca_scsi_device, 01679 public /*extends*/ linux_smart_device 01680 { 01681 public: 01682 linux_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1); 01683 virtual smart_device * autodetect_open(); 01684 virtual bool arcmsr_lock(); 01685 virtual bool arcmsr_unlock(); 01686 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop); 01687 }; 01688 01689 // Looks in /proc/scsi to suggest correct areca devices 01690 static int find_areca_in_proc() 01691 { 01692 const char* proc_format_string="host\tchan\tid\tlun\ttype\topens\tqdepth\tbusy\tonline\n"; 01693 01694 // check data formwat 01695 FILE *fp=fopen("/proc/scsi/sg/device_hdr", "r"); 01696 if (!fp) { 01697 pout("Unable to open /proc/scsi/sg/device_hdr for reading\n"); 01698 return 1; 01699 } 01700 01701 // get line, compare to format 01702 char linebuf[256]; 01703 linebuf[255]='\0'; 01704 char *out = fgets(linebuf, 256, fp); 01705 fclose(fp); 01706 if (!out) { 01707 pout("Unable to read contents of /proc/scsi/sg/device_hdr\n"); 01708 return 2; 01709 } 01710 01711 if (strcmp(linebuf, proc_format_string)) { 01712 // wrong format! 01713 // Fix this by comparing only tokens not white space!! 01714 pout("Unexpected format %s in /proc/scsi/sg/device_hdr\n", proc_format_string); 01715 return 3; 01716 } 01717 01718 // Format is understood, now search for correct device 01719 fp=fopen("/proc/scsi/sg/devices", "r"); 01720 if (!fp) return 1; 01721 int host, chan, id, lun, type, opens, qdepth, busy, online; 01722 int dev=-1; 01723 int found=0; 01724 // search all lines of /proc/scsi/sg/devices 01725 while (9 == fscanf(fp, "%d %d %d %d %d %d %d %d %d", &host, &chan, &id, &lun, &type, &opens, &qdepth, &busy, &online)) { 01726 dev++; 01727 if (id == 16 && type == 3) { 01728 // devices with id=16 and type=3 might be Areca controllers 01729 pout("Device /dev/sg%d appears to be an Areca controller.\n", dev); 01730 found++; 01731 } 01732 } 01733 fclose(fp); 01734 return 0; 01735 } 01736 01737 // Areca RAID Controller(SATA Disk) 01738 linux_areca_ata_device::linux_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum) 01739 : smart_device(intf, dev_name, "areca", "areca"), 01740 linux_smart_device(O_RDWR | O_EXCL | O_NONBLOCK) 01741 { 01742 set_disknum(disknum); 01743 set_encnum(encnum); 01744 set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum); 01745 } 01746 01747 smart_device * linux_areca_ata_device::autodetect_open() 01748 { 01749 int is_ata = 1; 01750 01751 // autodetect device type 01752 is_ata = arcmsr_get_dev_type(); 01753 if(is_ata < 0) 01754 { 01755 set_err(EIO); 01756 return this; 01757 } 01758 01759 if(is_ata == 1) 01760 { 01761 // SATA device 01762 return this; 01763 } 01764 01765 // SAS device 01766 smart_device_auto_ptr newdev(new linux_areca_scsi_device(smi(), get_dev_name(), get_disknum(), get_encnum())); 01767 close(); 01768 delete this; 01769 newdev->open(); // TODO: Can possibly pass open fd 01770 01771 return newdev.release(); 01772 } 01773 01774 int linux_areca_ata_device::arcmsr_do_scsi_io(struct scsi_cmnd_io * iop) 01775 { 01776 int ioctlreturn = 0; 01777 01778 if(!is_open()) { 01779 if(!open()){ 01780 find_areca_in_proc(); 01781 } 01782 } 01783 01784 ioctlreturn = do_normal_scsi_cmnd_io(get_fd(), iop, scsi_debugmode); 01785 if ( ioctlreturn || iop->scsi_status ) 01786 { 01787 // errors found 01788 return -1; 01789 } 01790 01791 return ioctlreturn; 01792 } 01793 01794 bool linux_areca_ata_device::arcmsr_lock() 01795 { 01796 return true; 01797 } 01798 01799 bool linux_areca_ata_device::arcmsr_unlock() 01800 { 01801 return true; 01802 } 01803 01804 // Areca RAID Controller(SAS Device) 01805 linux_areca_scsi_device::linux_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum) 01806 : smart_device(intf, dev_name, "areca", "areca"), 01807 linux_smart_device(O_RDWR | O_EXCL | O_NONBLOCK) 01808 { 01809 set_disknum(disknum); 01810 set_encnum(encnum); 01811 set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum); 01812 } 01813 01814 smart_device * linux_areca_scsi_device::autodetect_open() 01815 { 01816 return this; 01817 } 01818 01819 int linux_areca_scsi_device::arcmsr_do_scsi_io(struct scsi_cmnd_io * iop) 01820 { 01821 int ioctlreturn = 0; 01822 01823 if(!is_open()) { 01824 if(!open()){ 01825 find_areca_in_proc(); 01826 } 01827 } 01828 01829 ioctlreturn = do_normal_scsi_cmnd_io(get_fd(), iop, scsi_debugmode); 01830 if ( ioctlreturn || iop->scsi_status ) 01831 { 01832 // errors found 01833 return -1; 01834 } 01835 01836 return ioctlreturn; 01837 } 01838 01839 bool linux_areca_scsi_device::arcmsr_lock() 01840 { 01841 return true; 01842 } 01843 01844 bool linux_areca_scsi_device::arcmsr_unlock() 01845 { 01846 return true; 01847 } 01848 01849 ///////////////////////////////////////////////////////////////////////////// 01850 /// Marvell support 01851 01852 class linux_marvell_device 01853 : public /*implements*/ ata_device_with_command_set, 01854 public /*extends*/ linux_smart_device 01855 { 01856 public: 01857 linux_marvell_device(smart_interface * intf, const char * dev_name, const char * req_type); 01858 01859 protected: 01860 virtual int ata_command_interface(smart_command_set command, int select, char * data); 01861 }; 01862 01863 linux_marvell_device::linux_marvell_device(smart_interface * intf, 01864 const char * dev_name, const char * req_type) 01865 : smart_device(intf, dev_name, "marvell", req_type), 01866 linux_smart_device(O_RDONLY | O_NONBLOCK) 01867 { 01868 } 01869 01870 int linux_marvell_device::ata_command_interface(smart_command_set command, int select, char * data) 01871 { 01872 typedef struct { 01873 int inlen; 01874 int outlen; 01875 char cmd[540]; 01876 } mvsata_scsi_cmd; 01877 01878 int copydata = 0; 01879 mvsata_scsi_cmd smart_command; 01880 unsigned char *buff = (unsigned char *)&smart_command.cmd[6]; 01881 // See struct hd_drive_cmd_hdr in hdreg.h 01882 // buff[0]: ATA COMMAND CODE REGISTER 01883 // buff[1]: ATA SECTOR NUMBER REGISTER 01884 // buff[2]: ATA FEATURES REGISTER 01885 // buff[3]: ATA SECTOR COUNT REGISTER 01886 01887 // clear out buff. Large enough for HDIO_DRIVE_CMD (4+512 bytes) 01888 memset(&smart_command, 0, sizeof(smart_command)); 01889 smart_command.inlen = 540; 01890 smart_command.outlen = 540; 01891 smart_command.cmd[0] = 0xC; //Vendor-specific code 01892 smart_command.cmd[4] = 6; //command length 01893 01894 buff[0] = ATA_SMART_CMD; 01895 switch (command){ 01896 case CHECK_POWER_MODE: 01897 buff[0]=ATA_CHECK_POWER_MODE; 01898 break; 01899 case READ_VALUES: 01900 buff[2]=ATA_SMART_READ_VALUES; 01901 copydata=buff[3]=1; 01902 break; 01903 case READ_THRESHOLDS: 01904 buff[2]=ATA_SMART_READ_THRESHOLDS; 01905 copydata=buff[1]=buff[3]=1; 01906 break; 01907 case READ_LOG: 01908 buff[2]=ATA_SMART_READ_LOG_SECTOR; 01909 buff[1]=select; 01910 copydata=buff[3]=1; 01911 break; 01912 case IDENTIFY: 01913 buff[0]=ATA_IDENTIFY_DEVICE; 01914 copydata=buff[3]=1; 01915 break; 01916 case PIDENTIFY: 01917 buff[0]=ATA_IDENTIFY_PACKET_DEVICE; 01918 copydata=buff[3]=1; 01919 break; 01920 case ENABLE: 01921 buff[2]=ATA_SMART_ENABLE; 01922 buff[1]=1; 01923 break; 01924 case DISABLE: 01925 buff[2]=ATA_SMART_DISABLE; 01926 buff[1]=1; 01927 break; 01928 case STATUS: 01929 case STATUS_CHECK: 01930 // this command only says if SMART is working. It could be 01931 // replaced with STATUS_CHECK below. 01932 buff[2] = ATA_SMART_STATUS; 01933 break; 01934 case AUTO_OFFLINE: 01935 buff[2]=ATA_SMART_AUTO_OFFLINE; 01936 buff[3]=select; // YET NOTE - THIS IS A NON-DATA COMMAND!! 01937 break; 01938 case AUTOSAVE: 01939 buff[2]=ATA_SMART_AUTOSAVE; 01940 buff[3]=select; // YET NOTE - THIS IS A NON-DATA COMMAND!! 01941 break; 01942 case IMMEDIATE_OFFLINE: 01943 buff[2]=ATA_SMART_IMMEDIATE_OFFLINE; 01944 buff[1]=select; 01945 break; 01946 default: 01947 pout("Unrecognized command %d in mvsata_os_specific_handler()\n", command); 01948 EXIT(1); 01949 break; 01950 } 01951 // There are two different types of ioctls(). The HDIO_DRIVE_TASK 01952 // one is this: 01953 // We are now doing the HDIO_DRIVE_CMD type ioctl. 01954 if (ioctl(get_fd(), SCSI_IOCTL_SEND_COMMAND, (void *)&smart_command)) 01955 return -1; 01956 01957 if (command==CHECK_POWER_MODE) { 01958 // LEON -- CHECK THIS PLEASE. THIS SHOULD BE THE SECTOR COUNT 01959 // REGISTER, AND IT MIGHT BE buff[2] NOT buff[3]. Bruce 01960 data[0]=buff[3]; 01961 return 0; 01962 } 01963 01964 // Always succeed on a SMART status, as a disk that failed returned 01965 // buff[4]=0xF4, buff[5]=0x2C, i.e. "Bad SMART status" (see below). 01966 if (command == STATUS) 01967 return 0; 01968 //Data returned is starting from 0 offset 01969 if (command == STATUS_CHECK) 01970 { 01971 // Cyl low and Cyl high unchanged means "Good SMART status" 01972 if (buff[4] == 0x4F && buff[5] == 0xC2) 01973 return 0; 01974 // These values mean "Bad SMART status" 01975 if (buff[4] == 0xF4 && buff[5] == 0x2C) 01976 return 1; 01977 // We haven't gotten output that makes sense; print out some debugging info 01978 syserror("Error SMART Status command failed"); 01979 pout("Please get assistance from %s\n",PACKAGE_BUGREPORT); 01980 pout("Register values returned from SMART Status command are:\n"); 01981 pout("CMD =0x%02x\n",(int)buff[0]); 01982 pout("FR =0x%02x\n",(int)buff[1]); 01983 pout("NS =0x%02x\n",(int)buff[2]); 01984 pout("SC =0x%02x\n",(int)buff[3]); 01985 pout("CL =0x%02x\n",(int)buff[4]); 01986 pout("CH =0x%02x\n",(int)buff[5]); 01987 pout("SEL=0x%02x\n",(int)buff[6]); 01988 return -1; 01989 } 01990 01991 if (copydata) 01992 memcpy(data, buff, 512); 01993 return 0; 01994 } 01995 01996 ///////////////////////////////////////////////////////////////////////////// 01997 /// Highpoint RAID support 01998 01999 class linux_highpoint_device 02000 : public /*implements*/ ata_device_with_command_set, 02001 public /*extends*/ linux_smart_device 02002 { 02003 public: 02004 linux_highpoint_device(smart_interface * intf, const char * dev_name, 02005 unsigned char controller, unsigned char channel, unsigned char port); 02006 02007 protected: 02008 virtual int ata_command_interface(smart_command_set command, int select, char * data); 02009 02010 private: 02011 unsigned char m_hpt_data[3]; ///< controller/channel/port 02012 }; 02013 02014 linux_highpoint_device::linux_highpoint_device(smart_interface * intf, const char * dev_name, 02015 unsigned char controller, unsigned char channel, unsigned char port) 02016 : smart_device(intf, dev_name, "hpt", "hpt"), 02017 linux_smart_device(O_RDONLY | O_NONBLOCK) 02018 { 02019 m_hpt_data[0] = controller; m_hpt_data[1] = channel; m_hpt_data[2] = port; 02020 set_info().info_name = strprintf("%s [hpt_disk_%u/%u/%u]", dev_name, m_hpt_data[0], m_hpt_data[1], m_hpt_data[2]); 02021 } 02022 02023 // this implementation is derived from ata_command_interface with a header 02024 // packing for highpoint linux driver ioctl interface 02025 // 02026 // ioctl(fd,HPTIO_CTL,buff) 02027 // ^^^^^^^^^ 02028 // 02029 // structure of hpt_buff 02030 // +----+----+----+----+--------------------.....---------------------+ 02031 // | 1 | 2 | 3 | 4 | 5 | 02032 // +----+----+----+----+--------------------.....---------------------+ 02033 // 02034 // 1: The target controller [ int ( 4 Bytes ) ] 02035 // 2: The channel of the target controllee [ int ( 4 Bytes ) ] 02036 // 3: HDIO_ ioctl call [ int ( 4 Bytes ) ] 02037 // available from ${LINUX_KERNEL_SOURCE}/Documentation/ioctl/hdio 02038 // 4: the pmport that disk attached, [ int ( 4 Bytes ) ] 02039 // if no pmport device, set to 1 or leave blank 02040 // 5: data [ void * ( var leangth ) ] 02041 // 02042 #define STRANGE_BUFFER_LENGTH (4+512*0xf8) 02043 02044 int linux_highpoint_device::ata_command_interface(smart_command_set command, int select, char * data) 02045 { 02046 unsigned char hpt_buff[4*sizeof(int) + STRANGE_BUFFER_LENGTH]; 02047 unsigned int *hpt = (unsigned int *)hpt_buff; 02048 unsigned char *buff = &hpt_buff[4*sizeof(int)]; 02049 int copydata = 0; 02050 const int HDIO_DRIVE_CMD_OFFSET = 4; 02051 02052 memset(hpt_buff, 0, 4*sizeof(int) + STRANGE_BUFFER_LENGTH); 02053 hpt[0] = m_hpt_data[0]; // controller id 02054 hpt[1] = m_hpt_data[1]; // channel number 02055 hpt[3] = m_hpt_data[2]; // pmport number 02056 02057 buff[0]=ATA_SMART_CMD; 02058 switch (command){ 02059 case CHECK_POWER_MODE: 02060 buff[0]=ATA_CHECK_POWER_MODE; 02061 copydata=1; 02062 break; 02063 case READ_VALUES: 02064 buff[2]=ATA_SMART_READ_VALUES; 02065 buff[3]=1; 02066 copydata=512; 02067 break; 02068 case READ_THRESHOLDS: 02069 buff[2]=ATA_SMART_READ_THRESHOLDS; 02070 buff[1]=buff[3]=1; 02071 copydata=512; 02072 break; 02073 case READ_LOG: 02074 buff[2]=ATA_SMART_READ_LOG_SECTOR; 02075 buff[1]=select; 02076 buff[3]=1; 02077 copydata=512; 02078 break; 02079 case WRITE_LOG: 02080 break; 02081 case IDENTIFY: 02082 buff[0]=ATA_IDENTIFY_DEVICE; 02083 buff[3]=1; 02084 copydata=512; 02085 break; 02086 case PIDENTIFY: 02087 buff[0]=ATA_IDENTIFY_PACKET_DEVICE; 02088 buff[3]=1; 02089 copydata=512; 02090 break; 02091 case ENABLE: 02092 buff[2]=ATA_SMART_ENABLE; 02093 buff[1]=1; 02094 break; 02095 case DISABLE: 02096 buff[2]=ATA_SMART_DISABLE; 02097 buff[1]=1; 02098 break; 02099 case STATUS: 02100 buff[2]=ATA_SMART_STATUS; 02101 break; 02102 case AUTO_OFFLINE: 02103 buff[2]=ATA_SMART_AUTO_OFFLINE; 02104 buff[3]=select; 02105 break; 02106 case AUTOSAVE: 02107 buff[2]=ATA_SMART_AUTOSAVE; 02108 buff[3]=select; 02109 break; 02110 case IMMEDIATE_OFFLINE: 02111 buff[2]=ATA_SMART_IMMEDIATE_OFFLINE; 02112 buff[1]=select; 02113 break; 02114 case STATUS_CHECK: 02115 buff[1]=ATA_SMART_STATUS; 02116 break; 02117 default: 02118 pout("Unrecognized command %d in linux_highpoint_command_interface()\n" 02119 "Please contact " PACKAGE_BUGREPORT "\n", command); 02120 errno=ENOSYS; 02121 return -1; 02122 } 02123 02124 if (command==WRITE_LOG) { 02125 unsigned char task[4*sizeof(int)+sizeof(ide_task_request_t)+512]; 02126 unsigned int *hpt_tf = (unsigned int *)task; 02127 ide_task_request_t *reqtask = (ide_task_request_t *)(&task[4*sizeof(int)]); 02128 task_struct_t *taskfile = (task_struct_t *)reqtask->io_ports; 02129 int retval; 02130 02131 memset(task, 0, sizeof(task)); 02132 02133 hpt_tf[0] = m_hpt_data[0]; // controller id 02134 hpt_tf[1] = m_hpt_data[1]; // channel number 02135 hpt_tf[3] = m_hpt_data[2]; // pmport number 02136 hpt_tf[2] = HDIO_DRIVE_TASKFILE; // real hd ioctl 02137 02138 taskfile->data = 0; 02139 taskfile->feature = ATA_SMART_WRITE_LOG_SECTOR; 02140 taskfile->sector_count = 1; 02141 taskfile->sector_number = select; 02142 taskfile->low_cylinder = 0x4f; 02143 taskfile->high_cylinder = 0xc2; 02144 taskfile->device_head = 0; 02145 taskfile->command = ATA_SMART_CMD; 02146 02147 reqtask->data_phase = TASKFILE_OUT; 02148 reqtask->req_cmd = IDE_DRIVE_TASK_OUT; 02149 reqtask->out_size = 512; 02150 reqtask->in_size = 0; 02151 02152 memcpy(task+sizeof(ide_task_request_t)+4*sizeof(int), data, 512); 02153 02154 if ((retval=ioctl(get_fd(), HPTIO_CTL, task))) { 02155 if (retval==-EINVAL) 02156 pout("Kernel lacks HDIO_DRIVE_TASKFILE support; compile kernel with CONFIG_IDE_TASKFILE_IO set\n"); 02157 return -1; 02158 } 02159 return 0; 02160 } 02161 02162 if (command==STATUS_CHECK){ 02163 int retval; 02164 unsigned const char normal_lo=0x4f, normal_hi=0xc2; 02165 unsigned const char failed_lo=0xf4, failed_hi=0x2c; 02166 buff[4]=normal_lo; 02167 buff[5]=normal_hi; 02168 02169 hpt[2] = HDIO_DRIVE_TASK; 02170 02171 if ((retval=ioctl(get_fd(), HPTIO_CTL, hpt_buff))) { 02172 if (retval==-EINVAL) { 02173 pout("Error SMART Status command via HDIO_DRIVE_TASK failed"); 02174 pout("Rebuild older linux 2.2 kernels with HDIO_DRIVE_TASK support added\n"); 02175 } 02176 else 02177 syserror("Error SMART Status command failed"); 02178 return -1; 02179 } 02180 02181 if (buff[4]==normal_lo && buff[5]==normal_hi) 02182 return 0; 02183 02184 if (buff[4]==failed_lo && buff[5]==failed_hi) 02185 return 1; 02186 02187 syserror("Error SMART Status command failed"); 02188 pout("Please get assistance from " PACKAGE_HOMEPAGE "\n"); 02189 pout("Register values returned from SMART Status command are:\n"); 02190 pout("CMD=0x%02x\n",(int)buff[0]); 02191 pout("FR =0x%02x\n",(int)buff[1]); 02192 pout("NS =0x%02x\n",(int)buff[2]); 02193 pout("SC =0x%02x\n",(int)buff[3]); 02194 pout("CL =0x%02x\n",(int)buff[4]); 02195 pout("CH =0x%02x\n",(int)buff[5]); 02196 pout("SEL=0x%02x\n",(int)buff[6]); 02197 return -1; 02198 } 02199 02200 #if 1 02201 if (command==IDENTIFY || command==PIDENTIFY) { 02202 unsigned char deviceid[4*sizeof(int)+512*sizeof(char)]; 02203 unsigned int *hpt_id = (unsigned int *)deviceid; 02204 02205 hpt_id[0] = m_hpt_data[0]; // controller id 02206 hpt_id[1] = m_hpt_data[1]; // channel number 02207 hpt_id[3] = m_hpt_data[2]; // pmport number 02208 02209 hpt_id[2] = HDIO_GET_IDENTITY; 02210 if (!ioctl(get_fd(), HPTIO_CTL, deviceid) && (deviceid[4*sizeof(int)] & 0x8000)) 02211 buff[0]=(command==IDENTIFY)?ATA_IDENTIFY_PACKET_DEVICE:ATA_IDENTIFY_DEVICE; 02212 } 02213 #endif 02214 02215 hpt[2] = HDIO_DRIVE_CMD; 02216 if ((ioctl(get_fd(), HPTIO_CTL, hpt_buff))) 02217 return -1; 02218 02219 if (command==CHECK_POWER_MODE) 02220 buff[HDIO_DRIVE_CMD_OFFSET]=buff[2]; 02221 02222 if (copydata) 02223 memcpy(data, buff+HDIO_DRIVE_CMD_OFFSET, copydata); 02224 02225 return 0; 02226 } 02227 02228 #if 0 // TODO: Migrate from 'smart_command_set' to 'ata_in_regs' OR remove the function 02229 // Utility function for printing warnings 02230 void printwarning(smart_command_set command){ 02231 static int printed[4]={0,0,0,0}; 02232 const char* message= 02233 "can not be passed through the 3ware 3w-xxxx driver. This can be fixed by\n" 02234 "applying a simple 3w-xxxx driver patch that can be found here:\n" 02235 PACKAGE_HOMEPAGE "\n" 02236 "Alternatively, upgrade your 3w-xxxx driver to version 1.02.00.037 or greater.\n\n"; 02237 02238 if (command==AUTO_OFFLINE && !printed[0]) { 02239 printed[0]=1; 02240 pout("The SMART AUTO-OFFLINE ENABLE command (smartmontools -o on option/Directive)\n%s", message); 02241 } 02242 else if (command==AUTOSAVE && !printed[1]) { 02243 printed[1]=1; 02244 pout("The SMART AUTOSAVE ENABLE command (smartmontools -S on option/Directive)\n%s", message); 02245 } 02246 else if (command==STATUS_CHECK && !printed[2]) { 02247 printed[2]=1; 02248 pout("The SMART RETURN STATUS return value (smartmontools -H option/Directive)\n%s", message); 02249 } 02250 else if (command==WRITE_LOG && !printed[3]) { 02251 printed[3]=1; 02252 pout("The SMART WRITE LOG command (smartmontools -t selective) only supported via char /dev/tw[ae] interface\n"); 02253 } 02254 02255 return; 02256 } 02257 #endif 02258 02259 ///////////////////////////////////////////////////////////////////////////// 02260 /// SCSI open with autodetection support 02261 02262 smart_device * linux_scsi_device::autodetect_open() 02263 { 02264 // Open device 02265 if (!open()) 02266 return this; 02267 02268 // No Autodetection if device type was specified by user 02269 bool sat_only = false; 02270 if (*get_req_type()) { 02271 // Detect SAT if device object was created by scan_smart_devices(). 02272 if (!(m_scanning && !strcmp(get_req_type(), "sat"))) 02273 return this; 02274 sat_only = true; 02275 } 02276 02277 // The code below is based on smartd.cpp:SCSIFilterKnown() 02278 02279 // Get INQUIRY 02280 unsigned char req_buff[64] = {0, }; 02281 int req_len = 36; 02282 if (scsiStdInquiry(this, req_buff, req_len)) { 02283 // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices 02284 // watch this spot ... other devices could lock up here 02285 req_len = 64; 02286 if (scsiStdInquiry(this, req_buff, req_len)) { 02287 // device doesn't like INQUIRY commands 02288 close(); 02289 set_err(EIO, "INQUIRY failed"); 02290 return this; 02291 } 02292 } 02293 02294 int avail_len = req_buff[4] + 5; 02295 int len = (avail_len < req_len ? avail_len : req_len); 02296 if (len < 36) { 02297 if (sat_only) { 02298 close(); 02299 set_err(EIO, "INQUIRY too short for SAT"); 02300 } 02301 return this; 02302 } 02303 02304 // Use INQUIRY to detect type 02305 if (!sat_only) { 02306 02307 // 3ware ? 02308 if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4)) { 02309 close(); 02310 set_err(EINVAL, "AMCC/3ware controller, please try adding '-d 3ware,N',\n" 02311 "you may need to replace %s with /dev/twlN, /dev/twaN or /dev/tweN", get_dev_name()); 02312 return this; 02313 } 02314 02315 // DELL? 02316 if (!memcmp(req_buff + 8, "DELL PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8) 02317 || !memcmp(req_buff + 16, "PERC H700", 9) || !memcmp(req_buff + 8, "LSI\0",4) 02318 ) { 02319 close(); 02320 set_err(EINVAL, "DELL or MegaRaid controller, please try adding '-d megaraid,N'"); 02321 return this; 02322 } 02323 02324 // Marvell ? 02325 if (len >= 42 && !memcmp(req_buff + 36, "MVSATA", 6)) { 02326 //pout("Device %s: using '-d marvell' for ATA disk with Marvell driver\n", get_dev_name()); 02327 close(); 02328 smart_device_auto_ptr newdev( 02329 new linux_marvell_device(smi(), get_dev_name(), get_req_type()) 02330 ); 02331 newdev->open(); // TODO: Can possibly pass open fd 02332 delete this; 02333 return newdev.release(); 02334 } 02335 } 02336 02337 // SAT or USB ? 02338 { 02339 smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len); 02340 if (newdev) 02341 // NOTE: 'this' is now owned by '*newdev' 02342 return newdev; 02343 } 02344 02345 // Nothing special found 02346 02347 if (sat_only) { 02348 close(); 02349 set_err(EIO, "Not a SAT device"); 02350 } 02351 return this; 02352 } 02353 02354 ////////////////////////////////////////////////////////////////////// 02355 // USB bridge ID detection 02356 02357 // Read USB ID from /sys file 02358 static bool read_id(const std::string & path, unsigned short & id) 02359 { 02360 FILE * f = fopen(path.c_str(), "r"); 02361 if (!f) 02362 return false; 02363 int n = -1; 02364 bool ok = (fscanf(f, "%hx%n", &id, &n) == 1 && n == 4); 02365 fclose(f); 02366 return ok; 02367 } 02368 02369 // Get USB bridge ID for "sdX" 02370 static bool get_usb_id(const char * name, unsigned short & vendor_id, 02371 unsigned short & product_id, unsigned short & version) 02372 { 02373 // Only "sdX" supported 02374 if (!(!strncmp(name, "sd", 2) && !strchr(name, '/'))) 02375 return false; 02376 02377 // Start search at dir referenced by symlink "/sys/block/sdX/device" 02378 // -> "/sys/devices/.../usb*/.../host*/target*/..." 02379 std::string dir = strprintf("/sys/block/%s/device", name); 02380 02381 // Stop search at "/sys/devices" 02382 struct stat st; 02383 if (stat("/sys/devices", &st)) 02384 return false; 02385 ino_t stop_ino = st.st_ino; 02386 02387 // Search in parent directories until "idVendor" is found, 02388 // fail if "/sys/devices" reached or too many iterations 02389 int cnt = 0; 02390 do { 02391 dir += "/.."; 02392 if (!(++cnt < 10 && !stat(dir.c_str(), &st) && st.st_ino != stop_ino)) 02393 return false; 02394 } while (access((dir + "/idVendor").c_str(), 0)); 02395 02396 // Read IDs 02397 if (!( read_id(dir + "/idVendor", vendor_id) 02398 && read_id(dir + "/idProduct", product_id) 02399 && read_id(dir + "/bcdDevice", version) )) 02400 return false; 02401 02402 if (scsi_debugmode > 1) 02403 pout("USB ID = 0x%04x:0x%04x (0x%03x)\n", vendor_id, product_id, version); 02404 return true; 02405 } 02406 02407 ////////////////////////////////////////////////////////////////////// 02408 /// Linux interface 02409 02410 class linux_smart_interface 02411 : public /*implements*/ smart_interface 02412 { 02413 public: 02414 virtual std::string get_os_version_str(); 02415 02416 virtual std::string get_app_examples(const char * appname); 02417 02418 virtual bool scan_smart_devices(smart_device_list & devlist, const char * type, 02419 const char * pattern = 0); 02420 02421 protected: 02422 virtual ata_device * get_ata_device(const char * name, const char * type); 02423 02424 virtual scsi_device * get_scsi_device(const char * name, const char * type); 02425 02426 virtual smart_device * autodetect_smart_device(const char * name); 02427 02428 virtual smart_device * get_custom_smart_device(const char * name, const char * type); 02429 02430 virtual std::string get_valid_custom_dev_types_str(); 02431 02432 private: 02433 bool get_dev_list(smart_device_list & devlist, const char * pattern, 02434 bool scan_ata, bool scan_scsi, const char * req_type, bool autodetect); 02435 bool get_dev_megasas(smart_device_list & devlist); 02436 smart_device * missing_option(const char * opt); 02437 int megasas_dcmd_cmd(int bus_no, uint32_t opcode, void *buf, 02438 size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp); 02439 int megasas_pd_add_list(int bus_no, smart_device_list & devlist); 02440 }; 02441 02442 std::string linux_smart_interface::get_os_version_str() 02443 { 02444 struct utsname u; 02445 if (!uname(&u)) 02446 return strprintf("%s-linux-%s", u.machine, u.release); 02447 else 02448 return SMARTMONTOOLS_BUILD_HOST; 02449 } 02450 02451 std::string linux_smart_interface::get_app_examples(const char * appname) 02452 { 02453 if (!strcmp(appname, "smartctl")) 02454 return smartctl_examples; 02455 return ""; 02456 } 02457 02458 // we are going to take advantage of the fact that Linux's devfs will only 02459 // have device entries for devices that exist. So if we get the equivalent of 02460 // ls /dev/hd[a-t], we have all the ATA devices on the system 02461 bool linux_smart_interface::get_dev_list(smart_device_list & devlist, 02462 const char * pattern, bool scan_ata, bool scan_scsi, 02463 const char * req_type, bool autodetect) 02464 { 02465 // Use glob to look for any directory entries matching the pattern 02466 glob_t globbuf; 02467 memset(&globbuf, 0, sizeof(globbuf)); 02468 int retglob = glob(pattern, GLOB_ERR, NULL, &globbuf); 02469 if (retglob) { 02470 // glob failed: free memory and return 02471 globfree(&globbuf); 02472 02473 if (retglob==GLOB_NOMATCH){ 02474 pout("glob(3) found no matches for pattern %s\n", pattern); 02475 return true; 02476 } 02477 02478 if (retglob==GLOB_NOSPACE) 02479 set_err(ENOMEM, "glob(3) ran out of memory matching pattern %s", pattern); 02480 #ifdef GLOB_ABORTED // missing in old versions of glob.h 02481 else if (retglob==GLOB_ABORTED) 02482 set_err(EINVAL, "glob(3) aborted matching pattern %s", pattern); 02483 #endif 02484 else 02485 set_err(EINVAL, "Unexplained error in glob(3) of pattern %s", pattern); 02486 02487 return false; 02488 } 02489 02490 // did we find too many paths? 02491 const int max_pathc = 32; 02492 int n = (int)globbuf.gl_pathc; 02493 if (n > max_pathc) { 02494 pout("glob(3) found %d > MAX=%d devices matching pattern %s: ignoring %d paths\n", 02495 n, max_pathc, pattern, n - max_pathc); 02496 n = max_pathc; 02497 } 02498 02499 // now step through the list returned by glob. If not a link, copy 02500 // to list. If it is a link, evaluate it and see if the path ends 02501 // in "disc". 02502 for (int i = 0; i < n; i++){ 02503 // see if path is a link 02504 char linkbuf[1024]; 02505 int retlink = readlink(globbuf.gl_pathv[i], linkbuf, sizeof(linkbuf)-1); 02506 02507 char tmpname[1024]={0}; 02508 const char * name = 0; 02509 bool is_scsi = scan_scsi; 02510 // if not a link (or a strange link), keep it 02511 if (retlink<=0 || retlink>1023) 02512 name = globbuf.gl_pathv[i]; 02513 else { 02514 // or if it's a link that points to a disc, follow it 02515 linkbuf[retlink] = 0; 02516 const char *p; 02517 if ((p=strrchr(linkbuf, '/')) && !strcmp(p+1, "disc")) 02518 // This is the branch of the code that gets followed if we are 02519 // using devfs WITH traditional compatibility links. In this 02520 // case, we add the traditional device name to the list that 02521 // is returned. 02522 name = globbuf.gl_pathv[i]; 02523 else { 02524 // This is the branch of the code that gets followed if we are 02525 // using devfs WITHOUT traditional compatibility links. In 02526 // this case, we check that the link to the directory is of 02527 // the correct type, and then append "disc" to it. 02528 bool match_ata = strstr(linkbuf, "ide"); 02529 bool match_scsi = strstr(linkbuf, "scsi"); 02530 if (((match_ata && scan_ata) || (match_scsi && scan_scsi)) && !(match_ata && match_scsi)) { 02531 is_scsi = match_scsi; 02532 snprintf(tmpname, sizeof(tmpname), "%s/disc", globbuf.gl_pathv[i]); 02533 name = tmpname; 02534 } 02535 } 02536 } 02537 02538 if (name) { 02539 // Found a name, add device to list. 02540 smart_device * dev; 02541 if (autodetect) 02542 dev = autodetect_smart_device(name); 02543 else if (is_scsi) 02544 dev = new linux_scsi_device(this, name, req_type, true /*scanning*/); 02545 else 02546 dev = new linux_ata_device(this, name, req_type); 02547 if (dev) // autodetect_smart_device() may return nullptr. 02548 devlist.push_back(dev); 02549 } 02550 } 02551 02552 // free memory 02553 globfree(&globbuf); 02554 return true; 02555 } 02556 02557 // getting devices from LSI SAS MegaRaid, if available 02558 bool linux_smart_interface::get_dev_megasas(smart_device_list & devlist) 02559 { 02560 /* Scanning of disks on MegaRaid device */ 02561 /* Perform mknod of device ioctl node */ 02562 int mjr, n1; 02563 char line[128]; 02564 bool scan_megasas = false; 02565 FILE * fp = fopen("/proc/devices", "r"); 02566 while (fgets(line, sizeof(line), fp) != NULL) { 02567 n1=0; 02568 if (sscanf(line, "%d megaraid_sas_ioctl%n", &mjr, &n1) == 1 && n1 == 22) { 02569 scan_megasas = true; 02570 n1=mknod("/dev/megaraid_sas_ioctl_node", S_IFCHR, makedev(mjr, 0)); 02571 if(scsi_debugmode > 0) 02572 pout("Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno); 02573 if (n1 >= 0 || errno == EEXIST) 02574 break; 02575 } 02576 } 02577 fclose(fp); 02578 02579 if(!scan_megasas) 02580 return false; 02581 02582 // getting bus numbers with megasas devices 02583 struct dirent *ep; 02584 unsigned int host_no = 0; 02585 char sysfsdir[256]; 02586 02587 /* we are using sysfs to get list of all scsi hosts */ 02588 DIR * dp = opendir ("/sys/class/scsi_host/"); 02589 if (dp != NULL) 02590 { 02591 while ((ep = readdir (dp)) != NULL) { 02592 if (!sscanf(ep->d_name, "host%d", &host_no)) 02593 continue; 02594 /* proc_name should be megaraid_sas */ 02595 snprintf(sysfsdir, sizeof(sysfsdir) - 1, 02596 "/sys/class/scsi_host/host%d/proc_name", host_no); 02597 if((fp = fopen(sysfsdir, "r")) == NULL) 02598 continue; 02599 if(fgets(line, sizeof(line), fp) != NULL && !strncmp(line,"megaraid_sas",12)) { 02600 megasas_pd_add_list(host_no, devlist); 02601 } 02602 fclose(fp); 02603 } 02604 (void) closedir (dp); 02605 } else { /* sysfs not mounted ? */ 02606 for(unsigned i = 0; i <=16; i++) // trying to add devices on first 16 buses 02607 megasas_pd_add_list(i, devlist); 02608 } 02609 return true; 02610 } 02611 02612 bool linux_smart_interface::scan_smart_devices(smart_device_list & devlist, 02613 const char * type, const char * pattern /*= 0*/) 02614 { 02615 if (pattern) { 02616 set_err(EINVAL, "DEVICESCAN with pattern not implemented yet"); 02617 return false; 02618 } 02619 02620 if (!type) 02621 type = ""; 02622 02623 bool scan_ata = (!*type || !strcmp(type, "ata" )); 02624 // "sat" detection will be later handled in linux_scsi_device::autodetect_open() 02625 bool scan_scsi = (!*type || !strcmp(type, "scsi") || !strcmp(type, "sat")); 02626 if (!(scan_ata || scan_scsi)) 02627 return true; 02628 02629 if (scan_ata) 02630 get_dev_list(devlist, "/dev/hd[a-t]", true, false, type, false); 02631 if (scan_scsi) { 02632 bool autodetect = !*type; // Try USB autodetection if no type specifed 02633 get_dev_list(devlist, "/dev/sd[a-z]", false, true, type, autodetect); 02634 // Support up to 104 devices 02635 get_dev_list(devlist, "/dev/sd[a-c][a-z]", false, true, type, autodetect); 02636 // get device list from the megaraid device 02637 get_dev_megasas(devlist); 02638 } 02639 02640 // if we found traditional links, we are done 02641 if (devlist.size() > 0) 02642 return true; 02643 02644 // else look for devfs entries without traditional links 02645 // TODO: Add udev support 02646 return get_dev_list(devlist, "/dev/discs/disc*", scan_ata, scan_scsi, type, false); 02647 } 02648 02649 ata_device * linux_smart_interface::get_ata_device(const char * name, const char * type) 02650 { 02651 return new linux_ata_device(this, name, type); 02652 } 02653 02654 scsi_device * linux_smart_interface::get_scsi_device(const char * name, const char * type) 02655 { 02656 return new linux_scsi_device(this, name, type); 02657 } 02658 02659 smart_device * linux_smart_interface::missing_option(const char * opt) 02660 { 02661 set_err(EINVAL, "requires option '%s'", opt); 02662 return 0; 02663 } 02664 02665 int 02666 linux_smart_interface::megasas_dcmd_cmd(int bus_no, uint32_t opcode, void *buf, 02667 size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp) 02668 { 02669 struct megasas_iocpacket ioc; 02670 02671 if ((mbox != NULL && (mboxlen == 0 || mboxlen > MFI_MBOX_SIZE)) || 02672 (mbox == NULL && mboxlen != 0)) 02673 { 02674 errno = EINVAL; 02675 return (-1); 02676 } 02677 02678 bzero(&ioc, sizeof(ioc)); 02679 struct megasas_dcmd_frame * dcmd = &ioc.frame.dcmd; 02680 ioc.host_no = bus_no; 02681 if (mbox) 02682 bcopy(mbox, dcmd->mbox.w, mboxlen); 02683 dcmd->cmd = MFI_CMD_DCMD; 02684 dcmd->timeout = 0; 02685 dcmd->flags = 0; 02686 dcmd->data_xfer_len = bufsize; 02687 dcmd->opcode = opcode; 02688 02689 if (bufsize > 0) { 02690 dcmd->sge_count = 1; 02691 dcmd->data_xfer_len = bufsize; 02692 dcmd->sgl.sge32[0].phys_addr = (intptr_t)buf; 02693 dcmd->sgl.sge32[0].length = (uint32_t)bufsize; 02694 ioc.sge_count = 1; 02695 ioc.sgl_off = offsetof(struct megasas_dcmd_frame, sgl); 02696 ioc.sgl[0].iov_base = buf; 02697 ioc.sgl[0].iov_len = bufsize; 02698 } 02699 02700 int fd; 02701 if ((fd = ::open("/dev/megaraid_sas_ioctl_node", O_RDWR)) <= 0) { 02702 return (errno); 02703 } 02704 02705 int r = ioctl(fd, MEGASAS_IOC_FIRMWARE, &ioc); 02706 if (r < 0) { 02707 return (r); 02708 } 02709 02710 if (statusp != NULL) 02711 *statusp = dcmd->cmd_status; 02712 else if (dcmd->cmd_status != MFI_STAT_OK) { 02713 fprintf(stderr, "command %x returned error status %x\n", 02714 opcode, dcmd->cmd_status); 02715 errno = EIO; 02716 return (-1); 02717 } 02718 return (0); 02719 } 02720 02721 int 02722 linux_smart_interface::megasas_pd_add_list(int bus_no, smart_device_list & devlist) 02723 { 02724 /* 02725 * Keep fetching the list in a loop until we have a large enough 02726 * buffer to hold the entire list. 02727 */ 02728 megasas_pd_list * list = 0; 02729 for (unsigned list_size = 1024; ; ) { 02730 list = (megasas_pd_list *)realloc(list, list_size); 02731 if (!list) 02732 throw std::bad_alloc(); 02733 bzero(list, list_size); 02734 if (megasas_dcmd_cmd(bus_no, MFI_DCMD_PD_GET_LIST, list, list_size, NULL, 0, 02735 NULL) < 0) 02736 { 02737 free(list); 02738 return (-1); 02739 } 02740 if (list->size <= list_size) 02741 break; 02742 list_size = list->size; 02743 } 02744 02745 // adding all SCSI devices 02746 for (unsigned i = 0; i < list->count; i++) { 02747 if(list->addr[i].scsi_dev_type) 02748 continue; /* non disk device found */ 02749 char line[128]; 02750 snprintf(line, sizeof(line) - 1, "/dev/bus/%d", bus_no); 02751 smart_device * dev = new linux_megaraid_device(this, line, 0, list->addr[i].device_id); 02752 devlist.push_back(dev); 02753 } 02754 free(list); 02755 return (0); 02756 } 02757 02758 // Return kernel release as integer ("2.6.31" -> 206031) 02759 static unsigned get_kernel_release() 02760 { 02761 struct utsname u; 02762 if (uname(&u)) 02763 return 0; 02764 unsigned x = 0, y = 0, z = 0; 02765 if (!(sscanf(u.release, "%u.%u.%u", &x, &y, &z) == 3 02766 && x < 100 && y < 100 && z < 1000 )) 02767 return 0; 02768 return x * 100000 + y * 1000 + z; 02769 } 02770 02771 // Guess device type (ata or scsi) based on device name (Linux 02772 // specific) SCSI device name in linux can be sd, sr, scd, st, nst, 02773 // osst, nosst and sg. 02774 smart_device * linux_smart_interface::autodetect_smart_device(const char * name) 02775 { 02776 const char * test_name = name; 02777 02778 // Dereference symlinks 02779 struct stat st; 02780 std::string pathbuf; 02781 if (!lstat(name, &st) && S_ISLNK(st.st_mode)) { 02782 char * p = realpath(name, (char *)0); 02783 if (p) { 02784 pathbuf = p; 02785 free(p); 02786 test_name = pathbuf.c_str(); 02787 } 02788 } 02789 02790 // Remove the leading /dev/... if it's there 02791 static const char dev_prefix[] = "/dev/"; 02792 if (str_starts_with(test_name, dev_prefix)) 02793 test_name += strlen(dev_prefix); 02794 02795 // form /dev/h* or h* 02796 if (str_starts_with(test_name, "h")) 02797 return new linux_ata_device(this, name, ""); 02798 02799 // form /dev/ide/* or ide/* 02800 if (str_starts_with(test_name, "ide/")) 02801 return new linux_ata_device(this, name, ""); 02802 02803 // form /dev/s* or s* 02804 if (str_starts_with(test_name, "s")) { 02805 02806 // Try to detect possible USB->(S)ATA bridge 02807 unsigned short vendor_id = 0, product_id = 0, version = 0; 02808 if (get_usb_id(test_name, vendor_id, product_id, version)) { 02809 const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id, version); 02810 if (!usbtype) 02811 return 0; 02812 02813 // Kernels before 2.6.29 do not support the sense data length 02814 // required for SAT ATA PASS-THROUGH(16) 02815 if (!strcmp(usbtype, "sat") && get_kernel_release() < 206029) 02816 usbtype = "sat,12"; 02817 02818 // Return SAT/USB device for this type 02819 // (Note: linux_scsi_device::autodetect_open() will not be called in this case) 02820 return get_sat_device(usbtype, new linux_scsi_device(this, name, "")); 02821 } 02822 02823 // No USB bridge found, assume regular SCSI device 02824 return new linux_scsi_device(this, name, ""); 02825 } 02826 02827 // form /dev/scsi/* or scsi/* 02828 if (str_starts_with(test_name, "scsi/")) 02829 return new linux_scsi_device(this, name, ""); 02830 02831 // form /dev/ns* or ns* 02832 if (str_starts_with(test_name, "ns")) 02833 return new linux_scsi_device(this, name, ""); 02834 02835 // form /dev/os* or os* 02836 if (str_starts_with(test_name, "os")) 02837 return new linux_scsi_device(this, name, ""); 02838 02839 // form /dev/nos* or nos* 02840 if (str_starts_with(test_name, "nos")) 02841 return new linux_scsi_device(this, name, ""); 02842 02843 // form /dev/tw[ael]* or tw[ael]* 02844 if (str_starts_with(test_name, "tw") && strchr("ael", test_name[2])) 02845 return missing_option("-d 3ware,N"); 02846 02847 // form /dev/cciss/* or cciss/* 02848 if (str_starts_with(test_name, "cciss/")) 02849 return missing_option("-d cciss,N"); 02850 02851 // we failed to recognize any of the forms 02852 return 0; 02853 } 02854 02855 smart_device * linux_smart_interface::get_custom_smart_device(const char * name, const char * type) 02856 { 02857 // Marvell ? 02858 if (!strcmp(type, "marvell")) 02859 return new linux_marvell_device(this, name, type); 02860 02861 // 3Ware ? 02862 int disknum = -1, n1 = -1, n2 = -1; 02863 if (sscanf(type, "3ware,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) { 02864 if (n2 != (int)strlen(type)) { 02865 set_err(EINVAL, "Option -d 3ware,N requires N to be a non-negative integer"); 02866 return 0; 02867 } 02868 if (!(0 <= disknum && disknum <= 127)) { 02869 set_err(EINVAL, "Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum); 02870 return 0; 02871 } 02872 02873 if (!strncmp(name, "/dev/twl", 8)) 02874 return new linux_escalade_device(this, name, linux_escalade_device::AMCC_3WARE_9700_CHAR, disknum); 02875 else if (!strncmp(name, "/dev/twa", 8)) 02876 return new linux_escalade_device(this, name, linux_escalade_device::AMCC_3WARE_9000_CHAR, disknum); 02877 else if (!strncmp(name, "/dev/twe", 8)) 02878 return new linux_escalade_device(this, name, linux_escalade_device::AMCC_3WARE_678K_CHAR, disknum); 02879 else 02880 return new linux_escalade_device(this, name, linux_escalade_device::AMCC_3WARE_678K, disknum); 02881 } 02882 02883 // Areca? 02884 disknum = n1 = n2 = -1; 02885 int encnum = 1; 02886 if (sscanf(type, "areca,%n%d/%d%n", &n1, &disknum, &encnum, &n2) >= 1 || n1 == 6) { 02887 if (!(1 <= disknum && disknum <= 128)) { 02888 set_err(EINVAL, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum); 02889 return 0; 02890 } 02891 if (!(1 <= encnum && encnum <= 8)) { 02892 set_err(EINVAL, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum); 02893 return 0; 02894 } 02895 return new linux_areca_ata_device(this, name, disknum, encnum); 02896 } 02897 02898 // Highpoint ? 02899 int controller = -1, channel = -1; disknum = 1; 02900 n1 = n2 = -1; int n3 = -1; 02901 if (sscanf(type, "hpt,%n%d/%d%n/%d%n", &n1, &controller, &channel, &n2, &disknum, &n3) >= 2 || n1 == 4) { 02902 int len = strlen(type); 02903 if (!(n2 == len || n3 == len)) { 02904 set_err(EINVAL, "Option '-d hpt,L/M/N' supports 2-3 items"); 02905 return 0; 02906 } 02907 if (!(1 <= controller && controller <= 8)) { 02908 set_err(EINVAL, "Option '-d hpt,L/M/N' invalid controller id L supplied"); 02909 return 0; 02910 } 02911 if (!(1 <= channel && channel <= 16)) { 02912 set_err(EINVAL, "Option '-d hpt,L/M/N' invalid channel number M supplied"); 02913 return 0; 02914 } 02915 if (!(1 <= disknum && disknum <= 15)) { 02916 set_err(EINVAL, "Option '-d hpt,L/M/N' invalid pmport number N supplied"); 02917 return 0; 02918 } 02919 return new linux_highpoint_device(this, name, controller, channel, disknum); 02920 } 02921 02922 #ifdef HAVE_LINUX_CCISS_IOCTL_H 02923 // CCISS ? 02924 disknum = n1 = n2 = -1; 02925 if (sscanf(type, "cciss,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) { 02926 if (n2 != (int)strlen(type)) { 02927 set_err(EINVAL, "Option -d cciss,N requires N to be a non-negative integer"); 02928 return 0; 02929 } 02930 if (!(0 <= disknum && disknum <= 127)) { 02931 set_err(EINVAL, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum); 02932 return 0; 02933 } 02934 return get_sat_device("sat,auto", new linux_cciss_device(this, name, disknum)); 02935 } 02936 #endif // HAVE_LINUX_CCISS_IOCTL_H 02937 02938 // MegaRAID ? 02939 if (sscanf(type, "megaraid,%d", &disknum) == 1) { 02940 return new linux_megaraid_device(this, name, 0, disknum); 02941 } 02942 return 0; 02943 } 02944 02945 std::string linux_smart_interface::get_valid_custom_dev_types_str() 02946 { 02947 return "marvell, areca,N/E, 3ware,N, hpt,L/M/N, megaraid,N" 02948 #ifdef HAVE_LINUX_CCISS_IOCTL_H 02949 ", cciss,N" 02950 #endif 02951 ; 02952 } 02953 02954 } // namespace 02955 02956 ///////////////////////////////////////////////////////////////////////////// 02957 /// Initialize platform interface and register with smi() 02958 02959 void smart_interface::init() 02960 { 02961 static os_linux::linux_smart_interface the_interface; 02962 smart_interface::set(&the_interface); 02963 }
1.7.4