]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
* grub-core/disk/scsi.c (grub_scsi_read_capacity): Renamed to ...
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 30 Jan 2012 17:33:11 +0000 (18:33 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 30 Jan 2012 17:33:11 +0000 (18:33 +0100)
(grub_scsi_read_capacity10): ... this.
(grub_scsi_read_capacity16): New function.
(grub_scsi_open): Use read_capacity16 if read_capacity10 returned
0xffffffff.
Fix off-by-one error.
* include/grub/scsi.h (grub_scsi): Rename size to last_block and make it
64-bit unsigned.
* include/grub/scsicmd.h (grub_scsi_read_capacity): Rename to ...
(grub_scsi_read_capacity10): ... this.
(grub_scsi_read_capacity_data): Rename to ...
(grub_scsi_read_capacity10_data): ... this. Rename size to last_block.
(grub_scsi_read_capacity16): New struct.
(grub_scsi_read_capacity16_data): Likewise.
(grub_scsi_cmd_t): Rename grub_scsi_cmd_read_capacity to
grub_scsi_cmd_read_capacity10.
New command grub_scsi_cmd_read_capacity16.

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

index 38409d405caa46d511f43816bfff14772a62d290..cbf9dc3f45d874f499d81c39c96d6142d50c7d6d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2012-01-30  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       * grub-core/disk/scsi.c (grub_scsi_read_capacity): Renamed to ...
+       (grub_scsi_read_capacity10): ... this.
+       (grub_scsi_read_capacity16): New function.
+       (grub_scsi_open): Use read_capacity16 if read_capacity10 returned
+       0xffffffff.
+       Fix off-by-one error.
+       * include/grub/scsi.h (grub_scsi): Rename size to last_block and make it
+       64-bit unsigned.
+       * include/grub/scsicmd.h (grub_scsi_read_capacity): Rename to ...
+       (grub_scsi_read_capacity10): ... this.
+       (grub_scsi_read_capacity_data): Rename to ...
+       (grub_scsi_read_capacity10_data): ... this. Rename size to last_block.
+       (grub_scsi_read_capacity16): New struct.
+       (grub_scsi_read_capacity16_data): Likewise.
+       (grub_scsi_cmd_t): Rename grub_scsi_cmd_read_capacity to
+       grub_scsi_cmd_read_capacity10.
+       New command grub_scsi_cmd_read_capacity16.
+
 2012-01-30  Vladimir Serbinenko  <phcoder@gmail.com>
 
        SCSI >2TiB support.
index a1d04f40df62b2c628c1f432cc940a20ce399cf9..508bc27f6f801aaa46939b76eb04c39c9c48bb49 100644 (file)
@@ -153,14 +153,14 @@ grub_scsi_inquiry (grub_scsi_t scsi)
 
 /* Read the capacity and block size of SCSI.  */
 static grub_err_t
-grub_scsi_read_capacity (grub_scsi_t scsi)
+grub_scsi_read_capacity10 (grub_scsi_t scsi)
 {
-  struct grub_scsi_read_capacity rc;
-  struct grub_scsi_read_capacity_data rcd;
+  struct grub_scsi_read_capacity10 rc;
+  struct grub_scsi_read_capacity10_data rcd;
   grub_err_t err;
   grub_err_t err_sense;
 
-  rc.opcode = grub_scsi_cmd_read_capacity;
+  rc.opcode = grub_scsi_cmd_read_capacity10;
   rc.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
   rc.logical_block_addr = 0;
   rc.reserved1 = 0;
@@ -182,7 +182,42 @@ grub_scsi_read_capacity (grub_scsi_t scsi)
   if (err)
     return err;
 
-  scsi->size = grub_be_to_cpu32 (rcd.size);
+  scsi->last_block = grub_be_to_cpu32 (rcd.last_block);
+  scsi->blocksize = grub_be_to_cpu32 (rcd.blocksize);
+
+  return GRUB_ERR_NONE;
+}
+
+/* Read the capacity and block size of SCSI.  */
+static grub_err_t
+grub_scsi_read_capacity16 (grub_scsi_t scsi)
+{
+  struct grub_scsi_read_capacity16 rc;
+  struct grub_scsi_read_capacity16_data rcd;
+  grub_err_t err;
+  grub_err_t err_sense;
+
+  rc.opcode = grub_scsi_cmd_read_capacity16;
+  rc.lun = (scsi->lun << GRUB_SCSI_LUN_SHIFT) | 0x10;
+  rc.logical_block_addr = 0;
+  rc.alloc_len = grub_cpu_to_be32 (sizeof (rcd));
+  rc.PMI = 0;
+  rc.control = 0;
+       
+  err = scsi->dev->read (scsi, sizeof (rc), (char *) &rc,
+                        sizeof (rcd), (char *) &rcd);
+
+  /* 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... */
+
+  if (err)
+    return err;
+
+  scsi->last_block = grub_be_to_cpu64 (rcd.last_block);
   scsi->blocksize = grub_be_to_cpu32 (rcd.blocksize);
 
   return GRUB_ERR_NONE;
@@ -541,15 +576,26 @@ grub_scsi_open (const char *name, grub_disk_t disk)
       grub_errno = GRUB_ERR_NONE;
 
       /* Read capacity of media */
-      err = grub_scsi_read_capacity (scsi);
+      err = grub_scsi_read_capacity10 (scsi);
       if (err)
        {
          grub_free (scsi);
-         grub_dprintf ("scsi", "READ CAPACITY failed\n");
+         grub_dprintf ("scsi", "READ CAPACITY10 failed\n");
          return err;
        }
 
-      disk->total_sectors = scsi->size;
+      if (scsi->last_block == 0xffffffff)
+       {
+         err = grub_scsi_read_capacity16 (scsi);
+         if (err)
+           {
+             grub_free (scsi);
+             grub_dprintf ("scsi", "READ CAPACITY16 failed\n");
+             return err;
+           }
+       }
+
+      disk->total_sectors = scsi->last_block + 1;
       if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize)
        {
          grub_free (scsi);
@@ -557,11 +603,11 @@ grub_scsi_open (const char *name, grub_disk_t disk)
                             scsi->blocksize);
        }
       for (disk->log_sector_size = 0;
-          (1 << disk->log_sector_size) < scsi->blocksize;
+          (1U << disk->log_sector_size) < scsi->blocksize;
           disk->log_sector_size++);
 
