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