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