Handle defered device registration
This commit is contained in:
parent
5dbb0fc055
commit
9b6e10bbbf
1 changed files with 63 additions and 29 deletions
92
disk/ata.c
92
disk/ata.c
|
@ -332,11 +332,38 @@ grub_ata_identify (struct grub_ata_device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
check_device (struct grub_ata_device *dev)
|
||||||
|
{
|
||||||
|
grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4);
|
||||||
|
grub_ata_wait ();
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
grub_ata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A);
|
||||||
|
grub_ata_wait ();
|
||||||
|
grub_uint8_t sec = grub_ata_regget (dev, GRUB_ATA_REG_SECTORS);
|
||||||
|
grub_dprintf ("ata", "sectors=0x%x\n", sec);
|
||||||
|
if (sec != 0x5A)
|
||||||
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no device connected");
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
return grub_ata_identify (dev);
|
||||||
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_ata_device_initialize (int port, int device, int addr, int addr2)
|
grub_ata_device_initialize (int port, int device, int addr, int addr2)
|
||||||
{
|
{
|
||||||
struct grub_ata_device *dev;
|
struct grub_ata_device *dev;
|
||||||
struct grub_ata_device **devp;
|
struct grub_ata_device **devp;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
grub_dprintf ("ata", "detecting device %d,%d (0x%x, 0x%x)\n",
|
grub_dprintf ("ata", "detecting device %d,%d (0x%x, 0x%x)\n",
|
||||||
port, device, addr, addr2);
|
port, device, addr, addr2);
|
||||||
|
@ -352,39 +379,14 @@ grub_ata_device_initialize (int port, int device, int addr, int addr2)
|
||||||
dev->ioaddress2 = addr2 + GRUB_MACHINE_PCI_IO_BASE;
|
dev->ioaddress2 = addr2 + GRUB_MACHINE_PCI_IO_BASE;
|
||||||
dev->next = NULL;
|
dev->next = NULL;
|
||||||
|
|
||||||
grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4);
|
|
||||||
grub_ata_wait ();
|
|
||||||
|
|
||||||
/* 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. */
|
|
||||||
grub_ata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A);
|
|
||||||
grub_ata_wait ();
|
|
||||||
grub_uint8_t sec = grub_ata_regget (dev, GRUB_ATA_REG_SECTORS);
|
|
||||||
grub_dprintf ("ata", "sectors=0x%x\n", sec);
|
|
||||||
if (sec != 0x5A)
|
|
||||||
{
|
|
||||||
grub_free(dev);
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
grub_free (dev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register the device. */
|
/* Register the device. */
|
||||||
for (devp = &grub_ata_devices; *devp; devp = &(*devp)->next);
|
for (devp = &grub_ata_devices; *devp; devp = &(*devp)->next);
|
||||||
*devp = dev;
|
*devp = dev;
|
||||||
|
|
||||||
|
err = check_device (dev);
|
||||||
|
if (err)
|
||||||
|
grub_print_error ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,6 +669,14 @@ grub_ata_iterate (int (*hook) (const char *name))
|
||||||
for (dev = grub_ata_devices; dev; dev = dev->next)
|
for (dev = grub_ata_devices; dev; dev = dev->next)
|
||||||
{
|
{
|
||||||
char devname[10];
|
char devname[10];
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
err = check_device (dev);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (dev->atapi)
|
if (dev->atapi)
|
||||||
continue;
|
continue;
|
||||||
|
@ -685,6 +695,7 @@ static grub_err_t
|
||||||
grub_ata_open (const char *name, grub_disk_t disk)
|
grub_ata_open (const char *name, grub_disk_t disk)
|
||||||
{
|
{
|
||||||
struct grub_ata_device *dev;
|
struct grub_ata_device *dev;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
for (dev = grub_ata_devices; dev; dev = dev->next)
|
for (dev = grub_ata_devices; dev; dev = dev->next)
|
||||||
{
|
{
|
||||||
|
@ -701,6 +712,11 @@ grub_ata_open (const char *name, grub_disk_t disk)
|
||||||
if (dev->atapi)
|
if (dev->atapi)
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk");
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk");
|
||||||
|
|
||||||
|
err = check_device (dev);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
disk->total_sectors = dev->size;
|
disk->total_sectors = dev->size;
|
||||||
|
|
||||||
disk->id = (unsigned long) dev;
|
disk->id = (unsigned long) dev;
|
||||||
|
@ -757,6 +773,16 @@ grub_atapi_iterate (int (*hook) (const char *name, int luns))
|
||||||
for (dev = grub_ata_devices; dev; dev = dev->next)
|
for (dev = grub_ata_devices; dev; dev = dev->next)
|
||||||
{
|
{
|
||||||
char devname[10];
|
char devname[10];
|
||||||
|
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
err = check_device (dev);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
grub_snprintf (devname, sizeof (devname),
|
grub_snprintf (devname, sizeof (devname),
|
||||||
"ata%d", dev->port * 2 + dev->device);
|
"ata%d", dev->port * 2 + dev->device);
|
||||||
|
|
||||||
|
@ -827,6 +853,7 @@ grub_atapi_open (const char *name, struct grub_scsi *scsi)
|
||||||
{
|
{
|
||||||
struct grub_ata_device *dev;
|
struct grub_ata_device *dev;
|
||||||
struct grub_ata_device *devfnd = 0;
|
struct grub_ata_device *devfnd = 0;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
for (dev = grub_ata_devices; dev; dev = dev->next)
|
for (dev = grub_ata_devices; dev; dev = dev->next)
|
||||||
{
|
{
|
||||||
|
@ -846,6 +873,13 @@ grub_atapi_open (const char *name, struct grub_scsi *scsi)
|
||||||
if (! devfnd)
|
if (! devfnd)
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device");
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device");
|
||||||
|
|
||||||
|
err = check_device (devfnd);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (! devfnd->atapi)
|
||||||
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device");
|
||||||
|
|
||||||
scsi->data = devfnd;
|
scsi->data = devfnd;
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
|
Loading…
Reference in a new issue