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
26static const char * cvsid = "$Id: osst.c,v 1.65 2001/11/11 20:38:56 riede Exp $";
27const char * osst_version = "0.9.10";
28
29
30#define OSST_FW_NEED_POLL_MIN 10601
31#define OSST_FW_NEED_POLL_MAX 10704
32#define OSST_FW_NEED_POLL(x,d) ((x) >= OSST_FW_NEED_POLL_MIN && (x) <= OSST_FW_NEED_POLL_MAX && d->host->this_id != 7)
33
34#include <linux/module.h>
35
36#include <linux/fs.h>
37#include <linux/kernel.h>
38#include <linux/sched.h>
39#include <linux/mm.h>
40#include <linux/init.h>
41#include <linux/string.h>
42#include <linux/errno.h>
43#include <linux/mtio.h>
44#include <linux/ioctl.h>
45#include <linux/fcntl.h>
46#include <linux/spinlock.h>
47#include <linux/vmalloc.h>
48#include <linux/version.h>
49#include <asm/uaccess.h>
50#include <asm/dma.h>
51#include <asm/system.h>
52
53
54
55#define DEBUG 0
56
57
58
59
60#define OSST_DEB_MSG KERN_NOTICE
61
62#define MAJOR_NR OSST_MAJOR
63#include <linux/blk.h>
64
65#include "scsi.h"
66#include "hosts.h"
67#include <scsi/scsi_ioctl.h>
68
69#define ST_KILOBYTE 1024
70
71#include "st.h"
72#include "osst.h"
73#include "osst_options.h"
74#include "osst_detect.h"
75
76#include "constants.h"
77
78static int buffer_kbs = 0;
79static int write_threshold_kbs = 0;
80static int max_buffers = 0;
81static int max_sg_segs = 0;
82
83#ifdef MODULE
84MODULE_AUTHOR("Willem Riede");
85MODULE_DESCRIPTION("OnStream SCSI Tape Driver");
86MODULE_LICENSE("GPL");
87
88MODULE_PARM(buffer_kbs, "i");
89MODULE_PARM(write_threshold_kbs, "i");
90MODULE_PARM(max_buffers, "i");
91MODULE_PARM(max_sg_segs, "i");
92#else
93static struct osst_dev_parm {
94 char *name;
95 int *val;
96} parms[] __initdata = {
97 { "buffer_kbs", &buffer_kbs },
98 { "write_threshold_kbs", &write_threshold_kbs },
99 { "max_buffers", &max_buffers },
100 { "max_sg_segs", &max_sg_segs }
101 };
102#endif
103
104
105#define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
106#define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
107
108
109
110#if OSST_BUFFER_SIZE >= (2 << 24 - 1)
111#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
112#endif
113
114#if DEBUG
115static int debugging = 1;
116
117
118#endif
119
120#define MAX_RETRIES 0
121#define MAX_WRITE_RETRIES 0
122#define MAX_READY_RETRIES 5
123#define NO_TAPE NOT_READY
124
125#define OSST_TIMEOUT (200 * HZ)
126#define OSST_LONG_TIMEOUT (1800 * HZ)
127
128#define TAPE_NR(x) (MINOR(x) & ~(128 | ST_MODE_MASK))
129#define TAPE_MODE(x) ((MINOR(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
130
131
132
133#define SET_DENS_AND_BLK 0x10001
134
135static int osst_nbr_buffers;
136static int osst_buffer_size = OSST_BUFFER_SIZE;
137static int osst_write_threshold = OSST_WRITE_THRESHOLD;
138static int osst_max_buffers = OSST_MAX_BUFFERS;
139static int osst_max_sg_segs = OSST_MAX_SG;
140
141static OS_Scsi_Tape **os_scsi_tapes = NULL;
142static OSST_buffer **osst_buffers = NULL;
143
144static int modes_defined = FALSE;
145
146static OSST_buffer *new_tape_buffer(int, int);
147static int enlarge_buffer(OSST_buffer *, int, int);
148static void normalize_buffer(OSST_buffer *);
149static int append_to_buffer(const char *, OSST_buffer *, int);
150static int from_buffer(OSST_buffer *, char *, int);
151static int osst_zero_buffer_tail(OSST_buffer *);
152static int osst_copy_to_buffer(OSST_buffer *, unsigned char *);
153static int osst_copy_from_buffer(OSST_buffer *, unsigned char *);
154
155static int osst_init(void);
156static int osst_attach(Scsi_Device *);
157static int osst_detect(Scsi_Device *);
158static void osst_detach(Scsi_Device *);
159
160struct Scsi_Device_Template osst_template =
161{
162 name: "OnStream tape",
163 tag: "osst",
164 scsi_type: TYPE_TAPE,
165 major: OSST_MAJOR,
166 detect: osst_detect,
167 init: osst_init,
168 attach: osst_attach,
169 detach: osst_detach
170};
171
172static int osst_int_ioctl(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, unsigned int cmd_in,unsigned long arg);
173
174static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int frame, int skip);
175
176static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt);
177
178static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt);
179
180static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending);
181
182
183
184
185
186static int osst_chk_result(OS_Scsi_Tape * STp, Scsi_Request * SRpnt)
187{
188 int dev = TAPE_NR(STp->devt);
189 int result = SRpnt->sr_result;
190 unsigned char * sense = SRpnt->sr_sense_buffer, scode;
191#if DEBUG
192 const char *stp;
193#endif
194
195 if (!result) {
196 sense[0] = 0;
197 return 0;
198 }
199 if (driver_byte(result) & DRIVER_SENSE)
200 scode = sense[2] & 0x0f;
201 else {
202 sense[0] = 0;
203 scode = 0;
204 }
205
206#if DEBUG
207 if (debugging) {
208 printk(OSST_DEB_MSG "osst%d:D: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n",
209 dev, result,
210 SRpnt->sr_cmnd[0], SRpnt->sr_cmnd[1], SRpnt->sr_cmnd[2],
211 SRpnt->sr_cmnd[3], SRpnt->sr_cmnd[4], SRpnt->sr_cmnd[5],
212 SRpnt->sr_bufflen);
213 if (driver_byte(result) & DRIVER_SENSE)
214 print_req_sense("osst", SRpnt);
215 }
216 else
217#endif
218 if (!(driver_byte(result) & DRIVER_SENSE) ||
219 ((sense[0] & 0x70) == 0x70 &&
220 scode != NO_SENSE &&
221 scode != RECOVERED_ERROR &&
222
223 scode != BLANK_CHECK &&
224 scode != VOLUME_OVERFLOW &&
225 SRpnt->sr_cmnd[0] != MODE_SENSE &&
226 SRpnt->sr_cmnd[0] != TEST_UNIT_READY)) {
227 if (driver_byte(result) & DRIVER_SENSE) {
228 printk(KERN_WARNING "osst%d:W: Command with sense data: ", dev);
229 print_req_sense("osst:", SRpnt);
230 }
231 else {
232 static int notyetprinted = 1;
233
234 printk(KERN_WARNING
235 "osst%d:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
236 dev, result, suggestion(result), driver_byte(result) & DRIVER_MASK,
237 host_byte(result));
238 if (notyetprinted) {
239 notyetprinted = 0;
240 printk(KERN_INFO
241 "osst%d:I: This warning may be caused by your scsi controller,\n", dev);
242 printk(KERN_INFO
243 "osst%d:I: it has been reported with some Buslogic cards.\n", dev);
244 }
245 }
246 }
247 if ((sense[0] & 0x70) == 0x70 &&
248 scode == RECOVERED_ERROR) {
249 STp->recover_count++;
250 STp->recover_erreg++;
251#if DEBUG
252 if (debugging) {
253 if (SRpnt->sr_cmnd[0] == READ_6)
254 stp = "read";
255 else if (SRpnt->sr_cmnd[0] == WRITE_6)
256 stp = "write";
257 else
258 stp = "ioctl";
259 printk(OSST_DEB_MSG "osst%d:D: Recovered %s error (%d).\n", dev, stp,
260 os_scsi_tapes[dev]->recover_count);
261 }
262#endif
263 if ((sense[2] & 0xe0) == 0)
264 return 0;
265 }
266 return (-EIO);
267}
268
269
270
271static void osst_sleep_done (Scsi_Cmnd * SCpnt)
272{
273 unsigned int dev = TAPE_NR(SCpnt->request.rq_dev);
274 OS_Scsi_Tape * STp;
275
276 if (os_scsi_tapes && (STp = os_scsi_tapes[dev])) {
277 if ((STp->buffer)->writing &&
278 (SCpnt->sense_buffer[0] & 0x70) == 0x70 &&
279 (SCpnt->sense_buffer[2] & 0x40)) {
280
281 if ((SCpnt->sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW)
282 (STp->buffer)->midlevel_result = SCpnt->result;
283 else
284 (STp->buffer)->midlevel_result = INT_MAX;
285 }
286 else
287 (STp->buffer)->midlevel_result = SCpnt->result;
288 SCpnt->request.rq_status = RQ_SCSI_DONE;
289 (STp->buffer)->last_SRpnt = SCpnt->sc_request;
290
291#if DEBUG
292 STp->write_pending = 0;
293#endif
294 complete(SCpnt->request.waiting);
295 }
296#if DEBUG
297 else if (debugging)
298 printk(OSST_DEB_MSG "osst?:D: Illegal interrupt device %x\n", dev);
299#endif
300}
301
302
303
304
305
306static Scsi_Request * osst_do_scsi(Scsi_Request *SRpnt, OS_Scsi_Tape *STp,
307 unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
308{
309 unsigned char *bp;
310#ifdef OSST_INJECT_ERRORS
311 static int inject = 0;
312 static int repeat = 0;
313#endif
314 if (SRpnt == NULL) {
315 if ((SRpnt = scsi_allocate_request(STp->device)) == NULL) {
316 printk(KERN_ERR "osst%d:E: Can't get SCSI request.\n", TAPE_NR(STp->devt));
317 if (signal_pending(current))
318 (STp->buffer)->syscall_result = (-EINTR);
319 else
320 (STp->buffer)->syscall_result = (-EBUSY);
321 return NULL;
322 }
323 }
324
325 if (SRpnt->sr_device->scsi_level <= SCSI_2)
326 cmd[1] |= (SRpnt->sr_device->lun << 5) & 0xe0;
327 init_completion(&STp->wait);
328 SRpnt->sr_use_sg = (bytes > (STp->buffer)->sg[0].length) ?
329 (STp->buffer)->use_sg : 0;
330 if (SRpnt->sr_use_sg) {
331 bp = (char *)&(STp->buffer->sg[0]);
332 if (STp->buffer->sg_segs < SRpnt->sr_use_sg)
333 SRpnt->sr_use_sg = STp->buffer->sg_segs;
334 }
335 else
336 bp = (STp->buffer)->b_data;
337 SRpnt->sr_data_direction = direction;
338 SRpnt->sr_cmd_len = 0;
339 SRpnt->sr_request.waiting = &(STp->wait);
340 SRpnt->sr_request.rq_status = RQ_SCSI_BUSY;
341 SRpnt->sr_request.rq_dev = STp->devt;
342
343 scsi_do_req(SRpnt, (void *)cmd, bp, bytes, osst_sleep_done, timeout, retries);
344
345 if (do_wait) {
346 wait_for_completion(SRpnt->sr_request.waiting);
347 SRpnt->sr_request.waiting = NULL;
348 STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
349#ifdef OSST_INJECT_ERRORS
350 if (STp->buffer->syscall_result == 0 &&
351 cmd[0] == READ_6 &&
352 cmd[4] &&
353 ( (++ inject % 83) == 29 ||
354 (STp->first_frame_position == 240
355 &&
356 ++repeat < 3))) {
357 printk(OSST_DEB_MSG "osst%d:D: Injecting read error\n", TAPE_NR(STp->devt));
358 STp->buffer->last_result_fatal = 1;
359 }
360#endif
361 }
362 return SRpnt;
363}
364
365
366
367static void osst_write_behind_check(OS_Scsi_Tape *STp)
368{
369 OSST_buffer * STbuffer;
370
371 STbuffer = STp->buffer;
372
373#if DEBUG
374 if (STp->write_pending)
375 STp->nbr_waits++;
376 else
377 STp->nbr_finished++;
378#endif
379 wait_for_completion(&(STp->wait));
380 (STp->buffer)->last_SRpnt->sr_request.waiting = NULL;
381
382 STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
383
384 if ((STp->buffer)->syscall_result)
385 (STp->buffer)->syscall_result =
386 osst_write_error_recovery(STp, &((STp->buffer)->last_SRpnt), 1);
387 else
388 STp->first_frame_position++;
389
390 scsi_release_request((STp->buffer)->last_SRpnt);
391
392 if (STbuffer->writing < STbuffer->buffer_bytes)
393 printk(KERN_WARNING "osst:A: write_behind_check: something left in buffer!\n");
394
395 STbuffer->buffer_bytes -= STbuffer->writing;
396 STbuffer->writing = 0;
397
398 return;
399}
400
401
402
403
404
405
406
407static void osst_init_aux(OS_Scsi_Tape * STp, int frame_type, int frame_seq_number,
408 int logical_blk_num, int blk_sz, int blk_cnt)
409{
410 os_aux_t *aux = STp->buffer->aux;
411 os_partition_t *par = &aux->partition;
412 os_dat_t *dat = &aux->dat;
413
414 if (STp->raw) return;
415
416 memset(aux, 0, sizeof(*aux));
417 aux->format_id = htonl(0);
418 memcpy(aux->application_sig, "LIN4", 4);
419 aux->hdwr = htonl(0);
420 aux->frame_type = frame_type;
421
422 switch (frame_type) {
423 case OS_FRAME_TYPE_HEADER:
424 aux->update_frame_cntr = htonl(STp->update_frame_cntr);
425 par->partition_num = OS_CONFIG_PARTITION;
426 par->par_desc_ver = OS_PARTITION_VERSION;
427 par->wrt_pass_cntr = htons(0xffff);
428
429 par->first_frame_ppos = htonl(0);
430 par->last_frame_ppos = htonl(0xbb7);
431 aux->frame_seq_num = htonl(0);
432 aux->logical_blk_num_high = htonl(0);
433 aux->logical_blk_num = htonl(0);
434 aux->next_mark_ppos = htonl(STp->first_mark_ppos);
435 break;
436 case OS_FRAME_TYPE_DATA:
437 case OS_FRAME_TYPE_MARKER:
438 dat->dat_sz = 8;
439 dat->reserved1 = 0;
440 dat->entry_cnt = 1;
441 dat->reserved3 = 0;
442 dat->dat_list[0].blk_sz = htonl(blk_sz);
443 dat->dat_list[0].blk_cnt = htons(blk_cnt);
444 dat->dat_list[0].flags = frame_type==OS_FRAME_TYPE_MARKER?
445 OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
446 dat->dat_list[0].reserved = 0;
447 case OS_FRAME_TYPE_EOD:
448 aux->update_frame_cntr = htonl(0);
449 par->partition_num = OS_DATA_PARTITION;
450 par->par_desc_ver = OS_PARTITION_VERSION;
451 par->wrt_pass_cntr = htons(STp->wrt_pass_cntr);
452 par->first_frame_ppos = htonl(STp->first_data_ppos);
453 par->last_frame_ppos = htonl(STp->capacity);
454 aux->frame_seq_num = htonl(frame_seq_number);
455 aux->logical_blk_num_high = htonl(0);
456 aux->logical_blk_num = htonl(logical_blk_num);
457 break;
458 default: ;
459 }
460 aux->filemark_cnt = ntohl(STp->filemark_cnt);
461 aux->phys_fm = ntohl(0xffffffff);
462 aux->last_mark_ppos = ntohl(STp->last_mark_ppos);
463 aux->last_mark_lbn = ntohl(STp->last_mark_lbn);
464}
465
466
467
468
469static int osst_verify_frame(OS_Scsi_Tape * STp, int frame_seq_number, int quiet)
470{
471 os_aux_t * aux = STp->buffer->aux;
472 os_partition_t * par = &(aux->partition);
473 ST_partstat * STps = &(STp->ps[STp->partition]);
474 int dev = TAPE_NR(STp->devt);
475 int blk_cnt, blk_sz, i;
476
477 if (STp->raw) {
478 if (STp->buffer->syscall_result) {
479 for (i=0; i < STp->buffer->sg_segs; i++)
480 memset(STp->buffer->sg[i].address, 0, STp->buffer->sg[i].length);
481 strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
482 } else
483 STp->buffer->buffer_bytes = OS_FRAME_SIZE;
484 return 1;
485 }
486 if (STp->buffer->syscall_result) {
487#if DEBUG
488 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, read error\n", dev);
489#endif
490 return 0;
491 }
492 if (ntohl(aux->format_id) != 0) {
493#if DEBUG
494 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, format_id %u\n", dev, ntohl(aux->format_id));
495#endif
496 goto err_out;
497 }
498 if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
499 (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
500#if DEBUG
501 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, incorrect application signature\n", dev);
502#endif
503 goto err_out;
504 }
505 if (par->partition_num != OS_DATA_PARTITION) {
506 if (!STp->linux_media || STp->linux_media_version != 2) {
507#if DEBUG
508 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, partition num %d\n",
509 dev, par->partition_num);
510#endif
511 goto err_out;
512 }
513 }
514 if (par->par_desc_ver != OS_PARTITION_VERSION) {
515#if DEBUG
516 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, partition version %d\n", dev, par->par_desc_ver);
517#endif
518 goto err_out;
519 }
520 if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
521#if DEBUG
522 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n",
523 dev, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
524#endif
525 goto err_out;
526 }
527 if (aux->frame_type != OS_FRAME_TYPE_DATA &&
528 aux->frame_type != OS_FRAME_TYPE_EOD &&
529 aux->frame_type != OS_FRAME_TYPE_MARKER) {
530 if (!quiet)
531#if DEBUG
532 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, frame type %x\n", dev, aux->frame_type);
533#endif
534 goto err_out;
535 }
536 if (aux->frame_type == OS_FRAME_TYPE_EOD &&
537 STp->first_frame_position < STp->eod_frame_ppos) {
538 printk(KERN_INFO "osst%d:I: Skipping premature EOD frame %d\n", dev,
539 STp->first_frame_position);
540 goto err_out;
541 }
542 STp->frame_in_buffer = 1;
543
544 if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
545 if (!quiet)
546#if DEBUG
547 printk(OSST_DEB_MSG "osst%d:D: Skipping frame, sequence number %u (expected %d)\n",
548 dev, ntohl(aux->frame_seq_num), frame_seq_number);
549#endif
550 goto err_out;
551 }
552 if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
553 STps->eof = ST_FM_HIT;
554
555 i = ntohl(aux->filemark_cnt);
556 if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
557 STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
558#if DEBUG
559 printk(OSST_DEB_MSG "osst%d:D: %s filemark %d at frame pos %d\n", dev,
560 STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
561 i, STp->first_frame_position - 1);
562#endif
563 STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
564 if (i >= STp->filemark_cnt)
565 STp->filemark_cnt = i+1;
566 }
567 }
568 if (aux->frame_type == OS_FRAME_TYPE_EOD) {
569 STps->eof = ST_EOD_1;
570 }
571 if (aux->frame_type == OS_FRAME_TYPE_DATA) {
572 blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
573 blk_sz = ntohl(aux->dat.dat_list[0].blk_sz);
574 STp->buffer->buffer_bytes = blk_cnt * blk_sz;
575 STp->buffer->read_pointer = 0;
576
577
578 if (STp->block_size != blk_sz && blk_sz > 0) {
579 printk(KERN_INFO
580 "osst%d:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
581 dev, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
582 STp->block_size<1024?STp->block_size:STp->block_size/1024,
583 STp->block_size<1024?'b':'k');
584 STp->block_size = blk_sz;
585 STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
586 }
587 STps->eof = ST_NOEOF;
588 }
589 STp->frame_seq_number = ntohl(aux->frame_seq_num);
590 STp->logical_blk_num = ntohl(aux->logical_blk_num);
591 return 1;
592
593err_out:
594 if (STp->read_error_frame == 0)
595 STp->read_error_frame = STp->first_frame_position - 1;
596 return 0;
597}
598
599
600
601
602static int osst_wait_ready(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout)
603{
604 unsigned char cmd[MAX_COMMAND_SIZE];
605 Scsi_Request * SRpnt;
606 long startwait = jiffies;
607#if DEBUG
608 int dbg = debugging;
609 int dev = TAPE_NR(STp->devt);
610
611 printk(OSST_DEB_MSG "osst%d:D: Reached onstream wait ready\n", dev);
612#endif
613
614 memset(cmd, 0, MAX_COMMAND_SIZE);
615 cmd[0] = TEST_UNIT_READY;
616
617 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
618 *aSRpnt = SRpnt;
619 if (!SRpnt) return (-EBUSY);
620
621 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
622 (( SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 &&
623 (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8) ) ||
624 ( SRpnt->sr_sense_buffer[2] == 6 && SRpnt->sr_sense_buffer[12] == 0x28 &&
625 SRpnt->sr_sense_buffer[13] == 0 ) )) {
626#if DEBUG
627 if (debugging) {
628 printk(OSST_DEB_MSG "osst%d:D: Sleeping in onstream wait ready\n", dev);
629 printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev);
630 debugging = 0;
631 }
632#endif
633 set_current_state(TASK_INTERRUPTIBLE);
634 schedule_timeout(HZ / 10);
635
636 memset(cmd, 0, MAX_COMMAND_SIZE);
637 cmd[0] = TEST_UNIT_READY;
638
639 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
640 }
641 *aSRpnt = SRpnt;
642#if DEBUG
643 debugging = dbg;
644#endif
645 if ( STp->buffer->syscall_result &&
646 osst_write_error_recovery(STp, aSRpnt, 0) ) {
647#if DEBUG
648 printk(OSST_DEB_MSG "osst%d:D: Abnormal exit from onstream wait ready\n", dev);
649 printk(OSST_DEB_MSG "osst%d:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", dev,
650 STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2],
651 SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
652#endif
653 return (-EIO);
654 }
655#if DEBUG
656 printk(OSST_DEB_MSG "osst%d:D: Normal exit from onstream wait ready\n", dev);
657#endif
658 return 0;
659}
660
661
662
663
664static int osst_wait_for_medium(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned timeout)
665{
666 unsigned char cmd[MAX_COMMAND_SIZE];
667 Scsi_Request * SRpnt;
668 long startwait = jiffies;
669#if DEBUG
670 int dbg = debugging;
671 int dev = TAPE_NR(STp->devt);
672
673 printk(OSST_DEB_MSG "osst%d:D: Reached onstream wait for medium\n", dev);
674#endif
675
676 memset(cmd, 0, MAX_COMMAND_SIZE);
677 cmd[0] = TEST_UNIT_READY;
678
679 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
680 *aSRpnt = SRpnt;
681 if (!SRpnt) return (-EBUSY);
682
683 while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
684 SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 0x3a &&
685 SRpnt->sr_sense_buffer[13] == 0 ) {
686#if DEBUG
687 if (debugging) {
688 printk(OSST_DEB_MSG "osst%d:D: Sleeping in onstream wait medium\n", dev);
689 printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev);
690 debugging = 0;
691 }
692#endif
693 set_current_state(TASK_INTERRUPTIBLE);
694 schedule_timeout(HZ / 10);
695
696 memset(cmd, 0, MAX_COMMAND_SIZE);
697 cmd[0] = TEST_UNIT_READY;
698
699 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
700 }
701 *aSRpnt = SRpnt;
702#if DEBUG
703 debugging = dbg;
704#endif
705 if ( STp->buffer->syscall_result && SRpnt->sr_sense_buffer[2] != 2 &&
706 SRpnt->sr_sense_buffer[12] != 4 && SRpnt->sr_sense_buffer[13] == 1) {
707#if DEBUG
708 printk(OSST_DEB_MSG "osst%d:D: Abnormal exit from onstream wait medium\n", dev);
709 printk(OSST_DEB_MSG "osst%d:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", dev,
710 STp->buffer->syscall_result, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2],
711 SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
712#endif
713 return 0;
714 }
715#if DEBUG
716 printk(OSST_DEB_MSG "osst%d:D: Normal exit from onstream wait medium\n", dev);
717#endif
718 return 1;
719}
720
721static int osst_position_tape_and_confirm(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame)
722{
723 int retval;
724
725 osst_wait_ready(STp, aSRpnt, 15 * 60);
726 retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
727 if (retval) return (retval);
728 osst_wait_ready(STp, aSRpnt, 15 * 60);
729 return (osst_get_frame_position(STp, aSRpnt));
730}
731
732
733
734
735static int osst_flush_drive_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
736{
737 unsigned char cmd[MAX_COMMAND_SIZE];
738 Scsi_Request * SRpnt;
739
740 int result = 0;
741#if DEBUG
742 int dev = TAPE_NR(STp->devt);
743
744 printk(OSST_DEB_MSG "osst%d:D: Reached onstream flush drive buffer (write filemark)\n", dev);
745#endif
746
747 memset(cmd, 0, MAX_COMMAND_SIZE);
748 cmd[0] = WRITE_FILEMARKS;
749 cmd[1] = 1;
750
751 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_WRITE_RETRIES, TRUE);
752 *aSRpnt = SRpnt;
753 if (!SRpnt) return (-EBUSY);
754
755 if ((STp->buffer)->syscall_result)
756 result = osst_write_error_recovery(STp, aSRpnt, 0);
757
758 result |= osst_wait_ready(STp, aSRpnt, 5 * 60);
759 STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
760 return (result);
761}
762
763#define OSST_POLL_PER_SEC 10
764static int osst_wait_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int curr, int minlast, int to)
765{
766 long startwait = jiffies;
767 int dev = TAPE_NR(STp->devt);
768#if DEBUG
769 char notyetprinted = 1;
770#endif
771 if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
772 printk(KERN_ERR "osst%i:A: Waiting for frame without having initialized read!\n", dev);
773
774 while (time_before (jiffies, startwait + to*HZ))
775 {
776 int result;
777 result = osst_get_frame_position (STp, aSRpnt);
778 if (result == -EIO)
779 if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
780 return 0;
781 if (result < 0) break;
782 if (STp->first_frame_position == curr &&
783 ((minlast < 0 &&
784 (signed)STp->last_frame_position > (signed)curr + minlast) ||
785 (minlast >= 0 && STp->cur_frames > minlast)
786 ) && result >= 0)
787 {
788#if DEBUG
789 if (debugging || jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC)
790 printk (OSST_DEB_MSG
791 "osst%d:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
792 dev, curr, curr+minlast, STp->first_frame_position,
793 STp->last_frame_position, STp->cur_frames,
794 result, (jiffies-startwait)/HZ,
795 (((jiffies-startwait)%HZ)*10)/HZ);
796#endif
797 return 0;
798 }
799#if DEBUG
800 if (jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC && notyetprinted)
801 {
802 printk (OSST_DEB_MSG "osst%d:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
803 dev, curr, curr+minlast, STp->first_frame_position,
804 STp->last_frame_position, STp->cur_frames, result);
805 notyetprinted--;
806 }
807#endif
808 set_current_state(TASK_INTERRUPTIBLE);
809 schedule_timeout (HZ / OSST_POLL_PER_SEC);
810 }
811#if DEBUG
812 printk (OSST_DEB_MSG "osst%d:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
813 dev, curr, curr+minlast, STp->first_frame_position,
814 STp->last_frame_position, STp->cur_frames,
815 (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
816#endif
817 return -EBUSY;
818}
819
820
821
822
823static int osst_read_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int timeout)
824{
825 unsigned char cmd[MAX_COMMAND_SIZE];
826 Scsi_Request * SRpnt;
827 int retval = 0;
828#if DEBUG
829 os_aux_t * aux = STp->buffer->aux;
830 int dev = TAPE_NR(STp->devt);
831#endif
832
833
834 if (STp->poll)
835 retval = osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout);
836#if 0
837 printk ("osst_read: wait for frame returned %i\n", retval);
838#endif
839
840 memset(cmd, 0, MAX_COMMAND_SIZE);
841 cmd[0] = READ_6;
842 cmd[1] = 1;
843 cmd[4] = 1;
844
845#if DEBUG
846 if (debugging)
847 printk(OSST_DEB_MSG "osst%d:D: Reading frame from OnStream tape\n", dev);
848#endif
849 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
850 STp->timeout, MAX_RETRIES, TRUE);
851 *aSRpnt = SRpnt;
852 if (!SRpnt)
853 return (-EBUSY);
854
855 if ((STp->buffer)->syscall_result) {
856 retval = 1;
857 if (STp->read_error_frame == 0) {
858 STp->read_error_frame = STp->first_frame_position;
859#if DEBUG
860 printk(OSST_DEB_MSG "osst%d:D: Recording read error at %d\n", dev, STp->read_error_frame);
861#endif
862 }
863#if DEBUG
864 if (debugging)
865 printk(OSST_DEB_MSG "osst%d:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
866 dev,
867 SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[1],
868 SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[3],
869 SRpnt->sr_sense_buffer[4], SRpnt->sr_sense_buffer[5],
870 SRpnt->sr_sense_buffer[6], SRpnt->sr_sense_buffer[7]);
871#endif
872 }
873 else
874 STp->first_frame_position++;
875#if DEBUG
876 if (debugging) {
877 printk(OSST_DEB_MSG
878 "osst%d:D: AUX: %c%c%c%c UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", dev,
879 aux->application_sig[0], aux->application_sig[1],
880 aux->application_sig[2], aux->application_sig[3],
881 ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
882 aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
883 aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL",
884 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
885 ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
886 if (aux->frame_type==2)
887 printk(OSST_DEB_MSG "osst%d:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", dev,
888 ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
889 printk(OSST_DEB_MSG "osst%d:D: Exit read frame from OnStream tape with code %d\n", dev, retval);
890 }
891#endif
892 return (retval);
893}
894
895static int osst_initiate_read(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
896{
897 ST_partstat * STps = &(STp->ps[STp->partition]);
898 Scsi_Request * SRpnt ;
899 unsigned char cmd[MAX_COMMAND_SIZE];
900 int retval = 0;
901#if DEBUG
902 int dev = TAPE_NR(STp->devt);
903#endif
904
905 if (STps->rw != ST_READING) {
906 if (STps->rw == ST_WRITING) {
907 osst_flush_write_buffer(STp, aSRpnt);
908 osst_flush_drive_buffer(STp, aSRpnt);
909 }
910 STps->rw = ST_READING;
911 STp->frame_in_buffer = 0;
912
913
914
915
916
917 memset(cmd, 0, MAX_COMMAND_SIZE);
918 cmd[0] = READ_6;
919 cmd[1] = 1;
920
921#if DEBUG
922 printk(OSST_DEB_MSG "osst%d:D: Start Read Ahead on OnStream tape\n", dev);
923#endif
924 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_RETRIES, TRUE);
925 *aSRpnt = SRpnt;
926 retval = STp->buffer->syscall_result;
927 }
928
929 return retval;
930}
931
932static int osst_get_logical_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int frame_seq_number, int quiet)
933{
934 ST_partstat * STps = &(STp->ps[STp->partition]);
935 int dev = TAPE_NR(STp->devt);
936 int cnt = 0,
937 bad = 0,
938 past = 0,
939 x,
940 position;
941
942
943
944
945 while (1) {
946 if (cnt++ > 400) {
947 printk(KERN_ERR "osst%d:E: Couldn't find logical frame %d, aborting\n",
948 dev, frame_seq_number);
949 if (STp->read_error_frame) {
950 osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
951#if DEBUG
952 printk(OSST_DEB_MSG "osst%d:D: Repositioning tape to bad frame %d\n",
953 dev, STp->read_error_frame);
954#endif
955 STp->read_error_frame = 0;
956 }
957 return (-EIO);
958 }
959#if DEBUG
960 if (debugging)
961 printk(OSST_DEB_MSG "osst%d:D: Looking for frame %d, attempt %d\n",
962 dev, frame_seq_number, cnt);
963#endif
964 if ( osst_initiate_read(STp, aSRpnt)
965 || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
966 if (STp->raw)
967 return (-EIO);
968 position = osst_get_frame_position(STp, aSRpnt);
969 if (position >= 0xbae && position < 0xbb8)
970 position = 0xbb8;
971 else if (position > STp->eod_frame_ppos || ++bad == 10) {
972 position = STp->read_error_frame - 1;
973 }
974 else {
975 position += 39;
976 cnt += 20;
977 }
978#if DEBUG
979 printk(OSST_DEB_MSG "osst%d:D: Bad frame detected, positioning tape to block %d\n",
980 dev, position);
981#endif
982 osst_set_frame_position(STp, aSRpnt, position, 0);
983 continue;
984 }
985 if (osst_verify_frame(STp, frame_seq_number, quiet))
986 break;
987 if (osst_verify_frame(STp, -1, quiet)) {
988 x = ntohl(STp->buffer->aux->frame_seq_num);
989 if (STp->fast_open) {
990 printk(KERN_WARNING
991 "osst%d:W: Found logical frame %d instead of %d after fast open\n",
992 dev, x, frame_seq_number);
993 STp->header_ok = 0;
994 STp->read_error_frame = 0;
995 return (-EIO);
996 }
997 if (x > frame_seq_number) {
998 if (++past > 3) {
999
1000 position = STp->read_error_frame - 1;
1001 }
1002 else {
1003 position = osst_get_frame_position(STp, aSRpnt)
1004 + frame_seq_number - x - 1;
1005
1006 if (STp->first_frame_position >= 3000 && position < 3000)
1007 position -= 10;
1008 }
1009#if DEBUG
1010 printk(OSST_DEB_MSG
1011 "osst%d:D: Found logical frame %d while looking for %d: back up %d\n",
1012 dev, x, frame_seq_number,
1013 STp->first_frame_position - position);
1014#endif
1015 osst_set_frame_position(STp, aSRpnt, position, 0);
1016 cnt += 10;
1017 }
1018 else
1019 past = 0;
1020 }
1021 if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1022#if DEBUG
1023 printk(OSST_DEB_MSG "osst%d:D: Skipping config partition\n", dev);
1024#endif
1025 osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1026 cnt--;
1027 }
1028 STp->frame_in_buffer = 0;
1029 }
1030 if (cnt > 1) {
1031 STp->recover_count++;
1032 STp->recover_erreg++;
1033 printk(KERN_WARNING "osst%d:I: Don't worry, Read error at position %d recovered\n",
1034 dev, STp->read_error_frame);
1035 }
1036 STp->read_count++;
1037
1038#if DEBUG
1039 if (debugging || STps->eof)
1040 printk(OSST_DEB_MSG
1041 "osst%d:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1042 dev, frame_seq_number, STp->frame_seq_number, STps->eof);
1043#endif
1044 STp->fast_open = FALSE;
1045 STp->read_error_frame = 0;
1046 return (STps->eof);
1047}
1048
1049static int osst_seek_logical_blk(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int logical_blk_num)
1050{
1051 ST_partstat * STps = &(STp->ps[STp->partition]);
1052 int dev = TAPE_NR(STp->devt);
1053 int retries = 0;
1054 int frame_seq_estimate, ppos_estimate, move;
1055
1056 if (logical_blk_num < 0) logical_blk_num = 0;
1057#if DEBUG
1058 printk(OSST_DEB_MSG "osst%d:D: Seeking logical block %d (now at %d, size %d%c)\n",
1059 dev, logical_blk_num, STp->logical_blk_num,
1060 STp->block_size<1024?STp->block_size:STp->block_size/1024,
1061 STp->block_size<1024?'b':'k');
1062#endif
1063
1064 if (STps->drv_block >= 0) {
1065 move = logical_blk_num - STp->logical_blk_num;
1066 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1067 move /= (OS_DATA_SIZE / STp->block_size);
1068 frame_seq_estimate = STp->frame_seq_number + move;
1069 } else
1070 frame_seq_estimate = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1071
1072 if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1073 else ppos_estimate = frame_seq_estimate + 20;
1074 while (++retries < 10) {
1075 if (ppos_estimate > STp->eod_frame_ppos-2) {
1076 frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1077 ppos_estimate = STp->eod_frame_ppos - 2;
1078 }
1079 if (frame_seq_estimate < 0) {
1080 frame_seq_estimate = 0;
1081 ppos_estimate = 10;
1082 }
1083 osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1084 if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1085
1086 if (logical_blk_num < STp->logical_blk_num ||
1087 logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1088 if (STps->eof == ST_FM_HIT)
1089 move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1090 else {
1091 move = logical_blk_num - STp->logical_blk_num;
1092 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1093 move /= (OS_DATA_SIZE / STp->block_size);
1094 }
1095#if DEBUG
1096 printk(OSST_DEB_MSG
1097 "osst%d:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1098 dev, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1099 STp->logical_blk_num, logical_blk_num, move);
1100#endif
1101 frame_seq_estimate += move;
1102 ppos_estimate += move;
1103 continue;
1104 } else {
1105 STp->buffer->read_pointer = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1106 STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1107 STp->logical_blk_num = logical_blk_num;
1108#if DEBUG
1109 printk(OSST_DEB_MSG
1110 "osst%d:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1111 dev, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer,
1112 STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size,
1113 STp->block_size);
1114#endif
1115 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1116 if (STps->eof == ST_FM_HIT) {
1117 STps->drv_file++;
1118 STps->drv_block = 0;
1119 } else {
1120 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1121 STp->logical_blk_num -
1122 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1123 -1;
1124 }
1125 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1126 return 0;
1127 }
1128 }
1129 if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1130 goto error;
1131
1132#if DEBUG
1133 printk(OSST_DEB_MSG "osst%d:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n",
1134 dev, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate,
1135 STp->logical_blk_num, logical_blk_num);
1136#endif
1137 if (frame_seq_estimate != STp->frame_seq_number)
1138 ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1139 else
1140 break;
1141 }
1142error:
1143 printk(KERN_ERR "osst%d:E: Couldn't seek to logical block %d (at %d), %d retries\n",
1144 dev, logical_blk_num, STp->logical_blk_num, retries);
1145 return (-EIO);
1146}
1147
1148
1149
1150
1151
1152
1153#define OSST_FRAME_SHIFT 6
1154#define OSST_SECTOR_SHIFT 9
1155#define OSST_SECTOR_MASK 0x03F
1156
1157static int osst_get_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
1158{
1159 int sector;
1160#if DEBUG
1161 int dev = TAPE_NR(STp->devt);
1162
1163 printk(OSST_DEB_MSG
1164 "osst%d:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1165 dev, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1166 STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block,
1167 STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1168 STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1169 STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1170#endif
1171
1172 if (STp->ps[STp->partition].drv_block >= 0) {
1173 sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1174 STp->first_frame_position) << OSST_FRAME_SHIFT;
1175 if (STp->ps[STp->partition].rw == ST_WRITING)
1176 sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1177 else
1178 sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1179 } else {
1180 sector = osst_get_frame_position(STp, aSRpnt);
1181 if (sector > 0)
1182 sector <<= OSST_FRAME_SHIFT;
1183 }
1184 return sector;
1185}
1186
1187static int osst_seek_sector(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int sector)
1188{
1189 ST_partstat * STps = &(STp->ps[STp->partition]);
1190 int frame = sector >> OSST_FRAME_SHIFT,
1191 offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT,
1192 r;
1193#if DEBUG
1194 int dev = TAPE_NR(STp->devt);
1195
1196 printk(OSST_DEB_MSG "osst%d:D: Seeking sector %d in frame %d at offset %d\n",
1197 dev, sector, frame, offset);
1198#endif
1199 if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1200
1201 if (frame <= STp->first_data_ppos) {
1202 STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1203 return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1204 }
1205 r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1206 if (r < 0) return r;
1207
1208 r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1209 if (r < 0) return r;
1210
1211 if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1212
1213 if (offset) {
1214 STp->logical_blk_num += offset / STp->block_size;
1215 STp->buffer->read_pointer = offset;
1216 STp->buffer->buffer_bytes -= offset;
1217 } else {
1218 STp->frame_seq_number++;
1219 STp->frame_in_buffer = 0;
1220 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1221 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
1222 }
1223 STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1224 if (STps->eof == ST_FM_HIT) {
1225 STps->drv_file++;
1226 STps->drv_block = 0;
1227 } else {
1228 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1229 STp->logical_blk_num -
1230 (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1231 -1;
1232 }
1233 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1234#if DEBUG
1235 printk(OSST_DEB_MSG
1236 "osst%d:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1237 dev, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1238 STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1239#endif
1240 return 0;
1241}
1242
1243
1244
1245
1246
1247
1248
1249
1250static int osst_read_back_buffer_and_rewrite(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
1251 unsigned int frame, unsigned int skip, int pending)
1252{
1253 Scsi_Request * SRpnt = * aSRpnt;
1254 unsigned char * buffer, * p;
1255 unsigned char cmd[MAX_COMMAND_SIZE];
1256 int flag, new_frame, i;
1257 int nframes = STp->cur_frames;
1258 int blks_per_frame = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1259 int frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1260 - (nframes + pending - 1);
1261 int logical_blk_num = ntohl(STp->buffer->aux->logical_blk_num)
1262 - (nframes + pending - 1) * blks_per_frame;
1263 int dev = TAPE_NR(STp->devt);
1264 long startwait = jiffies;
1265#if DEBUG
1266 int dbg = debugging;
1267#endif
1268
1269 if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1270 return (-EIO);
1271
1272 printk(KERN_INFO "osst%d:I: Reading back %d frames from drive buffer%s\n",
1273 dev, nframes, pending?" and one that was pending":"");
1274
1275 osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1276#if DEBUG
1277 if (pending && debugging)
1278 printk(OSST_DEB_MSG "osst%d:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1279 dev, frame_seq_number + nframes,
1280 logical_blk_num + nframes * blks_per_frame,
1281 p[0], p[1], p[2], p[3]);
1282#endif
1283 for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1284
1285 memset(cmd, 0, MAX_COMMAND_SIZE);
1286 cmd[0] = 0x3C;
1287 cmd[1] = 6;
1288 cmd[7] = 32768 >> 8;
1289 cmd[8] = 32768 & 0xff;
1290
1291 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_READ,
1292 STp->timeout, MAX_RETRIES, TRUE);
1293
1294 if ((STp->buffer)->syscall_result || !SRpnt) {
1295 printk(KERN_ERR "osst%d:E: Failed to read frame back from OnStream buffer\n", dev);
1296 vfree((void *)buffer);
1297 *aSRpnt = SRpnt;
1298 return (-EIO);
1299 }
1300 osst_copy_from_buffer(STp->buffer, p);
1301#if DEBUG
1302 if (debugging)
1303 printk(OSST_DEB_MSG "osst%d:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1304 dev, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1305#endif
1306 }
1307 *aSRpnt = SRpnt;
1308 osst_get_frame_position(STp, aSRpnt);
1309
1310#if DEBUG
1311 printk(OSST_DEB_MSG "osst%d:D: Frames left in buffer: %d\n", dev, STp->cur_frames);
1312#endif
1313
1314
1315
1316 for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1317
1318 if (flag) {
1319 if (STp->write_type == OS_WRITE_HEADER) {
1320 i += skip;
1321 p += skip * OS_DATA_SIZE;
1322 }
1323 else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1324 new_frame = 3000-i;
1325 else
1326 new_frame += skip;
1327#if DEBUG
1328 printk(OSST_DEB_MSG "osst%d:D: Position to frame %d, write fseq %d\n",
1329 dev, new_frame+i, frame_seq_number+i);
1330#endif
1331 osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1332 osst_wait_ready(STp, aSRpnt, 60);
1333 osst_get_frame_position(STp, aSRpnt);
1334 SRpnt = * aSRpnt;
1335
1336 if (new_frame > frame + 1000) {
1337 printk(KERN_ERR "osst%d:E: Failed to find writable tape media\n", dev);
1338 vfree((void *)buffer);
1339 return (-EIO);
1340 }
1341 flag = 0;
1342 if ( i >= nframes + pending ) break;
1343 }
1344 osst_copy_to_buffer(STp->buffer, p);
1345
1346
1347
1348 osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1349 logical_blk_num + i*blks_per_frame,
1350 ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1351 memset(cmd, 0, MAX_COMMAND_SIZE);
1352 cmd[0] = WRITE_6;
1353 cmd[1] = 1;
1354 cmd[4] = 1;
1355
1356#if DEBUG
1357 if (debugging)
1358 printk(OSST_DEB_MSG
1359 "osst%d:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1360 dev, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1361 p[0], p[1], p[2], p[3]);
1362#endif
1363 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,
1364 STp->timeout, MAX_WRITE_RETRIES, TRUE);
1365
1366 if (STp->buffer->syscall_result)
1367 flag = 1;
1368 else {
1369 p += OS_DATA_SIZE; i++;
1370
1371
1372 if ( i == nframes + pending ) {
1373#if DEBUG
1374 printk(OSST_DEB_MSG "osst%d:D: Check re-write successful\n", dev);
1375#endif
1376 memset(cmd, 0, MAX_COMMAND_SIZE);
1377 cmd[0] = WRITE_FILEMARKS;
1378 cmd[1] = 1;
1379 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
1380 STp->timeout, MAX_WRITE_RETRIES, TRUE);
1381#if DEBUG
1382 if (debugging) {
1383 printk(OSST_DEB_MSG "osst%d:D: Sleeping in re-write wait ready\n", dev);
1384 printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev);
1385 debugging = 0;
1386 }
1387#endif
1388 flag = STp->buffer->syscall_result;
1389 while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1390
1391 memset(cmd, 0, MAX_COMMAND_SIZE);
1392 cmd[0] = TEST_UNIT_READY;
1393
1394 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout,
1395 MAX_READY_RETRIES, TRUE);
1396
1397 if (SRpnt->sr_sense_buffer[2] == 2 && SRpnt->sr_sense_buffer[12] == 4 &&
1398 (SRpnt->sr_sense_buffer[13] == 1 || SRpnt->sr_sense_buffer[13] == 8)) {
1399
1400 schedule_timeout(HZ / 10);
1401 continue;
1402 }
1403 if (STp->buffer->syscall_result)
1404 flag = 1;
1405 break;
1406 }
1407#if DEBUG
1408 debugging = dbg;
1409 printk(OSST_DEB_MSG "osst%d:D: Wait re-write finished\n", dev);
1410#endif
1411 }
1412 }
1413 *aSRpnt = SRpnt;
1414 if (flag) {
1415 if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 &&
1416 SRpnt->sr_sense_buffer[12] == 0 &&
1417 SRpnt->sr_sense_buffer[13] == 2) {
1418 printk(KERN_ERR "osst%d:E: Volume overflow in write error recovery\n", dev);
1419 vfree((void *)buffer);
1420 return (-EIO);
1421 }
1422 i = ((SRpnt->sr_sense_buffer[3] << 24) |
1423 (SRpnt->sr_sense_buffer[4] << 16) |
1424 (SRpnt->sr_sense_buffer[5] << 8) |
1425 SRpnt->sr_sense_buffer[6] ) - new_frame;
1426 p = &buffer[i * OS_DATA_SIZE];
1427#if DEBUG
1428 printk(OSST_DEB_MSG "osst%d:D: Additional write error at %d\n", dev, new_frame+i);
1429#endif
1430 osst_get_frame_position(STp, aSRpnt);
1431#if DEBUG
1432 printk(OSST_DEB_MSG "osst%d:D: reported frame positions: host = %d, tape = %d\n",
1433 dev, STp->first_frame_position, STp->last_frame_position);
1434#endif
1435 }
1436 }
1437 if (!pending)
1438 osst_copy_to_buffer(STp->buffer, p);
1439 vfree((void *)buffer);
1440 return 0;
1441}
1442
1443static int osst_reposition_and_retry(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
1444 unsigned int frame, unsigned int skip, int pending)
1445{
1446 unsigned char cmd[MAX_COMMAND_SIZE];
1447 Scsi_Request * SRpnt;
1448 int dev = TAPE_NR(STp->devt);
1449 int expected = 0;
1450 int attempts = 1000 / skip;
1451 int flag = 1;
1452 long startwait = jiffies;
1453#if DEBUG
1454 int dbg = debugging;
1455#endif
1456
1457 while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1458 if (flag) {
1459#if DEBUG
1460 debugging = dbg;
1461#endif
1462 if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1463 frame = 3000-skip;
1464 expected = frame+skip+STp->cur_frames+pending;
1465#if DEBUG
1466 printk(OSST_DEB_MSG "osst%d:D: Position to fppos %d, re-write from fseq %d\n",
1467 dev, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1468#endif
1469 osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1470 flag = 0;
1471 attempts--;
1472 }
1473 if (osst_get_frame_position(STp, aSRpnt) < 0) {
1474#if DEBUG
1475 printk(OSST_DEB_MSG "osst%d:D: Addl error, host %d, tape %d, buffer %d\n",
1476 dev, STp->first_frame_position,
1477 STp->last_frame_position, STp->cur_frames);
1478#endif
1479 frame = STp->last_frame_position;
1480 flag = 1;
1481 continue;
1482 }
1483 if (pending && STp->cur_frames < 50) {
1484
1485 memset(cmd, 0, MAX_COMMAND_SIZE);
1486 cmd[0] = WRITE_6;
1487 cmd[1] = 1;
1488 cmd[4] = 1;
1489#if DEBUG
1490 printk(OSST_DEB_MSG "osst%d:D: About to write pending fseq %d at fppos %d\n",
1491 dev, STp->frame_seq_number-1, STp->first_frame_position);
1492#endif
1493 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE,
1494 STp->timeout, MAX_WRITE_RETRIES, TRUE);
1495 *aSRpnt = SRpnt;
1496
1497 if (STp->buffer->syscall_result) {
1498 if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) == 13 &&
1499 SRpnt->sr_sense_buffer[12] == 0 &&
1500 SRpnt->sr_sense_buffer[13] == 2) {
1501 printk(KERN_ERR
1502 "osst%d:E: Volume overflow in write error recovery\n",
1503 dev);
1504 break;
1505 }
1506 flag = 1;
1507 }
1508 else
1509 pending = 0;
1510
1511 continue;
1512 }
1513 if (STp->cur_frames == 0) {
1514#if DEBUG
1515 debugging = dbg;
1516 printk(OSST_DEB_MSG "osst%d:D: Wait re-write finished\n", dev);
1517#endif
1518 if (STp->first_frame_position != expected) {
1519 printk(KERN_ERR "osst%d:A: Actual position %d - expected %d\n",
1520 dev, STp->first_frame_position, expected);
1521 return (-EIO);
1522 }
1523 return 0;
1524 }
1525#if DEBUG
1526 if (debugging) {
1527 printk(OSST_DEB_MSG "osst%d:D: Sleeping in re-write wait ready\n", dev);
1528 printk(OSST_DEB_MSG "osst%d:D: Turning off debugging for a while\n", dev);
1529 debugging = 0;
1530 }
1531#endif
1532 schedule_timeout(HZ / 10);
1533 }
1534 printk(KERN_ERR "osst%d:E: Failed to find valid tape media\n", dev);
1535#if DEBUG
1536 debugging = dbg;
1537#endif
1538 return (-EIO);
1539}
1540
1541
1542
1543
1544
1545static int osst_write_error_recovery(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int pending)
1546{
1547 Scsi_Request * SRpnt = * aSRpnt;
1548 ST_partstat * STps = & STp->ps[STp->partition];
1549 int dev = TAPE_NR(STp->devt);
1550 int retval = 0;
1551 int rw_state;
1552 unsigned int frame, skip;
1553
1554 rw_state = STps->rw;
1555
1556 if ((SRpnt->sr_sense_buffer[ 2] & 0x0f) != 3
1557 || SRpnt->sr_sense_buffer[12] != 12
1558 || SRpnt->sr_sense_buffer[13] != 0) {
1559#if DEBUG
1560 printk(OSST_DEB_MSG "osst%d:D: Write error recovery cannot handle %02x:%02x:%02x\n", dev,
1561 SRpnt->sr_sense_buffer[2], SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
1562#endif
1563 return (-EIO);
1564 }
1565 frame = (SRpnt->sr_sense_buffer[3] << 24) |
1566 (SRpnt->sr_sense_buffer[4] << 16) |
1567 (SRpnt->sr_sense_buffer[5] << 8) |
1568 SRpnt->sr_sense_buffer[6];
1569 skip = SRpnt->sr_sense_buffer[9];
1570
1571#if DEBUG
1572 printk(OSST_DEB_MSG "osst%d:D: Detected physical bad frame at %u, advised to skip %d\n", dev, frame, skip);
1573#endif
1574 osst_get_frame_position(STp, aSRpnt);
1575#if DEBUG
1576 printk(OSST_DEB_MSG "osst%d:D: reported frame positions: host = %d, tape = %d\n",
1577 dev, STp->first_frame_position, STp->last_frame_position);
1578#endif
1579 switch (STp->write_type) {
1580 case OS_WRITE_DATA:
1581 case OS_WRITE_EOD:
1582 case OS_WRITE_NEW_MARK:
1583 printk(KERN_WARNING
1584 "osst%d:I: Relocating %d buffered logical frames from position %u to %u\n",
1585 dev, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1586 if (STp->os_fw_rev >= 10600)
1587 retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1588 else
1589 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1590 printk(KERN_WARNING "osst%d:%s: %sWrite error%srecovered\n", dev,
1591 retval?"E" :"I",
1592 retval?"" :"Don't worry, ",
1593 retval?" not ":" ");
1594 break;
1595 case OS_WRITE_LAST_MARK:
1596 printk(KERN_ERR "osst%d:E: Bad frame in update last marker, fatal\n", dev);
1597 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1598 retval = -EIO;
1599 break;
1600 case OS_WRITE_HEADER:
1601 printk(KERN_WARNING "osst%d:I: Bad frame in header partition, skipped\n", dev);
1602 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1603 break;
1604 default:
1605 printk(KERN_INFO "osst%d:I: Bad frame in filler, ignored\n", dev);
1606 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1607 }
1608 osst_get_frame_position(STp, aSRpnt);
1609#if DEBUG
1610 printk(OSST_DEB_MSG "osst%d:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n",
1611 dev, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1612 printk(OSST_DEB_MSG "osst%d:D: next logical frame to write: %d\n", dev, STp->logical_blk_num);
1613#endif
1614 if (retval == 0) {
1615 STp->recover_count++;
1616 STp->recover_erreg++;
1617 }
1618 STps->rw = rw_state;
1619 return retval;
1620}
1621
1622static int osst_space_over_filemarks_backward(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
1623 int mt_op, int mt_count)
1624{
1625 int dev = TAPE_NR(STp->devt);
1626 int cnt;
1627 int last_mark_ppos = -1;
1628
1629#if DEBUG
1630 printk(OSST_DEB_MSG "osst%d:D: Reached space_over_filemarks_backwards %d %d\n", dev, mt_op, mt_count);
1631#endif
1632 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1633#if DEBUG
1634 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_bwd\n", dev);
1635#endif
1636 return -EIO;
1637 }
1638 if (STp->linux_media_version >= 4) {
1639
1640
1641
1642 cnt = ntohl(STp->buffer->aux->filemark_cnt);
1643 if (STp->header_ok &&
1644 STp->header_cache != NULL &&
1645 (cnt - mt_count) >= 0 &&
1646 (cnt - mt_count) < OS_FM_TAB_MAX &&
1647 (cnt - mt_count) < STp->filemark_cnt &&
1648 STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1649
1650 last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1651#if DEBUG
1652 if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1653 printk(OSST_DEB_MSG "osst%d:D: Filemark lookup fail due to %s\n", dev,
1654 STp->header_cache == NULL?"lack of header cache":"count out of range");
1655 else
1656 printk(OSST_DEB_MSG "osst%d:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1657 dev, cnt,
1658 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1659 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1660 STp->buffer->aux->last_mark_ppos))?"match":"error",
1661 mt_count, last_mark_ppos);
1662#endif
1663 if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1664 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1665 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1666#if DEBUG
1667 printk(OSST_DEB_MSG
1668 "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev);
1669#endif
1670 return (-EIO);
1671 }
1672 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1673 printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n",
1674 dev, last_mark_ppos);
1675 return (-EIO);
1676 }
1677 if (mt_op == MTBSFM) {
1678 STp->frame_seq_number++;
1679 STp->frame_in_buffer = 0;
1680 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1681 }
1682 return 0;
1683 }
1684#if DEBUG
1685 printk(OSST_DEB_MSG "osst%d:D: Reverting to scan filemark backwards\n", dev);
1686#endif
1687 }
1688 cnt = 0;
1689 while (cnt != mt_count) {
1690 last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1691 if (last_mark_ppos == -1)
1692 return (-EIO);
1693#if DEBUG
1694 printk(OSST_DEB_MSG "osst%d:D: Positioning to last mark at %d\n", dev, last_mark_ppos);
1695#endif
1696 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1697 cnt++;
1698 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1699#if DEBUG
1700 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev);
1701#endif
1702 return (-EIO);
1703 }
1704 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1705 printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n",
1706 dev, last_mark_ppos);
1707 return (-EIO);
1708 }
1709 }
1710 if (mt_op == MTBSFM) {
1711 STp->frame_seq_number++;
1712 STp->frame_in_buffer = 0;
1713 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1714 }
1715 return 0;
1716}
1717
1718
1719
1720
1721
1722
1723static int osst_space_over_filemarks_forward_slow(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
1724 int mt_op, int mt_count)
1725{
1726 int cnt = 0;
1727#if DEBUG
1728 int dev = TAPE_NR(STp->devt);
1729
1730 printk(OSST_DEB_MSG "osst%d:D: Reached space_over_filemarks_forward_slow %d %d\n", dev, mt_op, mt_count);
1731#endif
1732 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1733#if DEBUG
1734 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_fwd\n", dev);
1735#endif
1736 return (-EIO);
1737 }
1738 while (1) {
1739 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1740#if DEBUG
1741 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n", dev);
1742#endif
1743 return (-EIO);
1744 }
1745 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1746 cnt++;
1747 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1748#if DEBUG
1749 printk(OSST_DEB_MSG "osst%d:D: space_fwd: EOD reached\n", dev);
1750#endif
1751 if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1752#if DEBUG
1753 printk(OSST_DEB_MSG "osst%d:D: EOD position corrected (%d=>%d)\n",
1754 dev, STp->eod_frame_ppos, STp->first_frame_position-1);
1755#endif
1756 STp->eod_frame_ppos = STp->first_frame_position-1;
1757 }
1758 return (-EIO);
1759 }
1760 if (cnt == mt_count)
1761 break;
1762 STp->frame_in_buffer = 0;
1763 }
1764 if (mt_op == MTFSF) {
1765 STp->frame_seq_number++;
1766 STp->frame_in_buffer = 0;
1767 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1768 }
1769 return 0;
1770}
1771
1772
1773
1774
1775static int osst_space_over_filemarks_forward_fast(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt,
1776 int mt_op, int mt_count)
1777{
1778 int dev = TAPE_NR(STp->devt);
1779 int cnt = 0,
1780 next_mark_ppos = -1;
1781
1782#if DEBUG
1783 printk(OSST_DEB_MSG "osst%d:D: Reached space_over_filemarks_forward_fast %d %d\n", dev, mt_op, mt_count);
1784#endif
1785 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1786#if DEBUG
1787 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks_fwd\n", dev);
1788#endif
1789 return (-EIO);
1790 }
1791
1792 if (STp->linux_media_version >= 4) {
1793
1794
1795
1796 cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
1797 if (STp->header_ok &&
1798 STp->header_cache != NULL &&
1799 (cnt + mt_count) < OS_FM_TAB_MAX &&
1800 (cnt + mt_count) < STp->filemark_cnt &&
1801 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1802 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
1803
1804 next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
1805#if DEBUG
1806 if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
1807 printk(OSST_DEB_MSG "osst%d:D: Filemark lookup fail due to %s\n", dev,
1808 STp->header_cache == NULL?"lack of header cache":"count out of range");
1809 else
1810 printk(OSST_DEB_MSG "osst%d:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1811 dev, cnt,
1812 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1813 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
1814 STp->buffer->aux->last_mark_ppos))?"match":"error",
1815 mt_count, next_mark_ppos);
1816#endif
1817 if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
1818#if DEBUG
1819 printk(OSST_DEB_MSG "osst%d:D: Reverting to slow filemark space\n", dev);
1820#endif
1821 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
1822 } else {
1823 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
1824 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1825#if DEBUG
1826 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n",
1827 dev);
1828#endif
1829 return (-EIO);
1830 }
1831 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1832 printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n",
1833 dev, next_mark_ppos);
1834 return (-EIO);
1835 }
1836 if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
1837 printk(KERN_WARNING "osst%d:W: Expected to find marker %d at ppos %d, not %d\n",
1838 dev, cnt+mt_count, next_mark_ppos,
1839 ntohl(STp->buffer->aux->filemark_cnt));
1840 return (-EIO);
1841 }
1842 }
1843 } else {
1844
1845
1846
1847 while (1) {
1848 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1849 break;
1850 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1851#if DEBUG
1852 printk(OSST_DEB_MSG "osst%d:D: space_fwd: EOD reached\n", dev);
1853#endif
1854 return (-EIO);
1855 }
1856 if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
1857 if (STp->first_mark_ppos == -1) {
1858#if DEBUG
1859 printk(OSST_DEB_MSG "osst%d:D: Reverting to slow filemark space\n", dev);
1860#endif
1861 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
1862 }
1863 osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
1864 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1865#if DEBUG
1866 printk(OSST_DEB_MSG
1867 "osst%d:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
1868 dev);
1869#endif
1870 return (-EIO);
1871 }
1872 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1873 printk(KERN_WARNING "osst%d:W: Expected to find filemark at %d\n",
1874 dev, STp->first_mark_ppos);
1875 return (-EIO);
1876 }
1877 } else {
1878 if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
1879 return (-EIO);
1880 mt_count++;
1881 }
1882 }
1883 cnt++;
1884 while (cnt != mt_count) {
1885 next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
1886 if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
1887#if DEBUG
1888 printk(OSST_DEB_MSG "osst%d:D: Reverting to slow filemark space\n", dev);
1889#endif
1890 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
1891 }
1892#if DEBUG
1893 else printk(OSST_DEB_MSG "osst%d:D: Positioning to next mark at %d\n", dev, next_mark_ppos);
1894#endif
1895 osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
1896 cnt++;
1897 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1898#if DEBUG
1899 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in space_filemarks\n",
1900 dev);
1901#endif
1902 return (-EIO);
1903 }
1904 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1905 printk(KERN_WARNING "osst%d:W: Expected to find marker at ppos %d, not found\n",
1906 dev, next_mark_ppos);
1907 return (-EIO);
1908 }
1909 }
1910 }
1911 if (mt_op == MTFSF) {
1912 STp->frame_seq_number++;
1913 STp->frame_in_buffer = 0;
1914 STp->logical_blk_num += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1915 }
1916 return 0;
1917}
1918
1919
1920
1921
1922
1923#if DEBUG
1924static void osst_set_retries(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int retries)
1925{
1926 unsigned char cmd[MAX_COMMAND_SIZE];
1927 Scsi_Request * SRpnt = * aSRpnt;
1928 int dev = TAPE_NR(STp->devt);
1929
1930 memset(cmd, 0, MAX_COMMAND_SIZE);
1931 cmd[0] = MODE_SELECT;
1932 cmd[1] = 0x10;
1933 cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
1934
1935 (STp->buffer)->b_data[0] = cmd[4] - 1;
1936 (STp->buffer)->b_data[1] = 0;
1937 (STp->buffer)->b_data[2] = 0;
1938 (STp->buffer)->b_data[3] = 0;
1939 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
1940 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
1941 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
1942 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
1943
1944 if (debugging)
1945 printk(OSST_DEB_MSG "osst%d:D: Setting number of retries on OnStream tape to %d\n", dev, retries);
1946
1947 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
1948 *aSRpnt = SRpnt;
1949
1950 if ((STp->buffer)->syscall_result)
1951 printk (KERN_ERR "osst%d:D: Couldn't set retries to %d\n", dev, retries);
1952}
1953#endif
1954
1955
1956static int osst_write_filemark(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
1957{
1958 int result;
1959 int this_mark_ppos = STp->first_frame_position;
1960 int this_mark_lbn = STp->logical_blk_num;
1961#if DEBUG
1962 int dev = TAPE_NR(STp->devt);
1963#endif
1964
1965 if (STp->raw) return 0;
1966
1967 STp->write_type = OS_WRITE_NEW_MARK;
1968#if DEBUG
1969 printk(OSST_DEB_MSG "osst%d:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n",
1970 dev, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
1971#endif
1972 STp->dirty = 1;
1973 result = osst_flush_write_buffer(STp, aSRpnt);
1974 result |= osst_flush_drive_buffer(STp, aSRpnt);
1975 STp->last_mark_ppos = this_mark_ppos;
1976 STp->last_mark_lbn = this_mark_lbn;
1977 if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
1978 STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
1979 if (STp->filemark_cnt++ == 0)
1980 STp->first_mark_ppos = this_mark_ppos;
1981 return result;
1982}
1983
1984static int osst_write_eod(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
1985{
1986 int result;
1987#if DEBUG
1988 int dev = TAPE_NR(STp->devt);
1989#endif
1990
1991 if (STp->raw) return 0;
1992
1993 STp->write_type = OS_WRITE_EOD;
1994 STp->eod_frame_ppos = STp->first_frame_position;
1995#if DEBUG
1996 printk(OSST_DEB_MSG "osst%d:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", dev,
1997 STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
1998#endif
1999 STp->dirty = 1;
2000
2001 result = osst_flush_write_buffer(STp, aSRpnt);
2002 result |= osst_flush_drive_buffer(STp, aSRpnt);
2003 STp->eod_frame_lfa = --(STp->frame_seq_number);
2004 return result;
2005}
2006
2007static int osst_write_filler(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count)
2008{
2009 int dev = TAPE_NR(STp->devt);
2010
2011#if DEBUG
2012 printk(OSST_DEB_MSG "osst%d:D: Reached onstream write filler group %d\n", dev, where);
2013#endif
2014 osst_wait_ready(STp, aSRpnt, 60 * 5);
2015 osst_set_frame_position(STp, aSRpnt, where, 0);
2016 STp->write_type = OS_WRITE_FILLER;
2017 while (count--) {
2018 memcpy(STp->buffer->b_data, "Filler", 6);
2019 STp->buffer->buffer_bytes = 6;
2020 STp->dirty = 1;
2021 if (osst_flush_write_buffer(STp, aSRpnt)) {
2022 printk(KERN_INFO "osst%i:I: Couldn't write filler frame\n", dev);
2023 return (-EIO);
2024 }
2025 }
2026#if DEBUG
2027 printk(OSST_DEB_MSG "osst%d:D: Exiting onstream write filler group\n", dev);
2028#endif
2029 return osst_flush_drive_buffer(STp, aSRpnt);
2030}
2031
2032static int __osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int where, int count)
2033{
2034 int dev = TAPE_NR(STp->devt);
2035 int result;
2036
2037#if DEBUG
2038 printk(OSST_DEB_MSG "osst%d:D: Reached onstream write header group %d\n", dev, where);
2039#endif
2040 osst_wait_ready(STp, aSRpnt, 60 * 5);
2041 osst_set_frame_position(STp, aSRpnt, where, 0);
2042 STp->write_type = OS_WRITE_HEADER;
2043 while (count--) {
2044 osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2045 STp->buffer->buffer_bytes = sizeof(os_header_t);
2046 STp->dirty = 1;
2047 if (osst_flush_write_buffer(STp, aSRpnt)) {
2048 printk(KERN_INFO "osst%i:I: Couldn't write header frame\n", dev);
2049 return (-EIO);
2050 }
2051 }
2052 result = osst_flush_drive_buffer(STp, aSRpnt);
2053#if DEBUG
2054 printk(OSST_DEB_MSG "osst%d:D: Write onstream header group %s\n", dev, result?"failed":"done");
2055#endif
2056 return result;
2057}
2058
2059static int osst_write_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int locate_eod)
2060{
2061 os_header_t * header;
2062 int result;
2063 int dev = TAPE_NR(STp->devt);
2064
2065#if DEBUG
2066 printk(OSST_DEB_MSG "osst%d:D: Writing tape header\n", dev);
2067#endif
2068 if (STp->raw) return 0;
2069
2070 if (STp->header_cache == NULL) {
2071 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2072 printk(KERN_ERR "osst%i:E: Failed to allocate header cache\n", dev);
2073 return (-ENOMEM);
2074 }
2075 memset(STp->header_cache, 0, sizeof(os_header_t));
2076#if DEBUG
2077 printk(OSST_DEB_MSG "osst%d:D: Allocated and cleared memory for header cache\n", dev);
2078#endif
2079 }
2080 if (STp->header_ok) STp->update_frame_cntr++;
2081 else STp->update_frame_cntr = 0;
2082
2083 header = STp->header_cache;
2084 strcpy(header->ident_str, "ADR_SEQ");
2085 header->major_rev = 1;
2086 header->minor_rev = 4;
2087 header->ext_trk_tb_off = htons(17192);
2088 header->pt_par_num = 1;
2089 header->partition[0].partition_num = OS_DATA_PARTITION;
2090 header->partition[0].par_desc_ver = OS_PARTITION_VERSION;
2091 header->partition[0].wrt_pass_cntr = htons(STp->wrt_pass_cntr);
2092 header->partition[0].first_frame_ppos = htonl(STp->first_data_ppos);
2093 header->partition[0].last_frame_ppos = htonl(STp->capacity);
2094 header->partition[0].eod_frame_ppos = htonl(STp->eod_frame_ppos);
2095 header->cfg_col_width = htonl(20);
2096 header->dat_col_width = htonl(1500);
2097 header->qfa_col_width = htonl(0);
2098 header->ext_track_tb.nr_stream_part = 1;
2099 header->ext_track_tb.et_ent_sz = 32;
2100 header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2101 header->ext_track_tb.dat_ext_trk_ey.fmt = 1;
2102 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off = htons(17736);
2103 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2104 header->ext_track_tb.dat_ext_trk_ey.last_hlb = htonl(STp->eod_frame_lfa);
2105 header->ext_track_tb.dat_ext_trk_ey.last_pp = htonl(STp->eod_frame_ppos);
2106 header->dat_fm_tab.fm_part_num = 0;
2107 header->dat_fm_tab.fm_tab_ent_sz = 4;
2108 header->dat_fm_tab.fm_tab_ent_cnt = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2109 STp->filemark_cnt:OS_FM_TAB_MAX);
2110
2111 result = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2112 if (STp->update_frame_cntr == 0)
2113 osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2114 result &= __osst_write_header(STp, aSRpnt, 5, 5);
2115
2116 if (locate_eod) {
2117#if DEBUG
2118 printk(OSST_DEB_MSG "osst%d:D: Locating back to eod frame addr %d\n", dev, STp->eod_frame_ppos);
2119#endif
2120 osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2121 }
2122 if (result)
2123 printk(KERN_ERR "osst%i:E: Write header failed\n", dev);
2124 else {
2125 memcpy(STp->application_sig, "LIN4", 4);
2126 STp->linux_media = 1;
2127 STp->linux_media_version = 4;
2128 STp->header_ok = 1;
2129 }
2130 return result;
2131}
2132
2133static int osst_reset_header(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
2134{
2135 if (STp->header_cache != NULL)
2136 memset(STp->header_cache, 0, sizeof(os_header_t));
2137
2138 STp->logical_blk_num = STp->frame_seq_number = 0;
2139 STp->frame_in_buffer = 0;
2140 STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2141 STp->filemark_cnt = 0;
2142 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2143 return osst_write_header(STp, aSRpnt, 1);
2144}
2145
2146static int __osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int ppos)
2147{
2148 int dev = TAPE_NR(STp->devt);
2149 os_header_t * header;
2150 os_aux_t * aux;
2151 char id_string[8];
2152 int linux_media_version,
2153 update_frame_cntr;
2154
2155 if (STp->raw)
2156 return 1;
2157
2158 if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2159 if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2160 printk(KERN_WARNING "osst%i:W: Couldn't position tape\n", dev);
2161 if (osst_initiate_read (STp, aSRpnt)) {
2162 printk(KERN_WARNING "osst%i:W: Couldn't initiate read\n", dev);
2163 return 0;
2164 }
2165 }
2166 if (osst_read_frame(STp, aSRpnt, 180)) {
2167#if DEBUG
2168 printk(OSST_DEB_MSG "osst%d:D: Couldn't read header frame\n", dev);
2169#endif
2170 return 0;
2171 }
2172 header = (os_header_t *) STp->buffer->b_data;
2173 aux = STp->buffer->aux;
2174 if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2175#if DEBUG
2176 printk(OSST_DEB_MSG "osst%d:D: Skipping non-header frame (%d)\n", dev, ppos);
2177#endif
2178 return 0;
2179 }
2180 if (ntohl(aux->frame_seq_num) != 0 ||
2181 ntohl(aux->logical_blk_num) != 0 ||
2182 aux->partition.partition_num != OS_CONFIG_PARTITION ||
2183 ntohl(aux->partition.first_frame_ppos) != 0 ||
2184 ntohl(aux->partition.last_frame_ppos) != 0xbb7 ) {
2185#if DEBUG
2186 printk(OSST_DEB_MSG "osst%d:D: Invalid header frame (%d,%d,%d,%d,%d)\n", dev,
2187 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2188 aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2189 ntohl(aux->partition.last_frame_ppos));
2190#endif
2191 return 0;
2192 }
2193 if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2194 strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2195 strncpy(id_string, header->ident_str, 7);
2196 id_string[7] = 0;
2197#if DEBUG
2198 printk(OSST_DEB_MSG "osst%d:D: Invalid header identification string %s\n", dev, id_string);
2199#endif
2200 return 0;
2201 }
2202 update_frame_cntr = ntohl(aux->update_frame_cntr);
2203 if (update_frame_cntr < STp->update_frame_cntr) {
2204#if DEBUG
2205 printk(OSST_DEB_MSG "osst%d:D: Skipping frame %d with update_frame_counter %d<%d\n",
2206 dev, ppos, update_frame_cntr, STp->update_frame_cntr);
2207#endif
2208 return 0;
2209 }
2210 if (header->major_rev != 1 || header->minor_rev != 4 ) {
2211#if DEBUG
2212 printk(OSST_DEB_MSG "osst%d:D: %s revision %d.%d detected (1.4 supported)\n",
2213 dev, (header->major_rev != 1 || header->minor_rev < 2 ||
2214 header->minor_rev > 4 )? "Invalid" : "Warning:",
2215 header->major_rev, header->minor_rev);
2216#endif
2217 if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2218 return 0;
2219 }
2220#if DEBUG
2221 if (header->pt_par_num != 1)
2222 printk(KERN_INFO "osst%i:W: %d partitions defined, only one supported\n",
2223 dev, header->pt_par_num);
2224#endif
2225 memcpy(id_string, aux->application_sig, 4);
2226 id_string[4] = 0;
2227 if (memcmp(id_string, "LIN", 3) == 0) {
2228 STp->linux_media = 1;
2229 linux_media_version = id_string[3] - '0';
2230 if (linux_media_version != 4)
2231 printk(KERN_INFO "osst%i:I: Linux media version %d detected (current 4)\n",
2232 dev, linux_media_version);
2233 } else {
2234 printk(KERN_WARNING "osst%i:W: Non Linux media detected (%s)\n", dev, id_string);
2235 return 0;
2236 }
2237 if (linux_media_version < STp->linux_media_version) {
2238#if DEBUG
2239 printk(OSST_DEB_MSG "osst%d:D: Skipping frame %d with linux_media_version %d\n",
2240 dev, ppos, linux_media_version);
2241#endif
2242 return 0;
2243 }
2244 if (linux_media_version > STp->linux_media_version) {
2245#if DEBUG
2246 printk(OSST_DEB_MSG "osst%d:D: Frame %d sets linux_media_version to %d\n",
2247 dev, ppos, linux_media_version);
2248#endif
2249 memcpy(STp->application_sig, id_string, 5);
2250 STp->linux_media_version = linux_media_version;
2251 STp->update_frame_cntr = -1;
2252 }
2253 if (update_frame_cntr > STp->update_frame_cntr) {
2254#if DEBUG
2255 printk(OSST_DEB_MSG "osst%d:D: Frame %d sets update_frame_counter to %d\n",
2256 dev, ppos, update_frame_cntr);
2257#endif
2258 if (STp->header_cache == NULL) {
2259 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2260 printk(KERN_ERR "osst%i:E: Failed to allocate header cache\n", dev);
2261 return 0;
2262 }
2263#if DEBUG
2264 printk(OSST_DEB_MSG "osst%d:D: Allocated memory for header cache\n", dev);
2265#endif
2266 }
2267 osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2268 header = STp->header_cache;
2269
2270 STp->wrt_pass_cntr = ntohs(header->partition[0].wrt_pass_cntr);
2271 STp->first_data_ppos = ntohl(header->partition[0].first_frame_ppos);
2272 STp->eod_frame_ppos = ntohl(header->partition[0].eod_frame_ppos);
2273 STp->eod_frame_lfa = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2274 STp->filemark_cnt = ntohl(aux->filemark_cnt);
2275 STp->first_mark_ppos = ntohl(aux->next_mark_ppos);
2276 STp->last_mark_ppos = ntohl(aux->last_mark_ppos);
2277 STp->last_mark_lbn = ntohl(aux->last_mark_lbn);
2278 STp->update_frame_cntr = update_frame_cntr;
2279#if DEBUG
2280 printk(OSST_DEB_MSG "osst%d:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2281 dev, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2282 printk(OSST_DEB_MSG "osst%d:D: first data frame on tape = %d, last = %d, eod frame = %d\n", dev,
2283 STp->first_data_ppos,
2284 ntohl(header->partition[0].last_frame_ppos),
2285 ntohl(header->partition[0].eod_frame_ppos));
2286 printk(OSST_DEB_MSG "osst%d:D: first mark on tape = %d, last = %d, eod frame = %d\n",
2287 dev, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2288#endif
2289 if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2290#if DEBUG
2291 printk(OSST_DEB_MSG "osst%i:D: Moving filemark list to ADR 1.4 location\n", dev);
2292#endif
2293 memcpy((void *)header->dat_fm_tab.fm_tab_ent,
2294 (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2295 memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2296 }
2297 if (header->minor_rev == 4 &&
2298 (header->ext_trk_tb_off != htons(17192) ||
2299 header->partition[0].partition_num != OS_DATA_PARTITION ||
2300 header->partition[0].par_desc_ver != OS_PARTITION_VERSION ||
2301 header->partition[0].last_frame_ppos != htonl(STp->capacity) ||
2302 header->cfg_col_width != htonl(20) ||
2303 header->dat_col_width != htonl(1500) ||
2304 header->qfa_col_width != htonl(0) ||
2305 header->ext_track_tb.nr_stream_part != 1 ||
2306 header->ext_track_tb.et_ent_sz != 32 ||
2307 header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION ||
2308 header->ext_track_tb.dat_ext_trk_ey.fmt != 1 ||
2309 header->ext_track_tb.dat_ext_trk_ey.fm_tab_off != htons(17736) ||
2310 header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0 ||
2311 header->ext_track_tb.dat_ext_trk_ey.last_pp != htonl(STp->eod_frame_ppos) ||
2312 header->dat_fm_tab.fm_part_num != OS_DATA_PARTITION ||
2313 header->dat_fm_tab.fm_tab_ent_sz != 4 ||
2314 header->dat_fm_tab.fm_tab_ent_cnt !=
2315 htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2316 printk(KERN_WARNING "osst%i:W: Failed consistency check ADR 1.4 format\n", dev);
2317
2318 }
2319
2320 return 1;
2321}
2322
2323static int osst_analyze_headers(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
2324{
2325 int position, ppos;
2326 int first, last;
2327 int valid = 0;
2328 int dev = TAPE_NR(STp->devt);
2329
2330 position = osst_get_frame_position(STp, aSRpnt);
2331
2332 if (STp->raw) {
2333 STp->header_ok = STp->linux_media = 1;
2334 STp->linux_media_version = 0;
2335 return 1;
2336 }
2337 STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2338 STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2339 STp->eod_frame_ppos = STp->first_data_ppos = -1;
2340 STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2341#if DEBUG
2342 printk(OSST_DEB_MSG "osst%d:D: Reading header\n", dev);
2343#endif
2344
2345
2346
2347
2348 first = position==10?0xbae: 5;
2349 last = position==10?0xbb3:10;
2350
2351 for (ppos = first; ppos < last; ppos++)
2352 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2353 valid = 1;
2354
2355 first = position==10? 5:0xbae;
2356 last = position==10?10:0xbb3;
2357
2358 for (ppos = first; ppos < last; ppos++)
2359 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2360 valid = 1;
2361
2362 if (!valid) {
2363 printk(KERN_ERR "osst%i:E: Failed to find valid ADRL header, new media?\n", dev);
2364 STp->eod_frame_ppos = STp->first_data_ppos = 0;
2365 osst_set_frame_position(STp, aSRpnt, 10, 0);
2366 return 0;
2367 }
2368 if (position <= STp->first_data_ppos) {
2369 position = STp->first_data_ppos;
2370 STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2371 }
2372 osst_set_frame_position(STp, aSRpnt, position, 0);
2373 STp->header_ok = 1;
2374
2375 return 1;
2376}
2377
2378static int osst_verify_position(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt)
2379{
2380 int frame_position = STp->first_frame_position;
2381 int frame_seq_numbr = STp->frame_seq_number;
2382 int logical_blk_num = STp->logical_blk_num;
2383 int halfway_frame = STp->frame_in_buffer;
2384 int read_pointer = STp->buffer->read_pointer;
2385 int prev_mark_ppos = -1;
2386 int actual_mark_ppos, i, n;
2387#if DEBUG
2388 int dev = TAPE_NR(STp->devt);
2389
2390 printk(OSST_DEB_MSG "osst%d:D: Verify that the tape is really the one we think before writing\n", dev);
2391#endif
2392 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2393 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2394#if DEBUG
2395 printk(OSST_DEB_MSG "osst%d:D: Couldn't get logical blk num in verify_position\n", dev);
2396#endif
2397 return (-EIO);
2398 }
2399 if (STp->linux_media_version >= 4) {
2400 for (i=0; i<STp->filemark_cnt; i++)
2401 if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2402 prev_mark_ppos = n;
2403 } else
2404 prev_mark_ppos = frame_position - 1;
2405 actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2406 frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2407 if (frame_position != STp->first_frame_position ||
2408 frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2409 prev_mark_ppos != actual_mark_ppos ) {
2410#if DEBUG
2411 printk(OSST_DEB_MSG "osst%d:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", dev,
2412 STp->first_frame_position, frame_position,
2413 STp->frame_seq_number + (halfway_frame?0:1),
2414 frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2415#endif
2416 return (-EIO);
2417 }
2418 if (halfway_frame) {
2419
2420 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2421 STp->buffer->buffer_bytes = read_pointer;
2422 STp->ps[STp->partition].rw = ST_WRITING;
2423 STp->dirty = 1;
2424 }
2425 STp->frame_in_buffer = halfway_frame;
2426 STp->frame_seq_number = frame_seq_numbr;
2427 STp->logical_blk_num = logical_blk_num;
2428 return 0;
2429}
2430
2431
2432
2433
2434
2435
2436
2437static unsigned int osst_parse_firmware_rev (const char * str)
2438{
2439 if (str[1] == '.') {
2440 return (str[0]-'0')*10000
2441 +(str[2]-'0')*1000
2442 +(str[3]-'0')*100;
2443 } else {
2444 return (str[0]-'0')*10000
2445 +(str[1]-'0')*1000
2446 +(str[2]-'0')*100 - 100
2447 +(str[3]-'@');
2448 }
2449}
2450
2451
2452
2453
2454static int osst_configure_onstream(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
2455{
2456 unsigned char cmd[MAX_COMMAND_SIZE];
2457 int dev = TAPE_NR(STp->devt);
2458 Scsi_Request * SRpnt = * aSRpnt;
2459 osst_mode_parameter_header_t * header;
2460 osst_block_size_page_t * bs;
2461 osst_capabilities_page_t * cp;
2462 osst_tape_paramtr_page_t * prm;
2463 int drive_buffer_size;
2464
2465 if (STp->ready != ST_READY) {
2466#if DEBUG
2467 printk(OSST_DEB_MSG "osst%d:D: Not Ready\n", dev);
2468#endif
2469 return (-EIO);
2470 }
2471
2472 if (STp->os_fw_rev < 10600) {
2473 printk(KERN_INFO "osst%i:I: Old OnStream firmware revision detected (%s),\n", dev, STp->device->rev);
2474 printk(KERN_INFO "osst%d:I: an upgrade to version 1.06 or above is recommended\n", dev);
2475 }
2476
2477
2478
2479
2480
2481 memset(cmd, 0, MAX_COMMAND_SIZE);
2482 cmd[0] = MODE_SENSE;
2483 cmd[1] = 8;
2484 cmd[2] = BLOCK_SIZE_PAGE;
2485 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2486
2487 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
2488 if (SRpnt == NULL) {
2489#if DEBUG
2490 printk(OSST_DEB_MSG "osst :D: Busy\n");
2491#endif
2492 return (-EBUSY);
2493 }
2494 *aSRpnt = SRpnt;
2495 if ((STp->buffer)->syscall_result != 0) {
2496 printk (KERN_ERR "osst%i:E: Can't get tape block size mode page\n", dev);
2497 return (-EIO);
2498 }
2499
2500 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2501 bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2502
2503#if DEBUG
2504 printk(OSST_DEB_MSG "osst%d:D: 32KB play back: %s\n", dev, bs->play32 ? "Yes" : "No");
2505 printk(OSST_DEB_MSG "osst%d:D: 32.5KB play back: %s\n", dev, bs->play32_5 ? "Yes" : "No");
2506 printk(OSST_DEB_MSG "osst%d:D: 32KB record: %s\n", dev, bs->record32 ? "Yes" : "No");
2507 printk(OSST_DEB_MSG "osst%d:D: 32.5KB record: %s\n", dev, bs->record32_5 ? "Yes" : "No");
2508#endif
2509
2510
2511
2512
2513 bs->one = 1;
2514 bs->play32 = 0;
2515 bs->play32_5 = 1;
2516 bs->record32 = 0;
2517 bs->record32_5 = 1;
2518
2519 memset(cmd, 0, MAX_COMMAND_SIZE);
2520 cmd[0] = MODE_SELECT;
2521 cmd[1] = 0x10;
2522 cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2523
2524 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
2525 *aSRpnt = SRpnt;
2526 if ((STp->buffer)->syscall_result != 0) {
2527 printk (KERN_ERR "osst%i:E: Couldn't set tape block size mode page\n", dev);
2528 return (-EIO);
2529 }
2530
2531#if DEBUG
2532 printk(KERN_INFO "osst%d:D: Drive Block Size changed to 32.5K\n", dev);
2533
2534
2535
2536
2537 osst_set_retries(STp, aSRpnt, 0);
2538 SRpnt = * aSRpnt;
2539#endif
2540
2541
2542
2543
2544
2545 memset(cmd, 0, MAX_COMMAND_SIZE);
2546 cmd[0] = MODE_SELECT;
2547 cmd[1] = 0x10;
2548 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2549
2550 header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2551 header->medium_type = 0;
2552 header->dsp = 0;
2553 header->bdl = 0;
2554
2555 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2556 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2557 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2558 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2559 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2560 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2561 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2562 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2563
2564 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
2565 *aSRpnt = SRpnt;
2566
2567 if ((STp->buffer)->syscall_result != 0) {
2568 printk (KERN_ERR "osst%i:E: Couldn't set vendor name to %s\n", dev,
2569 (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2570 return (-EIO);
2571 }
2572
2573 memset(cmd, 0, MAX_COMMAND_SIZE);
2574 cmd[0] = MODE_SENSE;
2575 cmd[1] = 8;
2576 cmd[2] = CAPABILITIES_PAGE;
2577 cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2578
2579 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
2580 *aSRpnt = SRpnt;
2581
2582 if ((STp->buffer)->syscall_result != 0) {
2583 printk (KERN_ERR "osst%i:E: Can't get capabilities page\n", dev);
2584 return (-EIO);
2585 }
2586
2587 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2588 cp = (osst_capabilities_page_t *) ((STp->buffer)->b_data +
2589 sizeof(osst_mode_parameter_header_t) + header->bdl);
2590
2591 drive_buffer_size = ntohs(cp->buffer_size) / 2;
2592
2593 memset(cmd, 0, MAX_COMMAND_SIZE);
2594 cmd[0] = MODE_SENSE;
2595 cmd[1] = 8;
2596 cmd[2] = TAPE_PARAMTR_PAGE;
2597 cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2598
2599 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
2600 *aSRpnt = SRpnt;
2601
2602 if ((STp->buffer)->syscall_result != 0) {
2603 printk (KERN_ERR "osst%i:E: Can't get tape parameter page\n", dev);
2604 return (-EIO);
2605 }
2606
2607 header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2608 prm = (osst_tape_paramtr_page_t *) ((STp->buffer)->b_data +
2609 sizeof(osst_mode_parameter_header_t) + header->bdl);
2610
2611 STp->density = prm->density;
2612 STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2613#if DEBUG
2614 printk(OSST_DEB_MSG "osst%d:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2615 dev, STp->density, STp->capacity / 32, drive_buffer_size);
2616#endif
2617
2618 return 0;
2619
2620}
2621
2622
2623
2624
2625static int cross_eof(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int forward)
2626{
2627 int result;
2628 int dev = TAPE_NR(STp->devt);
2629
2630#if DEBUG
2631 if (debugging)
2632 printk(OSST_DEB_MSG "osst%d:D: Stepping over filemark %s.\n",
2633 dev, forward ? "forward" : "backward");
2634#endif
2635
2636 if (forward) {
2637
2638 result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2639 }
2640 else
2641
2642 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2643
2644 if (result < 0)
2645 printk(KERN_WARNING "osst%d:W: Stepping over filemark %s failed.\n",
2646 dev, forward ? "forward" : "backward");
2647
2648 return result;
2649}
2650
2651
2652
2653
2654static int osst_get_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
2655{
2656 unsigned char scmd[MAX_COMMAND_SIZE];
2657 Scsi_Request * SRpnt;
2658 int result = 0;
2659
2660
2661
2662 char mybuf[24];
2663 char * olddata = STp->buffer->b_data;
2664 int oldsize = STp->buffer->buffer_size;
2665 int dev = TAPE_NR(STp->devt);
2666
2667 if (STp->ready != ST_READY) return (-EIO);
2668
2669 memset (scmd, 0, MAX_COMMAND_SIZE);
2670 scmd[0] = READ_POSITION;
2671
2672 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2673 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, SCSI_DATA_READ,
2674 STp->timeout, MAX_READY_RETRIES, TRUE);
2675 if (!SRpnt) {
2676 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2677 return (-EBUSY);
2678 }
2679 *aSRpnt = SRpnt;
2680
2681 if (STp->buffer->syscall_result)
2682 result = ((SRpnt->sr_sense_buffer[2] & 0x0f) == 3) ? -EIO : -EINVAL;
2683
2684 if (result == -EINVAL)
2685 printk(KERN_ERR "osst%d:E: Can't read tape position.\n", dev);
2686 else {
2687
2688 if (result == -EIO) {
2689 unsigned char mysense[16];
2690 memcpy (mysense, SRpnt->sr_sense_buffer, 16);
2691 memset (scmd, 0, MAX_COMMAND_SIZE);
2692 scmd[0] = READ_POSITION;
2693 STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2694 SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, SCSI_DATA_READ,
2695 STp->timeout, MAX_READY_RETRIES, TRUE);
2696 if (!STp->buffer->syscall_result)
2697 memcpy (SRpnt->sr_sense_buffer, mysense, 16);
2698 }
2699 STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2700 + ((STp->buffer)->b_data[5] << 16)
2701 + ((STp->buffer)->b_data[6] << 8)
2702 + (STp->buffer)->b_data[7];
2703 STp->last_frame_position = ((STp->buffer)->b_data[ 8] << 24)
2704 + ((STp->buffer)->b_data[ 9] << 16)
2705 + ((STp->buffer)->b_data[10] << 8)
2706 + (STp->buffer)->b_data[11];
2707 STp->cur_frames = (STp->buffer)->b_data[15];
2708#if DEBUG
2709 if (debugging) {
2710 printk(OSST_DEB_MSG "osst%d:D: Drive Positions: host %d, tape %d%s, buffer %d\n", dev,
2711 STp->first_frame_position, STp->last_frame_position,
2712 ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2713 ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2714 STp->cur_frames);
2715 }
2716#endif
2717 if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2718#if DEBUG
2719 printk(KERN_WARNING "osst%d:D: Correcting read position %d, %d, %d\n", dev,
2720 STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2721#endif
2722 STp->first_frame_position = STp->last_frame_position;
2723 }
2724 }
2725 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2726
2727 return (result == 0 ? STp->first_frame_position : result);
2728}
2729
2730
2731
2732static int osst_set_frame_position(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt, int ppos, int skip)
2733{
2734 unsigned char scmd[MAX_COMMAND_SIZE];
2735 Scsi_Request * SRpnt;
2736 ST_partstat * STps;
2737 int result = 0;
2738 int pp = (ppos == 3000 && !skip)? 0 : ppos;
2739 int dev = TAPE_NR(STp->devt);
2740
2741 if (STp->ready != ST_READY) return (-EIO);
2742
2743 STps = &(STp->ps[STp->partition]);
2744
2745 if (ppos < 0 || ppos > STp->capacity) {
2746 printk(KERN_WARNING "osst%d:W: Reposition request %d out of range\n", dev, ppos);
2747 pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2748 result = (-EINVAL);
2749 }
2750
2751 do {
2752#if DEBUG
2753 if (debugging)
2754 printk(OSST_DEB_MSG "osst%d:D: Setting ppos to %d.\n", dev, pp);
2755#endif
2756 memset (scmd, 0, MAX_COMMAND_SIZE);
2757 scmd[0] = SEEK_10;
2758 scmd[1] = 1;
2759 scmd[3] = (pp >> 24);
2760 scmd[4] = (pp >> 16);
2761 scmd[5] = (pp >> 8);
2762 scmd[6] = pp;
2763 if (skip)
2764 scmd[9] = 0x80;
2765
2766 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, SCSI_DATA_NONE, STp->long_timeout,
2767 MAX_READY_RETRIES, TRUE);
2768 if (!SRpnt)
2769 return (-EBUSY);
2770 *aSRpnt = SRpnt;
2771
2772 if ((STp->buffer)->syscall_result != 0) {
2773#if DEBUG
2774 printk(OSST_DEB_MSG "osst%d:D: SEEK command from %d to %d failed.\n",
2775 dev, STp->first_frame_position, pp);
2776#endif
2777 result = (-EIO);
2778 }
2779 if (pp != ppos)
2780 osst_wait_ready(STp, aSRpnt, 5 * 60);
2781 } while ((pp != ppos) && (pp = ppos));
2782 STp->first_frame_position = STp->last_frame_position = ppos;
2783 STps->eof = ST_NOEOF;
2784 STps->at_sm = 0;
2785 STps->rw = ST_IDLE;
2786 STp->frame_in_buffer = 0;
2787 return result;
2788}
2789
2790
2791
2792
2793
2794
2795static int osst_flush_write_buffer(OS_Scsi_Tape *STp, Scsi_Request ** aSRpnt)
2796{
2797 int offset, transfer, blks = 0;
2798 int result = 0;
2799 unsigned char cmd[MAX_COMMAND_SIZE];
2800 Scsi_Request * SRpnt = *aSRpnt;
2801 ST_partstat * STps;
2802 int dev = TAPE_NR(STp->devt);
2803
2804 if ((STp->buffer)->writing) {
2805 if (SRpnt == (STp->buffer)->last_SRpnt)
2806#if DEBUG
2807 { printk(OSST_DEB_MSG
2808 "osst%d:D: aSRpnt points to Scsi_Request that write_behind_check will release -- cleared\n", dev);
2809#endif
2810 *aSRpnt = SRpnt = NULL;
2811#if DEBUG
2812 } else if (SRpnt)
2813 printk(OSST_DEB_MSG
2814 "osst%d:D: aSRpnt does not point to Scsi_Request that write_behind_check will release -- strange\n", dev);
2815#endif
2816 osst_write_behind_check(STp);
2817 if ((STp->buffer)->syscall_result) {
2818#if DEBUG
2819 if (debugging)
2820 printk(OSST_DEB_MSG "osst%d:D: Async write error (flush) %x.\n",
2821 dev, (STp->buffer)->midlevel_result);
2822#endif
2823 if ((STp->buffer)->midlevel_result == INT_MAX)
2824 return (-ENOSPC);
2825 return (-EIO);
2826 }
2827 }
2828
2829 result = 0;
2830 if (STp->dirty == 1) {
2831
2832 STp->write_count++;
2833 STps = &(STp->ps[STp->partition]);
2834 STps->rw = ST_WRITING;
2835 offset = STp->buffer->buffer_bytes;
2836 blks = (offset + STp->block_size - 1) / STp->block_size;
2837 transfer = OS_FRAME_SIZE;
2838
2839 if (offset < OS_DATA_SIZE)
2840 osst_zero_buffer_tail(STp->buffer);
2841
2842
2843 if (STp->poll)
2844 result = osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120);
2845
2846 memset(cmd, 0, MAX_COMMAND_SIZE);
2847 cmd[0] = WRITE_6;
2848 cmd[1] = 1;
2849 cmd[4] = 1;
2850
2851 switch (STp->write_type) {
2852 case OS_WRITE_DATA:
2853#if DEBUG
2854 if (debugging)
2855 printk(OSST_DEB_MSG "osst%d:D: Writing %d blocks to frame %d, lblks %d-%d\n",
2856 dev, blks, STp->frame_seq_number,
2857 STp->logical_blk_num - blks, STp->logical_blk_num - 1);
2858#endif
2859 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
2860 STp->logical_blk_num - blks, STp->block_size, blks);
2861 break;
2862 case OS_WRITE_EOD:
2863 osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
2864 STp->logical_blk_num, 0, 0);
2865 break;
2866 case OS_WRITE_NEW_MARK:
2867 osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
2868 STp->logical_blk_num++, 0, blks=1);
2869 break;
2870 case OS_WRITE_HEADER:
2871 osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
2872 break;
2873 default:
2874 osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
2875 }
2876#if DEBUG
2877 if (debugging)
2878 printk(OSST_DEB_MSG "osst%d:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
2879 dev, offset, transfer, blks);
2880#endif
2881
2882 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, SCSI_DATA_WRITE,
2883 STp->timeout, MAX_WRITE_RETRIES, TRUE);
2884 *aSRpnt = SRpnt;
2885 if (!SRpnt)
2886 return (-EBUSY);
2887
2888 if ((STp->buffer)->syscall_result != 0) {
2889#if DEBUG
2890 printk(OSST_DEB_MSG
2891 "osst%d:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
2892 dev, SRpnt->sr_sense_buffer[0], SRpnt->sr_sense_buffer[2],
2893 SRpnt->sr_sense_buffer[12], SRpnt->sr_sense_buffer[13]);
2894#endif
2895 if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
2896 (SRpnt->sr_sense_buffer[2] & 0x40) &&
2897 (SRpnt->sr_sense_buffer[2] & 0x0f) == NO_SENSE) {
2898 STp->dirty = 0;
2899 (STp->buffer)->buffer_bytes = 0;
2900 result = (-ENOSPC);
2901 }
2902 else {
2903 if (osst_write_error_recovery(STp, aSRpnt, 1)) {
2904 printk(KERN_ERR "osst%d:E: Error on flush write.\n", dev);
2905 result = (-EIO);
2906 }
2907 }
2908 STps->drv_block = (-1);
2909 }
2910 else {
2911 STp->first_frame_position++;
2912 STp->dirty = 0;
2913 (STp->buffer)->buffer_bytes = 0;
2914 }
2915 }
2916#if DEBUG
2917 printk(OSST_DEB_MSG "osst%d:D: Exit flush write buffer with code %d\n", dev, result);
2918#endif
2919 return result;
2920}
2921
2922
2923
2924
2925static int osst_flush_buffer(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int seek_next)
2926{
2927 ST_partstat * STps;
2928 int backspace = 0, result = 0;
2929#if DEBUG
2930 int dev = TAPE_NR(STp->devt);
2931#endif
2932
2933
2934
2935
2936
2937 if( STp->device->was_reset )
2938 return (-EIO);
2939
2940 if (STp->ready != ST_READY)
2941 return 0;
2942
2943 STps = &(STp->ps[STp->partition]);
2944 if (STps->rw == ST_WRITING)
2945 return osst_flush_write_buffer(STp, aSRpnt);
2946
2947 if (STp->block_size == 0)
2948 return 0;
2949
2950#if DEBUG
2951 printk(OSST_DEB_MSG "osst%d:D: Reached flush (read) buffer\n", dev);
2952#endif
2953
2954 if (!STp->can_bsr) {
2955 backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
2956 ((STp->buffer)->read_pointer + STp->block_size - 1 ) / STp->block_size ;
2957 (STp->buffer)->buffer_bytes = 0;
2958 (STp->buffer)->read_pointer = 0;
2959 STp->frame_in_buffer = 0;
2960 }
2961
2962 if (!seek_next) {
2963 if (STps->eof == ST_FM_HIT) {
2964 result = cross_eof(STp, aSRpnt, FALSE);
2965 if (!result)
2966 STps->eof = ST_NOEOF;
2967 else {
2968 if (STps->drv_file >= 0)
2969 STps->drv_file++;
2970 STps->drv_block = 0;
2971 }
2972 }
2973 if (!result && backspace > 0)
2974 result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
2975 }
2976 else if (STps->eof == ST_FM_HIT) {
2977 if (STps->drv_file >= 0)
2978 STps->drv_file++;
2979 STps->drv_block = 0;
2980 STps->eof = ST_NOEOF;
2981 }
2982
2983 return result;
2984}
2985
2986static int osst_write_frame(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, int synchronous)
2987{
2988 unsigned char cmd[MAX_COMMAND_SIZE];
2989 Scsi_Request * SRpnt;
2990 int blks;
2991#if DEBUG
2992 int dev = TAPE_NR(STp->devt);
2993#endif
2994
2995 if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) {
2996#if DEBUG
2997 printk(OSST_DEB_MSG "osst%d:D: Reaching config partition.\n", dev);
2998#endif
2999 if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3000 return (-EIO);
3001 }
3002
3003 if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3004#if DEBUG
3005 printk(OSST_DEB_MSG "osst%d:D: Skipping over config partition.\n", dev);
3006#endif
3007 osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3008 }
3009 }
3010
3011 if (STp->poll)
3012 osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 60);
3013
3014
3015
3016
3017 STp->ps[STp->partition].rw = ST_WRITING;
3018 STp->write_type = OS_WRITE_DATA;
3019
3020 memset(cmd, 0, MAX_COMMAND_SIZE);
3021 cmd[0] = WRITE_6;
3022 cmd[1] = 1;
3023 cmd[4] = 1;
3024 blks = STp->buffer->buffer_bytes / STp->block_size;
3025#if DEBUG
3026 if (debugging)
3027 printk(OSST_DEB_MSG "osst%d:D: Writing %d blocks to frame %d, lblks %d-%d\n", dev, blks,
3028 STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3029#endif
3030 osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3031 STp->logical_blk_num - blks, STp->block_size, blks);
3032
3033#if DEBUG
3034 if (!synchronous)
3035 STp->write_pending = 1;
3036#endif
3037 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, SCSI_DATA_WRITE, STp->timeout,
3038 MAX_WRITE_RETRIES, synchronous);
3039 if (!SRpnt)
3040 return (-EBUSY);
3041 *aSRpnt = SRpnt;
3042
3043 if (synchronous) {
3044 if (STp->buffer->syscall_result != 0) {
3045#if DEBUG
3046 if (debugging)
3047 printk(OSST_DEB_MSG "osst%d:D: Error on write:\n", dev);
3048#endif
3049 if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
3050 (SRpnt->sr_sense_buffer[2] & 0x40)) {
3051 if ((SRpnt->sr_sense_buffer[2] & 0x0f) == VOLUME_OVERFLOW)
3052 return (-ENOSPC);
3053 }
3054 else {
3055 if (osst_write_error_recovery(STp, aSRpnt, 1))
3056 return (-EIO);
3057 }
3058 }
3059 else
3060 STp->first_frame_position++;
3061 }
3062
3063 STp->write_count++;
3064
3065 return 0;
3066}
3067
3068
3069
3070
3071
3072static ssize_t osst_write(struct file * filp, const char * buf, size_t count, loff_t *ppos)
3073{
3074 struct inode *inode = filp->f_dentry->d_inode;
3075 ssize_t total, retval = 0;
3076 ssize_t i, do_count, blks, transfer;
3077 int write_threshold;
3078 int doing_write = 0;
3079 const char *b_point;
3080 Scsi_Request * SRpnt = NULL;
3081 OS_Scsi_Tape * STp;
3082 ST_mode * STm;
3083 ST_partstat * STps;
3084 int dev = TAPE_NR(inode->i_rdev);
3085
3086 STp = os_scsi_tapes[dev];
3087
3088 if (down_interruptible(&STp->lock))
3089 return (-ERESTARTSYS);
3090
3091
3092
3093
3094
3095
3096
3097 if( !scsi_block_when_processing_errors(STp->device) ) {
3098 retval = (-ENXIO);
3099 goto out;
3100 }
3101
3102 if (ppos != &filp->f_pos) {
3103
3104 retval = (-ENXIO);
3105 goto out;
3106 }
3107
3108 if (STp->ready != ST_READY) {
3109 if (STp->ready == ST_NO_TAPE)
3110 retval = (-ENOMEDIUM);
3111 else
3112 retval = (-EIO);
3113 goto out;
3114 }
3115 STm = &(STp->modes[STp->current_mode]);
3116 if (!STm->defined) {
3117 retval = (-ENXIO);
3118 goto out;
3119 }
3120 if (count == 0)
3121 goto out;
3122
3123
3124
3125
3126
3127 if (STp->device->was_reset) {
3128 retval = (-EIO);
3129 goto out;
3130 }
3131
3132#if DEBUG
3133 if (!STp->in_use) {
3134 printk(OSST_DEB_MSG "osst%d:D: Incorrect device.\n", dev);
3135 retval = (-EIO);
3136 goto out;
3137 }
3138#endif
3139
3140 if (STp->write_prot) {
3141 retval = (-EACCES);
3142 goto out;
3143 }
3144
3145
3146 if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3147 printk(KERN_ERR "osst%d:E: Write (%ld bytes) not multiple of tape block size (%d%c).\n",
3148 dev, (unsigned long)count, STp->block_size<1024?
3149 STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3150 retval = (-EINVAL);
3151 goto out;
3152 }
3153
3154 if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3155 printk(KERN_ERR "osst%d:E: Write truncated at EOM early warning (frame %d).\n",
3156 dev, STp->first_frame_position);
3157 retval = (-ENOSPC);
3158 goto out;
3159 }
3160
3161 STps = &(STp->ps[STp->partition]);
3162
3163 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
3164 !osst_int_ioctl(STp, &SRpnt, MTLOCK, 0))
3165 STp->door_locked = ST_LOCKED_AUTO;
3166
3167
3168 if (STps->rw == ST_READING) {
3169 retval = osst_flush_buffer(STp, &SRpnt, 0);
3170 if (retval)
3171 goto out;
3172 STps->rw = ST_IDLE;
3173 }
3174 else if (STps->rw != ST_WRITING) {
3175
3176 if (!STp->header_ok ||
3177 (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3178 (STps->drv_file == 0 && STps->drv_block == 0)) {
3179 STp->wrt_pass_cntr++;
3180#if DEBUG
3181 printk(OSST_DEB_MSG "osst%d:D: Allocating next write pass counter: %d\n",
3182 dev, STp->wrt_pass_cntr);
3183#endif
3184 osst_reset_header(STp, &SRpnt);
3185 STps->drv_file = STps->drv_block = 0;
3186 }
3187
3188 else {
3189 if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3190 STps->drv_file < 0 || STps->drv_block < 0) {
3191 if (STp->first_frame_position == STp->eod_frame_ppos) {
3192 STps->drv_file = STp->filemark_cnt;
3193 STps->drv_block = 0;
3194 }
3195 else {
3196
3197#if DEBUG
3198 printk(OSST_DEB_MSG
3199 "osst%d:D: Cannot write at indeterminate position.\n", dev);
3200#endif
3201 retval = (-EIO);
3202 goto out;
3203 }
3204 }
3205 if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3206 STp->filemark_cnt = STps->drv_file;
3207 STp->last_mark_ppos =
3208 ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3209 printk(KERN_WARNING
3210 "osst%d:W: Overwriting file %d with old write pass counter %d\n",
3211 dev, STps->drv_file, STp->wrt_pass_cntr);
3212 printk(KERN_WARNING
3213 "osst%d:W: may lead to stale data being accepted on reading back!\n",
3214 dev);
3215#if DEBUG
3216 printk(OSST_DEB_MSG
3217 "osst%d:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3218 dev, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3219#endif
3220 }
3221 }
3222 STp->fast_open = FALSE;
3223 }
3224 if (!STp->header_ok) {
3225#if DEBUG
3226 printk(OSST_DEB_MSG "osst%d:D: Write cannot proceed without valid headers\n", dev);
3227#endif
3228 retval = (-EIO);
3229 goto out;
3230 }
3231
3232 if ((STp->buffer)->writing) {
3233if (SRpnt) printk(KERN_ERR "osst%d:A: Not supposed to have SRpnt at line %d\n", dev, __LINE__);
3234 osst_write_behind_check(STp);
3235 if ((STp->buffer)->syscall_result) {
3236#if DEBUG
3237 if (debugging)
3238 printk(OSST_DEB_MSG "osst%d:D: Async write error (write) %x.\n", dev,
3239 (STp->buffer)->midlevel_result);
3240#endif
3241 if ((STp->buffer)->midlevel_result == INT_MAX)
3242 STps->eof = ST_EOM_OK;
3243 else
3244 STps->eof = ST_EOM_ERROR;
3245 }
3246 }
3247 if (STps->eof == ST_EOM_OK) {
3248 retval = (-ENOSPC);
3249 goto out;
3250 }
3251 else if (STps->eof == ST_EOM_ERROR) {
3252 retval = (-EIO);
3253 goto out;
3254 }
3255
3256
3257
3258 if ((copy_from_user(&i, buf, 1) != 0 ||
3259 copy_from_user(&i, buf + count - 1, 1) != 0)) {
3260 retval = (-EFAULT);
3261 goto out;
3262 }
3263
3264 if (!STm->do_buffer_writes) {
3265 write_threshold = 1;
3266 }
3267 else
3268 write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3269 if (!STm->do_async_writes)
3270 write_threshold--;
3271
3272 total = count;
3273#if DEBUG
3274 if (debugging)
3275 printk(OSST_DEB_MSG "osst%d:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3276 dev, count, STps->drv_file, STps->drv_block,
3277 STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3278#endif
3279 b_point = buf;
3280 while ((STp->buffer)->buffer_bytes + count > write_threshold)
3281 {
3282 doing_write = 1;
3283 do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3284 (STp->buffer)->buffer_bytes;
3285 if (do_count > count)
3286 do_count = count;
3287
3288 i = append_to_buffer(b_point, STp->buffer, do_count);
3289 if (i) {
3290 retval = i;
3291 goto out;
3292 }
3293
3294 blks = do_count / STp->block_size;
3295 STp->logical_blk_num += blks;
3296
3297 i = osst_write_frame(STp, &SRpnt, TRUE);
3298
3299 if (i == (-ENOSPC)) {
3300 transfer = STp->buffer->writing;
3301 if (transfer <= do_count) {
3302 filp->f_pos += do_count - transfer;
3303 count -= do_count - transfer;
3304 if (STps->drv_block >= 0) {
3305 STps->drv_block += (do_count - transfer) / STp->block_size;
3306 }
3307 STps->eof = ST_EOM_OK;
3308 retval = (-ENOSPC);
3309#if DEBUG
3310 if (debugging)
3311 printk(OSST_DEB_MSG "osst%d:D: EOM with %d bytes unwritten.\n",
3312 dev, transfer);
3313#endif
3314 }
3315 else {
3316 STps->eof = ST_EOM_ERROR;
3317 STps->drv_block = (-1);
3318 retval = (-EIO);
3319#if DEBUG
3320 if (debugging)
3321 printk(OSST_DEB_MSG "osst%d:D: EOM with lost data.\n", dev);
3322#endif
3323 }
3324 }
3325 else
3326 retval = i;
3327
3328 if (retval < 0) {
3329 if (SRpnt != NULL) {
3330 scsi_release_request(SRpnt);
3331 SRpnt = NULL;
3332 }
3333 STp->buffer->buffer_bytes = 0;
3334 STp->dirty = 0;
3335 if (count < total)
3336 retval = total - count;
3337 goto out;
3338 }
3339
3340 filp->f_pos += do_count;
3341 b_point += do_count;
3342 count -= do_count;
3343 if (STps->drv_block >= 0) {
3344 STps->drv_block += blks;
3345 }
3346 STp->buffer->buffer_bytes = 0;
3347 STp->dirty = 0;
3348 }
3349
3350 if (count != 0) {
3351 STp->dirty = 1;
3352 i = append_to_buffer(b_point, STp->buffer, count);
3353 if (i) {
3354 retval = i;
3355 goto out;
3356 }
3357 blks = count / STp->block_size;
3358 STp->logical_blk_num += blks;
3359 if (STps->drv_block >= 0) {
3360 STps->drv_block += blks;
3361 }
3362 filp->f_pos += count;
3363 count = 0;
3364 }
3365
3366 if (doing_write && (STp->buffer)->syscall_result != 0) {
3367 retval = (STp->buffer)->syscall_result;
3368 goto out;
3369 }
3370
3371 if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) {
3372
3373 (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3374 STp->block_size) * STp->block_size;
3375 STp->dirty = !((STp->buffer)->writing ==
3376 (STp->buffer)->buffer_bytes);
3377
3378 i = osst_write_frame(STp, &SRpnt, FALSE);
3379 if (i < 0) {
3380 retval = (-EIO);
3381 goto out;
3382 }
3383 SRpnt = NULL;
3384 }
3385 STps->at_sm &= (total == 0);
3386 if (total > 0)
3387 STps->eof = ST_NOEOF;
3388
3389 retval = total;
3390
3391out:
3392 if (SRpnt != NULL) scsi_release_request(SRpnt);
3393
3394 up(&STp->lock);
3395
3396 return retval;
3397}
3398
3399
3400
3401static ssize_t osst_read(struct file * filp, char * buf, size_t count, loff_t *ppos)
3402{
3403 struct inode * inode = filp->f_dentry->d_inode;
3404 ssize_t total, retval = 0;
3405 ssize_t i, transfer;
3406 int special;
3407 OS_Scsi_Tape * STp;
3408 ST_mode * STm;
3409 ST_partstat * STps;
3410 Scsi_Request *SRpnt = NULL;
3411 int dev = TAPE_NR(inode->i_rdev);
3412
3413 STp = os_scsi_tapes[dev];
3414
3415 if (down_interruptible(&STp->lock))
3416 return (-ERESTARTSYS);
3417
3418
3419
3420
3421
3422
3423
3424 if( !scsi_block_when_processing_errors(STp->device) ) {
3425 retval = (-ENXIO);
3426 goto out;
3427 }
3428
3429 if (ppos != &filp->f_pos) {
3430
3431 retval = (-ENXIO);
3432 goto out;
3433 }
3434
3435 if (STp->ready != ST_READY) {
3436 if (STp->ready == ST_NO_TAPE)
3437 retval = (-ENOMEDIUM);
3438 else
3439 retval = (-EIO);
3440 goto out;
3441 }
3442 STm = &(STp->modes[STp->current_mode]);
3443 if (!STm->defined) {
3444 retval = (-ENXIO);
3445 goto out;
3446 }
3447#if DEBUG
3448 if (!STp->in_use) {
3449 printk(OSST_DEB_MSG "osst%d:D: Incorrect device.\n", dev);
3450 retval = (-EIO);
3451 goto out;
3452 }
3453#endif
3454
3455 if (!STp->header_ok) {
3456 retval = (-EIO);
3457 goto out;
3458 }
3459
3460 if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
3461 !osst_int_ioctl(STp, &SRpnt, MTLOCK, 0))
3462 STp->door_locked = ST_LOCKED_AUTO;
3463
3464 STps = &(STp->ps[STp->partition]);
3465 if (STps->rw == ST_WRITING) {
3466 retval = osst_flush_buffer(STp, &SRpnt, 0);
3467 if (retval)
3468 goto out;
3469 STps->rw = ST_IDLE;
3470
3471 }
3472
3473 if ((count % STp->block_size) != 0) {
3474 printk(KERN_WARNING
3475 "osst%d:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", dev, count,
3476 STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3477 }
3478
3479#if DEBUG
3480 if (debugging && STps->eof != ST_NOEOF)
3481 printk(OSST_DEB_MSG "osst%d:D: EOF/EOM flag up (%d). Bytes %d\n", dev,
3482 STps->eof, (STp->buffer)->buffer_bytes);
3483#endif
3484 if ((STp->buffer)->buffer_bytes == 0 &&
3485 STps->eof >= ST_EOD_1) {
3486 if (STps->eof < ST_EOD) {
3487 STps->eof += 1;
3488 retval = 0;
3489 goto out;
3490 }
3491 retval = (-EIO);
3492 goto out;
3493 }
3494
3495
3496
3497 if (copy_from_user(&i, buf, 1) != 0 ||
3498 copy_to_user (buf, &i, 1) != 0 ||
3499 copy_from_user(&i, buf + count - 1, 1) != 0 ||
3500 copy_to_user (buf + count - 1, &i, 1) != 0) {
3501 retval = (-EFAULT);
3502 goto out;
3503 }
3504
3505
3506 for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3507
3508
3509 if ((STp->buffer)->buffer_bytes == 0) {
3510 if (STps->eof == ST_FM_HIT)
3511 break;
3512 special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3513 if (special < 0) {
3514 STp->frame_in_buffer = 0;
3515 retval = special;
3516 goto out;
3517 }
3518 }
3519
3520
3521 if ((STp->buffer)->buffer_bytes > 0) {
3522#if DEBUG
3523 if (debugging && STps->eof != ST_NOEOF)
3524 printk(OSST_DEB_MSG "osst%d:D: EOF up (%d). Left %d, needed %d.\n", dev,
3525 STps->eof, (STp->buffer)->buffer_bytes, count - total);
3526#endif
3527 transfer = (((STp->buffer)->buffer_bytes < count - total ?
3528 (STp->buffer)->buffer_bytes : count - total)/
3529 STp->block_size) * STp->block_size;
3530 i = from_buffer(STp->buffer, buf, transfer);
3531 if (i) {
3532 retval = i;
3533 goto out;
3534 }
3535 STp->logical_blk_num += transfer / STp->block_size;
3536 STps->drv_block += transfer / STp->block_size;
3537 filp->f_pos += transfer;
3538 buf += transfer;
3539 total += transfer;
3540 }
3541
3542 if ((STp->buffer)->buffer_bytes == 0) {
3543#if DEBUG
3544 if (debugging)
3545 printk(OSST_DEB_MSG "osst%d:D: Finished with frame %d\n",
3546 dev, STp->frame_seq_number);
3547#endif
3548 STp->frame_in_buffer = 0;
3549 STp->frame_seq_number++;
3550 }
3551 }
3552
3553
3554 if (total == 0) {
3555 if (STps->eof == ST_FM_HIT) {
3556 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
3557 STps->drv_block = 0;
3558 if (STps->drv_file >= 0)
3559 STps->drv_file++;
3560 }
3561 else if (STps->eof == ST_EOD_1) {
3562 STps->eof = ST_EOD_2;
3563 if (STps->drv_block > 0 && STps->drv_file >= 0)
3564 STps->drv_file++;
3565 STps->drv_block = 0;
3566 }
3567 else if (STps->eof == ST_EOD_2)
3568 STps->eof = ST_EOD;
3569 }
3570 else if (STps->eof == ST_FM)
3571 STps->eof = ST_NOEOF;
3572
3573 retval = total;
3574
3575out:
3576 if (SRpnt != NULL) scsi_release_request(SRpnt);
3577
3578 up(&STp->lock);
3579
3580 return retval;
3581}
3582
3583
3584
3585static void osst_log_options(OS_Scsi_Tape *STp, ST_mode *STm, int dev)
3586{
3587 printk(KERN_INFO
3588"osst%d:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3589 dev, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3590 STm->do_read_ahead);
3591 printk(KERN_INFO
3592"osst%d:I: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3593 dev, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3594 printk(KERN_INFO
3595"osst%d:I: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3596 dev, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3597 STp->scsi2_logical);
3598 printk(KERN_INFO
3599"osst%d:I: sysv: %d\n", dev, STm->sysv);
3600#if DEBUG
3601 printk(KERN_INFO
3602 "osst%d:D: debugging: %d\n",
3603 dev, debugging);
3604#endif
3605}
3606
3607
3608static int osst_set_options(OS_Scsi_Tape *STp, long options)
3609{
3610 int value;
3611 long code;
3612 ST_mode *STm;
3613 int dev = TAPE_NR(STp->devt);
3614
3615 STm = &(STp->modes[STp->current_mode]);
3616 if (!STm->defined) {
3617 memcpy(STm, &(STp->modes[0]), sizeof(ST_mode));
3618 modes_defined = TRUE;
3619#if DEBUG
3620 if (debugging)
3621 printk(OSST_DEB_MSG "osst%d:D: Initialized mode %d definition from mode 0\n",
3622 dev, STp->current_mode);
3623#endif
3624 }
3625
3626 code = options & MT_ST_OPTIONS;
3627 if (code == MT_ST_BOOLEANS) {
3628 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3629 STm->do_async_writes = (options & MT_ST_ASYNC_WRITES) != 0;
3630 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3631 STm->do_read_ahead = (options & MT_ST_READ_AHEAD) != 0;
3632 STp->two_fm = (options & MT_ST_TWO_FM) != 0;
3633 STp->fast_mteom = (options & MT_ST_FAST_MTEOM) != 0;
3634 STp->do_auto_lock = (options & MT_ST_AUTO_LOCK) != 0;
3635 STp->can_bsr = (options & MT_ST_CAN_BSR) != 0;
3636 STp->omit_blklims = (options & MT_ST_NO_BLKLIMS) != 0;
3637 if ((STp->device)->scsi_level >= SCSI_2)
3638 STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3639 STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0;
3640 STm->sysv = (options & MT_ST_SYSV) != 0;
3641#if DEBUG
3642 debugging = (options & MT_ST_DEBUGGING) != 0;
3643#endif
3644 osst_log_options(STp, STm, dev);
3645 }
3646 else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3647 value = (code == MT_ST_SETBOOLEANS);
3648 if ((options & MT_ST_BUFFER_WRITES) != 0)
3649 STm->do_buffer_writes = value;
3650 if ((options & MT_ST_ASYNC_WRITES) != 0)
3651 STm->do_async_writes = value;
3652 if ((options & MT_ST_DEF_WRITES) != 0)
3653 STm->defaults_for_writes = value;
3654 if ((options & MT_ST_READ_AHEAD) != 0)
3655 STm->do_read_ahead = value;
3656 if ((options & MT_ST_TWO_FM) != 0)
3657 STp->two_fm = value;
3658 if ((options & MT_ST_FAST_MTEOM) != 0)
3659 STp->fast_mteom = value;
3660 if ((options & MT_ST_AUTO_LOCK) != 0)
3661 STp->do_auto_lock = value;
3662 if ((options & MT_ST_CAN_BSR) != 0)
3663 STp->can_bsr = value;
3664 if ((options & MT_ST_NO_BLKLIMS) != 0)
3665 STp->omit_blklims = value;
3666 if ((STp->device)->scsi_level >= SCSI_2 &&
3667 (options & MT_ST_CAN_PARTITIONS) != 0)
3668 STp->can_partitions = value;
3669 if ((options & MT_ST_SCSI2LOGICAL) != 0)
3670 STp->scsi2_logical = value;
3671 if ((options & MT_ST_SYSV) != 0)
3672 STm->sysv = value;
3673#if DEBUG
3674 if ((options & MT_ST_DEBUGGING) != 0)
3675 debugging = value;
3676#endif
3677 osst_log_options(STp, STm, dev);
3678 }
3679 else if (code == MT_ST_WRITE_THRESHOLD) {
3680 value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3681 if (value < 1 || value > osst_buffer_size) {
3682 printk(KERN_WARNING "osst%d:W: Write threshold %d too small or too large.\n",
3683 dev, value);
3684 return (-EIO);
3685 }
3686 STp->write_threshold = value;
3687 printk(KERN_INFO "osst%d:I: Write threshold set to %d bytes.\n",
3688 dev, value);
3689 }
3690 else if (code == MT_ST_DEF_BLKSIZE) {
3691 value = (options & ~MT_ST_OPTIONS);
3692 if (value == ~MT_ST_OPTIONS) {
3693 STm->default_blksize = (-1);
3694 printk(KERN_INFO "osst%d:I: Default block size disabled.\n", dev);
3695 }
3696 else {
3697 if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3698 printk(KERN_WARNING "osst%d:W: Default block size cannot be set to %d.\n",
3699 dev, value);
3700 return (-EINVAL);
3701 }
3702 STm->default_blksize = value;
3703 printk(KERN_INFO "osst%d:I: Default block size set to %d bytes.\n",
3704 dev, STm->default_blksize);
3705 }
3706 }
3707 else if (code == MT_ST_TIMEOUTS) {
3708 value = (options & ~MT_ST_OPTIONS);
3709 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
3710 STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
3711 printk(KERN_INFO "osst%d:I: Long timeout set to %d seconds.\n", dev,
3712 (value & ~MT_ST_SET_LONG_TIMEOUT));
3713 }
3714 else {
3715 STp->timeout = value * HZ;
3716 printk(KERN_INFO "osst%d:I: Normal timeout set to %d seconds.\n", dev, value);
3717 }
3718 }
3719 else if (code == MT_ST_DEF_OPTIONS) {
3720 code = (options & ~MT_ST_CLEAR_DEFAULT);
3721 value = (options & MT_ST_CLEAR_DEFAULT);
3722 if (code == MT_ST_DEF_DENSITY) {
3723 if (value == MT_ST_CLEAR_DEFAULT) {
3724 STm->default_density = (-1);
3725 printk(KERN_INFO "osst%d:I: Density default disabled.\n", dev);
3726 }
3727 else {
3728 STm->default_density = value & 0xff;
3729 printk(KERN_INFO "osst%d:I: Density default set to %x\n",
3730 dev, STm->default_density);
3731 }
3732 }
3733 else if (code == MT_ST_DEF_DRVBUFFER) {
3734 if (value == MT_ST_CLEAR_DEFAULT) {
3735 STp->default_drvbuffer = 0xff;
3736 printk(KERN_INFO "osst%d:I: Drive buffer default disabled.\n", dev);
3737 }
3738 else {
3739 STp->default_drvbuffer = value & 7;
3740 printk(KERN_INFO "osst%d:I: Drive buffer default set to %x\n",
3741 dev, STp->default_drvbuffer);
3742 }
3743 }
3744 else if (code == MT_ST_DEF_COMPRESSION) {
3745 if (value == MT_ST_CLEAR_DEFAULT) {
3746 STm->default_compression = ST_DONT_TOUCH;
3747 printk(KERN_INFO "osst%d:I: Compression default disabled.\n", dev);
3748 }
3749 else {
3750 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
3751 printk(KERN_INFO "osst%d:I: Compression default set to %x\n",
3752 dev, (value & 1));
3753 }
3754 }
3755 }
3756 else
3757 return (-EIO);
3758
3759 return 0;
3760}
3761
3762
3763
3764static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned int cmd_in, unsigned long arg)
3765{
3766 int timeout;
3767 long ltmp;
3768 int i, ioctl_result;
3769 int chg_eof = TRUE;
3770 unsigned char cmd[MAX_COMMAND_SIZE];
3771 Scsi_Request * SRpnt = * aSRpnt;
3772 ST_partstat * STps;
3773 int fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
3774 int datalen = 0, direction = SCSI_DATA_NONE;
3775 int dev = TAPE_NR(STp->devt);
3776
3777 if (STp->ready != ST_READY && cmd_in != MTLOAD) {
3778 if (STp->ready == ST_NO_TAPE)
3779 return (-ENOMEDIUM);
3780 else
3781 return (-EIO);
3782 }
3783 timeout = STp->long_timeout;
3784 STps = &(STp->ps[STp->partition]);
3785 fileno = STps->drv_file;
3786 blkno = STps->drv_block;
3787 at_sm = STps->at_sm;
3788 frame_seq_numbr = STp->frame_seq_number;
3789 logical_blk_num = STp->logical_blk_num;
3790
3791 memset(cmd, 0, MAX_COMMAND_SIZE);
3792 switch (cmd_in) {
3793 case MTFSFM:
3794 chg_eof = FALSE;
3795 case MTFSF:
3796 if (STp->raw)
3797 return (-EIO);
3798 if (STp->linux_media)
3799 ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
3800 else
3801 ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
3802 if (fileno >= 0)
3803 fileno += arg;
3804 blkno = 0;
3805 at_sm &= (arg == 0);
3806 goto os_bypass;
3807
3808 case MTBSF:
3809 chg_eof = FALSE;
3810 case MTBSFM:
3811 if (STp->raw)
3812 return (-EIO);
3813 ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
3814 if (fileno >= 0)
3815 fileno -= arg;
3816 blkno = (-1);
3817 at_sm &= (arg == 0);
3818 goto os_bypass;
3819
3820 case MTFSR:
3821 case MTBSR:
3822#if DEBUG
3823 if (debugging)
3824 printk(OSST_DEB_MSG "osst%d:D: Skipping %lu blocks %s from logical block %d\n",
3825 dev, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
3826#endif
3827 if (cmd_in == MTFSR) {
3828 logical_blk_num += arg;
3829 if (blkno >= 0) blkno += arg;
3830 }
3831 else {
3832 logical_blk_num -= arg;
3833 if (blkno >= 0) blkno -= arg;
3834 }
3835 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
3836 fileno = STps->drv_file;
3837 blkno = STps->drv_block;
3838 at_sm &= (arg == 0);
3839 goto os_bypass;
3840
3841 case MTFSS:
3842 cmd[0] = SPACE;
3843 cmd[1] = 0x04;
3844 cmd[2] = (arg >> 16);
3845 cmd[3] = (arg >> 8);
3846 cmd[4] = arg;
3847#if DEBUG
3848 if (debugging)
3849 printk(OSST_DEB_MSG "osst%d:D: Spacing tape forward %d setmarks.\n", dev,
3850 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
3851#endif
3852 if (arg != 0) {
3853 blkno = fileno = (-1);
3854 at_sm = 1;
3855 }
3856 break;
3857 case MTBSS:
3858 cmd[0] = SPACE;
3859 cmd[1] = 0x04;
3860 ltmp = (-arg);
3861 cmd[2] = (ltmp >> 16);
3862 cmd[3] = (ltmp >> 8);
3863 cmd[4] = ltmp;
3864#if DEBUG
3865 if (debugging) {
3866 if (cmd[2] & 0x80)
3867 ltmp = 0xff000000;
3868 ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
3869 printk(OSST_DEB_MSG "osst%d:D: Spacing tape backward %ld setmarks.\n",
3870 dev, (-ltmp));
3871 }
3872#endif
3873 if (arg != 0) {
3874 blkno = fileno = (-1);
3875 at_sm = 1;
3876 }
3877 break;
3878 case MTWEOF:
3879 if ( STps->rw == ST_WRITING && !(STp->device)->was_reset)
3880 ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
3881 else
3882 ioctl_result = 0;
3883#if DEBUG
3884 if (debugging)
3885 printk(OSST_DEB_MSG "osst%d:D: Writing %ld filemark(s).\n", dev, arg);
3886#endif
3887 for (i=0; i<arg; i++)
3888 ioctl_result |= osst_write_filemark(STp, &SRpnt);
3889 if (fileno >= 0) fileno += arg;
3890 if (blkno >= 0) blkno = 0;
3891 goto os_bypass;
3892
3893 case MTWSM:
3894 if (STp->write_prot)
3895 return (-EACCES);
3896 if (!STp->raw)
3897 return 0;
3898 cmd[0] = WRITE_FILEMARKS;
3899 if (cmd_in == MTWSM)
3900 cmd[1] = 2;
3901 cmd[2] = (arg >> 16);
3902 cmd[3] = (arg >> 8);
3903 cmd[4] = arg;
3904 timeout = STp->timeout;
3905#if DEBUG
3906 if (debugging)
3907 printk(OSST_DEB_MSG "osst%d:D: Writing %d setmark(s).\n", dev,
3908 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
3909#endif
3910 if (fileno >= 0)
3911 fileno += arg;
3912 blkno = 0;
3913 at_sm = (cmd_in == MTWSM);
3914 break;
3915 case MTOFFL:
3916 case MTLOAD:
3917 case MTUNLOAD:
3918 case MTRETEN:
3919 cmd[0] = START_STOP;
3920 cmd[1] = 1;
3921 if (cmd_in == MTLOAD) {
3922 if (STp->ready == ST_NO_TAPE)
3923 cmd[4] = 4;
3924 else
3925 cmd[4] = 1;
3926 }
3927 if (cmd_in == MTRETEN)
3928 cmd[4] = 3;
3929 if (cmd_in == MTOFFL)
3930 cmd[4] = 4;
3931 timeout = STp->timeout;
3932#if DEBUG
3933 if (debugging) {
3934 switch (cmd_in) {
3935 case MTUNLOAD:
3936 printk(OSST_DEB_MSG "osst%d:D: Unloading tape.\n", dev);
3937 break;
3938 case MTLOAD:
3939 printk(OSST_DEB_MSG "osst%d:D: Loading tape.\n", dev);
3940 break;
3941 case MTRETEN:
3942 printk(OSST_DEB_MSG "osst%d:D: Retensioning tape.\n", dev);
3943 break;
3944 case MTOFFL:
3945 printk(OSST_DEB_MSG "osst%d:D: Ejecting tape.\n", dev);
3946 break;
3947 }
3948 }
3949#endif
3950 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
3951 break;
3952 case MTNOP:
3953#if DEBUG
3954 if (debugging)
3955 printk(OSST_DEB_MSG "osst%d:D: No-op on tape.\n", dev);
3956#endif
3957 return 0;
3958 break;
3959 case MTEOM:
3960#if DEBUG
3961 if (debugging)
3962 printk(OSST_DEB_MSG "osst%d:D: Spacing to end of recorded medium.\n", dev);
3963#endif
3964 osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
3965 if (osst_get_logical_frame(STp, &SRpnt, -1, 0) < 0) {
3966 ioctl_result = -EIO;
3967 goto os_bypass;
3968 }
3969 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
3970#if DEBUG
3971 printk(OSST_DEB_MSG "osst%d:D: No EOD frame found where expected.\n", dev);
3972#endif
3973 ioctl_result = -EIO;
3974 goto os_bypass;
3975 }
3976 ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
3977 fileno = STp->filemark_cnt;
3978 blkno = at_sm = 0;
3979 goto os_bypass;
3980
3981 case MTERASE:
3982 if (STp->write_prot)
3983 return (-EACCES);
3984 ioctl_result = osst_reset_header(STp, &SRpnt);
3985 i = osst_write_eod(STp, &SRpnt);
3986 if (i < ioctl_result) ioctl_result = i;
3987 i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
3988 if (i < ioctl_result) ioctl_result = i;
3989 fileno = blkno = at_sm = 0 ;
3990 goto os_bypass;
3991
3992 case MTREW:
3993 cmd[0] = REZERO_UNIT;
3994 cmd[1] = 1;
3995#if DEBUG
3996 if (debugging)
3997 printk(OSST_DEB_MSG "osst%d:D: Rewinding tape, Immed=%d.\n", dev, cmd[1]);
3998#endif
3999 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4000 break;
4001
4002 case MTLOCK:
4003 chg_eof = FALSE;
4004 cmd[0] = ALLOW_MEDIUM_REMOVAL;
4005 cmd[4] = SCSI_REMOVAL_PREVENT;
4006#if DEBUG
4007 if (debugging)
4008 printk(OSST_DEB_MSG "osst%d:D: Locking drive door.\n", dev);
4009#endif
4010 break;
4011
4012 case MTUNLOCK:
4013 chg_eof = FALSE;
4014 cmd[0] = ALLOW_MEDIUM_REMOVAL;
4015 cmd[4] = SCSI_REMOVAL_ALLOW;
4016#if DEBUG
4017 if (debugging)
4018 printk(OSST_DEB_MSG "osst%d:D: Unlocking drive door.\n", dev);
4019#endif
4020 break;
4021
4022 case MTSETBLK:
4023 case MTSETDENSITY:
4024 case MTSETDRVBUFFER:
4025 case SET_DENS_AND_BLK:
4026 chg_eof = FALSE;
4027 if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4028 return (-EIO);
4029 if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4030 (arg & MT_ST_BLKSIZE_MASK) != 0 &&
4031 ((arg & MT_ST_BLKSIZE_MASK) < STp->min_block ||
4032 (arg & MT_ST_BLKSIZE_MASK) > STp->max_block ||
4033 (arg & MT_ST_BLKSIZE_MASK) > osst_buffer_size)) {
4034 printk(KERN_WARNING "osst%d:W: Illegal block size.\n", dev);
4035 return (-EINVAL);
4036 }
4037 return 0;
4038
4039 default:
4040 return (-ENOSYS);
4041 }
4042
4043 SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, TRUE);
4044
4045 ioctl_result = (STp->buffer)->syscall_result;
4046
4047 if (!SRpnt) {
4048#if DEBUG
4049 printk(OSST_DEB_MSG "osst%d:D: Couldn't exec scsi cmd for IOCTL\n", dev);
4050#endif
4051 return ioctl_result;
4052 }
4053
4054 if (!ioctl_result) {
4055 STp->frame_seq_number = frame_seq_numbr;
4056 STp->logical_blk_num = logical_blk_num;
4057 }
4058
4059os_bypass:
4060#if DEBUG
4061 if (debugging)
4062 printk(OSST_DEB_MSG "osst%d:D: IOCTL (%d) Result=%d\n", dev, cmd_in, ioctl_result);
4063#endif
4064
4065 if (!ioctl_result) {
4066
4067 if (cmd_in == MTFSFM) {
4068 fileno--;
4069 blkno--;
4070 }
4071 if (cmd_in == MTBSFM) {
4072 fileno++;
4073 blkno++;
4074 }
4075 STps->drv_block = blkno;
4076 STps->drv_file = fileno;
4077 STps->at_sm = at_sm;
4078
4079 if (cmd_in == MTLOCK)
4080 STp->door_locked = ST_LOCKED_EXPLICIT;
4081 else if (cmd_in == MTUNLOCK)
4082 STp->door_locked = ST_UNLOCKED;
4083
4084 if (cmd_in == MTEOM)
4085 STps->eof = ST_EOD;
4086 else if (cmd_in == MTFSF)
4087 STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4088 else if (chg_eof)
4089 STps->eof = ST_NOEOF;
4090
4091 if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4092 STp->rew_at_close = 0;
4093 else if (cmd_in == MTLOAD) {
4094
4095 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4096 STp->ps[i].rw = ST_IDLE;
4097 STp->ps[i].last_block_valid = FALSE;
4098 }
4099 STp->partition = 0;
4100 }
4101
4102 if (cmd_in == MTREW) {
4103 ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4104 if (ioctl_result > 0)
4105 ioctl_result = 0;
4106 }
4107
4108 } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4109 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4110 STps->drv_file = STps->drv_block = -1;
4111 else
4112 STps->drv_file = STps->drv_block = 0;
4113 STps->eof = ST_NOEOF;
4114 } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4115 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4116 STps->drv_file = STps->drv_block = -1;
4117 else {
4118 STps->drv_file = STp->filemark_cnt;
4119 STps->drv_block = 0;
4120 }
4121 STps->eof = ST_EOD;
4122 } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4123 STps->drv_file = STps->drv_block = (-1);
4124 STps->eof = ST_NOEOF;
4125 STp->header_ok = 0;
4126 } else if (cmd_in == MTERASE) {
4127 STp->header_ok = 0;
4128 } else if (SRpnt) {
4129 if (SRpnt->sr_sense_buffer[2] & 0x40) {
4130 STps->eof = ST_EOM_OK;
4131 STps->drv_block = 0;
4132 }
4133 if (chg_eof)
4134 STps->eof = ST_NOEOF;
4135
4136 if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK)
4137 STps->eof = ST_EOD;
4138
4139 if (cmd_in == MTLOCK)
4140 STp->door_locked = ST_LOCK_FAILS;
4141
4142 if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4143 ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60);
4144 }
4145 *aSRpnt = SRpnt;
4146
4147 return ioctl_result;
4148}
4149
4150
4151
4152static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4153{
4154 unsigned short flags;
4155 int i, b_size, need_dma_buffer, new_session = FALSE, retval = 0;
4156 unsigned char cmd[MAX_COMMAND_SIZE];
4157 Scsi_Request * SRpnt;
4158 OS_Scsi_Tape * STp;
4159 ST_mode * STm;
4160 ST_partstat * STps;
4161 int dev = TAPE_NR(inode->i_rdev);
4162 int mode = TAPE_MODE(inode->i_rdev);
4163
4164 if (dev >= osst_template.dev_max || (STp = os_scsi_tapes[dev]) == NULL || !STp->device)
4165 return (-ENXIO);
4166
4167 if( !scsi_block_when_processing_errors(STp->device) ) {
4168 return -ENXIO;
4169 }
4170
4171 if (STp->in_use) {
4172#if DEBUG
4173 printk(OSST_DEB_MSG "osst%d:D: Device already in use.\n", dev);
4174#endif
4175 return (-EBUSY);
4176 }
4177 STp->in_use = 1;
4178 STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;
4179
4180 if (STp->device->host->hostt->module)
4181 __MOD_INC_USE_COUNT(STp->device->host->hostt->module);
4182 if (osst_template.module)
4183 __MOD_INC_USE_COUNT(osst_template.module);
4184 STp->device->access_count++;
4185
4186 if (mode != STp->current_mode) {
4187#if DEBUG
4188 if (debugging)
4189 printk(OSST_DEB_MSG "osst%d:D: Mode change from %d to %d.\n",
4190 dev, STp->current_mode, mode);
4191#endif
4192 new_session = TRUE;
4193 STp->current_mode = mode;
4194 }
4195 STm = &(STp->modes[STp->current_mode]);
4196
4197 flags = filp->f_flags;
4198 STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4199
4200 STp->raw = (MINOR(inode->i_rdev) & 0x40) != 0;
4201 if (STp->raw)
4202 STp->header_ok = 0;
4203
4204
4205 need_dma_buffer = STp->restr_dma;
4206 for (i=0; i < osst_nbr_buffers; i++)
4207 if (!osst_buffers[i]->in_use &&
4208 (!need_dma_buffer || osst_buffers[i]->dma))
4209 break;
4210 if (i >= osst_nbr_buffers) {
4211 STp->buffer = new_tape_buffer(FALSE, need_dma_buffer);
4212 if (STp->buffer == NULL) {
4213 printk(KERN_WARNING "osst%d:W: Can't allocate tape buffer.\n", dev);
4214 retval = (-EBUSY);
4215 goto err_out;
4216 }
4217 }
4218 else
4219 STp->buffer = osst_buffers[i];
4220 (STp->buffer)->in_use = 1;
4221 (STp->buffer)->writing = 0;
4222 (STp->buffer)->syscall_result = 0;
4223 (STp->buffer)->use_sg = STp->device->host->sg_tablesize;
4224
4225
4226 if (!(STp->buffer)->use_sg)
4227 (STp->buffer)->buffer_size = (STp->buffer)->sg[0].length;
4228 else {
4229 for (i=0, (STp->buffer)->buffer_size = 0; i < (STp->buffer)->use_sg &&
4230 i < (STp->buffer)->sg_segs; i++)
4231 (STp->buffer)->buffer_size += (STp->buffer)->sg[i].length;
4232 }
4233
4234 STp->dirty = 0;
4235 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4236 STps = &(STp->ps[i]);
4237 STps->rw = ST_IDLE;
4238 }
4239 STp->ready = ST_READY;
4240#if DEBUG
4241 STp->nbr_waits = STp->nbr_finished = 0;
4242#endif
4243
4244 memset (cmd, 0, MAX_COMMAND_SIZE);
4245 cmd[0] = TEST_UNIT_READY;
4246
4247 SRpnt = osst_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
4248 if (!SRpnt) {
4249 retval = (STp->buffer)->syscall_result;
4250 goto err_out;
4251 }
4252 if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
4253 (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY &&
4254 SRpnt->sr_sense_buffer[12] == 4 ) {
4255#if DEBUG
4256 printk(OSST_DEB_MSG "osst%d:D: Unit not ready, cause %x\n", dev, SRpnt->sr_sense_buffer[13]);
4257#endif
4258 if (SRpnt->sr_sense_buffer[13] == 2) {
4259 memset (cmd, 0, MAX_COMMAND_SIZE);
4260 cmd[0] = START_STOP;
4261 cmd[1] = 1;
4262 cmd[4] = 1;
4263 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
4264 STp->timeout, MAX_READY_RETRIES, TRUE);
4265 }
4266 osst_wait_ready(STp, &SRpnt, (SRpnt->sr_sense_buffer[13]==1?15:3) * 60);
4267 }
4268 if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
4269 (SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) {
4270#if DEBUG
4271 printk(OSST_DEB_MSG "osst%d:D: Unit wants attention\n", dev);
4272#endif
4273 STp->header_ok = 0;
4274
4275 for (i=0; i < 10; i++) {
4276
4277 memset (cmd, 0, MAX_COMMAND_SIZE);
4278 cmd[0] = TEST_UNIT_READY;
4279
4280 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
4281 STp->timeout, MAX_READY_RETRIES, TRUE);
4282 if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
4283 (SRpnt->sr_sense_buffer[2] & 0x0f) != UNIT_ATTENTION)
4284 break;
4285 }
4286
4287 STp->device->was_reset = 0;
4288 STp->partition = STp->new_partition = 0;
4289 if (STp->can_partitions)
4290 STp->nbr_partitions = 1;
4291 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4292 STps = &(STp->ps[i]);
4293 STps->rw = ST_IDLE;
4294 STps->eof = ST_NOEOF;
4295 STps->at_sm = 0;
4296 STps->last_block_valid = FALSE;
4297 STps->drv_block = 0;
4298 STps->drv_file = 0 ;
4299 }
4300 new_session = TRUE;
4301 STp->recover_count = 0;
4302 }
4303
4304
4305
4306
4307 if (!STp->buffer->syscall_result && STp->header_ok &&
4308 !SRpnt->sr_result && SRpnt->sr_sense_buffer[0] == 0) {
4309
4310 memset(cmd, 0, MAX_COMMAND_SIZE);
4311 cmd[0] = MODE_SENSE;
4312 cmd[1] = 8;
4313 cmd[2] = VENDOR_IDENT_PAGE;
4314 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4315
4316 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
4317
4318 if (STp->buffer->syscall_result ||
4319 STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4320 STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4321 STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4322 STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4' ) {
4323#if DEBUG
4324 printk(OSST_DEB_MSG "osst%d:D: Signature was changed to %c%c%c%c\n", dev,
4325 STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4326 STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4327 STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4328 STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4329#endif
4330 STp->header_ok = 0;
4331 }
4332 i = STp->first_frame_position;
4333 if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4334 if (STp->door_locked == ST_UNLOCKED) {
4335 if (osst_int_ioctl(STp, &SRpnt, MTLOCK, 0))
4336 printk(KERN_INFO "osst%d:I: Can't lock drive door\n", dev);
4337 else
4338 STp->door_locked = ST_LOCKED_AUTO;
4339 }
4340 if (!STp->frame_in_buffer) {
4341 STp->block_size = (STm->default_blksize > 0) ?
4342 STm->default_blksize : OS_DATA_SIZE;
4343 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4344 }
4345 STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4346 STp->fast_open = TRUE;
4347 scsi_release_request(SRpnt);
4348 return 0;
4349 }
4350#if DEBUG
4351 if (i != STp->first_frame_position)
4352 printk(OSST_DEB_MSG "osst%d:D: Tape position changed from %d to %d\n",
4353 dev, i, STp->first_frame_position);
4354#endif
4355 STp->header_ok = 0;
4356 }
4357 STp->fast_open = FALSE;
4358
4359 if ((STp->buffer)->syscall_result != 0 &&
4360 (SRpnt->sr_sense_buffer[2] != 2 || SRpnt->sr_sense_buffer[12] != 0x3A) ) {
4361
4362 memset(cmd, 0, MAX_COMMAND_SIZE);
4363 cmd[0] = MODE_SELECT;
4364 cmd[1] = 0x10;
4365 cmd[4] = 4 + MODE_HEADER_LENGTH;
4366
4367 (STp->buffer)->b_data[0] = cmd[4] - 1;
4368 (STp->buffer)->b_data[1] = 0;
4369 (STp->buffer)->b_data[2] = 0;
4370 (STp->buffer)->b_data[3] = 0;
4371 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4372 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4373 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4374 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4375
4376#if DEBUG
4377 printk(OSST_DEB_MSG "osst%d:D: Applying soft reset\n", dev);
4378#endif
4379 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
4380
4381 STp->header_ok = 0;
4382
4383 for (i=0; i < 10; i++) {
4384
4385 memset (cmd, 0, MAX_COMMAND_SIZE);
4386 cmd[0] = TEST_UNIT_READY;
4387
4388 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
4389 STp->timeout, MAX_READY_RETRIES, TRUE);
4390 if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
4391 (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY)
4392 break;
4393
4394 if ((SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) {
4395 STp->device->was_reset = 0;
4396 STp->partition = STp->new_partition = 0;
4397 if (STp->can_partitions)
4398 STp->nbr_partitions = 1;
4399 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4400 STps = &(STp->ps[i]);
4401 STps->rw = ST_IDLE;
4402 STps->eof = ST_NOEOF;
4403 STps->at_sm = 0;
4404 STps->last_block_valid = FALSE;
4405 STps->drv_block = 0;
4406 STps->drv_file = 0 ;
4407 }
4408 new_session = TRUE;
4409 }
4410 }
4411 }
4412
4413 if (osst_wait_ready(STp, &SRpnt, 15 * 60))
4414 printk(KERN_INFO "osst%i:I: Device did not become Ready in open\n",dev);
4415
4416 if ((STp->buffer)->syscall_result != 0) {
4417 if ((STp->device)->scsi_level >= SCSI_2 &&
4418 (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
4419 (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY &&
4420 SRpnt->sr_sense_buffer[12] == 0x3a) {
4421 STp->ready = ST_NO_TAPE;
4422 } else
4423 STp->ready = ST_NOT_READY;
4424 scsi_release_request(SRpnt);
4425 SRpnt = NULL;
4426 STp->density = 0;
4427 STp->write_prot = 0;
4428 STp->block_size = 0;
4429 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4430 STp->partition = STp->new_partition = 0;
4431 STp->door_locked = ST_UNLOCKED;
4432 return 0;
4433 }
4434
4435 osst_configure_onstream(STp, &SRpnt);
4436
4437
4438
4439 if (OS_FRAME_SIZE > (STp->buffer)->buffer_size &&
4440 !enlarge_buffer(STp->buffer, OS_FRAME_SIZE, STp->restr_dma)) {
4441 printk(KERN_NOTICE "osst%d:A: Framesize %d too large for buffer.\n", dev,
4442 OS_FRAME_SIZE);
4443 retval = (-EIO);
4444 goto err_out;
4445 }
4446
4447 if ((STp->buffer)->buffer_size >= OS_FRAME_SIZE) {
4448 for (i = 0, b_size = 0;
4449 i < STp->buffer->sg_segs && (b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE;
4450 b_size += STp->buffer->sg[i++].length);
4451 STp->buffer->aux = (os_aux_t *) (STp->buffer->sg[i].address + OS_DATA_SIZE - b_size);
4452#if DEBUG
4453 printk(OSST_DEB_MSG "osst%d:D: b_data points to %p in segment 0 at %p\n", dev,
4454 STp->buffer->b_data, STp->buffer->sg[0].address);
4455 printk(OSST_DEB_MSG "osst%d:D: AUX points to %p in segment %d at %p\n", dev,
4456 STp->buffer->aux, i, STp->buffer->sg[i].address);
4457#endif
4458 } else
4459 STp->buffer->aux = NULL;
4460
4461 STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4462 (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4463 STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4464 STp->buffer->buffer_bytes =
4465 STp->buffer->read_pointer =
4466 STp->frame_in_buffer = 0;
4467
4468#if DEBUG
4469 if (debugging)
4470 printk(OSST_DEB_MSG "osst%d:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4471 dev, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4472 (STp->buffer)->buffer_blocks);
4473#endif
4474
4475 if (STp->drv_write_prot) {
4476 STp->write_prot = 1;
4477#if DEBUG
4478 if (debugging)
4479 printk(OSST_DEB_MSG "osst%d:D: Write protected\n", dev);
4480#endif
4481 if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4482 retval = (-EROFS);
4483 goto err_out;
4484 }
4485 }
4486
4487 if (new_session) {
4488#if DEBUG
4489 if (debugging)
4490 printk(OSST_DEB_MSG "osst%d:D: New Session\n", dev);
4491#endif
4492 STp->density_changed = STp->blksize_changed = FALSE;
4493 STp->compression_changed = FALSE;
4494 }
4495
4496
4497
4498
4499 if (STp->door_locked == ST_UNLOCKED) {
4500 if (osst_int_ioctl(STp, &SRpnt, MTLOCK, 0))
4501 printk(KERN_INFO "osst%d:I: Can't lock drive door\n", dev);
4502 else
4503 STp->door_locked = ST_LOCKED_AUTO;
4504 }
4505
4506 osst_analyze_headers(STp, &SRpnt);
4507
4508 scsi_release_request(SRpnt);
4509 SRpnt = NULL;
4510
4511 return 0;
4512
4513err_out:
4514 if (SRpnt != NULL)
4515 scsi_release_request(SRpnt);
4516 if (STp->buffer != NULL) {
4517 STp->buffer->in_use = 0;
4518 STp->buffer = NULL;
4519 }
4520 STp->in_use = 0;
4521 STp->header_ok = 0;
4522 STp->device->access_count--;
4523
4524 if (STp->device->host->hostt->module)
4525 __MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
4526 if (osst_template.module)
4527 __MOD_DEC_USE_COUNT(osst_template.module);
4528
4529 return retval;
4530}
4531
4532
4533
4534static int os_scsi_tape_flush(struct file * filp)
4535{
4536 int result = 0, result2;
4537 OS_Scsi_Tape * STp;
4538 ST_mode * STm;
4539 ST_partstat * STps;
4540 Scsi_Request *SRpnt = NULL;
4541
4542 struct inode *inode = filp->f_dentry->d_inode;
4543 kdev_t devt = inode->i_rdev;
4544 int dev;
4545
4546 if (file_count(filp) > 1)
4547 return 0;
4548
4549 dev = TAPE_NR(devt);
4550 STp = os_scsi_tapes[dev];
4551 STm = &(STp->modes[STp->current_mode]);
4552 STps = &(STp->ps[STp->partition]);
4553
4554 if ( STps->rw == ST_WRITING && !(STp->device)->was_reset) {
4555 result = osst_flush_write_buffer(STp, &SRpnt);
4556 if (result != 0 && result != (-ENOSPC))
4557 goto out;
4558 }
4559 if ( STps->rw >= ST_WRITING && !(STp->device)->was_reset) {
4560
4561#if DEBUG
4562 if (debugging) {
4563 printk(OSST_DEB_MSG "osst%d:D: File length %ld bytes.\n",
4564 dev, (long)(filp->f_pos));
4565 printk(OSST_DEB_MSG "osst%d:D: Async write waits %d, finished %d.\n",
4566 dev, STp->nbr_waits, STp->nbr_finished);
4567 }
4568#endif
4569 if (STp->write_type != OS_WRITE_NEW_MARK) {
4570
4571 result = osst_flush_drive_buffer(STp, &SRpnt);
4572 if (result < 0) goto out;
4573 result = osst_write_filemark(STp, &SRpnt);
4574 if (result < 0) goto out;
4575
4576 if (STps->drv_file >= 0)
4577 STps->drv_file++ ;
4578 STps->drv_block = 0;
4579 }
4580 result = osst_write_eod(STp, &SRpnt);
4581 osst_write_header(STp, &SRpnt, !(STp->rew_at_close));
4582
4583 STps->eof = ST_FM;
4584
4585#if DEBUG
4586 if (debugging)
4587 printk(OSST_DEB_MSG "osst%d:D: Buffer flushed, %d EOF(s) written\n",
4588 dev, 1+STp->two_fm);
4589#endif
4590 }
4591 else if (!STp->rew_at_close) {
4592 STps = &(STp->ps[STp->partition]);
4593 if (!STm->sysv || STps->rw != ST_READING) {
4594 if (STp->can_bsr)
4595 result = osst_flush_buffer(STp, &SRpnt, 0);
4596 else if (STps->eof == ST_FM_HIT) {
4597 result = cross_eof(STp, &SRpnt, FALSE);
4598 if (result) {
4599 if (STps->drv_file >= 0)
4600 STps->drv_file++;
4601 STps->drv_block = 0;
4602 STps->eof = ST_FM;
4603 }
4604 else
4605 STps->eof = ST_NOEOF;
4606 }
4607 }
4608 else if ((STps->eof == ST_NOEOF &&
4609 !(result = cross_eof(STp, &SRpnt, TRUE))) ||
4610 STps->eof == ST_FM_HIT) {
4611 if (STps->drv_file >= 0)
4612 STps->drv_file++;
4613 STps->drv_block = 0;
4614 STps->eof = ST_FM;
4615 }
4616 }
4617
4618out:
4619 if (STp->rew_at_close) {
4620 result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4621 STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4622 if (result == 0 && result2 < 0)
4623 result = result2;
4624 }
4625 if (SRpnt) scsi_release_request(SRpnt);
4626
4627 if (STp->recover_count) {
4628 printk(KERN_INFO "osst%d:I: %d recovered errors in", dev, STp->recover_count);
4629 if (STp->write_count)
4630 printk(" %d frames written", STp->write_count);
4631 if (STp->read_count)
4632 printk(" %d frames read", STp->read_count);
4633 printk("\n");
4634 STp->recover_count = 0;
4635 }
4636 STp->write_count = 0;
4637 STp->read_count = 0;
4638
4639 return result;
4640}
4641
4642
4643
4644static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4645{
4646 int result = 0;
4647 OS_Scsi_Tape * STp;
4648 Scsi_Request * SRpnt = NULL;
4649
4650 kdev_t devt = inode->i_rdev;
4651 int dev;
4652
4653 dev = TAPE_NR(devt);
4654 STp = os_scsi_tapes[dev];
4655
4656 if (STp->door_locked == ST_LOCKED_AUTO)
4657 osst_int_ioctl(STp, &SRpnt, MTUNLOCK, 0);
4658 if (SRpnt) scsi_release_request(SRpnt);
4659
4660 if (STp->buffer != NULL)
4661 STp->buffer->in_use = 0;
4662
4663 if (STp->raw)
4664 STp->header_ok = 0;
4665
4666 STp->in_use = 0;
4667 STp->device->access_count--;
4668
4669 if (STp->device->host->hostt->module)
4670 __MOD_DEC_USE_COUNT(STp->device->host->hostt->module);
4671 if(osst_template.module)
4672 __MOD_DEC_USE_COUNT(osst_template.module);
4673
4674 return result;
4675}
4676
4677
4678
4679static int osst_ioctl(struct inode * inode,struct file * file,
4680 unsigned int cmd_in, unsigned long arg)
4681{
4682 int i, cmd_nr, cmd_type, retval = 0;
4683 unsigned int blk;
4684 OS_Scsi_Tape *STp;
4685 ST_mode *STm;
4686 ST_partstat *STps;
4687 Scsi_Request *SRpnt = NULL;
4688 int dev = TAPE_NR(inode->i_rdev);
4689
4690 STp = os_scsi_tapes[dev];
4691
4692 if (down_interruptible(&STp->lock))
4693 return -ERESTARTSYS;
4694
4695#if DEBUG
4696 if (debugging && !STp->in_use) {
4697 printk(OSST_DEB_MSG "osst%d:D: Incorrect device.\n", dev);
4698 retval = (-EIO);
4699 goto out;
4700 }
4701#endif
4702 STm = &(STp->modes[STp->current_mode]);
4703 STps = &(STp->ps[STp->partition]);
4704
4705
4706
4707
4708
4709
4710
4711 if( !scsi_block_when_processing_errors(STp->device) ) {
4712 retval = (-ENXIO);
4713 goto out;
4714 }
4715
4716 cmd_type = _IOC_TYPE(cmd_in);
4717 cmd_nr = _IOC_NR(cmd_in);
4718#if DEBUG
4719 printk(OSST_DEB_MSG "osst%d:D: Ioctl %d,%d in %s mode\n", dev,
4720 cmd_type, cmd_nr, STp->raw?"raw":"normal");
4721#endif
4722 if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4723 struct mtop mtc;
4724
4725 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4726 retval = (-EINVAL);
4727 goto out;
4728 }
4729
4730 i = copy_from_user((char *) &mtc, (char *)arg, sizeof(struct mtop));
4731 if (i) {
4732 retval = (-EFAULT);
4733 goto out;
4734 }
4735
4736 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
4737 printk(KERN_WARNING "osst%d:W: MTSETDRVBUFFER only allowed for root.\n", dev);
4738 retval = (-EPERM);
4739 goto out;
4740 }
4741
4742 if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
4743 retval = (-ENXIO);
4744 goto out;
4745 }
4746
4747 if (!(STp->device)->was_reset) {
4748
4749 if (STps->eof == ST_FM_HIT) {
4750 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
4751 mtc.mt_count -= 1;
4752 if (STps->drv_file >= 0)
4753 STps->drv_file += 1;
4754 }
4755 else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
4756 mtc.mt_count += 1;
4757 if (STps->drv_file >= 0)
4758 STps->drv_file += 1;
4759 }
4760 }
4761
4762 if (mtc.mt_op == MTSEEK) {
4763
4764 i = !STp->can_partitions || (STp->new_partition != STp->partition);
4765 }
4766 else {
4767 i = mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
4768 mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
4769 mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD ||
4770 mtc.mt_op == MTCOMPRESSION;
4771 }
4772 i = osst_flush_buffer(STp, &SRpnt, i);
4773 if (i < 0) {
4774 retval = i;
4775 goto out;
4776 }
4777 }
4778 else {
4779
4780
4781
4782
4783
4784 if(mtc.mt_op != MTREW &&
4785 mtc.mt_op != MTOFFL &&
4786 mtc.mt_op != MTRETEN &&
4787 mtc.mt_op != MTERASE &&
4788 mtc.mt_op != MTSEEK &&
4789 mtc.mt_op != MTEOM) {
4790 retval = (-EIO);
4791 goto out;
4792 }
4793 STp->device->was_reset = 0;
4794 if (STp->door_locked != ST_UNLOCKED &&
4795 STp->door_locked != ST_LOCK_FAILS) {
4796 if (osst_int_ioctl(STp, &SRpnt, MTLOCK, 0)) {
4797 printk(KERN_NOTICE "osst%d:I: Could not relock door after bus reset.\n",
4798 dev);
4799 STp->door_locked = ST_UNLOCKED;
4800 }
4801 }
4802 }
4803
4804 if (mtc.mt_op != MTNOP && mtc.mt_op != MTWEOF && mtc.mt_op != MTWSM &&
4805 mtc.mt_op != MTSETDENSITY && mtc.mt_op != MTSETBLK &&
4806 mtc.mt_op != MTSETDRVBUFFER && mtc.mt_op != MTSETPART)
4807 STps->rw = ST_IDLE;
4808
4809 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
4810 osst_int_ioctl(STp, &SRpnt, MTUNLOCK, 0);
4811
4812 if (mtc.mt_op == MTSETDRVBUFFER &&
4813 (mtc.mt_count & MT_ST_OPTIONS) != 0) {
4814 retval = osst_set_options(STp, mtc.mt_count);
4815 goto out;
4816 }
4817
4818 if (mtc.mt_op == MTSETPART) {
4819
4820
4821
4822
4823
4824
4825 if (mtc.mt_count >= STp->nbr_partitions)
4826 retval = -EINVAL;
4827 else {
4828 STp->new_partition = mtc.mt_count;
4829 retval = 0;
4830 }
4831 goto out;
4832 }
4833
4834 if (mtc.mt_op == MTMKPART) {
4835 if (!STp->can_partitions) {
4836 retval = (-EINVAL);
4837 goto out;
4838 }
4839 if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0
4840) {
4841 retval = i;
4842 goto out;
4843 }
4844 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4845 STp->ps[i].rw = ST_IDLE;
4846 STp->ps[i].at_sm = 0;
4847 STp->ps[i].last_block_valid = FALSE;
4848 }
4849 STp->partition = STp->new_partition = 0;
4850 STp->nbr_partitions = 1;
4851 STps->drv_block = STps->drv_file = 0;
4852 retval = 0;
4853 goto out;
4854 }
4855
4856 if (mtc.mt_op == MTSEEK) {
4857 if (STp->raw)
4858 i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
4859 else
4860 i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
4861 if (!STp->can_partitions)
4862 STp->ps[0].rw = ST_IDLE;
4863 retval = i;
4864 goto out;
4865 }
4866
4867
4868
4869
4870
4871 if (mtc.mt_op == MTCOMPRESSION)
4872 retval = -EINVAL ;
4873 else
4874
4875 retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
4876 goto out;
4877 }
4878
4879 if (!STm->defined) {
4880 retval = (-ENXIO);
4881 goto out;
4882 }
4883
4884 if ((i = osst_flush_buffer(STp, &SRpnt, FALSE)) < 0) {
4885 retval = i;
4886 goto out;
4887 }
4888
4889
4890
4891
4892
4893 if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
4894 struct mtget mt_status;
4895
4896 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
4897 retval = (-EINVAL);
4898 goto out;
4899 }
4900
4901 mt_status.mt_type = MT_ISONSTREAM_SC;
4902 mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
4903 mt_status.mt_dsreg =
4904 ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
4905 ((STp->density << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
4906 mt_status.mt_blkno = STps->drv_block;
4907 mt_status.mt_fileno = STps->drv_file;
4908 if (STp->block_size != 0) {
4909 if (STps->rw == ST_WRITING)
4910 mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
4911 else if (STps->rw == ST_READING)
4912 mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
4913 STp->block_size - 1) / STp->block_size;
4914 }
4915
4916 mt_status.mt_gstat = 0;
4917 if (STp->drv_write_prot)
4918 mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
4919 if (mt_status.mt_blkno == 0) {
4920 if (mt_status.mt_fileno == 0)
4921 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
4922 else
4923 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
4924 }
4925 mt_status.mt_resid = STp->partition;
4926 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
4927 mt_status.mt_gstat |= GMT_EOT(0xffffffff);
4928 else if (STps->eof >= ST_EOM_OK)
4929 mt_status.mt_gstat |= GMT_EOD(0xffffffff);
4930 if (STp->density == 1)
4931 mt_status.mt_gstat |= GMT_D_800(0xffffffff);
4932 else if (STp->density == 2)
4933 mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
4934 else if (STp->density == 3)
4935 mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
4936 if (STp->ready == ST_READY)
4937 mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
4938 if (STp->ready == ST_NO_TAPE)
4939 mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
4940 if (STps->at_sm)
4941 mt_status.mt_gstat |= GMT_SM(0xffffffff);
4942 if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
4943 STp->drv_buffer != 0)
4944 mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
4945
4946 i = copy_to_user((char *)arg, (char *)&mt_status,
4947 sizeof(struct mtget));
4948 if (i) {
4949 retval = (-EFAULT);
4950 goto out;
4951 }
4952
4953 STp->recover_erreg = 0;
4954 retval = 0;
4955 goto out;
4956 }
4957
4958 if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
4959 struct mtpos mt_pos;
4960
4961 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
4962 retval = (-EINVAL);
4963 goto out;
4964 }
4965 if (STp->raw)
4966 blk = osst_get_frame_position(STp, &SRpnt);
4967 else
4968 blk = osst_get_sector(STp, &SRpnt);
4969 if (blk < 0) {
4970 retval = blk;
4971 goto out;
4972 }
4973 mt_pos.mt_blkno = blk;
4974 i = copy_to_user((char *)arg, (char *) (&mt_pos), sizeof(struct mtpos));
4975 if (i)
4976 retval = -EFAULT;
4977 goto out;
4978 }
4979 if (SRpnt) scsi_release_request(SRpnt);
4980
4981 up(&STp->lock);
4982
4983 return scsi_ioctl(STp->device, cmd_in, (void *) arg);
4984
4985out:
4986 if (SRpnt) scsi_release_request(SRpnt);
4987
4988 up(&STp->lock);
4989
4990 return retval;
4991}
4992
4993
4994
4995
4996
4997static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma )
4998{
4999 int i, priority, b_size, order, got = 0, segs = 0;
5000 OSST_buffer *tb;
5001
5002 if (osst_nbr_buffers >= osst_template.dev_max)
5003 return NULL;
5004
5005 if (from_initialization)
5006 priority = GFP_ATOMIC;
5007 else
5008 priority = GFP_KERNEL;
5009
5010 i = sizeof(OSST_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5011 tb = (OSST_buffer *)kmalloc(i, priority);
5012 if (tb) {
5013
5014 if (need_dma)
5015 priority |= GFP_DMA;
5016
5017
5018
5019 for (b_size = PAGE_SIZE, order = 0;
5020 b_size < osst_buffer_size && order < OSST_FIRST_ORDER;
5021 b_size *= 2, order++ );
5022
5023 for ( ; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5024 tb->sg[0].address =
5025 (unsigned char *)__get_free_pages(priority, order);
5026 if (tb->sg[0].address != NULL) {
5027 tb->sg[0].page = NULL;
5028 tb->sg[0].length = b_size;
5029 break;
5030 }
5031 }
5032 if (tb->sg[segs].address == NULL) {
5033 kfree(tb);
5034 tb = NULL;
5035 }
5036 else {
5037
5038 for (b_size = PAGE_SIZE, order = 0;
5039 osst_buffer_size > tb->sg[0].length + (OSST_FIRST_SG - 1) * b_size;
5040 b_size *= 2, order++ );
5041
5042 for (segs=1, got=tb->sg[0].length;
5043 got < osst_buffer_size && segs < OSST_FIRST_SG; ) {
5044 tb->sg[segs].address =
5045 (unsigned char *)__get_free_pages(priority, order);
5046 if (tb->sg[segs].address == NULL) {
5047 if (osst_buffer_size - got <=
5048 (OSST_FIRST_SG - segs) * b_size / 2) {
5049 b_size /= 2;
5050 order--;
5051 continue;
5052 }
5053 tb->sg_segs = segs;
5054 tb->orig_sg_segs = 0;
5055#if DEBUG
5056 tb->buffer_size = got;
5057#endif
5058 normalize_buffer(tb);
5059 kfree(tb);
5060 tb = NULL;
5061 break;
5062 }
5063 tb->sg[segs].page = NULL;
5064 tb->sg[segs].length = b_size;
5065 got += b_size;
5066 segs++;
5067 }
5068 }
5069 }
5070 if (!tb) {
5071 printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer (nbr %d).\n",
5072 osst_nbr_buffers);
5073 return NULL;
5074 }
5075 tb->sg_segs = tb->orig_sg_segs = segs;
5076 tb->b_data = tb->sg[0].address;
5077
5078#if DEBUG
5079 if (debugging) {
5080 printk(OSST_DEB_MSG
5081 "osst :D: Allocated tape buffer %d (%d bytes, %d segments, dma: %d, a: %p).\n",
5082 osst_nbr_buffers, got, tb->sg_segs, need_dma, tb->b_data);
5083 printk(OSST_DEB_MSG
5084 "osst :D: segment sizes: first %d, last %d bytes.\n",
5085 tb->sg[0].length, tb->sg[segs-1].length);
5086 }
5087#endif
5088 tb->in_use = 0;
5089 tb->dma = need_dma;
5090 tb->buffer_size = got;
5091 tb->writing = 0;
5092 osst_buffers[osst_nbr_buffers++] = tb;
5093
5094 return tb;
5095}
5096
5097
5098
5099static int enlarge_buffer(OSST_buffer *STbuffer, int new_size, int need_dma)
5100{
5101 int segs, nbr, max_segs, b_size, priority, order, got;
5102
5103 normalize_buffer(STbuffer);
5104
5105 max_segs = STbuffer->use_sg;
5106 if (max_segs > osst_max_sg_segs)
5107 max_segs = osst_max_sg_segs;
5108 nbr = max_segs - STbuffer->sg_segs;
5109 if (nbr <= 0)
5110 return FALSE;
5111
5112 priority = GFP_KERNEL;
5113 if (need_dma)
5114 priority |= GFP_DMA;
5115 for (b_size = PAGE_SIZE, order = 0;
5116 b_size * nbr < new_size - STbuffer->buffer_size;
5117 b_size *= 2, order++);
5118
5119 for (segs=STbuffer->sg_segs, got=STbuffer->buffer_size;
5120 segs < max_segs && got < new_size; ) {
5121 STbuffer->sg[segs].address =
5122 (unsigned char *)__get_free_pages(priority, order);
5123 if (STbuffer->sg[segs].address == NULL) {
5124 if (new_size - got <= (max_segs - segs) * b_size / 2) {
5125 b_size /= 2;
5126 order--;
5127 continue;
5128 }
5129 printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5130 new_size);
5131#if DEBUG
5132 STbuffer->buffer_size = got;
5133#endif
5134 normalize_buffer(STbuffer);
5135 return FALSE;
5136 }
5137 STbuffer->sg[segs].page = NULL;
5138 STbuffer->sg[segs].length = b_size;
5139 STbuffer->sg_segs += 1;
5140 got += b_size;
5141 STbuffer->buffer_size = got;
5142 segs++;
5143 }
5144#if DEBUG
5145 if (debugging) {
5146 for (nbr=0; osst_buffers[nbr] != STbuffer && nbr < osst_nbr_buffers; nbr++);
5147 printk(OSST_DEB_MSG
5148 "osst :D: Expanded tape buffer %d (%d bytes, %d->%d segments, dma: %d, a: %p).\n",
5149 nbr, got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5150 printk(OSST_DEB_MSG
5151 "osst :D: segment sizes: first %d, last %d bytes.\n",
5152 STbuffer->sg[0].length, STbuffer->sg[segs-1].length);
5153 }
5154#endif
5155
5156 return TRUE;
5157}
5158
5159
5160
5161static void normalize_buffer(OSST_buffer *STbuffer)
5162{
5163 int i, order, b_size;
5164
5165 for (i=STbuffer->orig_sg_segs; i < STbuffer->sg_segs; i++) {
5166
5167 for (b_size = PAGE_SIZE, order = 0;
5168 b_size < STbuffer->sg[i].length;
5169 b_size *= 2, order++);
5170
5171 free_pages((unsigned long)STbuffer->sg[i].address, order);
5172 STbuffer->buffer_size -= STbuffer->sg[i].length;
5173 }
5174#if DEBUG
5175 if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5176 printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5177 STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5178#endif
5179 STbuffer->sg_segs = STbuffer->orig_sg_segs;
5180}
5181
5182
5183
5184
5185static int append_to_buffer(const char *ubp, OSST_buffer *st_bp, int do_count)
5186{
5187 int i, cnt, res, offset;
5188
5189 for (i=0, offset=st_bp->buffer_bytes;
5190 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5191 offset -= st_bp->sg[i].length;
5192 if (i == st_bp->sg_segs) {
5193 printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5194 return (-EIO);
5195 }
5196 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5197 cnt = st_bp->sg[i].length - offset < do_count ?
5198 st_bp->sg[i].length - offset : do_count;
5199 res = copy_from_user(st_bp->sg[i].address + offset, ubp, cnt);
5200 if (res)
5201 return (-EFAULT);
5202 do_count -= cnt;
5203 st_bp->buffer_bytes += cnt;
5204 ubp += cnt;
5205 offset = 0;
5206 }
5207 if (do_count) {
5208 printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5209 do_count);
5210 return (-EIO);
5211 }
5212 return 0;
5213}
5214
5215
5216
5217
5218static int from_buffer(OSST_buffer *st_bp, char *ubp, int do_count)
5219{
5220 int i, cnt, res, offset;
5221
5222 for (i=0, offset=st_bp->read_pointer;
5223 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5224 offset -= st_bp->sg[i].length;
5225 if (i == st_bp->sg_segs) {
5226 printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5227 return (-EIO);
5228 }
5229 for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5230 cnt = st_bp->sg[i].length - offset < do_count ?
5231 st_bp->sg[i].length - offset : do_count;
5232 res = copy_to_user(ubp, st_bp->sg[i].address + offset, cnt);
5233 if (res)
5234 return (-EFAULT);
5235 do_count -= cnt;
5236 st_bp->buffer_bytes -= cnt;
5237 st_bp->read_pointer += cnt;
5238 ubp += cnt;
5239 offset = 0;
5240 }
5241 if (do_count) {
5242 printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5243 return (-EIO);
5244 }
5245 return 0;
5246}
5247
5248
5249
5250static int osst_zero_buffer_tail(OSST_buffer *st_bp)
5251{
5252 int i, offset, do_count, cnt;
5253
5254 for (i = 0, offset = st_bp->buffer_bytes;
5255 i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5256 offset -= st_bp->sg[i].length;
5257 if (i == st_bp->sg_segs) {
5258 printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5259 return (-EIO);
5260 }
5261 for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5262 i < st_bp->sg_segs && do_count > 0; i++) {
5263 cnt = st_bp->sg[i].length - offset < do_count ?
5264 st_bp->sg[i].length - offset : do_count ;
5265 memset(st_bp->sg[i].address + offset, 0, cnt);
5266 do_count -= cnt;
5267 offset = 0;
5268 }
5269 if (do_count) {
5270 printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5271 return (-EIO);
5272 }
5273 return 0;
5274}
5275
5276
5277
5278static int osst_copy_to_buffer(OSST_buffer *st_bp, unsigned char *ptr)
5279{
5280 int i, cnt, do_count = OS_DATA_SIZE;
5281
5282 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5283 cnt = st_bp->sg[i].length < do_count ?
5284 st_bp->sg[i].length : do_count ;
5285 memcpy(st_bp->sg[i].address, ptr, cnt);
5286 do_count -= cnt;
5287 ptr += cnt;
5288 }
5289 if (do_count || i != st_bp->sg_segs-1) {
5290 printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5291 do_count, i);
5292 return (-EIO);
5293 }
5294 return 0;
5295}
5296
5297
5298
5299static int osst_copy_from_buffer(OSST_buffer *st_bp, unsigned char *ptr)
5300{
5301 int i, cnt, do_count = OS_DATA_SIZE;
5302
5303 for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5304 cnt = st_bp->sg[i].length < do_count ?
5305 st_bp->sg[i].length : do_count ;
5306 memcpy(ptr, st_bp->sg[i].address, cnt);
5307 do_count -= cnt;
5308 ptr += cnt;
5309 }
5310 if (do_count || i != st_bp->sg_segs-1) {
5311 printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5312 do_count, i);
5313 return (-EIO);
5314 }
5315 return 0;
5316}
5317
5318
5319
5320
5321static void validate_options (void)
5322{
5323 if (buffer_kbs > 0)
5324 osst_buffer_size = buffer_kbs * ST_KILOBYTE;
5325 if (write_threshold_kbs > 0)
5326 osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5327 if (osst_write_threshold > osst_buffer_size)
5328 osst_write_threshold = osst_buffer_size;
5329 if (max_buffers > 0)
5330 osst_max_buffers = max_buffers;
5331 if (max_sg_segs >= OSST_FIRST_SG)
5332 osst_max_sg_segs = max_sg_segs;
5333#if DEBUG
5334 printk(OSST_DEB_MSG "osst :D: bufsize %d, wrt %d, max buffers %d, s/g segs %d.\n",
5335 osst_buffer_size, osst_write_threshold, osst_max_buffers, osst_max_sg_segs);
5336
5337
5338#endif
5339}
5340
5341#ifndef MODULE
5342
5343
5344
5345static int __init osst_setup (char *str)
5346{
5347 int i, ints[5];
5348 char *stp;
5349
5350 stp = get_options(str, ARRAY_SIZE(ints), ints);
5351
5352 if (ints[0] > 0) {
5353 for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5354 *parms[i].val = ints[i + 1];
5355 } else {
5356 while (stp != NULL) {
5357 for (i = 0; i < ARRAY_SIZE(parms); i++) {
5358 int len = strlen(parms[i].name);
5359 if (!strncmp(stp, parms[i].name, len) &&
5360 (*(stp + len) == ':' || *(stp + len) == '=')) {
5361 *parms[i].val =
5362 simple_strtoul(stp + len + 1, NULL, 0);
5363 break;
5364 }
5365 }
5366 if (i >= sizeof(parms) / sizeof(struct osst_dev_parm))
5367 printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5368 stp);
5369 stp = strchr(stp, ',');
5370 if (stp)
5371 stp++;
5372 }
5373 }
5374
5375 return 1;
5376}
5377
5378__setup("osst=", osst_setup);
5379
5380#endif
5381
5382
5383static struct file_operations osst_fops = {
5384 read: osst_read,
5385 write: osst_write,
5386 ioctl: osst_ioctl,
5387 open: os_scsi_tape_open,
5388 flush: os_scsi_tape_flush,
5389 release: os_scsi_tape_close,
5390};
5391
5392static int osst_supports(Scsi_Device * SDp)
5393{
5394 struct osst_support_data {
5395 char *vendor;
5396 char *model;
5397 char *rev;
5398 char *driver_hint;
5399 };
5400
5401static struct osst_support_data support_list[] = {
5402
5403 SIGS_FROM_OSST,
5404 {NULL, }};
5405
5406 struct osst_support_data *rp;
5407
5408
5409
5410
5411
5412 for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5413 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5414 !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5415 !strncmp(rp->rev, SDp->rev, strlen(rp->rev)))
5416 return 1;
5417 return 0;
5418}
5419
5420static int osst_attach(Scsi_Device * SDp)
5421{
5422 OS_Scsi_Tape * tpnt;
5423 ST_mode * STm;
5424 ST_partstat * STps;
5425 int i, dev;
5426#ifdef CONFIG_DEVFS_FS
5427 int mode;
5428#endif
5429
5430 if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5431 return 1;
5432
5433 if (osst_template.nr_dev >= osst_template.dev_max) {
5434 SDp->attached--;
5435 return 1;
5436 }
5437
5438
5439 for (i=0; os_scsi_tapes[i] && i<osst_template.dev_max; i++);
5440 if(i >= osst_template.dev_max) panic ("Scsi_devices corrupt (osst)");
5441
5442
5443 tpnt = (OS_Scsi_Tape *)kmalloc(sizeof(OS_Scsi_Tape), GFP_ATOMIC);
5444 if (tpnt == NULL) {
5445 SDp->attached--;
5446 printk(KERN_WARNING "osst :W: Can't allocate device descriptor.\n");
5447 return 1;
5448 }
5449 memset(tpnt, 0, sizeof(OS_Scsi_Tape));
5450 os_scsi_tapes[i] = tpnt;
5451 dev = i;
5452 tpnt->capacity = 0xfffff;
5453
5454
5455 if (!new_tape_buffer(TRUE, TRUE))
5456 printk(KERN_ERR "osst :W: Unable to allocate a tape buffer.\n");
5457
5458#ifdef CONFIG_DEVFS_FS
5459 for (mode = 0; mode < ST_NBR_MODES; ++mode) {
5460 char name[8];
5461 static char *formats[ST_NBR_MODES] ={"", "l", "m", "a"};
5462
5463
5464 sprintf (name, "mt%s", formats[mode]);
5465# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5466 tpnt->de_r[mode] =
5467 devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
5468 MAJOR_NR, i + (mode << 5),
5469 S_IFCHR | S_IRUGO | S_IWUGO,
5470 &osst_fops, NULL);
5471# else
5472 tpnt->de_r[mode] =
5473 devfs_register (SDp->de, name, 0, DEVFS_FL_DEFAULT,
5474 MAJOR_NR, i + (mode << 5),
5475 S_IFCHR | S_IRUGO | S_IWUGO,
5476 0, 0, &osst_fops, NULL);
5477# endif
5478
5479 sprintf (name, "mt%sn", formats[mode]);
5480# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
5481 tpnt->de_n[mode] =
5482 devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
5483 MAJOR_NR, i + (mode << 5) + 128,
5484 S_IFCHR | S_IRUGO | S_IWUGO,
5485 &osst_fops, NULL);
5486# else
5487 tpnt->de_n[mode] =
5488 devfs_register (SDp->de, name, 0, DEVFS_FL_DEFAULT,
5489 MAJOR_NR, i + (mode << 5) + 128,
5490 S_IFCHR | S_IRUGO | S_IWUGO,
5491 0, 0, &osst_fops, NULL);
5492# endif
5493 }
5494 devfs_register_tape (tpnt->de_r[0]);
5495#endif
5496
5497 tpnt->device = SDp;
5498 tpnt->devt = MKDEV(MAJOR_NR, i);
5499 tpnt->dirty = 0;
5500 tpnt->in_use = 0;
5501 tpnt->drv_buffer = 1;
5502 tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5503 tpnt->density = 0;
5504 tpnt->do_auto_lock = OSST_AUTO_LOCK;
5505 tpnt->can_bsr = OSST_IN_FILE_POS;
5506 tpnt->can_partitions = 0;
5507 tpnt->two_fm = OSST_TWO_FM;
5508 tpnt->fast_mteom = OSST_FAST_MTEOM;
5509 tpnt->scsi2_logical = OSST_SCSI2LOGICAL;
5510 tpnt->write_threshold = osst_write_threshold;
5511 tpnt->default_drvbuffer = 0xff;
5512 tpnt->partition = 0;
5513 tpnt->new_partition = 0;
5514 tpnt->nbr_partitions = 0;
5515 tpnt->min_block = 512;
5516 tpnt->max_block = OS_DATA_SIZE;
5517 tpnt->timeout = OSST_TIMEOUT;
5518 tpnt->long_timeout = OSST_LONG_TIMEOUT;
5519
5520
5521
5522 tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5523 tpnt->omit_blklims = 1;
5524
5525 tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5526 tpnt->frame_in_buffer = 0;
5527 tpnt->header_ok = 0;
5528 tpnt->linux_media = 0;
5529 tpnt->header_cache = NULL;
5530
5531 for (i=0; i < ST_NBR_MODES; i++) {
5532 STm = &(tpnt->modes[i]);
5533 STm->defined = FALSE;
5534 STm->sysv = OSST_SYSV;
5535 STm->defaults_for_writes = 0;
5536 STm->do_async_writes = OSST_ASYNC_WRITES;
5537 STm->do_buffer_writes = OSST_BUFFER_WRITES;
5538 STm->do_read_ahead = OSST_READ_AHEAD;
5539 STm->default_compression = ST_DONT_TOUCH;
5540 STm->default_blksize = 512;
5541 STm->default_density = (-1);
5542 }
5543
5544 for (i=0; i < ST_NBR_PARTITIONS; i++) {
5545 STps = &(tpnt->ps[i]);
5546 STps->rw = ST_IDLE;
5547 STps->eof = ST_NOEOF;
5548 STps->at_sm = 0;
5549 STps->last_block_valid = FALSE;
5550 STps->drv_block = (-1);
5551 STps->drv_file = (-1);
5552 }
5553
5554 tpnt->current_mode = 0;
5555 tpnt->modes[0].defined = TRUE;
5556 tpnt->modes[2].defined = TRUE;
5557 tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = FALSE;
5558 init_MUTEX(&tpnt->lock);
5559
5560 osst_template.nr_dev++;
5561
5562 printk(KERN_INFO
5563 "osst :I: Attached OnStream %.5s tape at scsi%d, channel %d, id %d, lun %d as osst%d\n",
5564 SDp->model, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun, dev);
5565
5566 return 0;
5567};
5568
5569static int osst_detect(Scsi_Device * SDp)
5570{
5571 if (SDp->type != TYPE_TAPE) return 0;
5572 if ( ! osst_supports(SDp) ) return 0;
5573
5574 osst_template.dev_noticed++;
5575 return 1;
5576}
5577
5578static int osst_registered = 0;
5579
5580
5581static int osst_init()
5582{
5583 int i;
5584
5585 if (osst_template.dev_noticed == 0) return 0;
5586
5587 if(!osst_registered) {
5588#ifdef CONFIG_DEVFS_FS
5589 if (devfs_register_chrdev(MAJOR_NR,"osst",&osst_fops)) {
5590#else
5591 if (register_chrdev(MAJOR_NR,"osst",&osst_fops)) {
5592#endif
5593 printk(KERN_ERR "osst :W: Unable to get major %d for OnStream tapes\n",MAJOR_NR);
5594 return 1;
5595 }
5596 osst_registered++;
5597 }
5598
5599 if (os_scsi_tapes) return 0;
5600 osst_template.dev_max = OSST_MAX_TAPES;
5601 if (osst_template.dev_max > 128 / ST_NBR_MODES)
5602 printk(KERN_INFO "osst :I: Only %d tapes accessible.\n", 128 / ST_NBR_MODES);
5603 os_scsi_tapes =
5604 (OS_Scsi_Tape **)kmalloc(osst_template.dev_max * sizeof(OS_Scsi_Tape *),
5605 GFP_ATOMIC);
5606 if (os_scsi_tapes == NULL) {
5607 printk(KERN_ERR "osst :W: Unable to allocate array for OnStream SCSI tapes.\n");
5608#ifdef CONFIG_DEVFS_FS
5609 devfs_unregister_chrdev(MAJOR_NR, "osst");
5610#else
5611 unregister_chrdev(MAJOR_NR, "osst");
5612#endif
5613 return 1;
5614 }
5615
5616 for (i=0; i < osst_template.dev_max; ++i) os_scsi_tapes[i] = NULL;
5617
5618
5619 osst_buffers =
5620 (OSST_buffer **)kmalloc(osst_template.dev_max * sizeof(OSST_buffer *),
5621 GFP_ATOMIC);
5622 if (osst_buffers == NULL) {
5623 printk(KERN_ERR "osst :W: Unable to allocate tape buffer pointers.\n");
5624#ifdef CONFIG_DEVFS_FS
5625 devfs_unregister_chrdev(MAJOR_NR, "osst");
5626#else
5627 unregister_chrdev(MAJOR_NR, "osst");
5628#endif
5629 kfree(os_scsi_tapes);
5630 return 1;
5631 }
5632 osst_nbr_buffers = 0;
5633
5634 printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
5635
5636#if DEBUG
5637 printk(OSST_DEB_MSG "osst :D: Buffer size %d bytes, write threshold %d bytes.\n",
5638 osst_buffer_size, osst_write_threshold);
5639#endif
5640 return 0;
5641}
5642
5643
5644static void osst_detach(Scsi_Device * SDp)
5645{
5646 OS_Scsi_Tape * tpnt;
5647 int i;
5648#ifdef CONFIG_DEVFS_FS
5649 int mode;
5650#endif
5651
5652 for(i=0; i<osst_template.dev_max; i++) {
5653 tpnt = os_scsi_tapes[i];
5654 if(tpnt != NULL && tpnt->device == SDp) {
5655 tpnt->device = NULL;
5656#ifdef CONFIG_DEVFS_FS
5657 for (mode = 0; mode < ST_NBR_MODES; ++mode) {
5658 devfs_unregister (tpnt->de_r[mode]);
5659 tpnt->de_r[mode] = NULL;
5660 devfs_unregister (tpnt->de_n[mode]);
5661 tpnt->de_n[mode] = NULL;
5662 }
5663#endif
5664 kfree(tpnt);
5665 os_scsi_tapes[i] = NULL;
5666 SDp->attached--;
5667 osst_template.nr_dev--;
5668 osst_template.dev_noticed--;
5669 return;
5670 }
5671 }
5672 return;
5673}
5674
5675static int __init init_osst(void)
5676{
5677 validate_options();
5678 osst_template.module = THIS_MODULE;
5679 return scsi_register_module(MODULE_SCSI_DEV, &osst_template);
5680}
5681
5682static void __exit exit_osst (void)
5683{
5684 int i;
5685 OS_Scsi_Tape * STp;
5686
5687 scsi_unregister_module(MODULE_SCSI_DEV, &osst_template);
5688#ifdef CONFIG_DEVFS_FS
5689 devfs_unregister_chrdev(MAJOR_NR, "osst");
5690#else
5691 unregister_chrdev(MAJOR_NR, "osst");
5692#endif
5693 osst_registered--;
5694 if(os_scsi_tapes != NULL) {
5695 for (i=0; i < osst_template.dev_max; ++i) {
5696 if ((STp = os_scsi_tapes[i])) {
5697 if (STp->header_cache != NULL) vfree(STp->header_cache);
5698 kfree(STp);
5699 }
5700 }
5701 kfree(os_scsi_tapes);
5702
5703 if (osst_buffers != NULL) {
5704 for (i=0; i < osst_nbr_buffers; i++)
5705 if (osst_buffers[i] != NULL) {
5706 osst_buffers[i]->orig_sg_segs = 0;
5707 normalize_buffer(osst_buffers[i]);
5708 kfree(osst_buffers[i]);
5709 }
5710
5711 kfree(osst_buffers);
5712 }
5713 }
5714 osst_template.dev_max = 0;
5715 printk(KERN_INFO "osst :I: Unloaded.\n");
5716}
5717
5718module_init(init_osst);
5719module_exit(exit_osst);
5720