[haiku-commits] haiku: hrev46325 - src/add-ons/kernel/busses/scsi/ahci src/add-ons/kernel/file_systems/bfs src/add-ons/kernel/generic/scsi_periph src/bin headers/private/kernel/util

  • From: axeld@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 7 Nov 2013 19:06:53 +0100 (CET)

hrev46325 adds 19 changesets to branch 'master'
old head: 34ce2cefc8c211af77d0660309323358b3c34adc
new head: 0c873619ce86975e9ed3c66e88ca4dc9ef303a82
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=0c87361+%5E34ce2ce

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

29a8450: Added B_TRIM_DEVICE ioctl.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

a352b43: Added fstrim command.
  
  Later, there should be a service that runs this from time to time for all
  devices that support it.
  
  Conflicts:
        build/jam/HaikuImage

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

0a0ba4b: Added B_TRIM_DEVICE support to BFS.
  
  * It currently ignores the offset/size, though, and always trims everything.
  * Now only SCSI support is missing.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

960c56a: 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> ]

99086aa: trim: Target SCSI UNMAP command instead of WRITE SAME.
  
  * The UNMAP command is theoretically much faster, as it can get many block
    ranges instead of just a single range.
  * Furthermore, the ATA TRIM command resembles it much better.
  * Therefore, fs_trim_data now gets an array of ranges, and we use SCSI UNMAP
    to trim.
  * Updated BFS code to collect array ranges to fully support the new
    fs_trim_data possibilities.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

33945c5: ahci: Pushed TRIM support a tiny bit further.
  
  * Now doesn't do anything on SCSI_OP_UNMAP, instead of doing nothing on
    SCSI_OP_WRITE_SAME_16.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

13e72c9: ahci: Minor cleanup.
  
  * Mostly utilized ATACommands.h

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

d82e6bc: ahci: Use get_memory_map_etc().
  
  * Simplifies code a bit.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

6317a4c: scsi_periph: fixed copy&paste error in periph_trim_device().

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

e858a6b: ahci: WIP of implementing trim command.
  
  * Data Set Management specific bits are still missing.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

10deaef: ahci: Added missing wait_for_completion().
  
  * Thanks Marcus!
  * That made the return code for ExecuteSataRequest() pretty much useless,
    so I removed it again.
  * Also, a delete sreq was missing; I now allocate it on the stack instead.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

fd88486: ahci: Set the command bits as required.
  
  * The trim command should be functional now, but it's completely untested
    at this point.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

930cb42: ahci: Minor cleanup.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

2e4e1eb: ahci: fixed endless loop, and missing bit.
  
  * The value for trim is bit 0, not 0; added sata_request::SetFeature()
    to change this.
  * The lba range fill loop never ended.
  * Thanks to Marcus for proof-reading!

                                  [ Axel Doerfler <axeld@xxxxxxxxxxxxxxxx> ]

dbeb6b5: ahci: Fixed braindead variable naming.
  
  * Again, thanks Marcus!

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

79cb543: ahci: Minor coding style cleanup.
  
  * Renamed some methods to camel case.
  * Replaced coding error panics with ASSERTs.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

547cd46: trim: Added is_called_via_syscall() function.
  
  * And use it in get_trim_data_from_user(), formerly known as copy_*().
  * This fixes differentiating between user and kernel buffers.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

e6bde50: scsi_periph: use synchronous command.
  
  * The call waited anyway, so there is no reason to make it async.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

0c87361: ahci: Fixed missing endian conversion.
  
  * Spotted by Rene, thanks a lot!

                                  [ Axel Doerfler <axeld@xxxxxxxxxxxxxxxx> ]

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

23 files changed, 769 insertions(+), 185 deletions(-)
build/jam/images/HaikuImage                      |   2 +-
headers/os/drivers/Drivers.h                     |  14 +-
headers/private/drivers/scsi_cmds.h              |  37 ++-
headers/private/drivers/scsi_periph.h            |  15 +-
headers/private/fs_shell/fssh_api_wrapper.h      |   5 +
headers/private/fs_shell/fssh_drivers.h          |  24 +-
headers/private/kernel/syscall_restart.h         |  16 +-
headers/private/kernel/util/fs_trim_support.h    |  65 +++++
.../kernel/busses/scsi/ahci/ahci_port.cpp        | 265 ++++++++++++-------
src/add-ons/kernel/busses/scsi/ahci/ahci_port.h  |   4 +-
.../kernel/busses/scsi/ahci/sata_request.cpp     |  60 +++--
.../kernel/busses/scsi/ahci/sata_request.h       |  78 +++---
.../drivers/disk/scsi/scsi_disk/scsi_disk.cpp    |  50 +++-
.../kernel/file_systems/bfs/BlockAllocator.cpp   | 107 +++++++-
.../kernel/file_systems/bfs/BlockAllocator.h     |  10 +-
.../kernel/file_systems/bfs/kernel_interface.cpp |  31 ++-
src/add-ons/kernel/generic/scsi_periph/Jamfile   |   2 +-
src/add-ons/kernel/generic/scsi_periph/block.cpp |  72 ++++-
.../kernel/generic/scsi_periph/scsi_periph.cpp   |   5 +-
.../kernel/generic/scsi_periph/scsi_periph_int.h |   4 +-
src/add-ons/kernel/network/stack/utility.cpp     |   5 +-
src/bin/Jamfile                                  |   1 +
src/bin/fstrim.cpp                               |  82 ++++++

############################################################################

Commit:      29a845084326c35014460ab2c3cb23c89d239d38
URL:         http://cgit.haiku-os.org/haiku/commit/?id=29a8450
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Sun Aug  4 21:19:43 2013 UTC

Added B_TRIM_DEVICE ioctl.

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

diff --git a/headers/os/drivers/Drivers.h b/headers/os/drivers/Drivers.h
index 3484dbf..ff4e1e0 100644
--- a/headers/os/drivers/Drivers.h
+++ b/headers/os/drivers/Drivers.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2011, Haiku Inc. All Rights Reserved.
+ * Copyright 2002-2013, Haiku Inc. All Rights Reserved.
  * Distributed under the terms of the MIT License.
  */
 #ifndef _DRIVERS_DRIVERS_H
@@ -106,6 +106,7 @@ enum {
        B_GET_ICON_NAME,                                /* get an icon name 
identifier */
        B_GET_VECTOR_ICON,                              /* retrieves the 
device's vector icon */
        B_GET_DEVICE_NAME,                              /* get name, string 
buffer */
+       B_TRIM_DEVICE,                                  /* trims blocks, see 
fs_trim_data */
 
        B_GET_NEXT_OPEN_DEVICE = 1000,  /* obsolete, will be removed */
        B_ADD_FIXED_DRIVER,                             /* obsolete, will be 
removed */
@@ -169,6 +170,14 @@ typedef struct {
 } device_icon;
 
 
+/* B_TRIM_DEVICE data structure */
+typedef struct {
+       off_t   offset;                                 /* offset (in bytes) */
+       off_t   size;
+       off_t   trimmed_size;                   /* filled on return */
+} fs_trim_data;
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/headers/private/fs_shell/fssh_api_wrapper.h 
b/headers/private/fs_shell/fssh_api_wrapper.h
index edb40a9..b0d9a3d 100644
--- a/headers/private/fs_shell/fssh_api_wrapper.h
+++ b/headers/private/fs_shell/fssh_api_wrapper.h
@@ -435,6 +435,10 @@
 #define B_SET_INTERRUPTABLE_IO         FSSH_B_SET_INTERRUPTABLE_IO
 #define B_FLUSH_DRIVE_CACHE                    FSSH_B_FLUSH_DRIVE_CACHE
 #define B_GET_PATH_FOR_DEVICE          FSSH_B_GET_PATH_FOR_DEVICE
+#define B_GET_ICON_NAME                                FSSH_B_GET_ICON_NAME
+#define B_GET_VECTOR_ICON                      FSSH_B_GET_VECTOR_ICON
+#define B_GET_DEVICE_NAME                      FSSH_B_GET_DEVICE_NAME
+#define B_TRIM_DEVICE                          FSSH_B_TRIM_DEVICE
 #define B_GET_NEXT_OPEN_DEVICE         FSSH_B_GET_NEXT_OPEN_DEVICE
 #define B_ADD_FIXED_DRIVER                     FSSH_B_ADD_FIXED_DRIVER
 #define B_REMOVE_FIXED_DRIVER          FSSH_B_REMOVE_FIXED_DRIVER
@@ -462,6 +466,7 @@
 #define driver_path                            fssh_driver_path
 #define open_device_iterator   fssh_open_device_iterator
 #define device_icon                            fssh_device_icon
+#define fs_trim_data                   fssh_fs_trim_data
 
 
 
////////////////////////////////////////////////////////////////////////////////
diff --git a/headers/private/fs_shell/fssh_drivers.h 
b/headers/private/fs_shell/fssh_drivers.h
index a4d25bb..aa63da3 100644
--- a/headers/private/fs_shell/fssh_drivers.h
+++ b/headers/private/fs_shell/fssh_drivers.h
@@ -60,7 +60,7 @@ fssh_status_t         fssh_init_hardware(void);
 const char               **fssh_publish_devices(void);
 fssh_device_hooks      *fssh_find_device(const char *name);
 fssh_status_t          fssh_init_driver(void);
-void                           fssh_uninit_driver(void);       
+void                           fssh_uninit_driver(void);
 
 extern int32_t fssh_api_version;
 
@@ -111,17 +111,20 @@ enum {
                                                                                
/* B_DEV_MEDIA_CHANGE_REQUESTED: user */
                                                                                
/*  pressed button on drive */
                                                                                
/* B_DEV_DOOR_OPEN: door open */
-       
+
        FSSH_B_LOAD_MEDIA,                                      /* load the 
media if supported */
-       
+
        FSSH_B_GET_BIOS_DRIVE_ID,                       /* get bios id for this 
device */
 
        FSSH_B_SET_UNINTERRUPTABLE_IO,          /* prevent cntl-C from 
interrupting i/o */
        FSSH_B_SET_INTERRUPTABLE_IO,            /* allow cntl-C to interrupt 
i/o */
 
        FSSH_B_FLUSH_DRIVE_CACHE,                       /* flush drive cache */
-
        FSSH_B_GET_PATH_FOR_DEVICE,                     /* get the absolute 
path of the device */
+       FSSH_B_GET_ICON_NAME,                           /* get an icon name 
identifier */
+       FSSH_B_GET_VECTOR_ICON,                         /* retrieves the 
device's vector icon */
+       FSSH_B_GET_DEVICE_NAME,                         /* get name, string 
buffer */
+       FSSH_B_TRIM_DEVICE,                                     /* trims 
blocks, see fs_trim_data */
 
        FSSH_B_GET_NEXT_OPEN_DEVICE = 1000,     /* iterate through open devices 
*/
        FSSH_B_ADD_FIXED_DRIVER,                        /* private */
@@ -196,7 +199,7 @@ typedef char        fssh_driver_path[256];
 
 typedef struct {
        uint32_t        cookie;                 /* must be set to 0 before 
iterating */
-       char            device[256];    /* device path */       
+       char            device[256];    /* device path */
 } fssh_open_device_iterator;
 
 
@@ -210,6 +213,14 @@ typedef struct {
 } fssh_device_icon;
 
 
+/* B_TRIM_DEVICE data structure */
+typedef struct {
+       fssh_off_t      offset;                                 /* offset (in 
bytes) */
+       fssh_off_t      size;
+       fssh_off_t      trimmed_size;                   /* filled on return */
+} fssh_fs_trim_data;
+
+
 #ifdef __cplusplus
 }
 #endif

############################################################################

Commit:      a352b438960f14e070d0850080706f9930dcd30f
URL:         http://cgit.haiku-os.org/haiku/commit/?id=a352b43
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Sun Aug  4 22:14:52 2013 UTC

Added fstrim command.

Later, there should be a service that runs this from time to time for all
devices that support it.

Conflicts:
        build/jam/HaikuImage

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

diff --git a/build/jam/images/HaikuImage b/build/jam/images/HaikuImage
index 3dd454f..74bfa6d 100644
--- a/build/jam/images/HaikuImage
+++ b/build/jam/images/HaikuImage
@@ -13,7 +13,7 @@ SYSTEM_BIN = [ FFilterByBuildFeatures
        diskimage draggers driveinfo dstcheck du dumpcatalog
        echo eject env error expand expr
        factor false fdinfo ffm filepanel find finddir findpaths 
FirstBootPrompt fmt
-       fold fortune frcode ftp ftpd funzip fwcontrol@x86
+       fold fortune frcode fstrim ftp ftpd funzip fwcontrol@x86
        gawk gdb@x86 getlimits groupadd groupdel groupmod groups gzip gzexe
        hd head hey hostname
        id ident ifconfig <bin>install installsound iroster isvolume
diff --git a/src/bin/Jamfile b/src/bin/Jamfile
index aeb8a76..e2fb698 100644
--- a/src/bin/Jamfile
+++ b/src/bin/Jamfile
@@ -35,6 +35,7 @@ StdBinCommands
        error.c
        fortune.c
        finddir.c
+       fstrim.cpp
        hd.c
        idestatus.c
        listarea.c
diff --git a/src/bin/fstrim.cpp b/src/bin/fstrim.cpp
new file mode 100644
index 0000000..d5dda26
--- /dev/null
+++ b/src/bin/fstrim.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Distributed under the terms of the MIT license.
+ */
+
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <Drivers.h>
+
+#include <AutoDeleter.h>
+
+
+static struct option const kLongOptions[] = {
+       {"help", no_argument, 0, 'h'},
+       {NULL}
+};
+
+
+extern const char *__progname;
+static const char *kProgramName = __progname;
+
+
+void
+usage(int returnValue)
+{
+       fprintf(stderr, "Usage: %s <path-to-mounted-file-system>\n", 
kProgramName);
+       exit(returnValue);
+}
+
+
+int
+main(int argc, char** argv)
+{
+       int c;
+       while ((c = getopt_long(argc, argv, "h", kLongOptions, NULL)) != -1) {
+               switch (c) {
+                       case 0:
+                               break;
+                       case 'h':
+                               usage(0);
+                               break;
+                       default:
+                               usage(1);
+                               break;
+               }
+       }
+
+       if (argc - optind < 1)
+               usage(1);
+       const char* path = argv[optind++];
+
+       int fd = open(path, O_RDONLY);
+       if (fd < 0) {
+               fprintf(stderr, "%s: Could not access path: %s\n", kProgramName,
+                       strerror(errno));
+               return EXIT_FAILURE;
+       }
+
+       FileDescriptorCloser closer(fd);
+
+       fs_trim_data trimData;
+       trimData.offset = 0;
+       trimData.size = OFF_MAX;
+       trimData.trimmed_size = 0;
+
+       if (ioctl(fd, B_TRIM_DEVICE, &trimData, sizeof(fs_trim_data)) != 0) {
+               fprintf(stderr, "%s: Trimming failed: %s\n", kProgramName,
+                       strerror(errno));
+               return EXIT_FAILURE;
+       }
+
+       printf("Trimmed %lld bytes from device.\n", trimData.trimmed_size);
+       return EXIT_SUCCESS;
+}

############################################################################

Commit:      0a0ba4b5f09da93410943578b6c5aa1f3aa60cb0
URL:         http://cgit.haiku-os.org/haiku/commit/?id=0a0ba4b
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Sun Aug  4 22:16:54 2013 UTC

Added B_TRIM_DEVICE support to BFS.

* It currently ignores the offset/size, though, and always trims everything.
* Now only SCSI support is missing.

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

diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp 
b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp
index a6aceca..432df6c 100644
--- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2012, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2001-2013, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
  * This file may be used under the terms of the MIT License.
  */
 
@@ -1190,6 +1190,62 @@ BlockAllocator::_CheckGroup(int32 groupIndex) const
 #endif // DEBUG_ALLOCATION_GROUPS
 
 
+status_t
+BlockAllocator::Trim(off_t offset, off_t size, off_t& trimmedSize)
+{
+       RecursiveLocker locker(fLock);
+
+       // TODO: take given offset and size into account!
+       int32 lastGroup = fNumGroups - 1;
+       uint32 firstBlock = 0;
+       uint32 firstBit = 0;
+       off_t currentBlock = 0;
+       uint32 blockShift = fVolume->BlockShift();
+
+       off_t firstFree = -1;
+       size_t freeLength = 0;
+       trimmedSize = 0;
+
+       AllocationBlock cached(fVolume);
+       for (int32 groupIndex = 0; groupIndex <= lastGroup; groupIndex++) {
+               AllocationGroup& group = fGroups[groupIndex];
+
+               for (uint32 block = firstBlock; block < group.NumBlocks(); 
block++) {
+                       cached.SetTo(group, block);
+
+                       for (uint32 i = firstBit; i < cached.NumBlockBits(); 
i++) {
+                               if (cached.IsUsed(i)) {
+                                       // Block is in use
+                                       if (freeLength > 0) {
+                                               status_t status = 
_TrimNext(firstFree << blockShift,
+                                                       freeLength << 
blockShift, trimmedSize);
+                                               if (status != B_OK)
+                                                       return status;
+
+                                               freeLength = 0;
+                                       }
+                               } else if (freeLength++ == 0) {
+                                       // Block is free, start new free range
+                                       firstFree = currentBlock;
+                               }
+
+                               currentBlock++;
+                       }
+               }
+
+               firstBlock = 0;
+               firstBit = 0;
+       }
+
+       if (freeLength > 0) {
+               return _TrimNext(firstFree << blockShift, freeLength << 
blockShift,
+                       trimmedSize);
+       }
+
+       return B_OK;
+}
+
+
 //     #pragma mark - Bitmap validity checking
 
 // TODO: implement new FS checking API
@@ -2124,6 +2180,26 @@ BlockAllocator::_AddInodeToIndex(Inode* inode)
 }
 
 
+status_t
+BlockAllocator::_TrimNext(off_t offset, off_t size, off_t& trimmedSize)
+{
+       PRINT(("_TrimNext(offset %lld, size %lld)\n", offset, size));
+
+       fs_trim_data trimData;
+       trimData.offset = offset;
+       trimData.size = size;
+       trimData.trimmed_size = 0;
+
+       if (ioctl(fVolume->Device(), B_TRIM_DEVICE, &trimData,
+                       sizeof(fs_trim_data)) != 0) {
+               return errno;
+       }
+
+       trimmedSize += trimData.trimmed_size;
+       return B_OK;
+}
+
+
 //     #pragma mark - debugger commands
 
 
diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h 
b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h
index ba490ba..88b9d52 100644
--- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h
+++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2012, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2001-2013, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
  * This file may be used under the terms of the MIT License.
  */
 #ifndef BLOCK_ALLOCATOR_H
@@ -46,6 +46,8 @@ public:
                                                                int32 group, 
uint16 start, uint16 numBlocks,
                                                                uint16 minimum, 
block_run& run);
 
