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