+2011-05-13 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Give ATA device a bit more time on first try in order to allow disks
+ to spin up.
+
+ * grub-core/disk/ata.c (grub_atapi_identify): Use GRUB_ATA_TOUT_DEV_INIT
+ if dev->present is 1. Reset dev->present on failure.
+ (grub_ata_device_initialize): Set dev->present to 1.
+ * include/grub/ata.h (GRUB_ATA_TOUT_DEV_INIT): New value.
+ (grub_ata_device): New member 'present'.
+
2011-05-13 Vladimir Serbinenko <phcoder@gmail.com>
* util/grub-mkimage.c (generate_image): Update hash.
grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4);
grub_ata_wait ();
- if (grub_ata_check_ready (dev))
+ if ((grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY)
+ && grub_ata_wait_not_busy (dev, dev->present ? GRUB_ATA_TOUT_DEV_INIT
+ : GRUB_ATA_TOUT_STD))
{
grub_free (info);
+ dev->present = 0;
return grub_errno;
}
grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE);
grub_ata_wait ();
- if (grub_ata_wait_drq (dev, 0, GRUB_ATA_TOUT_STD))
+ if (grub_ata_wait_drq (dev, 0, dev->present ? GRUB_ATA_TOUT_DEV_INIT
+ : GRUB_ATA_TOUT_STD))
{
grub_free (info);
+ dev->present = 0;
return grub_errno;
}
grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE);
grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4);
grub_ata_wait ();
- if (grub_ata_check_ready (dev))
+ if ((grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY)
+ && grub_ata_wait_not_busy (dev, dev->present ? GRUB_ATA_TOUT_DEV_INIT
+ : GRUB_ATA_TOUT_STD))
{
+ dev->present = 0;
grub_free (info);
return grub_errno;
}
grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_IDENTIFY_DEVICE);
grub_ata_wait ();
- if (grub_ata_wait_drq (dev, 0, GRUB_ATA_TOUT_STD))
+ if (grub_ata_wait_drq (dev, 0, dev->present ? GRUB_ATA_TOUT_DEV_INIT
+ : GRUB_ATA_TOUT_STD))
{
grub_free (info);
grub_errno = GRUB_ERR_NONE;
return grub_atapi_identify (dev);
else if (sts == 0x00)
- /* No device, return error but don't print message. */
- return GRUB_ERR_UNKNOWN_DEVICE;
-
+ {
+ dev->present = 0;
+ /* No device, return error but don't print message. */
+ return GRUB_ERR_UNKNOWN_DEVICE;
+ }
else
- /* Other Error. */
- return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
- "device cannot be identified");
+ {
+ dev->present = 0;
+ /* Other Error. */
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
+ "device cannot be identified");
+ }
}
grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE);
dev->device = device;
dev->ioaddress = addr + GRUB_MACHINE_PCI_IO_BASE;
dev->ioaddress2 = addr2 + GRUB_MACHINE_PCI_IO_BASE;
+ dev->present = 1;
dev->next = NULL;
/* Register the device. */
enum grub_ata_timeout_milliseconds
{
GRUB_ATA_TOUT_STD = 1000, /* 1s standard timeout. */
- GRUB_ATA_TOUT_DATA = 10000 /* 10s DATA I/O timeout. */
+ GRUB_ATA_TOUT_DATA = 10000, /* 10s DATA I/O timeout. */
+ GRUB_ATA_TOUT_DEV_INIT = 10000, /* Give the device 10s on first try to spinon. */
};
struct grub_ata_device
/* Set to 0 for ATA, set to 1 for ATAPI. */
int atapi;
+ int present;
+
struct grub_ata_device *next;
};