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.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/*
|
||||
* Copyright 2008-2012, Axel Dörfler, [email protected].
|
||||
* Copyright 2008-2013, Axel Dörfler, [email protected].
|
||||
* 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
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user