2 * Copyright 2004-2013, Haiku, Inc. All RightsReserved.
3 * Copyright 2002/03, Thomas Kurschel. All rights reserved.
5 * Distributed under the terms of the MIT License.
11 /*! Use this module to minimize work required to write a SCSI
16 - medium changes (including restarting the medium)
17 - detection of medium capacity
22 #include <scsi_cmds.h>
25 // cookie issued by module per device
26 typedef struct scsi_periph_device_info
*scsi_periph_device
;
27 // cookie issued by module per file handle
28 typedef struct scsi_periph_handle_info
*scsi_periph_handle
;
30 // "standardized" error code to simplify handling of scsi errors
32 err_act_ok
, // executed successfully
33 err_act_retry
, // failed, retry 3 times
34 err_act_fail
, // failed, don't retry
35 err_act_many_retries
, // failed, retry multiple times (currently 10 times)
36 err_act_start
, // devices requires a "start" command
37 err_act_invalid_req
// request is invalid
40 // packed scsi command result
41 typedef struct err_res
{
42 status_t error_code
: 32; // Be error code
43 uint32 action
: 8; // err_act code
46 #define MK_ERROR( aaction, code ) ({ \
47 err_res res = {error_code: (code), action: (aaction) }; \
51 // cookie issued by driver to identify itself
52 //typedef struct periph_info *periph_cookie;
53 // cookie issued by driver per device
54 typedef struct periph_device_info
*periph_device_cookie
;
55 // cookie issued by driver per file handle
56 typedef struct periph_handle_info
*periph_handle_cookie
;
58 typedef struct IOOperation io_operation
;
60 // callbacks to be provided by peripheral driver
61 typedef struct scsi_periph_callbacks
{
62 // *** block devices ***
63 // informs of new size of medium
64 // (set to NULL if not a block device)
65 void (*set_capacity
)(periph_device_cookie cookie
, uint64 capacity
,
68 // *** removable devices
69 // called when media got changed (can be NULL if medium is not changable)
70 // (you don't need to call periph->media_changed, but it's doesn't if you do)
71 // ccb - request at your disposal
72 void (*media_changed
)(periph_device_cookie cookie
, scsi_ccb
*request
);
73 } scsi_periph_callbacks
;
75 typedef struct scsi_block_range
{
80 // functions provided by this module
81 typedef struct scsi_periph_interface
{
84 // *** init/cleanup ***
85 // preferred_ccb_size - preferred command size; if zero, the shortest is used
86 status_t (*register_device
)(periph_device_cookie cookie
,
87 scsi_periph_callbacks
*callbacks
, scsi_device scsiDevice
,
88 scsi_device_interface
*scsi
, device_node
*node
, bool removable
,
89 int preferredCcbSize
, scsi_periph_device
*driver
);
90 status_t (*unregister_device
)(scsi_periph_device driver
);
92 // *** basic command execution ***
93 // exec command, retrying on problems
94 status_t (*safe_exec
)(scsi_periph_device periphCookie
, scsi_ccb
*request
);
95 // exec simple command
96 status_t (*simple_exec
)(scsi_periph_device device
, void *cdb
,
97 uint8 cdbLength
, void *data
, size_t dataLength
, int ccbFlags
);
99 // *** file handling ***
100 // to be called when a new file is opened
101 status_t (*handle_open
)(scsi_periph_device device
,
102 periph_handle_cookie periph_handle
, scsi_periph_handle
*_handle
);
103 // to be called when a file is closed
104 status_t (*handle_close
)(scsi_periph_handle handle
);
105 // to be called when a file is freed
106 status_t (*handle_free
)(scsi_periph_handle handle
);
108 // *** default implementation for block devices ***
109 status_t (*read_write
)(scsi_periph_device_info
*device
, scsi_ccb
*request
,
110 uint64 offset
, size_t numBlocks
, physical_entry
* vecs
, size_t vecCount
,
111 bool isWrite
, size_t* _bytesTransferred
);
112 status_t (*io
)(scsi_periph_device device
, io_operation
*operation
,
113 size_t *_bytesTransferred
);
116 status_t (*ioctl
)(scsi_periph_handle handle
, int op
, void *buffer
,
118 // check medium capacity (calls set_capacity callback on success)
119 // request - ccb for this device; is used to talk to device
120 status_t (*check_capacity
)(scsi_periph_device device
, scsi_ccb
*request
);
122 // synchronizes (flush) the device cache
123 err_res (*synchronize_cache
)(scsi_periph_device device
, scsi_ccb
*request
);
125 status_t (*trim_device
)(scsi_periph_device_info
*device
, scsi_ccb
*request
,
126 scsi_block_range
* ranges
, uint32 rangeCount
);
128 // *** removable media ***
129 // to be called when a medium change is detected to block subsequent commands
130 void (*media_changed
)(scsi_periph_device device
);
131 // convert result of *request to err_res
132 err_res (*check_error
)(scsi_periph_device device
, scsi_ccb
*request
);
133 // send start or stop command to device
134 // withLoadEject = true - include loading/ejecting,
135 // false - only do allow/deny
136 err_res (*send_start_stop
)(scsi_periph_device device
, scsi_ccb
*request
,
137 bool start
, bool withLoadEject
);
138 // checks media status and waits for device to become ready
139 // returns: B_OK, B_DEV_MEDIA_CHANGE_REQUESTED, B_NO_MEMORY or
140 // pending error reported by handle_get_error
141 status_t (*get_media_status
)(scsi_periph_handle handle
);
143 // compose device name consisting of prefix and path/target/LUN
144 // (result must be freed by caller)
145 char *(*compose_device_name
)(device_node
*device_node
, const char *prefix
);
146 } scsi_periph_interface
;
148 #define SCSI_PERIPH_MODULE_NAME "generic/scsi_periph/v1"
150 #endif /* _SCSI_PERIPH_H */