diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 1e28b3dc5..4b5d195f2 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -398,6 +398,7 @@ grub_ahci_open (int id, int devnum, struct grub_ata *ata) grub_dprintf ("ahci", "opening AHCI dev `ahci%d'\n", dev->num); ata->data = dev; + ata->dma = 0; return GRUB_ERR_NONE; } diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 5015f8507..b33abf90d 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -255,8 +255,16 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, if (addressing == GRUB_ATA_LBA48 && ((sector + size) >> 28) != 0) { batch = 65536; - cmd = GRUB_ATA_CMD_READ_SECTORS_EXT; - cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_EXT; + if (ata->dma) + { + cmd = GRUB_ATA_CMD_READ_SECTORS_DMA_EXT; + cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_DMA_EXT; + } + else + { + cmd = GRUB_ATA_CMD_READ_SECTORS_EXT; + cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_EXT; + } } else { @@ -266,9 +274,17 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, batch = 256; else batch = 1; - cmd = GRUB_ATA_CMD_READ_SECTORS; - cmd_write = GRUB_ATA_CMD_WRITE_SECTORS; - } + if (ata->dma) + { + cmd = GRUB_ATA_CMD_READ_SECTORS_DMA; + cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_DMA; + } + else + { + cmd = GRUB_ATA_CMD_READ_SECTORS; + cmd_write = GRUB_ATA_CMD_WRITE_SECTORS; + } + } grub_size_t nsectors = 0; while (nsectors < size) @@ -285,6 +301,8 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, parms.taskfile.cmd = (! rw ? cmd : cmd_write); parms.buffer = buf; parms.size = batch * GRUB_DISK_SECTOR_SIZE; + if (ata->dma) + parms.dma = 1; err = ata->dev->readwrite (ata, &parms); if (err) diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index a24237a83..186caf6a2 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -474,6 +474,7 @@ grub_pata_open (int id, int devnum, struct grub_ata *ata) return err; ata->data = devfnd; + ata->dma = 0; return GRUB_ERR_NONE; } diff --git a/include/grub/ata.h b/include/grub/ata.h index b1c6ead26..bea74c180 100644 --- a/include/grub/ata.h +++ b/include/grub/ata.h @@ -82,6 +82,9 @@ enum grub_ata_commands GRUB_ATA_CMD_PACKET = 0xa0, GRUB_ATA_CMD_READ_SECTORS = 0x20, GRUB_ATA_CMD_READ_SECTORS_EXT = 0x24, + GRUB_ATA_CMD_READ_SECTORS_DMA = 0xc8, + GRUB_ATA_CMD_READ_SECTORS_DMA_EXT = 0x25, + GRUB_ATA_CMD_SECURITY_FREEZE_LOCK = 0xf5, GRUB_ATA_CMD_SET_FEATURES = 0xef, GRUB_ATA_CMD_SLEEP = 0xe6, @@ -89,6 +92,8 @@ enum grub_ata_commands GRUB_ATA_CMD_STANDBY_IMMEDIATE = 0xe0, GRUB_ATA_CMD_WRITE_SECTORS = 0x30, GRUB_ATA_CMD_WRITE_SECTORS_EXT = 0x34, + GRUB_ATA_CMD_WRITE_SECTORS_DMA_EXT = 0x35, + GRUB_ATA_CMD_WRITE_SECTORS_DMA = 0xca, }; enum grub_ata_timeout_milliseconds @@ -151,6 +156,7 @@ struct grub_disk_ata_pass_through_parms int write; void *cmd; int cmdsize; + int dma; }; struct grub_ata @@ -171,6 +177,8 @@ struct grub_ata /* Set to 0 for ATA, set to 1 for ATAPI. */ int atapi; + int dma; + void *data; struct grub_ata_dev *dev;