|
|
1.1 root 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 [email protected]
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: * File: scsi_tape.c
28: * Author: Alessandro Forin, Carnegie Mellon University
29: * Date: 10/90
30: *
31: * Middle layer of the SCSI driver: SCSI protocol implementation
32: *
33: * This file contains code for SCSI commands for SEQUENTIAL ACCESS devices.
34: */
35:
36: #include <mach/std_types.h>
37: #include <scsi/compat_30.h>
38:
39: #include <scsi/scsi.h>
40: #include <scsi/scsi_defs.h>
41:
42: #if (NSCSI > 0)
43:
44:
45: char *sctape_name(internal)
46: boolean_t internal;
47: {
48: return internal ? "tz" : "tape";
49: }
50:
51: void sctape_optimize(tgt)
52: target_info_t *tgt;
53: {
54: register int i;
55: char result[6];
56:
57: /* Some (DEC) tapes want to send you the self-test results */
58: for (i = 0; i < 10; i++) {
59: if (scsi_receive_diag( tgt, result, sizeof(result), 0)
60: == SCSI_RET_SUCCESS)
61: break;
62: }
63: if (scsi_debug)
64: printf("[tape_rcvdiag: after %d, x%x x%x x%x x%x x%x x%x]\n", i+1,
65: result[0], result[1], result[2], result[3], result[4], result[5]);
66: }
67:
68: /*
69: * SCSI commands specific to sequential access devices
70: */
71: int sctape_mode_select( tgt, vuque_data, vuque_data_len, newspeed, ior)
72: register target_info_t *tgt;
73: unsigned char *vuque_data;
74: int vuque_data_len;
75: int newspeed;
76: io_req_t ior;
77: {
78: scsi_cmd_mode_select_t *cmd;
79: scsi_mode_select_param_t *parm;
80:
81: bzero(tgt->cmd_ptr, sizeof(*cmd) + 2 * sizeof(*parm));
82: cmd = (scsi_cmd_mode_select_t*) (tgt->cmd_ptr);
83: cmd->scsi_cmd_code = SCSI_CMD_MODE_SELECT;
84: cmd->scsi_cmd_lun_and_lba1 = 0;
85: cmd->scsi_cmd_xfer_len = sizeof(scsi_mode_select_param_t) + vuque_data_len;
86:
87: parm = (scsi_mode_select_param_t*) (cmd + 1);
88: if (newspeed) {
89: parm->speed = tgt->dev_info.tape.speed;
90: } else {
91: /* Standard sez 0 -> no change */
92: parm->speed = 0;
93: }
94: /* parm->medium_type = 0; reserved */
95: parm->descs[0].density_code = tgt->dev_info.tape.density;
96: parm->buffer_mode = 1;
97: parm->desc_len = 8;
98: if (tgt->dev_info.tape.fixed_size) {
99: register int reclen = tgt->block_size;
100: parm->descs[0].reclen1 = reclen >> 16;
101: parm->descs[0].reclen2 = reclen >> 8;
102: parm->descs[0].reclen3 = reclen;
103: }
104:
105: if (vuque_data_len)
106: bcopy(vuque_data, (char*)(parm+1), vuque_data_len);
107:
108: tgt->cur_cmd = SCSI_CMD_MODE_SELECT;
109:
110: scsi_go_and_wait(tgt, sizeof(*cmd) + sizeof(*parm) + vuque_data_len, 0, ior);
111:
112: return tgt->done;
113: }
114:
115: void sctape_read( tgt, ior)
116: register target_info_t *tgt;
117: io_req_t ior;
118: {
119: scsi_cmd_read_t *cmd;
120: register unsigned len, max;
121: # define nbytes max
122: boolean_t fixed = FALSE;
123:
124: max = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data;
125:
126: len = ior->io_count;
127: if (tgt->dev_info.tape.fixed_size) {
128: unsigned int bs = tgt->block_size;
129: fixed = TRUE;
130: nbytes = len;
131: ior->io_residual += len % bs;
132: len = len / bs;
133: } else {
134: if (max > tgt->dev_info.tape.maxreclen)
135: max = tgt->dev_info.tape.maxreclen;
136: if (len > max) {
137: ior->io_residual = len - max;
138: len = max;
139: }
140: if (len < tgt->block_size)
141: len = tgt->block_size;
142: nbytes = len;
143: }
144:
145: cmd = (scsi_cmd_read_t*) (tgt->cmd_ptr);
146: cmd->scsi_cmd_code = SCSI_CMD_READ;
147: cmd->scsi_cmd_lun_and_lba1 = fixed ? SCSI_CMD_TP_FIXED : 0;
148: cmd->scsi_cmd_lba2 = len >> 16;
149: cmd->scsi_cmd_lba3 = len >> 8;
150: cmd->scsi_cmd_xfer_len = len;
151: cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
152:
153: tgt->cur_cmd = SCSI_CMD_READ;
154:
155: scsi_go(tgt, sizeof(*cmd), nbytes, FALSE);
156: #undef nbytes
157: }
158:
159: void sctape_write( tgt, ior)
160: register target_info_t *tgt;
161: io_req_t ior;
162: {
163: scsi_cmd_write_t *cmd;
164: register unsigned len, max;
165: boolean_t fixed = FALSE;
166:
167: len = ior->io_count;
168: max = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data;
169:
170: if (tgt->dev_info.tape.fixed_size) {
171: unsigned int bs = tgt->block_size;
172: fixed = TRUE;
173: ior->io_residual += len % bs;
174: len = len / bs;
175: } else {
176: if (max > tgt->dev_info.tape.maxreclen)
177: max = tgt->dev_info.tape.maxreclen;
178: if (len > max) {
179: ior->io_residual = len - max;
180: len = max;
181: }
182: if (len < tgt->block_size)
183: len = tgt->block_size;
184: }
185:
186: cmd = (scsi_cmd_write_t*) (tgt->cmd_ptr);
187: cmd->scsi_cmd_code = SCSI_CMD_WRITE;
188: cmd->scsi_cmd_lun_and_lba1 = fixed ? SCSI_CMD_TP_FIXED : 0;
189: cmd->scsi_cmd_lba2 = len >> 16;
190: cmd->scsi_cmd_lba3 = len >> 8;
191: cmd->scsi_cmd_xfer_len = len;
192: cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
193:
194: tgt->cur_cmd = SCSI_CMD_WRITE;
195:
196: scsi_go(tgt, sizeof(*cmd), 0, FALSE);
197: }
198:
199: int scsi_rewind( tgt, ior, wait)
200: register target_info_t *tgt;
201: io_req_t ior;
202: boolean_t wait;
203: {
204: scsi_cmd_rewind_t *cmd;
205:
206:
207: cmd = (scsi_cmd_rewind_t*) (tgt->cmd_ptr);
208: cmd->scsi_cmd_code = SCSI_CMD_REWIND;
209: cmd->scsi_cmd_lun_and_lba1 = wait ? 0 : SCSI_CMD_REW_IMMED;
210: cmd->scsi_cmd_lba2 = 0;
211: cmd->scsi_cmd_lba3 = 0;
212: cmd->scsi_cmd_xfer_len = 0;
213: cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
214:
215: tgt->cur_cmd = SCSI_CMD_REWIND;
216:
217: scsi_go( tgt, sizeof(*cmd), 0, FALSE);
218: return SCSI_RET_SUCCESS;
219: }
220:
221: int scsi_write_filemarks( tgt, count, ior)
222: register target_info_t *tgt;
223: register unsigned int count;
224: io_req_t ior;
225: {
226: scsi_cmd_write_fil_t *cmd;
227:
228: cmd = (scsi_cmd_write_fil_t*) (tgt->cmd_ptr);
229: cmd->scsi_cmd_code = SCSI_CMD_WRITE_FILEMARKS;
230: cmd->scsi_cmd_lun_and_lba1 = 0;
231: cmd->scsi_cmd_lba2 = count >> 16;
232: cmd->scsi_cmd_lba3 = count >> 8;
233: cmd->scsi_cmd_xfer_len = count;
234: cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
235:
236:
237: tgt->cur_cmd = SCSI_CMD_WRITE_FILEMARKS;
238:
239: scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior);
240:
241: return tgt->done;
242: }
243:
244: int scsi_space( tgt, mode, count, ior)
245: register target_info_t *tgt;
246: int mode;
247: register int count;
248: io_req_t ior;
249: {
250: scsi_cmd_space_t *cmd;
251:
252: cmd = (scsi_cmd_space_t*) (tgt->cmd_ptr);
253: cmd->scsi_cmd_code = SCSI_CMD_SPACE;
254: cmd->scsi_cmd_lun_and_lba1 = mode & 0x3;
255: cmd->scsi_cmd_lba2 = count >> 16;
256: cmd->scsi_cmd_lba3 = count >> 8;
257: cmd->scsi_cmd_xfer_len = count;
258: cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
259:
260:
261: tgt->cur_cmd = SCSI_CMD_SPACE;
262:
263: scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior);
264:
265: return tgt->done;
266: }
267:
268:
269: int scsi_read_block_limits( tgt, ior)
270: register target_info_t *tgt;
271: io_req_t ior;
272: {
273: scsi_cmd_block_limits_t *cmd;
274:
275: cmd = (scsi_cmd_block_limits_t*) (tgt->cmd_ptr);
276: cmd->scsi_cmd_code = SCSI_CMD_READ_BLOCK_LIMITS;
277: cmd->scsi_cmd_lun_and_lba1 = 0;
278: cmd->scsi_cmd_lba2 = 0;
279: cmd->scsi_cmd_lba3 = 0;
280: cmd->scsi_cmd_xfer_len = 0;
281: cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
282:
283:
284: tgt->cur_cmd = SCSI_CMD_READ_BLOCK_LIMITS;
285:
286: scsi_go_and_wait(tgt, sizeof(*cmd), sizeof(scsi_blimits_data_t), ior);
287: return tgt->done;
288: }
289:
290: #if 0 /* unused */
291:
292: void scsi_track_select( tgt, trackno, ior)
293: register target_info_t *tgt;
294: register unsigned char trackno;
295: io_req_t ior;
296: {
297: scsi_cmd_seek_t *cmd;
298:
299: cmd = (scsi_cmd_seek_t*) (tgt->cmd_ptr);
300: cmd->scsi_cmd_code = SCSI_CMD_TRACK_SELECT;
301: cmd->scsi_cmd_lun_and_lba1 = 0;
302: cmd->scsi_cmd_lba2 = 0;
303: cmd->scsi_cmd_lba3 = 0;
304: cmd->scsi_cmd_tp_trackno = trackno;
305: cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
306:
307:
308: tgt->cur_cmd = SCSI_CMD_TRACK_SELECT;
309:
310: scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior);
311: }
312:
313: void scsi_read_reverse( tgt, ior)
314: register target_info_t *tgt;
315: io_req_t ior;
316: {
317: scsi_cmd_rev_read_t *cmd;
318: register unsigned len;
319: unsigned int max_dma_data;
320:
321: max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data;
322:
323: len = ior->io_count;
324: if (len > max_dma_data)
325: len = max_dma_data;
326:
327: cmd = (scsi_cmd_rev_read_t*) (tgt->cmd_ptr);
328: cmd->scsi_cmd_code = SCSI_CMD_READ_REVERSE;
329: cmd->scsi_cmd_lun_and_lba1 = 0;
330: cmd->scsi_cmd_lba2 = len >> 16;
331: cmd->scsi_cmd_lba3 = len >> 8;
332: cmd->scsi_cmd_xfer_len = len;
333: cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
334:
335: tgt->cur_cmd = SCSI_CMD_READ_REVERSE;
336:
337: scsi_go(tgt, sizeof(*cmd), len, FALSE);
338: }
339:
340: void sctape_verify( tgt, len, ior)
341: register target_info_t *tgt;
342: register unsigned int len;
343: io_req_t ior;
344: {
345: scsi_cmd_verify_t *cmd;
346:
347: cmd = (scsi_cmd_verify_t*) (tgt->cmd_ptr);
348: cmd->scsi_cmd_code = SCSI_CMD_VERIFY_0;
349: cmd->scsi_cmd_lun_and_lba1 = 0;/* XXX */
350: cmd->scsi_cmd_lba2 = len >> 16;
351: cmd->scsi_cmd_lba3 = len >> 8;
352: cmd->scsi_cmd_xfer_len = len;
353: cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
354:
355:
356: tgt->cur_cmd = SCSI_CMD_VERIFY_0;
357:
358: scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior);
359: }
360:
361:
362: void scsi_recover_buffered_data( tgt, ior)
363: register target_info_t *tgt;
364: io_req_t ior;
365: {
366: scsi_cmd_recover_buffer_t *cmd;
367: register unsigned len;
368: unsigned int max_dma_data;
369:
370: max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data;
371:
372: len = ior->io_count;
373: if (len > max_dma_data)
374: len = max_dma_data;
375:
376: cmd = (scsi_cmd_recover_buffer_t*) (tgt->cmd_ptr);
377: cmd->scsi_cmd_code = SCSI_CMD_RECOVER_BUFFERED_DATA;
378: cmd->scsi_cmd_lun_and_lba1 = 0;
379: cmd->scsi_cmd_lba2 = len >> 16;
380: cmd->scsi_cmd_lba3 = len >> 8;
381: cmd->scsi_cmd_xfer_len = len;
382: cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
383:
384: tgt->cur_cmd = SCSI_CMD_RECOVER_BUFFERED_DATA;
385:
386: scsi_go(tgt, sizeof(*cmd), len, FALSE);
387: }
388:
389: void scsi_erase( tgt, mode, ior)
390: register target_info_t *tgt;
391: io_req_t ior;
392: {
393: scsi_cmd_erase_t *cmd;
394:
395: cmd = (scsi_cmd_erase_t*) (tgt->cmd_ptr);
396: cmd->scsi_cmd_code = SCSI_CMD_ERASE;
397: cmd->scsi_cmd_lun_and_lba1 = mode & SCSI_CMD_ER_LONG;
398: cmd->scsi_cmd_lba2 = 0;
399: cmd->scsi_cmd_lba3 = 0;
400: cmd->scsi_cmd_xfer_len = 0;
401: cmd->scsi_cmd_ctrl_byte = 0; /* not linked */
402:
403:
404: tgt->cur_cmd = SCSI_CMD_ERASE;
405:
406: scsi_go_and_wait(tgt, sizeof(*cmd), 0, ior);
407: }
408:
409: #endif
410:
411: #ifdef SCSI2
412: scsi_locate
413: scsi_read_position
414: #endif SCSI2
415: #endif /* NSCSI > 0 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.