xref: /haiku/headers/private/drivers/scsi_periph.h (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
1 /*
2  * Copyright 2004-2013, Haiku, Inc. All RightsReserved.
3  * Copyright 2002/03, Thomas Kurschel. All rights reserved.
4  *
5  * Distributed under the terms of the MIT License.
6  */
7 #ifndef _SCSI_PERIPH_H
8 #define _SCSI_PERIPH_H
9 
10 
11 /*!	Use this module to minimize work required to write a SCSI
12 	peripheral driver.
13 
14 	It takes care of:
15 	- error handling
16 	- medium changes (including restarting the medium)
17 	- detection of medium capacity
18 */
19 
20 
21 #include <bus/SCSI.h>
22 #include <scsi_cmds.h>
23 #include <Drivers.h>
24 
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;
29 
30 // "standardized" error code to simplify handling of scsi errors
31 typedef enum {
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
38 } err_act;
39 
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
44 } err_res;
45 
46 #define MK_ERROR( aaction, code ) ({ \
47 	err_res _res = {error_code: (code), action: (aaction) };	\
48 	_res;					\
49 })
50 
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;
57 
58 typedef struct IOOperation io_operation;
59 
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,
66 		uint32 blockSize);
67 
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;
74 
75 typedef struct scsi_block_range {
76 	uint64	offset;
77 	uint64	size;
78 } scsi_block_range;
79 
80 // functions provided by this module
81 typedef struct scsi_periph_interface {
82 	module_info info;
83 
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);
91 
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);
98 
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);
107 
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);
114 
115 	// block ioctls
116 	status_t (*ioctl)(scsi_periph_handle handle, int op, void *buffer,
117 		size_t length);
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);
121 
122 	// synchronizes (flush) the device cache
123 	err_res (*synchronize_cache)(scsi_periph_device device, scsi_ccb *request);
124 
125 	status_t (*trim_device)(scsi_periph_device_info *device, scsi_ccb *request,
126 		scsi_block_range* ranges, uint32 rangeCount);
127 
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);
142 
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;
147 
148 #define SCSI_PERIPH_MODULE_NAME "generic/scsi_periph/v1"
149 
150 #endif	/* _SCSI_PERIPH_H */
151