int mfi_lookup_drive(int fd, char *drive, uint16_t *device_id) { struct mfi_pd_list *list; long val; int error; u_int i; char *cp; uint8_t encl, slot; /* Look for a raw device id first. */ val = strtol(drive, &cp, 0); if (*cp == '\0') { if (val < 0 || val >= 0xffff) goto bad; *device_id = val; return (0); } /* Support for MegaCli style [Exx]:Syy notation. */ if (toupper(drive[0]) == 'E' || toupper(drive[0]) == 'S') { if (drive[1] == '\0') goto bad; cp = drive; if (toupper(drive[0]) == 'E') { cp++; /* Eat 'E' */ val = strtol(cp, &cp, 0); if (val < 0 || val > 0xff || *cp != ':') goto bad; encl = val; cp++; /* Eat ':' */ if (toupper(*cp) != 'S') goto bad; } else encl = 0xff; cp++; /* Eat 'S' */ if (*cp == '\0') goto bad; val = strtol(cp, &cp, 0); if (val < 0 || val > 0xff || *cp != '\0') goto bad; slot = val; if (mfi_pd_get_list(fd, &list, NULL) < 0) { error = errno; warn("Failed to fetch drive list"); return (error); } for (i = 0; i < list->count; i++) { if (list->addr[i].scsi_dev_type != 0) continue; if (((encl == 0xff && list->addr[i].encl_device_id == 0xffff) || list->addr[i].encl_index == encl) && list->addr[i].slot_number == slot) { *device_id = list->addr[i].device_id; free(list); return (0); } } free(list); warnx("Unknown drive %s", drive); return (EINVAL); } bad: warnx("Invalid drive number %s", drive); return (EINVAL); }
static int show_patrol(int ac, char **av) { struct mfi_pr_properties prop; struct mfi_pr_status status; struct mfi_pd_list *list; struct mfi_pd_info info; char label[24]; time_t now; uint32_t at; int error, fd; u_int i; fd = mfi_open(mfi_unit); if (fd < 0) { error = errno; warn("mfi_open"); return (error); } time(&now); mfi_get_time(fd, &at); error = patrol_get_props(fd, &prop); if (error) { close(fd); return (error); } printf("Operation Mode: "); switch (prop.op_mode) { case MFI_PR_OPMODE_AUTO: printf("auto\n"); break; case MFI_PR_OPMODE_MANUAL: printf("manual\n"); break; case MFI_PR_OPMODE_DISABLED: printf("disabled\n"); break; default: printf("??? (%02x)\n", prop.op_mode); break; } if (prop.op_mode == MFI_PR_OPMODE_AUTO) { if (at != 0 && prop.next_exec) printf(" Next Run Starts: %s", adapter_time(now, at, prop.next_exec)); if (prop.exec_freq == 0xffffffff) printf(" Runs Execute Continuously\n"); else if (prop.exec_freq != 0) printf(" Runs Start Every %u seconds\n", prop.exec_freq); } if (mfi_dcmd_command(fd, MFI_DCMD_PR_GET_STATUS, &status, sizeof(status), NULL, 0, NULL) < 0) { error = errno; warn("Failed to get patrol read properties"); close(fd); return (error); } printf("Runs Completed: %u\n", status.num_iteration); printf("Current State: "); switch (status.state) { case MFI_PR_STATE_STOPPED: printf("stopped\n"); break; case MFI_PR_STATE_READY: printf("ready\n"); break; case MFI_PR_STATE_ACTIVE: printf("active\n"); break; case MFI_PR_STATE_ABORTED: printf("aborted\n"); break; default: printf("??? (%02x)\n", status.state); break; } if (status.state == MFI_PR_STATE_ACTIVE) { if (mfi_pd_get_list(fd, &list, NULL) < 0) { error = errno; warn("Failed to get drive list"); close(fd); return (error); } for (i = 0; i < list->count; i++) { if (list->addr[i].scsi_dev_type != 0) continue; if (mfi_pd_get_info(fd, list->addr[i].device_id, &info, NULL) < 0) { error = errno; warn("Failed to fetch info for drive %u", list->addr[i].device_id); free(list); close(fd); return (error); } if (info.prog_info.active & MFI_PD_PROGRESS_PATROL) { snprintf(label, sizeof(label), " Drive %s", mfi_drive_name(NULL, list->addr[i].device_id, MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS)); mfi_display_progress(label, &info.prog_info.patrol); } } free(list); } close(fd); return (0); }