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