Add infrastructure for ATA bus commands, and implement the reset bus command.

This commit is contained in:
bouyer 2004-08-01 21:41:49 +00:00
parent 011181ac3e
commit 502e9c8209
2 changed files with 72 additions and 19 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: atactl.8,v 1.14 2003/12/20 20:03:20 lha Exp $
.\" $NetBSD: atactl.8,v 1.15 2004/08/01 21:41:49 bouyer Exp $
.\"
.\" Copyright (c) 1998 The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -34,12 +34,12 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd December 20, 2003
.Dd August 01, 2004
.Dt ATACTL 8
.Os
.Sh NAME
.Nm atactl
.Nd a program to manipulate ATA (IDE) devices
.Nd a program to manipulate ATA (IDE) devices and busses
.Sh SYNOPSIS
.Nm
.Ar device
@ -51,8 +51,9 @@
.Sh DESCRIPTION
.Nm
allows a user or system administrator to issue commands to and otherwise
control devices which reside on standard IDE and ATA controllers.
It is used by specifying a device to manipulate,
control devices which reside on standard IDE and ATA controllers, or
the ATA bus itself.
It is used by specifying a device or bus to manipulate,
the command to perform, and any arguments the command may require.
.Sh DEVICE COMMANDS
The following commands may be used on IDE and ATA devices.
@ -164,6 +165,15 @@ value is within the acceptable threshold.
.Pp
.Ar selftest-log
Print the selftest log.
.Sh BUS COMMANDS
The following commands may be used on IDE and ATA busses.
Note that not all devices support all commands.
.Pp
.Cm reset
.Pp
Reset the bus.
This will reset all ATA devices present on the bus.
Any ATAPI device with pending commands will also be reset.
.Sh SEE ALSO
.Xr ioctl 2 ,
.Xr wd 4

View File

@ -1,4 +1,4 @@
/* $NetBSD: atactl.c,v 1.29 2004/03/28 01:23:15 mycroft Exp $ */
/* $NetBSD: atactl.c,v 1.30 2004/08/01 21:41:49 bouyer Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -42,7 +42,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: atactl.c,v 1.29 2004/03/28 01:23:15 mycroft Exp $");
__RCSID("$NetBSD: atactl.c,v 1.30 2004/08/01 21:41:49 bouyer Exp $");
#endif
@ -94,9 +94,9 @@ void device_idle(int, char *[]);
void device_checkpower(int, char *[]);
void device_smart(int, char *[]);
void smart_temp(struct ata_smart_attr *, uint64_t);
void device_smart_temp(struct ata_smart_attr *, uint64_t);
struct command commands[] = {
struct command device_commands[] = {
{ "identify", "", device_identify },
{ "setidle", "idle-timer", device_setidle },
{ "setstandby", "standby-timer", device_setidle },
@ -108,6 +108,13 @@ struct command commands[] = {
{ NULL, NULL, NULL },
};
void bus_reset __P((int, char *[]));
struct command bus_commands[] = {
{ "reset", "", bus_reset },
{ NULL, NULL, NULL },
};
/*
* Tables containing bitmasks used for error reporting and
* device identification.
@ -204,7 +211,7 @@ static const struct {
{ 191, "Gsense error rate" },
{ 192, "Power-off retract count" },
{ 193, "Load cycle count" },
{ 194, "Temperature", smart_temp},
{ 194, "Temperature", device_smart_temp},
{ 195, "Hardware ECC Recovered" },
{ 196, "Reallocated event count" },
{ 197, "Current pending sector" },
@ -217,6 +224,7 @@ int
main(int argc, char *argv[])
{
int i;
struct command *commands = NULL;
/* Must have at least: device command */
if (argc < 3)
@ -255,15 +263,26 @@ main(int argc, char *argv[])
dvname = dvname_store;
/* Look up and call the command. */
for (i = 0; commands[i].cmd_name != NULL; i++)
if (strcmp(cmdname, commands[i].cmd_name) == 0)
for (i = 0; device_commands[i].cmd_name != NULL; i++) {
if (strcmp(cmdname, device_commands[i].cmd_name) == 0) {
commands = &device_commands[i];
break;
if (commands[i].cmd_name == NULL)
}
}
if (commands == NULL) {
for (i = 0; bus_commands[i].cmd_name != NULL; i++) {
if (strcmp(cmdname, bus_commands[i].cmd_name) == 0) {
commands = &bus_commands[i];
break;
}
}
}
if (commands == NULL)
errx(1, "unknown command: %s", cmdname);
argnames = commands[i].arg_names;
argnames = commands->arg_names;
(*commands[i].cmd_func)(argc, argv);
(*commands->cmd_func)(argc, argv);
exit(0);
}
@ -276,9 +295,14 @@ usage(void)
getprogname());
fprintf(stderr, " Available device commands:\n");
for (i=0; commands[i].cmd_name != NULL; i++)
fprintf(stderr, "\t%s %s\n", commands[i].cmd_name,
commands[i].arg_names);
for (i=0; device_commands[i].cmd_name != NULL; i++)
fprintf(stderr, "\t%s %s\n", device_commands[i].cmd_name,
device_commands[i].arg_names);
fprintf(stderr, " Available bus commands:\n");
for (i=0; bus_commands[i].cmd_name != NULL; i++)
fprintf(stderr, "\t%s %s\n", bus_commands[i].cmd_name,
bus_commands[i].arg_names);
exit(1);
}
@ -341,7 +365,7 @@ print_bitinfo(const char *bf, const char *af, u_int bits, struct bitinfo *binfo)
*/
void
smart_temp(struct ata_smart_attr *attr, uint64_t raw_value)
device_smart_temp(struct ata_smart_attr *attr, uint64_t raw_value)
{
printf("%" PRIu8, attr->raw[0]);
if (attr->raw[0] != raw_value)
@ -956,3 +980,22 @@ device_smart(int argc, char *argv[])
}
return;
}
/*
* bus_reset:
* Reset an ATA bus (will reset all devices on the bus)
*/
void
bus_reset(int argc, char *argv[])
{
int error;
/* no args */
if (argc != 0)
usage();
error = ioctl(fd, ATABUSIORESET, NULL);
if (error == -1)
err(1, "ATABUSIORESET failed");
}