* 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.
This commit is contained in:
parent
bc8d0f45a5
commit
9c08ad8707
4 changed files with 102 additions and 18 deletions
20
ChangeLog
20
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.
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,12 +97,29 @@ 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
|
||||
{
|
||||
grub_uint8_t opcode;
|
||||
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue