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