From: Christian Franke <Christian.Franke@t-online.de>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: Re: [PATCH] ata.mod under qemu
Date: Sat, 23 May 2009 23:04:07 +0200 [thread overview]
Message-ID: <4A1864C7.9060606@t-online.de> (raw)
In-Reply-To: <4A15C0C5.6070708@t-online.de>
[-- Attachment #1: Type: text/plain, Size: 461 bytes --]
Christian Franke wrote:
> Pavel Roskin wrote:
>>>
>> It helps detect CD-ROM under qemu. But on the real hardware, it
>> introduces ghost drives.
>>
>> Without the patch, I have (ata7) for the SATA hard drive. With the
>> patch, I have (ata7) for the SATA hard drive, (ata6) for the SATA DVD-RW
>> and two bogus unreadable drives (ata0) and (ata1).
>>
>>
New patch attached. Please test on the above hardware if possible.
--
Regards,
Christian Franke
[-- Attachment #2: grub2-ata-status-fix-2.patch --]
[-- Type: text/x-diff, Size: 4623 bytes --]
diff --git a/disk/ata.c b/disk/ata.c
index ea42d59..5fa0ef5 100644
--- a/disk/ata.c
+++ b/disk/ata.c
@@ -41,11 +41,14 @@ grub_ata_wait_not_busy (struct grub_ata_device *dev, int milliseconds)
grub_millisleep (1);
int i = 1;
- while (grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY)
+ grub_uint8_t sts;
+ while ((sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS))
+ & GRUB_ATA_STATUS_BUSY)
{
if (i >= milliseconds)
{
- grub_dprintf ("ata", "timeout: %dms\n", milliseconds);
+ grub_dprintf ("ata", "timeout: %dms, status=0x%x\n",
+ milliseconds, sts);
return grub_error (GRUB_ERR_TIMEOUT, "ATA timeout");
}
@@ -151,6 +154,7 @@ grub_atapi_identify (struct grub_ata_device *dev)
return grub_errno;
grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4);
+ grub_ata_wait ();
if (grub_ata_check_ready (dev))
{
grub_free (info);
@@ -248,6 +252,7 @@ grub_ata_identify (struct grub_ata_device *dev)
info16 = (grub_uint16_t *) info;
grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4);
+ grub_ata_wait ();
if (grub_ata_check_ready (dev))
{
grub_free (info);
@@ -259,24 +264,38 @@ grub_ata_identify (struct grub_ata_device *dev)
if (grub_ata_wait_drq (dev, 0, GRUB_ATA_TOUT_STD))
{
- if (grub_ata_regget (dev, GRUB_ATA_REG_ERROR) & 0x04) /* ABRT */
- {
- /* Device without ATA IDENTIFY, try ATAPI. */
- grub_free(info);
- grub_errno = GRUB_ERR_NONE;
- return grub_atapi_identify (dev);
- }
+ grub_free(info);
+ grub_errno = GRUB_ERR_NONE;
+ grub_uint8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS);
+
+ if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ
+ | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR
+ && (grub_ata_regget (dev, GRUB_ATA_REG_ERROR) & 0x04 /* ABRT */))
+ /* Device without ATA IDENTIFY, try ATAPI. */
+ return grub_atapi_identify (dev);
+
+ else if (sts == 0x00)
+ /* No device, return error but don't print message. */
+ return GRUB_ERR_UNKNOWN_DEVICE;
+
else
- {
- /* Error. */
- grub_free(info);
- return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
- "device can not be identified");
- }
+ /* Other Error. */
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+ "device can not be identified");
}
grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE);
+ /* Re-check status to avoid bogus identify data due to stuck DRQ. */
+ grub_uint8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS);
+ if (sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
+ {
+ grub_dprintf("ata", "bad status=0x%x", sts);
+ grub_free(info);
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+ "error reading ATA IDENTIFY data");
+ }
+
/* Now it is certain that this is not an ATAPI device. */
dev->atapi = 0;
@@ -334,26 +353,12 @@ grub_ata_device_initialize (int port, int device, int addr, int addr2)
grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4);
grub_ata_wait ();
- /* If status is 0x00, it is safe to assume that there
- is no device (or only a !READY) device connected. */
- grub_int8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS);
- grub_dprintf ("ata", "status=0x%x\n", sts);
- if (sts == 0x00)
- {
- grub_free(dev);
- return 0;
- }
-
/* Try to detect if the port is in use by writing to it,
waiting for a while and reading it again. If the value
- was preserved, there is a device connected.
- But this tests often detects a second (slave) device
- connected to a SATA controller which supports only one
- (master) device. In this case, the status register
- check above usually works. */
+ was preserved, there is a device connected. */
grub_ata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A);
grub_ata_wait ();
- grub_int8_t sec = grub_ata_regget (dev, GRUB_ATA_REG_SECTORS);
+ grub_uint8_t sec = grub_ata_regget (dev, GRUB_ATA_REG_SECTORS);
grub_dprintf ("ata", "sectors=0x%x\n", sec);
if (sec != 0x5A)
{
@@ -361,6 +366,12 @@ grub_ata_device_initialize (int port, int device, int addr, int addr2)
return 0;
}
+ /* The above test may detect a second (slave) device
+ connected to a SATA controller which supports only one
+ (master) device. It is not safe to use the status register
+ READY bit to check for controller channel existence. Some
+ ATAPI commands (RESET, DIAGNOSTIC) may clear this bit. */
+
/* Use the IDENTIFY DEVICE command to query the device. */
if (grub_ata_identify (dev))
{
next prev parent reply other threads:[~2009-05-23 21:04 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-05-18 17:59 [PATCH] ata.mod under qemu Vladimir 'phcoder' Serbinenko
2009-05-18 17:59 ` Vladimir 'phcoder' Serbinenko
2009-05-18 18:04 ` Vladimir 'phcoder' Serbinenko
2009-05-18 23:36 ` Pavel Roskin
2009-05-19 0:17 ` Pavel Roskin
2009-05-19 13:12 ` Christian Franke
2009-05-20 21:40 ` Christian Franke
2009-05-20 22:13 ` Pavel Roskin
2009-05-21 20:59 ` Christian Franke
2009-05-23 21:04 ` Christian Franke [this message]
2009-05-24 7:07 ` Pavel Roskin
2009-05-25 19:47 ` Christian Franke
2009-05-25 20:03 ` Pavel Roskin
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=4A1864C7.9060606@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.