From cc774926f12eff377bc25ed571e69b7978c1d978 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 30 Jan 2012 12:26:11 +0100 Subject: [PATCH] SCSI write support (for usbms mainly). * grub-core/disk/scsi.c (grub_scsi_write10): Uncomment. Make buffer a const pointer. (grub_scsi_write): Implement. * include/grub/scsi.h (grub_scsi_dev): Make write buffer a const pointer --- ChangeLog | 9 +++++++++ grub-core/disk/ata.c | 2 +- grub-core/disk/scsi.c | 42 ++++++++++++++++++++++++++++++++++-------- grub-core/disk/usbms.c | 4 ++-- include/grub/scsi.h | 2 +- 5 files changed, 47 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1055d1ad4..5641803dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2012-01-30 Vladimir Serbinenko + + SCSI write support (for usbms mainly). + + * grub-core/disk/scsi.c (grub_scsi_write10): Uncomment. Make buffer + a const pointer. + (grub_scsi_write): Implement. + * include/grub/scsi.h (grub_scsi_dev): Make write buffer a const pointer + 2012-01-30 Vladimir Serbinenko * grub-core/io/lzopio.c (uncompress_block): Fix use of incorrect diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 6d2ec0c78..c90e86832 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -537,7 +537,7 @@ grub_atapi_write (struct grub_scsi *scsi __attribute__((unused)), grub_size_t cmdsize __attribute__((unused)), char *cmd __attribute__((unused)), grub_size_t size __attribute__((unused)), - char *buf __attribute__((unused))) + const char *buf __attribute__((unused))) { // XXX: scsi.mod does not use write yet. return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ATAPI write not implemented"); diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index 610cc4dc5..b22f651e9 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -253,12 +253,11 @@ grub_scsi_read12 (grub_disk_t disk, grub_disk_addr_t sector, return err; } -#if 0 /* Send a SCSI request for DISK: write the data stored in BUF to SIZE sectors starting with SECTOR. */ static grub_err_t grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector, - grub_size_t size, char *buf) + grub_size_t size, const char *buf) { grub_scsi_t scsi; struct grub_scsi_write10 wr; @@ -287,6 +286,8 @@ grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector, return err; } +#if 0 + /* Send a SCSI request for DISK: write the data stored in BUF to SIZE sectors starting with SECTOR. */ static grub_err_t @@ -595,13 +596,38 @@ grub_scsi_write (grub_disk_t disk __attribute((unused)), grub_size_t size __attribute((unused)), const char *buf __attribute((unused))) { -#if 0 - /* XXX: Not tested yet! */ + grub_scsi_t scsi; - /* XXX: This should depend on the device type? */ - return grub_scsi_write10 (disk, sector, size, buf); -#endif - return GRUB_ERR_NOT_IMPLEMENTED_YET; + scsi = disk->data; + + if (scsi->devtype == grub_scsi_devtype_cdrom) + return grub_error (GRUB_ERR_IO, "no CD burning"); + + while (size) + { + /* PATA doesn't support more than 32K reads. + Not sure about AHCI and USB. If it's confirmed that either of + them can do bigger reads reliably this value can be moved to 'scsi' + structure. */ + grub_size_t len = 32768 >> disk->log_sector_size; + grub_err_t err; + if (len > size) + len = size; + /* Depending on the type, select a read function. */ + switch (scsi->devtype) + { + case grub_scsi_devtype_direct: + err = grub_scsi_write10 (disk, sector, len, buf); + if (err) + return err; + break; + } + size -= len; + sector += len; + buf += len << disk->log_sector_size; + } + + return GRUB_ERR_NONE; } diff --git a/grub-core/disk/usbms.c b/grub-core/disk/usbms.c index a4c2addf1..e264c464c 100644 --- a/grub-core/disk/usbms.c +++ b/grub-core/disk/usbms.c @@ -388,9 +388,9 @@ grub_usbms_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, static grub_err_t grub_usbms_write (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, - grub_size_t size, char *buf) + grub_size_t size, const char *buf) { - return grub_usbms_transfer (scsi, cmdsize, cmd, size, buf, 1); + return grub_usbms_transfer (scsi, cmdsize, cmd, size, (char *) buf, 1); } static grub_err_t diff --git a/include/grub/scsi.h b/include/grub/scsi.h index dfee69c62..e10f5e452 100644 --- a/include/grub/scsi.h +++ b/include/grub/scsi.h @@ -69,7 +69,7 @@ struct grub_scsi_dev /* Write SIZE bytes from BUF to the device SCSI after sending the command CMD of size CMDSIZE. */ grub_err_t (*write) (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, - grub_size_t size, char *buf); + grub_size_t size, const char *buf); /* The next scsi device. */ struct grub_scsi_dev *next;