⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_linux.cpp

📁 硬盘各项性能的测试,如温度容量版本健康度型号
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    tw_ioctl->opcode                              = TW_ATA_PASSTHRU;    tw_ioctl->input_length                        = 512; // correct even for non-data commands    tw_ioctl->output_length                       = 512; // correct even for non-data commands    tw_output                                     = (TW_Output *)tw_ioctl;    passthru                                      = (TW_Passthru *)&(tw_ioctl->input_data);  }  else {    pout("Unrecognized escalade_type %d in linux_3ware_command_interface(disk %d)\n"         "Please contact " PACKAGE_BUGREPORT "\n", escalade_type, disknum);    errno=ENOSYS;    return -1;  }  // Same for (almost) all commands - but some reset below  passthru->byte0.opcode  = TW_OP_ATA_PASSTHRU;  passthru->request_id    = 0xFF;  passthru->unit          = disknum;  passthru->status        = 0;  passthru->flags         = 0x1;  passthru->drive_head    = 0x0;  passthru->sector_num    = 0;  // All SMART commands use this CL/CH signature.  These are magic  // values from the ATA specifications.  passthru->cylinder_lo   = 0x4F;  passthru->cylinder_hi   = 0xC2;  // SMART ATA COMMAND REGISTER value  passthru->command       = ATA_SMART_CMD;  // Is this a command that reads or returns 512 bytes?  // passthru->param values are:  // 0x0 - non data command without TFR write check,  // 0x8 - non data command with TFR write check,  // 0xD - data command that returns data to host from device  // 0xF - data command that writes data from host to device  // passthru->size values are 0x5 for non-data and 0x07 for data  if (command == READ_VALUES     ||      command == READ_THRESHOLDS ||      command == READ_LOG        ||      command == IDENTIFY        ||      command == WRITE_LOG ) {    readdata=1;    passthru->byte0.sgloff = 0x5;    passthru->size         = 0x7;    passthru->param        = 0xD;    passthru->sector_count = 0x1;    // For 64-bit to work correctly, up the size of the command packet    // in dwords by 1 to account for the 64-bit single sgl 'address'    // field. Note that this doesn't agree with the typedefs but it's    // right (agree with kernel driver behavior/typedefs).    if (escalade_type==CONTROLLER_3WARE_9000_CHAR && sizeof(long)==8)      passthru->size++;  }  else {    // Non data command -- but doesn't use large sector    // count register values.    passthru->byte0.sgloff = 0x0;    passthru->size         = 0x5;    passthru->param        = 0x8;    passthru->sector_count = 0x0;  }  // Now set ATA registers depending upon command  switch (command){  case CHECK_POWER_MODE:    passthru->command     = ATA_CHECK_POWER_MODE;    passthru->features    = 0;    passthru->cylinder_lo = 0;    passthru->cylinder_hi = 0;    break;  case READ_VALUES:    passthru->features = ATA_SMART_READ_VALUES;    break;  case READ_THRESHOLDS:    passthru->features = ATA_SMART_READ_THRESHOLDS;    break;  case READ_LOG:    passthru->features = ATA_SMART_READ_LOG_SECTOR;    // log number to return    passthru->sector_num  = select;    break;  case WRITE_LOG:    if (escalade_type == CONTROLLER_3WARE_9000_CHAR)      memcpy((unsigned char *)tw_ioctl_apache->data_buffer, data, 512);    else if (escalade_type == CONTROLLER_3WARE_678K_CHAR)      memcpy((unsigned char *)tw_ioctl_char->data_buffer,   data, 512);    else {      // COMMAND NOT SUPPORTED VIA SCSI IOCTL INTERFACE      // memcpy(tw_output->output_data, data, 512);      printwarning(command);      errno=ENOTSUP;      return -1;    }    readdata=0;    passthru->features     = ATA_SMART_WRITE_LOG_SECTOR;    passthru->sector_count = 1;    passthru->sector_num   = select;    passthru->param        = 0xF;  // PIO data write    break;  case IDENTIFY:    // ATA IDENTIFY DEVICE    passthru->command     = ATA_IDENTIFY_DEVICE;    passthru->features    = 0;    passthru->cylinder_lo = 0;    passthru->cylinder_hi = 0;    break;  case PIDENTIFY:    // 3WARE controller can NOT have packet device internally    pout("WARNING - NO DEVICE FOUND ON 3WARE CONTROLLER (disk %d)\n", disknum);    pout("Note: /dev/sdX many need to be replaced with /dev/tweN or /dev/twaN\n");    errno=ENODEV;    return -1;  case ENABLE:    passthru->features = ATA_SMART_ENABLE;    break;  case DISABLE:    passthru->features = ATA_SMART_DISABLE;    break;  case AUTO_OFFLINE:    passthru->features     = ATA_SMART_AUTO_OFFLINE;    // Enable or disable?    passthru->sector_count = select;    break;  case AUTOSAVE:    passthru->features     = ATA_SMART_AUTOSAVE;    // Enable or disable?    passthru->sector_count = select;    break;  case IMMEDIATE_OFFLINE:    passthru->features    = ATA_SMART_IMMEDIATE_OFFLINE;    // What test type to run?    passthru->sector_num  = select;    break;  case STATUS_CHECK:    passthru->features = ATA_SMART_STATUS;    break;  case STATUS:    // This is JUST to see if SMART is enabled, by giving SMART status    // command. But it doesn't say if status was good, or failing.    // See below for the difference.    passthru->features = ATA_SMART_STATUS;    break;  default:    pout("Unrecognized command %d in linux_3ware_command_interface(disk %d)\n"         "Please contact " PACKAGE_BUGREPORT "\n", command, disknum);    errno=ENOSYS;    return -1;  }  // Now send the command down through an ioctl()  if (escalade_type==CONTROLLER_3WARE_9000_CHAR)    ioctlreturn=ioctl(fd, TW_IOCTL_FIRMWARE_PASS_THROUGH, tw_ioctl_apache);  else if (escalade_type==CONTROLLER_3WARE_678K_CHAR)    ioctlreturn=ioctl(fd, TW_CMD_PACKET_WITH_DATA, tw_ioctl_char);  else    ioctlreturn=ioctl(fd, SCSI_IOCTL_SEND_COMMAND, tw_ioctl);  // Deal with the different error cases  if (ioctlreturn) {    if (CONTROLLER_3WARE_678K==escalade_type && ((command==AUTO_OFFLINE || command==AUTOSAVE) && select)){      // error here is probably a kernel driver whose version is too old      printwarning(command);      errno=ENOTSUP;    }    if (!errno)      errno=EIO;    return -1;  }  // The passthru structure is valid after return from an ioctl if:  // - we are using the character interface OR  // - we are using the SCSI interface and this is a NON-READ-DATA command  // For SCSI interface, note that we set passthru to a different  // value after ioctl().  if (CONTROLLER_3WARE_678K==escalade_type) {    if (readdata)      passthru=NULL;    else      passthru=(TW_Passthru *)&(tw_output->output_data);  }  // See if the ATA command failed.  Now that we have returned from  // the ioctl() call, if passthru is valid, then:  // - passthru->status contains the 3ware controller STATUS  // - passthru->command contains the ATA STATUS register  // - passthru->features contains the ATA ERROR register  //  // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS  // If bit 0 (error bit) is set, then ATA ERROR register is valid.  // While we *might* decode the ATA ERROR register, at the moment it  // doesn't make much sense: we don't care in detail why the error  // happened.  if (passthru && (passthru->status || (passthru->command & 0x21))) {    errno=EIO;    return -1;  }  // If this is a read data command, copy data to output buffer  if (readdata) {    if (escalade_type==CONTROLLER_3WARE_9000_CHAR)      memcpy(data, (unsigned char *)tw_ioctl_apache->data_buffer, 512);    else if (escalade_type==CONTROLLER_3WARE_678K_CHAR)      memcpy(data, (unsigned char *)tw_ioctl_char->data_buffer, 512);    else      memcpy(data, tw_output->output_data, 512);  }  // For STATUS_CHECK, we need to check register values  if (command==STATUS_CHECK) {    // To find out if the SMART RETURN STATUS is good or failing, we    // need to examine the values of the Cylinder Low and Cylinder    // High Registers.    unsigned short cyl_lo=passthru->cylinder_lo;    unsigned short cyl_hi=passthru->cylinder_hi;    // If values in Cyl-LO and Cyl-HI are unchanged, SMART status is good.    if (cyl_lo==0x4F && cyl_hi==0xC2)      return 0;    // If values in Cyl-LO and Cyl-HI are as follows, SMART status is FAIL    if (cyl_lo==0xF4 && cyl_hi==0x2C)      return 1;    // Any other values mean that something has gone wrong with the command    if (CONTROLLER_3WARE_678K==escalade_type) {      printwarning(command);      errno=ENOSYS;      return 0;    }    else {      errno=EIO;      return -1;    }  }  // copy sector count register (one byte!) to return data  if (command==CHECK_POWER_MODE)    *data=*(char *)&(passthru->sector_count);  // look for nonexistent devices/ports  if (command==IDENTIFY && !nonempty((unsigned char *)data, 512)) {    errno=ENODEV;    return -1;  }  return 0;}int marvell_command_interface(int device,                              smart_command_set command,                              int select,                              char *data) {  typedef struct {    int  inlen;    int  outlen;    char cmd[540];  } mvsata_scsi_cmd;  int copydata = 0;  mvsata_scsi_cmd  smart_command;  unsigned char *buff = (unsigned char *)&smart_command.cmd[6];  // See struct hd_drive_cmd_hdr in hdreg.h  // buff[0]: ATA COMMAND CODE REGISTER  // buff[1]: ATA SECTOR NUMBER REGISTER  // buff[2]: ATA FEATURES REGISTER  // buff[3]: ATA SECTOR COUNT REGISTER  // clear out buff.  Large enough for HDIO_DRIVE_CMD (4+512 bytes)  memset(&smart_command, 0, sizeof(smart_command));  smart_command.inlen = 540;  smart_command.outlen = 540;  smart_command.cmd[0] = 0xC;  //Vendor-specific code  smart_command.cmd[4] = 6;     //command length  buff[0] = ATA_SMART_CMD;  switch (command){  case CHECK_POWER_MODE:    buff[0]=ATA_CHECK_POWER_MODE;    break;  case READ_VALUES:    buff[2]=ATA_SMART_READ_VALUES;    copydata=buff[3]=1;    break;  case READ_THRESHOLDS:    buff[2]=ATA_SMART_READ_THRESHOLDS;    copydata=buff[1]=buff[3]=1;    break;  case READ_LOG:    buff[2]=ATA_SMART_READ_LOG_SECTOR;    buff[1]=select;    copydata=buff[3]=1;    break;  case IDENTIFY:    buff[0]=ATA_IDENTIFY_DEVICE;    copydata=buff[3]=1;    break;  case PIDENTIFY:    buff[0]=ATA_IDENTIFY_PACKET_DEVICE;    copydata=buff[3]=1;    break;  case ENABLE:    buff[2]=ATA_SMART_ENABLE;    buff[1]=1;    break;  case DISABLE:    buff[2]=ATA_SMART_DISABLE;    buff[1]=1;    break;  case STATUS:  case STATUS_CHECK:    // this command only says if SMART is working.  It could be    // replaced with STATUS_CHECK below.    buff[2] = ATA_SMART_STATUS;    break;  case AUTO_OFFLINE:    buff[2]=ATA_SMART_AUTO_OFFLINE;    buff[3]=select;   // YET NOTE - THIS IS A NON-DATA COMMAND!!    break;  case AUTOSAVE:    buff[2]=ATA_SMART_AUTOSAVE;    buff[3]=select;   // YET NOTE - THIS IS A NON-DATA COMMAND!!    break;  case IMMEDIATE_OFFLINE:    buff[2]=ATA_SMART_IMMEDIATE_OFFLINE;    buff[1]=select;    break;  default:    pout("Unrecognized command %d in mvsata_os_specific_handler()\n", command);    exit(1);    break;  }  // There are two different types of ioctls().  The HDIO_DRIVE_TASK  // one is this:  // We are now doing the HDIO_DRIVE_CMD type ioctl.  if (ioctl(device, SCSI_IOCTL_SEND_COMMAND, (void *)&smart_command))      return -1;  if (command==CHECK_POWER_MODE) {    // LEON -- CHECK THIS PLEASE.  THIS SHOULD BE THE SECTOR COUNT    // REGISTER, AND IT MIGHT BE buff[2] NOT buff[3].  Bruce    data[0]=buff[3];    return 0;  }  // Always succeed on a SMART status, as a disk that failed returned  // buff[4]=0xF4, buff[5]=0x2C, i.e. "Bad SMART status" (see below).  if (command == STATUS)    return 0;  //Data returned is starting from 0 offset  if (command == STATUS_CHECK)  {    // Cyl low and Cyl high unchanged means "Good SMART status"    if (buff[4] == 0x4F && buff[5] == 0xC2)      return 0;    // These values mean "Bad SMART status"    if (buff[4] == 0xF4 && buff[5] == 0x2C)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -