2 * Copyright (c) 2016 Spectra Logic Corporation
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions, and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * substantially similar to the "NO WARRANTY" disclaimer below
13 * ("Disclaimer") and any redistribution must be conditioned upon
14 * including a substantially similar Disclaimer requirement for further
15 * binary redistribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGES.
30 * Authors: Ken Merry (Spectra Logic Corporation)
33 * ATA Extended Power Conditions (EPC) support
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
39 #include <sys/ioctl.h>
40 #include <sys/stdint.h>
41 #include <sys/types.h>
42 #include <sys/endian.h>
44 #include <sys/queue.h>
60 #include <cam/cam_debug.h>
61 #include <cam/cam_ccb.h>
62 #include <cam/scsi/scsi_all.h>
63 #include <cam/scsi/scsi_da.h>
64 #include <cam/scsi/scsi_pass.h>
65 #include <cam/scsi/scsi_message.h>
67 #include "camcontrol.h"
70 EPC_ACTION_NONE = 0x00,
71 EPC_ACTION_LIST = 0x01,
72 EPC_ACTION_TIMER_SET = 0x02,
73 EPC_ACTION_IMMEDIATE = 0x03,
74 EPC_ACTION_GETMODE = 0x04
77 static struct scsi_nv epc_flags[] = {
78 { "Supported", ATA_PCL_COND_SUPPORTED },
79 { "Saveable", ATA_PCL_COND_SUPPORTED },
80 { "Changeable", ATA_PCL_COND_CHANGEABLE },
81 { "Default Timer Enabled", ATA_PCL_DEFAULT_TIMER_EN },
82 { "Saved Timer Enabled", ATA_PCL_SAVED_TIMER_EN },
83 { "Current Timer Enabled", ATA_PCL_CURRENT_TIMER_EN },
84 { "Hold Power Condition Not Supported", ATA_PCL_HOLD_PC_NOT_SUP }
87 static struct scsi_nv epc_power_cond_map[] = {
88 { "Standby_z", ATA_EPC_STANDBY_Z },
89 { "z", ATA_EPC_STANDBY_Z },
90 { "Standby_y", ATA_EPC_STANDBY_Y },
91 { "y", ATA_EPC_STANDBY_Y },
92 { "Idle_a", ATA_EPC_IDLE_A },
93 { "a", ATA_EPC_IDLE_A },
94 { "Idle_b", ATA_EPC_IDLE_B },
95 { "b", ATA_EPC_IDLE_B },
96 { "Idle_c", ATA_EPC_IDLE_C },
97 { "c", ATA_EPC_IDLE_C }
100 static struct scsi_nv epc_rst_val[] = {
101 { "default", ATA_SF_EPC_RST_DFLT },
105 static struct scsi_nv epc_ps_map[] = {
106 { "unknown", ATA_SF_EPC_SRC_UNKNOWN },
107 { "battery", ATA_SF_EPC_SRC_BAT },
108 { "notbattery", ATA_SF_EPC_SRC_NOT_BAT }
112 * These aren't subcommands of the EPC SET FEATURES subcommand, but rather
113 * commands that determine the current capabilities and status of the drive.
114 * The EPC subcommands are limited to 4 bits, so we won't collide with any
117 #define CCTL_EPC_GET_STATUS 0x8001
118 #define CCTL_EPC_LIST 0x8002
120 static struct scsi_nv epc_cmd_map[] = {
121 { "restore", ATA_SF_EPC_RESTORE },
122 { "goto", ATA_SF_EPC_GOTO },
123 { "timer", ATA_SF_EPC_SET_TIMER },
124 { "state", ATA_SF_EPC_SET_STATE },
125 { "enable", ATA_SF_EPC_ENABLE },
126 { "disable", ATA_SF_EPC_DISABLE },
127 { "source", ATA_SF_EPC_SET_SOURCE },
128 { "status", CCTL_EPC_GET_STATUS },
129 { "list", CCTL_EPC_LIST }
132 static int epc_list(struct cam_device *device, camcontrol_devtype devtype,
133 union ccb *ccb, int retry_count, int timeout);
134 static void epc_print_pcl_desc(struct ata_power_cond_log_desc *desc,
136 static int epc_getmode(struct cam_device *device, camcontrol_devtype devtype,
137 union ccb *ccb, int retry_count, int timeout,
139 static int epc_set_features(struct cam_device *device,
140 camcontrol_devtype devtype, union ccb *ccb,
141 int retry_count, int timeout, int action,
142 int power_cond, int timer, int enable, int save,
143 int delayed_entry, int hold, int power_src,
147 epc_print_pcl_desc(struct ata_power_cond_log_desc *desc, const char *prefix)
150 unsigned int i, num_printed, max_chars;
155 num_printed = printf("%sFlags: ", prefix);
156 for (i = 0; i < (sizeof(epc_flags) / sizeof(epc_flags[0])); i++) {
157 if ((desc->flags & epc_flags[i].value) == 0)
160 num_printed += printf(", ");
162 if ((num_printed + strlen(epc_flags[i].name)) > max_chars) {
164 num_printed = printf("%s ", prefix);
166 num_printed += printf("%s", epc_flags[i].name);
173 printf("%sDefault timer setting: %.1f sec\n", prefix,
174 (double)(le32dec(desc->default_timer) / 10));
175 printf("%sSaved timer setting: %.1f sec\n", prefix,
176 (double)(le32dec(desc->saved_timer) / 10));
177 printf("%sCurrent timer setting: %.1f sec\n", prefix,
178 (double)(le32dec(desc->current_timer) / 10));
179 printf("%sNominal time to active: %.1f sec\n", prefix,
180 (double)(le32dec(desc->nom_time_to_active) / 10));
181 printf("%sMinimum timer: %.1f sec\n", prefix,
182 (double)(le32dec(desc->min_timer) / 10));
183 printf("%sMaximum timer: %.1f sec\n", prefix,
184 (double)(le32dec(desc->max_timer) / 10));
185 printf("%sNumber of transitions to power condition: %u\n", prefix,
186 le32dec(desc->num_transitions_to_pc));
187 printf("%sHours in power condition: %u\n", prefix,
188 le32dec(desc->hours_in_pc));
192 epc_list(struct cam_device *device, camcontrol_devtype devtype, union ccb *ccb,
193 int retry_count, int timeout)
195 struct ata_power_cond_log_idle *idle_log;
196 struct ata_power_cond_log_standby *standby_log;
197 uint8_t log_buf[sizeof(*idle_log) + sizeof(*standby_log)];
198 uint16_t log_addr = ATA_POWER_COND_LOG;
199 uint16_t page_number = ATA_PCL_IDLE;
203 lba = (((uint64_t)page_number & 0xff00) << 32) |
204 ((page_number & 0x00ff) << 8) |
207 error = build_ata_cmd(ccb,
208 /*retry_count*/ retry_count,
209 /*flags*/ CAM_DIR_IN | CAM_DEV_QFRZDIS,
210 /*tag_action*/ MSG_SIMPLE_Q_TAG,
211 /*protocol*/ AP_PROTO_DMA | AP_EXTEND,
212 /*ata_flags*/ AP_FLAG_BYT_BLOK_BLOCKS |
213 AP_FLAG_TLEN_SECT_CNT |
214 AP_FLAG_TDIR_FROM_DEV,
218 /*command*/ ATA_READ_LOG_DMA_EXT,
220 /*data_ptr*/ log_buf,
221 /*dxfer_len*/ sizeof(log_buf),
222 /*cdb_storage*/ NULL,
223 /*cdb_storage_len*/ 0,
224 /*sense_len*/ SSD_FULL_SIZE,
225 /*timeout*/ timeout ? timeout : 60000,
227 /*devtype*/ devtype);
230 warnx("%s: build_ata_cmd() failed, likely programmer error",
236 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
238 error = cam_send_ccb(device, ccb);
240 warn("error sending ATA READ LOG EXT CCB");
245 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
246 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL,stderr);
251 idle_log = (struct ata_power_cond_log_idle *)log_buf;
253 (struct ata_power_cond_log_standby *)&log_buf[sizeof(*idle_log)];
255 printf("ATA Power Conditions Log:\n");
256 printf(" Idle power conditions page:\n");
257 printf(" Idle A condition:\n");
258 epc_print_pcl_desc(&idle_log->idle_a_desc, " ");
259 printf(" Idle B condition:\n");
260 epc_print_pcl_desc(&idle_log->idle_b_desc, " ");
261 printf(" Idle C condition:\n");
262 epc_print_pcl_desc(&idle_log->idle_c_desc, " ");
263 printf(" Standby power conditions page:\n");
264 printf(" Standby Y condition:\n");
265 epc_print_pcl_desc(&standby_log->standby_y_desc, " ");
266 printf(" Standby Z condition:\n");
267 epc_print_pcl_desc(&standby_log->standby_z_desc, " ");
273 epc_getmode(struct cam_device *device, camcontrol_devtype devtype,
274 union ccb *ccb, int retry_count, int timeout, int power_only)
276 struct ata_params *ident = NULL;
277 struct ata_identify_log_sup_cap sup_cap;
278 const char *mode_name = NULL;
279 uint8_t error = 0, ata_device = 0, status = 0;
282 uint32_t page_number, log_address;
285 int res_available = 0;
291 goto check_power_mode;
294 * Get standard ATA Identify data.
296 retval = ata_do_identify(device, retry_count, timeout, ccb, &ident);
298 warnx("Couldn't get identify data");
303 * Get the ATA Identify Data Log (0x30),
304 * Supported Capabilities Page (0x03).
306 log_address = ATA_IDENTIFY_DATA_LOG;
307 page_number = ATA_IDL_SUP_CAP;
308 lba = (((uint64_t)page_number & 0xff00) << 32) |
309 ((page_number & 0x00ff) << 8) |
310 (log_address & 0xff);
312 bzero(&sup_cap, sizeof(sup_cap));
314 * XXX KDM check the supported protocol.
316 retval = build_ata_cmd(ccb,
317 /*retry_count*/ retry_count,
318 /*flags*/ CAM_DIR_IN | CAM_DEV_QFRZDIS,
319 /*tag_action*/ MSG_SIMPLE_Q_TAG,
320 /*protocol*/ AP_PROTO_DMA |
322 /*ata_flags*/ AP_FLAG_BYT_BLOK_BLOCKS |
323 AP_FLAG_TLEN_SECT_CNT |
324 AP_FLAG_TDIR_FROM_DEV,
328 /*command*/ ATA_READ_LOG_DMA_EXT,
330 /*data_ptr*/ (uint8_t *)&sup_cap,
331 /*dxfer_len*/ sizeof(sup_cap),
332 /*cdb_storage*/ NULL,
333 /*cdb_storage_len*/ 0,
334 /*sense_len*/ SSD_FULL_SIZE,
335 /*timeout*/ timeout ? timeout : 60000,
337 /*devtype*/ devtype);
340 warnx("%s: build_ata_cmd() failed, likely a programmer error",
346 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
348 retval = cam_send_ccb(device, ccb);
350 warn("error sending ATA READ LOG CCB");
355 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
356 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL,stderr);
361 if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
362 avail_bytes = ccb->csio.dxfer_len - ccb->csio.resid;
364 avail_bytes = ccb->ataio.dxfer_len - ccb->ataio.resid;
366 if (avail_bytes < (int)sizeof(sup_cap)) {
367 warnx("Couldn't get enough of the ATA Supported "
368 "Capabilities log, %d bytes returned", avail_bytes);
372 caps = le64dec(sup_cap.sup_cap);
373 if ((caps & ATA_SUP_CAP_VALID) == 0) {
374 warnx("Supported capabilities bits are not valid");
379 printf("APM: %sSupported, %sEnabled\n",
380 (ident->support.command2 & ATA_SUPPORT_APM) ? "" : "NOT ",
381 (ident->enabled.command2 & ATA_SUPPORT_APM) ? "" : "NOT ");
382 printf("EPC: %sSupported, %sEnabled\n",
383 (ident->support2 & ATA_SUPPORT_EPC) ? "" : "NOT ",
384 (ident->enabled2 & ATA_ENABLED_EPC) ? "" : "NOT ");
385 printf("Low Power Standby %sSupported\n",
386 (caps & ATA_SC_LP_STANDBY_SUP) ? "" : "NOT ");
387 printf("Set EPC Power Source %sSupported\n",
388 (caps & ATA_SC_SET_EPC_PS_SUP) ? "" : "NOT ");
393 retval = build_ata_cmd(ccb,
394 /*retry_count*/ retry_count,
395 /*flags*/ CAM_DIR_NONE | CAM_DEV_QFRZDIS,
396 /*tag_action*/ MSG_SIMPLE_Q_TAG,
397 /*protocol*/ AP_PROTO_NON_DATA |
399 /*ata_flags*/ AP_FLAG_BYT_BLOK_BLOCKS |
400 AP_FLAG_TLEN_NO_DATA |
402 /*features*/ ATA_SF_EPC,
405 /*command*/ ATA_CHECK_POWER_MODE,
409 /*cdb_storage*/ NULL,
410 /*cdb_storage_len*/ 0,
411 /*sense_len*/ SSD_FULL_SIZE,
412 /*timeout*/ timeout ? timeout : 60000,
414 /*devtype*/ devtype);
417 warnx("%s: build_ata_cmd() failed, likely a programmer error",
423 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
425 retval = cam_send_ccb(device, ccb);
427 warn("error sending ATA CHECK POWER MODE CCB");
433 * Check to see whether we got the requested ATA result if this
434 * is an SCSI ATA PASS-THROUGH command.
436 if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
437 && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)) {
438 int error_code, sense_key, asc, ascq;
440 retval = scsi_extract_sense_ccb(ccb, &error_code,
441 &sense_key, &asc, &ascq);
443 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL,
448 if ((sense_key == SSD_KEY_RECOVERED_ERROR)
455 if (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
456 && (res_available == 0)) {
457 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL,stderr);
462 retval = get_ata_status(device, ccb, &error, &count, &lba, &ata_device,
465 warnx("Unable to get ATA CHECK POWER MODE result");
470 mode_name = scsi_nv_to_str(epc_power_cond_map,
471 sizeof(epc_power_cond_map) / sizeof(epc_power_cond_map[0]), count);
472 printf("Current power state: ");
473 /* Note: ident can be null in power_only mode */
475 || (ident->enabled2 & ATA_ENABLED_EPC)) {
476 if (mode_name != NULL)
477 printf("%s", mode_name);
478 else if (count == 0xff) {
479 printf("PM0:Active or PM1:Idle");
484 printf("PM2:Standby");
490 printf("PM0:Active or PM1:Idle");
494 printf("(0x%02x)\n", count);
499 if (caps & ATA_SC_LP_STANDBY_SUP) {
502 wait_mode = (lba >> 20) & 0xff;
503 if (wait_mode == 0xff) {
504 printf("Device not waiting to enter lower power "
507 mode_name = scsi_nv_to_str(epc_power_cond_map,
508 sizeof(epc_power_cond_map) /
509 sizeof(epc_power_cond_map[0]), wait_mode);
510 printf("Device waiting to enter mode %s (0x%02x)\n",
511 (mode_name != NULL) ? mode_name : "Unknown",
514 printf("Device is %sheld in the current power condition\n",
515 (lba & 0x80000) ? "" : "NOT ");
523 epc_set_features(struct cam_device *device, camcontrol_devtype devtype,
524 union ccb *ccb, int retry_count, int timeout, int action,
525 int power_cond, int timer, int enable, int save,
526 int delayed_entry, int hold, int power_src, int restore_src)
537 case ATA_SF_EPC_SET_TIMER:
538 lba |= ((timer << ATA_SF_EPC_TIMER_SHIFT) &
539 ATA_SF_EPC_TIMER_MASK);
541 case ATA_SF_EPC_SET_STATE:
542 lba |= (enable ? ATA_SF_EPC_TIMER_EN : 0) |
543 (save ? ATA_SF_EPC_TIMER_SAVE : 0);
546 case ATA_SF_EPC_GOTO:
548 lba |= (delayed_entry ? ATA_SF_EPC_GOTO_DELAY : 0) |
549 (hold ? ATA_SF_EPC_GOTO_HOLD : 0);
551 case ATA_SF_EPC_RESTORE:
553 (save ? ATA_SF_EPC_RST_SAVE : 0);
555 case ATA_SF_EPC_ENABLE:
556 case ATA_SF_EPC_DISABLE:
558 case ATA_SF_EPC_SET_SOURCE:
563 error = build_ata_cmd(ccb,
564 /*retry_count*/ retry_count,
565 /*flags*/ CAM_DIR_NONE | CAM_DEV_QFRZDIS,
566 /*tag_action*/ MSG_SIMPLE_Q_TAG,
567 /*protocol*/ AP_PROTO_NON_DATA | AP_EXTEND,
568 /*ata_flags*/ AP_FLAG_BYT_BLOK_BLOCKS |
569 AP_FLAG_TLEN_NO_DATA |
570 AP_FLAG_TDIR_FROM_DEV,
571 /*features*/ ATA_SF_EPC,
572 /*sector_count*/ count,
574 /*command*/ ATA_SETFEATURES,
578 /*cdb_storage*/ NULL,
579 /*cdb_storage_len*/ 0,
580 /*sense_len*/ SSD_FULL_SIZE,
581 /*timeout*/ timeout ? timeout : 60000,
583 /*devtype*/ devtype);
586 warnx("%s: build_ata_cmd() failed, likely a programmer error",
592 ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
594 error = cam_send_ccb(device, ccb);
596 warn("error sending ATA SET FEATURES CCB");
601 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
602 cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL,stderr);
612 epc(struct cam_device *device, int argc, char **argv, char *combinedopt,
613 int retry_count, int timeout, int verbosemode __unused)
615 union ccb *ccb = NULL;
619 camcontrol_devtype devtype;
620 double timer_val = -1;
621 int timer_tenths = 0, power_cond = -1;
622 int delayed_entry = 0, hold = 0;
623 int enable = -1, save = 0;
624 int restore_src = -1;
629 ccb = cam_getccb(device);
631 warnx("%s: error allocating CCB", __func__);
636 CCB_CLEAR_ALL_EXCEPT_HDR(ccb);
638 while ((c = getopt(argc, argv, combinedopt)) != -1) {
641 scsi_nv_status status;
644 status = scsi_get_nv(epc_cmd_map,
645 (sizeof(epc_cmd_map) / sizeof(epc_cmd_map[0])),
646 optarg, &entry_num, SCSI_NV_FLAG_IG_CASE);
647 if (status == SCSI_NV_FOUND)
648 action = epc_cmd_map[entry_num].value;
650 warnx("%s: %s: %s option %s", __func__,
651 (status == SCSI_NV_AMBIGUOUS) ?
652 "ambiguous" : "invalid", "epc command",
672 scsi_nv_status status;
675 status = scsi_get_nv(epc_power_cond_map,
676 (sizeof(epc_power_cond_map) /
677 sizeof(epc_power_cond_map[0])), optarg,
678 &entry_num, SCSI_NV_FLAG_IG_CASE);
679 if (status == SCSI_NV_FOUND)
680 power_cond =epc_power_cond_map[entry_num].value;
682 warnx("%s: %s: %s option %s", __func__,
683 (status == SCSI_NV_AMBIGUOUS) ?
684 "ambiguous" : "invalid", "power condition",
695 scsi_nv_status status;
698 status = scsi_get_nv(epc_rst_val,
699 (sizeof(epc_rst_val) /
700 sizeof(epc_rst_val[0])), optarg,
701 &entry_num, SCSI_NV_FLAG_IG_CASE);
702 if (status == SCSI_NV_FOUND)
703 restore_src = epc_rst_val[entry_num].value;
705 warnx("%s: %s: %s option %s", __func__,
706 (status == SCSI_NV_AMBIGUOUS) ?
707 "ambiguous" : "invalid",
708 "restore value source", optarg);
718 scsi_nv_status status;
721 status = scsi_get_nv(epc_ps_map,
722 (sizeof(epc_ps_map) / sizeof(epc_ps_map[0])),
723 optarg, &entry_num, SCSI_NV_FLAG_IG_CASE);
724 if (status == SCSI_NV_FOUND)
725 power_src = epc_ps_map[entry_num].value;
727 warnx("%s: %s: %s option %s", __func__,
728 (status == SCSI_NV_AMBIGUOUS) ?
729 "ambiguous" : "invalid", "power source",
739 timer_val = strtod(optarg, &endptr);
741 warnx("Invalid timer value %f", timer_val);
744 } else if (*endptr != '\0') {
745 warnx("Invalid timer value %s", optarg);
749 timer_tenths = timer_val * 10;
758 warnx("Must specify an action");
763 error = get_device_type(device, retry_count, timeout,
764 /*printerrors*/ 1, &devtype);
766 errx(1, "Unable to determine device type");
773 warnx("The epc subcommand only works with ATA protocol "
777 break; /*NOTREACHED*/
781 case ATA_SF_EPC_SET_TIMER:
782 if (timer_val == -1) {
783 warnx("Must specify a timer value (-T time)");
787 case ATA_SF_EPC_SET_STATE:
789 warnx("Must specify enable (-e) or disable (-d)");
793 case ATA_SF_EPC_GOTO:
794 if (power_cond == -1) {
795 warnx("Must specify a power condition with -p");
801 case ATA_SF_EPC_SET_SOURCE:
802 if (power_src == -1) {
803 warnx("Must specify a power source (-S battery or "
804 "-S notbattery) value");
809 case ATA_SF_EPC_RESTORE:
810 if (restore_src == -1) {
811 warnx("Must specify a source for restored value, "
812 "-r default or -r saved");
817 case ATA_SF_EPC_ENABLE:
818 case ATA_SF_EPC_DISABLE:
819 case CCTL_EPC_GET_STATUS:
826 case CCTL_EPC_GET_STATUS:
827 error = epc_getmode(device, devtype, ccb, retry_count, timeout,
831 error = epc_list(device, devtype, ccb, retry_count, timeout);
833 case ATA_SF_EPC_RESTORE:
834 case ATA_SF_EPC_GOTO:
835 case ATA_SF_EPC_SET_TIMER:
836 case ATA_SF_EPC_SET_STATE:
837 case ATA_SF_EPC_ENABLE:
838 case ATA_SF_EPC_DISABLE:
839 case ATA_SF_EPC_SET_SOURCE:
840 error = epc_set_features(device, devtype, ccb, retry_count,
841 timeout, action, power_cond, timer_tenths, enable, save,
842 delayed_entry, hold, power_src, restore_src);
845 warnx("Not implemented yet");