FreeBSD/Linux Kernel Cross Reference
sys/scsi/scsi_tape.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: scsi_tape.c,v $
29 * Revision 2.15 93/05/10 21:23:17 rvb
30 * Always pass density code down. Fixed log.
31 * [93/04/09 af]
32 *
33 * Revision 2.14 92/08/03 17:55:37 jfriedl
34 * removed silly prototypes
35 * [92/08/02 jfriedl]
36 *
37 * Revision 2.13 92/05/21 17:24:52 jfriedl
38 * Cleanup to quiet gcc warnings.
39 * [92/05/16 jfriedl]
40 *
41 * Revision 2.12 92/02/23 22:45:07 elf
42 * Changed the interface of a number of functions not to
43 * require the scsi_softc pointer any longer. It was
44 * mostly unused, now it can be found via tgt->masterno.
45 * [92/02/22 19:29:10 af]
46 *
47 * Revision 2.11 91/11/12 11:17:27 rvb
48 * Deal with fixed-size tapes more gracefully: fixed a bug in
49 * read (incorrectly called the go routine with the number of
50 * blocks rather than the number of bytes), in mode select
51 * set the block size too.
52 * We seem to be happy with DEC TZK10s now.
53 * [91/10/30 13:39:34 af]
54 *
55 * Revision 2.10 91/08/24 12:29:16 af
56 * Support for fixed-size-tapes: careful about speed selections,
57 * round sizes properly, use fixed bit.
58 * [91/08/02 03:58:18 af]
59 *
60 * Revision 2.9 91/06/19 11:58:13 rvb
61 * File moved here from mips/PMAX since it is now "MI" code, also
62 * used by Vax3100 and soon -- the omron luna88k.
63 * [91/06/04 rvb]
64 *
65 * Revision 2.8 91/05/14 17:31:26 mrt
66 * Correcting copyright
67 *
68 * Revision 2.7 91/05/13 06:35:55 af
69 * Cleaned up mode_select, vendor unique data can be passed
70 * in if necessary. Density and speed are taken from target
71 * structure. Added rewind command and all th eothers that
72 * were missing (but what we do not use is disabled).
73 *
74 * Revision 2.6 91/02/05 17:46:24 mrt
75 * Added author notices
76 * [91/02/04 11:20:18 mrt]
77 *
78 * Changed to use new Mach copyright
79 * [91/02/02 12:19:07 mrt]
80 *
81 * Revision 2.5 90/12/05 23:35:49 af
82 * Mild attempt to get it working. Actually wrote and read
83 * back a tape.
84 * [90/12/03 23:49:49 af]
85 *
86 * Revision 2.3.1.1 90/11/01 03:40:30 af
87 * Created, from the SCSI specs:
88 * "Small Computer Systems Interface (SCSI)", ANSI Draft
89 * X3T9.2/82-2 - Rev 17B December 1985
90 * "Small Computer System Interface - 2 (SCSI-II)", ANSI Draft
91 * X3T9.2/86-109 - Rev 10C March 1990
92 * [90/10/11 af]
93 */
94 /*
95 * File: scsi_tape.c
96 * Author: Alessandro Forin, Carnegie Mellon University
97 * Date: 10/90
98 *
99 * Middle layer of the SCSI driver: SCSI protocol implementation
100 *
101 * This file contains code for SCSI commands for SEQUENTIAL ACCESS devices.
102 */
103
104 #include <mach/std_types.h>
105 #include <scsi/compat_30.h>
106
107 #include <scsi/scsi.h>
108 #include <scsi/scsi_defs.h>
109
110
111
112
113
114 char *sctape_name(internal)
115 boolean_t internal;
116 {
117 return internal ? "tz" : "tape";
118 }
119
120 void sctape_optimize(tgt)
121 target_info_t *tgt;
122 {
123 register int i;
124 char result[6];
125
126 /* Some (DEC) tapes want to send you the self-test results */
127 for (i = 0; i < 10; i++) {
128 if (scsi_receive_diag( tgt, result, sizeof(result), 0)
129 == SCSI_RET_SUCCESS)
130 break;
131 }
132 if (scsi_debug)
133 printf("[tape_rcvdiag: after %d, x%x x%x x%x x%x x%x x%x]\n", i+1,
134 result[0], result[1], result[2], result[3], result[4], result[5]);
135 }
136
137 /*
138 * SCSI commands specific to sequential access devices
139 */
140 int sctape_mode_select( tgt, vuque_data, vuque_data_len, newspeed, ior)
141 register target_info_t *tgt;
142 unsigned char *vuque_data;
143 int vuque_data_len;
144 int newspeed;
145 io_req_t ior;
146 {
147 scsi_cmd_mode_select_t *cmd;
148 scsi_mode_select_param_t *parm;
149
150 bzero(tgt->cmd_ptr, sizeof(*cmd) + 2 * sizeof(*parm));
151 cmd = (scsi_cmd_mode_select_t*) (tgt->cmd_ptr);
152 cmd->scsi_cmd_code = SCSI_CMD_MODE_SELECT;
153 cmd->scsi_cmd_lun_and_lba1 = 0;
154 cmd->scsi_cmd_xfer_len = sizeof(scsi_mode_select_param_t) + vuque_data_len;
155
156 parm = (scsi_mode_select_param_t*) (cmd + 1);
157 if (newspeed) {
158 parm->speed = tgt->dev_info.tape.speed;
159 } else {
160 /* Standard sez 0 -> no change */
161 parm->speed = 0;
162 }
163 /* parm->medium_type = 0; reserved */
164 parm->descs[0].density_code = tgt->dev_info.tape.density;
165 parm->buffer_mode = 1;
166 parm->desc_len = 8;
167 if (tgt->dev_info.tape.fixed_size) {
168 register int reclen = tgt->block_size;
169 parm->descs[0].reclen1 = reclen >> 16;
170 parm->descs[0].reclen2 = reclen >> 8;
171 parm->descs[0].reclen3 = reclen;
172 }
173
174 if (vuque_data_len)
175 bcopy(vuque_data, (char*)(parm+1), vuque_data_len);
176
177 tgt->cur_cmd = SCSI_CMD_MODE_SELECT;
178
179 scsi_go_and_wait(tgt, sizeof(*cmd) + sizeof(*parm) + vuque_data_len, 0, ior);
180
181 return tgt->done;
182 }
183
184 void sctape_read( tgt, ior)
185 register target_info_t *tgt;
186 io_req_t ior;
187 {
188 scsi_cmd_read_t *cmd;
189 register unsigned len, max;
190 # define nbytes max
191 boolean_t fixed = FALSE;
192
193 max = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data;
194
195 len = ior->io_count;
196 if (tgt->dev_info.tape.fixed_size) {
197 unsigned int bs = tgt->block_size;
198 fixed = TRUE;
199 nbytes = len;
200 ior->io_residual += len % bs;
201 len = len / bs;
202 } else {
203 if (max > tgt->dev_info.tape.maxreclen)
204 max = tgt->dev_info.tape.maxreclen;
205 if (len > max) {
206 ior->io_residual = len - max;
207 len = max;
208 }
209 if (len < tgt->block_size)
210 len = tgt->block_size;
211 nbytes = len;
212 }
213
214 cmd = (scsi_cmd_read_t*) (tgt->cmd_ptr);
215 cmd->scsi_cmd_code = SCSI_CMD_READ;
216 cmd->scsi_cmd_lun_and_lba1 = fixed ? SCSI_CMD_TP_FIXED : 0;
217 cmd->scsi_cmd_lba2 = len >> 16;
218 cmd->scsi_cmd_lba3 = len >> 8;
219 cmd->scsi_cmd_xfer_len = len;
220 cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
221
222 tgt->cur_cmd = SCSI_CMD_READ;
223
224 scsi_go(tgt, sizeof(*cmd), nbytes, FALSE);
225 #undef nbytes
226 }
227
228 void sctape_write( tgt, ior)
229 register target_info_t *tgt;
230 io_req_t ior;
231 {
232 scsi_cmd_write_t *cmd;
233 register unsigned len, max;
234 boolean_t fixed = FALSE;
235
236 len = ior->io_count;
237 max = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data;
238
239 if (tgt->dev_info.tape.fixed_size) {
240 unsigned int bs = tgt->block_size;
241 fixed = TRUE;
242 ior->io_residual += len % bs;
243 len = len / bs;
244 } else {
245 if (max > tgt->dev_info.tape.maxreclen)
246 max = tgt->dev_info.tape.maxreclen;
247 if (len > max) {
248 ior->io_residual = len - max;
249 len = max;
250 }
251 if (len < tgt->block_size)
252 len = tgt->block_size;
253 }
254
255 cmd = (scsi_cmd_write_t*) (tgt->cmd_ptr);
256 cmd->scsi_cmd_code = SCSI_CMD_WRITE;
257 cmd->scsi_cmd_lun_and_lba1 = fixed ? SCSI_CMD_TP_FIXED : 0;
258 cmd->scsi_cmd_lba2 = len >> 16;
259 cmd->scsi_cmd_lba3 = len >> 8;
260 cmd->scsi_cmd_xfer_len = len;
261 cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
262
263 tgt->cur_cmd = SCSI_CMD_WRITE;
264
265 scsi_go(tgt, sizeof(*cmd), 0, FALSE);
266 }
267
268 int scsi_rewind( tgt, ior, wait)
269 register target_info_t *tgt;
270 io_req_t ior;
271 boolean_t wait;
272 {
273 scsi_cmd_rewind_t *cmd;
274
275
276 cmd = (scsi_cmd_rewind_t*) (tgt->cmd_ptr);
277 cmd->scsi_cmd_code = SCSI_CMD_REWIND;
278 cmd->scsi_cmd_lun_and_lba1 = wait ? 0 : SCSI_CMD_REW_IMMED;
279 cmd->scsi_cmd_lba2 = 0;
280 cmd->scsi_cmd_lba3 = 0;
281 cmd->scsi_cmd_xfer_len = 0;
282 cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
283
284 tgt->cur_cmd = SCSI_CMD_REWIND;
285
286 scsi_go( tgt, sizeof(*cmd), 0, FALSE);
287 return SCSI_RET_SUCCESS;
288 }
289
290 int scsi_write_filemarks( tgt, count, ior)
291 register target_info_t *tgt;
292 register unsigned int count;
293 io_req_t ior;
294 {
295 scsi_cmd_write_fil_t *cmd;
296
297 cmd = (scsi_cmd_write_fil_t*) (tgt->cmd_ptr);
298 cmd->scsi_cmd_code = SCSI_CMD_WRITE_FILEMARKS;
299 cmd->scsi_cmd_lun_and_lba1 = 0;
300 cmd->scsi_cmd_lba2 = count >> 16;
301 cmd->scsi_cmd_lba3 = count >> 8;
302 cmd->scsi_cmd_xfer_len = count;
303 cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
304
305
306 tgt->cur_cmd = SCSI_CMD_WRITE_FILEMARKS;
307
308 scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior);
309
310 return tgt->done;
311 }
312
313 int scsi_space( tgt, mode, count, ior)
314 register target_info_t *tgt;
315 int mode;
316 register int count;
317 io_req_t ior;
318 {
319 scsi_cmd_space_t *cmd;
320
321 cmd = (scsi_cmd_space_t*) (tgt->cmd_ptr);
322 cmd->scsi_cmd_code = SCSI_CMD_SPACE;
323 cmd->scsi_cmd_lun_and_lba1 = mode & 0x3;
324 cmd->scsi_cmd_lba2 = count >> 16;
325 cmd->scsi_cmd_lba3 = count >> 8;
326 cmd->scsi_cmd_xfer_len = count;
327 cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
328
329
330 tgt->cur_cmd = SCSI_CMD_SPACE;
331
332 scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior);
333
334 return tgt->done;
335 }
336
337
338 int scsi_read_block_limits( tgt, ior)
339 register target_info_t *tgt;
340 io_req_t ior;
341 {
342 scsi_cmd_block_limits_t *cmd;
343
344 cmd = (scsi_cmd_block_limits_t*) (tgt->cmd_ptr);
345 cmd->scsi_cmd_code = SCSI_CMD_READ_BLOCK_LIMITS;
346 cmd->scsi_cmd_lun_and_lba1 = 0;
347 cmd->scsi_cmd_lba2 = 0;
348 cmd->scsi_cmd_lba3 = 0;
349 cmd->scsi_cmd_xfer_len = 0;
350 cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
351
352
353 tgt->cur_cmd = SCSI_CMD_READ_BLOCK_LIMITS;
354
355 scsi_go_and_wait(tgt, sizeof(*cmd), sizeof(scsi_blimits_data_t), ior);
356 return tgt->done;
357 }
358
359 #if 0 /* unused */
360
361 void scsi_track_select( tgt, trackno, ior)
362 register target_info_t *tgt;
363 register unsigned char trackno;
364 io_req_t ior;
365 {
366 scsi_cmd_seek_t *cmd;
367
368 cmd = (scsi_cmd_seek_t*) (tgt->cmd_ptr);
369 cmd->scsi_cmd_code = SCSI_CMD_TRACK_SELECT;
370 cmd->scsi_cmd_lun_and_lba1 = 0;
371 cmd->scsi_cmd_lba2 = 0;
372 cmd->scsi_cmd_lba3 = 0;
373 cmd->scsi_cmd_tp_trackno = trackno;
374 cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
375
376
377 tgt->cur_cmd = SCSI_CMD_TRACK_SELECT;
378
379 scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior);
380 }
381
382 void scsi_read_reverse( tgt, ior)
383 register target_info_t *tgt;
384 io_req_t ior;
385 {
386 scsi_cmd_rev_read_t *cmd;
387 register unsigned len;
388 unsigned int max_dma_data;
389
390 max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data;
391
392 len = ior->io_count;
393 if (len > max_dma_data)
394 len = max_dma_data;
395
396 cmd = (scsi_cmd_rev_read_t*) (tgt->cmd_ptr);
397 cmd->scsi_cmd_code = SCSI_CMD_READ_REVERSE;
398 cmd->scsi_cmd_lun_and_lba1 = 0;
399 cmd->scsi_cmd_lba2 = len >> 16;
400 cmd->scsi_cmd_lba3 = len >> 8;
401 cmd->scsi_cmd_xfer_len = len;
402 cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
403
404 tgt->cur_cmd = SCSI_CMD_READ_REVERSE;
405
406 scsi_go(tgt, sizeof(*cmd), len, FALSE);
407 }
408
409 void sctape_verify( tgt, len, ior)
410 register target_info_t *tgt;
411 register unsigned int len;
412 io_req_t ior;
413 {
414 scsi_cmd_verify_t *cmd;
415
416 cmd = (scsi_cmd_verify_t*) (tgt->cmd_ptr);
417 cmd->scsi_cmd_code = SCSI_CMD_VERIFY_0;
418 cmd->scsi_cmd_lun_and_lba1 = 0;/* XXX */
419 cmd->scsi_cmd_lba2 = len >> 16;
420 cmd->scsi_cmd_lba3 = len >> 8;
421 cmd->scsi_cmd_xfer_len = len;
422 cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
423
424
425 tgt->cur_cmd = SCSI_CMD_VERIFY_0;
426
427 scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior);
428 }
429
430
431 void scsi_recover_buffered_data( tgt, ior)
432 register target_info_t *tgt;
433 io_req_t ior;
434 {
435 scsi_cmd_recover_buffer_t *cmd;
436 register unsigned len;
437 unsigned int max_dma_data;
438
439 max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data;
440
441 len = ior->io_count;
442 if (len > max_dma_data)
443 len = max_dma_data;
444
445 cmd = (scsi_cmd_recover_buffer_t*) (tgt->cmd_ptr);
446 cmd->scsi_cmd_code = SCSI_CMD_RECOVER_BUFFERED_DATA;
447 cmd->scsi_cmd_lun_and_lba1 = 0;
448 cmd->scsi_cmd_lba2 = len >> 16;
449 cmd->scsi_cmd_lba3 = len >> 8;
450 cmd->scsi_cmd_xfer_len = len;
451 cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
452
453 tgt->cur_cmd = SCSI_CMD_RECOVER_BUFFERED_DATA;
454
455 scsi_go(tgt, sizeof(*cmd), len, FALSE);
456 }
457
458 void scsi_erase( tgt, mode, ior)
459 register target_info_t *tgt;
460 io_req_t ior;
461 {
462 scsi_cmd_erase_t *cmd;
463
464 cmd = (scsi_cmd_erase_t*) (tgt->cmd_ptr);
465 cmd->scsi_cmd_code = SCSI_CMD_ERASE;
466 cmd->scsi_cmd_lun_and_lba1 = mode & SCSI_CMD_ER_LONG;
467 cmd->scsi_cmd_lba2 = 0;
468 cmd->scsi_cmd_lba3 = 0;
469 cmd->scsi_cmd_xfer_len = 0;
470 cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
471
472
473 tgt->cur_cmd = SCSI_CMD_ERASE;
474
475 scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior);
476 }
477
478 #endif
479
480 #ifdef SCSI2
481 scsi_locate
482 scsi_read_position
483 #endif SCSI2
Cache object: 3c102f9c6bdc788a323c625ea83245bb
|