Ticket #2: smartnew.diff
File smartnew.diff, 73.5 KB (added by , 16 years ago) |
---|
-
os_freebsd.cpp
23 23 #include <camlib.h> 24 24 #include <cam/scsi/scsi_message.h> 25 25 #include <cam/scsi/scsi_pass.h> 26 #include <dev/usb/usb.h> 26 27 #if defined(__DragonFly__) 27 28 #include <sys/nata.h> 28 29 #else … … 30 31 #endif 31 32 #include <sys/stat.h> 32 33 #include <unistd.h> 33 #include <fcntl.h>34 34 #include <glob.h> 35 #include <fcntl.h>36 35 #include <stddef.h> 37 36 #include <paths.h> 37 #include <sys/utsname.h> 38 38 39 40 39 #include "config.h" 41 40 #include "int64.h" 42 41 #include "atacmds.h" … … 46 45 #include "extern.h" 47 46 #include "os_freebsd.h" 48 47 48 #include "dev_interface.h" 49 #include "dev_ata_cmd_set.h" 50 51 #define USBDEV "/dev/usb" 52 53 #define CONTROLLER_UNKNOWN 0x00 54 #define CONTROLLER_ATA 0x01 55 #define CONTROLLER_SCSI 0x02 56 #define CONTROLLER_3WARE 0x03 // set by -d option, but converted to one of three types below 57 #define CONTROLLER_3WARE_678K 0x04 // NOT set by guess_device_type() 58 #define CONTROLLER_3WARE_9000_CHAR 0x05 // set by guess_device_type() 59 #define CONTROLLER_3WARE_678K_CHAR 0x06 // set by guess_device_type() 60 #define CONTROLLER_MARVELL_SATA 0x07 // SATA drives behind Marvell controllers 61 #define CONTROLLER_SAT 0x08 // SATA device behind a SCSI ATA Translation (SAT) layer 62 #define CONTROLLER_HPT 0x09 // SATA drives behind HighPoint Raid controllers 63 #define CONTROLLER_CCISS 0x10 // CCISS controller 64 #define CONTROLLER_PARSEDEV 0x11 // "smartctl -r ataioctl,2 ..." output parser pseudo-device 65 #define CONTROLLER_USBCYPRESS 0x12 // ATA device behind Cypress USB bridge 66 #define CONTROLLER_ARECA 0x13 // Areca controller 67 49 68 static __unused const char *filenameandversion="$Id: os_freebsd.cpp,v 1.73 2009/01/14 02:39:00 sxzzsf Exp $"; 50 69 51 70 const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp,v 1.73 2009/01/14 02:39:00 sxzzsf Exp $" \ … … 58 77 struct freebsd_dev_channel *devicetable[FREEBSD_MAXDEV]; 59 78 60 79 // forward declaration 61 static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel *ch);80 // static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel *ch); 62 81 63 // print examples for smartctl 64 void print_smartctl_examples(){ 65 printf("=================================================== SMARTCTL EXAMPLES =====\n\n"); 66 #ifdef HAVE_GETOPT_LONG 67 printf( 82 83 // Returns 1 if device not available/open/found else 0. Also shifts fd into valid range. 84 static int isnotopen(int *fd, struct freebsd_dev_channel** fdchan) { 85 // put valid "file descriptor" into range 0...FREEBSD_MAXDEV-1 86 *fd -= FREEBSD_FDOFFSET; 87 88 // check for validity of "file descriptor". 89 if (*fd<0 || *fd>=FREEBSD_MAXDEV || !((*fdchan)=devicetable[*fd])) { 90 errno = ENODEV; 91 return 1; 92 } 93 94 return 0; 95 } 96 97 #define NO_RETURN 0 98 #define BAD_SMART 1 99 #define NO_DISK_3WARE 2 100 #define BAD_KERNEL 3 101 #define MAX_MSG 3 102 103 // Utility function for printing warnings 104 void printwarning(int msgNo, const char* extra) { 105 static int printed[] = {0,0,0,0}; 106 static const char* message[]={ 107 "The SMART RETURN STATUS return value (smartmontools -H option/Directive)\n can not be retrieved with this version of ATAng, please do not rely on this value\nYou should update to at least 5.2\n", 108 109 "Error SMART Status command failed\nPlease get assistance from \n" PACKAGE_HOMEPAGE "\nRegister values returned from SMART Status command are:\n", 110 111 "You must specify a DISK # for 3ware drives with -d 3ware,<n> where <n> begins with 1 for first disk drive\n", 112 113 "ATA support is not provided for this kernel version. Please ugrade to a recent 5-CURRENT kernel (post 09/01/2003 or so)\n" 114 }; 115 116 if (msgNo >= 0 && msgNo <= MAX_MSG) { 117 if (!printed[msgNo]) { 118 printed[msgNo] = 1; 119 pout("%s", message[msgNo]); 120 if (extra) 121 pout("%s",extra); 122 } 123 } 124 return; 125 } 126 127 128 // Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c 129 130 #define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520 131 #define BUFFER_LEN_9000_CHAR ( sizeof(TW_OSLI_IOCTL_NO_DATA_BUF) + sizeof(TWE_Command) ) // 2048 132 #define TW_IOCTL_BUFFER_SIZE ( MAX(BUFFER_LEN_678K_CHAR, BUFFER_LEN_9000_CHAR) ) 133 134 135 136 137 138 139 #ifndef ATA_DEVICE 140 #define ATA_DEVICE "/dev/ata" 141 #endif 142 143 144 145 // global variable holding byte count of allocated memory 146 long long bytes; 147 148 149 /* 150 * dev_legacy.cpp 151 * 152 * Home page of code is: http://smartmontools.sourceforge.net 153 * 154 * Copyright (C) 2008 Christian Franke <smartmontools-support@lists.sourceforge.net> 155 * 156 * This program is free software; you can redistribute it and/or modify 157 * it under the terms of the GNU General Public License as published by 158 * the Free Software Foundation; either version 2, or (at your option) 159 * any later version. 160 * 161 * You should have received a copy of the GNU General Public License 162 * (for example COPYING); If not, see <http://www.gnu.org/licenses/>. 163 * 164 */ 165 166 167 const char * dev_freebsd_cpp_cvsid = "$Id: dev_legacy.cpp,v 1.2 2008/12/18 03:40:05 dlukes Exp $" 168 DEV_INTERFACE_H_CVSID; 169 170 extern smartmonctrl * con; // con->reportscsiioctl 171 172 ///////////////////////////////////////////////////////////////////////////// 173 174 #ifdef HAVE_ATA_IDENTIFY_IS_CACHED 175 int ata_identify_is_cached(int fd); 176 #endif 177 178 ///////////////////////////////////////////////////////////////////////////// 179 180 namespace os_freebsd { // No need to publish anything, name provided for Doxygen 181 182 ///////////////////////////////////////////////////////////////////////////// 183 /// Implement shared open/close routines with old functions. 184 185 class freebsd_smart_device 186 : virtual public /*implements*/ smart_device 187 { 188 public: 189 explicit freebsd_smart_device(const char * mode) 190 : smart_device(never_called), 191 m_fd(-1), m_mode(mode) { } 192 193 virtual ~freebsd_smart_device() throw(); 194 195 virtual bool is_open() const; 196 197 virtual bool open(); 198 199 virtual bool close(); 200 201 protected: 202 /// Return filedesc for derived classes. 203 int get_fd() const 204 { return m_fd; } 205 206 private: 207 int m_fd; ///< filedesc, -1 if not open. 208 const char * m_mode; ///< Mode string for deviceopen(). 209 }; 210 211 212 freebsd_smart_device::~freebsd_smart_device() throw() 213 { 214 if (m_fd >= 0) 215 os_freebsd::freebsd_smart_device::close(); 216 } 217 218 // migration from the old_style 219 unsigned char m_controller_type; 220 unsigned char m_controller_port; 221 222 // examples for smartctl 223 static const char smartctl_examples[] = 224 "=================================================== SMARTCTL EXAMPLES =====\n\n" 68 225 " smartctl -a /dev/ad0 (Prints all SMART information)\n\n" 69 226 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/ad0\n" 70 227 " (Enables SMART on first disk)\n\n" … … 76 233 " smartctl -a --device=3ware,2 /dev/twe0\n" 77 234 " (Prints all SMART information for ATA disk on\n" 78 235 " third port of first 3ware RAID controller)\n" 79 ); 236 ; 237 238 bool freebsd_smart_device::is_open() const 239 { 240 return (m_fd >= 0); 241 } 242 243 244 static int hpt_hba(const char* name) { 245 int i=0; 246 const char *hpt_node[]={"hptmv", "hptmv6", "hptrr", "hptiop", "hptmviop", "hpt32xx", "rr2320", 247 "rr232x", "rr2310", "rr2310_00", "rr2300", "rr2340", "rr1740", NULL}; 248 while (hpt_node[i]) { 249 if (!strncmp(name, hpt_node[i], strlen(hpt_node[i]))) 250 return 1; 251 i++; 252 } 253 return 0; 254 } 255 256 static int get_tw_channel_unit (const char* name, int* unit, int* dev) { 257 const char *p; 258 259 /* device node sanity check */ 260 for (p = name + 3; *p; p++) 261 if (*p < '0' || *p > '9') 262 return -1; 263 if (strlen(name) > 4 && *(name + 3) == '0') 264 return -1; 265 266 if (dev != NULL) 267 *dev=atoi(name + 3); 268 269 /* no need for unit number */ 270 if (unit != NULL) 271 *unit=0; 272 return 0; 273 } 274 275 #ifndef IOCATAREQUEST 276 static int get_ata_channel_unit ( const char* name, int* unit, int* dev) { 277 #ifndef ATAREQUEST 278 *dev=0; 279 *unit=0; 280 return 0; 80 281 #else 81 printf( 82 " smartctl -a /dev/ad0 (Prints all SMART information)\n" 83 " smartctl -s on -o on -S on /dev/ad0 (Enables SMART on first disk)\n" 84 " smartctl -t long /dev/ad0 (Executes extended disk self-test)\n" 85 " smartctl -A -l selftest -q errorsonly /dev/ad0\n" 86 " (Prints Self-Test & Attribute errors)\n" 87 " smartctl -a -d 3ware,2 /dev/twa0\n" 88 " smartctl -a -d 3ware,2 /dev/twe0\n" 89 ); 282 // there is no direct correlation between name 'ad0, ad1, ...' and 283 // channel/unit number. So we need to iterate through the possible 284 // channels and check each unit to see if we match names 285 struct ata_cmd iocmd; 286 int fd,maxunit; 287 288 bzero(&iocmd, sizeof(struct ata_cmd)); 289 290 if ((fd = open(ATA_DEVICE, O_RDWR)) < 0) 291 return -errno; 292 293 iocmd.cmd = ATAGMAXCHANNEL; 294 if (ioctl(fd, IOCATA, &iocmd) < 0) { 295 return -errno; 296 close(fd); 297 } 298 maxunit = iocmd.u.maxchan; 299 for (*unit = 0; *unit < maxunit; (*unit)++) { 300 iocmd.channel = *unit; 301 iocmd.device = -1; 302 iocmd.cmd = ATAGPARM; 303 if (ioctl(fd, IOCATA, &iocmd) < 0) { 304 close(fd); 305 return -errno; 306 } 307 if (iocmd.u.param.type[0] && !strcmp(name,iocmd.u.param.name[0])) { 308 *dev = 0; 309 break; 310 } 311 if (iocmd.u.param.type[1] && !strcmp(name,iocmd.u.param.name[1])) { 312 *dev = 1; 313 break; 314 } 315 } 316 close(fd); 317 if (*unit == maxunit) 318 return -1; 319 else 320 return 0; 90 321 #endif 91 return;92 322 } 323 #endif 93 324 94 // Like open(). Return positive integer handle, used by functions below only. 95 int deviceopen (const char* dev, __unused char* mode) { 325 // Guess device type (ata or scsi) based on device name (FreeBSD 326 // specific) SCSI device name in FreeBSD can be sd, sr, scd, st, nst, 327 // osst, nosst and sg. 328 static const char * fbsd_dev_prefix = _PATH_DEV; 329 static const char * fbsd_dev_ata_disk_prefix = "ad"; 330 static const char * fbsd_dev_scsi_disk_plus = "da"; 331 static const char * fbsd_dev_scsi_pass = "pass"; 332 static const char * fbsd_dev_scsi_tape1 = "sa"; 333 static const char * fbsd_dev_scsi_tape2 = "nsa"; 334 static const char * fbsd_dev_scsi_tape3 = "esa"; 335 static const char * fbsd_dev_twe_ctrl = "twe"; 336 static const char * fbsd_dev_twa_ctrl = "twa"; 337 static const char * fbsd_dev_cciss = "ciss"; 338 339 int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel *chan) { 340 int len; 341 int dev_prefix_len = strlen(fbsd_dev_prefix); 342 343 // if dev_name null, or string length zero 344 if (!dev_name || !(len = strlen(dev_name))) 345 return CONTROLLER_UNKNOWN; 346 347 // Remove the leading /dev/... if it's there 348 if (!strncmp(fbsd_dev_prefix, dev_name, dev_prefix_len)) { 349 if (len <= dev_prefix_len) 350 // if nothing else in the string, unrecognized 351 return CONTROLLER_UNKNOWN; 352 // else advance pointer to following characters 353 dev_name += dev_prefix_len; 354 } 355 // form /dev/ad* or ad* 356 if (!strncmp(fbsd_dev_ata_disk_prefix, dev_name, 357 strlen(fbsd_dev_ata_disk_prefix))) { 358 #ifndef IOCATAREQUEST 359 if (chan != NULL) { 360 if (get_ata_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) { 361 return CONTROLLER_UNKNOWN; 362 } 363 } 364 #endif 365 return CONTROLLER_ATA; 366 } 367 368 // form /dev/pass* or pass* 369 if (!strncmp(fbsd_dev_scsi_pass, dev_name, 370 strlen(fbsd_dev_scsi_pass))) 371 goto handlescsi; 372 373 // form /dev/da* or da* 374 if (!strncmp(fbsd_dev_scsi_disk_plus, dev_name, 375 strlen(fbsd_dev_scsi_disk_plus))) 376 goto handlescsi; 377 378 // form /dev/sa* or sa* 379 if (!strncmp(fbsd_dev_scsi_tape1, dev_name, 380 strlen(fbsd_dev_scsi_tape1))) 381 goto handlescsi; 382 383 // form /dev/nsa* or nsa* 384 if (!strncmp(fbsd_dev_scsi_tape2, dev_name, 385 strlen(fbsd_dev_scsi_tape2))) 386 goto handlescsi; 387 388 // form /dev/esa* or esa* 389 if (!strncmp(fbsd_dev_scsi_tape3, dev_name, 390 strlen(fbsd_dev_scsi_tape3))) 391 goto handlescsi; 392 393 if (!strncmp(fbsd_dev_twa_ctrl,dev_name, 394 strlen(fbsd_dev_twa_ctrl))) { 395 if (chan != NULL) { 396 if (get_tw_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) { 397 return CONTROLLER_UNKNOWN; 398 } 399 } 400 else if (get_tw_channel_unit(dev_name,NULL,NULL)<0) { 401 return CONTROLLER_UNKNOWN; 402 } 403 return CONTROLLER_3WARE_9000_CHAR; 404 } 405 406 if (!strncmp(fbsd_dev_twe_ctrl,dev_name, 407 strlen(fbsd_dev_twe_ctrl))) { 408 if (chan != NULL) { 409 if (get_tw_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) { 410 return CONTROLLER_UNKNOWN; 411 } 412 } 413 else if (get_tw_channel_unit(dev_name,NULL,NULL)<0) { 414 return CONTROLLER_UNKNOWN; 415 } 416 return CONTROLLER_3WARE_678K_CHAR; 417 } 418 419 if (hpt_hba(dev_name)) { 420 return CONTROLLER_HPT; 421 } 422 423 // form /dev/ciss* 424 if (!strncmp(fbsd_dev_cciss, dev_name, 425 strlen(fbsd_dev_cciss))) 426 return CONTROLLER_CCISS; 427 428 // we failed to recognize any of the forms 429 return CONTROLLER_UNKNOWN; 430 431 handlescsi: 432 if (chan != NULL) { 433 if (!(chan->devname = (char *)calloc(1,DEV_IDLEN+1))) 434 return CONTROLLER_UNKNOWN; 435 436 if (cam_get_device(dev_name,chan->devname,DEV_IDLEN,&(chan->unitnum)) == -1) 437 return CONTROLLER_UNKNOWN; 438 } 439 return CONTROLLER_SCSI; 440 441 } 442 443 444 bool freebsd_smart_device::open() 445 { 446 447 const char *dev = get_dev_name(); 96 448 struct freebsd_dev_channel *fdchan; 97 449 int parse_ok, i; 98 450 … … 105 457 // of "file descriptors" already allocated. 106 458 if (i == FREEBSD_MAXDEV) { 107 459 errno = EMFILE; 108 return -1;460 return false; 109 461 } 110 462 111 463 fdchan = (struct freebsd_dev_channel *)calloc(1,sizeof(struct freebsd_dev_channel)); 112 464 if (fdchan == NULL) { 113 465 // errno already set by call to malloc() 114 return -1;466 return false; 115 467 } 116 468 117 469 parse_ok = parse_ata_chan_dev(dev,fdchan); 470 118 471 if (parse_ok == CONTROLLER_UNKNOWN) { 119 472 free(fdchan); 120 473 errno = ENOTTY; 121 return -1; // can't handle what we don't know474 return false; // can't handle what we don't know 122 475 } 123 476 124 477 if (parse_ok == CONTROLLER_ATA) { 125 478 #ifdef IOCATAREQUEST 126 if ((fdchan->device = open(dev,O_RDONLY))<0) {479 if ((fdchan->device = ::open(dev,O_RDONLY))<0) { 127 480 #else 128 if ((fdchan->atacommand = open("/dev/ata",O_RDWR))<0) {481 if ((fdchan->atacommand = ::open("/dev/ata",O_RDWR))<0) { 129 482 #endif 130 483 int myerror = errno; // preserve across free call 131 484 free(fdchan); 132 485 errno = myerror; 133 return -1;486 return false; 134 487 } 135 488 } 136 489 … … 138 491 char buf[512]; 139 492 sprintf(buf,"/dev/twe%d",fdchan->device); 140 493 #ifdef IOCATAREQUEST 141 if ((fdchan->device = open(buf,O_RDWR))<0) {494 if ((fdchan->device = ::open(buf,O_RDWR))<0) { 142 495 #else 143 if ((fdchan->atacommand = open(buf,O_RDWR))<0) {496 if ((fdchan->atacommand = ::open(buf,O_RDWR))<0) { 144 497 #endif 145 498 int myerror = errno; // preserve across free call 146 499 free(fdchan); 147 500 errno = myerror; 148 return -1;501 return false; 149 502 } 150 503 } 151 504 … … 153 506 char buf[512]; 154 507 sprintf(buf,"/dev/twa%d",fdchan->device); 155 508 #ifdef IOCATAREQUEST 156 if ((fdchan->device = open(buf,O_RDWR))<0) {509 if ((fdchan->device = ::open(buf,O_RDWR))<0) { 157 510 #else 158 if ((fdchan->atacommand = open(buf,O_RDWR))<0) {511 if ((fdchan->atacommand = ::open(buf,O_RDWR))<0) { 159 512 #endif 160 513 int myerror = errno; // preserve across free call 161 514 free(fdchan); 162 515 errno = myerror; 163 return -1;516 return false; 164 517 } 165 518 } 166 519 167 520 if (parse_ok == CONTROLLER_HPT) { 168 if ((fdchan->device = open(dev,O_RDWR))<0) {521 if ((fdchan->device = ::open(dev,O_RDWR))<0) { 169 522 int myerror = errno; // preserve across free call 170 523 free(fdchan); 171 524 errno = myerror; 172 return -1;525 return false; 173 526 } 174 527 } 175 528 176 529 if (parse_ok == CONTROLLER_CCISS) { 177 if ((fdchan->device = open(dev,O_RDWR))<0) {530 if ((fdchan->device = ::open(dev,O_RDWR))<0) { 178 531 int myerror = errno; // preserve across free call 179 532 free(fdchan); 180 533 errno = myerror; 181 return -1;534 return false; 182 535 } 183 536 } 184 537 … … 189 542 190 543 // return pointer to "file descriptor" table entry, properly offset. 191 544 devicetable[i]=fdchan; 192 return i+FREEBSD_FDOFFSET; 193 } 194 195 // Returns 1 if device not available/open/found else 0. Also shifts fd into valid range. 196 static int isnotopen(int *fd, struct freebsd_dev_channel** fdchan) { 197 // put valid "file descriptor" into range 0...FREEBSD_MAXDEV-1 198 *fd -= FREEBSD_FDOFFSET; 199 200 // check for validity of "file descriptor". 201 if (*fd<0 || *fd>=FREEBSD_MAXDEV || !((*fdchan)=devicetable[*fd])) { 202 errno = ENODEV; 203 return 1; 545 m_fd = i+FREEBSD_FDOFFSET; 546 // endofold 547 if (m_fd < 0) { 548 set_err((errno==ENOENT || errno==ENOTDIR) ? ENODEV : errno); 549 return false; 204 550 } 205 206 return 0; 551 return true; 207 552 } 208 553 209 // Like close(). Acts on handles returned by above function. 210 int deviceclose (int fd) { 554 bool freebsd_smart_device::close() 555 { 556 int fd = m_fd; m_fd = -1; 211 557 struct freebsd_dev_channel *fdchan; 212 558 int failed = 0; 213 559 214 560 // check for valid file descriptor 215 561 if (isnotopen(&fd, &fdchan)) 216 return -1;562 return false; 217 563 218 564 219 565 // did we allocate a SCSI device name? … … 222 568 223 569 // close device, if open 224 570 if (fdchan->device) 225 failed= close(fdchan->device);571 failed=::close(fdchan->device); 226 572 #ifndef IOCATAREQUEST 227 573 if (fdchan->atacommand) 228 failed= close(fdchan->atacommand);574 failed=::close(fdchan->atacommand); 229 575 #endif 230 576 231 577 // if close succeeded, then remove from device list … … 239 585 return failed; 240 586 } 241 587 242 #define NO_RETURN 0 243 #define BAD_SMART 1 244 #define NO_DISK_3WARE 2 245 #define BAD_KERNEL 3 246 #define MAX_MSG 3 588 ///////////////////////////////////////////////////////////////////////////// 589 /// Implement standard ATA support with old functions 247 590 248 // Utility function for printing warnings 249 void printwarning(int msgNo, const char* extra) { 250 static int printed[] = {0,0,0,0}; 251 static const char* message[]={ 252 "The SMART RETURN STATUS return value (smartmontools -H option/Directive)\n can not be retrieved with this version of ATAng, please do not rely on this value\nYou should update to at least 5.2\n", 591 class freebsd_ata_device 592 : public /*implements*/ ata_device_with_command_set, 593 public /*extends*/ freebsd_smart_device 594 { 595 public: 596 freebsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type); 597 598 #ifdef HAVE_ATA_IDENTIFY_IS_CACHED 599 virtual bool ata_identify_is_cached() const; 600 #endif 601 602 protected: 603 virtual int ata_command_interface(smart_command_set command, int select, char * data); 604 }; 605 606 freebsd_ata_device::freebsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type) 607 : smart_device(intf, dev_name, "ata", req_type), 608 freebsd_smart_device("ATA") 609 { 610 } 611 612 int freebsd_ata_device::ata_command_interface(smart_command_set command, int select, char * data) 613 { 614 int fd=get_fd(); 615 #if !defined(ATAREQUEST) && !defined(IOCATAREQUEST) 616 // sorry, but without ATAng, we can't do anything here 617 printwarning(BAD_KERNEL,NULL); 618 errno = ENOSYS; 619 return -1; 620 #else 621 struct freebsd_dev_channel* con; 622 int retval, copydata=0; 623 #ifdef IOCATAREQUEST 624 struct ata_ioc_request request; 625 #else 626 struct ata_cmd iocmd; 627 #endif 628 unsigned char buff[512]; 629 630 // check that "file descriptor" is valid 631 if (isnotopen(&fd,&con)) 632 return -1; 633 634 bzero(buff,512); 635 636 #ifdef IOCATAREQUEST 637 bzero(&request,sizeof(struct ata_ioc_request)); 638 #else 639 bzero(&iocmd,sizeof(struct ata_cmd)); 640 #endif 641 bzero(buff,512); 642 643 #ifndef IOCATAREQUEST 644 iocmd.cmd=ATAREQUEST; 645 iocmd.channel=con->channel; 646 iocmd.device=con->device; 647 #define request iocmd.u.request 648 #endif 649 650 request.u.ata.command=ATA_SMART_CMD; 651 request.timeout=600; 652 switch (command){ 653 case READ_VALUES: 654 request.u.ata.feature=ATA_SMART_READ_VALUES; 655 request.u.ata.lba=0xc24f<<8; 656 request.flags=ATA_CMD_READ; 657 request.data=(char *)buff; 658 request.count=512; 659 copydata=1; 660 break; 661 case READ_THRESHOLDS: 662 request.u.ata.feature=ATA_SMART_READ_THRESHOLDS; 663 request.u.ata.count=1; 664 request.u.ata.lba=1|(0xc24f<<8); 665 request.flags=ATA_CMD_READ; 666 request.data=(char *)buff; 667 request.count=512; 668 copydata=1; 669 break; 670 case READ_LOG: 671 request.u.ata.feature=ATA_SMART_READ_LOG_SECTOR; 672 request.u.ata.lba=select|(0xc24f<<8); 673 request.u.ata.count=1; 674 request.flags=ATA_CMD_READ; 675 request.data=(char *)buff; 676 request.count=512; 677 copydata=1; 678 break; 679 case IDENTIFY: 680 request.u.ata.command=ATA_IDENTIFY_DEVICE; 681 request.flags=ATA_CMD_READ; 682 request.data=(char *)buff; 683 request.count=512; 684 copydata=1; 685 break; 686 case PIDENTIFY: 687 request.u.ata.command=ATA_IDENTIFY_PACKET_DEVICE; 688 request.flags=ATA_CMD_READ; 689 request.data=(char *)buff; 690 request.count=512; 691 copydata=1; 692 break; 693 case ENABLE: 694 request.u.ata.feature=ATA_SMART_ENABLE; 695 request.u.ata.lba=0xc24f<<8; 696 request.flags=ATA_CMD_CONTROL; 697 break; 698 case DISABLE: 699 request.u.ata.feature=ATA_SMART_DISABLE; 700 request.u.ata.lba=0xc24f<<8; 701 request.flags=ATA_CMD_CONTROL; 702 break; 703 case AUTO_OFFLINE: 704 // NOTE: According to ATAPI 4 and UP, this command is obsolete 705 request.u.ata.feature=ATA_SMART_AUTO_OFFLINE; 706 request.u.ata.lba=0xc24f<<8; 707 request.u.ata.count=select; 708 request.flags=ATA_CMD_CONTROL; 709 break; 710 case AUTOSAVE: 711 request.u.ata.feature=ATA_SMART_AUTOSAVE; 712 request.u.ata.lba=0xc24f<<8; 713 request.u.ata.count=select; 714 request.flags=ATA_CMD_CONTROL; 715 break; 716 case IMMEDIATE_OFFLINE: 717 request.u.ata.feature=ATA_SMART_IMMEDIATE_OFFLINE; 718 request.u.ata.lba = select|(0xc24f<<8); // put test in sector 719 request.flags=ATA_CMD_CONTROL; 720 break; 721 case STATUS_CHECK: // same command, no HDIO in FreeBSD 722 case STATUS: 723 // this command only says if SMART is working. It could be 724 // replaced with STATUS_CHECK below. 725 request.u.ata.feature=ATA_SMART_STATUS; 726 request.u.ata.lba=0xc24f<<8; 727 request.flags=ATA_CMD_CONTROL; 728 break; 729 case CHECK_POWER_MODE: 730 request.u.ata.command=ATA_CHECK_POWER_MODE; 731 request.u.ata.feature=0; 732 request.flags=ATA_CMD_CONTROL; 733 break; 734 case WRITE_LOG: 735 memcpy(buff, data, 512); 736 request.u.ata.feature=ATA_SMART_WRITE_LOG_SECTOR; 737 request.u.ata.lba=select|(0xc24f<<8); 738 request.u.ata.count=1; 739 request.flags=ATA_CMD_WRITE; 740 request.data=(char *)buff; 741 request.count=512; 742 break; 743 default: 744 pout("Unrecognized command %d in ata_command_interface()\n" 745 "Please contact " PACKAGE_BUGREPORT "\n", command); 746 errno=ENOSYS; 747 return -1; 748 } 749 750 if (command==STATUS_CHECK){ 751 unsigned const char normal_lo=0x4f, normal_hi=0xc2; 752 unsigned const char failed_lo=0xf4, failed_hi=0x2c; 753 unsigned char low,high; 754 755 #ifdef IOCATAREQUEST 756 if ((retval=ioctl(con->device, IOCATAREQUEST, &request)) || request.error) 757 #else 758 if ((retval=ioctl(con->atacommand, IOCATA, &iocmd)) || request.error) 759 #endif 760 return -1; 761 762 #if __FreeBSD_version < 502000 763 printwarning(NO_RETURN,NULL); 764 #endif 765 766 high = (request.u.ata.lba >> 16) & 0xff; 767 low = (request.u.ata.lba >> 8) & 0xff; 768 769 // Cyl low and Cyl high unchanged means "Good SMART status" 770 if (low==normal_lo && high==normal_hi) 771 return 0; 772 773 // These values mean "Bad SMART status" 774 if (low==failed_lo && high==failed_hi) 775 return 1; 776 777 // We haven't gotten output that makes sense; print out some debugging info 778 char buf[512]; 779 sprintf(buf,"CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n", 780 (int)request.u.ata.command, 781 (int)request.u.ata.feature, 782 (int)request.u.ata.count, 783 (int)((request.u.ata.lba) & 0xff), 784 (int)((request.u.ata.lba>>8) & 0xff), 785 (int)((request.u.ata.lba>>16) & 0xff), 786 (int)request.error); 787 printwarning(BAD_SMART,buf); 788 return 0; 789 } 790 791 #ifdef IOCATAREQUEST 792 if ((retval=ioctl(con->device, IOCATAREQUEST, &request)) || request.error) 793 #else 794 if ((retval=ioctl(con->atacommand, IOCATA, &iocmd)) || request.error) 795 #endif 796 { 797 return -1; 798 } 799 // 800 if (command == CHECK_POWER_MODE) { 801 data[0] = request.u.ata.count & 0xff; 802 return 0; 803 } 804 if (copydata) 805 memcpy(data, buff, 512); 806 807 return 0; 808 #endif 809 } 810 811 #ifdef HAVE_ATA_IDENTIFY_IS_CACHED 812 bool freebsd_ata_device::ata_identify_is_cached() const 813 { 814 return !!::ata_identify_is_cached(get_fd()); 815 } 816 #endif 817 818 819 ///////////////////////////////////////////////////////////////////////////// 820 /// Implement AMCC/3ware RAID support with old functions 821 822 class freebsd_escalade_device 823 : public /*implements*/ ata_device_with_command_set, 824 public /*extends*/ freebsd_smart_device 825 { 826 public: 827 freebsd_escalade_device(smart_interface * intf, const char * dev_name, 828 int escalade_type, int disknum); 829 830 protected: 831 virtual int ata_command_interface(smart_command_set command, int select, char * data); 832 833 private: 834 int m_escalade_type; ///< Type string for escalade_command_interface(). 835 int m_disknum; ///< Disk number. 836 }; 837 838 freebsd_escalade_device::freebsd_escalade_device(smart_interface * intf, const char * dev_name, 839 int escalade_type, int disknum) 840 : smart_device(intf, dev_name, "3ware", "3ware"), 841 freebsd_smart_device( 842 escalade_type==CONTROLLER_3WARE_9000_CHAR ? "ATA_3WARE_9000" : 843 escalade_type==CONTROLLER_3WARE_678K_CHAR ? "ATA_3WARE_678K" : 844 /* CONTROLLER_3WARE_678K */ "ATA" ), 845 m_escalade_type(escalade_type), m_disknum(disknum) 846 { 847 set_info().info_name = strprintf("%s [3ware_disk_%02d]", dev_name, disknum); 848 } 849 850 int freebsd_escalade_device::ata_command_interface(smart_command_set command, int select, char * data) 851 { 852 // to hold true file descriptor 853 int fd = get_fd(); 854 struct freebsd_dev_channel* con; 855 856 // return value and buffer for ioctl() 857 int ioctlreturn, readdata=0; 858 struct twe_usercommand* cmd_twe = NULL; 859 TW_OSLI_IOCTL_NO_DATA_BUF* cmd_twa = NULL; 860 TWE_Command_ATA* ata = NULL; 861 862 // Used by both the SCSI and char interfaces 863 char ioctl_buffer[TW_IOCTL_BUFFER_SIZE]; 864 865 if (m_disknum < 0) { 866 printwarning(NO_DISK_3WARE,NULL); 867 return -1; 868 } 869 870 // check that "file descriptor" is valid 871 if (isnotopen(&fd,&con)) 872 return -1; 873 874 memset(ioctl_buffer, 0, TW_IOCTL_BUFFER_SIZE); 875 876 if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) { 877 cmd_twa = (TW_OSLI_IOCTL_NO_DATA_BUF*)ioctl_buffer; 878 cmd_twa->pdata = ((TW_OSLI_IOCTL_WITH_PAYLOAD*)cmd_twa)->payload.data_buf; 879 cmd_twa->driver_pkt.buffer_length = 512; 880 ata = (TWE_Command_ATA*)&cmd_twa->cmd_pkt.command.cmd_pkt_7k; 881 } else if (m_escalade_type==CONTROLLER_3WARE_678K_CHAR) { 882 cmd_twe = (struct twe_usercommand*)ioctl_buffer; 883 ata = &cmd_twe->tu_command.ata; 884 } else { 885 pout("Unrecognized escalade_type %d in freebsd_3ware_command_interface(disk %d)\n" 886 "Please contact " PACKAGE_BUGREPORT "\n", m_escalade_type, m_disknum); 887 errno=ENOSYS; 888 return -1; 889 } 890 891 ata->opcode = TWE_OP_ATA_PASSTHROUGH; 892 893 // Same for (almost) all commands - but some reset below 894 ata->request_id = 0xFF; 895 ata->unit = m_disknum; 896 ata->status = 0; 897 ata->flags = 0x1; 898 ata->drive_head = 0x0; 899 ata->sector_num = 0; 900 901 // All SMART commands use this CL/CH signature. These are magic 902 // values from the ATA specifications. 903 ata->cylinder_lo = 0x4F; 904 ata->cylinder_hi = 0xC2; 905 906 // SMART ATA COMMAND REGISTER value 907 ata->command = ATA_SMART_CMD; 908 909 // Is this a command that reads or returns 512 bytes? 910 // passthru->param values are: 911 // 0x0 - non data command without TFR write check, 912 // 0x8 - non data command with TFR write check, 913 // 0xD - data command that returns data to host from device 914 // 0xF - data command that writes data from host to device 915 // passthru->size values are 0x5 for non-data and 0x07 for data 916 if (command == READ_VALUES || 917 command == READ_THRESHOLDS || 918 command == READ_LOG || 919 command == IDENTIFY || 920 command == WRITE_LOG ) { 921 readdata=1; 922 if (m_escalade_type==CONTROLLER_3WARE_678K_CHAR) { 923 cmd_twe->tu_data = data; 924 cmd_twe->tu_size = 512; 925 } 926 ata->sgl_offset = 0x5; 927 ata->size = 0x5; 928 ata->param = 0xD; 929 ata->sector_count = 0x1; 930 // For 64-bit to work correctly, up the size of the command packet 931 // in dwords by 1 to account for the 64-bit single sgl 'address' 932 // field. Note that this doesn't agree with the typedefs but it's 933 // right (agree with kernel driver behavior/typedefs). 934 //if (sizeof(long)==8) 935 // ata->size++; 936 } 937 else { 938 // Non data command -- but doesn't use large sector 939 // count register values. 940 ata->sgl_offset = 0x0; 941 ata->size = 0x5; 942 ata->param = 0x8; 943 ata->sector_count = 0x0; 944 } 945 946 // Now set ATA registers depending upon command 947 switch (command){ 948 case CHECK_POWER_MODE: 949 ata->command = ATA_CHECK_POWER_MODE; 950 ata->features = 0; 951 ata->cylinder_lo = 0; 952 ata->cylinder_hi = 0; 953 break; 954 case READ_VALUES: 955 ata->features = ATA_SMART_READ_VALUES; 956 break; 957 case READ_THRESHOLDS: 958 ata->features = ATA_SMART_READ_THRESHOLDS; 959 break; 960 case READ_LOG: 961 ata->features = ATA_SMART_READ_LOG_SECTOR; 962 // log number to return 963 ata->sector_num = select; 964 break; 965 case WRITE_LOG: 966 readdata=0; 967 ata->features = ATA_SMART_WRITE_LOG_SECTOR; 968 ata->sector_count = 1; 969 ata->sector_num = select; 970 ata->param = 0xF; // PIO data write 971 break; 972 case IDENTIFY: 973 // ATA IDENTIFY DEVICE 974 ata->command = ATA_IDENTIFY_DEVICE; 975 ata->features = 0; 976 ata->cylinder_lo = 0; 977 ata->cylinder_hi = 0; 978 break; 979 case PIDENTIFY: 980 // 3WARE controller can NOT have packet device internally 981 pout("WARNING - NO DEVICE FOUND ON 3WARE CONTROLLER (disk %d)\n", m_disknum); 982 errno=ENODEV; 983 return -1; 984 case ENABLE: 985 ata->features = ATA_SMART_ENABLE; 986 break; 987 case DISABLE: 988 ata->features = ATA_SMART_DISABLE; 989 break; 990 case AUTO_OFFLINE: 991 ata->features = ATA_SMART_AUTO_OFFLINE; 992 // Enable or disable? 993 ata->sector_count = select; 994 break; 995 case AUTOSAVE: 996 ata->features = ATA_SMART_AUTOSAVE; 997 // Enable or disable? 998 ata->sector_count = select; 999 break; 1000 case IMMEDIATE_OFFLINE: 1001 ata->features = ATA_SMART_IMMEDIATE_OFFLINE; 1002 // What test type to run? 1003 ata->sector_num = select; 1004 break; 1005 case STATUS_CHECK: 1006 ata->features = ATA_SMART_STATUS; 1007 break; 1008 case STATUS: 1009 // This is JUST to see if SMART is enabled, by giving SMART status 1010 // command. But it doesn't say if status was good, or failing. 1011 // See below for the difference. 1012 ata->features = ATA_SMART_STATUS; 1013 break; 1014 default: 1015 pout("Unrecognized command %d in freebsd_3ware_command_interface(disk %d)\n" 1016 "Please contact " PACKAGE_BUGREPORT "\n", command, m_disknum); 1017 errno=ENOSYS; 1018 return -1; 1019 } 1020 1021 // Now send the command down through an ioctl() 1022 if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) { 1023 #ifdef IOCATAREQUEST 1024 ioctlreturn=ioctl(con->device,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa); 1025 #else 1026 ioctlreturn=ioctl(con->atacommand,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa); 1027 #endif 1028 } else { 1029 #ifdef IOCATAREQUEST 1030 ioctlreturn=ioctl(con->device,TWEIO_COMMAND,cmd_twe); 1031 #else 1032 ioctlreturn=ioctl(con->atacommand,TWEIO_COMMAND,cmd_twe); 1033 #endif 1034 } 1035 1036 // Deal with the different error cases 1037 if (ioctlreturn) { 1038 if (!errno) 1039 errno=EIO; 1040 return -1; 1041 } 1042 1043 // See if the ATA command failed. Now that we have returned from 1044 // the ioctl() call, if passthru is valid, then: 1045 // - ata->status contains the 3ware controller STATUS 1046 // - ata->command contains the ATA STATUS register 1047 // - ata->features contains the ATA ERROR register 1048 // 1049 // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS 1050 // If bit 0 (error bit) is set, then ATA ERROR register is valid. 1051 // While we *might* decode the ATA ERROR register, at the moment it 1052 // doesn't make much sense: we don't care in detail why the error 1053 // happened. 1054 1055 if (ata->status || (ata->command & 0x21)) { 1056 pout("Command failed, ata.status=(0x%2.2x), ata.command=(0x%2.2x), ata.flags=(0x%2.2x)\n",ata->status,ata->command,ata->flags); 1057 errno=EIO; 1058 return -1; 1059 } 1060 1061 // If this is a read data command, copy data to output buffer 1062 if (readdata) { 1063 if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) 1064 memcpy(data, cmd_twa->pdata, 512); 1065 } 1066 1067 // For STATUS_CHECK, we need to check register values 1068 if (command==STATUS_CHECK) { 253 1069 254 "Error SMART Status command failed\nPlease get assistance from \n" PACKAGE_HOMEPAGE "\nRegister values returned from SMART Status command are:\n", 1070 // To find out if the SMART RETURN STATUS is good or failing, we 1071 // need to examine the values of the Cylinder Low and Cylinder 1072 // High Registers. 255 1073 256 "You must specify a DISK # for 3ware drives with -d 3ware,<n> where <n> begins with 1 for first disk drive\n", 1074 unsigned short cyl_lo=ata->cylinder_lo; 1075 unsigned short cyl_hi=ata->cylinder_hi; 257 1076 258 "ATA support is not provided for this kernel version. Please ugrade to a recent 5-CURRENT kernel (post 09/01/2003 or so)\n"259 };260 261 if (msgNo >= 0 && msgNo <= MAX_MSG) {262 if (!printed[msgNo]) {263 printed[msgNo] = 1;264 pout("%s", message[msgNo]);265 if (extra)266 pout("%s",extra);267 }1077 // If values in Cyl-LO and Cyl-HI are unchanged, SMART status is good. 1078 if (cyl_lo==0x4F && cyl_hi==0xC2) 1079 return 0; 1080 1081 // If values in Cyl-LO and Cyl-HI are as follows, SMART status is FAIL 1082 if (cyl_lo==0xF4 && cyl_hi==0x2C) 1083 return 1; 1084 1085 errno=EIO; 1086 return -1; 268 1087 } 269 return; 1088 1089 // copy sector count register (one byte!) to return data 1090 if (command==CHECK_POWER_MODE) 1091 *data=*(char *)&(ata->sector_count); 1092 1093 // look for nonexistent devices/ports 1094 if (command==IDENTIFY && !nonempty((unsigned char *)data, 512)) { 1095 errno=ENODEV; 1096 return -1; 1097 } 1098 1099 return 0; 270 1100 } 271 1101 272 // Interface to ATA devices. See os_linux.c273 1102 274 int marvell_command_interface(__unused int fd, __unused smart_command_set command, __unused int select, __unused char *data) { 275 return -1; 1103 ///////////////////////////////////////////////////////////////////////////// 1104 /// Implement Highpoint RAID support with old functions 1105 1106 class freebsd_highpoint_device 1107 : public /*implements*/ ata_device_with_command_set, 1108 public /*extends*/ freebsd_smart_device 1109 { 1110 public: 1111 freebsd_highpoint_device(smart_interface * intf, const char * dev_name, 1112 unsigned char controller, unsigned char channel, unsigned char port); 1113 1114 protected: 1115 virtual int ata_command_interface(smart_command_set command, int select, char * data); 1116 1117 private: 1118 unsigned char m_hpt_data[3]; ///< controller/channel/port 1119 }; 1120 1121 1122 freebsd_highpoint_device::freebsd_highpoint_device(smart_interface * intf, const char * dev_name, 1123 unsigned char controller, unsigned char channel, unsigned char port) 1124 : smart_device(intf, dev_name, "hpt", "hpt"), 1125 freebsd_smart_device("ATA") 1126 { 1127 m_hpt_data[0] = controller; m_hpt_data[1] = channel; m_hpt_data[2] = port; 1128 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]); 276 1129 } 277 1130 278 int highpoint_command_interface(int fd, smart_command_set command, int select, char *data) { 1131 int freebsd_highpoint_device::ata_command_interface(smart_command_set command, int select, char * data) 1132 { 1133 int fd=get_fd(); 279 1134 int ids[2]; 280 1135 struct freebsd_dev_channel* fbcon; 281 1136 HPT_IOCTL_PARAM param; … … 288 1143 return -1; 289 1144 290 1145 // get internal deviceid 291 ids[0] = con->hpt_data[0] - 1;292 ids[1] = con->hpt_data[1] - 1;1146 ids[0] = m_hpt_data[0] - 1; 1147 ids[1] = m_hpt_data[1] - 1; 293 1148 294 1149 memset(¶m, 0, sizeof(HPT_IOCTL_PARAM)); 295 1150 … … 300 1155 param.out = (unsigned char *)&info; 301 1156 param.out_size = sizeof(HPT_CHANNEL_INFO_V2); 302 1157 303 if ( con->hpt_data[2]==1) {1158 if (m_hpt_data[2]==1) { 304 1159 param.ctrl_code = HPT_IOCTL_GET_CHANNEL_INFO; 305 1160 param.out_size = sizeof(HPT_CHANNEL_INFO); 306 1161 } 307 1162 if (ioctl(fbcon->device, HPT_DO_IOCONTROL, ¶m)!=0 || 308 info.devices[ con->hpt_data[2]-1]==0) {1163 info.devices[m_hpt_data[2]-1]==0) { 309 1164 return -1; 310 1165 } 311 1166 … … 316 1171 pide_pt_hdr->lbamid = 0x4f; 317 1172 pide_pt_hdr->lbahigh = 0xc2; 318 1173 pide_pt_hdr->command = ATA_SMART_CMD; 319 pide_pt_hdr->id = info.devices[ con->hpt_data[2] - 1];1174 pide_pt_hdr->id = info.devices[m_hpt_data[2] - 1]; 320 1175 321 1176 switch (command){ 322 1177 case READ_VALUES: … … 429 1284 return 0; 430 1285 } 431 1286 432 int areca_command_interface(__unused int fd, __unused int disknum, __unused smart_command_set command, __unused int select, __unused char *data) {433 return -1;434 }435 1287 436 int ata_command_interface(int fd, smart_command_set command, int select, char *data) { 437 #if !defined(ATAREQUEST) && !defined(IOCATAREQUEST) 438 // sorry, but without ATAng, we can't do anything here 439 printwarning(BAD_KERNEL,NULL); 440 errno = ENOSYS; 441 return -1; 442 #else 443 struct freebsd_dev_channel* con; 444 int retval, copydata=0; 445 #ifdef IOCATAREQUEST 446 struct ata_ioc_request request; 447 #else 448 struct ata_cmd iocmd; 449 #endif 450 unsigned char buff[512]; 1288 ///////////////////////////////////////////////////////////////////////////// 1289 /// Implement standard SCSI support with old functions 451 1290 452 // check that "file descriptor" is valid 453 if (isnotopen(&fd,&con)) 454 return -1; 1291 class freebsd_scsi_device 1292 : public /*implements*/ scsi_device, 1293 public /*extends*/ freebsd_smart_device 1294 { 1295 public: 1296 freebsd_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type); 455 1297 456 bzero(buff,512);1298 virtual smart_device * autodetect_open(); 457 1299 458 #ifdef IOCATAREQUEST 459 bzero(&request,sizeof(struct ata_ioc_request)); 460 #else 461 bzero(&iocmd,sizeof(struct ata_cmd)); 462 #endif 463 bzero(buff,512); 1300 virtual bool scsi_pass_through(scsi_cmnd_io * iop); 1301 }; 464 1302 465 #ifndef IOCATAREQUEST 466 iocmd.cmd=ATAREQUEST; 467 iocmd.channel=con->channel; 468 iocmd.device=con->device; 469 #define request iocmd.u.request 470 #endif 471 472 request.u.ata.command=ATA_SMART_CMD; 473 request.timeout=600; 474 switch (command){ 475 case READ_VALUES: 476 request.u.ata.feature=ATA_SMART_READ_VALUES; 477 request.u.ata.lba=0xc24f<<8; 478 request.flags=ATA_CMD_READ; 479 request.data=(char *)buff; 480 request.count=512; 481 copydata=1; 482 break; 483 case READ_THRESHOLDS: 484 request.u.ata.feature=ATA_SMART_READ_THRESHOLDS; 485 request.u.ata.count=1; 486 request.u.ata.lba=1|(0xc24f<<8); 487 request.flags=ATA_CMD_READ; 488 request.data=(char *)buff; 489 request.count=512; 490 copydata=1; 491 break; 492 case READ_LOG: 493 request.u.ata.feature=ATA_SMART_READ_LOG_SECTOR; 494 request.u.ata.lba=select|(0xc24f<<8); 495 request.u.ata.count=1; 496 request.flags=ATA_CMD_READ; 497 request.data=(char *)buff; 498 request.count=512; 499 copydata=1; 500 break; 501 case IDENTIFY: 502 request.u.ata.command=ATA_IDENTIFY_DEVICE; 503 request.flags=ATA_CMD_READ; 504 request.data=(char *)buff; 505 request.count=512; 506 copydata=1; 507 break; 508 case PIDENTIFY: 509 request.u.ata.command=ATA_IDENTIFY_PACKET_DEVICE; 510 request.flags=ATA_CMD_READ; 511 request.data=(char *)buff; 512 request.count=512; 513 copydata=1; 514 break; 515 case ENABLE: 516 request.u.ata.feature=ATA_SMART_ENABLE; 517 request.u.ata.lba=0xc24f<<8; 518 request.flags=ATA_CMD_CONTROL; 519 break; 520 case DISABLE: 521 request.u.ata.feature=ATA_SMART_DISABLE; 522 request.u.ata.lba=0xc24f<<8; 523 request.flags=ATA_CMD_CONTROL; 524 break; 525 case AUTO_OFFLINE: 526 // NOTE: According to ATAPI 4 and UP, this command is obsolete 527 request.u.ata.feature=ATA_SMART_AUTO_OFFLINE; 528 request.u.ata.lba=0xc24f<<8; 529 request.u.ata.count=select; 530 request.flags=ATA_CMD_CONTROL; 531 break; 532 case AUTOSAVE: 533 request.u.ata.feature=ATA_SMART_AUTOSAVE; 534 request.u.ata.lba=0xc24f<<8; 535 request.u.ata.count=select; 536 request.flags=ATA_CMD_CONTROL; 537 break; 538 case IMMEDIATE_OFFLINE: 539 request.u.ata.feature=ATA_SMART_IMMEDIATE_OFFLINE; 540 request.u.ata.lba = select|(0xc24f<<8); // put test in sector 541 request.flags=ATA_CMD_CONTROL; 542 break; 543 case STATUS_CHECK: // same command, no HDIO in FreeBSD 544 case STATUS: 545 // this command only says if SMART is working. It could be 546 // replaced with STATUS_CHECK below. 547 request.u.ata.feature=ATA_SMART_STATUS; 548 request.u.ata.lba=0xc24f<<8; 549 request.flags=ATA_CMD_CONTROL; 550 break; 551 case CHECK_POWER_MODE: 552 request.u.ata.command=ATA_CHECK_POWER_MODE; 553 request.u.ata.feature=0; 554 request.flags=ATA_CMD_CONTROL; 555 break; 556 case WRITE_LOG: 557 memcpy(buff, data, 512); 558 request.u.ata.feature=ATA_SMART_WRITE_LOG_SECTOR; 559 request.u.ata.lba=select|(0xc24f<<8); 560 request.u.ata.count=1; 561 request.flags=ATA_CMD_WRITE; 562 request.data=(char *)buff; 563 request.count=512; 564 break; 565 default: 566 pout("Unrecognized command %d in ata_command_interface()\n" 567 "Please contact " PACKAGE_BUGREPORT "\n", command); 568 errno=ENOSYS; 569 return -1; 570 } 571 572 if (command==STATUS_CHECK){ 573 unsigned const char normal_lo=0x4f, normal_hi=0xc2; 574 unsigned const char failed_lo=0xf4, failed_hi=0x2c; 575 unsigned char low,high; 576 577 #ifdef IOCATAREQUEST 578 if ((retval=ioctl(con->device, IOCATAREQUEST, &request)) || request.error) 579 #else 580 if ((retval=ioctl(con->atacommand, IOCATA, &iocmd)) || request.error) 581 #endif 582 return -1; 583 584 #if __FreeBSD_version < 502000 585 printwarning(NO_RETURN,NULL); 586 #endif 587 588 high = (request.u.ata.lba >> 16) & 0xff; 589 low = (request.u.ata.lba >> 8) & 0xff; 590 591 // Cyl low and Cyl high unchanged means "Good SMART status" 592 if (low==normal_lo && high==normal_hi) 593 return 0; 594 595 // These values mean "Bad SMART status" 596 if (low==failed_lo && high==failed_hi) 597 return 1; 598 599 // We haven't gotten output that makes sense; print out some debugging info 600 char buf[512]; 601 sprintf(buf,"CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n", 602 (int)request.u.ata.command, 603 (int)request.u.ata.feature, 604 (int)request.u.ata.count, 605 (int)((request.u.ata.lba) & 0xff), 606 (int)((request.u.ata.lba>>8) & 0xff), 607 (int)((request.u.ata.lba>>16) & 0xff), 608 (int)request.error); 609 printwarning(BAD_SMART,buf); 610 return 0; 611 } 612 613 #ifdef IOCATAREQUEST 614 if ((retval=ioctl(con->device, IOCATAREQUEST, &request)) || request.error) 615 #else 616 if ((retval=ioctl(con->atacommand, IOCATA, &iocmd)) || request.error) 617 #endif 618 { 619 return -1; 620 } 621 // 622 if (command == CHECK_POWER_MODE) { 623 data[0] = request.u.ata.count & 0xff; 624 return 0; 625 } 626 if (copydata) 627 memcpy(data, buff, 512); 628 629 return 0; 630 #endif 1303 freebsd_scsi_device::freebsd_scsi_device(smart_interface * intf, 1304 const char * dev_name, const char * req_type) 1305 : smart_device(intf, dev_name, "scsi", req_type), 1306 freebsd_smart_device("SCSI") 1307 { 631 1308 } 632 1309 633 634 1310 // Interface to SCSI devices. See os_linux.c 635 1311 int do_normal_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) 636 1312 { … … 733 1409 return 0; 734 1410 } 735 1411 1412 736 1413 /* Check and call the right interface. Maybe when the do_generic_scsi_cmd_io interface is better 737 1414 we can take off this crude way of calling the right interface */ 738 1415 int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report) 739 1416 { 740 1417 struct freebsd_dev_channel *fdchan; 741 switch( con->controller_type)1418 switch(m_controller_type) 742 1419 { 743 1420 case CONTROLLER_CCISS: 744 1421 #ifdef HAVE_DEV_CISS_CISSIO_H 745 1422 // check that "file descriptor" is valid 746 1423 if (isnotopen(&dev_fd,&fdchan)) 747 1424 return -ENOTTY; 748 return cciss_io_interface(fdchan->device, con->controller_port-1, iop, report);1425 return cciss_io_interface(fdchan->device, m_controller_port-1, iop, report); 749 1426 #else 750 1427 { 751 1428 static int warned = 0; … … 766 1443 } 767 1444 } 768 1445 769 // Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c 1446 bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io * iop) 1447 { 1448 unsigned char oldtype = m_controller_type, oldport = m_controller_port; 1449 m_controller_type = CONTROLLER_SCSI; m_controller_port = 0; 1450 int status = do_scsi_cmnd_io(get_fd(), iop, con->reportscsiioctl); 1451 m_controller_type = oldtype; m_controller_port = oldport; 1452 if (status < 0) { 1453 set_err(-status); 1454 return false; 1455 } 1456 return true; 1457 } 770 1458 771 #define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520772 #define BUFFER_LEN_9000_CHAR ( sizeof(TW_OSLI_IOCTL_NO_DATA_BUF) + sizeof(TWE_Command) ) // 2048773 #define TW_IOCTL_BUFFER_SIZE ( MAX(BUFFER_LEN_678K_CHAR, BUFFER_LEN_9000_CHAR) )774 1459 775 int escalade_command_interface(int fd, int disknum, int escalade_type, smart_command_set command, int select, char *data) { 776 // to hold true file descriptor 777 struct freebsd_dev_channel* con; 1460 ///////////////////////////////////////////////////////////////////////////// 1461 /// Implement CCISS RAID support with old functions 778 1462 779 // return value and buffer for ioctl() 780 int ioctlreturn, readdata=0; 781 struct twe_usercommand* cmd_twe = NULL; 782 TW_OSLI_IOCTL_NO_DATA_BUF* cmd_twa = NULL; 783 TWE_Command_ATA* ata = NULL; 1463 class freebsd_cciss_device 1464 : public /*implements*/ scsi_device, 1465 public /*extends*/ freebsd_smart_device 1466 { 1467 public: 1468 freebsd_cciss_device(smart_interface * intf, const char * name, unsigned char disknum); 784 1469 785 // Used by both the SCSI and char interfaces 786 char ioctl_buffer[TW_IOCTL_BUFFER_SIZE]; 1470 virtual bool scsi_pass_through(scsi_cmnd_io * iop); 787 1471 788 if (disknum < 0) { 789 printwarning(NO_DISK_3WARE,NULL); 790 return -1; 791 } 1472 private: 1473 unsigned char m_disknum; ///< Disk number. 1474 }; 792 1475 793 // check that "file descriptor" is valid794 if (isnotopen(&fd,&con))795 return -1;796 1476 797 memset(ioctl_buffer, 0, TW_IOCTL_BUFFER_SIZE); 1477 freebsd_cciss_device::freebsd_cciss_device(smart_interface * intf, 1478 const char * dev_name, unsigned char disknum) 1479 : smart_device(intf, dev_name, "cciss", "cciss"), 1480 freebsd_smart_device("SCSI"), 1481 m_disknum(disknum) 1482 { 1483 set_info().info_name = strprintf("%s [cciss_disk_%02d]", dev_name, disknum); 1484 } 798 1485 799 if (escalade_type==CONTROLLER_3WARE_9000_CHAR) { 800 cmd_twa = (TW_OSLI_IOCTL_NO_DATA_BUF*)ioctl_buffer; 801 cmd_twa->pdata = ((TW_OSLI_IOCTL_WITH_PAYLOAD*)cmd_twa)->payload.data_buf; 802 cmd_twa->driver_pkt.buffer_length = 512; 803 ata = (TWE_Command_ATA*)&cmd_twa->cmd_pkt.command.cmd_pkt_7k; 804 } else if (escalade_type==CONTROLLER_3WARE_678K_CHAR) { 805 cmd_twe = (struct twe_usercommand*)ioctl_buffer; 806 ata = &cmd_twe->tu_command.ata; 807 } else { 808 pout("Unrecognized escalade_type %d in freebsd_3ware_command_interface(disk %d)\n" 809 "Please contact " PACKAGE_BUGREPORT "\n", escalade_type, disknum); 810 errno=ENOSYS; 811 return -1; 1486 bool freebsd_cciss_device::scsi_pass_through(scsi_cmnd_io * iop) 1487 { 1488 // See os_linux.cpp 1489 unsigned char oldtype = m_controller_type, oldport = m_controller_port; 1490 m_controller_type = CONTROLLER_CCISS; m_controller_port = m_disknum+1; 1491 int status = do_scsi_cmnd_io(get_fd(), iop, con->reportscsiioctl); 1492 m_controller_type = oldtype; m_controller_port = oldport; 1493 if (status < 0) { 1494 set_err(-status); 1495 return false; 812 1496 } 1497 return true; 1498 } 813 1499 814 ata->opcode = TWE_OP_ATA_PASSTHROUGH;815 1500 816 // Same for (almost) all commands - but some reset below 817 ata->request_id = 0xFF; 818 ata->unit = disknum; 819 ata->status = 0; 820 ata->flags = 0x1; 821 ata->drive_head = 0x0; 822 ata->sector_num = 0; 1501 ///////////////////////////////////////////////////////////////////////////// 1502 /// SCSI open with autodetection support 823 1503 824 // All SMART commands use this CL/CH signature. These are magic 825 // values from the ATA specifications. 826 ata->cylinder_lo = 0x4F;827 ata->cylinder_hi = 0xC2;828 829 // SMART ATA COMMAND REGISTER value 830 ata->command = ATA_SMART_CMD;831 832 // Is this a command that reads or returns 512 bytes?833 // passthru->param values are: 834 // 0x0 - non data command without TFR write check,835 // 0x8 - non data command with TFR write check, 836 // 0xD - data command that returns data to host from device837 // 0xF - data command that writes data from host to device838 // passthru->size values are 0x5 for non-data and 0x07 for data839 if ( command == READ_VALUES ||840 command == READ_THRESHOLDS ||841 command == READ_LOG ||842 command == IDENTIFY ||843 command == WRITE_LOG) {844 readdata=1;845 if (escalade_type==CONTROLLER_3WARE_678K_CHAR) {846 cmd_twe->tu_data = data;847 cmd_twe->tu_size = 512;1504 smart_device * freebsd_scsi_device::autodetect_open() 1505 { 1506 // Open device 1507 if (!open()) 1508 return this; 1509 1510 // No Autodetection if device type was specified by user 1511 if (*get_req_type()) 1512 return this; 1513 1514 // The code below is based on smartd.cpp:SCSIFilterKnown() 1515 1516 // Get INQUIRY 1517 unsigned char req_buff[64] = {0, }; 1518 int req_len = 36; 1519 if (scsiStdInquiry(this, req_buff, req_len)) { 1520 // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices 1521 // watch this spot ... other devices could lock up here 1522 req_len = 64; 1523 if (scsiStdInquiry(this, req_buff, req_len)) { 1524 // device doesn't like INQUIRY commands 1525 close(); 1526 set_err(EIO, "INQUIRY failed"); 1527 return this; 848 1528 } 849 ata->sgl_offset = 0x5;850 ata->size = 0x5;851 ata->param = 0xD;852 ata->sector_count = 0x1;853 // For 64-bit to work correctly, up the size of the command packet854 // in dwords by 1 to account for the 64-bit single sgl 'address'855 // field. Note that this doesn't agree with the typedefs but it's856 // right (agree with kernel driver behavior/typedefs).857 //if (sizeof(long)==8)858 // ata->size++;859 1529 } 860 else {861 // Non data command -- but doesn't use large sector862 // count register values.863 ata->sgl_offset = 0x0;864 ata->size = 0x5;865 ata->param = 0x8;866 ata->sector_count = 0x0;867 }868 869 // Now set ATA registers depending upon command870 switch (command){871 case CHECK_POWER_MODE:872 ata->command = ATA_CHECK_POWER_MODE;873 ata->features = 0;874 ata->cylinder_lo = 0;875 ata->cylinder_hi = 0;876 break;877 case READ_VALUES:878 ata->features = ATA_SMART_READ_VALUES;879 break;880 case READ_THRESHOLDS:881 ata->features = ATA_SMART_READ_THRESHOLDS;882 break;883 case READ_LOG:884 ata->features = ATA_SMART_READ_LOG_SECTOR;885 // log number to return886 ata->sector_num = select;887 break;888 case WRITE_LOG:889 readdata=0;890 ata->features = ATA_SMART_WRITE_LOG_SECTOR;891 ata->sector_count = 1;892 ata->sector_num = select;893 ata->param = 0xF; // PIO data write894 break;895 case IDENTIFY:896 // ATA IDENTIFY DEVICE897 ata->command = ATA_IDENTIFY_DEVICE;898 ata->features = 0;899 ata->cylinder_lo = 0;900 ata->cylinder_hi = 0;901 break;902 case PIDENTIFY:903 // 3WARE controller can NOT have packet device internally904 pout("WARNING - NO DEVICE FOUND ON 3WARE CONTROLLER (disk %d)\n", disknum);905 errno=ENODEV;906 return -1;907 case ENABLE:908 ata->features = ATA_SMART_ENABLE;909 break;910 case DISABLE:911 ata->features = ATA_SMART_DISABLE;912 break;913 case AUTO_OFFLINE:914 ata->features = ATA_SMART_AUTO_OFFLINE;915 // Enable or disable?916 ata->sector_count = select;917 break;918 case AUTOSAVE:919 ata->features = ATA_SMART_AUTOSAVE;920 // Enable or disable?921 ata->sector_count = select;922 break;923 case IMMEDIATE_OFFLINE:924 ata->features = ATA_SMART_IMMEDIATE_OFFLINE;925 // What test type to run?926 ata->sector_num = select;927 break;928 case STATUS_CHECK:929 ata->features = ATA_SMART_STATUS;930 break;931 case STATUS:932 // This is JUST to see if SMART is enabled, by giving SMART status933 // command. But it doesn't say if status was good, or failing.934 // See below for the difference.935 ata->features = ATA_SMART_STATUS;936 break;937 default:938 pout("Unrecognized command %d in freebsd_3ware_command_interface(disk %d)\n"939 "Please contact " PACKAGE_BUGREPORT "\n", command, disknum);940 errno=ENOSYS;941 return -1;942 }943 1530 944 // Now send the command down through an ioctl() 945 if (escalade_type==CONTROLLER_3WARE_9000_CHAR) { 946 #ifdef IOCATAREQUEST 947 ioctlreturn=ioctl(con->device,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa); 1531 int avail_len = req_buff[4] + 5; 1532 int len = (avail_len < req_len ? avail_len : req_len); 1533 if (len < 36) 1534 return this; 1535 1536 // Use INQUIRY to detect type 1537 smart_device * newdev = 0; 1538 try { 1539 // 3ware ? 1540 if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4)) { 1541 close(); 1542 #if defined(_WIN32) || defined(__CYGWIN__) 1543 set_err(EINVAL, "AMCC/3ware controller, please try changing device to %s,N", get_dev_name()); 948 1544 #else 949 ioctlreturn=ioctl(con->atacommand,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa); 1545 set_err(EINVAL, "AMCC/3ware controller, please try adding '-d 3ware,N',\n" 1546 "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name()); 950 1547 #endif 951 } else { 952 #ifdef IOCATAREQUEST 953 ioctlreturn=ioctl(con->device,TWEIO_COMMAND,cmd_twe); 954 #else 955 ioctlreturn=ioctl(con->atacommand,TWEIO_COMMAND,cmd_twe); 956 #endif 957 } 1548 return this; 1549 } 958 1550 959 // Deal with the different error cases960 if (ioctlreturn) {961 if ( !errno)962 errno=EIO;963 return -1;1551 // SAT or USB ? 1552 newdev = smi()->autodetect_sat_device(this, req_buff, len); 1553 if (newdev) 1554 // NOTE: 'this' is now owned by '*newdev' 1555 return newdev; 964 1556 } 965 966 // See if the ATA command failed. Now that we have returned from 967 // the ioctl() call, if passthru is valid, then: 968 // - ata->status contains the 3ware controller STATUS 969 // - ata->command contains the ATA STATUS register 970 // - ata->features contains the ATA ERROR register 971 // 972 // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS 973 // If bit 0 (error bit) is set, then ATA ERROR register is valid. 974 // While we *might* decode the ATA ERROR register, at the moment it 975 // doesn't make much sense: we don't care in detail why the error 976 // happened. 977 978 if (ata->status || (ata->command & 0x21)) { 979 pout("Command failed, ata.status=(0x%2.2x), ata.command=(0x%2.2x), ata.flags=(0x%2.2x)\n",ata->status,ata->command,ata->flags); 980 errno=EIO; 981 return -1; 1557 catch (...) { 1558 // Cleanup if exception occurs after newdev was allocated 1559 delete newdev; 1560 throw; 982 1561 } 983 984 // If this is a read data command, copy data to output buffer985 if (readdata) {986 if (escalade_type==CONTROLLER_3WARE_9000_CHAR)987 memcpy(data, cmd_twa->pdata, 512);988 }989 1562 990 // For STATUS_CHECK, we need to check register values 991 if (command==STATUS_CHECK) { 992 993 // To find out if the SMART RETURN STATUS is good or failing, we 994 // need to examine the values of the Cylinder Low and Cylinder 995 // High Registers. 996 997 unsigned short cyl_lo=ata->cylinder_lo; 998 unsigned short cyl_hi=ata->cylinder_hi; 999 1000 // If values in Cyl-LO and Cyl-HI are unchanged, SMART status is good. 1001 if (cyl_lo==0x4F && cyl_hi==0xC2) 1002 return 0; 1003 1004 // If values in Cyl-LO and Cyl-HI are as follows, SMART status is FAIL 1005 if (cyl_lo==0xF4 && cyl_hi==0x2C) 1006 return 1; 1007 1008 errno=EIO; 1009 return -1; 1010 } 1011 1012 // copy sector count register (one byte!) to return data 1013 if (command==CHECK_POWER_MODE) 1014 *data=*(char *)&(ata->sector_count); 1015 1016 // look for nonexistent devices/ports 1017 if (command==IDENTIFY && !nonempty((unsigned char *)data, 512)) { 1018 errno=ENODEV; 1019 return -1; 1020 } 1021 1022 return 0; 1563 // Nothing special found 1564 return this; 1023 1565 } 1024 1566 1025 static int get_tw_channel_unit (const char* name, int* unit, int* dev) {1026 const char *p;1027 1567 1028 /* device node sanity check */ 1029 for (p = name + 3; *p; p++) 1030 if (*p < '0' || *p > '9') 1031 return -1; 1032 if (strlen(name) > 4 && *(name + 3) == '0') 1033 return -1; 1568 ///////////////////////////////////////////////////////////////////////////// 1569 /// Implement platform interface with old functions. 1034 1570 1035 if (dev != NULL) 1036 *dev=atoi(name + 3); 1571 class freebsd_smart_interface 1572 : public /*implements*/ smart_interface 1573 { 1574 public: 1575 virtual const char * get_os_version_str(); 1037 1576 1038 /* no need for unit number */ 1039 if (unit != NULL) 1040 *unit=0; 1041 return 0; 1042 } 1577 virtual const char * get_app_examples(const char * appname); 1043 1578 1044 static int hpt_hba(const char* name) { 1045 int i=0; 1046 const char *hpt_node[]={"hptmv", "hptmv6", "hptrr", "hptiop", "hptmviop", "hpt32xx", "rr2320", 1047 "rr232x", "rr2310", "rr2310_00", "rr2300", "rr2340", "rr1740", NULL}; 1048 while (hpt_node[i]) { 1049 if (!strncmp(name, hpt_node[i], strlen(hpt_node[i]))) 1050 return 1; 1051 i++; 1052 } 1053 return 0; 1054 } 1579 virtual bool scan_smart_devices(smart_device_list & devlist, const char * type, 1580 const char * pattern = 0); 1055 1581 1056 #ifndef ATA_DEVICE 1057 #define ATA_DEVICE "/dev/ata" 1058 #endif 1582 protected: 1583 virtual ata_device * get_ata_device(const char * name, const char * type); 1059 1584 1060 #ifndef IOCATAREQUEST 1061 static int get_ata_channel_unit ( const char* name, int* unit, int* dev) { 1062 #ifndef ATAREQUEST 1063 *dev=0; 1064 *unit=0; 1065 return 0; 1066 #else 1067 // there is no direct correlation between name 'ad0, ad1, ...' and 1068 // channel/unit number. So we need to iterate through the possible 1069 // channels and check each unit to see if we match names 1070 struct ata_cmd iocmd; 1071 int fd,maxunit; 1072 1073 bzero(&iocmd, sizeof(struct ata_cmd)); 1585 virtual scsi_device * get_scsi_device(const char * name, const char * type); 1074 1586 1075 if ((fd = open(ATA_DEVICE, O_RDWR)) < 0) 1076 return -errno; 1077 1078 iocmd.cmd = ATAGMAXCHANNEL; 1079 if (ioctl(fd, IOCATA, &iocmd) < 0) { 1080 return -errno; 1081 close(fd); 1082 } 1083 maxunit = iocmd.u.maxchan; 1084 for (*unit = 0; *unit < maxunit; (*unit)++) { 1085 iocmd.channel = *unit; 1086 iocmd.device = -1; 1087 iocmd.cmd = ATAGPARM; 1088 if (ioctl(fd, IOCATA, &iocmd) < 0) { 1089 close(fd); 1090 return -errno; 1091 } 1092 if (iocmd.u.param.type[0] && !strcmp(name,iocmd.u.param.name[0])) { 1093 *dev = 0; 1094 break; 1095 } 1096 if (iocmd.u.param.type[1] && !strcmp(name,iocmd.u.param.name[1])) { 1097 *dev = 1; 1098 break; 1099 } 1100 } 1101 close(fd); 1102 if (*unit == maxunit) 1103 return -1; 1104 else 1105 return 0; 1106 #endif 1107 } 1108 #endif 1587 virtual smart_device * autodetect_smart_device(const char * name); 1109 1588 1110 // Guess device type (ata or scsi) based on device name (FreeBSD 1111 // specific) SCSI device name in FreeBSD can be sd, sr, scd, st, nst, 1112 // osst, nosst and sg. 1113 static const char * fbsd_dev_prefix = _PATH_DEV; 1114 static const char * fbsd_dev_ata_disk_prefix = "ad"; 1115 static const char * fbsd_dev_scsi_disk_plus = "da"; 1116 static const char * fbsd_dev_scsi_pass = "pass"; 1117 static const char * fbsd_dev_scsi_tape1 = "sa"; 1118 static const char * fbsd_dev_scsi_tape2 = "nsa"; 1119 static const char * fbsd_dev_scsi_tape3 = "esa"; 1120 static const char * fbsd_dev_twe_ctrl = "twe"; 1121 static const char * fbsd_dev_twa_ctrl = "twa"; 1122 static const char * fbsd_dev_cciss = "ciss"; 1589 virtual smart_device * get_custom_smart_device(const char * name, const char * type); 1123 1590 1124 static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel *chan) { 1125 int len; 1126 int dev_prefix_len = strlen(fbsd_dev_prefix); 1127 1128 // if dev_name null, or string length zero 1129 if (!dev_name || !(len = strlen(dev_name))) 1130 return CONTROLLER_UNKNOWN; 1131 1132 // Remove the leading /dev/... if it's there 1133 if (!strncmp(fbsd_dev_prefix, dev_name, dev_prefix_len)) { 1134 if (len <= dev_prefix_len) 1135 // if nothing else in the string, unrecognized 1136 return CONTROLLER_UNKNOWN; 1137 // else advance pointer to following characters 1138 dev_name += dev_prefix_len; 1139 } 1140 // form /dev/ad* or ad* 1141 if (!strncmp(fbsd_dev_ata_disk_prefix, dev_name, 1142 strlen(fbsd_dev_ata_disk_prefix))) { 1143 #ifndef IOCATAREQUEST 1144 if (chan != NULL) { 1145 if (get_ata_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) { 1146 return CONTROLLER_UNKNOWN; 1147 } 1148 } 1149 #endif 1150 return CONTROLLER_ATA; 1151 } 1591 virtual const char * get_valid_custom_dev_types_str(); 1592 }; 1152 1593 1153 // form /dev/pass* or pass*1154 if (!strncmp(fbsd_dev_scsi_pass, dev_name,1155 strlen(fbsd_dev_scsi_pass)))1156 goto handlescsi;1157 1594 1158 // form /dev/da* or da* 1159 if (!strncmp(fbsd_dev_scsi_disk_plus, dev_name, 1160 strlen(fbsd_dev_scsi_disk_plus))) 1161 goto handlescsi; 1595 ////////////////////////////////////////////////////////////////////// 1596 char sysname[256]; 1597 const char * freebsd_smart_interface::get_os_version_str() 1598 { 1599 struct utsname osname; 1600 uname(&osname); 1601 snprintf(sysname, sizeof(sysname),"%s %s %s",osname.sysname, osname.release, 1602 osname.machine); 1603 return sysname; 1604 } 1162 1605 1163 // form /dev/sa* or sa* 1164 if (!strncmp(fbsd_dev_scsi_tape1, dev_name, 1165 strlen(fbsd_dev_scsi_tape1))) 1166 goto handlescsi; 1606 const char * freebsd_smart_interface::get_app_examples(const char * appname) 1607 { 1608 if (!strcmp(appname, "smartctl")) 1609 return smartctl_examples; 1610 return 0; 1611 } 1167 1612 1168 // form /dev/nsa* or nsa* 1169 if (!strncmp(fbsd_dev_scsi_tape2, dev_name, 1170 strlen(fbsd_dev_scsi_tape2)))1171 goto handlescsi; 1613 ata_device * freebsd_smart_interface::get_ata_device(const char * name, const char * type) 1614 { 1615 return new freebsd_ata_device(this, name, type); 1616 } 1172 1617 1173 // form /dev/esa* or esa* 1174 if (!strncmp(fbsd_dev_scsi_tape3, dev_name, 1175 strlen(fbsd_dev_scsi_tape3))) 1176 goto handlescsi; 1177 1178 if (!strncmp(fbsd_dev_twa_ctrl,dev_name, 1179 strlen(fbsd_dev_twa_ctrl))) { 1180 if (chan != NULL) { 1181 if (get_tw_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) { 1182 return CONTROLLER_UNKNOWN; 1183 } 1184 } 1185 else if (get_tw_channel_unit(dev_name,NULL,NULL)<0) { 1186 return CONTROLLER_UNKNOWN; 1187 } 1188 return CONTROLLER_3WARE_9000_CHAR; 1189 } 1618 scsi_device * freebsd_smart_interface::get_scsi_device(const char * name, const char * type) 1619 { 1620 return new freebsd_scsi_device(this, name, type); 1621 } 1190 1622 1191 if (!strncmp(fbsd_dev_twe_ctrl,dev_name, 1192 strlen(fbsd_dev_twe_ctrl))) { 1193 if (chan != NULL) { 1194 if (get_tw_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) { 1195 return CONTROLLER_UNKNOWN; 1196 } 1197 } 1198 else if (get_tw_channel_unit(dev_name,NULL,NULL)<0) { 1199 return CONTROLLER_UNKNOWN; 1200 } 1201 return CONTROLLER_3WARE_678K_CHAR; 1202 } 1623 static int 1624 cam_getumassno(char * devname) { 1625 union ccb ccb; 1626 int bufsize, fd; 1627 unsigned int i; 1628 int error = -1; 1629 char devstring[256]; 1630 1631 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) { 1632 warn("couldn't open %s", XPT_DEVICE); 1633 return(1); 1634 } 1635 bzero(&ccb, sizeof(union ccb)); 1203 1636 1204 if (hpt_hba(dev_name)) { 1205 return CONTROLLER_HPT;1206 } 1637 ccb.ccb_h.path_id = CAM_XPT_PATH_ID; 1638 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; 1639 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; 1207 1640 1208 // form /dev/ciss* 1209 if (!strncmp(fbsd_dev_cciss, dev_name, 1210 strlen(fbsd_dev_cciss))) 1211 return CONTROLLER_CCISS; 1641 ccb.ccb_h.func_code = XPT_DEV_MATCH; 1642 bufsize = sizeof(struct dev_match_result) * 100; 1643 ccb.cdm.match_buf_len = bufsize; 1644 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize); 1645 if (ccb.cdm.matches == NULL) { 1646 warnx("can't malloc memory for matches"); 1647 close(fd); 1648 return(1); 1649 } 1650 ccb.cdm.num_matches = 0; 1651 /* 1652 * We fetch all nodes, since we display most of them in the default 1653 * case, and all in the verbose case. 1654 */ 1655 ccb.cdm.num_patterns = 0; 1656 ccb.cdm.pattern_buf_len = 0; 1657 /* 1658 * We do the ioctl multiple times if necessary, in case there are 1659 * more than 100 nodes in the EDT. 1660 */ 1661 1662 do { 1663 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) { 1664 warn("error sending CAMIOCOMMAND ioctl"); 1665 error = -1; 1666 break; 1667 } 1668 if ((ccb.ccb_h.status != CAM_REQ_CMP) 1669 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST) 1670 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) { 1671 warnx("got CAM error %#x, CDM error %d\n", 1672 ccb.ccb_h.status, ccb.cdm.status); 1673 error = -1; 1674 break; 1675 } 1212 1676 1213 // we failed to recognize any of the forms 1214 return CONTROLLER_UNKNOWN; 1677 struct bus_match_result *bus_result = 0; 1678 for (i = 0; i < ccb.cdm.num_matches; i++) { 1679 switch (ccb.cdm.matches[i].type) { 1680 case DEV_MATCH_BUS: { 1681 // struct bus_match_result *bus_result; 1682 bus_result = 1683 &ccb.cdm.matches[i].result.bus_result; 1684 break; 1685 } 1686 case DEV_MATCH_DEVICE: { 1687 /* we are not interested in device name */ 1688 break; 1689 } 1690 case DEV_MATCH_PERIPH: { 1691 struct periph_match_result *periph_result; 1215 1692 1216 handlescsi: 1217 if (chan != NULL) { 1218 if (!(chan->devname = (char *)calloc(1,DEV_IDLEN+1))) 1219 return CONTROLLER_UNKNOWN; 1220 1221 if (cam_get_device(dev_name,chan->devname,DEV_IDLEN,&(chan->unitnum)) == -1) 1222 return CONTROLLER_UNKNOWN; 1223 } 1224 return CONTROLLER_SCSI; 1225 1226 } 1693 periph_result = 1694 &ccb.cdm.matches[i].result.periph_result; 1227 1695 1228 int guess_device_type (const char* dev_name) { 1229 return parse_ata_chan_dev(dev_name,NULL); 1696 snprintf(devstring,sizeof(devstring),"%s%d",periph_result->periph_name,periph_result->unit_number); 1697 if(strcmp(devstring,devname)==0){ /* found our device */ 1698 if(strcmp(bus_result->dev_name,"umass-sim")) { 1699 close(fd); 1700 return -1; /* non usb device found, giving up */ 1701 } 1702 /* return bus number */ 1703 return bus_result->unit_number; 1704 } 1705 break; 1706 } 1707 1708 default: 1709 fprintf(stdout, "WARN: unknown match type\n"); 1710 break; 1711 } 1712 } 1713 1714 } while ((ccb.ccb_h.status == CAM_REQ_CMP) 1715 && (ccb.cdm.status == CAM_DEV_MATCH_MORE)); 1716 close(fd); 1717 free(ccb.cdm.matches); 1718 return(error); /* no device found */ 1230 1719 } 1231 1720 1232 // global variable holding byte count of allocated memory1233 extern long long bytes;1234 1721 1235 1722 // we are using CAM subsystem XPT enumerator to found all SCSI devices on system 1236 1723 // despite of it's names … … 1477 1964 return n; 1478 1965 } 1479 1966 1480 int make_device_names (char*** devlist, const char* name) { 1481 if (!strcmp(name,"SCSI")) 1482 return get_dev_names_scsi(devlist); 1483 else if (!strcmp(name,"ATA")) 1484 return get_dev_names_ata(devlist); 1485 else 1967 1968 1969 bool freebsd_smart_interface::scan_smart_devices(smart_device_list & devlist, 1970 const char * type, const char * pattern /*= 0*/) 1971 { 1972 if (pattern) { 1973 set_err(EINVAL, "DEVICESCAN with pattern not implemented yet"); 1974 return false; 1975 } 1976 1977 // Make namelists 1978 char * * atanames = 0; int numata = 0; 1979 if (!type || !strcmp(type, "ata")) { 1980 numata = get_dev_names_ata(&atanames); 1981 if (numata < 0) { 1982 set_err(ENOMEM); 1983 return false; 1984 } 1985 } 1986 1987 char * * scsinames = 0; int numscsi = 0; 1988 if (!type || !strcmp(type, "scsi")) { 1989 numscsi = get_dev_names_scsi(&scsinames); 1990 if (numscsi < 0) { 1991 set_err(ENOMEM); 1992 return false; 1993 } 1994 } 1995 1996 // Add to devlist 1997 int i; 1998 if (type==NULL) 1999 type=""; 2000 for (i = 0; i < numata; i++) { 2001 ata_device * atadev = get_ata_device(atanames[i], type); 2002 if (atadev) 2003 devlist.add(atadev); 2004 } 2005 2006 for (i = 0; i < numscsi; i++) { 2007 scsi_device * scsidev = get_scsi_device(scsinames[i], type); 2008 if (scsidev) 2009 devlist.add(scsidev); 2010 } 2011 return true; 2012 } 2013 2014 2015 static char done[USB_MAX_DEVICES]; 2016 // static unsigned short vendor_id = 0, product_id = 0, version = 0; 2017 2018 static int usbdevinfo(int f, int a, int rec, int busno, unsigned short & vendor_id, 2019 unsigned short & product_id, unsigned short & version) 2020 { 2021 struct usb_device_info di; 2022 int e, p, i; 2023 char devname[256]; 2024 2025 snprintf(devname, sizeof(devname),"umass%d",busno); 2026 2027 di.udi_addr = a; 2028 e = ioctl(f, USB_DEVICEINFO, &di); 2029 if (e) { 2030 if (errno != ENXIO) 2031 printf("addr %d: I/O error\n", a); 2032 return 0; 2033 } 2034 done[a] = 1; 2035 2036 // list devices 2037 for (i = 0; i < USB_MAX_DEVNAMES; i++) { 2038 if (di.udi_devnames[i][0]) { 2039 if(strcmp(di.udi_devnames[i],devname)==0) { 2040 // device found! 2041 vendor_id = di.udi_vendorNo; 2042 product_id = di.udi_productNo; 2043 version = di.udi_releaseNo; 2044 return 1; 2045 // FIXME 2046 } 2047 } 2048 } 2049 if (!rec) 2050 return 0; 2051 for (p = 0; p < di.udi_nports; p++) { 2052 int s = di.udi_ports[p]; 2053 if (s >= USB_MAX_DEVICES) { 2054 continue; 2055 } 2056 if (s == 0) 2057 printf("addr 0 should never happen!\n"); 2058 else { 2059 if(usbdevinfo(f, s, 1, busno, vendor_id, product_id, version)) return 1; 2060 } 2061 } 2062 return 0; 2063 } 2064 2065 2066 2067 2068 static int usbdevlist(int busno,unsigned short & vendor_id, 2069 unsigned short & product_id, unsigned short & version) 2070 { 2071 int i, f, a, rc; 2072 char buf[50]; 2073 int ncont; 2074 2075 for (ncont = 0, i = 0; i < 10; i++) { 2076 snprintf(buf, sizeof(buf), "%s%d", USBDEV, i); 2077 f = open(buf, O_RDONLY); 2078 if (f >= 0) { 2079 memset(done, 0, sizeof done); 2080 for (a = 1; a < USB_MAX_DEVICES; a++) { 2081 if (!done[a]) { 2082 rc = usbdevinfo(f, a, 1, busno,vendor_id, product_id, version); 2083 if(rc) return 1; 2084 } 2085 2086 } 2087 close(f); 2088 } else { 2089 if (errno == ENOENT || errno == ENXIO) 2090 continue; 2091 warn("%s", buf); 2092 } 2093 ncont++; 2094 } 1486 2095 return 0; 1487 2096 } 2097 2098 // Get USB bridge ID for "/dev/daX" 2099 static bool get_usb_id(const char * path, unsigned short & vendor_id, 2100 unsigned short & product_id, unsigned short & version) 2101 { 2102 // Only "/dev/daX" supported 2103 if (!(!strncmp(path, "/dev/da", 7) && !strchr(path + 7, '/'))) 2104 return false; 2105 int bus = cam_getumassno((char *)path+5); 2106 2107 if (bus == -1) 2108 return false; 2109 2110 usbdevlist(bus,vendor_id, 2111 product_id, version); 2112 2113 return true; 2114 } 2115 2116 2117 smart_device * freebsd_smart_interface::autodetect_smart_device(const char * name) 2118 { 2119 int guess = parse_ata_chan_dev(name,NULL); 2120 unsigned short vendor_id = 0, product_id = 0, version = 0; 2121 2122 switch (guess) { 2123 case CONTROLLER_ATA : 2124 return new freebsd_ata_device(this, name, ""); 2125 case CONTROLLER_SCSI: 2126 // Try to detect possible USB->(S)ATA bridge 2127 if (get_usb_id(name, vendor_id, product_id, version)) { 2128 const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id, version); 2129 if (!usbtype) 2130 return 0; 2131 // Return SAT/USB device for this type 2132 // (Note: freebsd_scsi_device::autodetect_open() will not be called in this case) 2133 return get_sat_device(usbtype, new freebsd_scsi_device(this, name, "")); 2134 } 2135 // non usb device, handle as normal scsi 2136 return new freebsd_scsi_device(this, name, ""); 2137 case CONTROLLER_CCISS: 2138 // device - cciss, but no ID known 2139 set_err(EINVAL, "Option -d cciss,N requires N to be a non-negative integer"); 2140 return 0; 2141 } 2142 2143 2144 // TODO: Test autodetect device here 2145 return 0; 2146 } 2147 2148 2149 smart_device * freebsd_smart_interface::get_custom_smart_device(const char * name, const char * type) 2150 { 2151 // 3Ware ? 2152 int disknum = -1, n1 = -1, n2 = -1; 2153 if (sscanf(type, "3ware,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) { 2154 if (n2 != (int)strlen(type)) { 2155 set_err(EINVAL, "Option -d 3ware,N requires N to be a non-negative integer"); 2156 return 0; 2157 } 2158 if (!(0 <= disknum && disknum <= 15)) { 2159 set_err(EINVAL, "Option -d 3ware,N (N=%d) must have 0 <= N <= 15", disknum); 2160 return 0; 2161 } 2162 int contr = parse_ata_chan_dev(name,NULL); 2163 if (contr != CONTROLLER_3WARE_9000_CHAR && contr != CONTROLLER_3WARE_678K_CHAR) 2164 contr = CONTROLLER_3WARE_678K; 2165 return new freebsd_escalade_device(this, name, contr, disknum); 2166 } 2167 2168 // Highpoint ? 2169 int controller = -1, channel = -1; disknum = 1; 2170 n1 = n2 = -1; int n3 = -1; 2171 if (sscanf(type, "hpt,%n%d/%d%n/%d%n", &n1, &controller, &channel, &n2, &disknum, &n3) >= 2 || n1 == 4) { 2172 int len = strlen(type); 2173 if (!(n2 == len || n3 == len)) { 2174 set_err(EINVAL, "Option '-d hpt,L/M/N' supports 2-3 items"); 2175 return 0; 2176 } 2177 if (!(1 <= controller && controller <= 8)) { 2178 set_err(EINVAL, "Option '-d hpt,L/M/N' invalid controller id L supplied"); 2179 return 0; 2180 } 2181 if (!(1 <= channel && channel <= 8)) { 2182 set_err(EINVAL, "Option '-d hpt,L/M/N' invalid channel number M supplied"); 2183 return 0; 2184 } 2185 if (!(1 <= disknum && disknum <= 15)) { 2186 set_err(EINVAL, "Option '-d hpt,L/M/N' invalid pmport number N supplied"); 2187 return 0; 2188 } 2189 return new freebsd_highpoint_device(this, name, controller, channel, disknum); 2190 } 2191 2192 // CCISS ? 2193 disknum = n1 = n2 = -1; 2194 if (sscanf(type, "cciss,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) { 2195 if (n2 != (int)strlen(type)) { 2196 set_err(EINVAL, "Option -d cciss,N requires N to be a non-negative integer"); 2197 return 0; 2198 } 2199 if (!(0 <= disknum && disknum <= 15)) { 2200 set_err(EINVAL, "Option -d cciss,N (N=%d) must have 0 <= N <= 15", disknum); 2201 return 0; 2202 } 2203 return new freebsd_cciss_device(this, name, disknum); 2204 } 2205 2206 return 0; 2207 } 2208 2209 const char * freebsd_smart_interface::get_valid_custom_dev_types_str() 2210 { 2211 return "marvell, 3ware,N, hpt,L/M/N, cciss,N"; 2212 } 2213 2214 2215 } // namespace 2216 2217 2218 ///////////////////////////////////////////////////////////////////////////// 2219 /// Initialize platform interface and register with smi() 2220 2221 void smart_interface::init() 2222 { 2223 static os_freebsd::freebsd_smart_interface the_interface; 2224 smart_interface::set(&the_interface); 2225 }