haiku/headers/private/drivers/scsi_periph.h
Jérôme Duval 688acf41a3 add physical_block_size field where applicable
only scsi_disk checks the actual value, other drivers take the logical block size.

This change reports the physical block size from the disk rather than the block
size used by IDE/SATA/SCSI commands. On typical modern SATA disks, the SATA
commands will use 512 byte blocks, but the disk will actually read and write
4K blocks internally. This is only of importance for partition alignment for DriveSetup,
and is independant of file systems or partitioning systems. This could also influence
the recommended block size for some file systems.

Change-Id: Id0f2e22659e89fcef64c1f8d04f81cd68995e01f
Reviewed-on: https://review.haiku-os.org/c/haiku/+/5667
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
2022-09-23 06:56:01 +00:00

152 lines
5.4 KiB
C

/*
* Copyright 2004-2013, Haiku, Inc. All RightsReserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _SCSI_PERIPH_H
#define _SCSI_PERIPH_H
/*! Use this module to minimize work required to write a SCSI
peripheral driver.
It takes care of:
- error handling
- medium changes (including restarting the medium)
- detection of medium capacity
*/
#include <bus/SCSI.h>
#include <scsi_cmds.h>
#include <Drivers.h>
// cookie issued by module per device
typedef struct scsi_periph_device_info *scsi_periph_device;
// cookie issued by module per file handle
typedef struct scsi_periph_handle_info *scsi_periph_handle;
// "standardized" error code to simplify handling of scsi errors
typedef enum {
err_act_ok, // executed successfully
err_act_retry, // failed, retry 3 times
err_act_fail, // failed, don't retry
err_act_many_retries, // failed, retry multiple times (currently 10 times)
err_act_start, // devices requires a "start" command
err_act_invalid_req // request is invalid
} err_act;
// packed scsi command result
typedef struct err_res {
status_t error_code : 32; // Be error code
uint32 action : 8; // err_act code
} err_res;
#define MK_ERROR( aaction, code ) ({ \
err_res _res = {error_code: (code), action: (aaction) }; \
_res; \
})
// cookie issued by driver to identify itself
//typedef struct periph_info *periph_cookie;
// cookie issued by driver per device
typedef struct periph_device_info *periph_device_cookie;
// cookie issued by driver per file handle
typedef struct periph_handle_info *periph_handle_cookie;
typedef struct IOOperation io_operation;
// callbacks to be provided by peripheral driver
typedef struct scsi_periph_callbacks {
// *** block devices ***
// informs of new size of medium
// (set to NULL if not a block device)
void (*set_capacity)(periph_device_cookie cookie, uint64 capacity,
uint32 blockSize, uint32 physicalBlockSize);
// *** removable devices
// called when media got changed (can be NULL if medium is not changable)
// (you don't need to call periph->media_changed, but it's doesn't if you do)
// ccb - request at your disposal
void (*media_changed)(periph_device_cookie cookie, scsi_ccb *request);
} scsi_periph_callbacks;
typedef struct scsi_block_range {
// values are in blocks
uint64 lba;
uint64 size;
} scsi_block_range;
// functions provided by this module
typedef struct scsi_periph_interface {
module_info info;
// *** init/cleanup ***
// preferred_ccb_size - preferred command size; if zero, the shortest is used
status_t (*register_device)(periph_device_cookie cookie,
scsi_periph_callbacks *callbacks, scsi_device scsiDevice,
scsi_device_interface *scsi, device_node *node, bool removable,
int preferredCcbSize, scsi_periph_device *driver);
status_t (*unregister_device)(scsi_periph_device driver);
// *** basic command execution ***
// exec command, retrying on problems
status_t (*safe_exec)(scsi_periph_device periphCookie, scsi_ccb *request);
// exec simple command
status_t (*simple_exec)(scsi_periph_device device, void *cdb,
uint8 cdbLength, void *data, size_t dataLength, int ccbFlags);
// *** file handling ***
// to be called when a new file is opened
status_t (*handle_open)(scsi_periph_device device,
periph_handle_cookie periph_handle, scsi_periph_handle *_handle);
// to be called when a file is closed
status_t (*handle_close)(scsi_periph_handle handle);
// to be called when a file is freed
status_t (*handle_free)(scsi_periph_handle handle);
// *** default implementation for block devices ***
status_t (*read_write)(scsi_periph_device_info *device, scsi_ccb *request,
uint64 offset, size_t numBlocks, physical_entry* vecs, size_t vecCount,
bool isWrite, size_t* _bytesTransferred);
status_t (*io)(scsi_periph_device device, io_operation *operation,
size_t *_bytesTransferred);
// block ioctls
status_t (*ioctl)(scsi_periph_handle handle, int op, void *buffer,
size_t length);
// check medium capacity (calls set_capacity callback on success)
// 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,
scsi_block_range* ranges, uint32 rangeCount, uint64* trimmedBlocks);
// *** removable media ***
// to be called when a medium change is detected to block subsequent commands
void (*media_changed)(scsi_periph_device device);
// convert result of *request to err_res
err_res (*check_error)(scsi_periph_device device, scsi_ccb *request);
// send start or stop command to device
// withLoadEject = true - include loading/ejecting,
// false - only do allow/deny
err_res (*send_start_stop)(scsi_periph_device device, scsi_ccb *request,
bool start, bool withLoadEject);
// checks media status and waits for device to become ready
// 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);
// compose device name consisting of prefix and path/target/LUN
// (result must be freed by caller)
char *(*compose_device_name)(device_node *device_node, const char *prefix);
} scsi_periph_interface;
#define SCSI_PERIPH_MODULE_NAME "generic/scsi_periph/v1"
#endif /* _SCSI_PERIPH_H */