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