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