-      grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n",
-                   scsi->size, scsi->blocksize);
+      grub_dprintf ("scsi", "last_block=%" PRIuGRUB_UINT64_T ", blocksize=%u\n",
+                   scsi->last_block, scsi->blocksize);
       grub_dprintf ("scsi", "Disk total sectors = %llu\n",
                    (unsigned long long) disk->total_sectors);
 
index e10f5e452424ffe2f605d4850a8064c01118049f..13300ca1516215eb9790cec4649b895507baf0ca 100644 (file)
@@ -94,11 +94,11 @@ struct grub_scsi
   /* Set to 0 when not removable, 1 when removable.  */
   int removable;
 
-  /* Size of the device in blocks.  */
-  int size;
+  /* Size of the device in blocks - 1.  */
+  grub_uint64_t last_block;
 
   /* Size of one block.  */
-  int blocksize;
+  grub_uint32_t blocksize;
 
   /* Device-specific data.  */
   void *data;
index c969c394aa9b0d3c10d2861533ae48fe246ada56..a3e79888a6cdef03c565bac105b3a0e8a2cab35a 100644 (file)
@@ -85,7 +85,7 @@ struct grub_scsi_request_sense_data
   /* there can be additional sense field */
 } __attribute__((packed));
 
-struct grub_scsi_read_capacity
+struct grub_scsi_read_capacity10
 {
   grub_uint8_t opcode;
   grub_uint8_t lun; /* 7-5 LUN, 4-1 reserved, 0 reserved */
@@ -97,10 +97,27 @@ struct grub_scsi_read_capacity
   grub_uint16_t pad; /* To be ATAPI compatible */
 } __attribute__((packed));
 
-struct grub_scsi_read_capacity_data
+struct grub_scsi_read_capacity10_data
 {
-  grub_uint32_t size;
+  grub_uint32_t last_block;
+  grub_uint32_t blocksize;
+} __attribute__((packed));
+
+struct grub_scsi_read_capacity16
+{
+  grub_uint8_t opcode;
+  grub_uint8_t lun; /* 7-5 LUN, 4-0 0x10 */
+  grub_uint64_t logical_block_addr; /* only if PMI=1 */
+  grub_uint32_t alloc_len;
+  grub_uint8_t PMI;
+  grub_uint8_t control;
+} __attribute__((packed));
+
+struct grub_scsi_read_capacity16_data
+{
+  grub_uint64_t last_block;
   grub_uint32_t blocksize;
+  grub_uint8_t pad[20];
 } __attribute__((packed));
 
 struct grub_scsi_read10
@@ -170,11 +187,12 @@ typedef enum
     grub_scsi_cmd_test_unit_ready = 0x00,
     grub_scsi_cmd_request_sense = 0x03,
     grub_scsi_cmd_inquiry = 0x12,
-    grub_scsi_cmd_read_capacity = 0x25,
+    grub_scsi_cmd_read_capacity10 = 0x25,
     grub_scsi_cmd_read10 = 0x28,
     grub_scsi_cmd_write10 = 0x2a,
     grub_scsi_cmd_read16 = 0x88,
     grub_scsi_cmd_write16 = 0x8a,
+    grub_scsi_cmd_read_capacity16 = 0x9e,
     grub_scsi_cmd_read12 = 0xa8,
     grub_scsi_cmd_write12 = 0xaa,
   } grub_scsi_cmd_t;