Linux/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/init.h>
 42 #include <linux/string.h>
 43 #include <linux/errno.h>
 44 #include <linux/mtio.h>
 45 #include <linux/ioctl.h>
 46 #include <linux/fcntl.h>
 47 #include <linux/spinlock.h>
 48 #include <linux/vmalloc.h>
 49 #include <linux/blkdev.h>
 50 #include <linux/moduleparam.h>
 51 #include <linux/delay.h>
 52 #include <linux/jiffies.h>
 53 #include <linux/smp_lock.h>
 54 #include <asm/uaccess.h>
 55 #include <asm/dma.h>
 56 #include <asm/system.h>
 57 
 58 /* The driver prints some debugging information on the console if DEBUG
 59    is defined and non-zero. */
 60 #define DEBUG 0
 61 
 62 /* The message level for the debug messages is currently set to KERN_NOTICE
 63    so that people can easily see the messages. Later when the debugging messages
 64    in the drivers are more widely classified, this may be changed to KERN_DEBUG. */
 65 #define OSST_DEB_MSG  KERN_NOTICE
 66 
 67 #include <scsi/scsi.h>
 68 #include <scsi/scsi_dbg.h>
 69 #include <scsi/scsi_device.h>
 70 #include <scsi/scsi_driver.h>
 71 #include <scsi/scsi_eh.h>
 72 #include <scsi/scsi_host.h>
 73 #include <scsi/scsi_ioctl.h>
 74 
 75 #define ST_KILOBYTE 1024
 76 
 77 #include "st.h"
 78 #include "osst.h"
 79 #include "osst_options.h"
 80 #include "osst_detect.h"
 81 
 82 static int max_dev = 0;
 83 static int write_threshold_kbs = 0;
 84 static int max_sg_segs = 0;
 85 
 86 #ifdef MODULE
 87 MODULE_AUTHOR("Willem Riede");
 88 MODULE_DESCRIPTION("OnStream {DI-|FW-|SC-|USB}{30|50} Tape Driver");
 89 MODULE_LICENSE("GPL");
 90 MODULE_ALIAS_CHARDEV_MAJOR(OSST_MAJOR);
 91 MODULE_ALIAS_SCSI_DEVICE(TYPE_TAPE);
 92 
 93 module_param(max_dev, int, 0444);
 94 MODULE_PARM_DESC(max_dev, "Maximum number of OnStream Tape Drives to attach (4)");
 95 
 96 module_param(write_threshold_kbs, int, 0644);
 97 MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 32)");
 98 
 99 module_param(max_sg_segs, int, 0644);
