xref: /haiku/headers/private/drivers/scsi_periph.h (revision 8195a5a835117ab2da405e0d477153570b75d921)
1 /*
2  * Copyright 2004-2007, 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 <block_io.h>
23 #include <scsi_cmds.h>
24 #include <Drivers.h>
25 
26 // cookie issued by module per device
27 typedef struct scsi_periph_device_info *scsi_periph_device;
28 // cookie issued by module per file handle
29 typedef struct scsi_periph_handle_info *scsi_periph_handle;
30 
31 // "standardized" error code to simplify handling of scsi errors
32 typedef enum {
33 	err_act_ok,					// executed successfully
34 	err_act_retry,				// failed, retry 3 times
35 	err_act_fail,				// failed, don't retry
36 	err_act_many_retries,		// failed, retry multiple times (currently 10 times)
37 	err_act_start,				// devices requires a "start" command
38 	err_act_invalid_req			// request is invalid
39 } err_act;
40 
41 // packed scsi command result
42 typedef struct err_res {
43 	status_t error_code : 32;	// Be error code
44 	uint32 action : 8;			// err_act code
45 } err_res;
46 
47 #define MK_ERROR( aaction, code ) ({ \
48 	err_res res = {error_code: (code), action: (aaction) };	\
49 	res;					\
50 })
51 
52 // device icon type
53 typedef enum {
54 	icon_type_disk,
55 	icon_type_removal,
56 	icon_type_floppy,
57 	icon_type_cd
58 } icon_type;
59 
60 // cookie issued by driver to identify itself
61 //typedef struct periph_info *periph_cookie;
62 // cookie issued by driver per device
63 typedef struct periph_device_info *periph_device_cookie;
64 // cookie issued by driver per file handle
65 typedef struct periph_handle_info *periph_handle_cookie;
66 
67 
68 // callbacks to be provided by peripheral driver
69 typedef struct scsi_periph_callbacks {
70 	// *** block devices ***
71 	// informs of new size of medium
72 	// (set to NULL if not a block device)
73 	void (*set_capacity)( periph_device_cookie periph_device, uint64 capacity,
74 		uint32 block_size );
75 
76 	// *** removable devices
77 	// called when media got changed (can be NULL if medium is not changable)
78 	// (you don't need to call periph->media_changed, but it's doesn't if you do)
79 	// ccb - request at your disposal
80 	void (*media_changed)( periph_device_cookie periph_device,
81 		scsi_ccb *request );
82 } scsi_periph_callbacks;
83 
84 
85 // functions provided by this module
86 typedef struct scsi_periph_interface {
87 	module_info info;
88 
89 	// *** init/cleanup ***
90 	status_t (*register_device)(
91 		periph_device_cookie periph_device,
92 		scsi_periph_callbacks *callbacks,
93 		scsi_device scsi_device,
94 		scsi_device_interface *scsi,
95 		device_node_handle node,
96 		bool removable,
97 		scsi_periph_device *driver );
98 	status_t (*unregister_device)( scsi_periph_device driver );
99 
100 	// *** basic command execution ***
101 	// exec command, retrying on problems
102 	status_t (*safe_exec)(
103 		scsi_periph_device periph_device,
104 		scsi_ccb *request );
105 	// exec simple command
106 	status_t (*simple_exec)( scsi_periph_device device,
107 		void *cdb, uchar cdb_len, void *data, size_t data_len,
108 		int ccb_flags );
109 
110 	// *** file handling ***
111 	// to be called when a new file is opened
112 	status_t (*handle_open)( scsi_periph_device device,
113 		periph_handle_cookie periph_handle, scsi_periph_handle *res_handle );
114 	// to be called when a file is closed
115 	status_t (*handle_close)( scsi_periph_handle handle );
116 	// to be called when a file is freed
117 	status_t (*handle_free)( scsi_periph_handle handle );
118 
119 	// *** default implementation for block devices ***
120 	// block read
121 	// preferred_ccb_size - preferred command size; if zero, the shortest is used
122 	status_t (*read)( scsi_periph_handle handle, const phys_vecs *vecs,
123 		off_t pos, size_t num_blocks, uint32 block_size, size_t *bytes_transferred,
124 		int preferred_ccb_size );
125 	// block write
126 	// (see block_read)
127 	status_t (*write)( scsi_periph_handle handle, const phys_vecs *vecs,
128 		off_t pos, size_t num_blocks, uint32 block_size, size_t *bytes_transferred,
129 		int preferred_ccb_size );
130 	// block ioctls
131 	status_t (*ioctl)( scsi_periph_handle handle, int op, void *buf, size_t len );
132 	// check medium capacity (calls set_capacity callback on success)
133 	// request - ccb for this device; is used to talk to device
134 	status_t (*check_capacity)( scsi_periph_device device, scsi_ccb *request );
135 
136 	// *** removable media ***
137 	// to be called when a medium change is detected to block subsequent commands
138 	void (*media_changed)( scsi_periph_device device );
139 	// convert result of *request to err_res
140 	err_res (*check_error)( scsi_periph_device device, scsi_ccb *request );
141 	// send start or stop command to device
142 	// with_LoEj = true - include loading/ejecting,
143 	//             false - only do allow/deny
144 	err_res (*send_start_stop)( scsi_periph_device device, scsi_ccb *request,
145 		bool start, bool with_LoEj );
146 	// checks media status and waits for device to become ready
147 	// returns: B_OK, B_DEV_MEDIA_CHANGE_REQUESTED, B_NO_MEMORY or
148 	// pending error reported by handle_get_error
149 	status_t (*get_media_status)( scsi_periph_handle handle );
150 
151 	// compose device name consisting of prefix and path/target/LUN
152 	// (result must be freed by caller)
153 	char *(*compose_device_name)(device_node_handle device_node, const char *prefix);
154 
155 	// fill data with icon (for B_GET_ICON ioctl)
156 	status_t (*get_icon)( icon_type type, device_icon *data );
157 
158 	// synchronizes (flush) the device cache
159 	err_res(*synchronize_cache)(scsi_periph_device device, scsi_ccb *request);
160 } scsi_periph_interface;
161 
162 #define SCSI_PERIPH_MODULE_NAME "generic/scsi_periph/v1"
163 
164 #endif	/* _SCSI_PERIPH_H */
165