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