100 MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (9)");
101 #else
102 static struct osst_dev_parm {
103        char   *name;
104        int    *val;
105 } parms[] __initdata = {
106        { "max_dev",             &max_dev             },
107        { "write_threshold_kbs", &write_threshold_kbs },
108        { "max_sg_segs",         &max_sg_segs         }
109 };
110 #endif
111 
112 /* Some default definitions have been moved to osst_options.h */
113 #define OSST_BUFFER_SIZE (OSST_BUFFER_BLOCKS * ST_KILOBYTE)
114 #define OSST_WRITE_THRESHOLD (OSST_WRITE_THRESHOLD_BLOCKS * ST_KILOBYTE)
115 
116 /* The buffer size should fit into the 24 bits for length in the
117    6-byte SCSI read and write commands. */
118 #if OSST_BUFFER_SIZE >= (2 << 24 - 1)
119 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
120 #endif
121 
122 #if DEBUG
123 static int debugging = 1;
124 /* uncomment define below to test error recovery */
125 // #define OSST_INJECT_ERRORS 1 
126 #endif
127 
128 /* Do not retry! The drive firmware already retries when appropriate,
129    and when it tries to tell us something, we had better listen... */
130 #define MAX_RETRIES 0
131 
132 #define NO_TAPE  NOT_READY
133 
134 #define OSST_WAIT_POSITION_COMPLETE   (HZ > 200 ? HZ / 200 : 1)
135 #define OSST_WAIT_WRITE_COMPLETE      (HZ / 12)
136 #define OSST_WAIT_LONG_WRITE_COMPLETE (HZ / 2)
137         
138 #define OSST_TIMEOUT (200 * HZ)
139 #define OSST_LONG_TIMEOUT (1800 * HZ)
140 
141 #define TAPE_NR(x) (iminor(x) & ~(-1 << ST_MODE_SHIFT))
142 #define TAPE_MODE(x) ((iminor(x) & ST_MODE_MASK) >> ST_MODE_SHIFT)
143 #define TAPE_REWIND(x) ((iminor(x) & 0x80) == 0)
144 #define TAPE_IS_RAW(x) (TAPE_MODE(x) & (ST_NBR_MODES >> 1))
145 
146 /* Internal ioctl to set both density (uppermost 8 bits) and blocksize (lower
147    24 bits) */
148 #define SET_DENS_AND_BLK 0x10001
149 
150 static int osst_buffer_size       = OSST_BUFFER_SIZE;
151 static int osst_write_threshold   = OSST_WRITE_THRESHOLD;
152 static int osst_max_sg_segs       = OSST_MAX_SG;
153 static int osst_max_dev           = OSST_MAX_TAPES;
154 static int osst_nr_dev;
155 
156 static struct osst_tape **os_scsi_tapes = NULL;
157 static DEFINE_RWLOCK(os_scsi_tapes_lock);
158 
159 static int modes_defined = 0;
160 
161 static struct osst_buffer *new_tape_buffer(int, int, int);
162 static int enlarge_buffer(struct osst_buffer *, int);
163 static void normalize_buffer(struct osst_buffer *);
164 static int append_to_buffer(const char __user *, struct osst_buffer *, int);
165 static int from_buffer(struct osst_buffer *, char __user *, int);
166 static int osst_zero_buffer_tail(struct osst_buffer *);
167 static int osst_copy_to_buffer(struct osst_buffer *, unsigned char *);
168 static int osst_copy_from_buffer(struct osst_buffer *, unsigned char *);
169 
170 static int osst_probe(struct device *);
171 static int osst_remove(struct device *);
172 
173 static struct scsi_driver osst_template = {
174         .owner                  = THIS_MODULE,
175         .gendrv = {
176                 .name           =  "osst",
177                 .probe          = osst_probe,
178                 .remove         = osst_remove,
179         }
180 };
181 
182 static int osst_int_ioctl(struct osst_tape *STp, struct osst_request ** aSRpnt,
183                             unsigned int cmd_in, unsigned long arg);
184 
185 static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int frame, int skip);
186 
187 static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt);
188 
189 static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt);
190 
191 static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending);
192 
193 static inline char *tape_name(struct osst_tape *tape)
194 {
195         return tape->drive->disk_name;
196 }
197 
198 /* Routines that handle the interaction with mid-layer SCSI routines */
199 
200 
201 /* Normalize Sense */
202 static void osst_analyze_sense(struct osst_request *SRpnt, struct st_cmdstatus *s)
203 {
204         const u8 *ucp;
205         const u8 *sense = SRpnt->sense;
206 
207         s->have_sense = scsi_normalize_sense(SRpnt->sense,
208                                 SCSI_SENSE_BUFFERSIZE, &s->sense_hdr);
209         s->flags = 0;
210 
211         if (s->have_sense) {
212                 s->deferred = 0;
213                 s->remainder_valid =
214                         scsi_get_sense_info_fld(sense, SCSI_SENSE_BUFFERSIZE, &s->uremainder64);
215                 switch (sense[0] & 0x7f) {
216                 case 0x71:
217                         s->deferred = 1;
218                 case 0x70:
219                         s->fixed_format = 1;
220                         s->flags = sense[2] & 0xe0;
221                         break;
222                 case 0x73:
223                         s->deferred = 1;
224                 case 0x72:
225                         s->fixed_format = 0;
226                         ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4);
227                         s->flags = ucp ? (ucp[3] & 0xe0) : 0;
228                         break;
229                 }
230         }
231 }
232 
233 /* Convert the result to success code */
234 static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
235 {
236         char *name = tape_name(STp);
237         int result = SRpnt->result;
238         u8 * sense = SRpnt->sense, scode;
239 #if DEBUG
240         const char *stp;
241 #endif
242         struct st_cmdstatus *cmdstatp;
243 
244         if (!result)
245                 return 0;
246 
247         cmdstatp = &STp->buffer->cmdstat;
248         osst_analyze_sense(SRpnt, cmdstatp);
249 
250         if (cmdstatp->have_sense)
251                 scode = STp->buffer->cmdstat.sense_hdr.sense_key;
252         else
253                 scode = 0;
254 #if DEBUG
255         if (debugging) {
256                 printk(OSST_DEB_MSG "%s:D: Error: %x, cmd: %x %x %x %x %x %x\n",
257                    name, result,
258                    SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2],
259                    SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]);
260                 if (scode) printk(OSST_DEB_MSG "%s:D: Sense: %02x, ASC: %02x, ASCQ: %02x\n",
261                                 name, scode, sense[12], sense[13]);
262                 if (cmdstatp->have_sense)
263                         __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
264         }
265         else
266 #endif
267         if (cmdstatp->have_sense && (
268                  scode != NO_SENSE &&
269                  scode != RECOVERED_ERROR &&
270 /*               scode != UNIT_ATTENTION && */
271                  scode != BLANK_CHECK &&
272                  scode != VOLUME_OVERFLOW &&
273                  SRpnt->cmd[0] != MODE_SENSE &&
274                  SRpnt->cmd[0] != TEST_UNIT_READY)) { /* Abnormal conditions for tape */
275                 if (cmdstatp->have_sense) {
276                         printk(KERN_WARNING "%s:W: Command with sense data:\n", name);
277                         __scsi_print_sense("osst ", SRpnt->sense, SCSI_SENSE_BUFFERSIZE);
278                 }
279                 else {
280                         static  int     notyetprinted = 1;
281 
282                         printk(KERN_WARNING
283                              "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n",
284                              name, result, driver_byte(result),
285                              host_byte(result));
286                         if (notyetprinted) {
287                                 notyetprinted = 0;
288                                 printk(KERN_INFO
289                                         "%s:I: This warning may be caused by your scsi controller,\n", name);
290                                 printk(KERN_INFO
291                                         "%s:I: it has been reported with some Buslogic cards.\n", name);
292                         }
293                 }
294         }
295         STp->pos_unknown |= STp->device->was_reset;
296 
297         if (cmdstatp->have_sense && scode == RECOVERED_ERROR) {
298                 STp->recover_count++;
299                 STp->recover_erreg++;
300 #if DEBUG
301                 if (debugging) {
302                         if (SRpnt->cmd[0] == READ_6)
303                                 stp = "read";
304                         else if (SRpnt->cmd[0] == WRITE_6)
305                                 stp = "write";
306                         else
307                                 stp = "ioctl";
308                         printk(OSST_DEB_MSG "%s:D: Recovered %s error (%d).\n", name, stp,
309                                              STp->recover_count);
310                 }
311 #endif
312                 if ((sense[2] & 0xe0) == 0)
313                         return 0;
314         }
315         return (-EIO);
316 }
317 
318 
319 /* Wakeup from interrupt */
320 static void osst_end_async(struct request *req, int update)
321 {
322         struct osst_request *SRpnt = req->end_io_data;
323         struct osst_tape *STp = SRpnt->stp;
324         struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
325 
326         STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors;
327 #if DEBUG
328         STp->write_pending = 0;
329 #endif
330         if (SRpnt->waiting)
331                 complete(SRpnt->waiting);
332 
333         if (SRpnt->bio) {
334                 kfree(mdata->pages);
335                 blk_rq_unmap_user(SRpnt->bio);
336         }
337 
338         __blk_put_request(req->q, req);
339 }
340 
341 /* osst_request memory management */
342 static struct osst_request *osst_allocate_request(void)
343 {
344         return kzalloc(sizeof(struct osst_request), GFP_KERNEL);
345 }
346 
347 static void osst_release_request(struct osst_request *streq)
348 {
349         kfree(streq);
350 }
351 
352 static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
353                         int cmd_len, int data_direction, void *buffer, unsigned bufflen,
354                         int use_sg, int timeout, int retries)
355 {
356         struct request *req;
357         struct page **pages = NULL;
358         struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
359 
360         int err = 0;
361         int write = (data_direction == DMA_TO_DEVICE);
362 
363         req = blk_get_request(SRpnt->stp->device->request_queue, write, GFP_KERNEL);
364         if (!req)
365                 return DRIVER_ERROR << 24;
366 
367         req->cmd_type = REQ_TYPE_BLOCK_PC;
368         req->cmd_flags |= REQ_QUIET;
369 
370         SRpnt->bio = NULL;
371 
372         if (use_sg) {
373                 struct scatterlist *sg, *sgl = (struct scatterlist *)buffer;
374                 int i;
375 
376                 pages = kzalloc(use_sg * sizeof(struct page *), GFP_KERNEL);
377                 if (!pages)
378                         goto free_req;
379 
380                 for_each_sg(sgl, sg, use_sg, i)
381                         pages[i] = sg_page(sg);
382 
383                 mdata->null_mapped = 1;
384 
385                 mdata->page_order = get_order(sgl[0].length);
386                 mdata->nr_entries =
387                         DIV_ROUND_UP(bufflen, PAGE_SIZE << mdata->page_order);
388                 mdata->offset = 0;
389 
390                 err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen, GFP_KERNEL);
391                 if (err) {
392                         kfree(pages);
393                         goto free_req;
394                 }
395                 SRpnt->bio = req->bio;
396                 mdata->pages = pages;
397 
398         } else if (bufflen) {
399                 err = blk_rq_map_kern(req->q, req, buffer, bufflen, GFP_KERNEL);
400                 if (err)
401                         goto free_req;
402         }
403 
404         req->cmd_len = cmd_len;
405         memset(req->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
406         memcpy(req->cmd, cmd, req->cmd_len);
407         req->sense = SRpnt->sense;
408         req->sense_len = 0;
409         req->timeout = timeout;
410         req->retries = retries;
411         req->end_io_data = SRpnt;
412 
413         blk_execute_rq_nowait(req->q, NULL, req, 1, osst_end_async);
414         return 0;
415 free_req:
416         blk_put_request(req);
417         return DRIVER_ERROR << 24;
418 }
419 
420 /* Do the scsi command. Waits until command performed if do_wait is true.
421    Otherwise osst_write_behind_check() is used to check that the command
422    has finished. */
423 static  struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct osst_tape *STp, 
424         unsigned char *cmd, int bytes, int direction, int timeout, int retries, int do_wait)
425 {
426         unsigned char *bp;
427         unsigned short use_sg;
428 #ifdef OSST_INJECT_ERRORS
429         static   int   inject = 0;
430         static   int   repeat = 0;
431 #endif
432         struct completion *waiting;
433 
434         /* if async, make sure there's no command outstanding */
435         if (!do_wait && ((STp->buffer)->last_SRpnt)) {
436                 printk(KERN_ERR "%s: Async command already active.\n",
437                        tape_name(STp));
438                 if (signal_pending(current))
439                         (STp->buffer)->syscall_result = (-EINTR);
440                 else
441                         (STp->buffer)->syscall_result = (-EBUSY);
442                 return NULL;
443         }
444 
445         if (SRpnt == NULL) {
446                 SRpnt = osst_allocate_request();
447                 if (SRpnt == NULL) {
448                         printk(KERN_ERR "%s: Can't allocate SCSI request.\n",
449                                      tape_name(STp));
450                         if (signal_pending(current))
451                                 (STp->buffer)->syscall_result = (-EINTR);
452                         else
453                                 (STp->buffer)->syscall_result = (-EBUSY);
454                         return NULL;
455                 }
456                 SRpnt->stp = STp;
457         }
458 
459         /* If async IO, set last_SRpnt. This ptr tells write_behind_check
460            which IO is outstanding. It's nulled out when the IO completes. */
461         if (!do_wait)
462                 (STp->buffer)->last_SRpnt = SRpnt;
463 
464         waiting = &STp->wait;
465         init_completion(waiting);
466         SRpnt->waiting = waiting;
467 
468         use_sg = (bytes > STp->buffer->sg[0].length) ? STp->buffer->use_sg : 0;
469         if (use_sg) {
470                 bp = (char *)&(STp->buffer->sg[0]);
471                 if (STp->buffer->sg_segs < use_sg)
472                         use_sg = STp->buffer->sg_segs;
473         }
474         else
475                 bp = (STp->buffer)->b_data;
476 
477         memcpy(SRpnt->cmd, cmd, sizeof(SRpnt->cmd));
478         STp->buffer->cmdstat.have_sense = 0;
479         STp->buffer->syscall_result = 0;
480 
481         if (osst_execute(SRpnt, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
482                          use_sg, timeout, retries))
483                 /* could not allocate the buffer or request was too large */
484                 (STp->buffer)->syscall_result = (-EBUSY);
485         else if (do_wait) {
486                 wait_for_completion(waiting);
487                 SRpnt->waiting = NULL;
488                 STp->buffer->syscall_result = osst_chk_result(STp, SRpnt);
489 #ifdef OSST_INJECT_ERRORS
490                 if (STp->buffer->syscall_result == 0 &&
491                     cmd[0] == READ_6 &&
492                     cmd[4] && 
493                     ( (++ inject % 83) == 29  ||
494                       (STp->first_frame_position == 240 
495                                  /* or STp->read_error_frame to fail again on the block calculated above */ &&
496                                  ++repeat < 3))) {
497                         printk(OSST_DEB_MSG "%s:D: Injecting read error\n", tape_name(STp));
498                         STp->buffer->last_result_fatal = 1;
499                 }
500 #endif
501         }
502         return SRpnt;
503 }
504 
505 
506 /* Handle the write-behind checking (downs the semaphore) */
507 static void osst_write_behind_check(struct osst_tape *STp)
508 {
509         struct osst_buffer * STbuffer;
510 
511         STbuffer = STp->buffer;
512 
513 #if DEBUG
514         if (STp->write_pending)
515                 STp->nbr_waits++;
516         else
517                 STp->nbr_finished++;
518 #endif
519         wait_for_completion(&(STp->wait));
520         STp->buffer->last_SRpnt->waiting = NULL;
521 
522         STp->buffer->syscall_result = osst_chk_result(STp, STp->buffer->last_SRpnt);
523 
524         if (STp->buffer->syscall_result)
525                 STp->buffer->syscall_result =
526                         osst_write_error_recovery(STp, &(STp->buffer->last_SRpnt), 1);
527         else
528                 STp->first_frame_position++;
529 
530         osst_release_request(STp->buffer->last_SRpnt);
531 
532         if (STbuffer->writing < STbuffer->buffer_bytes)
533                 printk(KERN_WARNING "osst :A: write_behind_check: something left in buffer!\n");
534 
535         STbuffer->last_SRpnt = NULL;
536         STbuffer->buffer_bytes -= STbuffer->writing;
537         STbuffer->writing = 0;
538 
539         return;
540 }
541 
542 
543 
544 /* Onstream specific Routines */
545 /*
546  * Initialize the OnStream AUX
547  */
548 static void osst_init_aux(struct osst_tape * STp, int frame_type, int frame_seq_number,
549                                          int logical_blk_num, int blk_sz, int blk_cnt)
550 {
551         os_aux_t       *aux = STp->buffer->aux;
552         os_partition_t *par = &aux->partition;
553         os_dat_t       *dat = &aux->dat;
554 
555         if (STp->raw) return;
556 
557         memset(aux, 0, sizeof(*aux));
558         aux->format_id = htonl(0);
559         memcpy(aux->application_sig, "LIN4", 4);
560         aux->hdwr = htonl(0);
561         aux->frame_type = frame_type;
562 
563         switch (frame_type) {
564           case  OS_FRAME_TYPE_HEADER:
565                 aux->update_frame_cntr    = htonl(STp->update_frame_cntr);
566                 par->partition_num        = OS_CONFIG_PARTITION;
567                 par->par_desc_ver         = OS_PARTITION_VERSION;
568                 par->wrt_pass_cntr        = htons(0xffff);
569                 /* 0-4 = reserved, 5-9 = header, 2990-2994 = header, 2995-2999 = reserved */
570                 par->first_frame_ppos     = htonl(0);
571                 par->last_frame_ppos      = htonl(0xbb7);
572                 aux->frame_seq_num        = htonl(0);
573                 aux->logical_blk_num_high = htonl(0);
574                 aux->logical_blk_num      = htonl(0);
575                 aux->next_mark_ppos       = htonl(STp->first_mark_ppos);
576                 break;
577           case  OS_FRAME_TYPE_DATA:
578           case  OS_FRAME_TYPE_MARKER:
579                 dat->dat_sz = 8;
580                 dat->reserved1 = 0;
581                 dat->entry_cnt = 1;
582                 dat->reserved3 = 0;
583                 dat->dat_list[0].blk_sz   = htonl(blk_sz);
584                 dat->dat_list[0].blk_cnt  = htons(blk_cnt);
585                 dat->dat_list[0].flags    = frame_type==OS_FRAME_TYPE_MARKER?
586                                                         OS_DAT_FLAGS_MARK:OS_DAT_FLAGS_DATA;
587                 dat->dat_list[0].reserved = 0;
588           case  OS_FRAME_TYPE_EOD:
589                 aux->update_frame_cntr    = htonl(0);
590                 par->partition_num        = OS_DATA_PARTITION;
591                 par->par_desc_ver         = OS_PARTITION_VERSION;
592                 par->wrt_pass_cntr        = htons(STp->wrt_pass_cntr);
593                 par->first_frame_ppos     = htonl(STp->first_data_ppos);
594                 par->last_frame_ppos      = htonl(STp->capacity);
595                 aux->frame_seq_num        = htonl(frame_seq_number);
596                 aux->logical_blk_num_high = htonl(0);
597                 aux->logical_blk_num      = htonl(logical_blk_num);
598                 break;
599           default: ; /* probably FILL */
600         }
601         aux->filemark_cnt = htonl(STp->filemark_cnt);
602         aux->phys_fm = htonl(0xffffffff);
603         aux->last_mark_ppos = htonl(STp->last_mark_ppos);
604         aux->last_mark_lbn  = htonl(STp->last_mark_lbn);
605 }
606 
607 /*
608  * Verify that we have the correct tape frame
609  */
610 static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int quiet)
611 {
612         char               * name = tape_name(STp);
613         os_aux_t           * aux  = STp->buffer->aux;
614         os_partition_t     * par  = &(aux->partition);
615         struct st_partstat * STps = &(STp->ps[STp->partition]);
616         int                  blk_cnt, blk_sz, i;
617 
618         if (STp->raw) {
619                 if (STp->buffer->syscall_result) {
620                         for (i=0; i < STp->buffer->sg_segs; i++)
621                                 memset(page_address(sg_page(&STp->buffer->sg[i])),
622                                        0, STp->buffer->sg[i].length);
623                         strcpy(STp->buffer->b_data, "READ ERROR ON FRAME");
624                 } else
625                         STp->buffer->buffer_bytes = OS_FRAME_SIZE;
626                 return 1;
627         }
628         if (STp->buffer->syscall_result) {
629 #if DEBUG
630                 printk(OSST_DEB_MSG "%s:D: Skipping frame, read error\n", name);
631 #endif
632                 return 0;
633         }
634         if (ntohl(aux->format_id) != 0) {
635 #if DEBUG
636                 printk(OSST_DEB_MSG "%s:D: Skipping frame, format_id %u\n", name, ntohl(aux->format_id));
637 #endif
638                 goto err_out;
639         }
640         if (memcmp(aux->application_sig, STp->application_sig, 4) != 0 &&
641             (memcmp(aux->application_sig, "LIN3", 4) != 0 || STp->linux_media_version != 4)) {
642 #if DEBUG
643                 printk(OSST_DEB_MSG "%s:D: Skipping frame, incorrect application signature\n", name);
644 #endif
645                 goto err_out;
646         }
647         if (par->partition_num != OS_DATA_PARTITION) {
648                 if (!STp->linux_media || STp->linux_media_version != 2) {
649 #if DEBUG
650                         printk(OSST_DEB_MSG "%s:D: Skipping frame, partition num %d\n",
651                                             name, par->partition_num);
652 #endif
653                         goto err_out;
654                 }
655         }
656         if (par->par_desc_ver != OS_PARTITION_VERSION) {
657 #if DEBUG
658                 printk(OSST_DEB_MSG "%s:D: Skipping frame, partition version %d\n", name, par->par_desc_ver);
659 #endif
660                 goto err_out;
661         }
662         if (ntohs(par->wrt_pass_cntr) != STp->wrt_pass_cntr) {
663 #if DEBUG
664                 printk(OSST_DEB_MSG "%s:D: Skipping frame, wrt_pass_cntr %d (expected %d)\n", 
665                                     name, ntohs(par->wrt_pass_cntr), STp->wrt_pass_cntr);
666 #endif
667                 goto err_out;
668         }
669         if (aux->frame_type != OS_FRAME_TYPE_DATA &&
670             aux->frame_type != OS_FRAME_TYPE_EOD &&
671             aux->frame_type != OS_FRAME_TYPE_MARKER) {
672                 if (!quiet) {
673 #if DEBUG
674                         printk(OSST_DEB_MSG "%s:D: Skipping frame, frame type %x\n", name, aux->frame_type);
675 #endif
676                 }
677                 goto err_out;
678         }
679         if (aux->frame_type == OS_FRAME_TYPE_EOD &&
680             STp->first_frame_position < STp->eod_frame_ppos) {
681                 printk(KERN_INFO "%s:I: Skipping premature EOD frame %d\n", name,
682                                  STp->first_frame_position);
683                 goto err_out;
684         }
685         if (frame_seq_number != -1 && ntohl(aux->frame_seq_num) != frame_seq_number) {
686                 if (!quiet) {
687 #if DEBUG
688                         printk(OSST_DEB_MSG "%s:D: Skipping frame, sequence number %u (expected %d)\n", 
689                                             name, ntohl(aux->frame_seq_num), frame_seq_number);
690 #endif
691                 }
692                 goto err_out;
693         }
694         if (aux->frame_type == OS_FRAME_TYPE_MARKER) {
695                 STps->eof = ST_FM_HIT;
696 
697                 i = ntohl(aux->filemark_cnt);
698                 if (STp->header_cache != NULL && i < OS_FM_TAB_MAX && (i > STp->filemark_cnt ||
699                     STp->first_frame_position - 1 != ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i]))) {
700 #if DEBUG
701                         printk(OSST_DEB_MSG "%s:D: %s filemark %d at frame pos %d\n", name,
702                                   STp->header_cache->dat_fm_tab.fm_tab_ent[i] == 0?"Learned":"Corrected",
703                                   i, STp->first_frame_position - 1);
704 #endif
705                         STp->header_cache->dat_fm_tab.fm_tab_ent[i] = htonl(STp->first_frame_position - 1);
706                         if (i >= STp->filemark_cnt)
707                                  STp->filemark_cnt = i+1;
708                 }
709         }
710         if (aux->frame_type == OS_FRAME_TYPE_EOD) {
711                 STps->eof = ST_EOD_1;
712                 STp->frame_in_buffer = 1;
713         }
714         if (aux->frame_type == OS_FRAME_TYPE_DATA) {
715                 blk_cnt = ntohs(aux->dat.dat_list[0].blk_cnt);
716                 blk_sz  = ntohl(aux->dat.dat_list[0].blk_sz);
717                 STp->buffer->buffer_bytes = blk_cnt * blk_sz;
718                 STp->buffer->read_pointer = 0;
719                 STp->frame_in_buffer = 1;
720 
721                 /* See what block size was used to write file */
722                 if (STp->block_size != blk_sz && blk_sz > 0) {
723                         printk(KERN_INFO
724                 "%s:I: File was written with block size %d%c, currently %d%c, adjusted to match.\n",
725                                 name, blk_sz<1024?blk_sz:blk_sz/1024,blk_sz<1024?'b':'k',
726                                 STp->block_size<1024?STp->block_size:STp->block_size/1024,
727                                 STp->block_size<1024?'b':'k');
728                         STp->block_size            = blk_sz;
729                         STp->buffer->buffer_blocks = OS_DATA_SIZE / blk_sz;
730                 }
731                 STps->eof = ST_NOEOF;
732         }
733         STp->frame_seq_number = ntohl(aux->frame_seq_num);
734         STp->logical_blk_num  = ntohl(aux->logical_blk_num);
735         return 1;
736 
737 err_out:
738         if (STp->read_error_frame == 0)
739                 STp->read_error_frame = STp->first_frame_position - 1;
740         return 0;
741 }
742 
743 /*
744  * Wait for the unit to become Ready
745  */
746 static int osst_wait_ready(struct osst_tape * STp, struct osst_request ** aSRpnt,
747                                  unsigned timeout, int initial_delay)
748 {
749         unsigned char           cmd[MAX_COMMAND_SIZE];
750         struct osst_request   * SRpnt;
751         unsigned long           startwait = jiffies;
752 #if DEBUG
753         int                     dbg  = debugging;
754         char                  * name = tape_name(STp);
755 
756         printk(OSST_DEB_MSG "%s:D: Reached onstream wait ready\n", name);
757 #endif
758 
759         if (initial_delay > 0)
760                 msleep(jiffies_to_msecs(initial_delay));
761 
762         memset(cmd, 0, MAX_COMMAND_SIZE);
763         cmd[0] = TEST_UNIT_READY;
764 
765         SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
766         *aSRpnt = SRpnt;
767         if (!SRpnt) return (-EBUSY);
768 
769         while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
770                (( SRpnt->sense[2]  == 2 && SRpnt->sense[12] == 4    &&
771                  (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)    ) ||
772                 ( SRpnt->sense[2]  == 6 && SRpnt->sense[12] == 0x28 &&
773                   SRpnt->sense[13] == 0                                        )  )) {
774 #if DEBUG
775             if (debugging) {
776                 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait ready\n", name);
777                 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
778                 debugging = 0;
779             }
780 #endif
781             msleep(100);
782 
783             memset(cmd, 0, MAX_COMMAND_SIZE);
784             cmd[0] = TEST_UNIT_READY;
785 
786             SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
787         }
788         *aSRpnt = SRpnt;
789 #if DEBUG
790         debugging = dbg;
791 #endif
792         if ( STp->buffer->syscall_result &&
793              osst_write_error_recovery(STp, aSRpnt, 0) ) {
794 #if DEBUG
795             printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait ready\n", name);
796             printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
797                         STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
798                         SRpnt->sense[12], SRpnt->sense[13]);
799 #endif
800             return (-EIO);
801         }
802 #if DEBUG
803         printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait ready\n", name);
804 #endif
805         return 0;
806 }
807 
808 /*
809  * Wait for a tape to be inserted in the unit
810  */
811 static int osst_wait_for_medium(struct osst_tape * STp, struct osst_request ** aSRpnt, unsigned timeout)
812 {
813         unsigned char           cmd[MAX_COMMAND_SIZE];
814         struct osst_request   * SRpnt;
815         unsigned long           startwait = jiffies;
816 #if DEBUG
817         int                     dbg = debugging;
818         char                  * name = tape_name(STp);
819 
820         printk(OSST_DEB_MSG "%s:D: Reached onstream wait for medium\n", name);
821 #endif
822 
823         memset(cmd, 0, MAX_COMMAND_SIZE);
824         cmd[0] = TEST_UNIT_READY;
825 
826         SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
827         *aSRpnt = SRpnt;
828         if (!SRpnt) return (-EBUSY);
829 
830         while ( STp->buffer->syscall_result && time_before(jiffies, startwait + timeout*HZ) &&
831                 SRpnt->sense[2] == 2 && SRpnt->sense[12] == 0x3a && SRpnt->sense[13] == 0  ) {
832 #if DEBUG
833             if (debugging) {
834                 printk(OSST_DEB_MSG "%s:D: Sleeping in onstream wait medium\n", name);
835                 printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
836                 debugging = 0;
837             }
838 #endif
839             msleep(100);
840 
841             memset(cmd, 0, MAX_COMMAND_SIZE);
842             cmd[0] = TEST_UNIT_READY;
843 
844             SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
845         }
846         *aSRpnt = SRpnt;
847 #if DEBUG
848         debugging = dbg;
849 #endif
850         if ( STp->buffer->syscall_result     && SRpnt->sense[2]  != 2 &&
851              SRpnt->sense[12] != 4 && SRpnt->sense[13] == 1) {
852 #if DEBUG
853             printk(OSST_DEB_MSG "%s:D: Abnormal exit from onstream wait medium\n", name);
854             printk(OSST_DEB_MSG "%s:D: Result = %d, Sense: 0=%02x, 2=%02x, 12=%02x, 13=%02x\n", name,
855                         STp->buffer->syscall_result, SRpnt->sense[0], SRpnt->sense[2],
856                         SRpnt->sense[12], SRpnt->sense[13]);
857 #endif
858             return 0;
859         }
860 #if DEBUG
861         printk(OSST_DEB_MSG "%s:D: Normal exit from onstream wait medium\n", name);
862 #endif
863         return 1;
864 }
865 
866 static int osst_position_tape_and_confirm(struct osst_tape * STp, struct osst_request ** aSRpnt, int frame)
867 {
868         int     retval;
869 
870         osst_wait_ready(STp, aSRpnt, 15 * 60, 0);                       /* TODO - can this catch a write error? */
871         retval = osst_set_frame_position(STp, aSRpnt, frame, 0);
872         if (retval) return (retval);
873         osst_wait_ready(STp, aSRpnt, 15 * 60, OSST_WAIT_POSITION_COMPLETE);
874         return (osst_get_frame_position(STp, aSRpnt));
875 }
876 
877 /*
878  * Wait for write(s) to complete
879  */
880 static int osst_flush_drive_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt)
881 {
882         unsigned char           cmd[MAX_COMMAND_SIZE];
883         struct osst_request   * SRpnt;
884         int                     result = 0;
885         int                     delay  = OSST_WAIT_WRITE_COMPLETE;
886 #if DEBUG
887         char                  * name = tape_name(STp);
888 
889         printk(OSST_DEB_MSG "%s:D: Reached onstream flush drive buffer (write filemark)\n", name);
890 #endif
891 
892         memset(cmd, 0, MAX_COMMAND_SIZE);
893         cmd[0] = WRITE_FILEMARKS;
894         cmd[1] = 1;
895 
896         SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
897         *aSRpnt = SRpnt;
898         if (!SRpnt) return (-EBUSY);
899         if (STp->buffer->syscall_result) {
900                 if ((SRpnt->sense[2] & 0x0f) == 2 && SRpnt->sense[12] == 4) {
901                         if (SRpnt->sense[13] == 8) {
902                                 delay = OSST_WAIT_LONG_WRITE_COMPLETE;
903                         }
904                 } else
905                         result = osst_write_error_recovery(STp, aSRpnt, 0);
906         }
907         result |= osst_wait_ready(STp, aSRpnt, 5 * 60, delay);
908         STp->ps[STp->partition].rw = OS_WRITING_COMPLETE;
909 
910         return (result);
911 }
912 
913 #define OSST_POLL_PER_SEC 10
914 static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int curr, int minlast, int to)
915 {
916         unsigned long   startwait = jiffies;
917         char          * name      = tape_name(STp);
918 #if DEBUG
919         char       notyetprinted  = 1;
920 #endif
921         if (minlast >= 0 && STp->ps[STp->partition].rw != ST_READING)
922                 printk(KERN_ERR "%s:A: Waiting for frame without having initialized read!\n", name);
923 
924         while (time_before (jiffies, startwait + to*HZ))
925         { 
926                 int result;
927                 result = osst_get_frame_position(STp, aSRpnt);
928                 if (result == -EIO)
929                         if ((result = osst_write_error_recovery(STp, aSRpnt, 0)) == 0)
930                                 return 0;       /* successful recovery leaves drive ready for frame */
931                 if (result < 0) break;
932                 if (STp->first_frame_position == curr &&
933                     ((minlast < 0 &&
934                       (signed)STp->last_frame_position > (signed)curr + minlast) ||
935                      (minlast >= 0 && STp->cur_frames > minlast)
936                     ) && result >= 0)
937                 {
938 #if DEBUG                       
939                         if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC))
940                                 printk (OSST_DEB_MSG
941                                         "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n",
942                                         name, curr, curr+minlast, STp->first_frame_position,
943                                         STp->last_frame_position, STp->cur_frames,
944                                         result, (jiffies-startwait)/HZ, 
945                                         (((jiffies-startwait)%HZ)*10)/HZ);
946 #endif
947                         return 0;
948                 }
949 #if DEBUG
950                 if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted)
951                 {
952                         printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n",
953                                 name, curr, curr+minlast, STp->first_frame_position,
954                                 STp->last_frame_position, STp->cur_frames, result);
955                         notyetprinted--;
956                 }
957 #endif
958                 msleep(1000 / OSST_POLL_PER_SEC);
959         }
960 #if DEBUG
961         printk (OSST_DEB_MSG "%s:D: Fail wait f fr %i (>%i): %i-%i %i: %3li.%li s\n",
962                 name, curr, curr+minlast, STp->first_frame_position,
963                 STp->last_frame_position, STp->cur_frames,
964                 (jiffies-startwait)/HZ, (((jiffies-startwait)%HZ)*10)/HZ);
965 #endif  
966         return -EBUSY;
967 }
968 
969 static int osst_recover_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int writing)
970 {
971         struct osst_request   * SRpnt;
972         unsigned char           cmd[MAX_COMMAND_SIZE];
973         unsigned long           startwait = jiffies;
974         int                     retval    = 1;
975         char                  * name      = tape_name(STp);
976                                                                                                                                 
977         if (writing) {
978                 char    mybuf[24];
979                 char  * olddata = STp->buffer->b_data;
980                 int     oldsize = STp->buffer->buffer_size;
981 
982                 /* write zero fm then read pos - if shows write error, try to recover - if no progress, wait */
983 
984                 memset(cmd, 0, MAX_COMMAND_SIZE);
985                 cmd[0] = WRITE_FILEMARKS;
986                 cmd[1] = 1;
987                 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
988                                                                 MAX_RETRIES, 1);
989 
990                 while (retval && time_before (jiffies, startwait + 5*60*HZ)) {
991 
992                         if (STp->buffer->syscall_result && (SRpnt->sense[2] & 0x0f) != 2) {
993 
994                                 /* some failure - not just not-ready */
995                                 retval = osst_write_error_recovery(STp, aSRpnt, 0);
996                                 break;
997                         }
998                         schedule_timeout_interruptible(HZ / OSST_POLL_PER_SEC);
999 
1000                         STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
1001                         memset(cmd, 0, MAX_COMMAND_SIZE);
1002                         cmd[0] = READ_POSITION;
1003 
1004                         SRpnt = osst_do_scsi(SRpnt, STp, cmd, 20, DMA_FROM_DEVICE, STp->timeout,
1005                                                                                 MAX_RETRIES, 1);
1006 
1007                         retval = ( STp->buffer->syscall_result || (STp->buffer)->b_data[15] > 25 );
1008                         STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
1009                 }
1010                 if (retval)
1011                         printk(KERN_ERR "%s:E: Device did not succeed to write buffered data\n", name);
1012         } else
1013                 /* TODO - figure out which error conditions can be handled */
1014                 if (STp->buffer->syscall_result)
1015                         printk(KERN_WARNING
1016                                 "%s:W: Recover_wait_frame(read) cannot handle %02x:%02x:%02x\n", name,
1017                                         (*aSRpnt)->sense[ 2] & 0x0f,
1018                                         (*aSRpnt)->sense[12],
1019                                         (*aSRpnt)->sense[13]);
1020 
1021         return retval;
1022 }
1023 
1024 /*
1025  * Read the next OnStream tape frame at the current location
1026  */
1027 static int osst_read_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int timeout)
1028 {
1029         unsigned char           cmd[MAX_COMMAND_SIZE];
1030         struct osst_request   * SRpnt;
1031         int                     retval = 0;
1032 #if DEBUG
1033         os_aux_t              * aux    = STp->buffer->aux;
1034         char                  * name   = tape_name(STp);
1035 #endif
1036 
1037         if (STp->poll)
1038                 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, 0, timeout))
1039                         retval = osst_recover_wait_frame(STp, aSRpnt, 0);
1040 
1041         memset(cmd, 0, MAX_COMMAND_SIZE);
1042         cmd[0] = READ_6;
1043         cmd[1] = 1;
1044         cmd[4] = 1;
1045 
1046 #if DEBUG
1047         if (debugging)
1048                 printk(OSST_DEB_MSG "%s:D: Reading frame from OnStream tape\n", name);
1049 #endif
1050         SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1051                                       STp->timeout, MAX_RETRIES, 1);
1052         *aSRpnt = SRpnt;
1053         if (!SRpnt)
1054                 return (-EBUSY);
1055 
1056         if ((STp->buffer)->syscall_result) {
1057             retval = 1;
1058             if (STp->read_error_frame == 0) {
1059                 STp->read_error_frame = STp->first_frame_position;
1060 #if DEBUG
1061                 printk(OSST_DEB_MSG "%s:D: Recording read error at %d\n", name, STp->read_error_frame);
1062 #endif
1063             }
1064 #if DEBUG
1065             if (debugging)
1066                 printk(OSST_DEB_MSG "%s:D: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n",
1067                    name,
1068                    SRpnt->sense[0], SRpnt->sense[1],
1069                    SRpnt->sense[2], SRpnt->sense[3],
1070                    SRpnt->sense[4], SRpnt->sense[5],
1071                    SRpnt->sense[6], SRpnt->sense[7]);
1072 #endif
1073         }
1074         else
1075             STp->first_frame_position++;
1076 #if DEBUG
1077         if (debugging) {
1078            char sig[8]; int i;
1079            for (i=0;i<4;i++)
1080                    sig[i] = aux->application_sig[i]<32?'^':aux->application_sig[i];
1081            sig[4] = '\0';
1082            printk(OSST_DEB_MSG 
1083                 "%s:D: AUX: %s UpdFrCt#%d Wpass#%d %s FrSeq#%d LogBlk#%d Qty=%d Sz=%d\n", name, sig,
1084                         ntohl(aux->update_frame_cntr), ntohs(aux->partition.wrt_pass_cntr),
1085                         aux->frame_type==1?"EOD":aux->frame_type==2?"MARK":
1086                         aux->frame_type==8?"HEADR":aux->frame_type==0x80?"DATA":"FILL", 
1087                         ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
1088                         ntohs(aux->dat.dat_list[0].blk_cnt), ntohl(aux->dat.dat_list[0].blk_sz) );
1089            if (aux->frame_type==2)
1090                 printk(OSST_DEB_MSG "%s:D: mark_cnt=%d, last_mark_ppos=%d, last_mark_lbn=%d\n", name,
1091                         ntohl(aux->filemark_cnt), ntohl(aux->last_mark_ppos), ntohl(aux->last_mark_lbn));
1092            printk(OSST_DEB_MSG "%s:D: Exit read frame from OnStream tape with code %d\n", name, retval);
1093         }
1094 #endif
1095         return (retval);
1096 }
1097 
1098 static int osst_initiate_read(struct osst_tape * STp, struct osst_request ** aSRpnt)
1099 {
1100         struct st_partstat    * STps   = &(STp->ps[STp->partition]);
1101         struct osst_request   * SRpnt  ;
1102         unsigned char           cmd[MAX_COMMAND_SIZE];
1103         int                     retval = 0;
1104         char                  * name   = tape_name(STp);
1105 
1106         if (STps->rw != ST_READING) {         /* Initialize read operation */
1107                 if (STps->rw == ST_WRITING || STp->dirty) {
1108                         STp->write_type = OS_WRITE_DATA;
1109                         osst_flush_write_buffer(STp, aSRpnt);
1110                         osst_flush_drive_buffer(STp, aSRpnt);
1111                 }
1112                 STps->rw = ST_READING;
1113                 STp->frame_in_buffer = 0;
1114 
1115                 /*
1116                  *      Issue a read 0 command to get the OnStream drive
1117                  *      read frames into its buffer.
1118                  */
1119                 memset(cmd, 0, MAX_COMMAND_SIZE);
1120                 cmd[0] = READ_6;
1121                 cmd[1] = 1;
1122 
1123 #if DEBUG
1124                 printk(OSST_DEB_MSG "%s:D: Start Read Ahead on OnStream tape\n", name);
1125 #endif
1126                 SRpnt   = osst_do_scsi(*aSRpnt, STp, cmd, 0, DMA_NONE, STp->timeout, MAX_RETRIES, 1);
1127                 *aSRpnt = SRpnt;
1128                 if ((retval = STp->buffer->syscall_result))
1129                         printk(KERN_WARNING "%s:W: Error starting read ahead\n", name);
1130         }
1131 
1132         return retval;
1133 }
1134 
1135 static int osst_get_logical_frame(struct osst_tape * STp, struct osst_request ** aSRpnt,
1136                                                 int frame_seq_number, int quiet)
1137 {
1138         struct st_partstat * STps  = &(STp->ps[STp->partition]);
1139         char               * name  = tape_name(STp);
1140         int                  cnt   = 0,
1141                              bad   = 0,
1142                              past  = 0,
1143                              x,
1144                              position;
1145 
1146         /*
1147          * If we want just any frame (-1) and there is a frame in the buffer, return it
1148          */
1149         if (frame_seq_number == -1 && STp->frame_in_buffer) {
1150 #if DEBUG
1151                 printk(OSST_DEB_MSG "%s:D: Frame %d still in buffer\n", name, STp->frame_seq_number);
1152 #endif
1153                 return (STps->eof);
1154         }
1155         /*
1156          * Search and wait for the next logical tape frame
1157          */
1158         while (1) {
1159                 if (cnt++ > 400) {
1160                         printk(KERN_ERR "%s:E: Couldn't find logical frame %d, aborting\n",
1161                                             name, frame_seq_number);
1162                         if (STp->read_error_frame) {
1163                                 osst_set_frame_position(STp, aSRpnt, STp->read_error_frame, 0);
1164 #if DEBUG
1165                                 printk(OSST_DEB_MSG "%s:D: Repositioning tape to bad frame %d\n",
1166                                                     name, STp->read_error_frame);
1167 #endif
1168                                 STp->read_error_frame = 0;
1169                                 STp->abort_count++;
1170                         }
1171                         return (-EIO);
1172                 }
1173 #if DEBUG
1174                 if (debugging)
1175                         printk(OSST_DEB_MSG "%s:D: Looking for frame %d, attempt %d\n",
1176                                           name, frame_seq_number, cnt);
1177 #endif
1178                 if ( osst_initiate_read(STp, aSRpnt)
1179                 || ( (!STp->frame_in_buffer) && osst_read_frame(STp, aSRpnt, 30) ) ) {
1180                         if (STp->raw)
1181                                 return (-EIO);
1182                         position = osst_get_frame_position(STp, aSRpnt);
1183                         if (position >= 0xbae && position < 0xbb8)
1184                                 position = 0xbb8;
1185                         else if (position > STp->eod_frame_ppos || ++bad == 10) {
1186                                 position = STp->read_error_frame - 1;
1187                                 bad = 0;
1188                         }
1189                         else {
1190                                 position += 29;
1191                                 cnt      += 19;
1192                         }
1193 #if DEBUG
1194                         printk(OSST_DEB_MSG "%s:D: Bad frame detected, positioning tape to block %d\n",
1195                                          name, position);
1196 #endif
1197                         osst_set_frame_position(STp, aSRpnt, position, 0);
1198                         continue;
1199                 }
1200                 if (osst_verify_frame(STp, frame_seq_number, quiet))
1201                         break;
1202                 if (osst_verify_frame(STp, -1, quiet)) {
1203                         x = ntohl(STp->buffer->aux->frame_seq_num);
1204                         if (STp->fast_open) {
1205                                 printk(KERN_WARNING
1206                                        "%s:W: Found logical frame %d instead of %d after fast open\n",
1207                                        name, x, frame_seq_number);
1208                                 STp->header_ok = 0;
1209                                 STp->read_error_frame = 0;
1210                                 return (-EIO);
1211                         }
1212                         if (x > frame_seq_number) {
1213                                 if (++past > 3) {
1214                                         /* positioning backwards did not bring us to the desired frame */
1215                                         position = STp->read_error_frame - 1;
1216                                 }
1217                                 else {
1218                                         position = osst_get_frame_position(STp, aSRpnt)
1219                                                  + frame_seq_number - x - 1;
1220 
1221                                         if (STp->first_frame_position >= 3000 && position < 3000)
1222                                                 position -= 10;
1223                                 }
1224 #if DEBUG
1225                                 printk(OSST_DEB_MSG
1226                                        "%s:D: Found logical frame %d while looking for %d: back up %d\n",
1227                                                 name, x, frame_seq_number,
1228                                                 STp->first_frame_position - position);
1229 #endif
1230                                 osst_set_frame_position(STp, aSRpnt, position, 0);
1231                                 cnt += 10;
1232                         }
1233                         else
1234                                 past = 0;
1235                 }
1236                 if (osst_get_frame_position(STp, aSRpnt) == 0xbaf) {
1237 #if DEBUG
1238                         printk(OSST_DEB_MSG "%s:D: Skipping config partition\n", name);
1239 #endif
1240                         osst_set_frame_position(STp, aSRpnt, 0xbb8, 0);
1241                         cnt--;
1242                 }
1243                 STp->frame_in_buffer = 0;
1244         }
1245         if (cnt > 1) {
1246                 STp->recover_count++;
1247                 STp->recover_erreg++;
1248                 printk(KERN_WARNING "%s:I: Don't worry, Read error at position %d recovered\n", 
1249                                         name, STp->read_error_frame);
1250         }
1251         STp->read_count++;
1252 
1253 #if DEBUG
1254         if (debugging || STps->eof)
1255                 printk(OSST_DEB_MSG
1256                         "%s:D: Exit get logical frame (%d=>%d) from OnStream tape with code %d\n",
1257                         name, frame_seq_number, STp->frame_seq_number, STps->eof);
1258 #endif
1259         STp->fast_open = 0;
1260         STp->read_error_frame = 0;
1261         return (STps->eof);
1262 }
1263 
1264 static int osst_seek_logical_blk(struct osst_tape * STp, struct osst_request ** aSRpnt, int logical_blk_num)
1265 {
1266         struct st_partstat * STps = &(STp->ps[STp->partition]);
1267         char               * name = tape_name(STp);
1268         int     retries    = 0;
1269         int     frame_seq_estimate, ppos_estimate, move;
1270         
1271         if (logical_blk_num < 0) logical_blk_num = 0;
1272 #if DEBUG
1273         printk(OSST_DEB_MSG "%s:D: Seeking logical block %d (now at %d, size %d%c)\n",
1274                                 name, logical_blk_num, STp->logical_blk_num, 
1275                                 STp->block_size<1024?STp->block_size:STp->block_size/1024,
1276                                 STp->block_size<1024?'b':'k');
1277 #endif
1278         /* Do we know where we are? */
1279         if (STps->drv_block >= 0) {
1280                 move                = logical_blk_num - STp->logical_blk_num;
1281                 if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1282                 move               /= (OS_DATA_SIZE / STp->block_size);
1283                 frame_seq_estimate  = STp->frame_seq_number + move;
1284         } else
1285                 frame_seq_estimate  = logical_blk_num * STp->block_size / OS_DATA_SIZE;
1286 
1287         if (frame_seq_estimate < 2980) ppos_estimate = frame_seq_estimate + 10;
1288         else                           ppos_estimate = frame_seq_estimate + 20;
1289         while (++retries < 10) {
1290            if (ppos_estimate > STp->eod_frame_ppos-2) {
1291                frame_seq_estimate += STp->eod_frame_ppos - 2 - ppos_estimate;
1292                ppos_estimate       = STp->eod_frame_ppos - 2;
1293            }
1294            if (frame_seq_estimate < 0) {
1295                frame_seq_estimate = 0;
1296                ppos_estimate      = 10;
1297            }
1298            osst_set_frame_position(STp, aSRpnt, ppos_estimate, 0);
1299            if (osst_get_logical_frame(STp, aSRpnt, frame_seq_estimate, 1) >= 0) {
1300               /* we've located the estimated frame, now does it have our block? */
1301               if (logical_blk_num <  STp->logical_blk_num ||
1302                   logical_blk_num >= STp->logical_blk_num + ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt)) {
1303                  if (STps->eof == ST_FM_HIT)
1304                     move = logical_blk_num < STp->logical_blk_num? -2 : 1;
1305                  else {
1306                     move                = logical_blk_num - STp->logical_blk_num;
1307                     if (move < 0) move -= (OS_DATA_SIZE / STp->block_size) - 1;
1308                     move               /= (OS_DATA_SIZE / STp->block_size);
1309                  }
1310                  if (!move) move = logical_blk_num > STp->logical_blk_num ? 1 : -1;
1311 #if DEBUG
1312                  printk(OSST_DEB_MSG
1313                         "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d) move %d\n",
1314                                 name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, 
1315                                 STp->logical_blk_num, logical_blk_num, move);
1316 #endif
1317                  frame_seq_estimate += move;
1318                  ppos_estimate      += move;
1319                  continue;
1320               } else {
1321                  STp->buffer->read_pointer  = (logical_blk_num - STp->logical_blk_num) * STp->block_size;
1322                  STp->buffer->buffer_bytes -= STp->buffer->read_pointer;
1323                  STp->logical_blk_num       =  logical_blk_num;
1324 #if DEBUG
1325                  printk(OSST_DEB_MSG 
1326                         "%s:D: Seek success at ppos %d fsq %d in_buf %d, bytes %d, ptr %d*%d\n",
1327                                 name, ppos_estimate, STp->frame_seq_number, STp->frame_in_buffer, 
1328                                 STp->buffer->buffer_bytes, STp->buffer->read_pointer / STp->block_size, 
1329                                 STp->block_size);
1330 #endif
1331                  STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1332                  if (STps->eof == ST_FM_HIT) {
1333                      STps->drv_file++;
1334                      STps->drv_block = 0;
1335                  } else {
1336                      STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1337                                           STp->logical_blk_num -
1338                                              (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1339                                         -1;
1340                  }
1341                  STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1342                  return 0;
1343               }
1344            }
1345            if (osst_get_logical_frame(STp, aSRpnt, -1, 1) < 0)
1346               goto error;
1347            /* we are not yet at the estimated frame, adjust our estimate of its physical position */
1348 #if DEBUG
1349            printk(OSST_DEB_MSG "%s:D: Seek retry %d at ppos %d fsq %d (est %d) lbn %d (need %d)\n", 
1350                            name, retries, ppos_estimate, STp->frame_seq_number, frame_seq_estimate, 
1351                            STp->logical_blk_num, logical_blk_num);
1352 #endif
1353            if (frame_seq_estimate != STp->frame_seq_number)
1354               ppos_estimate += frame_seq_estimate - STp->frame_seq_number;
1355            else
1356               break;
1357         }
1358 error:
1359         printk(KERN_ERR "%s:E: Couldn't seek to logical block %d (at %d), %d retries\n", 
1360                             name, logical_blk_num, STp->logical_blk_num, retries);
1361         return (-EIO);
1362 }
1363 
1364 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
1365  * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
1366  * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
1367  * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
1368  */
1369 #define OSST_FRAME_SHIFT  6
1370 #define OSST_SECTOR_SHIFT 9
1371 #define OSST_SECTOR_MASK  0x03F
1372 
1373 static int osst_get_sector(struct osst_tape * STp, struct osst_request ** aSRpnt)
1374 {
1375         int     sector;
1376 #if DEBUG
1377         char  * name = tape_name(STp);
1378         
1379         printk(OSST_DEB_MSG 
1380                 "%s:D: Positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, %cptr %d, eof %d\n",
1381                 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1382                 STp->ps[STp->partition].drv_file, STp->ps[STp->partition].drv_block, 
1383                 STp->ps[STp->partition].rw == ST_WRITING?'w':'r',
1384                 STp->ps[STp->partition].rw == ST_WRITING?STp->buffer->buffer_bytes:
1385                 STp->buffer->read_pointer, STp->ps[STp->partition].eof);
1386 #endif
1387         /* do we know where we are inside a file? */
1388         if (STp->ps[STp->partition].drv_block >= 0) {
1389                 sector = (STp->frame_in_buffer ? STp->first_frame_position-1 :
1390                                 STp->first_frame_position) << OSST_FRAME_SHIFT;
1391                 if (STp->ps[STp->partition].rw == ST_WRITING)
1392                         sector |= (STp->buffer->buffer_bytes >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1393                 else
1394                         sector |= (STp->buffer->read_pointer >> OSST_SECTOR_SHIFT) & OSST_SECTOR_MASK;
1395         } else {
1396                 sector = osst_get_frame_position(STp, aSRpnt);
1397                 if (sector > 0)
1398                         sector <<= OSST_FRAME_SHIFT;
1399         }
1400         return sector;
1401 }
1402 
1403 static int osst_seek_sector(struct osst_tape * STp, struct osst_request ** aSRpnt, int sector)
1404 {
1405         struct st_partstat * STps   = &(STp->ps[STp->partition]);
1406         int                  frame  = sector >> OSST_FRAME_SHIFT,
1407                              offset = (sector & OSST_SECTOR_MASK) << OSST_SECTOR_SHIFT, 
1408                              r;
1409 #if DEBUG
1410         char          * name = tape_name(STp);
1411 
1412         printk(OSST_DEB_MSG "%s:D: Seeking sector %d in frame %d at offset %d\n",
1413                                 name, sector, frame, offset);
1414 #endif
1415         if (frame < 0 || frame >= STp->capacity) return (-ENXIO);
1416 
1417         if (frame <= STp->first_data_ppos) {
1418                 STp->frame_seq_number = STp->logical_blk_num = STps->drv_file = STps->drv_block = 0;
1419                 return (osst_set_frame_position(STp, aSRpnt, frame, 0));
1420         }
1421         r = osst_set_frame_position(STp, aSRpnt, offset?frame:frame-1, 0);
1422         if (r < 0) return r;
1423 
1424         r = osst_get_logical_frame(STp, aSRpnt, -1, 1);
1425         if (r < 0) return r;
1426 
1427         if (osst_get_frame_position(STp, aSRpnt) != (offset?frame+1:frame)) return (-EIO);
1428 
1429         if (offset) {
1430                 STp->logical_blk_num      += offset / STp->block_size;
1431                 STp->buffer->read_pointer  = offset;
1432                 STp->buffer->buffer_bytes -= offset;
1433         } else {
1434                 STp->frame_seq_number++;
1435                 STp->frame_in_buffer       = 0;
1436                 STp->logical_blk_num      += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1437                 STp->buffer->buffer_bytes  = STp->buffer->read_pointer = 0;
1438         }
1439         STps->drv_file = ntohl(STp->buffer->aux->filemark_cnt);
1440         if (STps->eof == ST_FM_HIT) {
1441                 STps->drv_file++;
1442                 STps->drv_block = 0;
1443         } else {
1444                 STps->drv_block = ntohl(STp->buffer->aux->last_mark_lbn)?
1445                                     STp->logical_blk_num -
1446                                         (STps->drv_file ? ntohl(STp->buffer->aux->last_mark_lbn) + 1 : 0):
1447                                   -1;
1448         }
1449         STps->eof       = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_NOEOF;
1450 #if DEBUG
1451         printk(OSST_DEB_MSG 
1452                 "%s:D: Now positioned at ppos %d, frame %d, lbn %d, file %d, blk %d, rptr %d, eof %d\n",
1453                 name, STp->first_frame_position, STp->frame_seq_number, STp->logical_blk_num,
1454                 STps->drv_file, STps->drv_block, STp->buffer->read_pointer, STps->eof);
1455 #endif
1456         return 0;
1457 }
1458 
1459 /*
1460  * Read back the drive's internal buffer contents, as a part
1461  * of the write error recovery mechanism for old OnStream
1462  * firmware revisions.
1463  * Precondition for this function to work: all frames in the
1464  * drive's buffer must be of one type (DATA, MARK or EOD)!
1465  */
1466 static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst_request ** aSRpnt,
1467                                                 unsigned int frame, unsigned int skip, int pending)
1468 {
1469         struct osst_request   * SRpnt = * aSRpnt;
1470         unsigned char         * buffer, * p;
1471         unsigned char           cmd[MAX_COMMAND_SIZE];
1472         int                     flag, new_frame, i;
1473         int                     nframes          = STp->cur_frames;
1474         int                     blks_per_frame   = ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1475         int                     frame_seq_number = ntohl(STp->buffer->aux->frame_seq_num)
1476                                                 - (nframes + pending - 1);
1477         int                     logical_blk_num  = ntohl(STp->buffer->aux->logical_blk_num) 
1478                                                 - (nframes + pending - 1) * blks_per_frame;
1479         char                  * name             = tape_name(STp);
1480         unsigned long           startwait        = jiffies;
1481 #if DEBUG
1482         int                     dbg              = debugging;
1483 #endif
1484 
1485         if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
1486                 return (-EIO);
1487 
1488         printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
1489                          name, nframes, pending?" and one that was pending":"");
1490 
1491         osst_copy_from_buffer(STp->buffer, (p = &buffer[nframes * OS_DATA_SIZE]));
1492 #if DEBUG
1493         if (pending && debugging)
1494                 printk(OSST_DEB_MSG "%s:D: Pending frame %d (lblk %d), data %02x %02x %02x %02x\n",
1495                                 name, frame_seq_number + nframes,
1496                                 logical_blk_num + nframes * blks_per_frame,
1497                                 p[0], p[1], p[2], p[3]);
1498 #endif
1499         for (i = 0, p = buffer; i < nframes; i++, p += OS_DATA_SIZE) {
1500 
1501                 memset(cmd, 0, MAX_COMMAND_SIZE);
1502                 cmd[0] = 0x3C;          /* Buffer Read           */
1503                 cmd[1] = 6;             /* Retrieve Faulty Block */
1504                 cmd[7] = 32768 >> 8;
1505                 cmd[8] = 32768 & 0xff;
1506 
1507                 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_FROM_DEVICE,
1508                                             STp->timeout, MAX_RETRIES, 1);
1509         
1510                 if ((STp->buffer)->syscall_result || !SRpnt) {
1511                         printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name);
1512                         vfree(buffer);
1513                         *aSRpnt = SRpnt;
1514                         return (-EIO);
1515                 }
1516                 osst_copy_from_buffer(STp->buffer, p);
1517 #if DEBUG
1518                 if (debugging)
1519                         printk(OSST_DEB_MSG "%s:D: Read back logical frame %d, data %02x %02x %02x %02x\n",
1520                                           name, frame_seq_number + i, p[0], p[1], p[2], p[3]);
1521 #endif
1522         }
1523         *aSRpnt = SRpnt;
1524         osst_get_frame_position(STp, aSRpnt);
1525 
1526 #if DEBUG
1527         printk(OSST_DEB_MSG "%s:D: Frames left in buffer: %d\n", name, STp->cur_frames);
1528 #endif
1529         /* Write synchronously so we can be sure we're OK again and don't have to recover recursively */
1530         /* In the header we don't actually re-write the frames that fail, just the ones after them */
1531 
1532         for (flag=1, new_frame=frame, p=buffer, i=0; i < nframes + pending; ) {
1533 
1534                 if (flag) {
1535                         if (STp->write_type == OS_WRITE_HEADER) {
1536                                 i += skip;
1537                                 p += skip * OS_DATA_SIZE;
1538                         }
1539                         else if (new_frame < 2990 && new_frame+skip+nframes+pending >= 2990)
1540                                 new_frame = 3000-i;
1541                         else
1542                                 new_frame += skip;
1543 #if DEBUG
1544                         printk(OSST_DEB_MSG "%s:D: Position to frame %d, write fseq %d\n",
1545                                                 name, new_frame+i, frame_seq_number+i);
1546 #endif
1547                         osst_set_frame_position(STp, aSRpnt, new_frame + i, 0);
1548                         osst_wait_ready(STp, aSRpnt, 60, OSST_WAIT_POSITION_COMPLETE);
1549                         osst_get_frame_position(STp, aSRpnt);
1550                         SRpnt = * aSRpnt;
1551 
1552                         if (new_frame > frame + 1000) {
1553                                 printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name);
1554                                 vfree(buffer);
1555                                 return (-EIO);
1556                         }
1557                         if ( i >= nframes + pending ) break;
1558                         flag = 0;
1559                 }
1560                 osst_copy_to_buffer(STp->buffer, p);
1561                 /*
1562                  * IMPORTANT: for error recovery to work, _never_ queue frames with mixed frame type!
1563                  */
1564                 osst_init_aux(STp, STp->buffer->aux->frame_type, frame_seq_number+i,
1565                                 logical_blk_num + i*blks_per_frame,
1566                                 ntohl(STp->buffer->aux->dat.dat_list[0].blk_sz), blks_per_frame);
1567                 memset(cmd, 0, MAX_COMMAND_SIZE);
1568                 cmd[0] = WRITE_6;
1569                 cmd[1] = 1;
1570                 cmd[4] = 1;
1571 
1572 #if DEBUG
1573                 if (debugging)
1574                         printk(OSST_DEB_MSG
1575                                 "%s:D: About to write frame %d, seq %d, lbn %d, data %02x %02x %02x %02x\n",
1576                                 name, new_frame+i, frame_seq_number+i, logical_blk_num + i*blks_per_frame,
1577                                 p[0], p[1], p[2], p[3]);
1578 #endif
1579                 SRpnt = osst_do_scsi(SRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1580                                             STp->timeout, MAX_RETRIES, 1);
1581 
1582                 if (STp->buffer->syscall_result)
1583                         flag = 1;
1584                 else {
1585                         p += OS_DATA_SIZE; i++;
1586 
1587                         /* if we just sent the last frame, wait till all successfully written */
1588                         if ( i == nframes + pending ) {
1589 #if DEBUG
1590                                 printk(OSST_DEB_MSG "%s:D: Check re-write successful\n", name);
1591 #endif
1592                                 memset(cmd, 0, MAX_COMMAND_SIZE);
1593                                 cmd[0] = WRITE_FILEMARKS;
1594                                 cmd[1] = 1;
1595                                 SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE,
1596                                                             STp->timeout, MAX_RETRIES, 1);
1597 #if DEBUG
1598                                 if (debugging) {
1599                                         printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1600                                         printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1601                                         debugging = 0;
1602                                 }
1603 #endif
1604                                 flag = STp->buffer->syscall_result;
1605                                 while ( !flag && time_before(jiffies, startwait + 60*HZ) ) {
1606 
1607                                         memset(cmd, 0, MAX_COMMAND_SIZE);
1608                                         cmd[0] = TEST_UNIT_READY;
1609 
1610                                         SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, DMA_NONE, STp->timeout,
1611                                                                                                 MAX_RETRIES, 1);
1612 
1613                                         if (SRpnt->sense[2] == 2 && SRpnt->sense[12] == 4 &&
1614                                             (SRpnt->sense[13] == 1 || SRpnt->sense[13] == 8)) {
1615                                                 /* in the process of becoming ready */
1616                                                 msleep(100);
1617                                                 continue;
1618                                         }
1619                                         if (STp->buffer->syscall_result)
1620                                                 flag = 1;
1621                                         break;
1622                                 }
1623 #if DEBUG
1624                                 debugging = dbg;
1625                                 printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1626 #endif
1627                         }
1628                 }
1629                 *aSRpnt = SRpnt;
1630                 if (flag) {
1631                         if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1632                              SRpnt->sense[12]         ==  0 &&
1633                              SRpnt->sense[13]         ==  2) {
1634                                 printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name);
1635                                 vfree(buffer);
1636                                 return (-EIO);                  /* hit end of tape = fail */
1637                         }
1638                         i = ((SRpnt->sense[3] << 24) |
1639                              (SRpnt->sense[4] << 16) |
1640                              (SRpnt->sense[5] <<  8) |
1641                               SRpnt->sense[6]        ) - new_frame;
1642                         p = &buffer[i * OS_DATA_SIZE];
1643 #if DEBUG
1644                         printk(OSST_DEB_MSG "%s:D: Additional write error at %d\n", name, new_frame+i);
1645 #endif
1646                         osst_get_frame_position(STp, aSRpnt);
1647 #if DEBUG
1648                         printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d, buffer = %d\n",
1649                                           name, STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
1650 #endif
1651                 }
1652         }
1653         if (flag) {
1654                 /* error recovery did not successfully complete */
1655                 printk(KERN_ERR "%s:D: Write error recovery failed in %s\n", name,
1656                                 STp->write_type == OS_WRITE_HEADER?"header":"body");
1657         }
1658         if (!pending)
1659                 osst_copy_to_buffer(STp->buffer, p);    /* so buffer content == at entry in all cases */
1660         vfree(buffer);
1661         return 0;
1662 }
1663 
1664 static int osst_reposition_and_retry(struct osst_tape * STp, struct osst_request ** aSRpnt,
1665                                         unsigned int frame, unsigned int skip, int pending)
1666 {
1667         unsigned char           cmd[MAX_COMMAND_SIZE];
1668         struct osst_request   * SRpnt;
1669         char                  * name      = tape_name(STp);
1670         int                     expected  = 0;
1671         int                     attempts  = 1000 / skip;
1672         int                     flag      = 1;
1673         unsigned long           startwait = jiffies;
1674 #if DEBUG
1675         int                     dbg       = debugging;
1676 #endif
1677 
1678         while (attempts && time_before(jiffies, startwait + 60*HZ)) {
1679                 if (flag) {
1680 #if DEBUG
1681                         debugging = dbg;
1682 #endif
1683                         if (frame < 2990 && frame+skip+STp->cur_frames+pending >= 2990)
1684                                 frame = 3000-skip;
1685                         expected = frame+skip+STp->cur_frames+pending;
1686 #if DEBUG
1687                         printk(OSST_DEB_MSG "%s:D: Position to fppos %d, re-write from fseq %d\n",
1688                                           name, frame+skip, STp->frame_seq_number-STp->cur_frames-pending);
1689 #endif
1690                         osst_set_frame_position(STp, aSRpnt, frame + skip, 1);
1691                         flag = 0;
1692                         attempts--;
1693                         schedule_timeout_interruptible(msecs_to_jiffies(100));
1694                 }
1695                 if (osst_get_frame_position(STp, aSRpnt) < 0) {         /* additional write error */
1696 #if DEBUG
1697                         printk(OSST_DEB_MSG "%s:D: Addl error, host %d, tape %d, buffer %d\n",
1698                                           name, STp->first_frame_position,
1699                                           STp->last_frame_position, STp->cur_frames);
1700 #endif
1701                         frame = STp->last_frame_position;
1702                         flag = 1;
1703                         continue;
1704                 }
1705                 if (pending && STp->cur_frames < 50) {
1706 
1707                         memset(cmd, 0, MAX_COMMAND_SIZE);
1708                         cmd[0] = WRITE_6;
1709                         cmd[1] = 1;
1710                         cmd[4] = 1;
1711 #if DEBUG
1712                         printk(OSST_DEB_MSG "%s:D: About to write pending fseq %d at fppos %d\n",
1713                                           name, STp->frame_seq_number-1, STp->first_frame_position);
1714 #endif
1715                         SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE,
1716                                                       STp->timeout, MAX_RETRIES, 1);
1717                         *aSRpnt = SRpnt;
1718 
1719                         if (STp->buffer->syscall_result) {              /* additional write error */
1720                                 if ((SRpnt->sense[ 2] & 0x0f) == 13 &&
1721                                      SRpnt->sense[12]         ==  0 &&
1722                                      SRpnt->sense[13]         ==  2) {
1723                                         printk(KERN_ERR
1724                                                "%s:E: Volume overflow in write error recovery\n",
1725                                                name);
1726                                         break;                          /* hit end of tape = fail */
1727                                 }
1728                                 flag = 1;
1729                         }
1730                         else
1731                                 pending = 0;
1732 
1733                         continue;
1734                 }
1735                 if (STp->cur_frames == 0) {
1736 #if DEBUG
1737                         debugging = dbg;
1738                         printk(OSST_DEB_MSG "%s:D: Wait re-write finished\n", name);
1739 #endif
1740                         if (STp->first_frame_position != expected) {
1741                                 printk(KERN_ERR "%s:A: Actual position %d - expected %d\n", 
1742                                                 name, STp->first_frame_position, expected);
1743                                 return (-EIO);
1744                         }
1745                         return 0;
1746                 }
1747 #if DEBUG
1748                 if (debugging) {
1749                         printk(OSST_DEB_MSG "%s:D: Sleeping in re-write wait ready\n", name);
1750                         printk(OSST_DEB_MSG "%s:D: Turning off debugging for a while\n", name);
1751                         debugging = 0;
1752                 }
1753 #endif
1754                 schedule_timeout_interruptible(msecs_to_jiffies(100));
1755         }
1756         printk(KERN_ERR "%s:E: Failed to find valid tape media\n", name);
1757 #if DEBUG
1758         debugging = dbg;
1759 #endif
1760         return (-EIO);
1761 }
1762 
1763 /*
1764  * Error recovery algorithm for the OnStream tape.
1765  */
1766 
1767 static int osst_write_error_recovery(struct osst_tape * STp, struct osst_request ** aSRpnt, int pending)
1768 {
1769         struct osst_request * SRpnt  = * aSRpnt;
1770         struct st_partstat  * STps   = & STp->ps[STp->partition];
1771         char                * name   = tape_name(STp);
1772         int                   retval = 0;
1773         int                   rw_state;
1774         unsigned int          frame, skip;
1775 
1776         rw_state = STps->rw;
1777 
1778         if ((SRpnt->sense[ 2] & 0x0f) != 3
1779           || SRpnt->sense[12]         != 12
1780           || SRpnt->sense[13]         != 0) {
1781 #if DEBUG
1782                 printk(OSST_DEB_MSG "%s:D: Write error recovery cannot handle %02x:%02x:%02x\n", name,
1783                         SRpnt->sense[2], SRpnt->sense[12], SRpnt->sense[13]);
1784 #endif
1785                 return (-EIO);
1786         }
1787         frame = (SRpnt->sense[3] << 24) |
1788                 (SRpnt->sense[4] << 16) |
1789                 (SRpnt->sense[5] <<  8) |
1790                  SRpnt->sense[6];
1791         skip  =  SRpnt->sense[9];
1792  
1793 #if DEBUG
1794         printk(OSST_DEB_MSG "%s:D: Detected physical bad frame at %u, advised to skip %d\n", name, frame, skip);
1795 #endif
1796         osst_get_frame_position(STp, aSRpnt);
1797 #if DEBUG
1798         printk(OSST_DEB_MSG "%s:D: reported frame positions: host = %d, tape = %d\n",
1799                         name, STp->first_frame_position, STp->last_frame_position);
1800 #endif
1801         switch (STp->write_type) {
1802            case OS_WRITE_DATA:
1803            case OS_WRITE_EOD:
1804            case OS_WRITE_NEW_MARK:
1805                 printk(KERN_WARNING 
1806                         "%s:I: Relocating %d buffered logical frames from position %u to %u\n",
1807                         name, STp->cur_frames, frame, (frame + skip > 3000 && frame < 3000)?3000:frame + skip);
1808                 if (STp->os_fw_rev >= 10600)
1809                         retval = osst_reposition_and_retry(STp, aSRpnt, frame, skip, pending);
1810                 else
1811                         retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, skip, pending);
1812                 printk(KERN_WARNING "%s:%s: %sWrite error%srecovered\n", name,
1813                                 retval?"E"    :"I",
1814                                 retval?""     :"Don't worry, ",
1815                                 retval?" not ":" ");
1816                 break;
1817            case OS_WRITE_LAST_MARK:
1818                 printk(KERN_ERR "%s:E: Bad frame in update last marker, fatal\n", name);
1819                 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1820                 retval = -EIO;
1821                 break;
1822            case OS_WRITE_HEADER:
1823                 printk(KERN_WARNING "%s:I: Bad frame in header partition, skipped\n", name);
1824                 retval = osst_read_back_buffer_and_rewrite(STp, aSRpnt, frame, 1, pending);
1825                 break;
1826            default:
1827                 printk(KERN_INFO "%s:I: Bad frame in filler, ignored\n", name);
1828                 osst_set_frame_position(STp, aSRpnt, frame + STp->cur_frames + pending, 0);
1829         }
1830         osst_get_frame_position(STp, aSRpnt);
1831 #if DEBUG
1832         printk(OSST_DEB_MSG "%s:D: Positioning complete, cur_frames %d, pos %d, tape pos %d\n", 
1833                         name, STp->cur_frames, STp->first_frame_position, STp->last_frame_position);
1834         printk(OSST_DEB_MSG "%s:D: next logical frame to write: %d\n", name, STp->logical_blk_num);
1835 #endif
1836         if (retval == 0) {
1837                 STp->recover_count++;
1838                 STp->recover_erreg++;
1839         } else
1840                 STp->abort_count++;
1841 
1842         STps->rw = rw_state;
1843         return retval;
1844 }
1845 
1846 static int osst_space_over_filemarks_backward(struct osst_tape * STp, struct osst_request ** aSRpnt,
1847                                                                  int mt_op, int mt_count)
1848 {
1849         char  * name = tape_name(STp);
1850         int     cnt;
1851         int     last_mark_ppos = -1;
1852 
1853 #if DEBUG
1854         printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_backwards %d %d\n", name, mt_op, mt_count);
1855 #endif
1856         if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1857 #if DEBUG
1858                 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_bwd\n", name);
1859 #endif
1860                 return -EIO;
1861         }
1862         if (STp->linux_media_version >= 4) {
1863                 /*
1864                  * direct lookup in header filemark list
1865                  */
1866                 cnt = ntohl(STp->buffer->aux->filemark_cnt);
1867                 if (STp->header_ok                         && 
1868                     STp->header_cache != NULL              &&
1869                     (cnt - mt_count)  >= 0                 &&
1870                     (cnt - mt_count)   < OS_FM_TAB_MAX     &&
1871                     (cnt - mt_count)   < STp->filemark_cnt &&
1872                     STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] == STp->buffer->aux->last_mark_ppos)
1873 
1874                         last_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt - mt_count]);
1875 #if DEBUG
1876                 if (STp->header_cache == NULL || (cnt - mt_count) < 0 || (cnt - mt_count) >= OS_FM_TAB_MAX)
1877                         printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
1878                                STp->header_cache == NULL?"lack of header cache":"count out of range");
1879                 else
1880                         printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
1881                                 name, cnt,
1882                                 ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
1883                                  (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt-1] ==
1884                                          STp->buffer->aux->last_mark_ppos))?"match":"error",
1885                                mt_count, last_mark_ppos);
1886 #endif
1887                 if (last_mark_ppos > 10 && last_mark_ppos < STp->eod_frame_ppos) {
1888                         osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1889                         if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1890 #if DEBUG
1891                                 printk(OSST_DEB_MSG 
1892                                         "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1893 #endif
1894                                 return (-EIO);
1895                         }
1896                         if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1897                                 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1898                                                  name, last_mark_ppos);
1899                                 return (-EIO);
1900                         }
1901                         goto found;
1902                 }
1903 #if DEBUG
1904                 printk(OSST_DEB_MSG "%s:D: Reverting to scan filemark backwards\n", name);
1905 #endif
1906         }
1907         cnt = 0;
1908         while (cnt != mt_count) {
1909                 last_mark_ppos = ntohl(STp->buffer->aux->last_mark_ppos);
1910                 if (last_mark_ppos == -1)
1911                         return (-EIO);
1912 #if DEBUG
1913                 printk(OSST_DEB_MSG "%s:D: Positioning to last mark at %d\n", name, last_mark_ppos);
1914 #endif
1915                 osst_position_tape_and_confirm(STp, aSRpnt, last_mark_ppos);
1916                 cnt++;
1917                 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1918 #if DEBUG
1919                         printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1920 #endif
1921                         return (-EIO);
1922                 }
1923                 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
1924                         printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
1925                                          name, last_mark_ppos);
1926                         return (-EIO);
1927                 }
1928         }
1929 found:
1930         if (mt_op == MTBSFM) {
1931                 STp->frame_seq_number++;
1932                 STp->frame_in_buffer      = 0;
1933                 STp->buffer->buffer_bytes = 0;
1934                 STp->buffer->read_pointer = 0;
1935                 STp->logical_blk_num     += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1936         }
1937         return 0;
1938 }
1939 
1940 /*
1941  * ADRL 1.1 compatible "slow" space filemarks fwd version
1942  *
1943  * Just scans for the filemark sequentially.
1944  */
1945 static int osst_space_over_filemarks_forward_slow(struct osst_tape * STp, struct osst_request ** aSRpnt,
1946                                                                      int mt_op, int mt_count)
1947 {
1948         int     cnt = 0;
1949 #if DEBUG
1950         char  * name = tape_name(STp);
1951 
1952         printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_slow %d %d\n", name, mt_op, mt_count);
1953 #endif
1954         if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1955 #if DEBUG
1956                 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
1957 #endif
1958                 return (-EIO);
1959         }
1960         while (1) {
1961                 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
1962 #if DEBUG
1963                         printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n", name);
1964 #endif
1965                         return (-EIO);
1966                 }
1967                 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
1968                         cnt++;
1969                 if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
1970 #if DEBUG
1971                         printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
1972 #endif
1973                         if (STp->first_frame_position > STp->eod_frame_ppos+1) {
1974 #if DEBUG
1975                                 printk(OSST_DEB_MSG "%s:D: EOD position corrected (%d=>%d)\n",
1976                                                 name, STp->eod_frame_ppos, STp->first_frame_position-1);
1977 #endif
1978                                 STp->eod_frame_ppos = STp->first_frame_position-1;
1979                         }
1980                         return (-EIO);
1981                 }
1982                 if (cnt == mt_count)
1983                         break;
1984                 STp->frame_in_buffer = 0;
1985         }
1986         if (mt_op == MTFSF) {
1987                 STp->frame_seq_number++;
1988                 STp->frame_in_buffer      = 0;
1989                 STp->buffer->buffer_bytes = 0;
1990                 STp->buffer->read_pointer = 0;
1991                 STp->logical_blk_num     += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
1992         }
1993         return 0;
1994 }
1995 
1996 /*
1997  * Fast linux specific version of OnStream FSF
1998  */
1999 static int osst_space_over_filemarks_forward_fast(struct osst_tape * STp, struct osst_request ** aSRpnt,
2000                                                                      int mt_op, int mt_count)
2001 {
2002         char  * name = tape_name(STp);
2003         int     cnt  = 0,
2004                 next_mark_ppos = -1;
2005 
2006 #if DEBUG
2007         printk(OSST_DEB_MSG "%s:D: Reached space_over_filemarks_forward_fast %d %d\n", name, mt_op, mt_count);
2008 #endif
2009         if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2010 #if DEBUG
2011                 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks_fwd\n", name);
2012 #endif
2013                 return (-EIO);
2014         }
2015 
2016         if (STp->linux_media_version >= 4) {
2017                 /*
2018                  * direct lookup in header filemark list
2019                  */
2020                 cnt = ntohl(STp->buffer->aux->filemark_cnt) - 1;
2021                 if (STp->header_ok                         && 
2022                     STp->header_cache != NULL              &&
2023                     (cnt + mt_count)   < OS_FM_TAB_MAX     &&
2024                     (cnt + mt_count)   < STp->filemark_cnt &&
2025                     ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2026                      (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] == STp->buffer->aux->last_mark_ppos)))
2027 
2028                         next_mark_ppos = ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[cnt + mt_count]);
2029 #if DEBUG
2030                 if (STp->header_cache == NULL || (cnt + mt_count) >= OS_FM_TAB_MAX)
2031                         printk(OSST_DEB_MSG "%s:D: Filemark lookup fail due to %s\n", name,
2032                                STp->header_cache == NULL?"lack of header cache":"count out of range");
2033                 else
2034                         printk(OSST_DEB_MSG "%s:D: Filemark lookup: prev mark %d (%s), skip %d to %d\n",
2035                                name, cnt,
2036                                ((cnt == -1 && ntohl(STp->buffer->aux->last_mark_ppos) == -1) ||
2037                                 (STp->header_cache->dat_fm_tab.fm_tab_ent[cnt] ==
2038                                          STp->buffer->aux->last_mark_ppos))?"match":"error",
2039                                mt_count, next_mark_ppos);
2040 #endif
2041                 if (next_mark_ppos <= 10 || next_mark_ppos > STp->eod_frame_ppos) {
2042 #if DEBUG
2043                         printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2044 #endif
2045                         return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2046                 } else {
2047                         osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2048                         if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2049 #if DEBUG
2050                                 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2051                                                  name);
2052 #endif
2053                                 return (-EIO);
2054                         }
2055                         if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2056                                 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2057                                                  name, next_mark_ppos);
2058                                 return (-EIO);
2059                         }
2060                         if (ntohl(STp->buffer->aux->filemark_cnt) != cnt + mt_count) {
2061                                 printk(KERN_WARNING "%s:W: Expected to find marker %d at ppos %d, not %d\n",
2062                                                  name, cnt+mt_count, next_mark_ppos,
2063                                                  ntohl(STp->buffer->aux->filemark_cnt));
2064                                 return (-EIO);
2065                         }
2066                 }
2067         } else {
2068                 /*
2069                  * Find nearest (usually previous) marker, then jump from marker to marker
2070                  */
2071                 while (1) {
2072                         if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER)
2073                                 break;
2074                         if (STp->buffer->aux->frame_type == OS_FRAME_TYPE_EOD) {
2075 #if DEBUG
2076                                 printk(OSST_DEB_MSG "%s:D: space_fwd: EOD reached\n", name);
2077 #endif
2078                                 return (-EIO);
2079                         }
2080                         if (ntohl(STp->buffer->aux->filemark_cnt) == 0) {
2081                                 if (STp->first_mark_ppos == -1) {
2082 #if DEBUG
2083                                         printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2084 #endif
2085                                         return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count);
2086                                 }
2087                                 osst_position_tape_and_confirm(STp, aSRpnt, STp->first_mark_ppos);
2088                                 if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2089 #if DEBUG
2090                                         printk(OSST_DEB_MSG
2091                                                "%s:D: Couldn't get logical blk num in space_filemarks_fwd_fast\n",
2092                                                name);
2093 #endif
2094                                         return (-EIO);
2095                                 }
2096                                 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2097                                         printk(KERN_WARNING "%s:W: Expected to find filemark at %d\n",
2098                                                          name, STp->first_mark_ppos);
2099                                         return (-EIO);
2100                                 }
2101                         } else {
2102                                 if (osst_space_over_filemarks_backward(STp, aSRpnt, MTBSF, 1) < 0)
2103                                         return (-EIO);
2104                                 mt_count++;
2105                         }
2106                 }
2107                 cnt++;
2108                 while (cnt != mt_count) {
2109                         next_mark_ppos = ntohl(STp->buffer->aux->next_mark_ppos);
2110                         if (!next_mark_ppos || next_mark_ppos > STp->eod_frame_ppos) {
2111 #if DEBUG
2112                                 printk(OSST_DEB_MSG "%s:D: Reverting to slow filemark space\n", name);
2113 #endif
2114                                 return osst_space_over_filemarks_forward_slow(STp, aSRpnt, mt_op, mt_count - cnt);
2115                         }
2116 #if DEBUG
2117                         else printk(OSST_DEB_MSG "%s:D: Positioning to next mark at %d\n", name, next_mark_ppos);
2118 #endif
2119                         osst_position_tape_and_confirm(STp, aSRpnt, next_mark_ppos);
2120                         cnt++;
2121                         if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2122 #if DEBUG
2123                                 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in space_filemarks\n",
2124                                                  name);
2125 #endif
2126                                 return (-EIO);
2127                         }
2128                         if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_MARKER) {
2129                                 printk(KERN_WARNING "%s:W: Expected to find marker at ppos %d, not found\n",
2130                                                  name, next_mark_ppos);
2131                                 return (-EIO);
2132                         }
2133                 }
2134         }
2135         if (mt_op == MTFSF) {
2136                 STp->frame_seq_number++;
2137                 STp->frame_in_buffer      = 0;
2138                 STp->buffer->buffer_bytes = 0;
2139                 STp->buffer->read_pointer = 0;
2140                 STp->logical_blk_num     += ntohs(STp->buffer->aux->dat.dat_list[0].blk_cnt);
2141         }
2142         return 0;
2143 }
2144 
2145 /*
2146  * In debug mode, we want to see as many errors as possible
2147  * to test the error recovery mechanism.
2148  */
2149 #if DEBUG
2150 static void osst_set_retries(struct osst_tape * STp, struct osst_request ** aSRpnt, int retries)
2151 {
2152         unsigned char           cmd[MAX_COMMAND_SIZE];
2153         struct osst_request   * SRpnt  = * aSRpnt;
2154         char                  * name   = tape_name(STp);
2155 
2156         memset(cmd, 0, MAX_COMMAND_SIZE);
2157         cmd[0] = MODE_SELECT;
2158         cmd[1] = 0x10;
2159         cmd[4] = NUMBER_RETRIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2160 
2161         (STp->buffer)->b_data[0] = cmd[4] - 1;
2162         (STp->buffer)->b_data[1] = 0;                   /* Medium Type - ignoring */
2163         (STp->buffer)->b_data[2] = 0;                   /* Reserved */
2164         (STp->buffer)->b_data[3] = 0;                   /* Block Descriptor Length */
2165         (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = NUMBER_RETRIES_PAGE | (1 << 7);
2166         (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 2;
2167         (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 4;
2168         (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = retries;
2169 
2170         if (debugging)
2171             printk(OSST_DEB_MSG "%s:D: Setting number of retries on OnStream tape to %d\n", name, retries);
2172 
2173         SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2174         *aSRpnt = SRpnt;
2175 
2176         if ((STp->buffer)->syscall_result)
2177             printk (KERN_ERR "%s:D: Couldn't set retries to %d\n", name, retries);
2178 }
2179 #endif
2180 
2181 
2182 static int osst_write_filemark(struct osst_tape * STp, struct osst_request ** aSRpnt)
2183 {
2184         int     result;
2185         int     this_mark_ppos = STp->first_frame_position;
2186         int     this_mark_lbn  = STp->logical_blk_num;
2187 #if DEBUG
2188         char  * name = tape_name(STp);
2189 #endif
2190 
2191         if (STp->raw) return 0;
2192 
2193         STp->write_type = OS_WRITE_NEW_MARK;
2194 #if DEBUG
2195         printk(OSST_DEB_MSG "%s:D: Writing Filemark %i at fppos %d (fseq %d, lblk %d)\n", 
2196                name, STp->filemark_cnt, this_mark_ppos, STp->frame_seq_number, this_mark_lbn);
2197 #endif
2198         STp->dirty = 1;
2199         result  = osst_flush_write_buffer(STp, aSRpnt);
2200         result |= osst_flush_drive_buffer(STp, aSRpnt);
2201         STp->last_mark_ppos = this_mark_ppos;
2202         STp->last_mark_lbn  = this_mark_lbn;
2203         if (STp->header_cache != NULL && STp->filemark_cnt < OS_FM_TAB_MAX)
2204                 STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt] = htonl(this_mark_ppos);
2205         if (STp->filemark_cnt++ == 0)
2206                 STp->first_mark_ppos = this_mark_ppos;
2207         return result;
2208 }
2209 
2210 static int osst_write_eod(struct osst_tape * STp, struct osst_request ** aSRpnt)
2211 {
2212         int     result;
2213 #if DEBUG
2214         char  * name = tape_name(STp);
2215 #endif
2216 
2217         if (STp->raw) return 0;
2218 
2219         STp->write_type = OS_WRITE_EOD;
2220         STp->eod_frame_ppos = STp->first_frame_position;
2221 #if DEBUG
2222         printk(OSST_DEB_MSG "%s:D: Writing EOD at fppos %d (fseq %d, lblk %d)\n", name,
2223                         STp->eod_frame_ppos, STp->frame_seq_number, STp->logical_blk_num);
2224 #endif
2225         STp->dirty = 1;
2226 
2227         result  = osst_flush_write_buffer(STp, aSRpnt); 
2228         result |= osst_flush_drive_buffer(STp, aSRpnt);
2229         STp->eod_frame_lfa = --(STp->frame_seq_number);
2230         return result;
2231 }
2232 
2233 static int osst_write_filler(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2234 {
2235         char * name = tape_name(STp);
2236 
2237 #if DEBUG
2238         printk(OSST_DEB_MSG "%s:D: Reached onstream write filler group %d\n", name, where);
2239 #endif
2240         osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2241         osst_set_frame_position(STp, aSRpnt, where, 0);
2242         STp->write_type = OS_WRITE_FILLER;
2243         while (count--) {
2244                 memcpy(STp->buffer->b_data, "Filler", 6);
2245                 STp->buffer->buffer_bytes = 6;
2246                 STp->dirty = 1;
2247                 if (osst_flush_write_buffer(STp, aSRpnt)) {
2248                         printk(KERN_INFO "%s:I: Couldn't write filler frame\n", name);
2249                         return (-EIO);
2250                 }
2251         }
2252 #if DEBUG
2253         printk(OSST_DEB_MSG "%s:D: Exiting onstream write filler group\n", name);
2254 #endif
2255         return osst_flush_drive_buffer(STp, aSRpnt);
2256 }
2257 
2258 static int __osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int where, int count)
2259 {
2260         char * name = tape_name(STp);
2261         int     result;
2262 
2263 #if DEBUG
2264         printk(OSST_DEB_MSG "%s:D: Reached onstream write header group %d\n", name, where);
2265 #endif
2266         osst_wait_ready(STp, aSRpnt, 60 * 5, 0);
2267         osst_set_frame_position(STp, aSRpnt, where, 0);
2268         STp->write_type = OS_WRITE_HEADER;
2269         while (count--) {
2270                 osst_copy_to_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2271                 STp->buffer->buffer_bytes = sizeof(os_header_t);
2272                 STp->dirty = 1;
2273                 if (osst_flush_write_buffer(STp, aSRpnt)) {
2274                         printk(KERN_INFO "%s:I: Couldn't write header frame\n", name);
2275                         return (-EIO);
2276                 }
2277         }
2278         result = osst_flush_drive_buffer(STp, aSRpnt);
2279 #if DEBUG
2280         printk(OSST_DEB_MSG "%s:D: Write onstream header group %s\n", name, result?"failed":"done");
2281 #endif
2282         return result;
2283 }
2284 
2285 static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRpnt, int locate_eod)
2286 {
2287         os_header_t * header;
2288         int           result;
2289         char        * name = tape_name(STp);
2290 
2291 #if DEBUG
2292         printk(OSST_DEB_MSG "%s:D: Writing tape header\n", name);
2293 #endif
2294         if (STp->raw) return 0;
2295 
2296         if (STp->header_cache == NULL) {
2297                 if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2298                         printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2299                         return (-ENOMEM);
2300                 }
2301                 memset(STp->header_cache, 0, sizeof(os_header_t));
2302 #if DEBUG
2303                 printk(OSST_DEB_MSG "%s:D: Allocated and cleared memory for header cache\n", name);
2304 #endif
2305         }
2306         if (STp->header_ok) STp->update_frame_cntr++;
2307         else                STp->update_frame_cntr = 0;
2308 
2309         header = STp->header_cache;
2310         strcpy(header->ident_str, "ADR_SEQ");
2311         header->major_rev      = 1;
2312         header->minor_rev      = 4;
2313         header->ext_trk_tb_off = htons(17192);
2314         header->pt_par_num     = 1;
2315         header->partition[0].partition_num              = OS_DATA_PARTITION;
2316         header->partition[0].par_desc_ver               = OS_PARTITION_VERSION;
2317         header->partition[0].wrt_pass_cntr              = htons(STp->wrt_pass_cntr);
2318         header->partition[0].first_frame_ppos           = htonl(STp->first_data_ppos);
2319         header->partition[0].last_frame_ppos            = htonl(STp->capacity);
2320         header->partition[0].eod_frame_ppos             = htonl(STp->eod_frame_ppos);
2321         header->cfg_col_width                           = htonl(20);
2322         header->dat_col_width                           = htonl(1500);
2323         header->qfa_col_width                           = htonl(0);
2324         header->ext_track_tb.nr_stream_part             = 1;
2325         header->ext_track_tb.et_ent_sz                  = 32;
2326         header->ext_track_tb.dat_ext_trk_ey.et_part_num = 0;
2327         header->ext_track_tb.dat_ext_trk_ey.fmt         = 1;
2328         header->ext_track_tb.dat_ext_trk_ey.fm_tab_off  = htons(17736);
2329         header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi = 0;
2330         header->ext_track_tb.dat_ext_trk_ey.last_hlb    = htonl(STp->eod_frame_lfa);
2331         header->ext_track_tb.dat_ext_trk_ey.last_pp     = htonl(STp->eod_frame_ppos);
2332         header->dat_fm_tab.fm_part_num                  = 0;
2333         header->dat_fm_tab.fm_tab_ent_sz                = 4;
2334         header->dat_fm_tab.fm_tab_ent_cnt               = htons(STp->filemark_cnt<OS_FM_TAB_MAX?
2335                                                                 STp->filemark_cnt:OS_FM_TAB_MAX);
2336 
2337         result  = __osst_write_header(STp, aSRpnt, 0xbae, 5);
2338         if (STp->update_frame_cntr == 0)
2339                     osst_write_filler(STp, aSRpnt, 0xbb3, 5);
2340         result &= __osst_write_header(STp, aSRpnt,     5, 5);
2341 
2342         if (locate_eod) {
2343 #if DEBUG
2344                 printk(OSST_DEB_MSG "%s:D: Locating back to eod frame addr %d\n", name, STp->eod_frame_ppos);
2345 #endif
2346                 osst_set_frame_position(STp, aSRpnt, STp->eod_frame_ppos, 0);
2347         }
2348         if (result)
2349                 printk(KERN_ERR "%s:E: Write header failed\n", name);
2350         else {
2351                 memcpy(STp->application_sig, "LIN4", 4);
2352                 STp->linux_media         = 1;
2353                 STp->linux_media_version = 4;
2354                 STp->header_ok           = 1;
2355         }
2356         return result;
2357 }
2358 
2359 static int osst_reset_header(struct osst_tape * STp, struct osst_request ** aSRpnt)
2360 {
2361         if (STp->header_cache != NULL)
2362                 memset(STp->header_cache, 0, sizeof(os_header_t));
2363 
2364         STp->logical_blk_num = STp->frame_seq_number = 0;
2365         STp->frame_in_buffer = 0;
2366         STp->eod_frame_ppos = STp->first_data_ppos = 0x0000000A;
2367         STp->filemark_cnt = 0;
2368         STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2369         return osst_write_header(STp, aSRpnt, 1);
2370 }
2371 
2372 static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt, int ppos)
2373 {
2374         char        * name = tape_name(STp);
2375         os_header_t * header;
2376         os_aux_t    * aux;
2377         char          id_string[8];
2378         int           linux_media_version,
2379                       update_frame_cntr;
2380 
2381         if (STp->raw)
2382                 return 1;
2383 
2384         if (ppos == 5 || ppos == 0xbae || STp->buffer->syscall_result) {
2385                 if (osst_set_frame_position(STp, aSRpnt, ppos, 0))
2386                         printk(KERN_WARNING "%s:W: Couldn't position tape\n", name);
2387                 osst_wait_ready(STp, aSRpnt, 60 * 15, 0);
2388                 if (osst_initiate_read (STp, aSRpnt)) {
2389                         printk(KERN_WARNING "%s:W: Couldn't initiate read\n", name);
2390                         return 0;
2391                 }
2392         }
2393         if (osst_read_frame(STp, aSRpnt, 180)) {
2394 #if DEBUG
2395                 printk(OSST_DEB_MSG "%s:D: Couldn't read header frame\n", name);
2396 #endif
2397                 return 0;
2398         }
2399         header = (os_header_t *) STp->buffer->b_data;   /* warning: only first segment addressable */
2400         aux = STp->buffer->aux;
2401         if (aux->frame_type != OS_FRAME_TYPE_HEADER) {
2402 #if DEBUG
2403                 printk(OSST_DEB_MSG "%s:D: Skipping non-header frame (%d)\n", name, ppos);
2404 #endif
2405                 return 0;
2406         }
2407         if (ntohl(aux->frame_seq_num)              != 0                   ||
2408             ntohl(aux->logical_blk_num)            != 0                   ||
2409                   aux->partition.partition_num     != OS_CONFIG_PARTITION ||
2410             ntohl(aux->partition.first_frame_ppos) != 0                   ||
2411             ntohl(aux->partition.last_frame_ppos)  != 0xbb7               ) {
2412 #if DEBUG
2413                 printk(OSST_DEB_MSG "%s:D: Invalid header frame (%d,%d,%d,%d,%d)\n", name,
2414                                 ntohl(aux->frame_seq_num), ntohl(aux->logical_blk_num),
2415                                 aux->partition.partition_num, ntohl(aux->partition.first_frame_ppos),
2416                                 ntohl(aux->partition.last_frame_ppos));
2417 #endif
2418                 return 0;
2419         }
2420         if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0 &&
2421             strncmp(header->ident_str, "ADR-SEQ", 7) != 0) {
2422                 strlcpy(id_string, header->ident_str, 8);
2423 #if DEBUG
2424                 printk(OSST_DEB_MSG "%s:D: Invalid header identification string %s\n", name, id_string);
2425 #endif
2426                 return 0;
2427         }
2428         update_frame_cntr = ntohl(aux->update_frame_cntr);
2429         if (update_frame_cntr < STp->update_frame_cntr) {
2430 #if DEBUG
2431                 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with update_frame_counter %d<%d\n",
2432                                    name, ppos, update_frame_cntr, STp->update_frame_cntr);
2433 #endif
2434                 return 0;
2435         }
2436         if (header->major_rev != 1 || header->minor_rev != 4 ) {
2437 #if DEBUG
2438                 printk(OSST_DEB_MSG "%s:D: %s revision %d.%d detected (1.4 supported)\n", 
2439                                  name, (header->major_rev != 1 || header->minor_rev < 2 || 
2440                                        header->minor_rev  > 4 )? "Invalid" : "Warning:",
2441                                  header->major_rev, header->minor_rev);
2442 #endif
2443                 if (header->major_rev != 1 || header->minor_rev < 2 || header->minor_rev > 4)
2444                         return 0;
2445         }
2446 #if DEBUG
2447         if (header->pt_par_num != 1)
2448                 printk(KERN_INFO "%s:W: %d partitions defined, only one supported\n", 
2449                                  name, header->pt_par_num);
2450 #endif
2451         memcpy(id_string, aux->application_sig, 4);
2452         id_string[4] = 0;
2453         if (memcmp(id_string, "LIN", 3) == 0) {
2454                 STp->linux_media = 1;
2455                 linux_media_version = id_string[3] - '';
2456                 if (linux_media_version != 4)
2457                         printk(KERN_INFO "%s:I: Linux media version %d detected (current 4)\n",
2458                                          name, linux_media_version);
2459         } else {
2460                 printk(KERN_WARNING "%s:W: Non Linux media detected (%s)\n", name, id_string);
2461                 return 0;
2462         }
2463         if (linux_media_version < STp->linux_media_version) {
2464 #if DEBUG
2465                 printk(OSST_DEB_MSG "%s:D: Skipping frame %d with linux_media_version %d\n",
2466                                   name, ppos, linux_media_version);
2467 #endif
2468                 return 0;
2469         }
2470         if (linux_media_version > STp->linux_media_version) {
2471 #if DEBUG
2472                 printk(OSST_DEB_MSG "%s:D: Frame %d sets linux_media_version to %d\n",
2473                                    name, ppos, linux_media_version);
2474 #endif
2475                 memcpy(STp->application_sig, id_string, 5);
2476                 STp->linux_media_version = linux_media_version;
2477                 STp->update_frame_cntr = -1;
2478         }
2479         if (update_frame_cntr > STp->update_frame_cntr) {
2480 #if DEBUG
2481                 printk(OSST_DEB_MSG "%s:D: Frame %d sets update_frame_counter to %d\n",
2482                                    name, ppos, update_frame_cntr);
2483 #endif
2484                 if (STp->header_cache == NULL) {
2485                         if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
2486                                 printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
2487                                 return 0;
2488                         }
2489 #if DEBUG
2490                         printk(OSST_DEB_MSG "%s:D: Allocated memory for header cache\n", name);
2491 #endif
2492                 }
2493                 osst_copy_from_buffer(STp->buffer, (unsigned char *)STp->header_cache);
2494                 header = STp->header_cache;     /* further accesses from cached (full) copy */
2495 
2496                 STp->wrt_pass_cntr     = ntohs(header->partition[0].wrt_pass_cntr);
2497                 STp->first_data_ppos   = ntohl(header->partition[0].first_frame_ppos);
2498                 STp->eod_frame_ppos    = ntohl(header->partition[0].eod_frame_ppos);
2499                 STp->eod_frame_lfa     = ntohl(header->ext_track_tb.dat_ext_trk_ey.last_hlb);
2500                 STp->filemark_cnt      = ntohl(aux->filemark_cnt);
2501                 STp->first_mark_ppos   = ntohl(aux->next_mark_ppos);
2502                 STp->last_mark_ppos    = ntohl(aux->last_mark_ppos);
2503                 STp->last_mark_lbn     = ntohl(aux->last_mark_lbn);
2504                 STp->update_frame_cntr = update_frame_cntr;
2505 #if DEBUG
2506         printk(OSST_DEB_MSG "%s:D: Detected write pass %d, update frame counter %d, filemark counter %d\n",
2507                           name, STp->wrt_pass_cntr, STp->update_frame_cntr, STp->filemark_cnt);
2508         printk(OSST_DEB_MSG "%s:D: first data frame on tape = %d, last = %d, eod frame = %d\n", name,
2509                           STp->first_data_ppos,
2510                           ntohl(header->partition[0].last_frame_ppos),
2511                           ntohl(header->partition[0].eod_frame_ppos));
2512         printk(OSST_DEB_MSG "%s:D: first mark on tape = %d, last = %d, eod frame = %d\n", 
2513                           name, STp->first_mark_ppos, STp->last_mark_ppos, STp->eod_frame_ppos);
2514 #endif
2515                 if (header->minor_rev < 4 && STp->linux_media_version == 4) {
2516 #if DEBUG
2517                         printk(OSST_DEB_MSG "%s:D: Moving filemark list to ADR 1.4 location\n", name);
2518 #endif
2519                         memcpy((void *)header->dat_fm_tab.fm_tab_ent, 
2520                                (void *)header->old_filemark_list, sizeof(header->dat_fm_tab.fm_tab_ent));
2521                         memset((void *)header->old_filemark_list, 0, sizeof(header->old_filemark_list));
2522                 }
2523                 if (header->minor_rev == 4   &&
2524                     (header->ext_trk_tb_off                          != htons(17192)               ||
2525                      header->partition[0].partition_num              != OS_DATA_PARTITION          ||
2526                      header->partition[0].par_desc_ver               != OS_PARTITION_VERSION       ||
2527                      header->partition[0].last_frame_ppos            != htonl(STp->capacity)       ||
2528                      header->cfg_col_width                           != htonl(20)                  ||
2529                      header->dat_col_width                           != htonl(1500)                ||
2530                      header->qfa_col_width                           != htonl(0)                   ||
2531                      header->ext_track_tb.nr_stream_part             != 1                          ||
2532                      header->ext_track_tb.et_ent_sz                  != 32                         ||
2533                      header->ext_track_tb.dat_ext_trk_ey.et_part_num != OS_DATA_PARTITION          ||
2534                      header->ext_track_tb.dat_ext_trk_ey.fmt         != 1                          ||
2535                      header->ext_track_tb.dat_ext_trk_ey.fm_tab_off  != htons(17736)               ||
2536                      header->ext_track_tb.dat_ext_trk_ey.last_hlb_hi != 0                          ||
2537                      header->ext_track_tb.dat_ext_trk_ey.last_pp     != htonl(STp->eod_frame_ppos) ||
2538                      header->dat_fm_tab.fm_part_num                  != OS_DATA_PARTITION          ||
2539                      header->dat_fm_tab.fm_tab_ent_sz                != 4                          ||
2540                      header->dat_fm_tab.fm_tab_ent_cnt               !=
2541                              htons(STp->filemark_cnt<OS_FM_TAB_MAX?STp->filemark_cnt:OS_FM_TAB_MAX)))
2542                         printk(KERN_WARNING "%s:W: Failed consistency check ADR 1.4 format\n", name);
2543 
2544         }
2545 
2546         return 1;
2547 }
2548 
2549 static int osst_analyze_headers(struct osst_tape * STp, struct osst_request ** aSRpnt)
2550 {
2551         int     position, ppos;
2552         int     first, last;
2553         int     valid = 0;
2554         char  * name  = tape_name(STp);
2555 
2556         position = osst_get_frame_position(STp, aSRpnt);
2557 
2558         if (STp->raw) {
2559                 STp->header_ok = STp->linux_media = 1;
2560                 STp->linux_media_version = 0;
2561                 return 1;
2562         }
2563         STp->header_ok = STp->linux_media = STp->linux_media_version = 0;
2564         STp->wrt_pass_cntr = STp->update_frame_cntr = -1;
2565         STp->eod_frame_ppos = STp->first_data_ppos = -1;
2566         STp->first_mark_ppos = STp->last_mark_ppos = STp->last_mark_lbn = -1;
2567 #if DEBUG
2568         printk(OSST_DEB_MSG "%s:D: Reading header\n", name);
2569 #endif
2570 
2571         /* optimization for speed - if we are positioned at ppos 10, read second group first  */        
2572         /* TODO try the ADR 1.1 locations for the second group if we have no valid one yet... */
2573 
2574         first = position==10?0xbae: 5;
2575         last  = position==10?0xbb3:10;
2576 
2577         for (ppos = first; ppos < last; ppos++)
2578                 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2579                         valid = 1;
2580 
2581         first = position==10? 5:0xbae;
2582         last  = position==10?10:0xbb3;
2583 
2584         for (ppos = first; ppos < last; ppos++)
2585                 if (__osst_analyze_headers(STp, aSRpnt, ppos))
2586                         valid = 1;
2587 
2588         if (!valid) {
2589                 printk(KERN_ERR "%s:E: Failed to find valid ADRL header, new media?\n", name);
2590                 STp->eod_frame_ppos = STp->first_data_ppos = 0;
2591                 osst_set_frame_position(STp, aSRpnt, 10, 0);
2592                 return 0;
2593         }
2594         if (position <= STp->first_data_ppos) {
2595                 position = STp->first_data_ppos;
2596                 STp->ps[0].drv_file = STp->ps[0].drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
2597         }
2598         osst_set_frame_position(STp, aSRpnt, position, 0);
2599         STp->header_ok = 1;
2600 
2601         return 1;
2602 }
2603 
2604 static int osst_verify_position(struct osst_tape * STp, struct osst_request ** aSRpnt)
2605 {
2606         int     frame_position  = STp->first_frame_position;
2607         int     frame_seq_numbr = STp->frame_seq_number;
2608         int     logical_blk_num = STp->logical_blk_num;
2609         int     halfway_frame   = STp->frame_in_buffer;
2610         int     read_pointer    = STp->buffer->read_pointer;
2611         int     prev_mark_ppos  = -1;
2612         int     actual_mark_ppos, i, n;
2613 #if DEBUG
2614         char  * name = tape_name(STp);
2615 
2616         printk(OSST_DEB_MSG "%s:D: Verify that the tape is really the one we think before writing\n", name);
2617 #endif
2618         osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2619         if (osst_get_logical_frame(STp, aSRpnt, -1, 0) < 0) {
2620 #if DEBUG
2621                 printk(OSST_DEB_MSG "%s:D: Couldn't get logical blk num in verify_position\n", name);
2622 #endif
2623                 return (-EIO);
2624         }
2625         if (STp->linux_media_version >= 4) {
2626                 for (i=0; i<STp->filemark_cnt; i++)
2627                         if ((n=ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[i])) < frame_position)
2628                                 prev_mark_ppos = n;
2629         } else
2630                 prev_mark_ppos = frame_position - 1;  /* usually - we don't really know */
2631         actual_mark_ppos = STp->buffer->aux->frame_type == OS_FRAME_TYPE_MARKER ?
2632                                 frame_position - 1 : ntohl(STp->buffer->aux->last_mark_ppos);
2633         if (frame_position  != STp->first_frame_position                   ||
2634             frame_seq_numbr != STp->frame_seq_number + (halfway_frame?0:1) ||
2635             prev_mark_ppos  != actual_mark_ppos                            ) {
2636 #if DEBUG
2637                 printk(OSST_DEB_MSG "%s:D: Block mismatch: fppos %d-%d, fseq %d-%d, mark %d-%d\n", name,
2638                                   STp->first_frame_position, frame_position, 
2639                                   STp->frame_seq_number + (halfway_frame?0:1),
2640                                   frame_seq_numbr, actual_mark_ppos, prev_mark_ppos);
2641 #endif
2642                 return (-EIO);
2643         }
2644         if (halfway_frame) {
2645                 /* prepare buffer for append and rewrite on top of original */
2646                 osst_set_frame_position(STp, aSRpnt, frame_position - 1, 0);
2647                 STp->buffer->buffer_bytes  = read_pointer;
2648                 STp->ps[STp->partition].rw = ST_WRITING;
2649                 STp->dirty                 = 1;
2650         }
2651         STp->frame_in_buffer  = halfway_frame;
2652         STp->frame_seq_number = frame_seq_numbr;
2653         STp->logical_blk_num  = logical_blk_num;
2654         return 0;
2655 }
2656 
2657 /* Acc. to OnStream, the vers. numbering is the following:
2658  * X.XX for released versions (X=digit), 
2659  * XXXY for unreleased versions (Y=letter)
2660  * Ordering 1.05 < 106A < 106B < ...  < 106a < ... < 1.06
2661  * This fn makes monoton numbers out of this scheme ...
2662  */
2663 static unsigned int osst_parse_firmware_rev (const char * str)
2664 {
2665         if (str[1] == '.') {
2666                 return (str[0]-'')*10000
2667                         +(str[2]-'')*1000
2668                         +(str[3]-'')*100;
2669         } else {
2670                 return (str[0]-'')*10000
2671                         +(str[1]-'')*1000
2672                         +(str[2]-'')*100 - 100
2673                         +(str[3]-'@');
2674         }
2675 }
2676 
2677 /*
2678  * Configure the OnStream SCII tape drive for default operation
2679  */
2680 static int osst_configure_onstream(struct osst_tape *STp, struct osst_request ** aSRpnt)
2681 {
2682         unsigned char                  cmd[MAX_COMMAND_SIZE];
2683         char                         * name = tape_name(STp);
2684         struct osst_request          * SRpnt = * aSRpnt;
2685         osst_mode_parameter_header_t * header;
2686         osst_block_size_page_t       * bs;
2687         osst_capabilities_page_t     * cp;
2688         osst_tape_paramtr_page_t     * prm;
2689         int                            drive_buffer_size;
2690 
2691         if (STp->ready != ST_READY) {
2692 #if DEBUG
2693             printk(OSST_DEB_MSG "%s:D: Not Ready\n", name);
2694 #endif
2695             return (-EIO);
2696         }
2697         
2698         if (STp->os_fw_rev < 10600) {
2699             printk(KERN_INFO "%s:I: Old OnStream firmware revision detected (%s),\n", name, STp->device->rev);
2700             printk(KERN_INFO "%s:I: an upgrade to version 1.06 or above is recommended\n", name);
2701         }
2702 
2703         /*
2704          * Configure 32.5KB (data+aux) frame size.
2705          * Get the current frame size from the block size mode page
2706          */
2707         memset(cmd, 0, MAX_COMMAND_SIZE);
2708         cmd[0] = MODE_SENSE;
2709         cmd[1] = 8;
2710         cmd[2] = BLOCK_SIZE_PAGE;
2711         cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2712 
2713         SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2714         if (SRpnt == NULL) {
2715 #if DEBUG
2716             printk(OSST_DEB_MSG "osst :D: Busy\n");
2717 #endif
2718             return (-EBUSY);
2719         }
2720         *aSRpnt = SRpnt;
2721         if ((STp->buffer)->syscall_result != 0) {
2722             printk (KERN_ERR "%s:E: Can't get tape block size mode page\n", name);
2723             return (-EIO);
2724         }
2725 
2726         header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2727         bs = (osst_block_size_page_t *) ((STp->buffer)->b_data + sizeof(osst_mode_parameter_header_t) + header->bdl);
2728 
2729 #if DEBUG
2730         printk(OSST_DEB_MSG "%s:D: 32KB play back: %s\n",   name, bs->play32     ? "Yes" : "No");
2731         printk(OSST_DEB_MSG "%s:D: 32.5KB play back: %s\n", name, bs->play32_5   ? "Yes" : "No");
2732         printk(OSST_DEB_MSG "%s:D: 32KB record: %s\n",      name, bs->record32   ? "Yes" : "No");
2733         printk(OSST_DEB_MSG "%s:D: 32.5KB record: %s\n",    name, bs->record32_5 ? "Yes" : "No");
2734 #endif
2735 
2736         /*
2737          * Configure default auto columns mode, 32.5KB transfer mode
2738          */ 
2739         bs->one = 1;
2740         bs->play32 = 0;
2741         bs->play32_5 = 1;
2742         bs->record32 = 0;
2743         bs->record32_5 = 1;
2744 
2745         memset(cmd, 0, MAX_COMMAND_SIZE);
2746         cmd[0] = MODE_SELECT;
2747         cmd[1] = 0x10;
2748         cmd[4] = BLOCK_SIZE_PAGE_LENGTH + MODE_HEADER_LENGTH;
2749 
2750         SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2751         *aSRpnt = SRpnt;
2752         if ((STp->buffer)->syscall_result != 0) {
2753             printk (KERN_ERR "%s:E: Couldn't set tape block size mode page\n", name);
2754             return (-EIO);
2755         }
2756 
2757 #if DEBUG
2758         printk(KERN_INFO "%s:D: Drive Block Size changed to 32.5K\n", name);
2759          /*
2760          * In debug mode, we want to see as many errors as possible
2761          * to test the error recovery mechanism.
2762          */
2763         osst_set_retries(STp, aSRpnt, 0);
2764         SRpnt = * aSRpnt;
2765 #endif
2766 
2767         /*
2768          * Set vendor name to 'LIN4' for "Linux support version 4".
2769          */
2770 
2771         memset(cmd, 0, MAX_COMMAND_SIZE);
2772         cmd[0] = MODE_SELECT;
2773         cmd[1] = 0x10;
2774         cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
2775 
2776         header->mode_data_length = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH - 1;
2777         header->medium_type      = 0;   /* Medium Type - ignoring */
2778         header->dsp              = 0;   /* Reserved */
2779         header->bdl              = 0;   /* Block Descriptor Length */
2780         
2781         (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = VENDOR_IDENT_PAGE | (1 << 7);
2782         (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 6;
2783         (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 'L';
2784         (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 'I';
2785         (STp->buffer)->b_data[MODE_HEADER_LENGTH + 4] = 'N';
2786         (STp->buffer)->b_data[MODE_HEADER_LENGTH + 5] = '4';
2787         (STp->buffer)->b_data[MODE_HEADER_LENGTH + 6] = 0;
2788         (STp->buffer)->b_data[MODE_HEADER_LENGTH + 7] = 0;
2789 
2790         SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_TO_DEVICE, STp->timeout, 0, 1);
2791         *aSRpnt = SRpnt;
2792 
2793         if ((STp->buffer)->syscall_result != 0) {
2794             printk (KERN_ERR "%s:E: Couldn't set vendor name to %s\n", name, 
2795                         (char *) ((STp->buffer)->b_data + MODE_HEADER_LENGTH + 2));
2796             return (-EIO);
2797         }
2798 
2799         memset(cmd, 0, MAX_COMMAND_SIZE);
2800         cmd[0] = MODE_SENSE;
2801         cmd[1] = 8;
2802         cmd[2] = CAPABILITIES_PAGE;
2803         cmd[4] = CAPABILITIES_PAGE_LENGTH + MODE_HEADER_LENGTH;
2804 
2805         SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2806         *aSRpnt = SRpnt;
2807 
2808         if ((STp->buffer)->syscall_result != 0) {
2809             printk (KERN_ERR "%s:E: Can't get capabilities page\n", name);
2810             return (-EIO);
2811         }
2812 
2813         header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2814         cp     = (osst_capabilities_page_t    *) ((STp->buffer)->b_data +
2815                  sizeof(osst_mode_parameter_header_t) + header->bdl);
2816 
2817         drive_buffer_size = ntohs(cp->buffer_size) / 2;
2818 
2819         memset(cmd, 0, MAX_COMMAND_SIZE);
2820         cmd[0] = MODE_SENSE;
2821         cmd[1] = 8;
2822         cmd[2] = TAPE_PARAMTR_PAGE;
2823         cmd[4] = TAPE_PARAMTR_PAGE_LENGTH + MODE_HEADER_LENGTH;
2824 
2825         SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], DMA_FROM_DEVICE, STp->timeout, 0, 1);
2826         *aSRpnt = SRpnt;
2827 
2828         if ((STp->buffer)->syscall_result != 0) {
2829             printk (KERN_ERR "%s:E: Can't get tape parameter page\n", name);
2830             return (-EIO);
2831         }
2832 
2833         header = (osst_mode_parameter_header_t *) (STp->buffer)->b_data;
2834         prm    = (osst_tape_paramtr_page_t    *) ((STp->buffer)->b_data +
2835                  sizeof(osst_mode_parameter_header_t) + header->bdl);
2836 
2837         STp->density  = prm->density;
2838         STp->capacity = ntohs(prm->segtrk) * ntohs(prm->trks);
2839 #if DEBUG
2840         printk(OSST_DEB_MSG "%s:D: Density %d, tape length: %dMB, drive buffer size: %dKB\n",
2841                           name, STp->density, STp->capacity / 32, drive_buffer_size);
2842 #endif
2843 
2844         return 0;
2845         
2846 }
2847 
2848 
2849 /* Step over EOF if it has been inadvertently crossed (ioctl not used because
2850    it messes up the block number). */
2851 static int cross_eof(struct osst_tape *STp, struct osst_request ** aSRpnt, int forward)
2852 {
2853         int     result;
2854         char  * name = tape_name(STp);
2855 
2856 #if DEBUG
2857         if (debugging)
2858                 printk(OSST_DEB_MSG "%s:D: Stepping over filemark %s.\n",
2859                                   name, forward ? "forward" : "backward");
2860 #endif
2861 
2862         if (forward) {
2863            /* assumes that the filemark is already read by the drive, so this is low cost */
2864            result = osst_space_over_filemarks_forward_slow(STp, aSRpnt, MTFSF, 1);
2865         }
2866         else
2867            /* assumes this is only called if we just read the filemark! */
2868            result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - 1);
2869 
2870         if (result < 0)
2871            printk(KERN_WARNING "%s:W: Stepping over filemark %s failed.\n",
2872                                 name, forward ? "forward" : "backward");
2873 
2874         return result;
2875 }
2876 
2877 
2878 /* Get the tape position. */
2879 
2880 static int osst_get_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt)
2881 {
2882         unsigned char           scmd[MAX_COMMAND_SIZE];
2883         struct osst_request   * SRpnt;
2884         int                     result = 0;
2885         char                  * name   = tape_name(STp);
2886 
2887         /* KG: We want to be able to use it for checking Write Buffer availability
2888          *  and thus don't want to risk to overwrite anything. Exchange buffers ... */
2889         char            mybuf[24];
2890         char          * olddata = STp->buffer->b_data;
2891         int             oldsize = STp->buffer->buffer_size;
2892 
2893         if (STp->ready != ST_READY) return (-EIO);
2894 
2895         memset (scmd, 0, MAX_COMMAND_SIZE);
2896         scmd[0] = READ_POSITION;
2897 
2898         STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2899         SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2900                                       STp->timeout, MAX_RETRIES, 1);
2901         if (!SRpnt) {
2902                 STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2903                 return (-EBUSY);
2904         }
2905         *aSRpnt = SRpnt;
2906 
2907         if (STp->buffer->syscall_result)
2908                 result = ((SRpnt->sense[2] & 0x0f) == 3) ? -EIO : -EINVAL;      /* 3: Write Error */
2909 
2910         if (result == -EINVAL)
2911                 printk(KERN_ERR "%s:E: Can't read tape position.\n", name);
2912         else {
2913                 if (result == -EIO) {   /* re-read position - this needs to preserve media errors */
2914                         unsigned char mysense[16];
2915                         memcpy (mysense, SRpnt->sense, 16);
2916                         memset (scmd, 0, MAX_COMMAND_SIZE);
2917                         scmd[0] = READ_POSITION;
2918                         STp->buffer->b_data = mybuf; STp->buffer->buffer_size = 24;
2919                         SRpnt = osst_do_scsi(SRpnt, STp, scmd, 20, DMA_FROM_DEVICE,
2920                                                     STp->timeout, MAX_RETRIES, 1);
2921 #if DEBUG
2922                         printk(OSST_DEB_MSG "%s:D: Reread position, reason=[%02x:%02x:%02x], result=[%s%02x:%02x:%02x]\n",
2923                                         name, mysense[2], mysense[12], mysense[13], STp->buffer->syscall_result?"":"ok:",
2924                                         SRpnt->sense[2],SRpnt->sense[12],SRpnt->sense[13]);
2925 #endif
2926                         if (!STp->buffer->syscall_result)
2927                                 memcpy (SRpnt->sense, mysense, 16);
2928                         else
2929                                 printk(KERN_WARNING "%s:W: Double error in get position\n", name);
2930                 }
2931                 STp->first_frame_position = ((STp->buffer)->b_data[4] << 24)
2932                                           + ((STp->buffer)->b_data[5] << 16)
2933                                           + ((STp->buffer)->b_data[6] << 8)
2934                                           +  (STp->buffer)->b_data[7];
2935                 STp->last_frame_position  = ((STp->buffer)->b_data[ 8] << 24)
2936                                           + ((STp->buffer)->b_data[ 9] << 16)
2937                                           + ((STp->buffer)->b_data[10] <<  8)
2938                                           +  (STp->buffer)->b_data[11];
2939                 STp->cur_frames           =  (STp->buffer)->b_data[15];
2940 #if DEBUG
2941                 if (debugging) {
2942                         printk(OSST_DEB_MSG "%s:D: Drive Positions: host %d, tape %d%s, buffer %d\n", name,
2943                                             STp->first_frame_position, STp->last_frame_position,
2944                                             ((STp->buffer)->b_data[0]&0x80)?" (BOP)":
2945                                             ((STp->buffer)->b_data[0]&0x40)?" (EOP)":"",
2946                                             STp->cur_frames);
2947                 }
2948 #endif
2949                 if (STp->cur_frames == 0 && STp->first_frame_position != STp->last_frame_position) {
2950 #if DEBUG
2951                         printk(OSST_DEB_MSG "%s:D: Correcting read position %d, %d, %d\n", name,
2952                                         STp->first_frame_position, STp->last_frame_position, STp->cur_frames);
2953 #endif
2954                         STp->first_frame_position = STp->last_frame_position;
2955                 }
2956         }
2957         STp->buffer->b_data = olddata; STp->buffer->buffer_size = oldsize;
2958 
2959         return (result == 0 ? STp->first_frame_position : result);
2960 }
2961 
2962 
2963 /* Set the tape block */
2964 static int osst_set_frame_position(struct osst_tape *STp, struct osst_request ** aSRpnt, int ppos, int skip)
2965 {
2966         unsigned char           scmd[MAX_COMMAND_SIZE];
2967         struct osst_request   * SRpnt;
2968         struct st_partstat    * STps;
2969         int                     result = 0;
2970         int                     pp     = (ppos == 3000 && !skip)? 0 : ppos;
2971         char                  * name   = tape_name(STp);
2972 
2973         if (STp->ready != ST_READY) return (-EIO);
2974 
2975         STps = &(STp->ps[STp->partition]);
2976 
2977         if (ppos < 0 || ppos > STp->capacity) {
2978                 printk(KERN_WARNING "%s:W: Reposition request %d out of range\n", name, ppos);
2979                 pp = ppos = ppos < 0 ? 0 : (STp->capacity - 1);
2980                 result = (-EINVAL);
2981         }
2982 
2983         do {
2984 #if DEBUG
2985                 if (debugging)
2986                         printk(OSST_DEB_MSG "%s:D: Setting ppos to %d.\n", name, pp);
2987 #endif
2988                 memset (scmd, 0, MAX_COMMAND_SIZE);
2989                 scmd[0] = SEEK_10;
2990                 scmd[1] = 1;
2991                 scmd[3] = (pp >> 24);
2992                 scmd[4] = (pp >> 16);
2993                 scmd[5] = (pp >> 8);
2994                 scmd[6] =  pp;
2995                 if (skip)
2996                         scmd[9] = 0x80;
2997 
2998                 SRpnt = osst_do_scsi(*aSRpnt, STp, scmd, 0, DMA_NONE, STp->long_timeout,
2999                                                                 MAX_RETRIES, 1);
3000                 if (!SRpnt)
3001                         return (-EBUSY);
3002                 *aSRpnt  = SRpnt;
3003 
3004                 if ((STp->buffer)->syscall_result != 0) {
3005 #if DEBUG
3006                         printk(OSST_DEB_MSG "%s:D: SEEK command from %d to %d failed.\n",
3007                                         name, STp->first_frame_position, pp);
3008 #endif
3009                         result = (-EIO);
3010                 }
3011                 if (pp != ppos)
3012                         osst_wait_ready(STp, aSRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
3013         } while ((pp != ppos) && (pp = ppos));
3014         STp->first_frame_position = STp->last_frame_position = ppos;
3015         STps->eof = ST_NOEOF;
3016         STps->at_sm = 0;
3017         STps->rw = ST_IDLE;
3018         STp->frame_in_buffer = 0;
3019         return result;
3020 }
3021 
3022 static int osst_write_trailer(struct osst_tape *STp, struct osst_request ** aSRpnt, int leave_at_EOT)
3023 {
3024         struct st_partstat * STps = &(STp->ps[STp->partition]);
3025         int result = 0;
3026 
3027         if (STp->write_type != OS_WRITE_NEW_MARK) {
3028                 /* true unless the user wrote the filemark for us */
3029                 result = osst_flush_drive_buffer(STp, aSRpnt);
3030                 if (result < 0) goto out;
3031                 result = osst_write_filemark(STp, aSRpnt);
3032                 if (result < 0) goto out;
3033 
3034                 if (STps->drv_file >= 0)
3035                         STps->drv_file++ ;
3036                 STps->drv_block = 0;
3037         }
3038         result = osst_write_eod(STp, aSRpnt);
3039         osst_write_header(STp, aSRpnt, leave_at_EOT);
3040 
3041         STps->eof = ST_FM;
3042 out:
3043         return result;
3044 }
3045 
3046 /* osst versions of st functions - augmented and stripped to suit OnStream only */
3047 
3048 /* Flush the write buffer (never need to write if variable blocksize). */
3049 static int osst_flush_write_buffer(struct osst_tape *STp, struct osst_request ** aSRpnt)
3050 {
3051         int                     offset, transfer, blks = 0;
3052         int                     result = 0;
3053         unsigned char           cmd[MAX_COMMAND_SIZE];
3054         struct osst_request   * SRpnt = *aSRpnt;
3055         struct st_partstat    * STps;
3056         char                  * name = tape_name(STp);
3057 
3058         if ((STp->buffer)->writing) {
3059                 if (SRpnt == (STp->buffer)->last_SRpnt)
3060 #if DEBUG
3061                         { printk(OSST_DEB_MSG
3062          "%s:D: aSRpnt points to osst_request that write_behind_check will release -- cleared\n", name);
3063 #endif
3064                         *aSRpnt = SRpnt = NULL;
3065 #if DEBUG
3066                         } else if (SRpnt)
3067                                 printk(OSST_DEB_MSG
3068          "%s:D: aSRpnt does not point to osst_request that write_behind_check will release -- strange\n", name);
3069 #endif  
3070                 osst_write_behind_check(STp);
3071                 if ((STp->buffer)->syscall_result) {
3072 #if DEBUG
3073                         if (debugging)
3074                                 printk(OSST_DEB_MSG "%s:D: Async write error (flush) %x.\n",
3075                                        name, (STp->buffer)->midlevel_result);
3076 #endif
3077                         if ((STp->buffer)->midlevel_result == INT_MAX)
3078                                 return (-ENOSPC);
3079                         return (-EIO);
3080                 }
3081         }
3082 
3083         result = 0;
3084         if (STp->dirty == 1) {
3085 
3086                 STp->write_count++;
3087                 STps     = &(STp->ps[STp->partition]);
3088                 STps->rw = ST_WRITING;
3089                 offset   = STp->buffer->buffer_bytes;
3090                 blks     = (offset + STp->block_size - 1) / STp->block_size;
3091                 transfer = OS_FRAME_SIZE;
3092                 
3093                 if (offset < OS_DATA_SIZE)
3094                         osst_zero_buffer_tail(STp->buffer);
3095 
3096                 if (STp->poll)
3097                         if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -50, 120))
3098                                 result = osst_recover_wait_frame(STp, aSRpnt, 1);
3099 
3100                 memset(cmd, 0, MAX_COMMAND_SIZE);
3101                 cmd[0] = WRITE_6;
3102                 cmd[1] = 1;
3103                 cmd[4] = 1;
3104 
3105                 switch  (STp->write_type) {
3106                    case OS_WRITE_DATA:
3107 #if DEBUG
3108                         if (debugging)
3109                                 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n",
3110                                         name, blks, STp->frame_seq_number, 
3111                                         STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3112 #endif
3113                         osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3114                                       STp->logical_blk_num - blks, STp->block_size, blks);
3115                         break;
3116                    case OS_WRITE_EOD:
3117                         osst_init_aux(STp, OS_FRAME_TYPE_EOD, STp->frame_seq_number++,
3118                                       STp->logical_blk_num, 0, 0);
3119                         break;
3120                    case OS_WRITE_NEW_MARK:
3121                         osst_init_aux(STp, OS_FRAME_TYPE_MARKER, STp->frame_seq_number++,
3122                                       STp->logical_blk_num++, 0, blks=1);
3123                         break;
3124                    case OS_WRITE_HEADER:
3125                         osst_init_aux(STp, OS_FRAME_TYPE_HEADER, 0, 0, 0, blks=0);
3126                         break;
3127                 default: /* probably FILLER */
3128                         osst_init_aux(STp, OS_FRAME_TYPE_FILL, 0, 0, 0, 0);
3129                 }
3130 #if DEBUG
3131                 if (debugging)
3132                         printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
3133                                                  name, offset, transfer, blks);
3134 #endif
3135 
3136                 SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, transfer, DMA_TO_DEVICE,
3137                                               STp->timeout, MAX_RETRIES, 1);
3138                 *aSRpnt = SRpnt;
3139                 if (!SRpnt)
3140                         return (-EBUSY);
3141 
3142                 if ((STp->buffer)->syscall_result != 0) {
3143 #if DEBUG
3144                         printk(OSST_DEB_MSG
3145                                 "%s:D: write sense [0]=0x%02x [2]=%02x [12]=%02x [13]=%02x\n",
3146                                 name, SRpnt->sense[0], SRpnt->sense[2],
3147                                 SRpnt->sense[12], SRpnt->sense[13]);
3148 #endif
3149                         if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3150                             (SRpnt->sense[2] & 0x40) && /* FIXME - SC-30 drive doesn't assert EOM bit */
3151                             (SRpnt->sense[2] & 0x0f) == NO_SENSE) {
3152                                 STp->dirty = 0;
3153                                 (STp->buffer)->buffer_bytes = 0;
3154                                 result = (-ENOSPC);
3155                         }
3156                         else {
3157                                 if (osst_write_error_recovery(STp, aSRpnt, 1)) {
3158                                         printk(KERN_ERR "%s:E: Error on flush write.\n", name);
3159                                         result = (-EIO);
3160                                 }
3161                         }
3162                         STps->drv_block = (-1);         /* FIXME - even if write recovery succeeds? */
3163                 }
3164                 else {
3165                         STp->first_frame_position++;
3166                         STp->dirty = 0;
3167                         (STp->buffer)->buffer_bytes = 0;
3168                 }
3169         }
3170 #if DEBUG
3171         printk(OSST_DEB_MSG "%s:D: Exit flush write buffer with code %d\n", name, result);
3172 #endif
3173         return result;
3174 }
3175 
3176 
3177 /* Flush the tape buffer. The tape will be positioned correctly unless
3178    seek_next is true. */
3179 static int osst_flush_buffer(struct osst_tape * STp, struct osst_request ** aSRpnt, int seek_next)
3180 {
3181         struct st_partstat * STps;
3182         int    backspace = 0, result = 0;
3183 #if DEBUG
3184         char * name = tape_name(STp);
3185 #endif
3186 
3187         /*
3188          * If there was a bus reset, block further access
3189          * to this device.
3190          */
3191         if( STp->pos_unknown)
3192                 return (-EIO);
3193 
3194         if (STp->ready != ST_READY)
3195                 return 0;
3196 
3197         STps = &(STp->ps[STp->partition]);
3198         if (STps->rw == ST_WRITING || STp->dirty) {     /* Writing */
3199                 STp->write_type = OS_WRITE_DATA;
3200                 return osst_flush_write_buffer(STp, aSRpnt);
3201         }
3202         if (STp->block_size == 0)
3203                 return 0;
3204 
3205 #if DEBUG
3206         printk(OSST_DEB_MSG "%s:D: Reached flush (read) buffer\n", name);
3207 #endif
3208 
3209         if (!STp->can_bsr) {
3210                 backspace = ((STp->buffer)->buffer_bytes + (STp->buffer)->read_pointer) / STp->block_size -
3211                             ((STp->buffer)->read_pointer + STp->block_size - 1        ) / STp->block_size ;
3212                 (STp->buffer)->buffer_bytes = 0;
3213                 (STp->buffer)->read_pointer = 0;
3214                 STp->frame_in_buffer = 0;               /* FIXME is this relevant w. OSST? */
3215         }
3216 
3217         if (!seek_next) {
3218                 if (STps->eof == ST_FM_HIT) {
3219                         result = cross_eof(STp, aSRpnt, 0); /* Back over the EOF hit */
3220                         if (!result)
3221                                 STps->eof = ST_NOEOF;
3222                         else {
3223                                 if (STps->drv_file >= 0)
3224                                         STps->drv_file++;
3225                                 STps->drv_block = 0;
3226                         }
3227                 }
3228                 if (!result && backspace > 0)   /* TODO -- design and run a test case for this */
3229                         result = osst_seek_logical_blk(STp, aSRpnt, STp->logical_blk_num - backspace);
3230         }
3231         else if (STps->eof == ST_FM_HIT) {
3232                 if (STps->drv_file >= 0)
3233                         STps->drv_file++;
3234                 STps->drv_block = 0;
3235                 STps->eof = ST_NOEOF;
3236         }
3237 
3238         return result;
3239 }
3240 
3241 static int osst_write_frame(struct osst_tape * STp, struct osst_request ** aSRpnt, int synchronous)
3242 {
3243         unsigned char           cmd[MAX_COMMAND_SIZE];
3244         struct osst_request   * SRpnt;
3245         int                     blks;
3246 #if DEBUG
3247         char                  * name = tape_name(STp);
3248 #endif
3249 
3250         if ((!STp-> raw) && (STp->first_frame_position == 0xbae)) { /* _must_ preserve buffer! */
3251 #if DEBUG
3252                 printk(OSST_DEB_MSG "%s:D: Reaching config partition.\n", name);
3253 #endif
3254                 if (osst_flush_drive_buffer(STp, aSRpnt) < 0) {
3255                         return (-EIO);
3256                 }
3257                 /* error recovery may have bumped us past the header partition */
3258                 if (osst_get_frame_position(STp, aSRpnt) < 0xbb8) {
3259 #if DEBUG
3260                         printk(OSST_DEB_MSG "%s:D: Skipping over config partition.\n", name);
3261 #endif
3262                 osst_position_tape_and_confirm(STp, aSRpnt, 0xbb8);
3263                 }
3264         }
3265 
3266         if (STp->poll)
3267                 if (osst_wait_frame (STp, aSRpnt, STp->first_frame_position, -48, 120))
3268                         if (osst_recover_wait_frame(STp, aSRpnt, 1))
3269                                 return (-EIO);
3270 
3271 //      osst_build_stats(STp, &SRpnt);
3272 
3273         STp->ps[STp->partition].rw = ST_WRITING;
3274         STp->write_type            = OS_WRITE_DATA;
3275                         
3276         memset(cmd, 0, MAX_COMMAND_SIZE);
3277         cmd[0]   = WRITE_6;
3278         cmd[1]   = 1;
3279         cmd[4]   = 1;                                           /* one frame at a time... */
3280         blks     = STp->buffer->buffer_bytes / STp->block_size;
3281 #if DEBUG
3282         if (debugging)
3283                 printk(OSST_DEB_MSG "%s:D: Writing %d blocks to frame %d, lblks %d-%d\n", name, blks, 
3284                         STp->frame_seq_number, STp->logical_blk_num - blks, STp->logical_blk_num - 1);
3285 #endif
3286         osst_init_aux(STp, OS_FRAME_TYPE_DATA, STp->frame_seq_number++,
3287                       STp->logical_blk_num - blks, STp->block_size, blks);
3288 
3289 #if DEBUG
3290         if (!synchronous)
3291                 STp->write_pending = 1;
3292 #endif
3293         SRpnt = osst_do_scsi(*aSRpnt, STp, cmd, OS_FRAME_SIZE, DMA_TO_DEVICE, STp->timeout,
3294                                                                         MAX_RETRIES, synchronous);
3295         if (!SRpnt)
3296                 return (-EBUSY);
3297         *aSRpnt = SRpnt;
3298 
3299         if (synchronous) {
3300                 if (STp->buffer->syscall_result != 0) {
3301 #if DEBUG
3302                         if (debugging)
3303                                 printk(OSST_DEB_MSG "%s:D: Error on write:\n", name);
3304 #endif
3305                         if ((SRpnt->sense[0] & 0x70) == 0x70 &&
3306                             (SRpnt->sense[2] & 0x40)) {
3307                                 if ((SRpnt->sense[2] & 0x0f) == VOLUME_OVERFLOW)
3308                                         return (-ENOSPC);
3309                         }
3310                         else {
3311                                 if (osst_write_error_recovery(STp, aSRpnt, 1))
3312                                         return (-EIO);
3313                         }
3314                 }
3315                 else
3316                         STp->first_frame_position++;
3317         }
3318 
3319         STp->write_count++;
3320 
3321         return 0;
3322 }
3323 
3324 /* Lock or unlock the drive door. Don't use when struct osst_request allocated. */
3325 static int do_door_lock(struct osst_tape * STp, int do_lock)
3326 {
3327         int retval, cmd;
3328 
3329         cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK;
3330 #if DEBUG
3331         printk(OSST_DEB_MSG "%s:D: %socking drive door.\n", tape_name(STp), do_lock ? "L" : "Unl");
3332 #endif
3333         retval = scsi_ioctl(STp->device, cmd, NULL);
3334         if (!retval) {
3335                 STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED;
3336         }
3337         else {
3338                 STp->door_locked = ST_LOCK_FAILS;
3339         }
3340         return retval;
3341 }
3342 
3343 /* Set the internal state after reset */
3344 static void reset_state(struct osst_tape *STp)
3345 {
3346         int i;
3347         struct st_partstat *STps;
3348 
3349         STp->pos_unknown = 0;
3350         for (i = 0; i < ST_NBR_PARTITIONS; i++) {
3351                 STps = &(STp->ps[i]);
3352                 STps->rw = ST_IDLE;
3353                 STps->eof = ST_NOEOF;
3354                 STps->at_sm = 0;
3355                 STps->last_block_valid = 0;
3356                 STps->drv_block = -1;
3357                 STps->drv_file = -1;
3358         }
3359 }
3360                                 
3361 
3362 /* Entry points to osst */
3363 
3364 /* Write command */
3365 static ssize_t osst_write(struct file * filp, const char __user * buf, size_t count, loff_t *ppos)
3366 {
3367         ssize_t               total, retval = 0;
3368         ssize_t               i, do_count, blks, transfer;
3369         int                   write_threshold;
3370         int                   doing_write = 0;
3371         const char   __user * b_point;
3372         struct osst_request * SRpnt = NULL;
3373         struct st_modedef   * STm;
3374         struct st_partstat  * STps;
3375         struct osst_tape    * STp  = filp->private_data;
3376         char                * name = tape_name(STp);
3377 
3378 
3379         if (mutex_lock_interruptible(&STp->lock))
3380                 return (-ERESTARTSYS);
3381 
3382         /*
3383          * If we are in the middle of error recovery, don't let anyone
3384          * else try and use this device.  Also, if error recovery fails, it
3385          * may try and take the device offline, in which case all further
3386          * access to the device is prohibited.
3387          */
3388         if( !scsi_block_when_processing_errors(STp->device) ) {
3389                 retval = (-ENXIO);
3390                 goto out;
3391         }
3392         
3393         if (STp->ready != ST_READY) {
3394                 if (STp->ready == ST_NO_TAPE)
3395                         retval = (-ENOMEDIUM);
3396                 else
3397                         retval = (-EIO);
3398                 goto out;
3399         }
3400         STm = &(STp->modes[STp->current_mode]);
3401         if (!STm->defined) {
3402                 retval = (-ENXIO);
3403                 goto out;
3404         }
3405         if (count == 0)
3406                 goto out;
3407 
3408         /*
3409          * If there was a bus reset, block further access
3410          * to this device.
3411          */
3412         if (STp->pos_unknown) {
3413                 retval = (-EIO);
3414                 goto out;
3415         }
3416 
3417 #if DEBUG
3418         if (!STp->in_use) {
3419                 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3420                 retval = (-EIO);
3421                 goto out;
3422         }
3423 #endif
3424 
3425         if (STp->write_prot) {
3426                 retval = (-EACCES);
3427                 goto out;
3428         }
3429 
3430         /* Write must be integral number of blocks */
3431         if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3432                 printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3433                                        name, count, STp->block_size<1024?
3434                                        STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3435                 retval = (-EINVAL);
3436                 goto out;
3437         }
3438 
3439         if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3440                 printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3441                                        name, STp->first_frame_position);
3442                 retval = (-ENOSPC);
3443                 goto out;
3444         }
3445 
3446         if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3447                 STp->door_locked = ST_LOCKED_AUTO;
3448 
3449         STps = &(STp->ps[STp->partition]);
3450 
3451         if (STps->rw == ST_READING) {
3452 #if DEBUG
3453                 printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name, 
3454                                         STps->drv_file, STps->drv_block);
3455 #endif
3456                 retval = osst_flush_buffer(STp, &SRpnt, 0);
3457                 if (retval)
3458                         goto out;
3459                 STps->rw = ST_IDLE;
3460         }
3461         if (STps->rw != ST_WRITING) {
3462                 /* Are we totally rewriting this tape? */
3463                 if (!STp->header_ok ||
3464                     (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3465                     (STps->drv_file == 0 && STps->drv_block == 0)) {
3466                         STp->wrt_pass_cntr++;
3467 #if DEBUG
3468                         printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3469                                                   name, STp->wrt_pass_cntr);
3470 #endif
3471                         osst_reset_header(STp, &SRpnt);
3472                         STps->drv_file = STps->drv_block = 0;
3473                 }
3474                 /* Do we know where we'll be writing on the tape? */
3475                 else {
3476                         if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3477                                         STps->drv_file < 0 || STps->drv_block < 0) {
3478                                 if (STp->first_frame_position == STp->eod_frame_ppos) { /* at EOD */
3479                                         STps->drv_file = STp->filemark_cnt;
3480                                         STps->drv_block = 0;
3481                                 }
3482                                 else {
3483                                         /* We have no idea where the tape is positioned - give up */
3484 #if DEBUG
3485                                         printk(OSST_DEB_MSG
3486                                                 "%s:D: Cannot write at indeterminate position.\n", name);
3487 #endif
3488                                         retval = (-EIO);
3489                                         goto out;
3490                                 }
3491                         }         
3492                         if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3493                                 STp->filemark_cnt = STps->drv_file;
3494                                 STp->last_mark_ppos =
3495                                         ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3496                                 printk(KERN_WARNING
3497                                         "%s:W: Overwriting file %d with old write pass counter %d\n",
3498                                                 name, STps->drv_file, STp->wrt_pass_cntr);
3499                                 printk(KERN_WARNING
3500                                         "%s:W: may lead to stale data being accepted on reading back!\n",
3501                                                 name);
3502 #if DEBUG
3503                                 printk(OSST_DEB_MSG
3504                                   "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3505                                         name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3506 #endif
3507                         }
3508                 }
3509                 STp->fast_open = 0;
3510         }
3511         if (!STp->header_ok) {
3512 #if DEBUG
3513                 printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3514 #endif
3515                 retval = (-EIO);
3516                 goto out;
3517         }
3518 
3519         if ((STp->buffer)->writing) {
3520 if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3521                 osst_write_behind_check(STp);
3522                 if ((STp->buffer)->syscall_result) {
3523 #if DEBUG
3524                 if (debugging)
3525                         printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3526                                                  (STp->buffer)->midlevel_result);
3527 #endif
3528                 if ((STp->buffer)->midlevel_result == INT_MAX)
3529                         STps->eof = ST_EOM_OK;
3530                 else
3531                         STps->eof = ST_EOM_ERROR;
3532                 }
3533         }
3534         if (STps->eof == ST_EOM_OK) {
3535                 retval = (-ENOSPC);
3536                 goto out;
3537         }
3538         else if (STps->eof == ST_EOM_ERROR) {
3539                 retval = (-EIO);
3540                 goto out;
3541         }
3542 
3543         /* Check the buffer readability in cases where copy_user might catch
3544                  the problems after some tape movement. */
3545         if ((copy_from_user(&i, buf, 1) != 0 ||
3546              copy_from_user(&i, buf + count - 1, 1) != 0)) {
3547                 retval = (-EFAULT);
3548                 goto out;
3549         }
3550 
3551         if (!STm->do_buffer_writes) {
3552                 write_threshold = 1;
3553         }
3554         else
3555                 write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3556         if (!STm->do_async_writes)
3557                 write_threshold--;
3558 
3559         total = count;
3560 #if DEBUG
3561         if (debugging)
3562                 printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3563                                 name, (int) count, STps->drv_file, STps->drv_block,
3564                                 STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3565 #endif
3566         b_point = buf;
3567         while ((STp->buffer)->buffer_bytes + count > write_threshold)
3568         {
3569                 doing_write = 1;
3570                 do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3571                            (STp->buffer)->buffer_bytes;
3572                 if (do_count > count)
3573                         do_count = count;
3574 
3575                 i = append_to_buffer(b_point, STp->buffer, do_count);
3576                 if (i) {
3577                         retval = i;
3578                         goto out;
3579                 }
3580 
3581                 blks = do_count / STp->block_size;
3582                 STp->logical_blk_num += blks;  /* logical_blk_num is incremented as data is moved from user */
3583   
3584                 i = osst_write_frame(STp, &SRpnt, 1);
3585 
3586                 if (i == (-ENOSPC)) {
3587                         transfer = STp->buffer->writing;        /* FIXME -- check this logic */
3588                         if (transfer <= do_count) {
3589                                 filp->f_pos += do_count - transfer;
3590                                 count -= do_count - transfer;
3591                                 if (STps->drv_block >= 0) {
3592                                         STps->drv_block += (do_count - transfer) / STp->block_size;
3593                                 }
3594                                 STps->eof = ST_EOM_OK;
3595                                 retval = (-ENOSPC);             /* EOM within current request */
3596 #if DEBUG
3597                                 if (debugging)
3598                                       printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3599                                                              name, (int) transfer);
3600 #endif
3601                         }
3602                         else {
3603                                 STps->eof = ST_EOM_ERROR;
3604                                 STps->drv_block = (-1);         /* Too cautious? */
3605                                 retval = (-EIO);                /* EOM for old data */
3606 #if DEBUG
3607                                 if (debugging)
3608                                       printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3609 #endif
3610                         }
3611                 }
3612                 else
3613                         retval = i;
3614                         
3615                 if (retval < 0) {
3616                         if (SRpnt != NULL) {
3617                                 osst_release_request(SRpnt);
3618                                 SRpnt = NULL;
3619                         }
3620                         STp->buffer->buffer_bytes = 0;
3621                         STp->dirty = 0;
3622                         if (count < total)
3623                                 retval = total - count;
3624                         goto out;
3625                 }
3626 
3627                 filp->f_pos += do_count;
3628                 b_point += do_count;
3629                 count -= do_count;
3630                 if (STps->drv_block >= 0) {
3631                         STps->drv_block += blks;
3632                 }
3633                 STp->buffer->buffer_bytes = 0;
3634                 STp->dirty = 0;
3635         }  /* end while write threshold exceeded */
3636 
3637         if (count != 0) {
3638                 STp->dirty = 1;
3639                 i = append_to_buffer(b_point, STp->buffer, count);
3640                 if (i) {
3641                         retval = i;
3642                         goto out;
3643                 }
3644                 blks = count / STp->block_size;
3645                 STp->logical_blk_num += blks;
3646                 if (STps->drv_block >= 0) {
3647                         STps->drv_block += blks;
3648                 }
3649                 filp->f_pos += count;
3650                 count = 0;
3651         }
3652 
3653         if (doing_write && (STp->buffer)->syscall_result != 0) {
3654                 retval = (STp->buffer)->syscall_result;
3655                 goto out;
3656         }
3657 
3658         if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) { 
3659                 /* Schedule an asynchronous write */
3660                 (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3661                                            STp->block_size) * STp->block_size;
3662                 STp->dirty = !((STp->buffer)->writing ==
3663                                           (STp->buffer)->buffer_bytes);
3664 
3665                 i = osst_write_frame(STp, &SRpnt, 0);
3666                 if (i < 0) {
3667                         retval = (-EIO);
3668                         goto out;
3669                 }
3670                 SRpnt = NULL;                   /* Prevent releasing this request! */
3671         }
3672         STps->at_sm &= (total == 0);
3673         if (total > 0)
3674                 STps->eof = ST_NOEOF;
3675 
3676         retval = total;
3677 
3678 out:
3679         if (SRpnt != NULL) osst_release_request(SRpnt);
3680 
3681         mutex_unlock(&STp->lock);
3682 
3683         return retval;
3684 }
3685 
3686 
3687 /* Read command */
3688 static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3689 {
3690         ssize_t               total, retval = 0;
3691         ssize_t               i, transfer;
3692         int                   special;
3693         struct st_modedef   * STm;
3694         struct st_partstat  * STps;
3695         struct osst_request * SRpnt = NULL;
3696         struct osst_tape    * STp   = filp->private_data;
3697         char                * name  = tape_name(STp);
3698 
3699 
3700         if (mutex_lock_interruptible(&STp->lock))
3701                 return (-ERESTARTSYS);
3702 
3703         /*
3704          * If we are in the middle of error recovery, don't let anyone
3705          * else try and use this device.  Also, if error recovery fails, it
3706          * may try and take the device offline, in which case all further
3707          * access to the device is prohibited.
3708          */
3709         if( !scsi_block_when_processing_errors(STp->device) ) {
3710                 retval = (-ENXIO);
3711                 goto out;
3712         }
3713         
3714         if (STp->ready != ST_READY) {
3715                 if (STp->ready == ST_NO_TAPE)
3716                         retval = (-ENOMEDIUM);
3717                 else
3718                         retval = (-EIO);
3719                 goto out;
3720         }
3721         STm = &(STp->modes[STp->current_mode]);
3722         if (!STm->defined) {
3723