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