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