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