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