Attached is a patch to enhance atacontrol so that it may control an ATA hard disk's advanced power management (APM) and acoustic management features. The former is typically important with laptop/notebook hard disks where the drives are designed to operate in low power mode by default. For systems where this is not important, it can lead to the drive constantly spinning up-and-down, leading to reduced performance. This feature can also be used to enable power management where it is not enabled by default. Acoustic management functions similarly. Note that /usr/include/sys/ata.h (in the source as sys/sys/ata.h) is modified to include the appropriate symbolic representation of the APM and acoustic feature codes from the ATA specification. Fix: The following patch is uuencoded in order to prevent modification by e-mail servers. It patches the following files: (based in /usr/src) sbin/atacontrol/atacontrol.c sbin/atacontrol/atacontrol.8 sys/sys/ata.h (yes, I really did include the additions to the manpage!!) How-To-Repeat: This is not a bug, so there's nothing to repeat.
The following patch is an update to provide equivalent functionality for FreeBSD 6.0-RELEASE. It would be very helpful to have this in future FreeBSD releases. Thanks. -- Cut Here -- -- Cut Here -- -- Cut Here -- -- Cut Here -- --- sbin/atacontrol/atacontrol.c.ORIG Sun Aug 7 06:16:58 2005 +++ sbin/atacontrol/atacontrol.c Mon Jan 16 02:00:12 2006 @@ -108,6 +108,8 @@ " atacontrol rebuild array\n" " atacontrol status array\n" " atacontrol mode device [mode]\n" + " atacontrol feature device apm apmlevel\n" + " atacontrol feature device acoustic soundsupplevel\n" " atacontrol cap device\n" ); exit(EX_USAGE); @@ -319,6 +321,88 @@ err(1, "ioctl(IOCATAGMODE)"); printf("current mode = %s\n", mode2str(mode)); } + exit(EX_OK); + } + if (!strcmp(argv[1], "feature") && argc == 5) { + int disk; + char device[64]; + struct ata_ioc_request request; + + 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"); + + bzero(&request, sizeof(struct ata_ioc_request)); + request.u.ata.command = ATA_SETFEATURES; + request.flags = ATA_CMD_CONTROL; + request.timeout = 500; + if (!strcmp(argv[3], "apm")) { + if (!strcmp(argv[4], "off")) { + request.u.ata.feature = ATA_SF_DIS_APM; + } + else if (!strcmp(argv[4], "maxperf")) { + request.u.ata.feature = ATA_SF_ENAB_APM; + request.u.ata.count = 0xfe; + } + else if (!strcmp(argv[4], "minpower")) { + request.u.ata.feature = ATA_SF_ENAB_APM; + request.u.ata.count = 0x01; + } + else { + int offset = 0; + + request.u.ata.feature = ATA_SF_ENAB_APM; + if (argv[4][0] == 's') { + offset = atoi(&argv[4][1]); + request.u.ata.count = 0x01; + } else { + offset = atoi(&argv[4][1]); + request.u.ata.count = 0x80; + } + if (offset >= 0 && offset <= 127) + request.u.ata.count += offset; + } + } + else if (!strcmp(argv[3], "acoustic")) { + if (!strcmp(argv[4], "off")) { + request.u.ata.feature = ATA_SF_DIS_ACCOUS; + } + else if (!strcmp(argv[4], "maxperf")) { + request.u.ata.feature = ATA_SF_ENAB_ACCOUS; + request.u.ata.count = 0xfe; + } + else if (!strcmp(argv[4], "maxquiet")) { + request.u.ata.feature = ATA_SF_ENAB_ACCOUS; + request.u.ata.count = 0x80; + } + else { + request.u.ata.feature = ATA_SF_ENAB_ACCOUS; + request.u.ata.count = atoi(argv[4]); + if (request.u.ata.count > 124) + request.u.ata.count = 124; + } + } + else + usage(); + + if (ioctl(fd, IOCATAREQUEST, &request) < 0) + err(1, "ioctl(IOCATAREQUEST)"); + + if (request.error != 0) { + fprintf(stderr, + "IOCATAREQUEST returned err status %d", + request.error); + exit(EX_IOERR); + } + exit(EX_OK); } if (!strcmp(argv[1], "cap") && argc == 3) { --- sbin/atacontrol/atacontrol.8.ORIG Fri Aug 19 10:54:42 2005 +++ sbin/atacontrol/atacontrol.8 Mon Jan 16 02:09:05 2006 @@ -64,6 +64,16 @@ .Ic mode .Ar device .Nm +.Ic feature +.Ar device +.Ic apm +.Ar apmlevel +.Nm +.Ic feature +.Ar device +.Ic acoustic +.Ar soundsupplevel +.Nm .Ic info .Ar channel .Nm @@ -187,6 +197,44 @@ (alias .Cm UDMA133 ) . The device name and manufacture/version strings are shown. +.It Ic feature / apm +Set disk drive Advanced Power Management (APM) level. +This command is generally used on laptop (notebook) hard disks to control +the power level consumed by the drive (at the expense of performance). +.Pp +The +.Ar apmlevel +may be set to one of: +.Cm off +(turn off APM), +.Cm maxperf +or +.Cm minpower +(optimize for maximum performance or minimum power, respectively), or +a numeric level which can be 0 to 127 inclusive indicating an increasing +level of performance over power savings. +The numeric levels may be prefixed by +.Cm s +which will allow the drive to include suspension as part of the +power savings. Note that not all hard drives will support the +.Cm off +command, and that the number of incremental power savings levels +do not typically have as wide of a range as this command will +support. +.It Ic feature / acoustic +Control disk drive Acoustic Management level. The +.Ar soundsupplevel +may be set to +.Cm off +which will turn off acoustic management, +.Cm maxperf +to optimize for maximum performance, +.Cm maxquiet +to optimize for maximum quiet, or a numeric level +from 0 to 124. The higher the numeric level, the higher the +theoretical sound level emitted from the drive. Note that few +devices support this command and even fewer will allow the +range of levels supported. .It Ic cap Show detailed info about the device on .Ar device . -- Cut Here -- -- Cut Here -- -- Cut Here -- -- Cut Here --
Oops...this is also required for the FreeBSD 6.0 patch above. It is the required change to /usr/include/sys/ata.h that provides the ATA codes for APM and acoustic management. -- Cut Here -- -- Cut Here -- -- Cut Here -- -- Cut Here -- -- Cut Here -- --- usr/include/sys/ata.h.ORIG Thu Nov 3 02:09:29 2005 +++ usr/include/sys/ata.h Mon Jan 16 01:06:47 2006 @@ -267,6 +267,10 @@ #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 adv power mgmt */ +#define ATA_SF_DIS_APM 0x85 /* disable adv power mgmt */ +#define ATA_SF_ENAB_ACCOUS 0x42 /* enable acoustic mgmt */ +#define ATA_SF_DIS_ACCOUS 0xc2 /* disable acoustic mgmt */ #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 */ -- Cut Here -- -- Cut Here -- -- Cut Here -- -- Cut Here -- -- Cut Here --
Responsible Changed From-To: freebsd-bugs->sos Over to maintainer.
Responsible Changed From-To: sos->freebsd-bugs sos@ is not actively working on ATA-related PRs.
State Changed From-To: open->suspended Work on the ATA subsytem has been suspended, because eventually it will get replaced by CAM.
ata(4) is no more on 9.x+. Long live atacam(4).