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