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
}
#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),
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;
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;
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;
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,
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;