diff --git a/sbin/atacontrol/atacontrol.c b/sbin/atacontrol/atacontrol.c index 1e6edc1..d23ba89 100644 --- a/sbin/atacontrol/atacontrol.c +++ b/sbin/atacontrol/atacontrol.c @@ -111,6 +111,10 @@ usage() " atacontrol status array\n" " atacontrol mode device [mode]\n" " atacontrol cap device\n" + " atacontrol setcap device enableapm val\n" + " atacontrol setcap device disableapm\n" + " atacontrol setcap device enableaac val\n" + " atacontrol setcap device disableaac\n" ); exit(EX_USAGE); } @@ -349,6 +353,58 @@ main(int argc, char **argv) ata_cap_print(fd); exit(EX_OK); } + if (!strcmp(argv[1], "setcap") && (argc == 4 || argc == 5)) { + int disk; + char device[64]; + + if (!(sscanf(argv[2], "ad%d", &disk) == 1 || + sscanf(argv[2], "acd%d", &disk) == 1 || + sscanf(argv[2], "afd%d", &disk) == 1 || + sscanf(argv[2], "ast%d", &disk) == 1)) { + fprintf(stderr, "atacontrol: Invalid device %s\n", + argv[2]); + exit(EX_USAGE); + } + sprintf(device, "/dev/%s", argv[2]); + if ((fd = open(device, O_RDONLY)) < 0) + err(1, "device not found"); + if (!strcmp(argv[3], "enableapm")) { + int apm; + + if (argc != 5) + errx(1, "enableapm requires argument"); + apm = atoi(argv[4]); + if (ioctl(fd, IOCATAENAPM, &apm) < 0) + err(1, "ioctl(IOCATAENAPM)"); + exit(EX_OK); + } else if (!strcmp(argv[3], "disableapm")) { + if (argc != 4) + errx(1, "disableapm does not take argument"); + if (ioctl(fd, IOCATADISAPM) < 0) + err(1, "ioctl(IOCATADISAPM)"); + exit(EX_OK); + } + else if (!strcmp(argv[3], "enableaac")) { + int aac; + + if (argc != 5) + errx(1, "enableaac requires argument"); + aac = atoi(argv[4]); + if (ioctl(fd, IOCATAENAAC, &aac) < 0) + err(1, "ioctl(IOCATAENAAC)"); + exit(EX_OK); + } else if (!strcmp(argv[3], "disableaac")) { + if (argc != 4) + errx(1, "disableaac does not take argument"); + if (ioctl(fd, IOCATADISAAC) < 0) + err(1, "ioctl(IOCATADISAAC)"); + exit(EX_OK); + } else { + fprintf(stderr, "atacontrol: Invalid setcap capability %s\n", + argv[3]); + exit(EX_USAGE); + } + } if ((fd = open("/dev/ata", O_RDWR)) < 0) err(1, "control device not found"); diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 41948c6..1346c6b 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -514,6 +514,27 @@ ata_device_ioctl(device_t dev, u_long cmd, caddr_t data) case IOCATAGMODE: *mode = atadev->mode; return 0; + + case IOCATAENAPM: + if (*mode < 0 || *mode > 255) + return (EINVAL); + error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_ENAB_APM, 0, *mode); + return error; + + case IOCATADISAPM: + error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_DIS_APM, 0, 0); + return error; + + case IOCATAENAAC: + if (*mode < 0 || *mode > 255) + return (EINVAL); + error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_ENAB_AAC, 0, *mode); + return error; + + case IOCATADISAAC: + error = ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_DIS_AAC, 0, 0); + return error; + default: return ENOTTY; } diff --git a/sys/sys/ata.h b/sys/sys/ata.h index a7e377f..2c251bf 100644 --- a/sys/sys/ata.h +++ b/sys/sys/ata.h @@ -281,6 +281,10 @@ struct ata_params { #define ATA_SF_DIS_RELIRQ 0xdd /* disable release interrupt */ #define ATA_SF_ENAB_SRVIRQ 0x5e /* enable service interrupt */ #define ATA_SF_DIS_SRVIRQ 0xde /* disable service interrupt */ +#define ATA_SF_ENAB_APM 0x05 /* enable APM */ +#define ATA_SF_DIS_APM 0x85 /* disable APM */ +#define ATA_SF_ENAB_AAC 0x42 /* enable Automatic Acoustic Management */ +#define ATA_SF_DIS_AAC 0xc2 /* disable Automatic Acoustic Management */ #define ATA_SECURITY_FREEE_LOCK 0xf5 /* freeze security config */ #define ATA_READ_NATIVE_MAX_ADDDRESS 0xf8 /* read native max address */ #define ATA_SET_MAX_ADDRESS 0xf9 /* set max address */ @@ -432,6 +436,10 @@ struct ata_ioc_request { #define IOCATAGPARM _IOR('a', 101, struct ata_params) #define IOCATAGMODE _IOR('a', 102, int) #define IOCATASMODE _IOW('a', 103, int) +#define IOCATAENAPM _IOW('a', 104, int) +#define IOCATADISAPM _IO('a', 105) +#define IOCATAENAAC _IOW('a', 106, int) +#define IOCATADISAAC _IO('a', 107) struct ata_ioc_raid_config {