This source file includes following definitions.
- st_sleep_done
- decode_sns
- st_chk_result
- write_behind_check
- flush_write_buffer
- flush_buffer
- scsi_tape_open
- scsi_tape_close
- st_write
- st_read
- st_int_ioctl
- st_ioctl
- st_attach
- st_init1
- st_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #include <linux/fs.h>
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/string.h>
40 #include <linux/errno.h>
41 #include <linux/mtio.h>
42 #include <linux/ioctl.h>
43 #include <linux/fcntl.h>
44 #include <asm/segment.h>
45 #include <asm/system.h>
46
47 #define MAJOR_NR 9
48 #include "../blk.h"
49 #include "scsi.h"
50 #include "st.h"
51
52 #define MAX_RETRIES 5
53 #define NO_TAPE NOT_READY
54
55
56
57
58
59
60
61
62
63
64
65
66 #define ST_TIMEOUT 6000
67 #define ST_LONG_TIMEOUT 200000
68
69
70 #define ST_BUFFER_BLOCKS 64
71
72
73 #define ST_WRITE_THRESHOLD_BLOCKS 60
74 #define ST_BLOCK_SIZE 512
75 #define ST_BUFFER_SIZE (ST_BUFFER_BLOCKS * ST_BLOCK_SIZE)
76 #define ST_WRITE_THRESHOLD (ST_WRITE_THRESHOLD_BLOCKS * ST_BLOCK_SIZE)
77
78 static int st_nbr_buffers;
79 static ST_buffer *st_buffers[2];
80
81 static Scsi_Tape * scsi_tapes;
82 int NR_ST=0;
83 int MAX_ST=0;
84
85 static int st_int_ioctl(struct inode * inode,struct file * file,
86 unsigned int cmd_in, unsigned long arg);
87
88
89
90
91
92 static void st_sleep_done (Scsi_Cmnd * SCpnt)
93 {
94 int st_nbr;
95
96 if ((st_nbr = SCpnt->request.dev) < NR_ST && st_nbr >= 0) {
97 if (scsi_tapes[st_nbr].buffer->writing &&
98 (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
99 (SCpnt->sense_buffer[2] & 0x40))
100 scsi_tapes[st_nbr].buffer->last_result = 0x7fffffff;
101 else
102 scsi_tapes[st_nbr].buffer->last_result = SCpnt->result;
103 if (scsi_tapes[st_nbr].buffer->writing)
104 SCpnt->request.dev = -1;
105 else
106 SCpnt->request.dev = 0xffff;
107 if (scsi_tapes[st_nbr].buffer->writing <= 0)
108 wake_up( &scsi_tapes[st_nbr].waiting );
109 }
110 #ifdef DEBUG
111 else
112 printk("st?: Illegal interrupt device %x\n", st_nbr);
113 #endif
114 }
115
116
117
118 #ifdef DEBUG
119
120 static void decode_sns(int dev, char *sense_buffer)
121 {
122 static char *snstext[] = {
123 "None","Recovered Error","Not Ready","Medium Error","Hardware Error",
124 "Illegal Request","Unit Attention","Data Protect","Blank Check",
125 "Key=E","Key=F","Filemark","End-Of-Medium","Incorrect Block Length",
126 "14","15"};
127
128 if (sense_buffer[0]!=0) {
129 if ((sense_buffer[0] & 0x70) == 0x70) {
130 if (sense_buffer[2] & 0x80) printk( "FMK ");
131 if (sense_buffer[2] & 0x40) printk( "EOM ");
132 if (sense_buffer[2] & 0x20) printk( "ILI ");
133 printk( "st%d: sense key %s\n", dev, snstext[sense_buffer[2] & 0x0f]);
134 } else {
135 if (sense_buffer[0] < 15)
136 printk("st%d: old sense key %s\n", dev, snstext[sense_buffer[0] & 0x0f]);
137 else
138 printk("st%d: sns = %2x %2x\n", dev, sense_buffer[0], sense_buffer[2]);
139 }
140 }
141 return;
142 }
143 #endif
144
145
146
147 static int st_chk_result(int dev, int result, char *sense)
148 {
149 if (!result)
150 return 0;
151 #ifdef DEBUG
152 printk("st%d: Error: %x\n", dev, result);
153 decode_sns(dev, sense);
154 #endif
155 if ((sense[0] & 0x70) == 0x70 &&
156 ((sense[2] & 0x80) ))
157 return 0;
158 return (-EIO);
159 }
160
161
162 #if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
163
164 static void write_behind_check(int dev)
165 {
166 cli();
167 if (scsi_tapes[dev].buffer->last_result < 0) {
168 scsi_tapes[dev].buffer->writing = (- scsi_tapes[dev].buffer->writing);
169 sleep_on( &scsi_tapes[dev].waiting );
170 scsi_tapes[dev].buffer->writing = (- scsi_tapes[dev].buffer->writing);
171 }
172 sti();
173
174 if (scsi_tapes[dev].buffer->writing < scsi_tapes[dev].buffer->buffer_bytes)
175 memcpy(scsi_tapes[dev].buffer->b_data,
176 scsi_tapes[dev].buffer->b_data + scsi_tapes[dev].buffer->writing,
177 scsi_tapes[dev].buffer->buffer_bytes -
178 scsi_tapes[dev].buffer->writing);
179 scsi_tapes[dev].buffer->buffer_bytes -= scsi_tapes[dev].buffer->writing;
180 scsi_tapes[dev].buffer->writing = 0;
181
182 return;
183 }
184 #endif
185
186
187
188 static int flush_write_buffer(int dev)
189 {
190 int offset, transfer, blks;
191 int result;
192 unsigned char cmd[10];
193 Scsi_Cmnd *SCpnt;
194
195 #if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
196 if (scsi_tapes[dev].buffer->writing) {
197 write_behind_check(dev);
198 if (scsi_tapes[dev].buffer->last_result) {
199 #ifdef DEBUG
200 printk("st%d: Async write error %x.\n", dev,
201 scsi_tapes[dev].buffer->last_result);
202 #endif
203 return (-EIO);
204 }
205 }
206 #endif
207
208 result = 0;
209 if (scsi_tapes[dev].dirty==1) {
210 SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
211
212 offset = scsi_tapes[dev].buffer->buffer_bytes;
213 transfer = ((offset + scsi_tapes[dev].block_size - 1) /
214 scsi_tapes[dev].block_size) * scsi_tapes[dev].block_size;
215 #ifdef DEBUG
216 printk("st%d: Flushing %d bytes.\n", dev, transfer);
217 #endif
218 memset(scsi_tapes[dev].buffer->b_data + offset, 0, transfer - offset);
219
220 SCpnt->sense_buffer[0] = 0;
221 memset(cmd, 0, 10);
222 cmd[0] = WRITE_6;
223 cmd[1] = 1;
224 blks = transfer / scsi_tapes[dev].block_size;
225 cmd[2] = blks >> 16;
226 cmd[3] = blks >> 8;
227 cmd[4] = blks;
228 SCpnt->request.dev = dev;
229 scsi_do_cmd (SCpnt,
230 (void *) cmd, scsi_tapes[dev].buffer->b_data, transfer,
231 st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
232
233 if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
234
235 if (SCpnt->result != 0) {
236 printk("st%d: Error on flush:\n", dev);
237 #ifdef DEBUG
238 st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
239 #endif
240 result = (-EIO);
241 }
242 else {
243 scsi_tapes[dev].dirty = 0;
244 scsi_tapes[dev].buffer->buffer_bytes = 0;
245 }
246 SCpnt->request.dev = -1;
247 }
248 return result;
249 }
250
251
252
253
254 static int flush_buffer(struct inode * inode, struct file * filp,
255 int seek_next)
256 {
257 int dev;
258 int backspace, result;
259
260 dev = inode->i_rdev & 127;
261
262 if (scsi_tapes[dev].rw == 2)
263 return flush_write_buffer(dev);
264
265 backspace = (scsi_tapes[dev].buffer->buffer_bytes +
266 scsi_tapes[dev].buffer->read_pointer) / scsi_tapes[dev].block_size -
267 (scsi_tapes[dev].buffer->read_pointer + scsi_tapes[dev].block_size - 1) /
268 scsi_tapes[dev].block_size;
269 scsi_tapes[dev].buffer->buffer_bytes = 0;
270 scsi_tapes[dev].buffer->read_pointer = 0;
271 result = 0;
272 if (!seek_next && backspace > 0) {
273 result = st_int_ioctl(inode, filp, MTBSR, backspace);
274 if (!result) {
275 scsi_tapes[dev].eof = 0;
276 scsi_tapes[dev].eof_hit = 0;
277 }
278 }
279 return result;
280
281 }
282
283
284
285 static int scsi_tape_open(struct inode * inode, struct file * filp)
286 {
287 int dev;
288 unsigned short flags;
289 int i;
290 unsigned char cmd[10];
291 Scsi_Cmnd * SCpnt;
292
293 dev = inode->i_rdev & 127;
294 if (dev >= NR_ST)
295 return (-ENODEV);
296 if (scsi_tapes[dev].in_use) {
297 printk("st%d: Device already in use.\n", dev);
298 return (-EBUSY);
299 }
300
301
302 for (i=0; i < st_nbr_buffers; i++)
303 if (!st_buffers[i]->in_use)
304 break;
305 if (i >= st_nbr_buffers) {
306 printk("st%d: No free buffers.\n", dev);
307 return (-EBUSY);
308 }
309 st_buffers[i]->in_use = 1;
310 st_buffers[i]->writing = 0;
311 scsi_tapes[dev].buffer = st_buffers[i];
312 scsi_tapes[dev].in_use = 1;
313
314 flags = filp->f_flags;
315 scsi_tapes[dev].write_prot = ((flags & O_ACCMODE) == O_RDONLY);
316
317 scsi_tapes[dev].dirty = 0;
318 scsi_tapes[dev].rw = 0;
319 scsi_tapes[dev].eof = 0;
320 scsi_tapes[dev].eof_hit = 0;
321
322 SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
323 if (!SCpnt) {
324 printk("st%d: Tape request not allocated", dev);
325 return (-EBUSY);
326 }
327
328 SCpnt->sense_buffer[0]=0;
329 memset ((void *) &cmd[0], 0, 10);
330 cmd[0] = TEST_UNIT_READY;
331 SCpnt->request.dev = dev;
332 scsi_do_cmd(SCpnt,
333 (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data,
334 ST_BLOCK_SIZE, st_sleep_done, ST_LONG_TIMEOUT, MAX_RETRIES);
335
336 if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
337
338 if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
339 (SCpnt->sense_buffer[2] & 0x0f) == UNIT_ATTENTION) {
340 #ifdef DEBUG
341 decode_sns(dev, SCpnt->sense_buffer);
342 #endif
343 SCpnt->sense_buffer[0]=0;
344 memset ((void *) &cmd[0], 0, 10);
345 cmd[0] = TEST_UNIT_READY;
346 SCpnt->request.dev = dev;
347 scsi_do_cmd(SCpnt,
348 (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data,
349 ST_BLOCK_SIZE, st_sleep_done, ST_LONG_TIMEOUT, MAX_RETRIES);
350
351 if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
352 }
353
354 if (SCpnt->result != 0) {
355 #ifdef DEBUG
356 decode_sns(dev, SCpnt->sense_buffer);
357 #endif
358 if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
359 (SCpnt->sense_buffer[2] & 0x0f) == NO_TAPE)
360 printk("st%d: No tape.\n", dev);
361 else
362 printk("st%d: Error %x.\n", dev, SCpnt->result);
363 scsi_tapes[dev].buffer->in_use = 0;
364 scsi_tapes[dev].in_use = 0;
365 SCpnt->request.dev = -1;
366 return (-EIO);
367 }
368
369 SCpnt->sense_buffer[0]=0;
370 memset ((void *) &cmd[0], 0, 10);
371 cmd[0] = READ_BLOCK_LIMITS;
372 SCpnt->request.dev = dev;
373 scsi_do_cmd(SCpnt,
374 (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data,
375 ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
376
377 if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
378
379 if (!SCpnt->result && !SCpnt->sense_buffer[0]) {
380 scsi_tapes[dev].max_block = (scsi_tapes[dev].buffer->b_data[1] << 16) |
381 (scsi_tapes[dev].buffer->b_data[2] << 8) | scsi_tapes[dev].buffer->b_data[3];
382 scsi_tapes[dev].min_block = (scsi_tapes[dev].buffer->b_data[4] << 8) |
383 scsi_tapes[dev].buffer->b_data[5];
384 #ifdef DEBUG
385 printk("st%d: Block limits %d - %d bytes.\n", dev, scsi_tapes[dev].min_block,
386 scsi_tapes[dev].max_block);
387 #endif
388 }
389 else {
390 scsi_tapes[dev].min_block = scsi_tapes[dev].max_block = (-1);
391 #ifdef DEBUG
392 printk("st%d: Can't read block limits.\n", dev);
393 #endif
394 }
395
396 SCpnt->sense_buffer[0]=0;
397 memset ((void *) &cmd[0], 0, 10);
398 cmd[0] = MODE_SENSE;
399 cmd[4] = 12;
400 SCpnt->request.dev = dev;
401 scsi_do_cmd(SCpnt,
402 (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data,
403 ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
404
405 if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
406
407 i = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
408 if (i) {
409 #ifdef DEBUG
410 printk("st%d: No Mode Sense.\n", dev);
411 #endif
412 scsi_tapes[dev].buffer->b_data[2] =
413 scsi_tapes[dev].buffer->b_data[3] = 0;
414 }
415 SCpnt->request.dev = -1;
416
417 #ifdef DEBUG
418 printk("st%d: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n", dev,
419 scsi_tapes[dev].buffer->b_data[0], scsi_tapes[dev].buffer->b_data[1],
420 scsi_tapes[dev].buffer->b_data[2], scsi_tapes[dev].buffer->b_data[3]);
421 #endif
422
423 if (scsi_tapes[dev].buffer->b_data[3] >= 8) {
424 scsi_tapes[dev].block_size = scsi_tapes[dev].buffer->b_data[9] * 65536 +
425 scsi_tapes[dev].buffer->b_data[10] * 256 + scsi_tapes[dev].buffer->b_data[11];
426 #ifdef DEBUG
427 printk("st%d: Density %x, tape length: %x, blocksize: %d\n", dev,
428 scsi_tapes[dev].buffer->b_data[4], scsi_tapes[dev].buffer->b_data[5] *
429 65536 + scsi_tapes[dev].buffer->b_data[6] * 256 +
430 scsi_tapes[dev].buffer->b_data[7], scsi_tapes[dev].buffer->b_data[9] *
431 65536 + scsi_tapes[dev].buffer->b_data[10] * 256 +
432 scsi_tapes[dev].buffer->b_data[11]);
433 #endif
434 if (scsi_tapes[dev].block_size > ST_BUFFER_SIZE) {
435 printk("st%d: Blocksize %d too large for buffer.\n", dev,
436 scsi_tapes[dev].block_size);
437 scsi_tapes[dev].buffer->in_use = 0;
438 scsi_tapes[dev].in_use = 0;
439 return (-EIO);
440 }
441
442 if (scsi_tapes[dev].block_size == 0) {
443 printk("st%d: Fixing block size to 512 bytes.\n", dev);
444 if (st_int_ioctl(inode, filp, MTSETBLK, ST_BLOCK_SIZE)) {
445 printk("st%d: Can't set fixed block size.\n", dev);
446 scsi_tapes[dev].buffer->in_use = 0;
447 scsi_tapes[dev].in_use = 0;
448 return (-EIO);
449 }
450 scsi_tapes[dev].block_size = ST_BLOCK_SIZE;
451 }
452 }
453 else
454 scsi_tapes[dev].block_size = ST_BLOCK_SIZE;
455
456 scsi_tapes[dev].buffer->buffer_blocks =
457 ST_BUFFER_SIZE / scsi_tapes[dev].block_size;
458 scsi_tapes[dev].buffer->buffer_size =
459 scsi_tapes[dev].buffer->buffer_blocks * scsi_tapes[dev].block_size;
460 scsi_tapes[dev].buffer->buffer_bytes = scsi_tapes[dev].buffer->read_pointer = 0;
461
462 #ifdef DEBUG
463 printk("st%d: Block size: %d, buffer size: %d (%d blocks).\n", dev,
464 scsi_tapes[dev].block_size, scsi_tapes[dev].buffer->buffer_size,
465 scsi_tapes[dev].buffer->buffer_blocks);
466 #endif
467
468 if (scsi_tapes[dev].buffer->b_data[2] & 0x80) {
469 scsi_tapes[dev].write_prot = 1;
470 #ifdef DEBUG
471 printk( "st%d: Write protected\n", dev);
472 #endif
473 }
474
475 return 0;
476 }
477
478
479
480 static void scsi_tape_close(struct inode * inode, struct file * filp)
481 {
482 int dev;
483 int result;
484 int rewind;
485 static unsigned char cmd[10];
486 Scsi_Cmnd * SCpnt;
487
488 dev = inode->i_rdev;
489 rewind = (dev & 0x80) == 0;
490 dev = dev & 127;
491
492 if ( scsi_tapes[dev].rw == 2) {
493
494 result = flush_write_buffer(dev);
495
496 #ifdef DEBUG
497 printk("st%d: File length %d bytes.\n", dev, filp->f_pos);
498 #endif
499
500 if (!result) {
501 SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
502
503 SCpnt->sense_buffer[0] = 0;
504 memset(cmd, 0, 10);
505 cmd[0] = WRITE_FILEMARKS;
506 cmd[4] = 1;
507 SCpnt->request.dev = dev;
508 scsi_do_cmd( SCpnt,
509 (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data,
510 ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
511
512 if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
513
514 if (SCpnt->result) {
515 printk("st%d: Error on write filemark:\n", dev);
516 #ifdef DEBUG
517 st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
518 #endif
519 }
520 SCpnt->request.dev = -1;
521 }
522
523 #ifdef DEBUG
524 printk("st%d: Buffer flushed, EOF written\n", dev);
525 #endif
526 }
527 else if (!rewind) {
528 if ((scsi_tapes[dev].eof == 1) && !scsi_tapes[dev].eof_hit)
529 st_int_ioctl(inode, filp, MTBSF, 1);
530 #ifdef ST_IN_FILE_POS
531 flush_buffer(inode, filp, 0);
532 #endif
533 }
534
535 if (rewind)
536 st_int_ioctl(inode, filp, MTREW, 1);
537
538 scsi_tapes[dev].buffer->in_use = 0;
539 scsi_tapes[dev].in_use = 0;
540
541 return;
542 }
543
544
545
546 int st_write(struct inode * inode, struct file * filp, char * buf, int count)
547 {
548 int dev;
549 int total, do_count, blks, retval;
550 static unsigned char cmd[10];
551 char *b_point;
552 Scsi_Cmnd * SCpnt;
553
554 dev = inode->i_rdev & 127;
555 #ifdef DEBUG
556 if (!scsi_tapes[dev].in_use) {
557 printk("st%d: Incorrect device.\n", dev);
558 return (-EIO);
559 }
560 #endif
561
562 if (scsi_tapes[dev].write_prot)
563 return (-EACCES);
564
565 if (scsi_tapes[dev].rw == 1) {
566 retval = flush_buffer(inode, filp, 0);
567 if (retval)
568 return retval;
569 scsi_tapes[dev].rw = 2;
570 }
571
572 #if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
573 if (scsi_tapes[dev].buffer->writing) {
574 write_behind_check(dev);
575 if (scsi_tapes[dev].buffer->last_result) {
576 #ifdef DEBUG
577 printk("st%d: Async write error %x.\n", dev,
578 scsi_tapes[dev].buffer->last_result);
579 #endif
580
581
582
583 retval = (-EIO);
584 return retval;
585 }
586 }
587 #endif
588
589 SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
590
591 total = count;
592
593 memset(cmd, 0, 10);
594 cmd[0] = WRITE_6;
595 cmd[1] = 1;
596
597 scsi_tapes[dev].rw = 2;
598
599 b_point = buf;
600 while((scsi_tapes[dev].buffer->buffer_bytes + count) >=
601 scsi_tapes[dev].buffer->buffer_size) {
602 do_count = scsi_tapes[dev].buffer->buffer_size -
603 scsi_tapes[dev].buffer->buffer_bytes;
604 memcpy_fromfs(scsi_tapes[dev].buffer->b_data +
605 scsi_tapes[dev].buffer->buffer_bytes,b_point,do_count);
606
607 blks = scsi_tapes[dev].buffer->buffer_blocks;
608 cmd[2] = blks >> 16;
609 cmd[3] = blks >> 8;
610 cmd[4] = blks;
611 SCpnt->sense_buffer[0] = 0;
612 SCpnt->request.dev = dev;
613 scsi_do_cmd (SCpnt,
614 (void *) cmd, scsi_tapes[dev].buffer->b_data,
615 scsi_tapes[dev].buffer->buffer_size,
616 st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
617
618 if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
619
620 if (SCpnt->result || SCpnt->sense_buffer[0] != 0) {
621 #ifdef DEBUG
622 printk("st%d: Error on write:\n", dev);
623 st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
624 #endif
625 if ((SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
626 (SCpnt->sense_buffer[2] & 0x40))
627 retval = (-ENOSPC);
628 else
629 retval = (-EIO);
630 SCpnt->request.dev = -1;
631 if (count < total)
632 return total - count;
633 else
634 return retval;
635 }
636 filp->f_pos += do_count;
637 b_point += do_count;
638 count -= do_count;
639 scsi_tapes[dev].buffer->buffer_bytes = 0;
640 scsi_tapes[dev].dirty = 0;
641 }
642 if (count != 0) {
643 scsi_tapes[dev].dirty = 1;
644 memcpy_fromfs(scsi_tapes[dev].buffer->b_data +
645 scsi_tapes[dev].buffer->buffer_bytes,b_point,count);
646 filp->f_pos += count;
647 scsi_tapes[dev].buffer->buffer_bytes += count;
648 count = 0;
649 }
650
651 do_count = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
652 if (do_count) {
653 SCpnt->request.dev = -1;
654 return do_count;
655 }
656
657 #if ST_WRITE_THRESHOLD_BLOCKS < ST_BUFFER_BLOCKS
658 if (scsi_tapes[dev].buffer->buffer_bytes >= ST_WRITE_THRESHOLD) {
659
660 scsi_tapes[dev].buffer->writing = (scsi_tapes[dev].buffer->buffer_bytes /
661 scsi_tapes[dev].block_size) * scsi_tapes[dev].block_size;
662 scsi_tapes[dev].dirty = 0;
663
664 blks = scsi_tapes[dev].buffer->writing / scsi_tapes[dev].block_size;
665 cmd[2] = blks >> 16;
666 cmd[3] = blks >> 8;
667 cmd[4] = blks;
668 SCpnt->result = scsi_tapes[dev].buffer->last_result = -1;
669 SCpnt->sense_buffer[0] = 0;
670 SCpnt->request.dev = dev;
671 scsi_do_cmd (SCpnt,
672 (void *) cmd, scsi_tapes[dev].buffer->b_data,
673 scsi_tapes[dev].buffer->writing,
674 st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
675 }
676 else
677 #endif
678 SCpnt->request.dev = -1;
679
680 return( total);
681 }
682
683
684
685 int st_read(struct inode * inode, struct file * filp, char * buf, int count)
686 {
687 int dev;
688 int total;
689 int transfer, blks;
690 static unsigned char cmd[10];
691 Scsi_Cmnd * SCpnt;
692
693 dev = inode->i_rdev & 127;
694 #ifdef DEBUG
695 if (!scsi_tapes[dev].in_use) {
696 printk("st%d: Incorrect device.\n", dev);
697 return (-EIO);
698 }
699 #endif
700
701 if (scsi_tapes[dev].rw == 2) {
702 transfer = flush_buffer(inode, filp, 0);
703 if (transfer)
704 return transfer;
705 scsi_tapes[dev].rw = 1;
706 }
707
708 #ifdef DEBUG
709 if (scsi_tapes[dev].eof)
710 printk("st%d: EOF flag up. Bytes %d\n", dev,
711 scsi_tapes[dev].buffer->buffer_bytes);
712 #endif
713 if ((scsi_tapes[dev].buffer->buffer_bytes == 0) &&
714 scsi_tapes[dev].eof == 2)
715 return (-EIO);
716
717 scsi_tapes[dev].rw = 1;
718
719 SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
720
721 for (total = 0; total < count; ) {
722
723 if (scsi_tapes[dev].buffer->buffer_bytes == 0 &&
724 scsi_tapes[dev].eof == 0) {
725
726 memset(cmd, 0, 10);
727 cmd[0] = READ_6;
728 cmd[1] = 1;
729 blks = scsi_tapes[dev].buffer->buffer_blocks;
730 cmd[2] = blks >> 16;
731 cmd[3] = blks >> 8;
732 cmd[4] = blks;
733
734 SCpnt->sense_buffer[0] = 0;
735 SCpnt->request.dev = dev;
736 scsi_do_cmd (SCpnt,
737 (void *) cmd, scsi_tapes[dev].buffer->b_data,
738 scsi_tapes[dev].buffer->buffer_size,
739 st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
740
741 if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
742
743 scsi_tapes[dev].buffer->read_pointer = 0;
744 scsi_tapes[dev].eof_hit = 0;
745
746 if (SCpnt->result != 0 || SCpnt->sense_buffer[0] != 0) {
747 #ifdef DEBUG
748 printk("st%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", dev,
749 SCpnt->sense_buffer[0], SCpnt->sense_buffer[1],
750 SCpnt->sense_buffer[2], SCpnt->sense_buffer[3],
751 SCpnt->sense_buffer[4], SCpnt->sense_buffer[5],
752 SCpnt->sense_buffer[6], SCpnt->sense_buffer[7]);
753 #endif
754 if ((SCpnt->sense_buffer[0] & 0x70) == 0x70) {
755
756 if ((SCpnt->sense_buffer[2] & 0xe0) != 0) {
757 transfer = (SCpnt->sense_buffer[3] << 24) |
758 (SCpnt->sense_buffer[4] << 16) |
759 (SCpnt->sense_buffer[5] << 8) | SCpnt->sense_buffer[6];
760
761 if (SCpnt->sense_buffer[2] & 0x20) {
762 printk("st%d: Incorrect block size.\n", dev);
763 SCpnt->request.dev = -1;
764 return (-EIO);
765 }
766 else if (SCpnt->sense_buffer[2] & 0x40) {
767 scsi_tapes[dev].eof = 2;
768 scsi_tapes[dev].buffer->buffer_bytes =
769 (scsi_tapes[dev].buffer->buffer_blocks - transfer) *
770 scsi_tapes[dev].block_size;
771 #ifdef DEBUG
772 printk("st%d: EOM detected (%d blocks read).\n", dev,
773 scsi_tapes[dev].buffer->buffer_blocks - transfer);
774 #endif
775 }
776 else if (SCpnt->sense_buffer[2] & 0x80) {
777 scsi_tapes[dev].eof = 1;
778 scsi_tapes[dev].buffer->buffer_bytes =
779 (scsi_tapes[dev].buffer->buffer_blocks - transfer) *
780 scsi_tapes[dev].block_size;
781 #ifdef DEBUG
782 printk("st%d: EOF detected (%d blocks read, transferred %d bytes).\n",
783 dev, scsi_tapes[dev].buffer->buffer_blocks - transfer, total);
784 #endif
785 }
786 }
787 else {
788 #ifdef DEBUG
789 printk("st%d: Tape error. Sense key %x\n", dev,
790 SCpnt->sense_buffer[2] & 0x0f);
791 decode_sns(dev, SCpnt->sense_buffer);
792 #endif
793 SCpnt->request.dev = -1;
794 if (total)
795 return total;
796 else
797 return -EIO;
798 }
799 }
800 else {
801 transfer = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
802 SCpnt->request.dev = -1;
803 return transfer;
804 }
805 }
806 else
807 scsi_tapes[dev].buffer->buffer_bytes =
808 scsi_tapes[dev].buffer->buffer_size;
809 }
810
811
812 if (scsi_tapes[dev].buffer->buffer_bytes > 0) {
813 #ifdef DEBUG
814 if (scsi_tapes[dev].eof)
815 printk("st%d: EOF up. Left %d, needed %d.\n", dev,
816 scsi_tapes[dev].buffer->buffer_bytes, count - total);
817 #endif
818 transfer = scsi_tapes[dev].buffer->buffer_bytes < count - total ?
819 scsi_tapes[dev].buffer->buffer_bytes : count - total;
820 memcpy_tofs(buf, scsi_tapes[dev].buffer->b_data +
821 scsi_tapes[dev].buffer->read_pointer,transfer);
822 filp->f_pos += transfer;
823 buf += transfer;
824 total += transfer;
825 scsi_tapes[dev].buffer->buffer_bytes -= transfer;
826 scsi_tapes[dev].buffer->read_pointer += transfer;
827 }
828 else if (scsi_tapes[dev].eof) {
829 scsi_tapes[dev].eof_hit = 1;
830 SCpnt->request.dev = -1;
831 if (total == 0 && scsi_tapes[dev].eof == 1)
832 scsi_tapes[dev].eof = 0;
833 if (total == 0 && scsi_tapes[dev].eof == 2)
834 return (-EIO);
835 return total;
836 }
837
838 }
839
840 SCpnt->request.dev = -1;
841
842 return total;
843 }
844
845
846
847 static int st_int_ioctl(struct inode * inode,struct file * file,
848 unsigned int cmd_in, unsigned long arg)
849 {
850 int dev = inode->i_rdev;
851 int timeout = ST_LONG_TIMEOUT;
852 long ltmp;
853 int ioctl_result;
854 unsigned char cmd[10];
855 Scsi_Cmnd * SCpnt;
856
857 dev = dev & 127;
858
859 memset(cmd, 0, 10);
860 switch (cmd_in) {
861 case MTFSF:
862 case MTFSFM:
863 cmd[0] = SPACE;
864 cmd[1] = 0x01;
865 cmd[2] = (arg >> 16);
866 cmd[3] = (arg >> 8);
867 cmd[4] = arg;
868 #ifdef DEBUG
869 printk("st%d: Spacing tape forward %d files.\n", dev,
870 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
871 #endif
872 break;
873 case MTBSF:
874 case MTBSFM:
875 cmd[0] = SPACE;
876 cmd[1] = 0x01;
877 ltmp = (-arg);
878 cmd[2] = (ltmp >> 16);
879 cmd[3] = (ltmp >> 8);
880 cmd[4] = ltmp;
881 #ifdef DEBUG
882 if (cmd[2] & 0x80)
883 ltmp = 0xff000000;
884 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
885 printk("st%d: Spacing tape backward %d files.\n", dev, (-ltmp));
886 #endif
887 break;
888 case MTFSR:
889 cmd[0] = SPACE;
890 cmd[1] = 0x00;
891 cmd[2] = (arg >> 16);
892 cmd[3] = (arg >> 8);
893 cmd[4] = arg;
894 #ifdef DEBUG
895 printk("st%d: Spacing tape forward %d blocks.\n", dev,
896 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
897 #endif
898 break;
899 case MTBSR:
900 cmd[0] = SPACE;
901 cmd[1] = 0x00;
902 ltmp = (-arg);
903 cmd[2] = (ltmp >> 16);
904 cmd[3] = (ltmp >> 8);
905 cmd[4] = ltmp;
906 #ifdef DEBUG
907 if (cmd[2] & 0x80)
908 ltmp = 0xff000000;
909 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
910 printk("st%d: Spacing tape backward %d blocks.\n", dev, (-ltmp));
911 #endif
912 break;
913 case MTWEOF:
914 if (scsi_tapes[dev].write_prot)
915 return (-EACCES);
916 cmd[0] = WRITE_FILEMARKS;
917 cmd[2] = (arg >> 16);
918 cmd[3] = (arg >> 8);
919 cmd[4] = arg;
920 timeout = ST_TIMEOUT;
921 #ifdef DEBUG
922 printk("st%d: Writing %d filemarks.\n", dev,
923 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
924 #endif
925 break;
926 case MTREW:
927 cmd[0] = REZERO_UNIT;
928 #ifdef ST_NOWAIT
929 cmd[1] = 1;
930 timeout = ST_TIMEOUT;
931 #endif
932 #ifdef DEBUG
933 printk("st%d: Rewinding tape.\n", dev);
934 #endif
935 break;
936 case MTOFFL:
937 cmd[0] = START_STOP;
938 #ifdef ST_NOWAIT
939 cmd[1] = 1;
940 timeout = ST_TIMEOUT;
941 #endif
942 #ifdef DEBUG
943 printk("st%d: Unloading tape.\n", dev);
944 #endif
945 break;
946 case MTNOP:
947 #ifdef DEBUG
948 printk("st%d: No op on tape.\n", dev);
949 #endif
950 return 0;
951 break;
952 case MTRETEN:
953 cmd[0] = START_STOP;
954 #ifdef ST_NOWAIT
955 cmd[1] = 1;
956 timeout = ST_TIMEOUT;
957 #endif
958 cmd[4] = 3;
959 #ifdef DEBUG
960 printk("st%d: Retensioning tape.\n", dev);
961 #endif
962 break;
963 case MTEOM:
964 cmd[0] = SPACE;
965 cmd[1] = 3;
966 #ifdef DEBUG
967 printk("st%d: Spacing to end of recorded medium.\n", dev);
968 #endif
969 break;
970 case MTERASE:
971 if (scsi_tapes[dev].write_prot)
972 return (-EACCES);
973 cmd[0] = ERASE;
974 cmd[1] = 1;
975 #ifdef DEBUG
976 printk("st%d: Erasing tape.\n", dev);
977 #endif
978 break;
979 case MTSEEK:
980 if (scsi_tapes[dev].device->scsi_level < SCSI_2) {
981 cmd[0] = QFA_SEEK_BLOCK;
982 cmd[2] = (arg >> 16);
983 cmd[3] = (arg >> 8);
984 cmd[4] = arg;
985 cmd[5] = 0;
986 }
987 else {
988 cmd[0] = SEEK_10;
989 cmd[1] = 4;
990 cmd[3] = (arg >> 24);
991 cmd[4] = (arg >> 16);
992 cmd[5] = (arg >> 8);
993 cmd[6] = arg;
994 }
995 #ifdef ST_NOWAIT
996 cmd[1] |= 1;
997 timeout = ST_TIMEOUT;
998 #endif
999 #ifdef DEBUG
1000 printk("st%d: Seeking tape to block %d.\n", dev, arg);
1001 #endif
1002 break;
1003 case MTSETBLK:
1004 case MTSETDENSITY:
1005 if (scsi_tapes[dev].dirty || scsi_tapes[dev].buffer->buffer_bytes != 0)
1006 return (-EIO);
1007 if (cmd_in == MTSETBLK &&
1008 (arg < scsi_tapes[dev].min_block || arg > scsi_tapes[dev].max_block ||
1009 arg > ST_BUFFER_SIZE)) {
1010 printk("st%d: Illegal block size.\n", dev);
1011 return (-EINVAL);
1012 }
1013 cmd[0] = MODE_SELECT;
1014 cmd[4] = 12;
1015
1016 memset(scsi_tapes[dev].buffer->b_data, 0, 12);
1017 scsi_tapes[dev].buffer->b_data[2] = 0x10;
1018 scsi_tapes[dev].buffer->b_data[3] = 8;
1019 if (cmd_in == MTSETBLK)
1020 ltmp = arg;
1021 else {
1022 scsi_tapes[dev].buffer->b_data[4] = arg;
1023 ltmp = scsi_tapes[dev].block_size;
1024 }
1025 scsi_tapes[dev].buffer->b_data[9] = (ltmp >> 16);
1026 scsi_tapes[dev].buffer->b_data[10] = (ltmp >> 8);
1027 scsi_tapes[dev].buffer->b_data[11] = ltmp;
1028 timeout = ST_TIMEOUT;
1029 #ifdef DEBUG
1030 if (cmd_in == MTSETBLK)
1031 printk("st%d: Setting block size to %d bytes.\n", dev,
1032 scsi_tapes[dev].buffer->b_data[9] * 65536 +
1033 scsi_tapes[dev].buffer->b_data[10] * 256 +
1034 scsi_tapes[dev].buffer->b_data[11]);
1035 else
1036 printk("st%d: Setting density code to %x.\n", dev,
1037 scsi_tapes[dev].buffer->b_data[4]);
1038 #endif
1039 break;
1040 default:
1041 printk("st%d: Unknown st_ioctl command %x.\n", dev, cmd_in);
1042 return (-ENOSYS);
1043 }
1044
1045 SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
1046 SCpnt->sense_buffer[0] = 0;
1047 SCpnt->request.dev = dev;
1048 scsi_do_cmd(SCpnt,
1049 (void *) cmd, (void *) scsi_tapes[dev].buffer->b_data, ST_BLOCK_SIZE,
1050 st_sleep_done, timeout, MAX_RETRIES);
1051
1052 if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
1053
1054 SCpnt->request.dev = -1;
1055
1056 ioctl_result = st_chk_result(dev, SCpnt->result, SCpnt->sense_buffer);
1057
1058 if (!ioctl_result) {
1059 if (cmd_in == MTBSFM)
1060 ioctl_result = st_int_ioctl(inode, file, MTFSF, 1);
1061 else if (cmd_in == MTFSFM)
1062 ioctl_result = st_int_ioctl(inode, file, MTBSF, 1);
1063 else if (cmd_in == MTSETBLK) {
1064 scsi_tapes[dev].block_size = arg;
1065 scsi_tapes[dev].buffer->buffer_blocks =
1066 ST_BUFFER_SIZE / scsi_tapes[dev].block_size;
1067 scsi_tapes[dev].buffer->buffer_size =
1068 scsi_tapes[dev].buffer->buffer_blocks * scsi_tapes[dev].block_size;
1069 scsi_tapes[dev].buffer->buffer_bytes =
1070 scsi_tapes[dev].buffer->read_pointer = 0;
1071 }
1072 if (cmd_in == MTEOM || cmd_in == MTWEOF) {
1073 scsi_tapes[dev].eof = 2;
1074 scsi_tapes[dev].eof_hit = 0;
1075 }
1076 else if (cmd_in != MTSETBLK && cmd_in != MTNOP) {
1077 scsi_tapes[dev].eof = 0;
1078 scsi_tapes[dev].eof_hit = 0;
1079 }
1080 }
1081
1082 return ioctl_result ;
1083 }
1084
1085
1086
1087
1088 static int st_ioctl(struct inode * inode,struct file * file,
1089 unsigned int cmd_in, unsigned long arg)
1090 {
1091 int dev = inode->i_rdev;
1092 int i, cmd, result;
1093 struct mtop mtc;
1094 struct mtpos mt_pos;
1095 unsigned char scmd[10];
1096 Scsi_Cmnd *SCpnt;
1097
1098 dev = dev & 127;
1099 #ifdef DEBUG
1100 if (!scsi_tapes[dev].in_use) {
1101 printk("st%d: Incorrect device.\n", dev);
1102 return (-EIO);
1103 }
1104 #endif
1105
1106 cmd = cmd_in & IOCCMD_MASK;
1107 if (cmd == (MTIOCTOP & IOCCMD_MASK)) {
1108
1109 if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(mtc))
1110 return (-EINVAL);
1111
1112 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(mtc));
1113 if (i)
1114 return i;
1115
1116 memcpy_fromfs((char *) &mtc, (char *)arg, sizeof(struct mtop));
1117
1118 i = flush_buffer(inode, file, mtc.mt_op == MTSEEK ||
1119 mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
1120 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM);
1121 if (i < 0)
1122 return i;
1123
1124 return st_int_ioctl(inode, file, mtc.mt_op, mtc.mt_count);
1125 }
1126 else if (cmd == (MTIOCGET & IOCCMD_MASK)) {
1127
1128 if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(struct mtget))
1129 return (-EINVAL);
1130 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mtget));
1131 if (i)
1132 return i;
1133
1134 memcpy_tofs((char *)arg, (char *)scsi_tapes[dev].buffer->mt_status,
1135 sizeof(struct mtget));
1136 return 0;
1137 }
1138 else if (cmd == (MTIOCPOS & IOCCMD_MASK)) {
1139 #ifdef DEBUG
1140 printk("st%d: get tape position.\n", dev);
1141 #endif
1142 if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(struct mtpos))
1143 return (-EINVAL);
1144
1145 i = flush_buffer(inode, file, 0);
1146 if (i < 0)
1147 return i;
1148
1149 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct mtpos));
1150 if (i)
1151 return i;
1152
1153 SCpnt = allocate_device(NULL, scsi_tapes[dev].device->index, 1);
1154
1155 SCpnt->sense_buffer[0]=0;
1156 memset (scmd, 0, 10);
1157 if (scsi_tapes[dev].device->scsi_level < SCSI_2) {
1158 scmd[0] = QFA_REQUEST_BLOCK;
1159 scmd[4] = 3;
1160 }
1161 else {
1162 scmd[0] = READ_POSITION;
1163 scmd[1] = 1;
1164 }
1165 SCpnt->request.dev = dev;
1166 SCpnt->sense_buffer[0] = 0;
1167 scsi_do_cmd(SCpnt,
1168 (void *) scmd, (void *) scsi_tapes[dev].buffer->b_data,
1169 ST_BLOCK_SIZE, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
1170
1171 if (SCpnt->request.dev == dev) sleep_on( &scsi_tapes[dev].waiting );
1172
1173 if (SCpnt->result || SCpnt->sense_buffer[0]) {
1174 mt_pos.mt_blkno = (-1);
1175 #ifdef DEBUG
1176 printk("st%d: Can't read tape position.\n", dev);
1177 #endif
1178 result = (-EIO);
1179 }
1180 else {
1181 result = 0;
1182 if (scsi_tapes[dev].device->scsi_level < SCSI_2)
1183 mt_pos.mt_blkno = (scsi_tapes[dev].buffer->b_data[0] << 16)
1184 + (scsi_tapes[dev].buffer->b_data[1] << 8)
1185 + scsi_tapes[dev].buffer->b_data[2];
1186 else
1187 mt_pos.mt_blkno = (scsi_tapes[dev].buffer->b_data[4] << 24)
1188 + (scsi_tapes[dev].buffer->b_data[5] << 16)
1189 + (scsi_tapes[dev].buffer->b_data[6] << 8)
1190 + scsi_tapes[dev].buffer->b_data[7];
1191
1192 }
1193
1194 SCpnt->request.dev = -1;
1195
1196 memcpy_tofs((char *)arg, (char *) (&mt_pos), sizeof(struct mtpos));
1197 return result;
1198 }
1199 else
1200 return scsi_ioctl(scsi_tapes[dev].device, cmd_in, (void *) arg);
1201 }
1202
1203
1204
1205 static struct file_operations st_fops = {
1206 NULL,
1207 st_read,
1208 st_write,
1209 NULL,
1210 NULL,
1211 st_ioctl,
1212 NULL,
1213 scsi_tape_open,
1214 scsi_tape_close
1215 };
1216
1217 void st_attach(Scsi_Device * SDp){
1218 scsi_tapes[NR_ST++].device = SDp;
1219 if(NR_ST > MAX_ST) panic ("scsi_devices corrupt (st)");
1220 };
1221
1222 unsigned long st_init1(unsigned long mem_start, unsigned long mem_end){
1223 scsi_tapes = (Scsi_Tape *) mem_start;
1224 mem_start += MAX_ST * sizeof(Scsi_Tape);
1225 return mem_start;
1226 };
1227
1228
1229 unsigned long st_init(unsigned long mem_start, unsigned long mem_end)
1230 {
1231 int i;
1232
1233 if (register_chrdev(MAJOR_NR,"st",&st_fops)) {
1234 printk("Unable to get major %d for SCSI tapes\n",MAJOR_NR);
1235 return mem_start;
1236 }
1237 if (NR_ST == 0) return mem_start;
1238
1239 #ifdef DEBUG
1240 printk("st: Init tape.\n");
1241 #endif
1242
1243 for (i=0; i < NR_ST; ++i) {
1244 scsi_tapes[i].capacity = 0xfffff;
1245 scsi_tapes[i].dirty = 0;
1246 scsi_tapes[i].rw = 0;
1247 scsi_tapes[i].eof = 0;
1248 scsi_tapes[i].waiting = NULL;
1249 scsi_tapes[i].in_use = 0;
1250 }
1251
1252
1253
1254 if (NR_ST == 1)
1255 st_nbr_buffers = 1;
1256 else
1257 st_nbr_buffers = 2;
1258 for (i=0; i < st_nbr_buffers; i++) {
1259 st_buffers[i] = (ST_buffer *) mem_start;
1260 #ifdef DEBUG
1261 printk("st: Buffer address: %x\n", st_buffers[i]);
1262 #endif
1263 mem_start += sizeof(ST_buffer) - 1 + ST_BUFFER_BLOCKS * ST_BLOCK_SIZE;
1264 st_buffers[i]->mt_status = (struct mtget *) mem_start;
1265 mem_start += sizeof(struct mtget);
1266 st_buffers[i]->in_use = 0;
1267 st_buffers[i]->writing = 0;
1268
1269
1270 memset((void *) st_buffers[i]->mt_status, 0, sizeof(struct mtget));
1271 st_buffers[i]->mt_status->mt_type = MT_ISSCSI1;
1272 }
1273
1274 return mem_start;
1275 }