[haiku-commits] BRANCH axeld-github.trim [a6ecf2a] src/add-ons/kernel/generic/scsi_periph src/add-ons/kernel/drivers/disk/scsi/scsi_disk headers/private/drivers

  • From: axeld-github.trim <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 5 Aug 2013 01:15:31 +0200 (CEST)

added 1 changeset to branch 'refs/remotes/axeld-github/trim'
old head: 1c6edcdcdc8ab0b4a9ed79d2c0464e73ac8e0745
new head: a6ecf2a9d10d98245fe6346a1116aec5fc653f62
overview: https://github.com/axeld/haiku/compare/1c6edcd...a6ecf2a

----------------------------------------------------------------------------

a6ecf2a: This gets the trim command as WRITE SAME operation to SCSI
  
  * Neither hardware nor driver to test it; AHCI/IDE support is next
    on the table.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

Commit:      a6ecf2a9d10d98245fe6346a1116aec5fc653f62
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Sun Aug  4 22:51:37 2013 UTC

----------------------------------------------------------------------------

5 files changed, 93 insertions(+), 13 deletions(-)
headers/private/drivers/scsi_periph.h            | 11 +++--
.../drivers/disk/scsi/scsi_disk/scsi_disk.cpp    | 39 ++++++++++++++--
src/add-ons/kernel/generic/scsi_periph/block.cpp | 47 ++++++++++++++++++--
.../kernel/generic/scsi_periph/scsi_periph.cpp   |  5 ++-
.../kernel/generic/scsi_periph/scsi_periph_int.h |  4 +-

----------------------------------------------------------------------------

diff --git a/headers/private/drivers/scsi_periph.h 
b/headers/private/drivers/scsi_periph.h
index 03fd57e..b879521 100644
--- a/headers/private/drivers/scsi_periph.h
+++ b/headers/private/drivers/scsi_periph.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2008, Haiku, Inc. All RightsReserved.
+ * Copyright 2004-2013, Haiku, Inc. All RightsReserved.
  * Copyright 2002/03, Thomas Kurschel. All rights reserved.
  *
  * Distributed under the terms of the MIT License.
@@ -7,6 +7,7 @@
 #ifndef _SCSI_PERIPH_H
 #define _SCSI_PERIPH_H
 
+
 /*!    Use this module to minimize work required to write a SCSI
        peripheral driver.
 
@@ -114,6 +115,12 @@ typedef struct scsi_periph_interface {
        // request - ccb for this device; is used to talk to device
        status_t (*check_capacity)(scsi_periph_device device, scsi_ccb 
*request);
 
+       // synchronizes (flush) the device cache
+       err_res (*synchronize_cache)(scsi_periph_device device, scsi_ccb 
*request);
+
+       status_t (*trim_device)(scsi_periph_device_info *device, scsi_ccb 
*request,
+               uint64 offset, uint64 numBlocks);
+
        // *** removable media ***
        // to be called when a medium change is detected to block subsequent 
commands
        void (*media_changed)(scsi_periph_device device);
@@ -128,8 +135,6 @@ typedef struct scsi_periph_interface {
        // returns: B_OK, B_DEV_MEDIA_CHANGE_REQUESTED, B_NO_MEMORY or
        // pending error reported by handle_get_error
        status_t (*get_media_status)(scsi_periph_handle handle);
-       // synchronizes (flush) the device cache
-       err_res(*synchronize_cache)(scsi_periph_device device, scsi_ccb 
*request);
 
        // compose device name consisting of prefix and path/target/LUN
        // (result must be freed by caller)
diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp 
b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp
index d3d13af..c566396 100644
--- a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp
+++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp
@@ -1,9 +1,10 @@
 /*
- * Copyright 2008-2012, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2008-2013, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
  * Copyright 2002/03, Thomas Kurschel. All rights reserved.
  * Distributed under the terms of the MIT License.
  */
 
+
 /*!    Peripheral driver to handle any kind of SCSI disks,
        i.e. hard disk and floopy disks (ZIP etc.)
 
@@ -93,7 +94,6 @@ get_geometry(das_handle* handle, device_geometry* geometry)
        if (status != B_OK)
                return status;
 
-
        devfs_compute_geometry_size(geometry, info->capacity, info->block_size);
 
        geometry->device_type = B_DISK;
@@ -153,6 +153,24 @@ synchronize_cache(das_driver_info *device)
 }
 
 
+static status_t
+trim_device(das_driver_info* device, off_t offset, off_t size)
+{
+       TRACE("trim_device()\n");
+
+       scsi_ccb* request = device->scsi->alloc_ccb(device->scsi_device);
+       if (request == NULL)
+               return B_NO_MEMORY;
+
+       status_t status = 
sSCSIPeripheral->trim_device(device->scsi_periph_device,
+               request, offset / device->block_size, size / 
device->block_size);
+
+       device->scsi->free_ccb(request);
+
+       return status;
+}
+
+
 static int
 log2(uint32 x)
 {
@@ -385,6 +403,21 @@ das_ioctl(void* cookie, uint32 op, void* buffer, size_t 
length)
                case B_FLUSH_DRIVE_CACHE:
                        return synchronize_cache(info);
 
+               case B_TRIM_DEVICE:
+               {
+                       fs_trim_data trimData;
+                       if (user_memcpy(&trimData, buffer, 
sizeof(fs_trim_data)) != B_OK)
+                               return B_BAD_ADDRESS;
+
+                       status_t status = trim_device(info, trimData.offset, 
trimData.size);
+                       if (status != B_OK)
+                               return status;
+
+                       trimData.trimmed_size = trimData.size;
+
+                       return user_memcpy(buffer, &trimData, 
sizeof(fs_trim_data));
+               }
+
                default:
                        return 
sSCSIPeripheral->ioctl(handle->scsi_periph_handle, op,
                                buffer, length);
@@ -649,7 +682,7 @@ struct driver_module_info sSCSIDiskDriver = {
        das_init_driver,
        das_uninit_driver,
        das_register_child_devices,
-       das_rescan_child_devices,       
+       das_rescan_child_devices,
        NULL,   // removed
 };
 
diff --git a/src/add-ons/kernel/generic/scsi_periph/block.cpp 
b/src/add-ons/kernel/generic/scsi_periph/block.cpp
index 3b3ac63..0c6eb0d 100644
--- a/src/add-ons/kernel/generic/scsi_periph/block.cpp
+++ b/src/add-ons/kernel/generic/scsi_periph/block.cpp
@@ -1,12 +1,12 @@
 /*
- * Copyright 2004-2011, Haiku, Inc. All RightsReserved.
+ * Copyright 2004-2013, Haiku, Inc. All RightsReserved.
  * Copyright 2002-2003, Thomas Kurschel. All rights reserved.
  *
  * Distributed under the terms of the MIT License.
  */
 
 