+                       status_t                Trim(off_t offset, off_t size, 
off_t& trimmedSize);
+
                        status_t                StartChecking(const 
check_control* control);
                        status_t                StopChecking(check_control* 
control);
                        status_t                CheckNextNode(check_control* 
control);
@@ -81,6 +83,8 @@ private:
                        void                    _FreeIndices();
                        status_t                _AddInodeToIndex(Inode* inode);
                        status_t                _WriteBackCheckBitmap();
+                       status_t                _TrimNext(off_t offset, off_t 
size,
+                                                               off_t& 
trimmedSize);
 
        static  status_t                _Initialize(BlockAllocator* self);
 
diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp 
b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp
index 6504c99..1140003 100644
--- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2010, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2001-2013, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
  * This file may be used under the terms of the MIT License.
  */
 
@@ -623,6 +623,20 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* 
_cookie, uint32 cmd,
        Volume* volume = (Volume*)_volume->private_volume;
 
        switch (cmd) {
+               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 = 
volume->Allocator().Trim(trimData.offset,
+                               trimData.size, trimData.trimmed_size);
+                       if (status != B_OK)
+                               return status;
+
+                       return user_memcpy(buffer, &trimData, 
sizeof(fs_trim_data));
+               }
+
                case BFS_IOCTL_VERSION:
                {
                        uint32 version = 0x10000;

############################################################################

Commit:      960c56aea53d8a930ab5dbbd3265e2b14e04e0ae
URL:         http://cgit.haiku-os.org/haiku/commit/?id=960c56a
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Sun Aug  4 22:51:37 2013 UTC

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.

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

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

############################################################################

Commit:      99086aa32333be5792b0f059ccbbe3c90be05ea6
URL:         http://cgit.haiku-os.org/haiku/commit/?id=99086aa
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Wed Aug 14 23:34:59 2013 UTC

trim: Target SCSI UNMAP command instead of WRITE SAME.

* The UNMAP command is theoretically much faster, as it can get many block
  ranges instead of just a single range.
* Furthermore, the ATA TRIM command resembles it much better.
* Therefore, fs_trim_data now gets an array of ranges, and we use SCSI UNMAP
  to trim.
* Updated BFS code to collect array ranges to fully support the new
  fs_trim_data possibilities.

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

diff --git a/headers/os/drivers/Drivers.h b/headers/os/drivers/Drivers.h
index ff4e1e0..a854305 100644
--- a/headers/os/drivers/Drivers.h
+++ b/headers/os/drivers/Drivers.h
@@ -172,9 +172,12 @@ typedef struct {
 
 /* B_TRIM_DEVICE data structure */
 typedef struct {
-       off_t   offset;                                 /* offset (in bytes) */
-       off_t   size;
-       off_t   trimmed_size;                   /* filled on return */
+       uint32  range_count;
+       uint64  trimmed_size;                   /* filled on return */
+       struct range {
+               uint64  offset;                         /* offset (in bytes) */
+               uint64  size;
+       } ranges[1];
 } fs_trim_data;
 
 
diff --git a/headers/private/drivers/scsi_cmds.h 
b/headers/private/drivers/scsi_cmds.h
index ea45233..732583d 100644
--- a/headers/private/drivers/scsi_cmds.h
+++ b/headers/private/drivers/scsi_cmds.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2010, 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.
@@ -185,6 +185,8 @@
 #define SCSI_OP_WRITE_BUFFER                           0x3b
 #define SCSI_OP_READ_BUFFER                                    0x3c
 #define SCSI_OP_CHANGE_DEFINITION                      0x40
+#define SCSI_OP_WRITE_SAME_10                          0x41
+#define SCSI_OP_UNMAP                                          0x42
 #define SCSI_OP_READ_SUB_CHANNEL                       0x42
 #define SCSI_OP_READ_TOC                                       0x43
 #define SCSI_OP_PLAY_MSF                                       0x47
@@ -457,7 +459,38 @@ typedef struct scsi_cmd_wsame_16 {
        );
        uint8   control;
 } _PACKED scsi_cmd_wsame_16;
-       
+
+
+// UNMAP
+
+typedef struct scsi_cmd_unmap {
+       uint8   opcode;
+       LBITFIELD8_2(
+               anchor : 1,
+               _reserved1_7 : 7
+       );
+       uint32  _reserved1;
+       LBITFIELD8_2(
+               group_number : 5,
+               _reserved5_7 : 3
+       );
+       uint16  length;
+       uint8   control;
+} _PACKED scsi_cmd_unmap;
+
+struct scsi_unmap_block_descriptor {
+       uint64  lba;
+       uint32  block_count;
+       uint32  _reserved1;
+} _PACKED;
+
+struct scsi_unmap_parameter_list {
+       uint16  data_length;
+       uint16  block_data_length;
+       uint32  _reserved1;
+       struct scsi_unmap_block_descriptor blocks[1];
+} _PACKED;
+
 
 // REQUEST SENSE
 
diff --git a/headers/private/drivers/scsi_periph.h 
b/headers/private/drivers/scsi_periph.h
index b879521..9be19ab 100644
--- a/headers/private/drivers/scsi_periph.h
+++ b/headers/private/drivers/scsi_periph.h
@@ -72,6 +72,10 @@ typedef struct scsi_periph_callbacks {
        void (*media_changed)(periph_device_cookie cookie, scsi_ccb *request);
 } scsi_periph_callbacks;
 
+typedef struct scsi_block_range {
+       uint64  offset;
+       uint64  size;
+} scsi_block_range;
 
 // functions provided by this module
 typedef struct scsi_periph_interface {
@@ -119,7 +123,7 @@ typedef struct scsi_periph_interface {
        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);
+               scsi_block_range* ranges, uint32 rangeCount);
 
        // *** removable media ***
        // to be called when a medium change is detected to block subsequent 
commands
diff --git a/headers/private/fs_shell/fssh_drivers.h 
b/headers/private/fs_shell/fssh_drivers.h
index aa63da3..aa67e69 100644
--- a/headers/private/fs_shell/fssh_drivers.h
+++ b/headers/private/fs_shell/fssh_drivers.h
@@ -215,9 +215,12 @@ typedef struct {
 
 /* B_TRIM_DEVICE data structure */
 typedef struct {
-       fssh_off_t      offset;                                 /* offset (in 
bytes) */
-       fssh_off_t      size;
-       fssh_off_t      trimmed_size;                   /* filled on return */
+       uint32_t        range_count;
+       uint64_t        trimmed_size;                   /* filled on return */
+       struct range {
+               uint64_t        offset;                         /* offset (in 
bytes) */
+               uint64_t        size;
+       } ranges[1];
 } fssh_fs_trim_data;
 
 
diff --git a/headers/private/kernel/util/fs_trim_support.h 
b/headers/private/kernel/util/fs_trim_support.h
new file mode 100644
index 0000000..a9f993c
--- /dev/null
+++ b/headers/private/kernel/util/fs_trim_support.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2013, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Distributed under the terms of the MIT license.
+ */
+#ifndef _FS_TRIM_SUPPORT_H
+#define _FS_TRIM_SUPPORT_H
+
+
+#include <Drivers.h>
+
+#include <kernel.h>
+
+
+static inline status_t
+copy_trim_data_from_user(void* buffer, size_t size, fs_trim_data*& _trimData)
+{
+       if (!IS_USER_ADDRESS(buffer))
+               return B_BAD_ADDRESS;
+
+       uint32 count;
+       if (user_memcpy(&count, buffer, sizeof(count)) != B_OK)
+               return B_BAD_ADDRESS;
+
+       size_t bytes = (count - 1) * sizeof(uint64) * 2 + sizeof(fs_trim_data);
+       if (bytes > size)
+               return B_BAD_VALUE;
+
+       void* trimBuffer = malloc(bytes);
+       if (trimBuffer == NULL)
+               return B_NO_MEMORY;
+
+       if (user_memcpy(trimBuffer, buffer, bytes) != B_OK)
+               return B_BAD_ADDRESS;
+
+       _trimData = (fs_trim_data*)trimBuffer;
+       return B_OK;
+}
+
+
+static inline status_t
+copy_trim_data_to_user(void* buffer, fs_trim_data* trimData)
+{
+       // Do not copy any ranges
+       return user_memcpy(buffer, trimData, sizeof(uint64) * 2);
+}
+
+
+#endif // _FS_TRIM_SUPPORT_H
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 c566396..f445764 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
@@ -21,7 +21,10 @@
 #include <string.h>
 #include <stdlib.h>
 
+#include <AutoDeleter.h>
+
 #include <fs/devfs.h>
+#include <util/fs_trim_support.h>
 
 #include "dma_resources.h"
 #include "IORequest.h"
@@ -154,7 +157,7 @@ synchronize_cache(das_driver_info *device)
 
 
 static status_t
-trim_device(das_driver_info* device, off_t offset, off_t size)
+trim_device(das_driver_info* device, fs_trim_data* trimData)
 {
        TRACE("trim_device()\n");
 
@@ -162,10 +165,17 @@ trim_device(das_driver_info* device, off_t offset, off_t 
size)
        if (request == NULL)
                return B_NO_MEMORY;
 
+       uint64 trimmedSize = 0;
+       for (uint32 i = 0; i < trimData->range_count; i++) {
+               trimmedSize += trimData->ranges[i].size;
+       }
        status_t status = 
sSCSIPeripheral->trim_device(device->scsi_periph_device,
-               request, offset / device->block_size, size / 
device->block_size);
+               request, (scsi_block_range*)&trimData->ranges[0],
+               trimData->range_count);
 
        device->scsi->free_ccb(request);
+       if (status == B_OK)
+               trimData->trimmed_size = trimmedSize;
 
        return status;
 }
@@ -405,17 +415,19 @@ das_ioctl(void* cookie, uint32 op, void* buffer, size_t 
length)
 
                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);
