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