From: Christian Franke <Christian.Franke@t-online.de>
To: grub-devel@gnu.org
Subject: [PATCH] hdparm.mod - get/set ATA disk parameters
Date: Sat, 24 Jan 2009 23:59:01 +0100 [thread overview]
Message-ID: <497B9D35.5010703@t-online.de> (raw)
[-- Attachment #1: Type: text/plain, Size: 1564 bytes --]
This patch adds a command which allows to change a few (S)ATA drive
settings. It relies on a new pass-through function in ata.mod.
Command name and option syntax are borrowed from the well-known Linux tool.
Examples:
- Set AAM of system drive to "fast", other drive to "quiet":
hdparm -S 254 (ata0)
hdparm -S 128 (ata1)
- Change APM level
(reportedly useful to avoid clicking noise of some Notebook disks):
hdparm -B 254 (ata0)
- Set standby timeout to 10min
(e.g. if disk is likely not used in the selected boot configuration):
hdparm -S 120 (ata0)
- Set disk to standby or sleep mode (e.g. before running a long memtest):
hdparm -y (ata0)
hdparm -Y (ata0)
- Freeze security settings (some BIOS don't):
hdparm -F (ata0)
Thanks for any comment.
Christian
2009-01-24 Christian Franke <franke@computer.org>
* commands/hdparm.c: New file. Provides `hdparm' command
which sends ATA commands via grub_ata_pass_through.
* conf/i386-pc.rmk: Add hdparm.mod.
* disk/ata.c: Include <grub/ata.h>.
(GRUB_CDROM_SECTOR_SIZE): Remove.
(GRUB_ATA_*): Move to include/grub/ata.h.
(GRUB_ATAPI_*): Likewise.
(enum grub_ata_commands): Likewise.
(grub_ata_pass_through): New function.
(GRUB_MOD_INIT): Set grub_disk_ata_pass_through pointer.
(GRUB_MOD_FINI): Reset grub_disk_ata_pass_through pointer.
* include/grub/ata.h: New file, contains declarations from ata.c.
* include/grub/disk.h (grub_disk_ata_pass_through_parms): New struct.
(grub_disk_ata_pass_through): New exported variable.
* kern/disk.c (grub_disk_ata_pass_through): New variable.
[-- Attachment #2: grub2-hdparm-mod.patch --]
[-- Type: text/x-diff, Size: 20211 bytes --]
diff --git a/commands/hdparm.c b/commands/hdparm.c
new file mode 100644
index 0000000..e829ced
--- /dev/null
+++ b/commands/hdparm.c
@@ -0,0 +1,340 @@
+/* hdparm.c - command to get/set ATA disk parameters. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/arg.h>
+#include <grub/ata.h>
+#include <grub/disk.h>
+#include <grub/dl.h>
+#include <grub/misc.h>
+#include <grub/normal.h>
+#include <grub/mm.h>
+#include <grub/lib/hexdump.h>
+
+
+static const struct grub_arg_option options[] = {
+ {"apm", 'B', 0, "Set Advanced Power Management\n"
+ "(1=low, ..., 254=high, 255=off)",
+ 0, ARG_TYPE_INT},
+ {"power", 'C', 0, "Check power mode", 0, ARG_TYPE_NONE},
+ {"security-freeze", 'F', 0, "Freeze ATA security settings until reset",
+ 0, ARG_TYPE_NONE},
+ {"aam", 'M', 0, "Set Automatic Acoustic Management\n"
+ "(0=off, 128=quiet, ..., 254=fast)",
+ 0, ARG_TYPE_INT},
+ {"standby-timeout", 'S', 0, "Set standby timeout\n"
+ "(0=off, 1=5s, 2=10s, ..., 240=20m, 241=30m, ...)",
+ 0, ARG_TYPE_INT},
+ {"standby", 'y', 0, "Set drive to standby mode", 0, ARG_TYPE_NONE},
+ {"sleep", 'Y', 0, "Set drive to sleep mode", 0, ARG_TYPE_NONE},
+ {"identify", 'i', 0, "Print drive identity and settings",
+ 0, ARG_TYPE_NONE},
+ {"dumpid", 'I', 0, "Dump contents of ATA IDENTIFY sector",
+ 0, ARG_TYPE_NONE},
+ {"quiet", 'q', 0, "Do not print messages", 0, ARG_TYPE_NONE},
+ {0, 0, 0, 0, 0, 0}
+};
+
+static int quiet = 0;
+
+static grub_err_t
+grub_hdparm_do_ata_cmd (grub_disk_t disk, grub_uint8_t cmd,
+ grub_uint8_t features, grub_uint8_t sectors,
+ grub_uint8_t *ret_sectors,
+ void * buffer, int size)
+{
+ struct grub_disk_ata_pass_through_parms apt;
+ grub_memset (&apt, 0, sizeof (apt));
+
+ apt.taskfile[GRUB_ATA_REG_CMD] = cmd;
+ apt.taskfile[GRUB_ATA_REG_FEATURES] = features;
+ apt.taskfile[GRUB_ATA_REG_SECTORS] = sectors;
+ apt.buffer = buffer;
+ apt.size = size;
+
+ if (grub_disk_ata_pass_through (disk, &apt))
+ return grub_errno;
+
+ if (ret_sectors)
+ *ret_sectors = apt.taskfile[GRUB_ATA_REG_SECTORS];
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_hdparm_simple_cmd (const char * msg,
+ grub_disk_t disk, grub_uint8_t cmd)
+{
+ if (! quiet && msg)
+ grub_printf ("%s", msg);
+
+ grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, 0, 0, NULL, NULL, 0);
+
+ if (! quiet && msg)
+ grub_printf ("%s\n", ! err ? "" : ": not supported");
+ return err;
+}
+
+static grub_err_t
+grub_hdparm_set_val_cmd (const char * msg, int val,
+ grub_disk_t disk, grub_uint8_t cmd,
+ grub_uint8_t features, grub_uint8_t sectors)
+{
+ if (! quiet && msg && *msg)
+ {
+ if (val >= 0)
+ grub_printf ("Set %s to %d", msg, val);
+ else
+ grub_printf ("Disable %s", msg);
+ }
+
+ grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, features, sectors,
+ NULL, NULL, 0);
+
+ if (! quiet && msg)
+ grub_printf ("%s\n", ! err ? "" : ": not supported");
+ return err;
+}
+
+static const char *
+le16_to_char (char *dest, const grub_uint16_t * src16, unsigned bytes)
+{
+ grub_uint16_t * dest16 = (grub_uint16_t *) dest;
+ unsigned i;
+ for (i = 0; i < bytes / 2; i++)
+ dest16[i] = grub_be_to_cpu16 (src16[i]);
+ return dest;
+}
+
+static void
+grub_hdparm_print_identify (const char * idbuf)
+{
+ const grub_uint16_t * idw = (const grub_uint16_t *) idbuf;
+
+ /* Print identity strings. */
+ char tmp[40];
+ grub_printf ("Model: \"%.40s\"\n", le16_to_char (tmp, &idw[27], 40));
+ grub_printf ("Firmware: \"%.8s\"\n", le16_to_char (tmp, &idw[23], 8));
+ grub_printf ("Serial: \"%.20s\"\n", le16_to_char (tmp, &idw[10], 20));
+
+ /* Print AAM and APM settings. */
+ grub_uint16_t features = grub_le_to_cpu16 (idw[83]);
+ grub_uint16_t enabled = grub_le_to_cpu16 (idw[86]);
+
+ grub_printf("Automatic Acoustic Management: ");
+ if (features & 0x0200)
+ {
+ if (enabled & 0x0200)
+ {
+ grub_uint16_t aam = grub_le_to_cpu16 (idw[94]);
+ grub_printf("%u (128=quiet, ..., 254=fast, recommended=%u)\n",
+ aam & 0xff, (aam >> 8) & 0xff);
+ }
+ else
+ grub_printf("disabled\n");
+ }
+ else
+ grub_printf("not supported\n");
+
+ grub_printf("Advanced Power Management: ");
+ if (features & 0x0008)
+ {
+ if (enabled & 0x0008)
+ grub_printf ("%u (1=low, ..., 254=high)\n",
+ grub_le_to_cpu16 (idw[91]) & 0xff);
+ else
+ grub_printf ("disabled\n");
+ }
+ else
+ grub_printf ("not supported\n");
+
+ /* Print security settings. */
+ grub_uint16_t security = grub_le_to_cpu16 (idw[128]);
+
+ grub_printf("ATA Security: ");
+ if (security & 0x0001)
+ grub_printf ("%s, %s, %s, %s\n",
+ (security & 0x0002 ? "ENABLED" : "disabled"),
+ (security & 0x0004 ? "**LOCKED**" : "not locked"),
+ (security & 0x0008 ? "frozen" : "NOT FROZEN"),
+ (security & 0x0010 ? "COUNT EXPIRED" : "count not expired"));
+ else
+ grub_printf ("no supported\n");
+}
+
+static void
+grub_hdparm_print_standby_tout (int timeout)
+{
+ if (timeout == 0)
+ grub_printf ("off");
+ else if (timeout <= 252 || timeout == 255)
+ {
+ int h = 0, m = 0 , s = 0;
+ if (timeout == 255)
+ {
+ m = 21;
+ s = 15;
+ }
+ else if (timeout == 252)
+ m = 21;
+ else if (timeout <= 240)
+ {
+ s = timeout * 5;
+ m = s / 60;
+ s %= 60;
+ }
+ else
+ {
+ m = (timeout - 240) * 30;
+ h = m / 60;
+ m %= 60;
+ }
+ grub_printf("%02d:%02d:%02d", h, m, s);
+ }
+ else
+ grub_printf("invalid or vendor-specific");
+}
+
+static int get_int_arg (const struct grub_arg_list *state)
+{
+ return (state->set ? (int)grub_strtoul (state->arg, 0, 0) : -1);
+}
+
+
+static grub_err_t
+grub_cmd_hdparm (struct grub_arg_list *state, int argc, char **args) // state????
+{
+ /* Check command line. */
+ if (argc != 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing device name argument");
+
+ grub_size_t len = grub_strlen (args[0]);
+ if (! (args[0][0] == '(' && args[0][len - 1] == ')'))
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "argument is not a device name");
+ args[0][len - 1] = 0;
+
+ if (! grub_disk_ata_pass_through)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "ATA pass through not available");
+
+ int i = 0;
+ int apm = get_int_arg (&state[i++]);
+ int power = state[i++].set;
+ int sec_freeze = state[i++].set;
+ int aam = get_int_arg (&state[i++]);
+ int standby_tout = get_int_arg (&state[i++]);
+ int standby_now = state[i++].set;
+ int sleep_now = state[i++].set;
+ int ident = state[i++].set;
+ int dumpid = state[i++].set;
+ quiet = state[i++].set;
+
+ /* Open disk. */
+ grub_disk_t disk = grub_disk_open (&args[0][1]);
+ if (! disk)
+ return grub_errno;
+
+ if (disk->partition)
+ {
+ grub_disk_close (disk);
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "partition not allowed");
+ }
+
+ /* Change settings. */
+ if (aam >= 0)
+ grub_hdparm_set_val_cmd ("Automatic Acoustic Management", (aam ? aam : -1),
+ disk, GRUB_ATA_CMD_SET_FEATURES, (aam ? 0x42 : 0xc2), aam);
+
+ if (apm >= 0)
+ grub_hdparm_set_val_cmd ("Advanced Power Management",
+ (apm != 255 ? apm : -1), disk, GRUB_ATA_CMD_SET_FEATURES,
+ (apm != 255 ? 0x05 : 0x85), (apm != 255 ? apm : 0));
+
+ if (standby_tout >= 0)
+ {
+ if (! quiet)
+ {
+ grub_printf ("Set standby timeout to %d (", standby_tout);
+ grub_hdparm_print_standby_tout (standby_tout);
+ grub_printf (")");
+ }
+ /* The IDLE cmd sets disk to idle mode and configures standby timer. */
+ grub_hdparm_set_val_cmd ("", -1, disk, GRUB_ATA_CMD_IDLE, 0, standby_tout);
+ }
+
+ if (sec_freeze)
+ grub_hdparm_simple_cmd ("Freeze security settings", disk,
+ GRUB_ATA_CMD_SECURITY_FREEZE_LOCK);
+
+ /* Print/dump IDENTIFY. */
+ if (ident || dumpid)
+ {
+ char buf[GRUB_DISK_SECTOR_SIZE];
+ if (grub_hdparm_do_ata_cmd (disk, GRUB_ATA_CMD_IDENTIFY_DEVICE,
+ 0, 0, NULL, buf, sizeof(buf)))
+ grub_printf("Cannot read ATA IDENTIFY data\n");
+ else
+ {
+ if (ident)
+ grub_hdparm_print_identify (buf);
+ if (dumpid)
+ hexdump (0, buf, sizeof(buf));
+ }
+ }
+
+ /* Check power mode. */
+ if (power)
+ {
+ grub_printf("Disk power mode is ");
+ grub_uint8_t mode = 0;
+ if (grub_hdparm_do_ata_cmd (disk, GRUB_ATA_CMD_CHECK_POWER_MODE,
+ 0, 0, &mode, NULL, 0))
+ grub_printf ("unknown\n");
+ else
+ grub_printf ("%s (0x%02x)\n",
+ (mode == 0xff ? "active/idle" :
+ mode == 0x80 ? "idle" :
+ mode == 0x00 ? "standby" : "unknown"), mode);
+ }
+
+ /* Change power mode. */
+ if (standby_now)
+ grub_hdparm_simple_cmd ("Set disk to standby mode", disk,
+ GRUB_ATA_CMD_STANDBY_IMMEDIATE);
+
+ if (sleep_now)
+ grub_hdparm_simple_cmd ("Set disk to sleep mode", disk,
+ GRUB_ATA_CMD_SLEEP);
+
+ grub_disk_close (disk);
+ grub_errno = GRUB_ERR_NONE;
+ return 0;
+}
+
+
+GRUB_MOD_INIT(hdparm)
+{
+ (void) mod;
+
+ grub_register_command ("hdparm", grub_cmd_hdparm, GRUB_COMMAND_FLAG_BOTH,
+ "hdparm [OPTIONS] DISK",
+ "Get/set ATA disk parameters.", options);
+}
+
+GRUB_MOD_FINI(hdparm)
+{
+ grub_unregister_command ("hdparm");
+}
diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk
index 0998252..a7d652c 100644
--- a/conf/i386-pc.rmk
+++ b/conf/i386-pc.rmk
@@ -164,7 +164,7 @@ pkglib_MODULES = biosdisk.mod _chain.mod _linux.mod linux.mod normal.mod \
vbe.mod vbetest.mod vbeinfo.mod play.mod serial.mod \
ata.mod vga.mod memdisk.mod pci.mod lspci.mod \
aout.mod _bsd.mod bsd.mod pxe.mod pxecmd.mod datetime.mod date.mod \
- datehook.mod lsmmap.mod
+ datehook.mod lsmmap.mod hdparm.mod
# For biosdisk.mod.
biosdisk_mod_SOURCES = disk/i386/pc/biosdisk.c
@@ -321,5 +321,10 @@ lsmmap_mod_SOURCES = commands/lsmmap.c
lsmmap_mod_CFLAGS = $(COMMON_CFLAGS)
lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For hdparm.mod.
+hdparm_mod_SOURCES = commands/hdparm.c lib/hexdump.c
+hdparm_mod_CFLAGS = $(COMMON_CFLAGS)
+hdparm_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
include $(srcdir)/conf/i386.mk
include $(srcdir)/conf/common.mk
diff --git a/disk/.ata.c.swp b/disk/.ata.c.swp
new file mode 100644
index 0000000..96cc004
Binary files /dev/null and b/disk/.ata.c.swp differ
diff --git a/disk/ata.c b/disk/ata.c
index e981fe9..6dd417f 100644
--- a/disk/ata.c
+++ b/disk/ata.c
@@ -1,7 +1,7 @@
/* ata.c - ATA disk access. */
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+ * Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,6 +17,7 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <grub/ata.h>
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/disk.h>
@@ -38,54 +39,6 @@ typedef enum
static const int grub_ata_ioaddress[] = { 0x1f0, 0x170 };
static const int grub_ata_ioaddress2[] = { 0x3f6, 0x376 };
-#define GRUB_CDROM_SECTOR_SIZE 2048
-
-#define GRUB_ATA_REG_DATA 0
-#define GRUB_ATA_REG_ERROR 1
-#define GRUB_ATA_REG_FEATURES 1
-#define GRUB_ATA_REG_SECTORS 2
-#define GRUB_ATAPI_REG_IREASON 2
-#define GRUB_ATA_REG_SECTNUM 3
-#define GRUB_ATA_REG_CYLLSB 4
-#define GRUB_ATA_REG_CYLMSB 5
-#define GRUB_ATA_REG_LBALOW 3
-#define GRUB_ATA_REG_LBAMID 4
-#define GRUB_ATAPI_REG_CNTLOW 4
-#define GRUB_ATA_REG_LBAHIGH 5
-#define GRUB_ATAPI_REG_CNTHIGH 5
-#define GRUB_ATA_REG_DISK 6
-#define GRUB_ATA_REG_CMD 7
-#define GRUB_ATA_REG_STATUS 7
-
-#define GRUB_ATA_REG2_CONTROL 0
-
-#define GRUB_ATA_STATUS_ERR 0x01
-#define GRUB_ATA_STATUS_INDEX 0x02
-#define GRUB_ATA_STATUS_ECC 0x04
-#define GRUB_ATA_STATUS_DRQ 0x08
-#define GRUB_ATA_STATUS_SEEK 0x10
-#define GRUB_ATA_STATUS_WRERR 0x20
-#define GRUB_ATA_STATUS_READY 0x40
-#define GRUB_ATA_STATUS_BUSY 0x80
-
-/* ATAPI interrupt reason values (I/O, D/C bits). */
-#define GRUB_ATAPI_IREASON_MASK 0x3
-#define GRUB_ATAPI_IREASON_DATA_OUT 0x0
-#define GRUB_ATAPI_IREASON_CMD_OUT 0x1
-#define GRUB_ATAPI_IREASON_DATA_IN 0x2
-#define GRUB_ATAPI_IREASON_ERROR 0x3
-
-enum grub_ata_commands
- {
- GRUB_ATA_CMD_READ_SECTORS = 0x20,
- GRUB_ATA_CMD_READ_SECTORS_EXT = 0x24,
- GRUB_ATA_CMD_WRITE_SECTORS = 0x30,
- GRUB_ATA_CMD_WRITE_SECTORS_EXT = 0x34,
- GRUB_ATA_CMD_IDENTIFY_DEVICE = 0xEC,
- GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE = 0xA1,
- GRUB_ATA_CMD_PACKET = 0xA0,
- };
-
enum grub_ata_timeout_milliseconds
{
GRUB_ATA_TOUT_STD = 1000, /* 1s standard timeout. */
@@ -962,6 +915,67 @@ static struct grub_scsi_dev grub_atapi_dev =
.write = grub_atapi_write
};
+/* ATA pass through support, used by hdparm.mod. */
+static grub_err_t
+grub_ata_pass_through (grub_disk_t disk,
+ struct grub_disk_ata_pass_through_parms *parms)
+{
+ if (disk->dev->id != GRUB_DISK_DEVICE_ATA_ID)
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ "Device not accessed via ata.mod");
+
+ struct grub_ata_device *dev = (struct grub_ata_device *) disk->data;
+
+ if (! (parms->size == 0 || parms->size == GRUB_DISK_SECTOR_SIZE))
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ "ATA multi-sector read and DATA OUT not implemented");
+
+ grub_dprintf("ata", "ata_pass_through: cmd=0x%x, features=0x%x, sectors=0x%x, size=%d\n",
+ parms->taskfile[GRUB_ATA_REG_CMD], parms->taskfile[GRUB_ATA_REG_FEATURES],
+ parms->taskfile[GRUB_ATA_REG_SECTORS], parms->size);
+
+ /* Set registers. */
+ grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4
+ | (parms->taskfile[GRUB_ATA_REG_DISK] & 0xf));
+ if (grub_ata_check_ready (dev))
+ return grub_errno;
+
+ int i;
+ for (i = GRUB_ATA_REG_FEATURES; i <= GRUB_ATA_REG_LBAHIGH; i++)
+ grub_ata_regset (dev, i, parms->taskfile[i]);
+
+ /* Start command. */
+ grub_ata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile[GRUB_ATA_REG_CMD]);
+
+ /* Wait for !BSY. */
+ if (grub_ata_wait_not_busy(dev, GRUB_ATA_TOUT_DATA))
+ return grub_errno;
+
+ /* Check status. */
+ grub_int8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS);
+ grub_dprintf("ata", "status=%x\n", sts);
+
+ /* Transfer data. */
+ if ((sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_DRQ)
+ {
+ if (parms->size != GRUB_DISK_SECTOR_SIZE)
+ return grub_error (GRUB_ERR_READ_ERROR, "DRQ unexpected");
+ grub_ata_pio_read (dev, parms->buffer, GRUB_DISK_SECTOR_SIZE);
+ }
+
+ /* Return registers. */
+ for (i = GRUB_ATA_REG_ERROR; i <= GRUB_ATA_REG_STATUS; i++)
+ parms->taskfile[i] = grub_ata_regget (dev, i);
+
+ grub_dprintf("ata", "status=%x, error=%x\n", sts,
+ parms->taskfile[GRUB_ATA_REG_ERROR]);
+
+ if (parms->taskfile[GRUB_ATA_REG_STATUS] & (GRUB_ATA_STATUS_DRQ|GRUB_ATA_STATUS_ERR))
+ return grub_error (GRUB_ERR_READ_ERROR, "ATA passthrough failed");
+
+ return GRUB_ERR_NONE;
+}
+
\f
GRUB_MOD_INIT(ata)
@@ -983,10 +997,16 @@ GRUB_MOD_INIT(ata)
/* ATAPI devices are handled by scsi.mod. */
grub_scsi_dev_register (&grub_atapi_dev);
+
+ /* Register ATA pass through function. */
+ grub_disk_ata_pass_through = grub_ata_pass_through;
}
GRUB_MOD_FINI(ata)
{
+ if (grub_disk_ata_pass_through == grub_ata_pass_through)
+ grub_disk_ata_pass_through = NULL;
+
grub_scsi_dev_unregister (&grub_atapi_dev);
grub_disk_dev_unregister (&grub_atadisk_dev);
}
diff --git a/include/grub/ata.h b/include/grub/ata.h
new file mode 100644
index 0000000..f4c5d5b
--- /dev/null
+++ b/include/grub/ata.h
@@ -0,0 +1,76 @@
+/* ata.h - ATA disk access. */
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef GRUB_ATA_H
+#define GRUB_ATA_H
+
+#define GRUB_ATA_REG_DATA 0
+#define GRUB_ATA_REG_ERROR 1
+#define GRUB_ATA_REG_FEATURES 1
+#define GRUB_ATA_REG_SECTORS 2
+#define GRUB_ATAPI_REG_IREASON 2
+#define GRUB_ATA_REG_SECTNUM 3
+#define GRUB_ATA_REG_CYLLSB 4
+#define GRUB_ATA_REG_CYLMSB 5
+#define GRUB_ATA_REG_LBALOW 3
+#define GRUB_ATA_REG_LBAMID 4
+#define GRUB_ATAPI_REG_CNTLOW 4
+#define GRUB_ATA_REG_LBAHIGH 5
+#define GRUB_ATAPI_REG_CNTHIGH 5
+#define GRUB_ATA_REG_DISK 6
+#define GRUB_ATA_REG_CMD 7
+#define GRUB_ATA_REG_STATUS 7
+
+#define GRUB_ATA_REG2_CONTROL 0
+
+#define GRUB_ATA_STATUS_ERR 0x01
+#define GRUB_ATA_STATUS_INDEX 0x02
+#define GRUB_ATA_STATUS_ECC 0x04
+#define GRUB_ATA_STATUS_DRQ 0x08
+#define GRUB_ATA_STATUS_SEEK 0x10
+#define GRUB_ATA_STATUS_WRERR 0x20
+#define GRUB_ATA_STATUS_READY 0x40
+#define GRUB_ATA_STATUS_BUSY 0x80
+
+/* ATAPI interrupt reason values (I/O, D/C bits). */
+#define GRUB_ATAPI_IREASON_MASK 0x3
+#define GRUB_ATAPI_IREASON_DATA_OUT 0x0
+#define GRUB_ATAPI_IREASON_CMD_OUT 0x1
+#define GRUB_ATAPI_IREASON_DATA_IN 0x2
+#define GRUB_ATAPI_IREASON_ERROR 0x3
+
+enum grub_ata_commands
+{
+ GRUB_ATA_CMD_CHECK_POWER_MODE = 0xe5,
+ GRUB_ATA_CMD_IDENTIFY_DEVICE = 0xec,
+ GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE = 0xa1,
+ GRUB_ATA_CMD_IDLE = 0xe3,
+ GRUB_ATA_CMD_PACKET = 0xa0,
+ GRUB_ATA_CMD_READ_SECTORS = 0x20,
+ GRUB_ATA_CMD_READ_SECTORS_EXT = 0x24,
+ GRUB_ATA_CMD_SECURITY_FREEZE_LOCK = 0xf5,
+ GRUB_ATA_CMD_SET_FEATURES = 0xef,
+ GRUB_ATA_CMD_SLEEP = 0xe6,
+ GRUB_ATA_CMD_STANDBY_IMMEDIATE = 0xe0,
+ GRUB_ATA_CMD_WRITE_SECTORS = 0x30,
+ GRUB_ATA_CMD_WRITE_SECTORS_EXT = 0x34,
+};
+
+#endif /* ! GRUB_ATA_H */
diff --git a/include/grub/disk.h b/include/grub/disk.h
index f2fa421..1e8046a 100644
--- a/include/grub/disk.h
+++ b/include/grub/disk.h
@@ -161,6 +161,17 @@ grub_uint64_t EXPORT_FUNC(grub_disk_get_size) (grub_disk_t disk);
extern void (* EXPORT_VAR(grub_disk_firmware_fini)) (void);
extern int EXPORT_VAR(grub_disk_firmware_is_tainted);
+/* ATA pass through parameters and function. */
+struct grub_disk_ata_pass_through_parms
+{
+ grub_uint8_t taskfile[8];
+ void * buffer;
+ int size;
+};
+
+extern grub_err_t (* EXPORT_VAR(grub_disk_ata_pass_through)) (grub_disk_t,
+ struct grub_disk_ata_pass_through_parms *);
+
#ifdef GRUB_UTIL
void grub_raid_init (void);
void grub_raid_fini (void);
diff --git a/kern/disk.c b/kern/disk.c
index ed82506..3f7e451 100644
--- a/kern/disk.c
+++ b/kern/disk.c
@@ -46,6 +46,10 @@ static struct grub_disk_cache grub_disk_cache_table[GRUB_DISK_CACHE_NUM];
void (*grub_disk_firmware_fini) (void);
int grub_disk_firmware_is_tainted;
+grub_err_t (* grub_disk_ata_pass_through) (grub_disk_t,
+ struct grub_ata_pass_through_cmd *);
+
+
#if 0
static unsigned long grub_disk_cache_hits;
static unsigned long grub_disk_cache_misses;
next reply other threads:[~2009-01-24 22:59 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-24 22:59 Christian Franke [this message]
2009-02-07 21:38 ` [PATCH] hdparm.mod - get/set ATA disk parameters Robert Millan
2009-02-07 22:46 ` Christian Franke
2009-02-07 22:59 ` Robert Millan
2009-02-07 23:12 ` Christian Franke
2009-02-08 0:32 ` Robert Millan
2009-02-09 19:42 ` Christian Franke
2009-02-12 22:21 ` Christian Franke
2009-02-14 14:13 ` Christian Franke
2009-02-21 13:05 ` Robert Millan
2009-02-21 18:00 ` Christian Franke
2009-02-21 19:51 ` Robert Millan
2009-02-21 20:38 ` Christian Franke
2009-02-21 20:46 ` Robert Millan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=497B9D35.5010703@t-online.de \
--to=christian.franke@t-online.de \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.