1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * tape device driver for 3480/3490E/3590 tapes. |
4 | * |
5 | * S390 and zSeries version |
6 | * Copyright IBM Corp. 2001, 2009 |
7 | * Author(s): Carsten Otte <cotte@de.ibm.com> |
8 | * Tuan Ngo-Anh <ngoanh@de.ibm.com> |
9 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
10 | * Stefan Bader <shbader@de.ibm.com> |
11 | */ |
12 | |
13 | #ifndef _TAPE_H |
14 | #define _TAPE_H |
15 | |
16 | #include <asm/ccwdev.h> |
17 | #include <asm/debug.h> |
18 | #include <asm/idals.h> |
19 | #include <linux/kernel.h> |
20 | #include <linux/module.h> |
21 | #include <linux/mtio.h> |
22 | #include <linux/interrupt.h> |
23 | #include <linux/workqueue.h> |
24 | |
25 | struct gendisk; |
26 | |
27 | /* |
28 | * Define DBF_LIKE_HELL for lots of messages in the debug feature. |
29 | */ |
30 | #define DBF_LIKE_HELL |
31 | #ifdef DBF_LIKE_HELL |
32 | #define DBF_LH(level, str, ...) \ |
33 | do { \ |
34 | debug_sprintf_event(TAPE_DBF_AREA, level, str, ## __VA_ARGS__); \ |
35 | } while (0) |
36 | #else |
37 | #define DBF_LH(level, str, ...) do {} while(0) |
38 | #endif |
39 | |
40 | /* |
41 | * macros s390 debug feature (dbf) |
42 | */ |
43 | #define DBF_EVENT(d_level, d_str...) \ |
44 | do { \ |
45 | debug_sprintf_event(TAPE_DBF_AREA, d_level, d_str); \ |
46 | } while (0) |
47 | |
48 | #define DBF_EXCEPTION(d_level, d_str...) \ |
49 | do { \ |
50 | debug_sprintf_exception(TAPE_DBF_AREA, d_level, d_str); \ |
51 | } while (0) |
52 | |
53 | #define TAPE_VERSION_MAJOR 2 |
54 | #define TAPE_VERSION_MINOR 0 |
55 | #define TAPE_MAGIC "tape" |
56 | |
57 | #define TAPE_MINORS_PER_DEV 2 /* two minors per device */ |
58 | #define TAPEBLOCK_HSEC_SIZE 2048 |
59 | #define TAPEBLOCK_HSEC_S2B 2 |
60 | #define TAPEBLOCK_RETRIES 5 |
61 | |
62 | enum tape_medium_state { |
63 | MS_UNKNOWN, |
64 | MS_LOADED, |
65 | MS_UNLOADED, |
66 | MS_SIZE |
67 | }; |
68 | |
69 | enum tape_state { |
70 | TS_UNUSED=0, |
71 | TS_IN_USE, |
72 | TS_BLKUSE, |
73 | TS_INIT, |
74 | TS_NOT_OPER, |
75 | TS_SIZE |
76 | }; |
77 | |
78 | enum tape_op { |
79 | TO_BLOCK, /* Block read */ |
80 | TO_BSB, /* Backward space block */ |
81 | TO_BSF, /* Backward space filemark */ |
82 | TO_DSE, /* Data security erase */ |
83 | TO_FSB, /* Forward space block */ |
84 | TO_FSF, /* Forward space filemark */ |
85 | TO_LBL, /* Locate block label */ |
86 | TO_NOP, /* No operation */ |
87 | TO_RBA, /* Read backward */ |
88 | TO_RBI, /* Read block information */ |
89 | TO_RFO, /* Read forward */ |
90 | TO_REW, /* Rewind tape */ |
91 | TO_RUN, /* Rewind and unload tape */ |
92 | TO_WRI, /* Write block */ |
93 | TO_WTM, /* Write tape mark */ |
94 | TO_MSEN, /* Medium sense */ |
95 | TO_LOAD, /* Load tape */ |
96 | TO_READ_CONFIG, /* Read configuration data */ |
97 | TO_READ_ATTMSG, /* Read attention message */ |
98 | TO_DIS, /* Tape display */ |
99 | TO_ASSIGN, /* Assign tape to channel path */ |
100 | TO_UNASSIGN, /* Unassign tape from channel path */ |
101 | TO_CRYPT_ON, /* Enable encrpytion */ |
102 | TO_CRYPT_OFF, /* Disable encrpytion */ |
103 | TO_KEKL_SET, /* Set KEK label */ |
104 | TO_KEKL_QUERY, /* Query KEK label */ |
105 | TO_RDC, /* Read device characteristics */ |
106 | TO_SIZE, /* #entries in tape_op_t */ |
107 | }; |
108 | |
109 | /* Forward declaration */ |
110 | struct tape_device; |
111 | |
112 | /* tape_request->status can be: */ |
113 | enum tape_request_status { |
114 | TAPE_REQUEST_INIT, /* request is ready to be processed */ |
115 | TAPE_REQUEST_QUEUED, /* request is queued to be processed */ |
116 | TAPE_REQUEST_IN_IO, /* request is currently in IO */ |
117 | TAPE_REQUEST_DONE, /* request is completed. */ |
118 | TAPE_REQUEST_CANCEL, /* request should be canceled. */ |
119 | TAPE_REQUEST_LONG_BUSY, /* request has to be restarted after long busy */ |
120 | }; |
121 | |
122 | /* Tape CCW request */ |
123 | struct tape_request { |
124 | struct list_head list; /* list head for request queueing. */ |
125 | struct tape_device *device; /* tape device of this request */ |
126 | struct ccw1 *cpaddr; /* address of the channel program. */ |
127 | void *cpdata; /* pointer to ccw data. */ |
128 | enum tape_request_status status;/* status of this request */ |
129 | int options; /* options for execution. */ |
130 | int retries; /* retry counter for error recovery. */ |
131 | int rescnt; /* residual count from devstat. */ |
132 | struct timer_list timer; /* timer for std_assign_timeout(). */ |
133 | |
134 | /* Callback for delivering final status. */ |
135 | void (*callback)(struct tape_request *, void *); |
136 | void *callback_data; |
137 | |
138 | enum tape_op op; |
139 | int rc; |
140 | }; |
141 | |
142 | /* Function type for magnetic tape commands */ |
143 | typedef int (*tape_mtop_fn)(struct tape_device *, int); |
144 | |
145 | /* Size of the array containing the mtops for a discipline */ |
146 | #define TAPE_NR_MTOPS (MTMKPART+1) |
147 | |
148 | /* Tape Discipline */ |
149 | struct tape_discipline { |
150 | struct module *owner; |
151 | int (*setup_device)(struct tape_device *); |
152 | void (*cleanup_device)(struct tape_device *); |
153 | int (*irq)(struct tape_device *, struct tape_request *, struct irb *); |
154 | struct tape_request *(*read_block)(struct tape_device *, size_t); |
155 | struct tape_request *(*write_block)(struct tape_device *, size_t); |
156 | void (*process_eov)(struct tape_device*); |
157 | /* ioctl function for additional ioctls. */ |
158 | int (*ioctl_fn)(struct tape_device *, unsigned int, unsigned long); |
159 | /* Array of tape commands with TAPE_NR_MTOPS entries */ |
160 | tape_mtop_fn *mtop_array; |
161 | }; |
162 | |
163 | /* |
164 | * The discipline irq function either returns an error code (<0) which |
165 | * means that the request has failed with an error or one of the following: |
166 | */ |
167 | #define TAPE_IO_SUCCESS 0 /* request successful */ |
168 | #define TAPE_IO_PENDING 1 /* request still running */ |
169 | #define TAPE_IO_RETRY 2 /* retry to current request */ |
170 | #define TAPE_IO_STOP 3 /* stop the running request */ |
171 | #define TAPE_IO_LONG_BUSY 4 /* delay the running request */ |
172 | |
173 | /* Char Frontend Data */ |
174 | struct tape_char_data { |
175 | struct idal_buffer *idal_buf; /* idal buffer for user char data */ |
176 | int block_size; /* of size block_size. */ |
177 | }; |
178 | |
179 | /* Tape Info */ |
180 | struct tape_device { |
181 | /* entry in tape_device_list */ |
182 | struct list_head node; |
183 | |
184 | int cdev_id; |
185 | struct ccw_device * cdev; |
186 | struct tape_class_device * nt; |
187 | struct tape_class_device * rt; |
188 | |
189 | /* Device mutex to serialize tape commands. */ |
190 | struct mutex mutex; |
191 | |
192 | /* Device discipline information. */ |
193 | struct tape_discipline * discipline; |
194 | void * discdata; |
195 | |
196 | /* Generic status flags */ |
197 | long tape_generic_status; |
198 | |
199 | /* Device state information. */ |
200 | wait_queue_head_t state_change_wq; |
201 | enum tape_state tape_state; |
202 | enum tape_medium_state medium_state; |
203 | unsigned char * modeset_byte; |
204 | |
205 | /* Reference count. */ |
206 | atomic_t ref_count; |
207 | |
208 | /* Request queue. */ |
209 | struct list_head req_queue; |
210 | |
211 | /* Request wait queue. */ |
212 | wait_queue_head_t wait_queue; |
213 | |
214 | /* Each tape device has (currently) two minor numbers. */ |
215 | int first_minor; |
216 | |
217 | /* Number of tapemarks required for correct termination. */ |
218 | int required_tapemarks; |
219 | |
220 | /* Block ID of the BOF */ |
221 | unsigned int bof; |
222 | |
223 | /* Character device frontend data */ |
224 | struct tape_char_data char_data; |
225 | |
226 | /* Function to start or stop the next request later. */ |
227 | struct delayed_work tape_dnr; |
228 | |
229 | /* Timer for long busy */ |
230 | struct timer_list lb_timeout; |
231 | |
232 | }; |
233 | |
234 | /* Externals from tape_core.c */ |
235 | extern struct tape_request *tape_alloc_request(int cplength, int datasize); |
236 | extern void tape_free_request(struct tape_request *); |
237 | extern int tape_do_io(struct tape_device *, struct tape_request *); |
238 | extern int tape_do_io_async(struct tape_device *, struct tape_request *); |
239 | extern int tape_do_io_interruptible(struct tape_device *, struct tape_request *); |
240 | extern int tape_cancel_io(struct tape_device *, struct tape_request *); |
241 | |
242 | static inline int |
243 | tape_do_io_free(struct tape_device *device, struct tape_request *request) |
244 | { |
245 | int rc; |
246 | |
247 | rc = tape_do_io(device, request); |
248 | tape_free_request(request); |
249 | return rc; |
250 | } |
251 | |
252 | static inline void |
253 | tape_do_io_async_free(struct tape_device *device, struct tape_request *request) |
254 | { |
255 | request->callback = (void *) tape_free_request; |
256 | request->callback_data = NULL; |
257 | tape_do_io_async(device, request); |
258 | } |
259 | |
260 | extern int tape_open(struct tape_device *); |
261 | extern int tape_release(struct tape_device *); |
262 | extern int tape_mtop(struct tape_device *, int, int); |
263 | extern void tape_state_set(struct tape_device *, enum tape_state); |
264 | |
265 | extern int tape_generic_online(struct tape_device *, struct tape_discipline *); |
266 | extern int tape_generic_offline(struct ccw_device *); |
267 | |
268 | /* Externals from tape_devmap.c */ |
269 | extern int tape_generic_probe(struct ccw_device *); |
270 | extern void tape_generic_remove(struct ccw_device *); |
271 | |
272 | extern struct tape_device *tape_find_device(int devindex); |
273 | extern struct tape_device *tape_get_device(struct tape_device *); |
274 | extern void tape_put_device(struct tape_device *); |
275 | |
276 | /* Externals from tape_char.c */ |
277 | extern int tapechar_init(void); |
278 | extern void tapechar_exit(void); |
279 | extern int tapechar_setup_device(struct tape_device *); |
280 | extern void tapechar_cleanup_device(struct tape_device *); |
281 | |
282 | /* tape initialisation functions */ |
283 | #ifdef CONFIG_PROC_FS |
284 | extern void tape_proc_init (void); |
285 | extern void tape_proc_cleanup (void); |
286 | #else |
287 | static inline void tape_proc_init (void) {;} |
288 | static inline void tape_proc_cleanup (void) {;} |
289 | #endif |
290 | |
291 | /* a function for dumping device sense info */ |
292 | extern void tape_dump_sense_dbf(struct tape_device *, struct tape_request *, |
293 | struct irb *); |
294 | |
295 | /* functions for handling the status of a device */ |
296 | extern void tape_med_state_set(struct tape_device *, enum tape_medium_state); |
297 | |
298 | /* The debug area */ |
299 | extern debug_info_t *TAPE_DBF_AREA; |
300 | |
301 | /* functions for building ccws */ |
302 | static inline struct ccw1 * |
303 | tape_ccw_cc(struct ccw1 *ccw, __u8 cmd_code, __u16 memsize, void *cda) |
304 | { |
305 | ccw->cmd_code = cmd_code; |
306 | ccw->flags = CCW_FLAG_CC; |
307 | ccw->count = memsize; |
308 | ccw->cda = (__u32)(addr_t) cda; |
309 | return ccw + 1; |
310 | } |
311 | |
312 | static inline struct ccw1 * |
313 | tape_ccw_end(struct ccw1 *ccw, __u8 cmd_code, __u16 memsize, void *cda) |
314 | { |
315 | ccw->cmd_code = cmd_code; |
316 | ccw->flags = 0; |
317 | ccw->count = memsize; |
318 | ccw->cda = (__u32)(addr_t) cda; |
319 | return ccw + 1; |
320 | } |
321 | |
322 | static inline struct ccw1 * |
323 | tape_ccw_cmd(struct ccw1 *ccw, __u8 cmd_code) |
324 | { |
325 | ccw->cmd_code = cmd_code; |
326 | ccw->flags = 0; |
327 | ccw->count = 0; |
328 | ccw->cda = (__u32)(addr_t) &ccw->cmd_code; |
329 | return ccw + 1; |
330 | } |
331 | |
332 | static inline struct ccw1 * |
333 | tape_ccw_repeat(struct ccw1 *ccw, __u8 cmd_code, int count) |
334 | { |
335 | while (count-- > 0) { |
336 | ccw->cmd_code = cmd_code; |
337 | ccw->flags = CCW_FLAG_CC; |
338 | ccw->count = 0; |
339 | ccw->cda = (__u32)(addr_t) &ccw->cmd_code; |
340 | ccw++; |
341 | } |
342 | return ccw; |
343 | } |
344 | |
345 | static inline struct ccw1 * |
346 | tape_ccw_cc_idal(struct ccw1 *ccw, __u8 cmd_code, struct idal_buffer *idal) |
347 | { |
348 | ccw->cmd_code = cmd_code; |
349 | ccw->flags = CCW_FLAG_CC; |
350 | idal_buffer_set_cda(idal, ccw); |
351 | return ccw++; |
352 | } |
353 | |
354 | static inline struct ccw1 * |
355 | tape_ccw_end_idal(struct ccw1 *ccw, __u8 cmd_code, struct idal_buffer *idal) |
356 | { |
357 | ccw->cmd_code = cmd_code; |
358 | ccw->flags = 0; |
359 | idal_buffer_set_cda(idal, ccw); |
360 | return ccw++; |
361 | } |
362 | |
363 | /* Global vars */ |
364 | extern const char *tape_state_verbose[]; |
365 | extern const char *tape_op_verbose[]; |
366 | |
367 | #endif /* for ifdef tape.h */ |
368 | |