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