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