void ata_print_ident(struct ata_params *ident_data) { char product[48], revision[16]; cam_strvis(product, ident_data->model, sizeof(ident_data->model), sizeof(product)); cam_strvis(revision, ident_data->revision, sizeof(ident_data->revision), sizeof(revision)); printf("<%s %s> %s-%d", product, revision, (ident_data->config == ATA_PROTO_CFA) ? "CFA" : (ident_data->config & ATA_PROTO_ATAPI) ? "ATAPI" : "ATA", ata_version(ident_data->version_major)); if (ident_data->satacapabilities && ident_data->satacapabilities != 0xffff) { if (ident_data->satacapabilities & ATA_SATA_GEN3) printf(" SATA 3.x"); else if (ident_data->satacapabilities & ATA_SATA_GEN2) printf(" SATA 2.x"); else if (ident_data->satacapabilities & ATA_SATA_GEN1) printf(" SATA 1.x"); else printf(" SATA"); } printf(" device\n"); }
void semb_print_ident_short(struct sep_identify_data *ident_data) { char vendor[9], product[17], revision[5], fw[5]; cam_strvis(vendor, ident_data->vendor_id, 8, sizeof(vendor)); cam_strvis(product, ident_data->product_id, 16, sizeof(product)); cam_strvis(revision, ident_data->product_rev, 4, sizeof(revision)); cam_strvis(fw, ident_data->firmware_rev, 4, sizeof(fw)); printf("<%s %s %s %s>", vendor, product, revision, fw); }
void ata_print_ident_short(struct ata_params *ident_data) { char product[48], revision[16]; cam_strvis(product, ident_data->model, sizeof(ident_data->model), sizeof(product)); cam_strvis(revision, ident_data->revision, sizeof(ident_data->revision), sizeof(revision)); printf("<%s %s>", product, revision); }
void ata_print_ident(struct ata_params *ident_data) { const char *proto; char product[48], revision[16], ata[12], sata[12]; cam_strvis(product, ident_data->model, sizeof(ident_data->model), sizeof(product)); cam_strvis(revision, ident_data->revision, sizeof(ident_data->revision), sizeof(revision)); proto = (ident_data->config == ATA_PROTO_CFA) ? "CFA" : (ident_data->config & ATA_PROTO_ATAPI) ? "ATAPI" : "ATA"; if (ata_version(ident_data->version_major) == 0) { snprintf(ata, sizeof(ata), "%s", proto); } else if (ata_version(ident_data->version_major) <= 7) { snprintf(ata, sizeof(ata), "%s-%d", proto, ata_version(ident_data->version_major)); } else if (ata_version(ident_data->version_major) == 8) { snprintf(ata, sizeof(ata), "%s8-ACS", proto); } else { snprintf(ata, sizeof(ata), "ACS-%d %s", ata_version(ident_data->version_major) - 7, proto); } if (ident_data->satacapabilities && ident_data->satacapabilities != 0xffff) { if (ident_data->satacapabilities & ATA_SATA_GEN3) snprintf(sata, sizeof(sata), " SATA 3.x"); else if (ident_data->satacapabilities & ATA_SATA_GEN2) snprintf(sata, sizeof(sata), " SATA 2.x"); else if (ident_data->satacapabilities & ATA_SATA_GEN1) snprintf(sata, sizeof(sata), " SATA 1.x"); else snprintf(sata, sizeof(sata), " SATA"); } else sata[0] = 0; printf("<%s %s> %s%s device\n", product, revision, ata, sata); }
/* Borrowed heavily from scsi_all.c:scsi_print_inquiry(). */ const char * mpt_pd_inq_string(CONFIG_PAGE_RAID_PHYS_DISK_0 *pd_info) { RAID_PHYS_DISK0_INQUIRY_DATA *inq_data; u_char vendor[9], product[17], revision[5]; static char inq_string[64]; inq_data = &pd_info->InquiryData; cam_strvis(vendor, inq_data->VendorID, sizeof(inq_data->VendorID), sizeof(vendor)); cam_strvis(product, inq_data->ProductID, sizeof(inq_data->ProductID), sizeof(product)); cam_strvis(revision, inq_data->ProductRevLevel, sizeof(inq_data->ProductRevLevel), sizeof(revision)); /* Total hack. */ if (strcmp(vendor, "ATA") == 0) snprintf(inq_string, sizeof(inq_string), "<%s %s> SATA", product, revision); else snprintf(inq_string, sizeof(inq_string), "<%s %s %s> SAS", vendor, product, revision); return (inq_string); }
/* * Find entry in vendors list that belongs to * the vendor of given cam device. */ static const struct fw_vendor * fw_get_vendor(struct cam_device *cam_dev) { char vendor[SID_VENDOR_SIZE + 1]; const struct fw_vendor *vp; if (cam_dev == NULL) return (NULL); cam_strvis((u_char *)vendor, (u_char *)cam_dev->inq_data.vendor, sizeof(cam_dev->inq_data.vendor), sizeof(vendor)); for (vp = vendors_list; vp->pattern != NULL; vp++) { if (!cam_strmatch((const u_char *)vendor, (const u_char *)vp->pattern, strlen(vendor))) break; } return (vp); }
void semb_print_ident(struct sep_identify_data *ident_data) { char vendor[9], product[17], revision[5], fw[5], in[7], ins[5]; cam_strvis(vendor, ident_data->vendor_id, 8, sizeof(vendor)); cam_strvis(product, ident_data->product_id, 16, sizeof(product)); cam_strvis(revision, ident_data->product_rev, 4, sizeof(revision)); cam_strvis(fw, ident_data->firmware_rev, 4, sizeof(fw)); cam_strvis(in, ident_data->interface_id, 6, sizeof(in)); cam_strvis(ins, ident_data->interface_rev, 4, sizeof(ins)); printf("<%s %s %s %s> SEMB %s %s device\n", vendor, product, revision, fw, in, ins); }
/* * Decode the SMP REPORT MANUFACTURER INFORMATION response. The format is * current as of SPL Revision 7, but the parsing should be backward * compatible for older versions of the spec. */ void smp_report_manuf_info_sbuf(struct smp_report_manuf_info_response *response, int response_len, struct sbuf *sb) { char vendor[16], product[48], revision[16]; char comp_vendor[16]; sbuf_printf(sb, "Report Manufacturer Information\n"); sbuf_printf(sb, "Expander Change count: %d\n", scsi_2btoul(response->expander_change_count)); sbuf_printf(sb, "SAS 1.1 Format: %s\n", smp_yesno(response->sas_11_format & SMP_RMI_SAS11_FORMAT)); cam_strvis(vendor, response->vendor, sizeof(response->vendor), sizeof(vendor)); cam_strvis(product, response->product, sizeof(response->product), sizeof(product)); cam_strvis(revision, response->revision, sizeof(response->revision), sizeof(revision)); sbuf_printf(sb, "<%s %s %s>\n", vendor, product, revision); if ((response->sas_11_format & SMP_RMI_SAS11_FORMAT) == 0) { uint8_t *curbyte; int line_start, line_cursor; sbuf_printf(sb, "Vendor Specific Data:\n"); /* * Print out the bytes roughly in the style of hd(1), but * without the extra ASCII decoding. Hexadecimal line * numbers on the left, and 16 bytes per line, with an * extra space after the first 8 bytes. * * It would be nice if this sort of thing were available * in a library routine. */ for (curbyte = (uint8_t *)&response->comp_vendor, line_start= 1, line_cursor = 0; curbyte < (uint8_t *)&response->crc; curbyte++, line_cursor++) { if (line_start != 0) { sbuf_printf(sb, "%08lx ", (unsigned long)(curbyte - (uint8_t *)response)); line_start = 0; line_cursor = 0; } sbuf_printf(sb, "%02x", *curbyte); if (line_cursor == 15) { sbuf_printf(sb, "\n"); line_start = 1; } else sbuf_printf(sb, " %s", (line_cursor == 7) ? " " : ""); } if (line_cursor != 16) sbuf_printf(sb, "\n"); return; } cam_strvis(comp_vendor, response->comp_vendor, sizeof(response->comp_vendor), sizeof(comp_vendor)); sbuf_printf(sb, "Component Vendor: %s\n", comp_vendor); sbuf_printf(sb, "Component ID: %#x\n", scsi_2btoul(response->comp_id)); sbuf_printf(sb, "Component Revision: %#x\n", response->comp_revision); sbuf_printf(sb, "Vendor Specific: 0x%016jx\n", (uintmax_t)scsi_8btou64(response->vendor_specific)); }
/***************************************************************************** * Processes HDD and SMART commands. *****************************************************************************/ void stat_hdd() { time_t tm; int channels_n, channel, device, i; int f_ata_request_supported, f_smart_supported, f_smart_enabled; struct ata_device dev[2]; u_llong sectors; struct dev_match_result matches[100]; union ccb ccb; msg_debug(1, "Processing of HDD/HDD_LIST/SMART command started"); /* check byte order */ #if BYTE_ORDER != LITTLE_ENDIAN msg_err(0, "%s: ussd supports only LITTLE_ENDIAN byte order", __FUNCTION__); stat_hdd_finish(); return; #endif /* get statistics of all devices from devstat library */ if ((f_stat_hdd_command_hdd || f_stat_hdd_command_hdd_list) && !stat_hdd_get_devstat()) { stat_hdd_finish(); return; } /* check if [IOC]ATAREQUEST ioctl request supported by system */ f_ata_request_supported = stat_hdd_is_ata_request_supported(); if (f_stat_hdd_command_hdd || f_stat_hdd_command_smart) { tm = get_remote_tm(); printf("%lu ata_request_supported %d\n", (u_long)tm, f_ata_request_supported); } /* determine number of ATA channels */ if (stat_hdd_get_ata_channels_n(&channels_n)) { /* process all channels */ for (channel = 0; channels_n < 0 || channel < channels_n; channel++) { msg_debug(2, "%s: Processing ATA channel %d", __FUNCTION__, channel); /* get channel devices */ bzero(dev, sizeof(dev)); if (!stat_hdd_get_ata_channel_devices(channel, dev)) { if (channels_n < 0) break; else continue; } /* check if channel has at least one device */ if (!*dev[0].name && !*dev[1].name) { msg_debug(2, "%s: No devices found", __FUNCTION__); continue; } /* Process all devices within channel */ for (device = 0; device < 2; device++) { /* skip if there is no device */ if (!*dev[device].name) continue; msg_debug(2, "%s: Found device %s", __FUNCTION__, dev[device].name); if (!stat_hdd_is_device_ata(&dev[device])) { msg_debug(2, "%s: Device is not ATA device", __FUNCTION__); continue; } /* process HDD_LIST command */ if (f_stat_hdd_command_hdd_list) { tm = get_remote_tm(); printf("%lu hdd_exists:%s 1\n", (u_long)tm, dev[device].name); } /* go to the next device if no HDD or SMART command given */ if (!f_stat_hdd_command_hdd && !f_stat_hdd_command_smart) { stat_hdd_fake_devstat(dev[device].name); continue; } /* refresh device parameters because they can be cached by system */ stat_hdd_refresh_ata_device_params(&dev[device]); /* process HDD command */ if (f_stat_hdd_command_hdd) { /* get device size */ sectors = stat_hdd_get_device_size(&dev[device]); tm = get_remote_tm(); printf("%lu hdd_model:%s %s\n", (u_long)tm, dev[device].name, dev[device].model); printf("%lu hdd_serno:%s %s\n", (u_long)tm, dev[device].name, dev[device].serial); printf("%lu hdd_revision:%s %s\n", (u_long)tm, dev[device].name, dev[device].revision); printf("%lu hdd_size_sectors:%s %llu\n", (u_long)tm, dev[device].name, sectors); printf("%lu hdd_size_mbytes:%s %llu\n", (u_long)tm, dev[device].name, sectors >> 11); /* print devstat statistics of device */ stat_hdd_print_devstat(dev[device].name); } stat_hdd_fake_devstat(dev[device].name); /* process SMART command in remaining code */ if (!f_stat_hdd_command_smart) continue; /* check if SMART supported by device */ f_smart_supported = stat_hdd_is_smart_supported(&dev[device]); /* check if SMART enabled on device */ f_smart_enabled = stat_hdd_is_smart_enabled(&dev[device]); /* enable SMART if requested */ if (conf.f_enable_smart && f_ata_request_supported && f_smart_supported && !f_smart_enabled && stat_hdd_ata_command_interface(&dev[device], SMART_ENABLE_OPERATIONS, NULL)) { f_smart_enabled = 1; msg_notice("SMART has been successfully enabled " "on device %s", dev[device].name); } tm = get_remote_tm(); printf("%lu smart_supported:%s %d\n", (u_long)tm, dev[device].name, f_smart_supported); printf("%lu smart_enabled:%s %d\n", (u_long)tm, dev[device].name, f_smart_enabled); /* don't try to get SMART if no attributes requested */ if (!f_stat_hdd_smart_attrs_requested) { msg_debug(2, "%s: No SMART attributes requested", __FUNCTION__); continue; } /* don't try to get SMART if system doesn't support [IOC]ATAREQUEST ioctl request */ if (!f_ata_request_supported) { msg_debug(2, "%s: Can't get SMART because system doesn't " "support [IOC]ATAREQUEST ioctl request", __FUNCTION__); continue; } /* don't try to get SMART if it is not supported by device */ if (!f_smart_supported) { msg_debug(2, "%s: SMART is not supported by device", __FUNCTION__); continue; } /* don't try to get SMART if it is not enabled on device */ if (!f_smart_enabled) { msg_debug(2, "%s: SMART is not enabled on device", __FUNCTION__); continue; } /* get SMART values */ if (!stat_hdd_ata_command_interface(&dev[device], SMART_READ_VALUES, (char *)&dev[device].smart_values)) continue; msg_debug(2, "%s: Got SMART values", __FUNCTION__); /* get SMART thresholds */ if (!stat_hdd_ata_command_interface(&dev[device], SMART_READ_THRESHOLDS, (char *)&dev[device].smart_thresholds)) continue; msg_debug(2, "%s: Got SMART thresholds", __FUNCTION__); /* process SMART attributes */ stat_hdd_process_smart_attributes(&dev[device]); } } msg_debug(2, "%s: All ATA channels processed", __FUNCTION__); } /* processing SCSI bus * now we're not support SMART on SCSI, sad but true */ msg_debug(2, "%s: Processing SCSI bus", __FUNCTION__); if ((channel = open(XPT_DEVICE, O_RDWR)) == -1) { msg_debug(1, "%s: open(%s) error %d (%s)", __FUNCTION__, XPT_DEVICE, errno, strerror(errno)); stat_hdd_finish(); return; } bzero(&ccb, sizeof(ccb)); ccb.ccb_h.path_id = CAM_XPT_PATH_ID; ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; ccb.ccb_h.func_code = XPT_DEV_MATCH; ccb.cdm.match_buf_len = sizeof(matches); ccb.cdm.matches = &matches[0]; if (ioctl(channel, CAMIOCOMMAND, &ccb) == -1) { msg_debug(1, "%s: ioctl(CAMIOCOMMAND) error %d (%s)", __FUNCTION__, errno, strerror(errno)); stat_hdd_finish(); return; } if ((ccb.ccb_h.status != CAM_REQ_CMP) || ((ccb.cdm.status != CAM_DEV_MATCH_LAST) && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) { msg_debug(1, "%s: CAM return error %#x, CDM error %d\n", __FUNCTION__, ccb.ccb_h.status, ccb.cdm.status); stat_hdd_finish(); return; } /* walking CAM hierarchy */ for(device = 0; (unsigned) device < ccb.cdm.num_matches; device++) { if (ccb.cdm.matches[device].type == DEV_MATCH_DEVICE) { if (ccb.cdm.matches[device].result.device_result.flags & DEV_RESULT_UNCONFIGURED) continue; #if __FreeBSD_version > 800100 /* new atacam devices - see ada(4) */ if (ccb.cdm.matches[device].result.device_result.protocol == PROTO_ATA) { cam_strvis((void *) dev[0].model, ccb.cdm.matches[device].result.device_result.ident_data.model, sizeof(ccb.cdm.matches[device].result.device_result.ident_data.model), sizeof(dev[0].model)); cam_strvis((void *) dev[0].serial, ccb.cdm.matches[device].result.device_result.ident_data.serial, sizeof(ccb.cdm.matches[device].result.device_result.ident_data.serial), sizeof(dev[0].serial)); cam_strvis((void *) dev[0].revision, ccb.cdm.matches[device].result.device_result.ident_data.revision, sizeof(ccb.cdm.matches[device].result.device_result.ident_data.revision), sizeof(dev[0].revision)); memcpy(&dev[0].params, &ccb.cdm.matches[device].result.device_result.ident_data, sizeof(dev[0].params)); /* fake 3'rd device on IDE channel is atacam */ dev[0].device = 2; } else if (ccb.cdm.matches[device].result.device_result.protocol == PROTO_SCSI) { #endif cam_strvis((u_int8_t *) dev[0].model, (u_int8_t *) ccb.cdm.matches[device].result.device_result.inq_data.vendor, sizeof(ccb.cdm.matches[device].result.device_result.inq_data.vendor), sizeof(dev[0].model)); if (strlen(dev[0].model) < sizeof(dev[0].model)+2) strlcat(dev[0].model, " ", sizeof(dev[0].model)); cam_strvis((u_int8_t *) dev[0].model+strlen(dev[0].model), (u_int8_t *) ccb.cdm.matches[device].result.device_result.inq_data.product, sizeof(ccb.cdm.matches[device].result.device_result.inq_data.product), sizeof(dev[0].model)-strlen(dev[0].model)); cam_strvis((u_int8_t *) dev[0].revision, (u_int8_t *) ccb.cdm.matches[device].result.device_result.inq_data.revision, sizeof(ccb.cdm.matches[device].result.device_result.inq_data.revision), sizeof(dev[0].revision)); /* fake 4'th device on IDE channel is SCSI disk */ dev[0].device = 3; msg_debug(2, "%s: found SCSI device, model is %s", __FUNCTION__, dev[0].model); #if __FreeBSD_version > 800100 } #endif } if (ccb.cdm.matches[device].type == DEV_MATCH_PERIPH) { for (i=0; i < dinfo.numdevs; i++) { if (((dinfo.devices[i].device_type & DEVSTAT_TYPE_MASK) != DEVSTAT_TYPE_DIRECT) || (dinfo.devices[i].device_type & DEVSTAT_TYPE_PASS)) continue; if (!strcmp(dinfo.devices[i].device_name, ccb.cdm.matches[device].result.periph_result.periph_name) && (unsigned) dinfo.devices[i].unit_number == ccb.cdm.matches[device].result.periph_result.unit_number) { snprintf(dev[0].name, sizeof(dev[0].name), "%s%d", ccb.cdm.matches[device].result.periph_result.periph_name, ccb.cdm.matches[device].result.periph_result.unit_number); msg_debug(2, "%s: periph %s have stat", __FUNCTION__, dev[0].name); if (dev[0].device == 2) stat_hdd_refresh_ata_device_params(&dev[0]); if (dev[0].device == 3) stat_hdd_refresh_cam_device_params(&dev[0]); if (f_stat_hdd_command_hdd_list) { tm = get_remote_tm(); printf("%lu hdd_exists:%s 1\n", (u_long)tm, dev[0].name); } if (f_stat_hdd_command_hdd) { sectors = stat_hdd_get_device_size(&dev[0]); tm = get_remote_tm(); printf("%lu hdd_model:%s %s\n", (u_long)tm, dev[0].name, dev[0].model); printf("%lu hdd_serno:%s %s\n", (u_long)tm, dev[0].name, dev[0].serial); printf("%lu hdd_revision:%s %s\n", (u_long)tm, dev[0].name, dev[0].revision); printf("%lu hdd_size_sectors:%s %llu\n", (u_long)tm, dev[0].name, sectors); printf("%lu hdd_size_mbytes:%s %llu\n", (u_long)tm, dev[0].name, sectors >> 11); stat_hdd_print_devstat(dev[0].name); } stat_hdd_fake_devstat(dev[0].name); if (!f_stat_hdd_command_smart) break; /* Now i don't know how to read SMART from SCSI */ if (dev[0].device == 3) { break; } f_smart_supported = stat_hdd_is_smart_supported(&dev[0]); f_smart_enabled = stat_hdd_is_smart_enabled(&dev[0]); if (conf.f_enable_smart && f_ata_request_supported && f_smart_supported && !f_smart_enabled && stat_hdd_ata_command_interface(&dev[0], SMART_ENABLE_OPERATIONS, NULL)) { f_smart_enabled = 1; msg_notice("SMART has been successfully enabled on device %s", dev[0].name); } tm = get_remote_tm(); printf("%lu smart_supported:%s %d\n", (u_long)tm, dev[0].name, f_smart_supported); printf("%lu smart_enabled:%s %d\n", (u_long)tm, dev[0].name, f_smart_enabled); if (!f_stat_hdd_smart_attrs_requested) { msg_debug(2, "%s: No SMART attributes requested", __FUNCTION__); break; } if (!f_smart_supported) { msg_debug(2, "%s: SMART is not supported by device", __FUNCTION__); break; } if (!f_smart_enabled) { msg_debug(2, "%s: SMART is not enabled on device", __FUNCTION__); break; } if (!stat_hdd_ata_command_interface(&dev[0], SMART_READ_VALUES, (char *)&dev[0].smart_values)) break; msg_debug(2, "%s: Got SMART values", __FUNCTION__); if (!stat_hdd_ata_command_interface(&dev[0], SMART_READ_THRESHOLDS, (char *)&dev[0].smart_thresholds)) break; msg_debug(2, "%s: Got SMART thresholds", __FUNCTION__); stat_hdd_process_smart_attributes(&dev[0]); break; } } } }