+                       fs_trim_data* trimData;
+                       status_t status = copy_trim_data_from_user(buffer, 
length,
+                               trimData);
                        if (status != B_OK)
                                return status;
 
-                       trimData.trimmed_size = trimData.size;
+                       MemoryDeleter deleter(trimData);
+
+                       status = trim_device(info, trimData);
+                       if (status != B_OK)
+                               return status;
 
-                       return user_memcpy(buffer, &trimData, 
sizeof(fs_trim_data));
+                       return copy_trim_data_to_user(buffer, trimData);
                }
 
                default:
diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp 
b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp
index 432df6c..31dd753 100644
--- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.cpp
@@ -1191,19 +1191,28 @@ BlockAllocator::_CheckGroup(int32 groupIndex) const
 
 
 status_t
-BlockAllocator::Trim(off_t offset, off_t size, off_t& trimmedSize)
+BlockAllocator::Trim(uint64 offset, uint64 size, uint64& trimmedSize)
 {
+       const uint32 kTrimRanges = 128;
+       fs_trim_data* trimData = (fs_trim_data*)malloc(sizeof(fs_trim_data)
+               + sizeof(uint64) * kTrimRanges);
+       if (trimData == NULL)
+               return B_NO_MEMORY;
+
+       MemoryDeleter deleter(trimData);
        RecursiveLocker locker(fLock);
 
        // TODO: take given offset and size into account!
        int32 lastGroup = fNumGroups - 1;
        uint32 firstBlock = 0;
        uint32 firstBit = 0;
-       off_t currentBlock = 0;
+       uint64 currentBlock = 0;
        uint32 blockShift = fVolume->BlockShift();
 
-       off_t firstFree = -1;
+       uint64 firstFree = 0;
        size_t freeLength = 0;
+
+       trimData->range_count = 0;
        trimmedSize = 0;
 
        AllocationBlock cached(fVolume);
@@ -1217,8 +1226,9 @@ BlockAllocator::Trim(off_t offset, off_t size, off_t& 
trimmedSize)
                                if (cached.IsUsed(i)) {
                                        // Block is in use
                                        if (freeLength > 0) {
-                                               status_t status = 
_TrimNext(firstFree << blockShift,
-                                                       freeLength << 
blockShift, trimmedSize);
+                                               status_t status = 
_TrimNext(*trimData, kTrimRanges,
+                                                       firstFree << 
blockShift, freeLength << blockShift,
+                                                       false, trimmedSize);
                                                if (status != B_OK)
                                                        return status;
 
@@ -1237,12 +1247,8 @@ BlockAllocator::Trim(off_t offset, off_t size, off_t& 
trimmedSize)
                firstBit = 0;
        }
 
-       if (freeLength > 0) {
-               return _TrimNext(firstFree << blockShift, freeLength << 
blockShift,
-                       trimmedSize);
-       }
-
-       return B_OK;
+       return _TrimNext(*trimData, kTrimRanges, firstFree << blockShift,
+               freeLength << blockShift, true, trimmedSize);
 }
 
 
@@ -2181,21 +2187,44 @@ BlockAllocator::_AddInodeToIndex(Inode* inode)
 
 
 status_t
-BlockAllocator::_TrimNext(off_t offset, off_t size, off_t& trimmedSize)
+BlockAllocator::_AddTrim(fs_trim_data& trimData, uint32 maxRanges,
+       uint64 offset, uint64 size)
 {
-       PRINT(("_TrimNext(offset %lld, size %lld)\n", offset, size));
+       if (trimData.range_count < maxRanges && size > 0) {
+               trimData.ranges[trimData.range_count].offset = offset;
+               trimData.ranges[trimData.range_count].size = size;
+               trimData.range_count++;
+               return true;
+       }
 
-       fs_trim_data trimData;
-       trimData.offset = offset;
-       trimData.size = size;
-       trimData.trimmed_size = 0;
+       return false;
+}
 
-       if (ioctl(fVolume->Device(), B_TRIM_DEVICE, &trimData,
-                       sizeof(fs_trim_data)) != 0) {
-               return errno;
+
+status_t
+BlockAllocator::_TrimNext(fs_trim_data& trimData, uint32 maxRanges,
+       uint64 offset, uint64 size, bool force, uint64& trimmedSize)
+{
+       PRINT(("_TrimNext(index %" B_PRIu32 ", offset %" B_PRIu64 ", size %"
+               B_PRIu64 ")\n", trimData.range_count, offset, size));
+
+       bool pushed = _AddTrim(trimData, maxRanges, offset, size);
+
+       if (!pushed || force) {
+               // Trim now
+               trimData.trimmed_size = 0;
+               if (ioctl(fVolume->Device(), B_TRIM_DEVICE, &trimData,
+                               sizeof(fs_trim_data)) != 0) {
+                       return errno;
+               }
+
+               trimmedSize += trimData.trimmed_size;
+               trimData.range_count = 0;
        }
 
-       trimmedSize += trimData.trimmed_size;
+       if (!pushed)
+               _AddTrim(trimData, maxRanges, offset, size);
+
        return B_OK;
 }
 
diff --git a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h 
b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h
index 88b9d52..d3da867 100644
--- a/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h
+++ b/src/add-ons/kernel/file_systems/bfs/BlockAllocator.h
@@ -46,7 +46,8 @@ public:
                                                                int32 group, 
uint16 start, uint16 numBlocks,
                                                                uint16 minimum, 
block_run& run);
 
-                       status_t                Trim(off_t offset, off_t size, 
off_t& trimmedSize);
+                       status_t                Trim(uint64 offset, uint64 size,
+                                                               uint64& 
trimmedSize);
 
                        status_t                StartChecking(const 
check_control* control);
                        status_t                StopChecking(check_control* 
control);
@@ -83,8 +84,11 @@ private:
                        void                    _FreeIndices();
                        status_t                _AddInodeToIndex(Inode* inode);
                        status_t                _WriteBackCheckBitmap();
-                       status_t                _TrimNext(off_t offset, off_t 
size,
-                                                               off_t& 
trimmedSize);
+                       status_t                _AddTrim(fs_trim_data& 
trimData, uint32 maxRanges,
+                                                               uint64 offset, 
uint64 size);
+                       status_t                _TrimNext(fs_trim_data& 
trimData, uint32 maxRanges,
+                                                               uint64 offset, 
uint64 size, bool force,
+                                                               uint64& 
trimmedSize);
 
        static  status_t                _Initialize(BlockAllocator* self);
 
diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp 
b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp
index 1140003..ab68d57 100644
--- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp
+++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp
@@ -20,8 +20,10 @@
 // TODO: temporary solution as long as there is no public I/O requests API
 #ifndef BFS_SHELL
 #      include <io_requests.h>
+#      include <util/fs_trim_support.h>
 #endif
 
+
 #define BFS_IO_SIZE    65536
 
 
@@ -623,19 +625,32 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* 
_cookie, uint32 cmd,
        Volume* volume = (Volume*)_volume->private_volume;
 
        switch (cmd) {
+#ifndef BFS_SHELL
                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 = 
volume->Allocator().Trim(trimData.offset,
-                               trimData.size, trimData.trimmed_size);
+                       fs_trim_data* trimData;
+                       status_t status = copy_trim_data_from_user(buffer, 
bufferLength,
+                               trimData);
                        if (status != B_OK)
                                return status;
 
-                       return user_memcpy(buffer, &trimData, 
sizeof(fs_trim_data));
+                       MemoryDeleter deleter(trimData);
+                       trimData->trimmed_size = 0;
+
+                       for (uint32 i = 0; i < trimData->range_count; i++) {
+                               uint64 trimmedSize = 0;
+                               status_t status = volume->Allocator().Trim(
+                                       trimData->ranges[i].offset, 
trimData->ranges[i].size,
+                                       trimmedSize);
+                               if (status != B_OK)
+                                       return status;
+
+                               trimData->trimmed_size += trimmedSize;
+                       }
+
+                       return copy_trim_data_to_user(buffer, trimData);
                }
+#endif
 
                case BFS_IOCTL_VERSION:
                {
diff --git a/src/add-ons/kernel/generic/scsi_periph/Jamfile 
b/src/add-ons/kernel/generic/scsi_periph/Jamfile
index 2aaa529..5fd764c 100644
--- a/src/add-ons/kernel/generic/scsi_periph/Jamfile
+++ b/src/add-ons/kernel/generic/scsi_periph/Jamfile
@@ -1,6 +1,6 @@
 SubDir HAIKU_TOP src add-ons kernel generic scsi_periph ;
 
-UsePrivateHeaders drivers kernel ;
+UsePrivateHeaders drivers kernel shared ;
 SubDirHdrs $(HAIKU_TOP) src system kernel device_manager ;
 
 # disable debug output, if debugging is disabled
diff --git a/src/add-ons/kernel/generic/scsi_periph/block.cpp 
b/src/add-ons/kernel/generic/scsi_periph/block.cpp
index 0c6eb0d..7f6cfcd 100644
--- a/src/add-ons/kernel/generic/scsi_periph/block.cpp
+++ b/src/add-ons/kernel/generic/scsi_periph/block.cpp
@@ -9,9 +9,12 @@
 //!    Handling of block device
 
 
-#include "scsi_periph_int.h"
 #include <string.h>
 
+#include <AutoDeleter.h>
+
+#include "scsi_periph_int.h"
+
 
 status_t
 periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *request)
@@ -117,23 +120,53 @@ periph_check_capacity(scsi_periph_device_info *device, 
scsi_ccb *request)
 
 status_t
 periph_trim_device(scsi_periph_device_info *device, scsi_ccb *request,
-       uint64 offset, uint64 numBlocks)
+       scsi_block_range* ranges, uint32 rangeCount)
 {
        err_res res;
        int retries = 0;
 
+       size_t unmapBlockSize = (rangeCount - 1)
+                       * sizeof(scsi_unmap_block_descriptor)
+               + sizeof(scsi_unmap_parameter_list);
+
+       // TODO: check block limits VPD page
+       // TODO: instead of failing, we should try to complete the request in
+       // several passes.
+       if (unmapBlockSize > 65536 || rangeCount == 0)
+               return B_BAD_VALUE;
+
+       scsi_unmap_parameter_list* unmapBlocks
+               = (scsi_unmap_parameter_list*)malloc(unmapBlockSize);
+       if (unmapBlocks == NULL)
+               return B_NO_MEMORY;
+
+       MemoryDeleter deleter(unmapBlocks);
+
+       // Prepare request data
+       memset(unmapBlocks, 0, unmapBlockSize);
+       unmapBlocks->data_length = B_HOST_TO_BENDIAN_INT16(unmapBlockSize - 1);
+       unmapBlocks->data_length = B_HOST_TO_BENDIAN_INT16(unmapBlockSize - 3);
+
+       for (uint32 i = 0; i < rangeCount; i++) {
+               unmapBlocks->blocks[i].lba = B_HOST_TO_BENDIAN_INT64(
+                       ranges[i].offset / device->block_size);
+               unmapBlocks->blocks[i].block_count = B_HOST_TO_BENDIAN_INT32(
+                       ranges[i].size / device->block_size);
+       }
+
        do {
                request->flags = SCSI_DIR_OUT;
-               request->sort = offset;
+               request->sort = ranges[0].offset / device->block_size;
                request->timeout = device->std_timeout;
 
-               scsi_cmd_wsame_16* cmd = (scsi_cmd_wsame_16*)request->cdb;
+               scsi_cmd_unmap* cmd = (scsi_cmd_unmap*)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);
+               cmd->opcode = SCSI_OP_UNMAP;
+               cmd->length = B_HOST_TO_BENDIAN_INT16(unmapBlockSize);
+
+               request->data = (uint8*)unmapBlocks;
+               request->data_length = unmapBlockSize;
 
                request->cdb_length = sizeof(*cmd);
 
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 30df67a..af032b4 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
@@ -78,7 +78,7 @@ status_t periph_handle_free(scsi_periph_handle_info *handle);
 
 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);
