]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Support ATA disks with 4K sectors.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 25 Jul 2011 06:14:34 +0000 (08:14 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 25 Jul 2011 06:14:34 +0000 (08:14 +0200)
* include/grub/ata.h (grub_ata): New member log_sector_size.
* grub-core/disk/ata.c (grub_ata_dumpinfo): Show sector size.
(grub_ata_identify): Read sector size.
(grub_ata_readwrite): Use log_sector_size rather than hardcoded value.

ChangeLog
grub-core/disk/ata.c
include/grub/ata.h

index 32dfada58d3b7411f1e05975d9a8135c24915dd1..5c4e20c28371e35ad3957d6f3ae5a103f853dd64 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2011-07-25  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       Support ATA disks with non-4K sectors.
+
+       * include/grub/ata.h (grub_ata): New member log_sector_size.
+       * grub-core/disk/ata.c (grub_ata_dumpinfo): Show sector size.
+       (grub_ata_identify): Read sector size.
+       (grub_ata_readwrite): Use log_sector_size rather than hardcoded value.
+
 2011-07-25  Vladimir Serbinenko  <phcoder@gmail.com>
 
        * util/grub-install.in: Don't use uhci outside of x86.
index 8add7f4de7e428eba5b61e2572f669e70875a100..330635f57a09b2c818f39f93bfa5d101cc961abf 100644 (file)
@@ -57,6 +57,7 @@ grub_ata_dumpinfo (struct grub_ata *dev, char *info)
     {
       grub_dprintf ("ata", "Addressing: %d\n", dev->addr);
       grub_dprintf ("ata", "Sectors: %lld\n", (unsigned long long) dev->size);
+      grub_dprintf ("ata", "Sector size: %u\n", 1U << dev->log_sector_size);
     }
 }
 
@@ -170,6 +171,21 @@ grub_ata_identify (struct grub_ata *dev)
   else
     dev->size = grub_le_to_cpu64(*((grub_uint64_t *) &info16[100]));
 
+  if (info16[106] & (1 << 12))
+    {
+      grub_uint32_t secsize;
+      secsize = grub_le_to_cpu32 (*((grub_uint32_t *) &info16[117]));
+      if (secsize & (secsize - 1) || !secsize
+         || secsize > 1048576)
+       secsize = 256;
+      for (dev->log_sector_size = 0;
+          (1U << dev->log_sector_size) < secsize;
+          dev->log_sector_size++);
+      dev->log_sector_size++;
+    }
+  else
+    dev->log_sector_size = 9;
+
   /* Read CHS information.  */
   dev->cylinders = info16[1];
   dev->heads = info16[3];
@@ -314,7 +330,7 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
       grub_ata_setaddress (ata, &parms, sector, batch, addressing);
       parms.taskfile.cmd = (! rw ? cmd : cmd_write);
       parms.buffer = buf;
-      parms.size = batch * GRUB_DISK_SECTOR_SIZE;
+      parms.size = batch << ata->log_sector_size;
       parms.write = rw;
       if (ata->dma)
        parms.dma = 1;
@@ -322,9 +338,9 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
       err = ata->dev->readwrite (ata, &parms, 0);
       if (err)
        return err;
-      if (parms.size != batch * GRUB_DISK_SECTOR_SIZE)
+      if (parms.size != batch << ata->log_sector_size)
        return grub_error (GRUB_ERR_READ_ERROR, "incomplete read");
-      buf += GRUB_DISK_SECTOR_SIZE * batch;
+      buf += batch << ata->log_sector_size;
       sector += batch;
       nsectors += batch;
     }
@@ -433,6 +449,7 @@ grub_ata_open (const char *name, grub_disk_t disk)
     return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk");
 
   disk->total_sectors = ata->size;
+  disk->log_sector_size = ata->log_sector_size;
 
   disk->id = grub_make_scsi_id (id, bus, 0);
 
index 6938b6a42f7c1be005ce211c40f5443622eb3a92..1a19f27aaf920012000e08b920c485e12660c248 100644 (file)
@@ -170,6 +170,7 @@ struct grub_ata
 
   /* Sector count.  */
   grub_uint64_t size;
+  grub_uint32_t log_sector_size;
 
   /* CHS maximums.  */
   grub_uint16_t cylinders;