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

📄 os_linux.cpp

📁 硬盘各项性能的测试,如温度容量版本健康度型号
💻 CPP
📖 第 1 页 / 共 5 页
字号:
  // and set up return values  *names=mp;  return n;}// makes a list of device names to scan, for either ATA or SCSI// devices.  Return -1 if no memory remaining, else the number of// devices on the list, which can be >=0.int make_device_names (char*** devlist, const char* name) {  int retval, maxdev;#if 0  // for testing case where no device names are found  return 0;#endif  if (!strcmp(name,"SCSI"))    retval=get_dev_names(devlist,"/dev/sd[a-z]", name, maxdev=26);  else if (!strcmp(name,"ATA"))    retval=get_dev_names(devlist,"/dev/hd[a-t]", name, maxdev=20);  else    // don't recognize disk type!    return 0;  // if we found traditional links, we are done  if (retval>0)    return retval;  // else look for devfs entries without traditional links  return get_dev_names(devlist,"/dev/discs/disc*", name, maxdev);}// PURPOSE//   This is an interface routine meant to isolate the OS dependent//   parts of the code, and to provide a debugging interface.  Each//   different port and OS needs to provide it's own interface.  This//   is the linux one.// DETAILED DESCRIPTION OF ARGUMENTS//   device: is the file descriptor provided by open()//   command: defines the different operations.//   select: additional input data if needed (which log, which type of//           self-test).//   data:   location to write output data, if needed (512 bytes).//   Note: not all commands use all arguments.// RETURN VALUES//  -1 if the command failed//   0 if the command succeeded,//   STATUS_CHECK routine://  -1 if the command failed//   0 if the command succeeded and disk SMART status is "OK"//   1 if the command succeeded and disk SMART status is "FAILING"#define BUFFER_LENGTH (4+512)int ata_command_interface(int device, smart_command_set command, int select, char *data){  unsigned char buff[BUFFER_LENGTH];  // positive: bytes to write to caller.  negative: bytes to READ from  // caller. zero: non-data command  int copydata=0;  const int HDIO_DRIVE_CMD_OFFSET = 4;  // See struct hd_drive_cmd_hdr in hdreg.h.  Before calling ioctl()  // buff[0]: ATA COMMAND CODE REGISTER  // buff[1]: ATA SECTOR NUMBER REGISTER == LBA LOW REGISTER  // buff[2]: ATA FEATURES REGISTER  // buff[3]: ATA SECTOR COUNT REGISTER  // Note that on return:  // buff[2] contains the ATA SECTOR COUNT REGISTER  // clear out buff.  Large enough for HDIO_DRIVE_CMD (4+512 bytes)  memset(buff, 0, BUFFER_LENGTH);  buff[0]=ATA_SMART_CMD;  switch (command){  case CHECK_POWER_MODE:    buff[0]=ATA_CHECK_POWER_MODE;    copydata=1;    break;  case READ_VALUES:    buff[2]=ATA_SMART_READ_VALUES;    buff[3]=1;    copydata=512;    break;  case READ_THRESHOLDS:    buff[2]=ATA_SMART_READ_THRESHOLDS;    buff[1]=buff[3]=1;    copydata=512;    break;  case READ_LOG:    buff[2]=ATA_SMART_READ_LOG_SECTOR;    buff[1]=select;    buff[3]=1;    copydata=512;    break;  case WRITE_LOG:    break;  case IDENTIFY:    buff[0]=ATA_IDENTIFY_DEVICE;    buff[3]=1;    copydata=512;    break;  case PIDENTIFY:    buff[0]=ATA_IDENTIFY_PACKET_DEVICE;    buff[3]=1;    copydata=512;    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:    // 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:    // NOTE: According to ATAPI 4 and UP, this command is obsolete    // select == 241 for enable but no data transfer.  Use TASK ioctl.    buff[1]=ATA_SMART_AUTO_OFFLINE;    buff[2]=select;    break;  case AUTOSAVE:    // select == 248 for enable but no data transfer.  Use TASK ioctl.    buff[1]=ATA_SMART_AUTOSAVE;    buff[2]=select;    break;  case IMMEDIATE_OFFLINE:    buff[2]=ATA_SMART_IMMEDIATE_OFFLINE;    buff[1]=select;    break;  case STATUS_CHECK:    // This command uses HDIO_DRIVE_TASK and has different syntax than    // the other commands.    buff[1]=ATA_SMART_STATUS;    break;  default:    pout("Unrecognized command %d in linux_ata_command_interface()\n"         "Please contact " PACKAGE_BUGREPORT "\n", command);    errno=ENOSYS;    return -1;  }  // This command uses the HDIO_DRIVE_TASKFILE ioctl(). This is the  // only ioctl() that can be used to WRITE data to the disk.  if (command==WRITE_LOG) {    unsigned char task[sizeof(ide_task_request_t)+512];    ide_task_request_t *reqtask=(ide_task_request_t *) task;    task_struct_t      *taskfile=(task_struct_t *) reqtask->io_ports;    int retval;    memset(task,      0, sizeof(task));    taskfile->data           = 0;    taskfile->feature        = ATA_SMART_WRITE_LOG_SECTOR;    taskfile->sector_count   = 1;    taskfile->sector_number  = select;    taskfile->low_cylinder   = 0x4f;    taskfile->high_cylinder  = 0xc2;    taskfile->device_head    = 0;    taskfile->command        = ATA_SMART_CMD;    reqtask->data_phase      = TASKFILE_OUT;    reqtask->req_cmd         = IDE_DRIVE_TASK_OUT;    reqtask->out_size        = 512;    reqtask->in_size         = 0;    // copy user data into the task request structure    memcpy(task+sizeof(ide_task_request_t), data, 512);    if ((retval=ioctl(device, HDIO_DRIVE_TASKFILE, task))) {      if (retval==-EINVAL)        pout("Kernel lacks HDIO_DRIVE_TASKFILE support; compile kernel with CONFIG_IDE_TASKFILE_IO set\n");      return -1;    }    return 0;  }  // There are two different types of ioctls().  The HDIO_DRIVE_TASK  // one is this:  if (command==STATUS_CHECK || command==AUTOSAVE || command==AUTO_OFFLINE){    int retval;    // NOT DOCUMENTED in /usr/src/linux/include/linux/hdreg.h. You    // have to read the IDE driver source code.  Sigh.    // buff[0]: ATA COMMAND CODE REGISTER    // buff[1]: ATA FEATURES REGISTER    // buff[2]: ATA SECTOR_COUNT    // buff[3]: ATA SECTOR NUMBER    // buff[4]: ATA CYL LO REGISTER    // buff[5]: ATA CYL HI REGISTER    // buff[6]: ATA DEVICE HEAD    unsigned const char normal_lo=0x4f, normal_hi=0xc2;    unsigned const char failed_lo=0xf4, failed_hi=0x2c;    buff[4]=normal_lo;    buff[5]=normal_hi;    if ((retval=ioctl(device, HDIO_DRIVE_TASK, buff))) {      if (retval==-EINVAL) {        pout("Error SMART Status command via HDIO_DRIVE_TASK failed");        pout("Rebuild older linux 2.2 kernels with HDIO_DRIVE_TASK support added\n");      }      else        syserror("Error SMART Status command failed");      return -1;    }    // Cyl low and Cyl high unchanged means "Good SMART status"    if (buff[4]==normal_lo && buff[5]==normal_hi)      return 0;    // These values mean "Bad SMART status"    if (buff[4]==failed_lo && buff[5]==failed_hi)      return 1;    // We haven't gotten output that makes sense; print out some debugging info    syserror("Error SMART Status command failed");    pout("Please get assistance from " PACKAGE_HOMEPAGE "\n");    pout("Register values returned from SMART Status command are:\n");    pout("ST =0x%02x\n",(int)buff[0]);    pout("ERR=0x%02x\n",(int)buff[1]);    pout("NS =0x%02x\n",(int)buff[2]);    pout("SC =0x%02x\n",(int)buff[3]);    pout("CL =0x%02x\n",(int)buff[4]);    pout("CH =0x%02x\n",(int)buff[5]);    pout("SEL=0x%02x\n",(int)buff[6]);    return -1;  }#if 1  // Note to people doing ports to other OSes -- don't worry about  // this block -- you can safely ignore it.  I have put it here  // because under linux when you do IDENTIFY DEVICE to a packet  // device, it generates an ugly kernel syslog error message.  This  // is harmless but frightens users.  So this block detects packet  // devices and make IDENTIFY DEVICE fail "nicely" without a syslog  // error message.  //  // If you read only the ATA specs, it appears as if a packet device  // *might* respond to the IDENTIFY DEVICE command.  This is  // misleading - it's because around the time that SFF-8020 was  // incorporated into the ATA-3/4 standard, the ATA authors were  // sloppy. See SFF-8020 and you will see that ATAPI devices have  // *always* had IDENTIFY PACKET DEVICE as a mandatory part of their  // command set, and return 'Command Aborted' to IDENTIFY DEVICE.  if (command==IDENTIFY || command==PIDENTIFY){    unsigned short deviceid[256];    // check the device identity, as seen when the system was booted    // or the device was FIRST registered.  This will not be current    // if the user has subsequently changed some of the parameters. If    // device is a packet device, swap the command interpretations.    if (!ioctl(device, HDIO_GET_IDENTITY, deviceid) && (deviceid[0] & 0x8000))      buff[0]=(command==IDENTIFY)?ATA_IDENTIFY_PACKET_DEVICE:ATA_IDENTIFY_DEVICE;  }#endif  // We are now doing the HDIO_DRIVE_CMD type ioctl.  if ((ioctl(device, HDIO_DRIVE_CMD, buff)))    return -1;  // CHECK POWER MODE command returns information in the Sector Count  // register (buff[3]).  Copy to return data buffer.  if (command==CHECK_POWER_MODE)    buff[HDIO_DRIVE_CMD_OFFSET]=buff[2];  // if the command returns data then copy it back  if (copydata)    memcpy(data, buff+HDIO_DRIVE_CMD_OFFSET, copydata);  return 0;}// >>>>>> Start of general SCSI specific linux code/* Linux specific code. * Historically smartmontools (and smartsuite before it) used the * SCSI_IOCTL_SEND_COMMAND ioctl which is available to all linux device * nodes that use the SCSI subsystem. A better interface has been available * via the SCSI generic (sg) driver but this involves the extra step of * mapping disk devices (e.g. /dev/sda) to the corresponding sg device * (e.g. /dev/sg2). In the linux kernel 2.6 series most of the facilities of * the sg driver have become available via the SG_IO ioctl which is available * on all SCSI devices (on SCSI tape devices from lk 2.6.6). * So the strategy below is to find out if the SG_IO ioctl is available and * if so use it; failing that use the older SCSI_IOCTL_SEND_COMMAND ioctl. * Should work in 2.0, 2.2, 2.4 and 2.6 series linux kernels. */#define MAX_DXFER_LEN 1024      /* can be increased if necessary */#define SEND_IOCTL_RESP_SENSE_LEN 16    /* ioctl limitation */#define SG_IO_RESP_SENSE_LEN 64 /* large enough see buffer */#define LSCSI_DRIVER_MASK  0xf /* mask out "suggestions" */#define LSCSI_DRIVER_SENSE  0x8 /* alternate CHECK CONDITION indication */#define LSCSI_DRIVER_TIMEOUT  0x6#define LSCSI_DID_TIME_OUT  0x3#define LSCSI_DID_BUS_BUSY  0x2#define LSCSI_DID_NO_CONNECT  0x1#ifndef SCSI_IOCTL_SEND_COMMAND#define SCSI_IOCTL_SEND_COMMAND 1#endif#define SG_IO_PRESENT_UNKNOWN 0#define SG_IO_PRESENT_YES 1#define SG_IO_PRESENT_NO 2static int sg_io_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report,                         int unknown);static int sisc_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report);static int sg_io_state = SG_IO_PRESENT_UNKNOWN;/* Preferred implementation for issuing SCSI commands in linux. This * function uses the SG_IO ioctl. Return 0 if command issued successfully * (various status values should still be checked). If the SCSI command * cannot be issued then a negative errno value is returned. */static int sg_io_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report,                         int unknown){#ifndef SG_IO    ARGUSED(dev_fd); ARGUSED(iop); ARGUSED(report);    return -ENOTTY;#else    struct sg_io_hdr io_hdr;    if (report > 0) {        int k, j;        const unsigned char * ucp = iop->cmnd;        const char * np;        char buff[256];        const int sz = (int)sizeof(buff);        np = scsi_get_opcode_name(ucp[0]);        j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");        for (k = 0; k < (int)iop->cmnd_len; ++k)            j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]);        if ((report > 1) &&            (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {            int trunc = (iop->dxfer_len > 256) ? 1 : 0;            j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n  Outgoing "                          "data, len=%d%s:\n", (int)iop->dxfer_len,                          (trunc ? " [only first 256 bytes shown]" : ""));            dStrHex((const char *)iop->dxferp,                    (trunc ? 256 : iop->dxfer_len) , 1);        }        else            j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");        pout(buff);    }    memset(&io_hdr, 0, sizeof(struct sg_io_hdr));    io_hdr.interface_id = 'S';    io_hdr.cmd_len = iop->cmnd_len;    io_hdr.mx_sb_len = iop->max_sense_len;    io_hdr.dxfer_len = iop->dxfer_len;

⌨️ 快捷键说明

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