+       scsi_block_range* ranges, uint32 rangeCount);
 
 
 // device.c
diff --git a/src/bin/fstrim.cpp b/src/bin/fstrim.cpp
index d5dda26..cc0b47f 100644
--- a/src/bin/fstrim.cpp
+++ b/src/bin/fstrim.cpp
@@ -7,7 +7,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <getopt.h>
-#include <limits.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -66,8 +66,9 @@ main(int argc, char** argv)
        FileDescriptorCloser closer(fd);
 
        fs_trim_data trimData;
-       trimData.offset = 0;
-       trimData.size = OFF_MAX;
+       trimData.range_count = 1;
+       trimData.ranges[0].offset = 0;
+       trimData.ranges[0].size = UINT64_MAX;
        trimData.trimmed_size = 0;
 
        if (ioctl(fd, B_TRIM_DEVICE, &trimData, sizeof(fs_trim_data)) != 0) {

############################################################################

Commit:      33945c5c8993bedfe46a43a12f27e8178c249dd6
URL:         http://cgit.haiku-os.org/haiku/commit/?id=33945c5
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Wed Aug 14 23:40:12 2013 UTC

ahci: Pushed TRIM support a tiny bit further.

* Now doesn't do anything on SCSI_OP_UNMAP, instead of doing nothing on
  SCSI_OP_WRITE_SAME_16.

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
index ecc84d0..f3de1bb 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
@@ -51,7 +51,7 @@ AHCIPort::AHCIPort(AHCIController *controller, int index)
        fTestUnitReadyActive(false),
        fResetPort(false),
        fError(false),
-       fTrim(false)
+       fTrimSupported(false)
 {
        B_INITIALIZE_SPINLOCK(&fSpinlock);
        fRequestSem = create_sem(1, "ahci request");
@@ -604,7 +604,7 @@ AHCIPort::ScsiInquiry(scsi_ccb *request)
        if (!fIsATAPI) {
                fSectorCount = ataData.SectorCount(fUse48BitCommands, true);
                fSectorSize = ataData.SectorSize();
-               fTrim = ataData.data_set_management_support;
+               fTrimSupported = ataData.data_set_management_support;
                TRACE("lba %d, lba48 %d, fUse48BitCommands %d, sectors %" 
B_PRIu32
                        ", sectors48 %" B_PRIu64 ", size %" B_PRIu64 "\n",
                        ataData.dma_supported != 0, ataData.lba48_supported != 
0,
@@ -634,7 +634,7 @@ AHCIPort::ScsiInquiry(scsi_ccb *request)
        TRACE("model number: %s\n", modelNumber);
        TRACE("serial number: %s\n", serialNumber);
        TRACE("firmware rev.: %s\n", firmwareRev);
-       TRACE("trim support: %s\n", fTrim ? "yes" : "no");
+       TRACE("trim support: %s\n", fTrimSupported ? "yes" : "no");
 
        // There's not enough space to fit all of the data in. ATA has 40 bytes 
for
        // the model number, 20 for the serial number and another 8 for the
@@ -787,6 +787,23 @@ AHCIPort::ScsiReadWrite(scsi_ccb *request, uint64 lba, 
size_t sectorCount,
 
 
 void
+AHCIPort::ScsiUnmap(scsi_ccb* request, scsi_unmap_parameter_list* unmapBlocks)
+{
+       TRACE("%s unimplemented: TRIM call\n", __func__);
+
+       sata_request* sreq = new(std::nothrow) sata_request(request);
+       if (sreq == NULL) {
+               TRACE("out of memory when allocating unmap request\n");
+               request->subsys_status = SCSI_REQ_ABORTED;
+               gSCSI->finished(request, 1);
+               return;
+       }
+
+       delete sreq;
+}
+
+
+void
 AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite)
 {
        FLOW("ExecuteAtaRequest port %d\n", fIndex);
@@ -1018,12 +1035,11 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
                        }
                        break;
                }
-               case SCSI_OP_WRITE_SAME_16:
+               case SCSI_OP_UNMAP:
                {
-                       const scsi_cmd_wsame_16 *cmd = (const scsi_cmd_wsame_16 
*)request->cdb;
+                       const scsi_cmd_unmap* cmd = (const 
scsi_cmd_unmap*)request->cdb;
 
-                       // SCSI unmap is used for trim, otherwise we don't 
support it
-                       if (!cmd->unmap) {
+                       if (!fTrimSupported) {
                                TRACE("%s port %d: unsupported request opcode 
0x%02x\n",
                                        __func__, fIndex, request->cdb[0]);
                                request->subsys_status = SCSI_REQ_ABORTED;
@@ -1031,16 +1047,19 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
                                break;
                        }
 
-                       if (!fTrim) {
-                               // Drive doesn't support trim (or atapi)
-                               // Just say it was successful and quit
-                               request->subsys_status = SCSI_REQ_CMP;
-                       } else {
-                               TRACE("%s unimplemented: TRIM call\n", 
__func__);
-                               // TODO: Make Serial ATA (sata_request?) trim 
call here.
+                       scsi_unmap_parameter_list* unmapBlocks
+                               = (scsi_unmap_parameter_list*)request->data;
+                       if (unmapBlocks == NULL
+                               || B_BENDIAN_TO_HOST_INT16(cmd->length) != 
request->data_length
+                               || 
B_BENDIAN_TO_HOST_INT16(unmapBlocks->data_length)
+                                       != request->data_length - 1) {
+                               TRACE("%s port %d: invalid unmap parameter data 
length\n",
+                                       __func__, fIndex);
                                request->subsys_status = SCSI_REQ_ABORTED;
+                               gSCSI->finished(request, 1);
+                       } else {
+                               ScsiUnmap(request, unmapBlocks);
                        }
-                       gSCSI->finished(request, 1);
                        break;
                }
                default:
diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h
index 962e5f7..f89a622 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h
@@ -36,6 +36,8 @@ private:
        void            ScsiReadCapacity16(scsi_ccb *request);
        void            ScsiReadWrite(scsi_ccb *request, uint64 lba, size_t 
sectorCount, bool isWrite);
        void            ScsiSynchronizeCache(scsi_ccb *request);
+       void            ScsiUnmap(scsi_ccb* request,
+                                       struct scsi_unmap_parameter_list* 
unmapBlocks);
 
        void            ExecuteSataRequest(sata_request *request, bool isWrite 
= false);
 
@@ -71,7 +73,7 @@ private:
        bool                                                    
fTestUnitReadyActive;
        bool                                                    fResetPort;
        bool                                                    fError;
-       bool                                                    fTrim;
+       bool                                                    fTrimSupported;
 
        volatile fis *                                  fFIS;
        volatile command_list_entry *   fCommandList;

############################################################################

Commit:      13e72c9a72945449ff77fcd56d7d0868e159641e
URL:         http://cgit.haiku-os.org/haiku/commit/?id=13e72c9
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Wed Sep 18 21:04:21 2013 UTC

ahci: Minor cleanup.

* Mostly utilized ATACommands.h

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
index f3de1bb..e0f1c39 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
@@ -13,6 +13,7 @@
 #include <ByteOrder.h>
 #include <KernelExport.h>
 
+#include <ATACommands.h>
 #include <ATAInfoBlock.h>
 
 #include "ahci_controller.h"
@@ -358,8 +359,8 @@ AHCIPort::InterruptErrorHandler(uint32 is)
        uint32 ci = fRegs->ci;
 
        if (!fTestUnitReadyActive) {
-               TRACE("AHCIPort::InterruptErrorHandler port %d, "
-                       "fCommandsActive 0x%08" B_PRIx32 ", is 0x%08" B_PRIx32 
", ci 0x%08" B_PRIx32 "\n", fIndex,
+               TRACE("AHCIPort::InterruptErrorHandler port %d, fCommandsActive 
0x%08"
+                       B_PRIx32 ", is 0x%08" B_PRIx32 ", ci 0x%08" B_PRIx32 
"\n", fIndex,
                        fCommandsActive, is, ci);
 
                TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts);
@@ -563,7 +564,8 @@ AHCIPort::ScsiInquiry(scsi_ccb *request)
 
        sata_request sreq;
        sreq.set_data(&ataData, sizeof(ataData));
-       sreq.set_ata_cmd(fIsATAPI ? 0xa1 : 0xec); // Identify (Packet) Device
+       sreq.set_ata_cmd(fIsATAPI
+               ? ATA_COMMAND_IDENTIFY_PACKET_DEVICE : 
ATA_COMMAND_IDENTIFY_DEVICE);
        ExecuteSataRequest(&sreq);
        sreq.wait_for_completion();
 
@@ -671,7 +673,8 @@ AHCIPort::ScsiSynchronizeCache(scsi_ccb *request)
                return;
        }
 
-       sreq->set_ata_cmd(fUse48BitCommands ? 0xea : 0xe7); // Flush Cache
+       sreq->set_ata_cmd(fUse48BitCommands
+               ? ATA_COMMAND_FLUSH_CACHE_EXT : ATA_COMMAND_FLUSH_CACHE);
        ExecuteSataRequest(sreq);
 }
 
@@ -771,7 +774,9 @@ AHCIPort::ScsiReadWrite(scsi_ccb *request, uint64 lba, 
size_t sectorCount,
                }
                if (lba > MAX_SECTOR_LBA_48)
                        panic("achi: ScsiReadWrite position too large for 
48-bit LBA\n");
-               sreq->set_ata48_cmd(isWrite ? 0x35 : 0x25, lba, sectorCount);
+               sreq->set_ata48_cmd(
+                       isWrite ? ATA_COMMAND_WRITE_DMA_EXT : 
ATA_COMMAND_READ_DMA_EXT,
+                       lba, sectorCount);
        } else {
                if (sectorCount > 256) {
                        panic("ahci: ScsiReadWrite length too large, %lu 
sectors",
@@ -779,7 +784,8 @@ AHCIPort::ScsiReadWrite(scsi_ccb *request, uint64 lba, 
size_t sectorCount,
                }
                if (lba > MAX_SECTOR_LBA_28)
                        panic("achi: ScsiReadWrite position too large for 
normal LBA\n");
-               sreq->set_ata28_cmd(isWrite ? 0xca : 0xc8, lba, sectorCount);
+               sreq->set_ata28_cmd(isWrite
+                       ? ATA_COMMAND_WRITE_DMA : ATA_COMMAND_READ_DMA, lba, 
sectorCount);
        }
 
        ExecuteSataRequest(sreq, isWrite);
@@ -799,6 +805,7 @@ AHCIPort::ScsiUnmap(scsi_ccb* request, 
scsi_unmap_parameter_list* unmapBlocks)
                return;
        }
 
+       sreq->set_ata_cmd(ATA_COMMAND_DATA_SET_MANAGEMENT);
        delete sreq;
 }
 
@@ -1074,7 +1081,6 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
 uchar
 AHCIPort::ScsiAbortRequest(scsi_ccb *request)
 {
-
        return SCSI_REQ_CMP;
 }
 
diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
index 9bd871b..2f5a2d2 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
@@ -10,6 +10,9 @@
 #include "scsi_cmds.h"
 
 
+#define FIS_TYPE_REGISTER_HOST_TO_DEVICE 0x27
+
+
 sata_request::sata_request()
        :
        fCcb(NULL),
@@ -54,7 +57,7 @@ void
 sata_request::set_ata_cmd(uint8 command)
 {
        memset(fFis, 0, sizeof(fFis));
-       fFis[0] = 0x27;
+       fFis[0] = FIS_TYPE_REGISTER_HOST_TO_DEVICE;
        fFis[1] = 0x80;
        fFis[2] = command;
 }

############################################################################

Commit:      d82e6bcf6b00372ab17739d91d169c9ef2952d79
URL:         http://cgit.haiku-os.org/haiku/commit/?id=d82e6bc
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Sun Oct 27 22:22:50 2013 UTC

ahci: Use get_memory_map_etc().

* Simplifies code a bit.

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
index e0f1c39..620c1f3 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
@@ -434,16 +434,20 @@ status_t
 AHCIPort::FillPrdTable(volatile prd *prdTable, int *prdCount, int prdMax,
        const void *data, size_t dataSize)
 {
-       int peMax = prdMax + 1;
-       physical_entry pe[peMax];
-       if (get_memory_map(data, dataSize, pe, peMax ) < B_OK) {
-               TRACE("AHCIPort::FillPrdTable get_memory_map failed\n");
+       int maxEntries = prdMax + 1;
+       physical_entry entries[maxEntries];
+       uint32 entriesUsed = maxEntries;
+
+       status_t status = get_memory_map_etc(B_CURRENT_TEAM, data, dataSize,
+               entries, &entriesUsed);
+       if (status != B_OK) {
+               TRACE("AHCIPort::FillPrdTable get_memory_map() failed: %s\n",
+                       strerror(status));
                return B_ERROR;
        }
-       int peUsed;
-       for (peUsed = 0; pe[peUsed].size; peUsed++)
-               ;
-       return FillPrdTable(prdTable, prdCount, prdMax, pe, peUsed, dataSize);
+
+       return FillPrdTable(prdTable, prdCount, prdMax, entries, entriesUsed,
+               dataSize);
 }
 
 

############################################################################

Commit:      6317a4c399354af8180690daea02de8dc9dc328f
URL:         http://cgit.haiku-os.org/haiku/commit/?id=6317a4c
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Sun Oct 27 22:28:38 2013 UTC

scsi_periph: fixed copy&paste error in periph_trim_device().

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

diff --git a/src/add-ons/kernel/generic/scsi_periph/block.cpp 
b/src/add-ons/kernel/generic/scsi_periph/block.cpp
index 7f6cfcd..8e1d330 100644
--- a/src/add-ons/kernel/generic/scsi_periph/block.cpp
+++ b/src/add-ons/kernel/generic/scsi_periph/block.cpp
@@ -145,7 +145,8 @@ periph_trim_device(scsi_periph_device_info *device, 
scsi_ccb *request,
        // Prepare request data
        memset(unmapBlocks, 0, unmapBlockSize);
        unmapBlocks->data_length = B_HOST_TO_BENDIAN_INT16(unmapBlockSize - 1);
-       unmapBlocks->data_length = B_HOST_TO_BENDIAN_INT16(unmapBlockSize - 3);
+       unmapBlocks->block_data_length
+               = B_HOST_TO_BENDIAN_INT16(unmapBlockSize - 7);
 
        for (uint32 i = 0; i < rangeCount; i++) {
                unmapBlocks->blocks[i].lba = B_HOST_TO_BENDIAN_INT64(

############################################################################

Commit:      e858a6b2a0e4ee1c8c80c09b1f3ecfef04e8025e
URL:         http://cgit.haiku-os.org/haiku/commit/?id=e858a6b
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Mon Oct 28 00:05:47 2013 UTC

ahci: WIP of implementing trim command.

* Data Set Management specific bits are still missing.

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
index 620c1f3..99d2da6 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
@@ -15,6 +15,7 @@
 
 #include <ATACommands.h>
 #include <ATAInfoBlock.h>
+#include <AutoDeleter.h>
 
 #include "ahci_controller.h"
 #include "ahci_tracing.h"
@@ -801,7 +802,7 @@ AHCIPort::ScsiUnmap(scsi_ccb* request, 
scsi_unmap_parameter_list* unmapBlocks)
 {
        TRACE("%s unimplemented: TRIM call\n", __func__);
 
-       sata_request* sreq = new(std::nothrow) sata_request(request);
+       sata_request* sreq = new(std::nothrow) sata_request();
        if (sreq == NULL) {
                TRACE("out of memory when allocating unmap request\n");
                request->subsys_status = SCSI_REQ_ABORTED;
@@ -809,12 +810,55 @@ AHCIPort::ScsiUnmap(scsi_ccb* request, 
scsi_unmap_parameter_list* unmapBlocks)
                return;
        }
 
+       // Determine how many ranges we'll need
+       // We assume that the SCSI unmap ranges cannot be merged together
+       uint32 scsiRangeCount = unmapBlocks->block_data_length
+               / sizeof(scsi_unmap_block_descriptor);
+       uint32 lbaRangeCount = 0;
+       for (uint32 i = 0; i < scsiRangeCount; i++) {
+               lbaRangeCount += ((uint32)B_BENDIAN_TO_HOST_INT32(
+                       unmapBlocks->blocks[i].block_count) + 65534) / 65535;
+       }
+
+       uint32 lbaRangesSize = lbaRangeCount * sizeof(uint64);
+       uint64* lbaRanges
+               = (uint64*)malloc(lbaRangesSize);
+       if (lbaRanges == NULL) {
+               TRACE("out of memory when allocating %" B_PRIu32 " unmap 
ranges\n",
+                       lbaRangeCount);
+               request->subsys_status = SCSI_REQ_ABORTED;
+               gSCSI->finished(request, 1);
+               return;
+       }
+
+       MemoryDeleter deleter(lbaRanges);
+
+       for (uint32 i = 0, scsiIndex = 0; scsiIndex < scsiRangeCount; 
scsiIndex++) {
+               uint64 lba = (uint64)B_BENDIAN_TO_HOST_INT64(
+                       unmapBlocks->blocks[scsiIndex].lba);
+               uint64 bytesLeft = (uint32)B_BENDIAN_TO_HOST_INT32(
+                       unmapBlocks->blocks[scsiIndex].block_count);
+               while (bytesLeft > 0) {
+                       uint16 blocks = bytesLeft > 65535 ? 65535 : 
(uint16)bytesLeft;
+                       lbaRanges[i++] = B_HOST_TO_LENDIAN_INT64(
+                               ((uint64)blocks << 48) | lba);
+                       lba += blocks;
+               }
+       }
+
        sreq->set_ata_cmd(ATA_COMMAND_DATA_SET_MANAGEMENT);
-       delete sreq;
+       sreq->set_data(lbaRanges, lbaRangesSize);
+
+       bool success = ExecuteSataRequest(sreq);
+
+       request->data_resid = 0;
+       request->device_status = SCSI_STATUS_GOOD;
+       request->subsys_status = success ? SCSI_REQ_CMP : SCSI_REQ_CMP_ERR;
+       gSCSI->finished(request, 1);
 }
 
 
-void
+bool
 AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite)
 {
        FLOW("ExecuteAtaRequest port %d\n", fIndex);
@@ -858,7 +902,7 @@ AHCIPort::ExecuteSataRequest(sata_request *request, bool 
isWrite)
                ResetPort();
                FinishTransfer();
                request->abort();
-               return;
+               return false;
        }
 
        cpu_status cpu = disable_interrupts();
@@ -902,9 +946,11 @@ AHCIPort::ExecuteSataRequest(sata_request *request, bool 
isWrite)
        if (status == B_TIMED_OUT) {
                TRACE("ExecuteAtaRequest port %d: device timeout\n", fIndex);
                request->abort();
-       } else {
-               request->finish(tfd, bytesTransfered);
+               return false;
        }
+
+       request->finish(tfd, bytesTransfered);
+       return true;
 }
 
 
diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h
index f89a622..7ac542c 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h
@@ -39,7 +39,7 @@ private:
        void            ScsiUnmap(scsi_ccb* request,
                                        struct scsi_unmap_parameter_list* 
unmapBlocks);
 
-       void            ExecuteSataRequest(sata_request *request, bool isWrite 
= false);
+       bool            ExecuteSataRequest(sata_request *request, bool isWrite 
= false);
 
        void            ResetDevice();
        status_t        ResetPort(bool forceDeviceReset = false);

############################################################################

Commit:      10deaef118d90eb9af9f78c6432db502d42305ab
URL:         http://cgit.haiku-os.org/haiku/commit/?id=10deaef
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Mon Oct 28 22:24:21 2013 UTC

ahci: Added missing wait_for_completion().

* Thanks Marcus!
* That made the return code for ExecuteSataRequest() pretty much useless,
  so I removed it again.
* Also, a delete sreq was missing; I now allocate it on the stack instead.

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
index 99d2da6..45ebc9c 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
@@ -802,14 +802,6 @@ AHCIPort::ScsiUnmap(scsi_ccb* request, 
scsi_unmap_parameter_list* unmapBlocks)
 {
        TRACE("%s unimplemented: TRIM call\n", __func__);
 
-       sata_request* sreq = new(std::nothrow) sata_request();
-       if (sreq == NULL) {
-               TRACE("out of memory when allocating unmap request\n");
-               request->subsys_status = SCSI_REQ_ABORTED;
-               gSCSI->finished(request, 1);
-               return;
-       }
-
        // Determine how many ranges we'll need
        // We assume that the SCSI unmap ranges cannot be merged together
        uint32 scsiRangeCount = unmapBlocks->block_data_length
@@ -846,19 +838,26 @@ AHCIPort::ScsiUnmap(scsi_ccb* request, 
scsi_unmap_parameter_list* unmapBlocks)
                }
        }
 
-       sreq->set_ata_cmd(ATA_COMMAND_DATA_SET_MANAGEMENT);
-       sreq->set_data(lbaRanges, lbaRangesSize);
+       sata_request sreq;
+       sreq.set_ata_cmd(ATA_COMMAND_DATA_SET_MANAGEMENT);
+       sreq.set_data(lbaRanges, lbaRangesSize);
+
+       ExecuteSataRequest(&sreq);
+       sreq.wait_for_completion();
 
-       bool success = ExecuteSataRequest(sreq);
+       if ((sreq.completion_status() & ATA_ERR) != 0) {
+               TRACE("trim failed (%" B_PRIu32 " ranges)!", lbaRangeCount);
+               request->subsys_status = SCSI_REQ_CMP_ERR;
+       } else
+               request->subsys_status = SCSI_REQ_CMP;
 
        request->data_resid = 0;
        request->device_status = SCSI_STATUS_GOOD;
-       request->subsys_status = success ? SCSI_REQ_CMP : SCSI_REQ_CMP_ERR;
        gSCSI->finished(request, 1);
 }
 
 
-bool
+void
 AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite)
 {
        FLOW("ExecuteAtaRequest port %d\n", fIndex);
@@ -902,7 +901,7 @@ AHCIPort::ExecuteSataRequest(sata_request *request, bool 
isWrite)
                ResetPort();
                FinishTransfer();
                request->abort();
-               return false;
+               return;
        }
 
        cpu_status cpu = disable_interrupts();
@@ -946,11 +945,10 @@ AHCIPort::ExecuteSataRequest(sata_request *request, bool 
isWrite)
        if (status == B_TIMED_OUT) {
                TRACE("ExecuteAtaRequest port %d: device timeout\n", fIndex);
                request->abort();
-               return false;
+               return;
        }
 
        request->finish(tfd, bytesTransfered);
-       return true;
 }
 
 
diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h
index 7ac542c..f89a622 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h
@@ -39,7 +39,7 @@ private:
        void            ScsiUnmap(scsi_ccb* request,
                                        struct scsi_unmap_parameter_list* 
unmapBlocks);
 
-       bool            ExecuteSataRequest(sata_request *request, bool isWrite 
= false);
+       void            ExecuteSataRequest(sata_request *request, bool isWrite 
= false);
 
        void            ResetDevice();
        status_t        ResetPort(bool forceDeviceReset = false);

############################################################################

Commit:      fd88486a317f6ec0ab9c0cb755aebde1bb0ead0f
URL:         http://cgit.haiku-os.org/haiku/commit/?id=fd88486
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Mon Oct 28 22:36:27 2013 UTC

ahci: Set the command bits as required.

* The trim command should be functional now, but it's completely untested
  at this point.

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
index 45ebc9c..d50ce71 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
@@ -839,7 +839,8 @@ AHCIPort::ScsiUnmap(scsi_ccb* request, 
scsi_unmap_parameter_list* unmapBlocks)
        }
 
        sata_request sreq;
-       sreq.set_ata_cmd(ATA_COMMAND_DATA_SET_MANAGEMENT);
+       sreq.set_ata48_cmd(ATA_COMMAND_DATA_SET_MANAGEMENT, 0,
+               (lbaRangesSize + 511) / 512);
        sreq.set_data(lbaRanges, lbaRangesSize);
 
        ExecuteSataRequest(&sreq);

############################################################################

Commit:      930cb4206be505be32df1872254f54407af9c1c0
URL:         http://cgit.haiku-os.org/haiku/commit/?id=930cb42
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Mon Oct 28 22:45:28 2013 UTC

ahci: Minor cleanup.

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
index d50ce71..3a5611d 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2008-2013 Haiku, Inc. All rights reserved.
  * Copyright 2007-2009, Marcus Overhagen. All rights reserved.
  * Distributed under the terms of the MIT License.
  */
@@ -36,7 +37,7 @@
 #define RWTRACE(a...)
 
 
-AHCIPort::AHCIPort(AHCIController *controller, int index)
+AHCIPort::AHCIPort(AHCIController* controller, int index)
        :
        fController(controller),
        fIndex(index),
@@ -77,24 +78,25 @@ AHCIPort::Init1()
                + sizeof(fis) + sizeof(command_table)
                + sizeof(prd) * PRD_TABLE_ENTRY_COUNT;
 
-       char *virtAddr;
+       char* virtAddr;
        phys_addr_t physAddr;
+       char name[32];
+       snprintf(name, sizeof(name), "AHCI port %d", fIndex);
 
-       fArea = alloc_mem((void **)&virtAddr, &physAddr, size, 0,
-               "some AHCI port");
+       fArea = alloc_mem((void**)&virtAddr, &physAddr, size, 0, name);
        if (fArea < B_OK) {
                TRACE("failed allocating memory for port %d\n", fIndex);
                return fArea;
        }
        memset(virtAddr, 0, size);
 
-       fCommandList = (command_list_entry *)virtAddr;
+       fCommandList = (command_list_entry*)virtAddr;
        virtAddr += sizeof(command_list_entry) * COMMAND_LIST_ENTRY_COUNT;
-       fFIS = (fis *)virtAddr;
+       fFIS = (fis*)virtAddr;
        virtAddr += sizeof(fis);
-       fCommandTable = (command_table *)virtAddr;
+       fCommandTable = (command_table*)virtAddr;
        virtAddr += sizeof(command_table);
-       fPRDTable = (prd *)virtAddr;
+       fPRDTable = (prd*)virtAddr;
        TRACE("PRD table is at %p\n", fPRDTable);
 
        fRegs->clb  = LO32(physAddr);
@@ -303,8 +305,8 @@ AHCIPort::PostReset()
 
        if (!fTestUnitReadyActive) {
                TRACE("device signature 0x%08" B_PRIx32 " (%s)\n", fRegs->sig,
-                       (fRegs->sig == 0xeb140101) ? "ATAPI" : (fRegs->sig == 
0x00000101) ?
-                               "ATA" : "unknown");
+                       fRegs->sig == 0xeb140101 ? "ATAPI" : fRegs->sig == 
0x00000101
+                               ? "ATA" : "unknown");
        }
 
        return B_OK;
@@ -341,9 +343,9 @@ AHCIPort::Interrupt()
 
        uint32 ci = fRegs->ci;
 
-       RWTRACE("[%lld] %ld AHCIPort::Interrupt port %d, fCommandsActive 0x%08" 
B_PRIx32 ", "
-               "is 0x%08" B_PRIx32 ", ci 0x%08" B_PRIx32 "\n", system_time(), 
find_thread(NULL),
-               fIndex, fCommandsActive, is, ci);
+       RWTRACE("[%lld] %ld AHCIPort::Interrupt port %d, fCommandsActive 0x%08"
+               B_PRIx32 ", is 0x%08" B_PRIx32 ", ci 0x%08" B_PRIx32 "\n",
+               system_time(), find_thread(NULL), fIndex, fCommandsActive, is, 
ci);
 
        acquire_spinlock(&fSpinlock);
        if ((fCommandsActive & 1) && !(ci & 1)) {
@@ -432,8 +434,8 @@ AHCIPort::InterruptErrorHandler(uint32 is)
 
 
 status_t
-AHCIPort::FillPrdTable(volatile prd *prdTable, int *prdCount, int prdMax,
-       const void *data, size_t dataSize)
+AHCIPort::FillPrdTable(volatile prd* prdTable, int* prdCount, int prdMax,
+       const void* data, size_t dataSize)
 {
        int maxEntries = prdMax + 1;
        physical_entry entries[maxEntries];
@@ -453,8 +455,8 @@ AHCIPort::FillPrdTable(volatile prd *prdTable, int 
*prdCount, int prdMax,
 
 
 status_t
-AHCIPort::FillPrdTable(volatile prd *prdTable, int *prdCount, int prdMax,
-       const physical_entry *sgTable, int sgCount, size_t dataSize)
+AHCIPort::FillPrdTable(volatile prd* prdTable, int* prdCount, int prdMax,
+       const physical_entry* sgTable, int sgCount, size_t dataSize)
 {
        *prdCount = 0;
        while (sgCount > 0 && dataSize > 0) {
@@ -510,7 +512,7 @@ AHCIPort::StartTransfer()
 
 
 status_t
-AHCIPort::WaitForTransfer(int *tfd, bigtime_t timeout)
+AHCIPort::WaitForTransfer(int* tfd, bigtime_t timeout)
 {
        status_t result = acquire_sem_etc(fResponseSem, 1, B_RELATIVE_TIMEOUT,
                timeout);
@@ -541,7 +543,7 @@ AHCIPort::FinishTransfer()
 
 
 void
-AHCIPort::ScsiTestUnitReady(scsi_ccb *request)
+AHCIPort::ScsiTestUnitReady(scsi_ccb* request)
 {
        TRACE("AHCIPort::ScsiTestUnitReady port %d\n", fIndex);
        request->subsys_status = SCSI_REQ_CMP;
@@ -550,17 +552,18 @@ AHCIPort::ScsiTestUnitReady(scsi_ccb *request)
 
 
 void
-AHCIPort::ScsiInquiry(scsi_ccb *request)
+AHCIPort::ScsiInquiry(scsi_ccb* request)
 {
        TRACE("AHCIPort::ScsiInquiry port %d\n", fIndex);
 
-       const scsi_cmd_inquiry *cmd = (const scsi_cmd_inquiry *)request->cdb;
+       const scsi_cmd_inquiry* cmd = (const scsi_cmd_inquiry*)request->cdb;
        scsi_res_inquiry scsiData;
        ata_device_infoblock ataData;
 
        ASSERT(sizeof(ataData) == 512);
 
-       if (cmd->evpd || cmd->page_code || request->data_length < 
sizeof(scsiData)) {
+       if (cmd->evpd || cmd->page_code
+               || request->data_length < sizeof(scsiData)) {
                TRACE("invalid request\n");
                request->subsys_status = SCSI_REQ_ABORTED;
                gSCSI->finished(request, 1);
@@ -582,7 +585,7 @@ AHCIPort::ScsiInquiry(scsi_ccb *request)
        }
 
 /*
-       uint8 *data = (uint8*) &ataData;
+       uint8* data = (uint8*) &ataData;
        for (int i = 0; i < 512; i += 8) {
                TRACE("  %02x %02x %02x %02x %02x %02x %02x %02x\n", data[i], 
data[i+1],
                        data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], 
data[i+7]);
@@ -666,11 +669,11 @@ AHCIPort::ScsiInquiry(scsi_ccb *request)
 
 
 void
-AHCIPort::ScsiSynchronizeCache(scsi_ccb *request)
+AHCIPort::ScsiSynchronizeCache(scsi_ccb* request)
 {
        //TRACE("AHCIPort::ScsiSynchronizeCache port %d\n", fIndex);
 
-       sata_request *sreq = new(std::nothrow) sata_request(request);
+       sata_request* sreq = new(std::nothrow) sata_request(request);
        if (sreq == NULL) {
                TRACE("out of memory when allocating sync request\n");
                request->subsys_status = SCSI_REQ_ABORTED;
@@ -685,11 +688,12 @@ AHCIPort::ScsiSynchronizeCache(scsi_ccb *request)
 
 
 void
-AHCIPort::ScsiReadCapacity(scsi_ccb *request)
+AHCIPort::ScsiReadCapacity(scsi_ccb* request)
 {
        TRACE("AHCIPort::ScsiReadCapacity port %d\n", fIndex);
 
-       const scsi_cmd_read_capacity *cmd = (const scsi_cmd_read_capacity 
*)request->cdb;
+       const scsi_cmd_read_capacity* cmd
+               = (const scsi_cmd_read_capacity*)request->cdb;
        scsi_res_read_capacity scsiData;
 
        if (cmd->pmi || cmd->lba || request->data_length < sizeof(scsiData)) {
@@ -721,11 +725,10 @@ AHCIPort::ScsiReadCapacity(scsi_ccb *request)
 
 
 void
-AHCIPort::ScsiReadCapacity16(scsi_ccb *request)
+AHCIPort::ScsiReadCapacity16(scsi_ccb* request)
 {
        TRACE("AHCIPort::ScsiReadCapacity16 port %d\n", fIndex);
 
-       //const scsi_cmd_read_capacity_long *cmd = (const 
scsi_cmd_read_capacity_long *)request->cdb;
        scsi_res_read_capacity_long scsiData;
 
        TRACE("SectorSize %" B_PRIu32 ", SectorCount 0x%" B_PRIx64 "\n",
@@ -746,7 +749,7 @@ AHCIPort::ScsiReadCapacity16(scsi_ccb *request)
 
 
 void
-AHCIPort::ScsiReadWrite(scsi_ccb *request, uint64 lba, size_t sectorCount,
+AHCIPort::ScsiReadWrite(scsi_ccb* request, uint64 lba, size_t sectorCount,
        bool isWrite)
 {
        RWTRACE("[%lld] %ld ScsiReadWrite: position %llu, size %lu, isWrite 
%d\n",
@@ -764,7 +767,7 @@ AHCIPort::ScsiReadWrite(scsi_ccb *request, uint64 lba, 
size_t sectorCount,
 #endif
 
        ASSERT(request->data_length == sectorCount * 512);
-       sata_request *sreq = new(std::nothrow) sata_request(request);
+       sata_request* sreq = new(std::nothrow) sata_request(request);
        if (sreq == NULL) {
                TRACE("out of memory when allocating read/write request\n");
                request->subsys_status = SCSI_REQ_ABORTED;
@@ -813,8 +816,7 @@ AHCIPort::ScsiUnmap(scsi_ccb* request, 
scsi_unmap_parameter_list* unmapBlocks)
        }
 
        uint32 lbaRangesSize = lbaRangeCount * sizeof(uint64);
-       uint64* lbaRanges
-               = (uint64*)malloc(lbaRangesSize);
+       uint64* lbaRanges = (uint64*)malloc(lbaRangesSize);
        if (lbaRanges == NULL) {
                TRACE("out of memory when allocating %" B_PRIu32 " unmap 
ranges\n",
                        lbaRangeCount);
@@ -859,7 +861,7 @@ AHCIPort::ScsiUnmap(scsi_ccb* request, 
scsi_unmap_parameter_list* unmapBlocks)
 
 
 void
-AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite)
+AHCIPort::ExecuteSataRequest(sata_request* request, bool isWrite)
 {
        FLOW("ExecuteAtaRequest port %d\n", fIndex);
 
@@ -881,13 +883,13 @@ AHCIPort::ExecuteSataRequest(sata_request *request, bool 
isWrite)
 
        fCommandList->prdtl_flags_cfl = 0;
        fCommandList->cfl = 5; // 20 bytes, length in DWORDS
-       memcpy((char *)fCommandTable->cfis, request->fis(), 20);
+       memcpy((char*)fCommandTable->cfis, request->fis(), 20);
 
        fTestUnitReadyActive = request->is_test_unit_ready();
        if (request->is_atapi()) {
                // ATAPI PACKET is a 12 or 16 byte SCSI command
-               memset((char *)fCommandTable->acmd, 0, 32);
-               memcpy((char *)fCommandTable->acmd, request->ccb()->cdb,
+               memset((char*)fCommandTable->acmd, 0, 32);
+               memcpy((char*)fCommandTable->acmd, request->ccb()->cdb,
                        request->ccb()->cdb_length);
                fCommandList->a = 1;
        }
@@ -954,7 +956,7 @@ AHCIPort::ExecuteSataRequest(sata_request *request, bool 
isWrite)
 
 
 void
-AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
+AHCIPort::ScsiExecuteRequest(scsi_ccb* request)
 {
 //     TRACE("AHCIPort::ScsiExecuteRequest port %d, opcode 0x%02x, length 
%u\n", fIndex, request->cdb[0], request->cdb_length);
 
@@ -977,7 +979,7 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
 
 //             TRACE("AHCIPort::ScsiExecuteRequest ATAPI: port %d, opcode 
0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length);
 
-               sata_request *sreq = new(std::nothrow) sata_request(request);
+               sata_request* sreq = new(std::nothrow) sata_request(request);
                if (sreq == NULL) {
                        TRACE("out of memory when allocating atapi request\n");
                        request->subsys_status = SCSI_REQ_ABORTED;
@@ -986,7 +988,7 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
                }
 
                sreq->set_atapi_cmd(request->data_length);
-//             uint8 *data = (uint8*) sreq->ccb()->cdb;
+//             uint8* data = (uint8*) sreq->ccb()->cdb;
 //             for (int i = 0; i < 16; i += 8) {
 //                     TRACE("  %02x %02x %02x %02x %02x %02x %02x %02x\n", 
data[i], data[i+1], data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], 
data[i+7]);
 //             }
@@ -1032,7 +1034,7 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
                case SCSI_OP_READ_6:
                case SCSI_OP_WRITE_6:
                {
-                       const scsi_cmd_rw_6 *cmd = (const scsi_cmd_rw_6 
*)request->cdb;
+                       const scsi_cmd_rw_6* cmd = (const 
scsi_cmd_rw_6*)request->cdb;
                        uint32 position = ((uint32)cmd->high_lba << 16)
                                | ((uint32)cmd->mid_lba << 8) | 
(uint32)cmd->low_lba;
                        size_t length = cmd->length != 0 ? cmd->length : 256;
@@ -1043,7 +1045,7 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
                case SCSI_OP_READ_10:
                case SCSI_OP_WRITE_10:
                {
-                       const scsi_cmd_rw_10 *cmd = (const scsi_cmd_rw_10 
*)request->cdb;
+                       const scsi_cmd_rw_10* cmd = (const 
scsi_cmd_rw_10*)request->cdb;
                        uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba);
                        size_t length = B_BENDIAN_TO_HOST_INT16(cmd->length);
                        bool isWrite = request->cdb[0] == SCSI_OP_WRITE_10;
@@ -1060,7 +1062,7 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
                case SCSI_OP_READ_12:
                case SCSI_OP_WRITE_12:
                {
-                       const scsi_cmd_rw_12 *cmd = (const scsi_cmd_rw_12 
*)request->cdb;
+                       const scsi_cmd_rw_12* cmd = (const 
scsi_cmd_rw_12*)request->cdb;
                        uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba);
                        size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length);
                        bool isWrite = request->cdb[0] == SCSI_OP_WRITE_12;
@@ -1077,7 +1079,7 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
                case SCSI_OP_READ_16:
                case SCSI_OP_WRITE_16:
                {
-                       const scsi_cmd_rw_16 *cmd = (const scsi_cmd_rw_16 
*)request->cdb;
+                       const scsi_cmd_rw_16* cmd = (const 
scsi_cmd_rw_16*)request->cdb;
                        uint64 position = B_BENDIAN_TO_HOST_INT64(cmd->lba);
                        size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length);
                        bool isWrite = request->cdb[0] == SCSI_OP_WRITE_16;
@@ -1128,14 +1130,14 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
 
 
 uchar
-AHCIPort::ScsiAbortRequest(scsi_ccb *request)
+AHCIPort::ScsiAbortRequest(scsi_ccb* request)
 {
        return SCSI_REQ_CMP;
 }
 
 
 uchar
-AHCIPort::ScsiTerminateRequest(scsi_ccb *request)
+AHCIPort::ScsiTerminateRequest(scsi_ccb* request)
 {
        return SCSI_REQ_CMP;
 }
@@ -1149,12 +1151,13 @@ AHCIPort::ScsiResetDevice()
 
 
 void
-AHCIPort::ScsiGetRestrictions(bool *isATAPI, bool *noAutoSense,
-       uint32 *maxBlocks)
+AHCIPort::ScsiGetRestrictions(bool* isATAPI, bool* noAutoSense,
+       uint32* maxBlocks)
 {
        *isATAPI = fIsATAPI;
        *noAutoSense = fIsATAPI; // emulated auto sense for ATA, but not ATAPI
        *maxBlocks = fUse48BitCommands ? 65536 : 256;
        TRACE("AHCIPort::ScsiGetRestrictions port %d: isATAPI %d, noAutoSense 
%d, "
-               "maxBlocks %" B_PRIu32 "\n", fIndex, *isATAPI, *noAutoSense, 
*maxBlocks);
+               "maxBlocks %" B_PRIu32 "\n", fIndex, *isATAPI, *noAutoSense,
+               *maxBlocks);
 }
diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
index 2f5a2d2..d5cfd82 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
@@ -59,6 +59,7 @@ sata_request::set_ata_cmd(uint8 command)
        memset(fFis, 0, sizeof(fFis));
        fFis[0] = FIS_TYPE_REGISTER_HOST_TO_DEVICE;
        fFis[1] = 0x80;
+               // This is a command
        fFis[2] = command;
 }
 
@@ -71,6 +72,7 @@ sata_request::set_ata28_cmd(uint8 command, uint32 lba, uint8 
sectorCount)
        fFis[5] = (lba >> 8) & 0xff;
        fFis[6] = (lba >> 16) & 0xff;
        fFis[7] = 0x40 | ((lba >> 24) & 0x0f);
+               // device
        fFis[12] = sectorCount & 0xff;
 }
 
@@ -83,6 +85,7 @@ sata_request::set_ata48_cmd(uint8 command, uint64 lba, uint16 
sectorCount)
        fFis[5] = (lba >> 8) & 0xff;
        fFis[6] = (lba >> 16) & 0xff;
        fFis[7] = 0x40;
+               // device
        fFis[8] = (lba >> 24) & 0xff;
        fFis[9] = (lba >> 32) & 0xff;
        fFis[10] = (lba >> 40) & 0xff;

############################################################################

Commit:      2e4e1eb2d9d4505cd716151de281319a03695f36
URL:         http://cgit.haiku-os.org/haiku/commit/?id=2e4e1eb
Author:      Axel Doerfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Tue Oct 29 13:25:15 2013 UTC
Committer:   Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Commit-Date: Thu Nov  7 18:05:41 2013 UTC

ahci: fixed endless loop, and missing bit.

* The value for trim is bit 0, not 0; added sata_request::SetFeature()
  to change this.
* The lba range fill loop never ended.
* Thanks to Marcus for proof-reading!

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
index 3a5611d..00f17eb 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
@@ -837,12 +837,14 @@ AHCIPort::ScsiUnmap(scsi_ccb* request, 
scsi_unmap_parameter_list* unmapBlocks)
                        lbaRanges[i++] = B_HOST_TO_LENDIAN_INT64(
                                ((uint64)blocks << 48) | lba);
                        lba += blocks;
+                       bytesLeft -= blocks;
                }
        }
 
        sata_request sreq;
        sreq.set_ata48_cmd(ATA_COMMAND_DATA_SET_MANAGEMENT, 0,
                (lbaRangesSize + 511) / 512);
+       sreq.SetFeature(1);
        sreq.set_data(lbaRanges, lbaRangesSize);
 
        ExecuteSataRequest(&sreq);
diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
index d5cfd82..2fe8b21 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
@@ -95,6 +95,14 @@ sata_request::set_ata48_cmd(uint8 command, uint64 lba, 
uint16 sectorCount)
 
 
 void
+sata_request::SetFeature(uint16 feature)
+{
+       fFis[3] = (uint8)(feature & 0xff);
+       fFis[11] = (uint8)(feature >> 8);
+}
+
+
+void
 sata_request::set_atapi_cmd(size_t transferLength)
 {
        fIsATAPI = true;
diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.h 
b/src/add-ons/kernel/busses/scsi/ahci/sata_request.h
index 71550f6..61191be 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/sata_request.h
+++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.h
@@ -20,6 +20,7 @@ public:
        void                    set_ata_cmd(uint8 command);
        void                    set_ata28_cmd(uint8 command, uint32 lba, uint8 
sectorCount);
        void                    set_ata48_cmd(uint8 command, uint64 lba, uint16 
sectorCount);
+       void                    SetFeature(uint16 feature);
 
        void                    set_atapi_cmd(size_t transferLength);
        bool                    is_atapi();

############################################################################

Commit:      dbeb6b56b467bbbe02be03f8ea813708c0fd2443
URL:         http://cgit.haiku-os.org/haiku/commit/?id=dbeb6b5
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Tue Oct 29 21:53:24 2013 UTC

ahci: Fixed braindead variable naming.

* Again, thanks Marcus!

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
index 00f17eb..e170d33 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
@@ -830,14 +830,14 @@ AHCIPort::ScsiUnmap(scsi_ccb* request, 
scsi_unmap_parameter_list* unmapBlocks)
        for (uint32 i = 0, scsiIndex = 0; scsiIndex < scsiRangeCount; 
scsiIndex++) {
                uint64 lba = (uint64)B_BENDIAN_TO_HOST_INT64(
                        unmapBlocks->blocks[scsiIndex].lba);
-               uint64 bytesLeft = (uint32)B_BENDIAN_TO_HOST_INT32(
+               uint64 blocksLeft = (uint32)B_BENDIAN_TO_HOST_INT32(
                        unmapBlocks->blocks[scsiIndex].block_count);
-               while (bytesLeft > 0) {
-                       uint16 blocks = bytesLeft > 65535 ? 65535 : 
(uint16)bytesLeft;
+               while (blocksLeft > 0) {
+                       uint16 blocks = blocksLeft > 65535 ? 65535 : 
(uint16)blocksLeft;
                        lbaRanges[i++] = B_HOST_TO_LENDIAN_INT64(
                                ((uint64)blocks << 48) | lba);
                        lba += blocks;
-                       bytesLeft -= blocks;
+                       blocksLeft -= blocks;
                }
        }
 

############################################################################

Commit:      79cb543ae0f372eeb1ff7a9c108d19b9150e76c7
URL:         http://cgit.haiku-os.org/haiku/commit/?id=79cb543
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Tue Oct 29 22:29:06 2013 UTC

ahci: Minor coding style cleanup.

* Renamed some methods to camel case.
* Replaced coding error panics with ASSERTs.

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

diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
index e170d33..652f153 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp
@@ -571,13 +571,13 @@ AHCIPort::ScsiInquiry(scsi_ccb* request)
        }
 
        sata_request sreq;
-       sreq.set_data(&ataData, sizeof(ataData));
-       sreq.set_ata_cmd(fIsATAPI
+       sreq.SetData(&ataData, sizeof(ataData));
+       sreq.SetATACommand(fIsATAPI
                ? ATA_COMMAND_IDENTIFY_PACKET_DEVICE : 
ATA_COMMAND_IDENTIFY_DEVICE);
        ExecuteSataRequest(&sreq);
-       sreq.wait_for_completion();
+       sreq.WaitForCompletion();
 
-       if (sreq.completion_status() & ATA_ERR) {
+       if ((sreq.CompletionStatus() & ATA_ERR) != 0) {
                TRACE("identify device failed\n");
                request->subsys_status = SCSI_REQ_CMP_ERR;
                gSCSI->finished(request, 1);
@@ -585,7 +585,7 @@ AHCIPort::ScsiInquiry(scsi_ccb* request)
        }
 
 /*
-       uint8* data = (uint8*) &ataData;
+       uint8* data = (uint8*)&ataData;
        for (int i = 0; i < 512; i += 8) {
                TRACE("  %02x %02x %02x %02x %02x %02x %02x %02x\n", data[i], 
data[i+1],
                        data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], 
data[i+7]);
@@ -681,7 +681,7 @@ AHCIPort::ScsiSynchronizeCache(scsi_ccb* request)
                return;
        }
 
-       sreq->set_ata_cmd(fUse48BitCommands
+       sreq->SetATACommand(fUse48BitCommands
                ? ATA_COMMAND_FLUSH_CACHE_EXT : ATA_COMMAND_FLUSH_CACHE);
        ExecuteSataRequest(sreq);
 }
@@ -782,7 +782,7 @@ AHCIPort::ScsiReadWrite(scsi_ccb* request, uint64 lba, 
size_t sectorCount,
                }
                if (lba > MAX_SECTOR_LBA_48)
                        panic("achi: ScsiReadWrite position too large for 
48-bit LBA\n");
-               sreq->set_ata48_cmd(
+               sreq->SetATA48Command(
                        isWrite ? ATA_COMMAND_WRITE_DMA_EXT : 
ATA_COMMAND_READ_DMA_EXT,
                        lba, sectorCount);
        } else {
@@ -792,7 +792,7 @@ AHCIPort::ScsiReadWrite(scsi_ccb* request, uint64 lba, 
size_t sectorCount,
                }
                if (lba > MAX_SECTOR_LBA_28)
                        panic("achi: ScsiReadWrite position too large for 
normal LBA\n");
-               sreq->set_ata28_cmd(isWrite
+               sreq->SetATA28Command(isWrite
                        ? ATA_COMMAND_WRITE_DMA : ATA_COMMAND_READ_DMA, lba, 
sectorCount);
        }
 
@@ -842,15 +842,15 @@ AHCIPort::ScsiUnmap(scsi_ccb* request, 
scsi_unmap_parameter_list* unmapBlocks)
        }
 
        sata_request sreq;
-       sreq.set_ata48_cmd(ATA_COMMAND_DATA_SET_MANAGEMENT, 0,
+       sreq.SetATA48Command(ATA_COMMAND_DATA_SET_MANAGEMENT, 0,
                (lbaRangesSize + 511) / 512);
        sreq.SetFeature(1);
-       sreq.set_data(lbaRanges, lbaRangesSize);
+       sreq.SetData(lbaRanges, lbaRangesSize);
 
        ExecuteSataRequest(&sreq);
-       sreq.wait_for_completion();
+       sreq.WaitForCompletion();
 
-       if ((sreq.completion_status() & ATA_ERR) != 0) {
+       if ((sreq.CompletionStatus() & ATA_ERR) != 0) {
                TRACE("trim failed (%" B_PRIu32 " ranges)!", lbaRangeCount);
                request->subsys_status = SCSI_REQ_CMP_ERR;
        } else
@@ -871,13 +871,13 @@ AHCIPort::ExecuteSataRequest(sata_request* request, bool 
isWrite)
 
        int prdEntrys;
 
-       if (request->ccb() && request->ccb()->data_length) {
+       if (request->CCB() && request->CCB()->data_length) {
                FillPrdTable(fPRDTable, &prdEntrys, PRD_TABLE_ENTRY_COUNT,
-                       request->ccb()->sg_list, request->ccb()->sg_count,
-                       request->ccb()->data_length);
-       } else if (request->data() && request->size()) {
+                       request->CCB()->sg_list, request->CCB()->sg_count,
+                       request->CCB()->data_length);
+       } else if (request->Data() && request->Size()) {
                FillPrdTable(fPRDTable, &prdEntrys, PRD_TABLE_ENTRY_COUNT,
-                       request->data(), request->size());
+                       request->Data(), request->Size());
        } else
                prdEntrys = 0;
 
@@ -885,14 +885,14 @@ AHCIPort::ExecuteSataRequest(sata_request* request, bool 
isWrite)
 
        fCommandList->prdtl_flags_cfl = 0;
        fCommandList->cfl = 5; // 20 bytes, length in DWORDS
-       memcpy((char*)fCommandTable->cfis, request->fis(), 20);
+       memcpy((char*)fCommandTable->cfis, request->FIS(), 20);
 
-       fTestUnitReadyActive = request->is_test_unit_ready();
-       if (request->is_atapi()) {
+       fTestUnitReadyActive = request->IsTestUnitReady();
+       if (request->IsATAPI()) {
                // ATAPI PACKET is a 12 or 16 byte SCSI command
                memset((char*)fCommandTable->acmd, 0, 32);
-               memcpy((char*)fCommandTable->acmd, request->ccb()->cdb,
-                       request->ccb()->cdb_length);
+               memcpy((char*)fCommandTable->acmd, request->CCB()->cdb,
+                       request->CCB()->cdb_length);
                fCommandList->a = 1;
        }
 
@@ -905,7 +905,7 @@ AHCIPort::ExecuteSataRequest(sata_request* request, bool 
isWrite)
                TRACE("ExecuteAtaRequest port %d: device is busy\n", fIndex);
                ResetPort();
                FinishTransfer();
-               request->abort();
+               request->Abort();
                return;
        }
 
@@ -949,11 +949,11 @@ AHCIPort::ExecuteSataRequest(sata_request* request, bool 
isWrite)
 
        if (status == B_TIMED_OUT) {
                TRACE("ExecuteAtaRequest port %d: device timeout\n", fIndex);
-               request->abort();
+               request->Abort();
                return;
        }
 
-       request->finish(tfd, bytesTransfered);
+       request->Finish(tfd, bytesTransfered);
 }
 
 
@@ -989,7 +989,7 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb* request)
                        return;
                }
 
-               sreq->set_atapi_cmd(request->data_length);
+               sreq->SetATAPICommand(request->data_length);
 //             uint8* data = (uint8*) sreq->ccb()->cdb;
 //             for (int i = 0; i < 16; i += 8) {
 //                     TRACE("  %02x %02x %02x %02x %02x %02x %02x %02x\n", 
data[i], data[i+1], data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], 
data[i+7]);
diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp 
b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
index 2fe8b21..9114978 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
+++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp
@@ -25,7 +25,7 @@ sata_request::sata_request()
 }
 
 
-sata_request::sata_request(scsi_ccb *ccb)
+sata_request::sata_request(scsi_ccb* ccb)
        :
        fCcb(ccb),
        fIsATAPI(false),
@@ -45,16 +45,16 @@ sata_request::~sata_request()
 
 
 void
-sata_request::set_data(void *data, size_t dataSize)
+sata_request::SetData(void* data, size_t dataSize)
 {
-       if (fCcb) panic("wrong usage");
-       fData = data;
-       fDataSize = dataSize;
+       ASSERT(fCcb == NULL);
+       fData = data;
+       fDataSize = dataSize;
 }
 
 
 void
-sata_request::set_ata_cmd(uint8 command)
+sata_request::SetATACommand(uint8 command)
 {
        memset(fFis, 0, sizeof(fFis));
        fFis[0] = FIS_TYPE_REGISTER_HOST_TO_DEVICE;
@@ -65,9 +65,9 @@ sata_request::set_ata_cmd(uint8 command)
 
 
 void
-sata_request::set_ata28_cmd(uint8 command, uint32 lba, uint8 sectorCount)
+sata_request::SetATA28Command(uint8 command, uint32 lba, uint8 sectorCount)
 {
-       set_ata_cmd(command);
+       SetATACommand(command);
        fFis[4] = lba & 0xff;
        fFis[5] = (lba >> 8) & 0xff;
        fFis[6] = (lba >> 16) & 0xff;
@@ -78,9 +78,9 @@ sata_request::set_ata28_cmd(uint8 command, uint32 lba, uint8 
sectorCount)
 
 
 void
-sata_request::set_ata48_cmd(uint8 command, uint64 lba, uint16 sectorCount)
+sata_request::SetATA48Command(uint8 command, uint64 lba, uint16 sectorCount)
 {
-       set_ata_cmd(command);
+       SetATACommand(command);
        fFis[4] = lba & 0xff;
        fFis[5] = (lba >> 8) & 0xff;
        fFis[6] = (lba >> 16) & 0xff;
@@ -103,10 +103,10 @@ sata_request::SetFeature(uint16 feature)
 
 
 void
-sata_request::set_atapi_cmd(size_t transferLength)
+sata_request::SetATAPICommand(size_t transferLength)
 {
        fIsATAPI = true;
-       set_ata_cmd(0xa0);
+       SetATACommand(0xa0);
        if (1 /* isPIO */) {
                if (transferLength == 0)
                        transferLength = 2;
@@ -119,13 +119,13 @@ sata_request::set_atapi_cmd(size_t transferLength)
 
 
 void
-sata_request::finish(int tfd, size_t bytesTransfered)
+sata_request::Finish(int tfd, size_t bytesTransfered)
 {
-       if (tfd & (ATA_ERR | ATA_DF)) {
+       if ((tfd & (ATA_ERR | ATA_DF)) != 0) {
                uint8 status = tfd & 0xff;
                uint8 error = (tfd >> 8) & 0xff;
 
-               if (!is_test_unit_ready()) {
+               if (!IsTestUnitReady()) {
                        dprintf("ahci: sata_request::finish ATA command 0x%02x 
failed\n",
                                fFis[2]);
                        dprintf("ahci: sata_request::finish status 0x%02x, 
error 0x%02x\n",
@@ -140,7 +140,7 @@ sata_request::finish(int tfd, size_t bytesTransfered)
                if (tfd & (ATA_ERR | ATA_DF)) {
                        fCcb->subsys_status = SCSI_REQ_CMP_ERR;
                        if (fIsATAPI) {
-                               if (!is_test_unit_ready()) {
+                               if (!IsTestUnitReady()) {
                                        dprintf("ahci: sata_request::finish 
ATAPI packet %02x %02x "
                                                "%02x %02x %02x %02x %02x %02x 
%02x %02x %02x %02x "
                                                "%02x %02x %02x %02x (len 
%d)\n",
@@ -181,10 +181,10 @@ sata_request::finish(int tfd, size_t bytesTransfered)
 
 
 void
-sata_request::abort()
+sata_request::Abort()
 {
        dprintf("ahci: sata_request::abort called for command 0x%02x\n", 
fFis[2]);
-       if (fCcb) {
+       if (fCcb != NULL) {
                fCcb->subsys_status = SCSI_REQ_ABORTED;
                gSCSI->finished(fCcb, 1);
                delete this;
@@ -196,16 +196,16 @@ sata_request::abort()
 
 
 void
-sata_request::wait_for_completion()
+sata_request::WaitForCompletion()
 {
-       if (fCcb) panic("wrong usage");
+       ASSERT(fCcb == NULL);
        acquire_sem(fCompletionSem);
 }
 
 
 int
-sata_request::completion_status()
+sata_request::CompletionStatus()
 {
-       if (fCcb) panic("wrong usage");
+       ASSERT(fCcb == NULL);
        return fCompletionStatus;
 }
diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.h 
b/src/add-ons/kernel/busses/scsi/ahci/sata_request.h
index 61191be..5686530 100644
--- a/src/add-ons/kernel/busses/scsi/ahci/sata_request.h
+++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.h
@@ -5,88 +5,91 @@
 #ifndef _SATA_REQUEST_H
 #define _SATA_REQUEST_H
 
+
 #include "ahci_defs.h"
 #include "scsi_cmds.h"
 
-class sata_request
-{
+
+class sata_request {
 public:
-                                       sata_request();
-                                       sata_request(scsi_ccb *ccb);
-                                       ~sata_request();
+                                                               sata_request();
+                                                               
sata_request(scsi_ccb* ccb);
+                                                               ~sata_request();
 
-       void                    set_data(void *data, size_t dataSize);
+                       void                            SetData(void* data, 
size_t dataSize);
 
-       void                    set_ata_cmd(uint8 command);
-       void                    set_ata28_cmd(uint8 command, uint32 lba, uint8 
sectorCount);
-       void                    set_ata48_cmd(uint8 command, uint64 lba, uint16 
sectorCount);
-       void                    SetFeature(uint16 feature);
+                       void                            SetATACommand(uint8 
command);
+                       void                            SetATA28Command(uint8 
command, uint32 lba,
+                                                                       uint8 
sectorCount);
+                       void                            SetATA48Command(uint8 
command, uint64 lba,
+                                                                       uint16 
sectorCount);
+                       void                            SetFeature(uint16 
feature);
 
-       void                    set_atapi_cmd(size_t transferLength);
-       bool                    is_atapi();
-       bool                    is_test_unit_ready();
+                       void                            SetATAPICommand(size_t 
transferLength);
+                       bool                            IsATAPI();
+                       bool                            IsTestUnitReady();
 
-       scsi_ccb *              ccb();
-       const void *    fis();
-       void *                  data();
-       int                             size();
-       void                    finish(int tfd, size_t bytesTransfered);
-       void                    abort();
+                       scsi_ccb*                       CCB();
+                       const void*                     FIS();
+                       void*                           Data();
+                       int                                     Size();
+                       void                            Finish(int tfd, size_t 
bytesTransfered);
+                       void                            Abort();
 
-       void                    wait_for_completion();
-       int                             completion_status();
+                       void                            WaitForCompletion();
+                       int                                     
CompletionStatus();
 
 private:
-       scsi_ccb *              fCcb;
-       uint8                   fFis[20];
-       bool                    fIsATAPI;
-       sem_id                  fCompletionSem;
-       int                             fCompletionStatus;
-       void *                  fData;
-       size_t                  fDataSize;
+                       scsi_ccb*                       fCcb;
+                       uint8                           fFis[20];
+                       bool                            fIsATAPI;
+                       sem_id                          fCompletionSem;
+                       int                                     
fCompletionStatus;
+                       void*                           fData;
+                       size_t                          fDataSize;
 };
 

[ *** diff truncated: 54 lines dropped *** ]


############################################################################

Commit:      547cd462f843df15db02ed0dd7a35528221b66bc
URL:         http://cgit.haiku-os.org/haiku/commit/?id=547cd46
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Sat Nov  2 23:18:57 2013 UTC

trim: Added is_called_via_syscall() function.

* And use it in get_trim_data_from_user(), formerly known as copy_*().
* This fixes differentiating between user and kernel buffers.

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

############################################################################

Commit:      e6bde50a074e8e2b2f917f2758efe0604463c24d
URL:         http://cgit.haiku-os.org/haiku/commit/?id=e6bde50
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Sat Nov  2 23:27:40 2013 UTC

scsi_periph: use synchronous command.

* The call waited anyway, so there is no reason to make it async.

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

############################################################################

Revision:    hrev46325
Commit:      0c873619ce86975e9ed3c66e88ca4dc9ef303a82
URL:         http://cgit.haiku-os.org/haiku/commit/?id=0c87361
Author:      Axel Doerfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Sun Nov  3 22:17:36 2013 UTC
Committer:   Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Commit-Date: Thu Nov  7 18:06:35 2013 UTC

ahci: Fixed missing endian conversion.

* Spotted by Rene, thanks a lot!

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


Other related posts:

  • » [haiku-commits] haiku: hrev46325 - src/add-ons/kernel/busses/scsi/ahci src/add-ons/kernel/file_systems/bfs src/add-ons/kernel/generic/scsi_periph src/bin headers/private/kernel/util - axeld