-//!    Handling of block device (currently, only a capacity check is provided)
+//!    Handling of block device
 
 
 #include "scsi_periph_int.h"
@@ -59,10 +59,10 @@ periph_check_capacity(scsi_periph_device_info *device, 
scsi_ccb *request)
 
                if (capacity == UINT_MAX) {
                        mutex_unlock(&device->mutex);
-                       
+
                        scsi_cmd_read_capacity_long *cmd
                                = (scsi_cmd_read_capacity_long *)request->cdb;
-                       
+
                        scsi_res_read_capacity_long capacityLongResult;
                        request->data = (uint8*)&capacityLongResult;
                        request->data_length = sizeof(capacityLongResult);
@@ -114,3 +114,42 @@ periph_check_capacity(scsi_periph_device_info *device, 
scsi_ccb *request)
        return res;
 }
 
+
+status_t
+periph_trim_device(scsi_periph_device_info *device, scsi_ccb *request,
+       uint64 offset, uint64 numBlocks)
+{
+       err_res res;
+       int retries = 0;
+
+       do {
+               request->flags = SCSI_DIR_OUT;
+               request->sort = offset;
+               request->timeout = device->std_timeout;
+
+               scsi_cmd_wsame_16* cmd = (scsi_cmd_wsame_16*)request->cdb;
+
+               memset(cmd, 0, sizeof(*cmd));
+               cmd->opcode = SCSI_OP_WRITE_SAME_16;
+               cmd->unmap = 1;
+               cmd->lba = B_HOST_TO_BENDIAN_INT64(offset);
+               cmd->length = B_HOST_TO_BENDIAN_INT32(numBlocks);
+
+               request->cdb_length = sizeof(*cmd);
+
+               device->scsi->async_io(request);
+
+               acquire_sem(request->completion_sem);
+
+               // ask generic peripheral layer what to do now
+               res = periph_check_error(device, request);
+       } while ((res.action == err_act_retry && retries++ < 3)
+               || (res.action == err_act_many_retries && retries++ < 30));
+
+       // peripheral layer only creates "read" error
+       if (res.error_code == B_DEV_READ_ERROR)
+               return B_DEV_WRITE_ERROR;
+
+       return res.error_code;
+}
+
diff --git a/src/add-ons/kernel/generic/scsi_periph/scsi_periph.cpp 
b/src/add-ons/kernel/generic/scsi_periph/scsi_periph.cpp
index c3b1663..7970698 100644
--- a/src/add-ons/kernel/generic/scsi_periph/scsi_periph.cpp
+++ b/src/add-ons/kernel/generic/scsi_periph/scsi_periph.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2008, Haiku, Inc. All RightsReserved.
+ * Copyright 2004-2013, Haiku, Inc. All RightsReserved.
  * Copyright 2002-2003, Thomas Kurschel. All rights reserved.
  *
  * Distributed under the terms of the MIT License.
@@ -135,12 +135,13 @@ static scsi_periph_interface sSCSIPeripheralModule = {
        periph_io,
        periph_ioctl,
        periph_check_capacity,
+       periph_synchronize_cache,
+       periph_trim_device,
 
        periph_media_changed_public,
        periph_check_error,
        periph_send_start_stop,
        periph_get_media_status,
-       periph_synchronize_cache,
 
        periph_compose_device_name
 };
diff --git a/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h 
b/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h
index c7493a5..30df67a 100644
--- a/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h
+++ b/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2008, Haiku, Inc. All Rights Reserved.
+ * Copyright 2004-2013, Haiku, Inc. All Rights Reserved.
  * Copyright 2002, Thomas Kurschel. All rights reserved.
  * Distributed under the terms of the MIT License.
  */
@@ -77,6 +77,8 @@ status_t periph_handle_free(scsi_periph_handle_info *handle);
 // block.c
 
 status_t periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *ccb);
+status_t periph_trim_device(scsi_periph_device_info *device, scsi_ccb *request,
+       uint64 offset, uint64 numBlocks);
 
 
 // device.c


Other related posts:

  • » [haiku-commits] BRANCH axeld-github.trim [a6ecf2a] src/add-ons/kernel/generic/scsi_periph src/add-ons/kernel/drivers/disk/scsi/scsi_disk headers/private/drivers - axeld-github . trim