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