Changeset 3650
- Timestamp:
- 10/18/12 14:26:56 (7 months ago)
- Location:
- trunk/smartmontools
- Files:
-
- 2 modified
-
ChangeLog (modified) (1 diff)
-
os_freebsd.cpp (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/smartmontools/ChangeLog
r3649 r3650 4 4 Compile fixes for Areca patch on FreeBSD. 5 5 Added support for the /dev/twsX (3ware 9750) controller on FreeBSD. 6 FreeBSD: Migrate 3ware interface to ata_pass_through() 6 7 7 8 2012-10-16 Christian Franke <franke@computer.org> -
trunk/smartmontools/os_freebsd.cpp
r3649 r3650 455 455 456 456 class freebsd_escalade_device 457 : public /*implements*/ ata_device _with_command_set,457 : public /*implements*/ ata_device, 458 458 public /*extends*/ freebsd_smart_device 459 459 { … … 463 463 464 464 protected: 465 virtual int ata_command_interface(smart_command_set command, int select, char * data);465 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); 466 466 virtual bool open(); 467 467 … … 496 496 } 497 497 498 int freebsd_escalade_device::ata_command_interface(smart_command_set command, int select, char * data)498 bool freebsd_escalade_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) 499 499 { 500 500 // to hold true file descriptor 501 501 int fd = get_fd(); 502 502 503 // return value and buffer for ioctl() 504 int ioctlreturn, readdata=0; 503 if (!ata_cmd_is_ok(in, 504 true, // data_out_support 505 false, // TODO: multi_sector_support 506 true) // ata_48bit_support 507 ) 508 return false; 509 505 510 struct twe_usercommand* cmd_twe = NULL; 506 511 TW_OSLI_IOCTL_NO_DATA_BUF* cmd_twa = NULL; … … 526 531 ata = &cmd_twe->tu_command.ata; 527 532 } else { 528 pout("Unrecognized escalade_type %d in freebsd_3ware_command_interface(disk %d)\n" 529 "Please contact " PACKAGE_BUGREPORT "\n", m_escalade_type, m_disknum); 530 errno=ENOSYS; 531 return -1; 533 return set_err(ENOSYS, 534 "Unrecognized escalade_type %d in linux_3ware_command_interface(disk %d)\n" 535 "Please contact " PACKAGE_BUGREPORT "\n", (int)m_escalade_type, m_disknum); 532 536 } 533 537 … … 537 541 ata->request_id = 0xFF; 538 542 ata->unit = m_disknum; 539 ata->status = 0; 543 ata->status = 0; 540 544 ata->flags = 0x1; 541 ata->drive_head = 0x0; 542 ata->sector_num = 0; 543 544 // All SMART commands use this CL/CH signature. These are magic 545 // values from the ATA specifications. 546 ata->cylinder_lo = 0x4F; 547 ata->cylinder_hi = 0xC2; 548 549 // SMART ATA COMMAND REGISTER value 550 ata->command = ATA_SMART_CMD; 545 // Set registers 546 { 547 const ata_in_regs_48bit & r = in.in_regs; 548 ata->features = r.features_16; 549 ata->sector_count = r.sector_count_16; 550 ata->sector_num = r.lba_low_16; 551 ata->cylinder_lo = r.lba_mid_16; 552 ata->cylinder_hi = r.lba_high_16; 553 ata->drive_head = r.device; 554 ata->command = r.command; 555 } 551 556 552 557 // Is this a command that reads or returns 512 bytes? … … 557 562 // 0xF - data command that writes data from host to device 558 563 // passthru->size values are 0x5 for non-data and 0x07 for data 559 if (command == READ_VALUES || 560 command == READ_THRESHOLDS || 561 command == READ_LOG || 562 command == IDENTIFY || 563 command == WRITE_LOG ) 564 { 565 readdata=1; 566 if (m_escalade_type==CONTROLLER_3WARE_678K_CHAR) { 567 cmd_twe->tu_data = data; 568 cmd_twe->tu_size = 512; 569 } 570 ata->sgl_offset = 0x5; 571 ata->size = 0x5; 564 bool readdata = false; 565 if (in.direction == ata_cmd_in::data_in) { 566 readdata=true; 567 ata->sgl_offset = 0x5; 568 ata->size = 0x5; // TODO: other values for multisector? 572 569 ata->param = 0xD; 573 ata->sector_count = 0x1;574 570 // For 64-bit to work correctly, up the size of the command packet 575 571 // in dwords by 1 to account for the 64-bit single sgl 'address' 576 572 // field. Note that this doesn't agree with the typedefs but it's 577 573 // right (agree with kernel driver behavior/typedefs). 578 // if (sizeof(long)==8)574 // if (sizeof(long)==8) 579 575 // ata->size++; 580 576 } 581 else {577 else if (in.direction == ata_cmd_in::no_data) { 582 578 // Non data command -- but doesn't use large sector 583 579 // count register values. 584 ata->sgl_offset = 0x0;580 ata->sgl_offset = 0x0; 585 581 ata->size = 0x5; 586 582 ata->param = 0x8; … … 588 584 } 589 585 590 // Now set ATA registers depending upon command 591 switch (command){ 592 case CHECK_POWER_MODE: 593 ata->command = ATA_CHECK_POWER_MODE; 594 ata->features = 0; 595 ata->cylinder_lo = 0; 596 ata->cylinder_hi = 0; 597 break; 598 case READ_VALUES: 599 ata->features = ATA_SMART_READ_VALUES; 600 break; 601 case READ_THRESHOLDS: 602 ata->features = ATA_SMART_READ_THRESHOLDS; 603 break; 604 case READ_LOG: 605 ata->features = ATA_SMART_READ_LOG_SECTOR; 606 // log number to return 607 ata->sector_num = select; 608 break; 609 case WRITE_LOG: 610 readdata=0; 611 ata->features = ATA_SMART_WRITE_LOG_SECTOR; 612 ata->sector_count = 1; 613 ata->sector_num = select; 614 ata->param = 0xF; // PIO data write 615 break; 616 case IDENTIFY: 617 // ATA IDENTIFY DEVICE 618 ata->command = ATA_IDENTIFY_DEVICE; 619 ata->features = 0; 620 ata->cylinder_lo = 0; 621 ata->cylinder_hi = 0; 622 break; 623 case PIDENTIFY: 624 // 3WARE controller can NOT have packet device internally 625 pout("WARNING - NO DEVICE FOUND ON 3WARE CONTROLLER (disk %d)\n", m_disknum); 626 errno=ENODEV; 627 return -1; 628 case ENABLE: 629 ata->features = ATA_SMART_ENABLE; 630 break; 631 case DISABLE: 632 ata->features = ATA_SMART_DISABLE; 633 break; 634 case AUTO_OFFLINE: 635 ata->features = ATA_SMART_AUTO_OFFLINE; 636 // Enable or disable? 637 ata->sector_count = select; 638 break; 639 case AUTOSAVE: 640 ata->features = ATA_SMART_AUTOSAVE; 641 // Enable or disable? 642 ata->sector_count = select; 643 break; 644 case IMMEDIATE_OFFLINE: 645 ata->features = ATA_SMART_IMMEDIATE_OFFLINE; 646 // What test type to run? 647 ata->sector_num = select; 648 break; 649 case STATUS_CHECK: 650 ata->features = ATA_SMART_STATUS; 651 break; 652 case STATUS: 653 // This is JUST to see if SMART is enabled, by giving SMART status 654 // command. But it doesn't say if status was good, or failing. 655 // See below for the difference. 656 ata->features = ATA_SMART_STATUS; 657 break; 658 default: 659 pout("Unrecognized command %d in freebsd_3ware_command_interface(disk %d)\n" 660 "Please contact " PACKAGE_BUGREPORT "\n", command, m_disknum); 661 errno=ENOSYS; 662 return -1; 586 else if (in.direction == ata_cmd_in::data_out) { 587 // Non data command -- but doesn't use large sector 588 // count register values. 589 ata->sgl_offset = 0x5; 590 ata->size = 0x5; // TODO: not valid for multisector 591 ata->param = 0xF; // PIO data write 592 if (m_escalade_type==CONTROLLER_3WARE_678K_CHAR) { 593 cmd_twe->tu_data = in.buffer; 594 cmd_twe->tu_size = in.size; 595 } 596 else if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) { 597 cmd_twa->pdata = in.buffer; 598 cmd_twa->driver_pkt.buffer_length = in.size; 599 } 663 600 } 664 601 665 602 // Now send the command down through an ioctl() 603 int ioctlreturn; 666 604 if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) { 667 605 ioctlreturn=ioctl(fd,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa); … … 672 610 // Deal with the different error cases 673 611 if (ioctlreturn) { 674 if (!errno) 675 errno=EIO; 676 return -1; 612 return set_err(EIO); 677 613 } 678 614 … … 691 627 if (ata->status || (ata->command & 0x21)) { 692 628 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); 693 errno=EIO; 694 return -1; 629 return set_err(EIO); 695 630 } 696 631 … … 698 633 if (readdata) { 699 634 if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) 700 memcpy(data, cmd_twa->pdata, 512); 701 } 702 703 // For STATUS_CHECK, we need to check register values 704 if (command==STATUS_CHECK) { 705 706 // To find out if the SMART RETURN STATUS is good or failing, we 707 // need to examine the values of the Cylinder Low and Cylinder 708 // High Registers. 709 710 unsigned short cyl_lo=ata->cylinder_lo; 711 unsigned short cyl_hi=ata->cylinder_hi; 712 713 // If values in Cyl-LO and Cyl-HI are unchanged, SMART status is good. 714 if (cyl_lo==0x4F && cyl_hi==0xC2) 715 return 0; 716 717 // If values in Cyl-LO and Cyl-HI are as follows, SMART status is FAIL 718 if (cyl_lo==0xF4 && cyl_hi==0x2C) 719 return 1; 720 721 errno=EIO; 722 return -1; 723 } 724 725 // copy sector count register (one byte!) to return data 726 if (command==CHECK_POWER_MODE) 727 *data=*(char *)&(ata->sector_count); 728 635 memcpy(in.buffer, cmd_twa->pdata, in.size); 636 else if(m_escalade_type==CONTROLLER_3WARE_678K_CHAR) { 637 memcpy(in.buffer, cmd_twe->tu_data, in.size); // untested 638 } 639 } 640 // Return register values 641 if (ata) { 642 ata_out_regs_48bit & r = out.out_regs; 643 r.error = ata->features; 644 r.sector_count_16 = ata->sector_count; 645 r.lba_low_16 = ata->sector_num; 646 r.lba_mid_16 = ata->cylinder_lo; 647 r.lba_high_16 = ata->cylinder_hi; 648 r.device = ata->drive_head; 649 r.status = ata->command; 650 } 729 651 // look for nonexistent devices/ports 730 if (command==IDENTIFY && !nonempty(data, 512)) { 731 errno=ENODEV; 732 return -1; 733 } 734 735 return 0; 652 if (in.in_regs.command == ATA_IDENTIFY_DEVICE 653 && !nonempty((unsigned char *)in.buffer, in.size)) { 654 return set_err(ENODEV, "No drive on port %d", m_disknum); 655 } 656 return true; 736 657 } 737 658