]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
SCSI >2TiB support.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 30 Jan 2012 11:47:26 +0000 (12:47 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 30 Jan 2012 11:47:26 +0000 (12:47 +0100)
* grub-core/disk/scsi.c (grub_scsi_read16): New function.
(grub_scsi_write16): Likewise.
(grub_scsi_read): Use read16 when necessary.
(grub_scsi_write): Likewise.
* include/grub/scsicmd.h (grub_scsi_read16): New struct.
(grub_scsi_write16): Likewise.
(grub_scsi_cmd_t): Add READ16 and WRITE16.

ChangeLog
grub-core/disk/scsi.c
include/grub/scsicmd.h

index 5641803dc7b973deeaa09bda05903e2f6f1557be..38409d405caa46d511f43816bfff14772a62d290 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2012-01-30  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       SCSI >2TiB support.
+
+       * grub-core/disk/scsi.c (grub_scsi_read16): New function.
+       (grub_scsi_write16): Likewise.
+       (grub_scsi_read): Use read16 when necessary.
+       (grub_scsi_write): Likewise.
+       * include/grub/scsicmd.h (grub_scsi_read16): New struct.
+       (grub_scsi_write16): Likewise.
+       (grub_scsi_cmd_t): Add READ16 and WRITE16.
+
 2012-01-30  Vladimir Serbinenko  <phcoder@gmail.com>
 
        SCSI write support (for usbms mainly).
index b22f651e9eaab6cfd7434814610be57487ed4c9e..a1d04f40df62b2c628c1f432cc940a20ce399cf9 100644 (file)
@@ -253,6 +253,38 @@ grub_scsi_read12 (grub_disk_t disk, grub_disk_addr_t sector,
   return err;
 }
 
+/* Send a SCSI request for DISK: read SIZE sectors starting with
+   sector SECTOR to BUF.  */
+static grub_err_t
+grub_scsi_read16 (grub_disk_t disk, grub_disk_addr_t sector,
+                 grub_size_t size, char *buf)
+{
+  grub_scsi_t scsi;
+  struct grub_scsi_read16 rd;
+  grub_err_t err;
+  grub_err_t err_sense;
+
+  scsi = disk->data;
+
+  rd.opcode = grub_scsi_cmd_read16;
+  rd.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
+  rd.lba = grub_cpu_to_be64 (sector);
+  rd.size = grub_cpu_to_be32 (size);
+  rd.reserved = 0;
+  rd.control = 0;
+
+  err = scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * scsi->blocksize, buf);
+
+  /* Each SCSI command should be followed by Request Sense.
+     If not so, many devices STALLs or definitely freezes. */
+  err_sense = grub_scsi_request_sense (scsi);
+  if (err_sense != GRUB_ERR_NONE)
+       grub_errno = err;
+  /* err_sense is ignored for now and Request Sense Data also... */
+
+  return err;
+}
+
 /* Send a SCSI request for DISK: write the data stored in BUF to SIZE
    sectors starting with SECTOR.  */
 static grub_err_t
@@ -321,6 +353,39 @@ grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector,
 }
 #endif
 
+/* Send a SCSI request for DISK: write the data stored in BUF to SIZE
+   sectors starting with SECTOR.  */
+static grub_err_t
+grub_scsi_write16 (grub_disk_t disk, grub_disk_addr_t sector,
+                  grub_size_t size, const char *buf)
+{
+  grub_scsi_t scsi;
+  struct grub_scsi_write16 wr;
+  grub_err_t err;
+  grub_err_t err_sense;
+
+  scsi = disk->data;
+
+  wr.opcode = grub_scsi_cmd_write16;
+  wr.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
+  wr.lba = grub_cpu_to_be64 (sector);
+  wr.size = grub_cpu_to_be32 (size);
+  wr.reserved = 0;
+  wr.control = 0;
+
+  err = scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * scsi->blocksize, buf);
+
+  /* Each SCSI command should be followed by Request Sense.
+     If not so, many devices STALLs or definitely freezes. */
+  err_sense = grub_scsi_request_sense (scsi);
+  if (err_sense != GRUB_ERR_NONE)
+       grub_errno = err;
+  /* err_sense is ignored for now and Request Sense Data also... */
+
+  return err;
+}
+
+
 \f
 static int
 grub_scsi_iterate (int (*hook) (const char *name),
@@ -540,13 +605,19 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector,
       switch (scsi->devtype)
        {
        case grub_scsi_devtype_direct:
-         err = grub_scsi_read10 (disk, sector, len, buf);
+         if (sector >> 32)
+           err = grub_scsi_read16 (disk, sector, len, buf);
+         else
+           err = grub_scsi_read10 (disk, sector, len, buf);
          if (err)
            return err;
          break;
 
        case grub_scsi_devtype_cdrom:
-         err = grub_scsi_read12 (disk, sector, len, buf);
+         if (sector >> 32)
+           err = grub_scsi_read16 (disk, sector, len, buf);
+         else
+           err = grub_scsi_read12 (disk, sector, len, buf);
          if (err)
            return err;
          break;
@@ -617,7 +688,10 @@ grub_scsi_write (grub_disk_t disk __attribute((unused)),
       switch (scsi->devtype)
        {
        case grub_scsi_devtype_direct:
-         err = grub_scsi_write10 (disk, sector, len, buf);
+         if (sector >> 32)
+           err = grub_scsi_write16 (disk, sector, len, buf);
+         else
+           err = grub_scsi_write10 (disk, sector, len, buf);
          if (err)
            return err;
          break;
index 9cc5afe72d3bfae919429e26c2ba6f02f5616366..c969c394aa9b0d3c10d2861533ae48fe246ada56 100644 (file)
@@ -124,6 +124,16 @@ struct grub_scsi_read12
   grub_uint8_t control;
 } __attribute__((packed));
 
+struct grub_scsi_read16
+{
+  grub_uint8_t opcode;
+  grub_uint8_t lun;
+  grub_uint64_t lba;
+  grub_uint32_t size;
+  grub_uint8_t reserved;
+  grub_uint8_t control;
+} __attribute__((packed));
+
 struct grub_scsi_write10
 {
   grub_uint8_t opcode;
@@ -145,6 +155,16 @@ struct grub_scsi_write12
   grub_uint8_t control;
 } __attribute__((packed));
 
+struct grub_scsi_write16
+{
+  grub_uint8_t opcode;
+  grub_uint8_t lun;
+  grub_uint64_t lba;
+  grub_uint32_t size;
+  grub_uint8_t reserved;
+  grub_uint8_t control;
+} __attribute__((packed));
+
 typedef enum
   {
     grub_scsi_cmd_test_unit_ready = 0x00,
@@ -153,6 +173,8 @@ typedef enum
     grub_scsi_cmd_read_capacity = 0x25,
     grub_scsi_cmd_read10 = 0x28,
     grub_scsi_cmd_write10 = 0x2a,
+    grub_scsi_cmd_read16 = 0x88,
+    grub_scsi_cmd_write16 = 0x8a,
     grub_scsi_cmd_read12 = 0xa8,
     grub_scsi_cmd_write12 = 0xaa,
   } grub_scsi_cmd_t;