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