patch-2_6_7-vs1_9_1_12
[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 "hosts.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 (ppos != &filp->f_pos) {
3189                 /* "A request was outside the capabilities of the device." */
3190                 retval = (-ENXIO);
3191                 goto out;
3192         }
3193
3194         if (STp->ready != ST_READY) {
3195                 if (STp->ready == ST_NO_TAPE)
3196                         retval = (-ENOMEDIUM);
3197                 else
3198                         retval = (-EIO);
3199                 goto out;
3200         }
3201         STm = &(STp->modes[STp->current_mode]);
3202         if (!STm->defined) {
3203                 retval = (-ENXIO);
3204                 goto out;
3205         }
3206         if (count == 0)
3207                 goto out;
3208
3209         /*
3210          * If there was a bus reset, block further access
3211          * to this device.
3212          */
3213         if (STp->pos_unknown) {
3214                 retval = (-EIO);
3215                 goto out;
3216         }
3217
3218 #if DEBUG
3219         if (!STp->in_use) {
3220                 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3221                 retval = (-EIO);
3222                 goto out;
3223         }
3224 #endif
3225
3226         if (STp->write_prot) {
3227                 retval = (-EACCES);
3228                 goto out;
3229         }
3230
3231         /* Write must be integral number of blocks */
3232         if (STp->block_size != 0 && (count % STp->block_size) != 0) {
3233                 printk(KERN_ERR "%s:E: Write (%Zd bytes) not multiple of tape block size (%d%c).\n",
3234                                        name, count, STp->block_size<1024?
3235                                        STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3236                 retval = (-EINVAL);
3237                 goto out;
3238         }
3239
3240         if (STp->first_frame_position >= STp->capacity - OSST_EOM_RESERVE) {
3241                 printk(KERN_ERR "%s:E: Write truncated at EOM early warning (frame %d).\n",
3242                                        name, STp->first_frame_position);
3243                 retval = (-ENOSPC);
3244                 goto out;
3245         }
3246
3247         if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3248                 STp->door_locked = ST_LOCKED_AUTO;
3249
3250         STps = &(STp->ps[STp->partition]);
3251
3252         if (STps->rw == ST_READING) {
3253 #if DEBUG
3254                 printk(OSST_DEB_MSG "%s:D: Switching from read to write at file %d, block %d\n", name, 
3255                                         STps->drv_file, STps->drv_block);
3256 #endif
3257                 retval = osst_flush_buffer(STp, &SRpnt, 0);
3258                 if (retval)
3259                         goto out;
3260                 STps->rw = ST_IDLE;
3261         }
3262         if (STps->rw != ST_WRITING) {
3263                 /* Are we totally rewriting this tape? */
3264                 if (!STp->header_ok ||
3265                     (STp->first_frame_position == STp->first_data_ppos && STps->drv_block < 0) ||
3266                     (STps->drv_file == 0 && STps->drv_block == 0)) {
3267                         STp->wrt_pass_cntr++;
3268 #if DEBUG
3269                         printk(OSST_DEB_MSG "%s:D: Allocating next write pass counter: %d\n",
3270                                                   name, STp->wrt_pass_cntr);
3271 #endif
3272                         osst_reset_header(STp, &SRpnt);
3273                         STps->drv_file = STps->drv_block = 0;
3274                 }
3275                 /* Do we know where we'll be writing on the tape? */
3276                 else {
3277                         if ((STp->fast_open && osst_verify_position(STp, &SRpnt)) ||
3278                                         STps->drv_file < 0 || STps->drv_block < 0) {
3279                                 if (STp->first_frame_position == STp->eod_frame_ppos) { /* at EOD */
3280                                         STps->drv_file = STp->filemark_cnt;
3281                                         STps->drv_block = 0;
3282                                 }
3283                                 else {
3284                                         /* We have no idea where the tape is positioned - give up */
3285 #if DEBUG
3286                                         printk(OSST_DEB_MSG
3287                                                 "%s:D: Cannot write at indeterminate position.\n", name);
3288 #endif
3289                                         retval = (-EIO);
3290                                         goto out;
3291                                 }
3292                         }         
3293                         if ((STps->drv_file + STps->drv_block) > 0 && STps->drv_file < STp->filemark_cnt) {
3294                                 STp->filemark_cnt = STps->drv_file;
3295                                 STp->last_mark_ppos =
3296                                         ntohl(STp->header_cache->dat_fm_tab.fm_tab_ent[STp->filemark_cnt-1]);
3297                                 printk(KERN_WARNING
3298                                         "%s:W: Overwriting file %d with old write pass counter %d\n",
3299                                                 name, STps->drv_file, STp->wrt_pass_cntr);
3300                                 printk(KERN_WARNING
3301                                         "%s:W: may lead to stale data being accepted on reading back!\n",
3302                                                 name);
3303 #if DEBUG
3304                                 printk(OSST_DEB_MSG
3305                                   "%s:D: resetting filemark count to %d and last mark ppos,lbn to %d,%d\n",
3306                                         name, STp->filemark_cnt, STp->last_mark_ppos, STp->last_mark_lbn);
3307 #endif
3308                         }
3309                 }
3310                 STp->fast_open = FALSE;
3311         }
3312         if (!STp->header_ok) {
3313 #if DEBUG
3314                 printk(OSST_DEB_MSG "%s:D: Write cannot proceed without valid headers\n", name);
3315 #endif
3316                 retval = (-EIO);
3317                 goto out;
3318         }
3319
3320         if ((STp->buffer)->writing) {
3321 if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name, __LINE__);
3322                 osst_write_behind_check(STp);
3323                 if ((STp->buffer)->syscall_result) {
3324 #if DEBUG
3325                 if (debugging)
3326                         printk(OSST_DEB_MSG "%s:D: Async write error (write) %x.\n", name,
3327                                                  (STp->buffer)->midlevel_result);
3328 #endif
3329                 if ((STp->buffer)->midlevel_result == INT_MAX)
3330                         STps->eof = ST_EOM_OK;
3331                 else
3332                         STps->eof = ST_EOM_ERROR;
3333                 }
3334         }
3335         if (STps->eof == ST_EOM_OK) {
3336                 retval = (-ENOSPC);
3337                 goto out;
3338         }
3339         else if (STps->eof == ST_EOM_ERROR) {
3340                 retval = (-EIO);
3341                 goto out;
3342         }
3343
3344         /* Check the buffer readability in cases where copy_user might catch
3345                  the problems after some tape movement. */
3346         if ((copy_from_user(&i, buf, 1) != 0 ||
3347              copy_from_user(&i, buf + count - 1, 1) != 0)) {
3348                 retval = (-EFAULT);
3349                 goto out;
3350         }
3351
3352         if (!STm->do_buffer_writes) {
3353                 write_threshold = 1;
3354         }
3355         else
3356                 write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
3357         if (!STm->do_async_writes)
3358                 write_threshold--;
3359
3360         total = count;
3361 #if DEBUG
3362         if (debugging)
3363                 printk(OSST_DEB_MSG "%s:D: Writing %d bytes to file %d block %d lblk %d fseq %d fppos %d\n",
3364                                 name, count, STps->drv_file, STps->drv_block,
3365                                 STp->logical_blk_num, STp->frame_seq_number, STp->first_frame_position);
3366 #endif
3367         b_point = buf;
3368         while ((STp->buffer)->buffer_bytes + count > write_threshold)
3369         {
3370                 doing_write = 1;
3371                 do_count = (STp->buffer)->buffer_blocks * STp->block_size -
3372                            (STp->buffer)->buffer_bytes;
3373                 if (do_count > count)
3374                         do_count = count;
3375
3376                 i = append_to_buffer(b_point, STp->buffer, do_count);
3377                 if (i) {
3378                         retval = i;
3379                         goto out;
3380                 }
3381
3382                 blks = do_count / STp->block_size;
3383                 STp->logical_blk_num += blks;  /* logical_blk_num is incremented as data is moved from user */
3384   
3385                 i = osst_write_frame(STp, &SRpnt, TRUE);
3386
3387                 if (i == (-ENOSPC)) {
3388                         transfer = STp->buffer->writing;        /* FIXME -- check this logic */
3389                         if (transfer <= do_count) {
3390                                 filp->f_pos += do_count - transfer;
3391                                 count -= do_count - transfer;
3392                                 if (STps->drv_block >= 0) {
3393                                         STps->drv_block += (do_count - transfer) / STp->block_size;
3394                                 }
3395                                 STps->eof = ST_EOM_OK;
3396                                 retval = (-ENOSPC);             /* EOM within current request */
3397 #if DEBUG
3398                                 if (debugging)
3399                                       printk(OSST_DEB_MSG "%s:D: EOM with %d bytes unwritten.\n",
3400                                                              name, transfer);
3401 #endif
3402                         }
3403                         else {
3404                                 STps->eof = ST_EOM_ERROR;
3405                                 STps->drv_block = (-1);         /* Too cautious? */
3406                                 retval = (-EIO);                /* EOM for old data */
3407 #if DEBUG
3408                                 if (debugging)
3409                                       printk(OSST_DEB_MSG "%s:D: EOM with lost data.\n", name);
3410 #endif
3411                         }
3412                 }
3413                 else
3414                         retval = i;
3415                         
3416                 if (retval < 0) {
3417                         if (SRpnt != NULL) {
3418                                 scsi_release_request(SRpnt);
3419                                 SRpnt = NULL;
3420                         }
3421                         STp->buffer->buffer_bytes = 0;
3422                         STp->dirty = 0;
3423                         if (count < total)
3424                                 retval = total - count;
3425                         goto out;
3426                 }
3427
3428                 filp->f_pos += do_count;
3429                 b_point += do_count;
3430                 count -= do_count;
3431                 if (STps->drv_block >= 0) {
3432                         STps->drv_block += blks;
3433                 }
3434                 STp->buffer->buffer_bytes = 0;
3435                 STp->dirty = 0;
3436         }  /* end while write threshold exceeded */
3437
3438         if (count != 0) {
3439                 STp->dirty = 1;
3440                 i = append_to_buffer(b_point, STp->buffer, count);
3441                 if (i) {
3442                         retval = i;
3443                         goto out;
3444                 }
3445                 blks = count / STp->block_size;
3446                 STp->logical_blk_num += blks;
3447                 if (STps->drv_block >= 0) {
3448                         STps->drv_block += blks;
3449                 }
3450                 filp->f_pos += count;
3451                 count = 0;
3452         }
3453
3454         if (doing_write && (STp->buffer)->syscall_result != 0) {
3455                 retval = (STp->buffer)->syscall_result;
3456                 goto out;
3457         }
3458
3459         if (STm->do_async_writes && ((STp->buffer)->buffer_bytes >= STp->write_threshold)) { 
3460                 /* Schedule an asynchronous write */
3461                 (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
3462                                            STp->block_size) * STp->block_size;
3463                 STp->dirty = !((STp->buffer)->writing ==
3464                                           (STp->buffer)->buffer_bytes);
3465
3466                 i = osst_write_frame(STp, &SRpnt, FALSE);
3467                 if (i < 0) {
3468                         retval = (-EIO);
3469                         goto out;
3470                 }
3471                 SRpnt = NULL;                   /* Prevent releasing this request! */
3472         }
3473         STps->at_sm &= (total == 0);
3474         if (total > 0)
3475                 STps->eof = ST_NOEOF;
3476
3477         retval = total;
3478
3479 out:
3480         if (SRpnt != NULL) scsi_release_request(SRpnt);
3481
3482         up(&STp->lock);
3483
3484         return retval;
3485 }
3486
3487
3488 /* Read command */
3489 static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, loff_t *ppos)
3490 {
3491         ssize_t        total, retval = 0;
3492         ssize_t        i, transfer;
3493         int            special;
3494         ST_mode      * STm;
3495         ST_partstat  * STps;
3496         Scsi_Request * SRpnt = NULL;
3497         OS_Scsi_Tape * STp   = filp->private_data;
3498         char         * name  = tape_name(STp);
3499
3500
3501         if (down_interruptible(&STp->lock))
3502                 return (-ERESTARTSYS);
3503
3504         /*
3505          * If we are in the middle of error recovery, don't let anyone
3506          * else try and use this device.  Also, if error recovery fails, it
3507          * may try and take the device offline, in which case all further
3508          * access to the device is prohibited.
3509          */
3510         if( !scsi_block_when_processing_errors(STp->device) ) {
3511                 retval = (-ENXIO);
3512                 goto out;
3513         }
3514         
3515         if (ppos != &filp->f_pos) {
3516                 /* "A request was outside the capabilities of the device." */
3517                 retval = (-ENXIO);
3518                 goto out;
3519         }
3520
3521         if (STp->ready != ST_READY) {
3522                 if (STp->ready == ST_NO_TAPE)
3523                         retval = (-ENOMEDIUM);
3524                 else
3525                         retval = (-EIO);
3526                 goto out;
3527         }
3528         STm = &(STp->modes[STp->current_mode]);
3529         if (!STm->defined) {
3530                 retval = (-ENXIO);
3531                 goto out;
3532         }
3533 #if DEBUG
3534         if (!STp->in_use) {
3535                 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
3536                 retval = (-EIO);
3537                 goto out;
3538         }
3539 #endif
3540         /* Must have initialized medium */
3541         if (!STp->header_ok) {
3542                 retval = (-EIO);
3543                 goto out;
3544         }
3545
3546         if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED && !do_door_lock(STp, 1))
3547                 STp->door_locked = ST_LOCKED_AUTO;
3548
3549         STps = &(STp->ps[STp->partition]);
3550         if (STps->rw == ST_WRITING) {
3551                 retval = osst_flush_buffer(STp, &SRpnt, 0);
3552                 if (retval)
3553                         goto out;
3554                 STps->rw = ST_IDLE;
3555                 /* FIXME -- this may leave the tape without EOD and up2date headers */
3556         }
3557
3558         if ((count % STp->block_size) != 0) {
3559                 printk(KERN_WARNING
3560                     "%s:W: Read (%Zd bytes) not multiple of tape block size (%d%c).\n", name, count,
3561                     STp->block_size<1024?STp->block_size:STp->block_size/1024, STp->block_size<1024?'b':'k');
3562         }
3563
3564 #if DEBUG
3565         if (debugging && STps->eof != ST_NOEOF)
3566                 printk(OSST_DEB_MSG "%s:D: EOF/EOM flag up (%d). Bytes %d\n", name,
3567                                      STps->eof, (STp->buffer)->buffer_bytes);
3568 #endif
3569         if ((STp->buffer)->buffer_bytes == 0 &&
3570              STps->eof >= ST_EOD_1) {
3571                 if (STps->eof < ST_EOD) {
3572                         STps->eof += 1;
3573                         retval = 0;
3574                         goto out;
3575                 }
3576                 retval = (-EIO);  /* EOM or Blank Check */
3577                 goto out;
3578         }
3579
3580         /* Check the buffer writability before any tape movement. Don't alter
3581                  buffer data. */
3582         if (copy_from_user(&i, buf, 1)             != 0 ||
3583             copy_to_user  (buf, &i, 1)             != 0 ||
3584             copy_from_user(&i, buf + count - 1, 1) != 0 ||
3585             copy_to_user  (buf + count - 1, &i, 1) != 0) {
3586                 retval = (-EFAULT);
3587                 goto out;
3588         }
3589
3590         /* Loop until enough data in buffer or a special condition found */
3591         for (total = 0, special = 0; total < count - STp->block_size + 1 && !special; ) {
3592
3593                 /* Get new data if the buffer is empty */
3594                 if ((STp->buffer)->buffer_bytes == 0) {
3595                         if (STps->eof == ST_FM_HIT)
3596                                 break;
3597                         special = osst_get_logical_frame(STp, &SRpnt, STp->frame_seq_number, 0);
3598                         if (special < 0) {                      /* No need to continue read */
3599                                 STp->frame_in_buffer = 0;
3600                                 retval = special;
3601                                 goto out;
3602                         }
3603                 }
3604
3605                 /* Move the data from driver buffer to user buffer */
3606                 if ((STp->buffer)->buffer_bytes > 0) {
3607 #if DEBUG
3608                         if (debugging && STps->eof != ST_NOEOF)
3609                             printk(OSST_DEB_MSG "%s:D: EOF up (%d). Left %d, needed %d.\n", name,
3610                                                  STps->eof, (STp->buffer)->buffer_bytes, count - total);
3611 #endif
3612                         /* force multiple of block size, note block_size may have been adjusted */
3613                         transfer = (((STp->buffer)->buffer_bytes < count - total ?
3614                                      (STp->buffer)->buffer_bytes : count - total)/
3615                                         STp->block_size) * STp->block_size;
3616
3617                         if (transfer == 0) {
3618                                 printk(KERN_WARNING
3619                                   "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
3620                                         name, count, STp->block_size < 1024?
3621                                         STp->block_size:STp->block_size/1024,
3622                                         STp->block_size<1024?'b':'k');
3623                                 break;
3624                         }
3625                         i = from_buffer(STp->buffer, buf, transfer);
3626                         if (i)  {
3627                                 retval = i;
3628                                 goto out;
3629                         }
3630                         STp->logical_blk_num += transfer / STp->block_size;
3631                         STps->drv_block      += transfer / STp->block_size;
3632                         filp->f_pos          += transfer;
3633                         buf                  += transfer;
3634                         total                += transfer;
3635                 }
3636  
3637                 if ((STp->buffer)->buffer_bytes == 0) {
3638 #if DEBUG
3639                         if (debugging)
3640                                 printk(OSST_DEB_MSG "%s:D: Finished with frame %d\n",
3641                                                 name, STp->frame_seq_number);
3642 #endif
3643                         STp->frame_in_buffer = 0;
3644                         STp->frame_seq_number++;              /* frame to look for next time */
3645                 }
3646         } /* for (total = 0, special = 0; total < count && !special; ) */
3647
3648         /* Change the eof state if no data from tape or buffer */
3649         if (total == 0) {
3650                 if (STps->eof == ST_FM_HIT) {
3651                         STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD_2:ST_FM;
3652                         STps->drv_block = 0;
3653                         if (STps->drv_file >= 0)
3654                                 STps->drv_file++;
3655                 }
3656                 else if (STps->eof == ST_EOD_1) {
3657                         STps->eof = ST_EOD_2;
3658                         if (STps->drv_block > 0 && STps->drv_file >= 0)
3659                                 STps->drv_file++;
3660                         STps->drv_block = 0;
3661                 }
3662                 else if (STps->eof == ST_EOD_2)
3663                         STps->eof = ST_EOD;
3664         }
3665         else if (STps->eof == ST_FM)
3666                 STps->eof = ST_NOEOF;
3667
3668         retval = total;
3669
3670 out:
3671         if (SRpnt != NULL) scsi_release_request(SRpnt);
3672
3673         up(&STp->lock);
3674
3675         return retval;
3676 }
3677
3678
3679 /* Set the driver options */
3680 static void osst_log_options(OS_Scsi_Tape *STp, ST_mode *STm, char *name)
3681 {
3682   printk(KERN_INFO
3683 "%s:I: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n",
3684          name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes,
3685          STm->do_read_ahead);
3686   printk(KERN_INFO
3687 "%s:I:    can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n",
3688          name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock);
3689   printk(KERN_INFO
3690 "%s:I:    defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n",
3691          name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions,
3692          STp->scsi2_logical);
3693   printk(KERN_INFO
3694 "%s:I:    sysv: %d\n", name, STm->sysv);
3695 #if DEBUG
3696   printk(KERN_INFO
3697          "%s:D:    debugging: %d\n",
3698          name, debugging);
3699 #endif
3700 }
3701
3702
3703 static int osst_set_options(OS_Scsi_Tape *STp, long options)
3704 {
3705         int       value;
3706         long      code;
3707         ST_mode * STm;
3708         char    * name = tape_name(STp);
3709
3710         STm = &(STp->modes[STp->current_mode]);
3711         if (!STm->defined) {
3712                 memcpy(STm, &(STp->modes[0]), sizeof(ST_mode));
3713                 modes_defined = TRUE;
3714 #if DEBUG
3715                 if (debugging)
3716                         printk(OSST_DEB_MSG "%s:D: Initialized mode %d definition from mode 0\n",
3717                                              name, STp->current_mode);
3718 #endif
3719         }
3720
3721         code = options & MT_ST_OPTIONS;
3722         if (code == MT_ST_BOOLEANS) {
3723                 STm->do_buffer_writes = (options & MT_ST_BUFFER_WRITES) != 0;
3724                 STm->do_async_writes  = (options & MT_ST_ASYNC_WRITES) != 0;
3725                 STm->defaults_for_writes = (options & MT_ST_DEF_WRITES) != 0;
3726                 STm->do_read_ahead    = (options & MT_ST_READ_AHEAD) != 0;
3727                 STp->two_fm           = (options & MT_ST_TWO_FM) != 0;
3728                 STp->fast_mteom       = (options & MT_ST_FAST_MTEOM) != 0;
3729                 STp->do_auto_lock     = (options & MT_ST_AUTO_LOCK) != 0;
3730                 STp->can_bsr          = (options & MT_ST_CAN_BSR) != 0;
3731                 STp->omit_blklims     = (options & MT_ST_NO_BLKLIMS) != 0;
3732                 if ((STp->device)->scsi_level >= SCSI_2)
3733                         STp->can_partitions = (options & MT_ST_CAN_PARTITIONS) != 0;
3734                 STp->scsi2_logical    = (options & MT_ST_SCSI2LOGICAL) != 0;
3735                 STm->sysv             = (options & MT_ST_SYSV) != 0;
3736 #if DEBUG
3737                 debugging = (options & MT_ST_DEBUGGING) != 0;
3738 #endif
3739                 osst_log_options(STp, STm, name);
3740         }
3741         else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) {
3742                 value = (code == MT_ST_SETBOOLEANS);
3743                 if ((options & MT_ST_BUFFER_WRITES) != 0)
3744                         STm->do_buffer_writes = value;
3745                 if ((options & MT_ST_ASYNC_WRITES) != 0)
3746                         STm->do_async_writes = value;
3747                 if ((options & MT_ST_DEF_WRITES) != 0)
3748                         STm->defaults_for_writes = value;
3749                 if ((options & MT_ST_READ_AHEAD) != 0)
3750                         STm->do_read_ahead = value;
3751                 if ((options & MT_ST_TWO_FM) != 0)
3752                         STp->two_fm = value;
3753                 if ((options & MT_ST_FAST_MTEOM) != 0)
3754                         STp->fast_mteom = value;
3755                 if ((options & MT_ST_AUTO_LOCK) != 0)
3756                         STp->do_auto_lock = value;
3757                 if ((options & MT_ST_CAN_BSR) != 0)
3758                         STp->can_bsr = value;
3759                 if ((options & MT_ST_NO_BLKLIMS) != 0)
3760                         STp->omit_blklims = value;
3761                 if ((STp->device)->scsi_level >= SCSI_2 &&
3762                     (options & MT_ST_CAN_PARTITIONS) != 0)
3763                         STp->can_partitions = value;
3764                 if ((options & MT_ST_SCSI2LOGICAL) != 0)
3765                         STp->scsi2_logical = value;
3766                 if ((options & MT_ST_SYSV) != 0)
3767                         STm->sysv = value;
3768 #if DEBUG
3769                 if ((options & MT_ST_DEBUGGING) != 0)
3770                         debugging = value;
3771 #endif
3772                 osst_log_options(STp, STm, name);
3773         }
3774         else if (code == MT_ST_WRITE_THRESHOLD) {
3775                 value = (options & ~MT_ST_OPTIONS) * ST_KILOBYTE;
3776                 if (value < 1 || value > osst_buffer_size) {
3777                         printk(KERN_WARNING "%s:W: Write threshold %d too small or too large.\n",
3778                                              name, value);
3779                         return (-EIO);
3780                 }
3781                 STp->write_threshold = value;
3782                 printk(KERN_INFO "%s:I: Write threshold set to %d bytes.\n",
3783                                   name, value);
3784         }
3785         else if (code == MT_ST_DEF_BLKSIZE) {
3786                 value = (options & ~MT_ST_OPTIONS);
3787                 if (value == ~MT_ST_OPTIONS) {
3788                         STm->default_blksize = (-1);
3789                         printk(KERN_INFO "%s:I: Default block size disabled.\n", name);
3790                 }
3791                 else {
3792                         if (value < 512 || value > OS_DATA_SIZE || OS_DATA_SIZE % value) {
3793                                 printk(KERN_WARNING "%s:W: Default block size cannot be set to %d.\n",
3794                                                          name, value);
3795                                 return (-EINVAL);
3796                         }
3797                         STm->default_blksize = value;
3798                         printk(KERN_INFO "%s:I: Default block size set to %d bytes.\n",
3799                                           name, STm->default_blksize);
3800                 }
3801         }
3802         else if (code == MT_ST_TIMEOUTS) {
3803                 value = (options & ~MT_ST_OPTIONS);
3804                 if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) {
3805                         STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ;
3806                         printk(KERN_INFO "%s:I: Long timeout set to %d seconds.\n", name,
3807                                              (value & ~MT_ST_SET_LONG_TIMEOUT));
3808                 }
3809                 else {
3810                         STp->timeout = value * HZ;
3811                         printk(KERN_INFO "%s:I: Normal timeout set to %d seconds.\n", name, value);
3812                 }
3813         }
3814         else if (code == MT_ST_DEF_OPTIONS) {
3815                 code = (options & ~MT_ST_CLEAR_DEFAULT);
3816                 value = (options & MT_ST_CLEAR_DEFAULT);
3817                 if (code == MT_ST_DEF_DENSITY) {
3818                         if (value == MT_ST_CLEAR_DEFAULT) {
3819                                 STm->default_density = (-1);
3820                                 printk(KERN_INFO "%s:I: Density default disabled.\n", name);
3821                         }
3822                         else {
3823                                 STm->default_density = value & 0xff;
3824                                 printk(KERN_INFO "%s:I: Density default set to %x\n",
3825                                                   name, STm->default_density);
3826                         }
3827                 }
3828                 else if (code == MT_ST_DEF_DRVBUFFER) {
3829                         if (value == MT_ST_CLEAR_DEFAULT) {
3830                                 STp->default_drvbuffer = 0xff;
3831                                 printk(KERN_INFO "%s:I: Drive buffer default disabled.\n", name);
3832                         }
3833                         else {
3834                                 STp->default_drvbuffer = value & 7;
3835                                 printk(KERN_INFO "%s:I: Drive buffer default set to %x\n",
3836                                                   name, STp->default_drvbuffer);
3837                         }
3838                 }
3839                 else if (code == MT_ST_DEF_COMPRESSION) {
3840                         if (value == MT_ST_CLEAR_DEFAULT) {
3841                                 STm->default_compression = ST_DONT_TOUCH;
3842                                 printk(KERN_INFO "%s:I: Compression default disabled.\n", name);
3843                         }
3844                         else {
3845                                 STm->default_compression = (value & 1 ? ST_YES : ST_NO);
3846                                 printk(KERN_INFO "%s:I: Compression default set to %x\n",
3847                                                   name, (value & 1));
3848                         }
3849                 }
3850         }
3851         else
3852                 return (-EIO);
3853
3854         return 0;
3855 }
3856
3857
3858 /* Internal ioctl function */
3859 static int osst_int_ioctl(OS_Scsi_Tape * STp, Scsi_Request ** aSRpnt, unsigned int cmd_in, unsigned long arg)
3860 {
3861         int            timeout;
3862         long           ltmp;
3863         int            i, ioctl_result;
3864         int            chg_eof = TRUE;
3865         unsigned char  cmd[MAX_COMMAND_SIZE];
3866         Scsi_Request * SRpnt = * aSRpnt;
3867         ST_partstat  * STps;
3868         int            fileno, blkno, at_sm, frame_seq_numbr, logical_blk_num;
3869         int            datalen = 0, direction = SCSI_DATA_NONE;
3870         char         * name = tape_name(STp);
3871
3872         if (STp->ready != ST_READY && cmd_in != MTLOAD) {
3873                 if (STp->ready == ST_NO_TAPE)
3874                         return (-ENOMEDIUM);
3875                 else
3876                         return (-EIO);
3877         }
3878         timeout = STp->long_timeout;
3879         STps = &(STp->ps[STp->partition]);
3880         fileno = STps->drv_file;
3881         blkno = STps->drv_block;
3882         at_sm = STps->at_sm;
3883         frame_seq_numbr = STp->frame_seq_number;
3884         logical_blk_num = STp->logical_blk_num;
3885
3886         memset(cmd, 0, MAX_COMMAND_SIZE);
3887         switch (cmd_in) {
3888          case MTFSFM:
3889                 chg_eof = FALSE; /* Changed from the FSF after this */
3890          case MTFSF:
3891                 if (STp->raw)
3892                    return (-EIO);
3893                 if (STp->linux_media)
3894                    ioctl_result = osst_space_over_filemarks_forward_fast(STp, &SRpnt, cmd_in, arg);
3895                 else
3896                    ioctl_result = osst_space_over_filemarks_forward_slow(STp, &SRpnt, cmd_in, arg);
3897                 if (fileno >= 0)
3898                    fileno += arg;
3899                 blkno = 0;
3900                 at_sm &= (arg == 0);
3901                 goto os_bypass;
3902
3903          case MTBSF:
3904                 chg_eof = FALSE; /* Changed from the FSF after this */
3905          case MTBSFM:
3906                 if (STp->raw)
3907                    return (-EIO);
3908                 ioctl_result = osst_space_over_filemarks_backward(STp, &SRpnt, cmd_in, arg);
3909                 if (fileno >= 0)
3910                    fileno -= arg;
3911                 blkno = (-1);  /* We can't know the block number */
3912                 at_sm &= (arg == 0);
3913                 goto os_bypass;
3914
3915          case MTFSR:
3916          case MTBSR:
3917 #if DEBUG
3918                 if (debugging)
3919                    printk(OSST_DEB_MSG "%s:D: Skipping %lu blocks %s from logical block %d\n",
3920                                 name, arg, cmd_in==MTFSR?"forward":"backward", logical_blk_num);
3921 #endif
3922                 if (cmd_in == MTFSR) {
3923                    logical_blk_num += arg;
3924                    if (blkno >= 0) blkno += arg;
3925                 }
3926                 else {
3927                    logical_blk_num -= arg;
3928                    if (blkno >= 0) blkno -= arg;
3929                 }
3930                 ioctl_result = osst_seek_logical_blk(STp, &SRpnt, logical_blk_num);
3931                 fileno = STps->drv_file;
3932                 blkno  = STps->drv_block;
3933                 at_sm &= (arg == 0);
3934                 goto os_bypass;
3935
3936          case MTFSS:
3937                 cmd[0] = SPACE;
3938                 cmd[1] = 0x04; /* Space Setmarks */   /* FIXME -- OS can't do this? */
3939                 cmd[2] = (arg >> 16);
3940                 cmd[3] = (arg >> 8);
3941                 cmd[4] = arg;
3942 #if DEBUG
3943                 if (debugging)
3944                         printk(OSST_DEB_MSG "%s:D: Spacing tape forward %d setmarks.\n", name,
3945                 cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
3946 #endif
3947                 if (arg != 0) {
3948                         blkno = fileno = (-1);
3949                         at_sm = 1;
3950                 }
3951                 break;
3952          case MTBSS:
3953                 cmd[0] = SPACE;
3954                 cmd[1] = 0x04; /* Space Setmarks */   /* FIXME -- OS can't do this? */
3955                 ltmp = (-arg);
3956                 cmd[2] = (ltmp >> 16);
3957                 cmd[3] = (ltmp >> 8);
3958                 cmd[4] = ltmp;
3959 #if DEBUG
3960                 if (debugging) {
3961                         if (cmd[2] & 0x80)
3962                            ltmp = 0xff000000;
3963                         ltmp = ltmp | (cmd[2] << 16) | (cmd[3] << 8) | cmd[4];
3964                         printk(OSST_DEB_MSG "%s:D: Spacing tape backward %ld setmarks.\n",
3965                                                 name, (-ltmp));
3966                  }
3967 #endif
3968                  if (arg != 0) {
3969                         blkno = fileno = (-1);
3970                         at_sm = 1;
3971                  }
3972                  break;
3973          case MTWEOF:
3974                  if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
3975                         STp->write_type = OS_WRITE_DATA;
3976                         ioctl_result = osst_flush_write_buffer(STp, &SRpnt);
3977                  } else
3978                         ioctl_result = 0;
3979 #if DEBUG
3980                  if (debugging) 
3981                            printk(OSST_DEB_MSG "%s:D: Writing %ld filemark(s).\n", name, arg);
3982 #endif
3983                  for (i=0; i<arg; i++)
3984                         ioctl_result |= osst_write_filemark(STp, &SRpnt);
3985                  if (fileno >= 0) fileno += arg;
3986                  if (blkno  >= 0) blkno   = 0;
3987                  goto os_bypass;
3988
3989          case MTWSM:
3990                  if (STp->write_prot)
3991                         return (-EACCES);
3992                  if (!STp->raw)
3993                         return 0;
3994                  cmd[0] = WRITE_FILEMARKS;   /* FIXME -- need OS version */
3995                  if (cmd_in == MTWSM)
3996                          cmd[1] = 2;
3997                  cmd[2] = (arg >> 16);
3998                  cmd[3] = (arg >> 8);
3999                  cmd[4] = arg;
4000                  timeout = STp->timeout;
4001 #if DEBUG
4002                  if (debugging) 
4003                            printk(OSST_DEB_MSG "%s:D: Writing %d setmark(s).\n", name,
4004                                   cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
4005 #endif
4006                  if (fileno >= 0)
4007                         fileno += arg;
4008                  blkno = 0;
4009                  at_sm = (cmd_in == MTWSM);
4010                  break;
4011          case MTOFFL:
4012          case MTLOAD:
4013          case MTUNLOAD:
4014          case MTRETEN:
4015                  cmd[0] = START_STOP;
4016                  cmd[1] = 1;                    /* Don't wait for completion */
4017                  if (cmd_in == MTLOAD) {
4018                      if (STp->ready == ST_NO_TAPE)
4019                          cmd[4] = 4;            /* open tray */
4020                       else
4021                          cmd[4] = 1;            /* load */
4022                  }
4023                  if (cmd_in == MTRETEN)
4024                          cmd[4] = 3;            /* retension then mount */
4025                  if (cmd_in == MTOFFL)
4026                          cmd[4] = 4;            /* rewind then eject */
4027                  timeout = STp->timeout;
4028 #if DEBUG
4029                  if (debugging) {
4030                          switch (cmd_in) {
4031                                  case MTUNLOAD:
4032                                          printk(OSST_DEB_MSG "%s:D: Unloading tape.\n", name);
4033                                          break;
4034                                  case MTLOAD:
4035                                          printk(OSST_DEB_MSG "%s:D: Loading tape.\n", name);
4036                                          break;
4037                                  case MTRETEN:
4038                                          printk(OSST_DEB_MSG "%s:D: Retensioning tape.\n", name);
4039                                          break;
4040                                  case MTOFFL:
4041                                          printk(OSST_DEB_MSG "%s:D: Ejecting tape.\n", name);
4042                                          break;
4043                          }
4044                  }
4045 #endif
4046        fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4047                  break;
4048          case MTNOP:
4049 #if DEBUG
4050                  if (debugging)
4051                          printk(OSST_DEB_MSG "%s:D: No-op on tape.\n", name);
4052 #endif
4053                  return 0;  /* Should do something ? */
4054                  break;
4055          case MTEOM:
4056 #if DEBUG
4057                 if (debugging)
4058                    printk(OSST_DEB_MSG "%s:D: Spacing to end of recorded medium.\n", name);
4059 #endif
4060                 if ((osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0) ||
4061                             (osst_get_logical_frame(STp, &SRpnt, -1, 0)               < 0)) {
4062                    ioctl_result = -EIO;
4063                    goto os_bypass;
4064                 }
4065                 if (STp->buffer->aux->frame_type != OS_FRAME_TYPE_EOD) {
4066 #if DEBUG
4067                    printk(OSST_DEB_MSG "%s:D: No EOD frame found where expected.\n", name);
4068 #endif
4069                    ioctl_result = -EIO;
4070                    goto os_bypass;
4071                 }
4072                 ioctl_result = osst_set_frame_position(STp, &SRpnt, STp->eod_frame_ppos, 0);
4073                 fileno = STp->filemark_cnt;
4074                 blkno  = at_sm = 0;
4075                 goto os_bypass;
4076
4077          case MTERASE:
4078                 if (STp->write_prot)
4079                    return (-EACCES);
4080                 ioctl_result = osst_reset_header(STp, &SRpnt);
4081                 i = osst_write_eod(STp, &SRpnt);
4082                 if (i < ioctl_result) ioctl_result = i;
4083                 i = osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos);
4084                 if (i < ioctl_result) ioctl_result = i;
4085                 fileno = blkno = at_sm = 0 ;
4086                 goto os_bypass;
4087
4088          case MTREW:
4089                 cmd[0] = REZERO_UNIT; /* rewind */
4090                 cmd[1] = 1;
4091 #if DEBUG
4092                 if (debugging)
4093                    printk(OSST_DEB_MSG "%s:D: Rewinding tape, Immed=%d.\n", name, cmd[1]);
4094 #endif
4095                 fileno = blkno = at_sm = frame_seq_numbr = logical_blk_num = 0 ;
4096                 break;
4097
4098          case MTSETBLK:           /* Set block length */
4099                  if ((STps->drv_block == 0 )                      &&
4100                      !STp->dirty                                  &&
4101                      ((STp->buffer)->buffer_bytes == 0)           &&
4102                      ((arg & MT_ST_BLKSIZE_MASK) >= 512 )         && 
4103                      ((arg & MT_ST_BLKSIZE_MASK) <= OS_DATA_SIZE) &&
4104                      !(OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))  ) {
4105                          /*
4106                           * Only allowed to change the block size if you opened the
4107                           * device at the beginning of a file before writing anything.
4108                           * Note, that when reading, changing block_size is futile,
4109                           * as the size used when writing overrides it.
4110                           */
4111                          STp->block_size = (arg & MT_ST_BLKSIZE_MASK);
4112                          printk(KERN_INFO "%s:I: Block size set to %d bytes.\n",
4113                                            name, STp->block_size);
4114                          return 0;
4115                  }
4116          case MTSETDENSITY:       /* Set tape density */
4117          case MTSETDRVBUFFER:     /* Set drive buffering */
4118          case SET_DENS_AND_BLK:   /* Set density and block size */
4119                  chg_eof = FALSE;
4120                  if (STp->dirty || (STp->buffer)->buffer_bytes != 0)
4121                          return (-EIO);       /* Not allowed if data in buffer */
4122                  if ((cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) &&
4123                      (arg & MT_ST_BLKSIZE_MASK) != 0                    &&
4124                      (arg & MT_ST_BLKSIZE_MASK) != STp->block_size       ) {
4125                          printk(KERN_WARNING "%s:W: Illegal to set block size to %d%s.\n",
4126                                                 name, (int)(arg & MT_ST_BLKSIZE_MASK),
4127                                                 (OS_DATA_SIZE % (arg & MT_ST_BLKSIZE_MASK))?"":" now");
4128                          return (-EINVAL);
4129                  }
4130                  return 0;  /* FIXME silently ignore if block size didn't change */
4131
4132          default:
4133                 return (-ENOSYS);
4134         }
4135
4136         SRpnt = osst_do_scsi(SRpnt, STp, cmd, datalen, direction, timeout, MAX_RETRIES, TRUE);
4137
4138         ioctl_result = (STp->buffer)->syscall_result;
4139
4140         if (!SRpnt) {
4141 #if DEBUG
4142                 printk(OSST_DEB_MSG "%s:D: Couldn't exec scsi cmd for IOCTL\n", name);
4143 #endif
4144                 return ioctl_result;
4145         }
4146
4147         if (!ioctl_result) {  /* SCSI command successful */
4148                 STp->frame_seq_number = frame_seq_numbr;
4149                 STp->logical_blk_num  = logical_blk_num;
4150         }
4151
4152 os_bypass:
4153 #if DEBUG
4154         if (debugging)
4155                 printk(OSST_DEB_MSG "%s:D: IOCTL (%d) Result=%d\n", name, cmd_in, ioctl_result);
4156 #endif
4157
4158         if (!ioctl_result) {                            /* success */
4159
4160                 if (cmd_in == MTFSFM) {
4161                          fileno--;
4162                          blkno--;
4163                 }
4164                 if (cmd_in == MTBSFM) {
4165                          fileno++;
4166                          blkno++;
4167                 }
4168                 STps->drv_block = blkno;
4169                 STps->drv_file = fileno;
4170                 STps->at_sm = at_sm;
4171
4172                 if (cmd_in == MTEOM)
4173                         STps->eof = ST_EOD;
4174                 else if ((cmd_in == MTFSFM || cmd_in == MTBSF) && STps->eof == ST_FM_HIT) {
4175                         ioctl_result = osst_seek_logical_blk(STp, &SRpnt, STp->logical_blk_num-1);
4176                         STps->drv_block++;
4177                         STp->logical_blk_num++;
4178                         STp->frame_seq_number++;
4179                         STp->frame_in_buffer = 0;
4180                         STp->buffer->read_pointer = 0;
4181                 }
4182                 else if (cmd_in == MTFSF)
4183                         STps->eof = (STp->first_frame_position >= STp->eod_frame_ppos)?ST_EOD:ST_FM;
4184                 else if (chg_eof)
4185                         STps->eof = ST_NOEOF;
4186
4187                 if (cmd_in == MTOFFL || cmd_in == MTUNLOAD)
4188                         STp->rew_at_close = 0;
4189                 else if (cmd_in == MTLOAD) {
4190                         for (i=0; i < ST_NBR_PARTITIONS; i++) {
4191                             STp->ps[i].rw = ST_IDLE;
4192                             STp->ps[i].last_block_valid = FALSE;/* FIXME - where else is this field maintained? */
4193                         }
4194                         STp->partition = 0;
4195                 }
4196
4197                 if (cmd_in == MTREW) {
4198                         ioctl_result = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos); 
4199                         if (ioctl_result > 0)
4200                                 ioctl_result = 0;
4201                 }
4202
4203         } else if (cmd_in == MTBSF || cmd_in == MTBSFM ) {
4204                 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos) < 0)
4205                         STps->drv_file = STps->drv_block = -1;
4206                 else
4207                         STps->drv_file = STps->drv_block = 0;
4208                 STps->eof = ST_NOEOF;
4209         } else if (cmd_in == MTFSF || cmd_in == MTFSFM) {
4210                 if (osst_position_tape_and_confirm(STp, &SRpnt, STp->eod_frame_ppos) < 0)
4211                         STps->drv_file = STps->drv_block = -1;
4212                 else {
4213                         STps->drv_file  = STp->filemark_cnt;
4214                         STps->drv_block = 0;
4215                 }
4216                 STps->eof = ST_EOD;
4217         } else if (cmd_in == MTBSR || cmd_in == MTFSR || cmd_in == MTWEOF || cmd_in == MTEOM) {
4218                 STps->drv_file = STps->drv_block = (-1);
4219                 STps->eof = ST_NOEOF;
4220                 STp->header_ok = 0;
4221         } else if (cmd_in == MTERASE) {
4222                 STp->header_ok = 0;
4223         } else if (SRpnt) {  /* SCSI command was not completely successful. */
4224                 if (SRpnt->sr_sense_buffer[2] & 0x40) {
4225                         STps->eof = ST_EOM_OK;
4226                         STps->drv_block = 0;
4227                 }
4228                 if (chg_eof)
4229                         STps->eof = ST_NOEOF;
4230
4231                 if ((SRpnt->sr_sense_buffer[2] & 0x0f) == BLANK_CHECK)
4232                         STps->eof = ST_EOD;
4233
4234                 if (cmd_in == MTLOAD && osst_wait_for_medium(STp, &SRpnt, 60))
4235                         ioctl_result = osst_wait_ready(STp, &SRpnt, 5 * 60, OSST_WAIT_POSITION_COMPLETE);
4236         }
4237         *aSRpnt = SRpnt;
4238
4239         return ioctl_result;
4240 }
4241
4242
4243 /* Open the device */
4244 static int os_scsi_tape_open(struct inode * inode, struct file * filp)
4245 {
4246         unsigned short flags;
4247         int            i, b_size, new_session = FALSE, retval = 0;
4248         unsigned char  cmd[MAX_COMMAND_SIZE];
4249         Scsi_Request * SRpnt = NULL;
4250         OS_Scsi_Tape * STp;
4251         ST_mode      * STm;
4252         ST_partstat  * STps;
4253         char         * name;
4254         int            dev  = TAPE_NR(inode);
4255         int            mode = TAPE_MODE(inode);
4256
4257         write_lock(&os_scsi_tapes_lock);
4258         if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
4259             (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
4260                 write_unlock(&os_scsi_tapes_lock);
4261                 return (-ENXIO);
4262         }
4263
4264         name = tape_name(STp);
4265
4266         if (STp->in_use) {
4267                 write_unlock(&os_scsi_tapes_lock);
4268 #if DEBUG
4269                 printk(OSST_DEB_MSG "%s:D: Device already in use.\n", name);
4270 #endif
4271                 return (-EBUSY);
4272         }
4273         if (scsi_device_get(STp->device)) {
4274                 write_unlock(&os_scsi_tapes_lock);
4275 #if DEBUG
4276                 printk(OSST_DEB_MSG "%s:D: Failed scsi_device_get.\n", name);
4277 #endif
4278                 return (-ENXIO);
4279         }
4280         filp->private_data = STp;
4281         STp->in_use = 1;
4282         write_unlock(&os_scsi_tapes_lock);
4283         STp->rew_at_close = TAPE_REWIND(inode);
4284
4285         if( !scsi_block_when_processing_errors(STp->device) ) {
4286                 return -ENXIO;
4287         }
4288
4289         if (mode != STp->current_mode) {
4290 #if DEBUG
4291                 if (debugging)
4292                         printk(OSST_DEB_MSG "%s:D: Mode change from %d to %d.\n",
4293                                                name, STp->current_mode, mode);
4294 #endif
4295                 new_session = TRUE;
4296                 STp->current_mode = mode;
4297         }
4298         STm = &(STp->modes[STp->current_mode]);
4299
4300         flags = filp->f_flags;
4301         STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
4302
4303         STp->raw = TAPE_IS_RAW(inode);
4304         if (STp->raw)
4305                 STp->header_ok = 0;
4306
4307         /* Allocate data segments for this device's tape buffer */
4308         if (!enlarge_buffer(STp->buffer, STp->restr_dma)) {
4309                 printk(KERN_ERR "%s:E: Unable to allocate memory segments for tape buffer.\n", name);
4310                 retval = (-EOVERFLOW);
4311                 goto err_out;
4312         }
4313         if (STp->buffer->buffer_size >= OS_FRAME_SIZE) {
4314                 for (i = 0, b_size = 0; 
4315                      (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE); 
4316                      b_size += STp->buffer->sg[i++].length);
4317                 STp->buffer->aux = (os_aux_t *) (page_address(STp->buffer->sg[i].page) + OS_DATA_SIZE - b_size);
4318 #if DEBUG
4319                 printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name,
4320                         STp->buffer->b_data, page_address(STp->buffer->sg[0].page));
4321                 printk(OSST_DEB_MSG "%s:D: AUX points to %p in segment %d at %p\n", name,
4322                          STp->buffer->aux, i, page_address(STp->buffer->sg[i].page));
4323 #endif
4324         } else {
4325                 STp->buffer->aux = NULL; /* this had better never happen! */
4326                 printk(KERN_NOTICE "%s:A: Framesize %d too large for buffer.\n", name, OS_FRAME_SIZE);
4327                 retval = (-EIO);
4328                 goto err_out;
4329         }
4330         STp->buffer->writing = 0;
4331         STp->buffer->syscall_result = 0;
4332         STp->dirty = 0;
4333         for (i=0; i < ST_NBR_PARTITIONS; i++) {
4334                 STps = &(STp->ps[i]);
4335                 STps->rw = ST_IDLE;
4336         }
4337         STp->ready = ST_READY;
4338 #if DEBUG
4339         STp->nbr_waits = STp->nbr_finished = 0;
4340 #endif
4341
4342         memset (cmd, 0, MAX_COMMAND_SIZE);
4343         cmd[0] = TEST_UNIT_READY;
4344
4345         SRpnt = osst_do_scsi(NULL, STp, cmd, 0, SCSI_DATA_NONE, STp->timeout, MAX_READY_RETRIES, TRUE);
4346         if (!SRpnt) {
4347                 retval = (STp->buffer)->syscall_result;
4348                 goto err_out;
4349         }
4350         if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70      &&
4351             (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY &&
4352              SRpnt->sr_sense_buffer[12]        == 4         ) {
4353 #if DEBUG
4354                 printk(OSST_DEB_MSG "%s:D: Unit not ready, cause %x\n", name, SRpnt->sr_sense_buffer[13]);
4355 #endif
4356                 if (filp->f_flags & O_NONBLOCK) {
4357                         retval = -EAGAIN;
4358                         goto err_out;
4359                 }
4360                 if (SRpnt->sr_sense_buffer[13] == 2) {  /* initialize command required (LOAD) */
4361                         memset (cmd, 0, MAX_COMMAND_SIZE);
4362                         cmd[0] = START_STOP;
4363                         cmd[1] = 1;
4364                         cmd[4] = 1;
4365                         SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
4366                                              STp->timeout, MAX_READY_RETRIES, TRUE);
4367                 }
4368                 osst_wait_ready(STp, &SRpnt, (SRpnt->sr_sense_buffer[13]==1?15:3) * 60, 0);
4369         }
4370         if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
4371             (SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) { /* New media? */
4372 #if DEBUG
4373                 printk(OSST_DEB_MSG "%s:D: Unit wants attention\n", name);
4374 #endif
4375                 STp->header_ok = 0;
4376
4377                 for (i=0; i < 10; i++) {
4378
4379                         memset (cmd, 0, MAX_COMMAND_SIZE);
4380                         cmd[0] = TEST_UNIT_READY;
4381
4382                         SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
4383                                              STp->timeout, MAX_READY_RETRIES, TRUE);
4384                         if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
4385                             (SRpnt->sr_sense_buffer[2] & 0x0f) != UNIT_ATTENTION)
4386                                 break;
4387                 }
4388
4389                 STp->pos_unknown = 0;
4390                 STp->partition = STp->new_partition = 0;
4391                 if (STp->can_partitions)
4392                         STp->nbr_partitions = 1;  /* This guess will be updated later if necessary */
4393                 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4394                         STps = &(STp->ps[i]);
4395                         STps->rw = ST_IDLE;             /* FIXME - seems to be redundant... */
4396                         STps->eof = ST_NOEOF;
4397                         STps->at_sm = 0;
4398                         STps->last_block_valid = FALSE;
4399                         STps->drv_block = 0;
4400                         STps->drv_file = 0 ;
4401                 }
4402                 new_session = TRUE;
4403                 STp->recover_count = 0;
4404         }
4405         /*
4406          * if we have valid headers from before, and the drive/tape seem untouched,
4407          * open without reconfiguring and re-reading the headers
4408          */
4409         if (!STp->buffer->syscall_result && STp->header_ok &&
4410             !SRpnt->sr_result && SRpnt->sr_sense_buffer[0] == 0) {
4411
4412                 memset(cmd, 0, MAX_COMMAND_SIZE);
4413                 cmd[0] = MODE_SENSE;
4414                 cmd[1] = 8;
4415                 cmd[2] = VENDOR_IDENT_PAGE;
4416                 cmd[4] = VENDOR_IDENT_PAGE_LENGTH + MODE_HEADER_LENGTH;
4417
4418                 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_READ, STp->timeout, 0, TRUE);
4419
4420                 if (STp->buffer->syscall_result                     ||
4421                     STp->buffer->b_data[MODE_HEADER_LENGTH + 2] != 'L' ||
4422                     STp->buffer->b_data[MODE_HEADER_LENGTH + 3] != 'I' ||
4423                     STp->buffer->b_data[MODE_HEADER_LENGTH + 4] != 'N' ||
4424                     STp->buffer->b_data[MODE_HEADER_LENGTH + 5] != '4'  ) {
4425 #if DEBUG
4426                         printk(OSST_DEB_MSG "%s:D: Signature was changed to %c%c%c%c\n", name,
4427                           STp->buffer->b_data[MODE_HEADER_LENGTH + 2],
4428                           STp->buffer->b_data[MODE_HEADER_LENGTH + 3],
4429                           STp->buffer->b_data[MODE_HEADER_LENGTH + 4],
4430                           STp->buffer->b_data[MODE_HEADER_LENGTH + 5]);
4431 #endif
4432                         STp->header_ok = 0;
4433                 }
4434                 i = STp->first_frame_position;
4435                 if (STp->header_ok && i == osst_get_frame_position(STp, &SRpnt)) {
4436                         if (STp->door_locked == ST_UNLOCKED) {
4437                                 if (do_door_lock(STp, 1))
4438                                         printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4439                                 else
4440                                         STp->door_locked = ST_LOCKED_AUTO;
4441                         }
4442                         if (!STp->frame_in_buffer) {
4443                                 STp->block_size = (STm->default_blksize > 0) ?
4444                                                         STm->default_blksize : OS_DATA_SIZE;
4445                                 STp->buffer->buffer_bytes = STp->buffer->read_pointer = 0;
4446                         }
4447                         STp->buffer->buffer_blocks = OS_DATA_SIZE / STp->block_size;
4448                         STp->fast_open = TRUE;
4449                         scsi_release_request(SRpnt);
4450                         return 0;
4451                 }
4452 #if DEBUG
4453                 if (i != STp->first_frame_position)
4454                         printk(OSST_DEB_MSG "%s:D: Tape position changed from %d to %d\n",
4455                                                 name, i, STp->first_frame_position);
4456 #endif
4457                 STp->header_ok = 0;
4458         }
4459         STp->fast_open = FALSE;
4460
4461         if ((STp->buffer)->syscall_result != 0 &&   /* in all error conditions except no medium */ 
4462             (SRpnt->sr_sense_buffer[2] != 2 || SRpnt->sr_sense_buffer[12] != 0x3A) ) {
4463
4464                 memset(cmd, 0, MAX_COMMAND_SIZE);
4465                 cmd[0] = MODE_SELECT;
4466                 cmd[1] = 0x10;
4467                 cmd[4] = 4 + MODE_HEADER_LENGTH;
4468
4469                 (STp->buffer)->b_data[0] = cmd[4] - 1;
4470                 (STp->buffer)->b_data[1] = 0;                   /* Medium Type - ignoring */
4471                 (STp->buffer)->b_data[2] = 0;                   /* Reserved */
4472                 (STp->buffer)->b_data[3] = 0;                   /* Block Descriptor Length */
4473                 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 0] = 0x3f;
4474                 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 1] = 1;
4475                 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 2] = 2;
4476                 (STp->buffer)->b_data[MODE_HEADER_LENGTH + 3] = 3;
4477
4478 #if DEBUG
4479                 printk(OSST_DEB_MSG "%s:D: Applying soft reset\n", name);
4480 #endif
4481                 SRpnt = osst_do_scsi(SRpnt, STp, cmd, cmd[4], SCSI_DATA_WRITE, STp->timeout, 0, TRUE);
4482
4483                 STp->header_ok = 0;
4484
4485                 for (i=0; i < 10; i++) {
4486
4487                         memset (cmd, 0, MAX_COMMAND_SIZE);
4488                         cmd[0] = TEST_UNIT_READY;
4489
4490                         SRpnt = osst_do_scsi(SRpnt, STp, cmd, 0, SCSI_DATA_NONE,
4491                                              STp->timeout, MAX_READY_RETRIES, TRUE);
4492                         if ((SRpnt->sr_sense_buffer[0] & 0x70) != 0x70 ||
4493                             (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY)
4494                         break;
4495
4496                         if ((SRpnt->sr_sense_buffer[2] & 0x0f) == UNIT_ATTENTION) {
4497                                 STp->pos_unknown = 0;
4498                                 STp->partition = STp->new_partition = 0;
4499                                 if (STp->can_partitions)
4500                                         STp->nbr_partitions = 1;  /* This guess will be updated later if necessary */
4501                                 for (i=0; i < ST_NBR_PARTITIONS; i++) {
4502                                         STps = &(STp->ps[i]);
4503                                         STps->rw = ST_IDLE;
4504                                         STps->eof = ST_NOEOF;
4505                                         STps->at_sm = 0;
4506                                         STps->last_block_valid = FALSE;
4507                                         STps->drv_block = 0;
4508                                         STps->drv_file = 0 ;
4509                                 }
4510                                 new_session = TRUE;
4511                         }
4512                 }
4513         }
4514
4515         if (osst_wait_ready(STp, &SRpnt, 15 * 60, 0))           /* FIXME - not allowed with NOBLOCK */
4516                  printk(KERN_INFO "%s:I: Device did not become Ready in open\n", name);
4517
4518         if ((STp->buffer)->syscall_result != 0) {
4519                 if ((STp->device)->scsi_level >= SCSI_2 &&
4520                     (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
4521                     (SRpnt->sr_sense_buffer[2] & 0x0f) == NOT_READY &&
4522                      SRpnt->sr_sense_buffer[12] == 0x3a) { /* Check ASC */
4523                         STp->ready = ST_NO_TAPE;
4524                 } else
4525                         STp->ready = ST_NOT_READY;
4526                 scsi_release_request(SRpnt);
4527                 SRpnt = NULL;
4528                 STp->density = 0;       /* Clear the erroneous "residue" */
4529                 STp->write_prot = 0;
4530                 STp->block_size = 0;
4531                 STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
4532                 STp->partition = STp->new_partition = 0;
4533                 STp->door_locked = ST_UNLOCKED;
4534                 return 0;
4535         }
4536
4537         osst_configure_onstream(STp, &SRpnt);
4538
4539         STp->block_size = STp->raw ? OS_FRAME_SIZE : (
4540                              (STm->default_blksize > 0) ? STm->default_blksize : OS_DATA_SIZE);
4541         STp->buffer->buffer_blocks = STp->raw ? 1 : OS_DATA_SIZE / STp->block_size;
4542         STp->buffer->buffer_bytes  =
4543         STp->buffer->read_pointer  =
4544         STp->frame_in_buffer       = 0;
4545
4546 #if DEBUG
4547         if (debugging)
4548                 printk(OSST_DEB_MSG "%s:D: Block size: %d, frame size: %d, buffer size: %d (%d blocks).\n",
4549                      name, STp->block_size, OS_FRAME_SIZE, (STp->buffer)->buffer_size,
4550                      (STp->buffer)->buffer_blocks);
4551 #endif
4552
4553         if (STp->drv_write_prot) {
4554                 STp->write_prot = 1;
4555 #if DEBUG
4556                 if (debugging)
4557                         printk(OSST_DEB_MSG "%s:D: Write protected\n", name);
4558 #endif
4559                 if ((flags & O_ACCMODE) == O_WRONLY || (flags & O_ACCMODE) == O_RDWR) {
4560                         retval = (-EROFS);
4561                         goto err_out;
4562                 }
4563         }
4564
4565         if (new_session) {  /* Change the drive parameters for the new mode */
4566 #if DEBUG
4567                 if (debugging)
4568         printk(OSST_DEB_MSG "%s:D: New Session\n", name);
4569 #endif
4570                 STp->density_changed = STp->blksize_changed = FALSE;
4571                 STp->compression_changed = FALSE;
4572         }
4573
4574         /*
4575          * properly position the tape and check the ADR headers
4576          */
4577         if (STp->door_locked == ST_UNLOCKED) {
4578                  if (do_door_lock(STp, 1))
4579                         printk(KERN_INFO "%s:I: Can't lock drive door\n", name);
4580                  else
4581                         STp->door_locked = ST_LOCKED_AUTO;
4582         }
4583
4584         osst_analyze_headers(STp, &SRpnt);
4585
4586         scsi_release_request(SRpnt);
4587         SRpnt = NULL;
4588
4589         return 0;
4590
4591 err_out:
4592         if (SRpnt != NULL)
4593                 scsi_release_request(SRpnt);
4594         normalize_buffer(STp->buffer);
4595         STp->header_ok = 0;
4596         STp->in_use = 0;
4597         scsi_device_put(STp->device);
4598
4599         return retval;
4600 }
4601
4602
4603 /* Flush the tape buffer before close */
4604 static int os_scsi_tape_flush(struct file * filp)
4605 {
4606         int            result = 0, result2;
4607         OS_Scsi_Tape * STp  = filp->private_data;
4608         ST_mode      * STm  = &(STp->modes[STp->current_mode]);
4609         ST_partstat  * STps = &(STp->ps[STp->partition]);
4610         Scsi_Request * SRpnt = NULL;
4611         char         * name = tape_name(STp);
4612
4613         if (file_count(filp) > 1)
4614                 return 0;
4615
4616         if ((STps->rw == ST_WRITING || STp->dirty) && !STp->pos_unknown) {
4617                 STp->write_type = OS_WRITE_DATA;
4618                 result = osst_flush_write_buffer(STp, &SRpnt);
4619                 if (result != 0 && result != (-ENOSPC))
4620                         goto out;
4621         }
4622         if ( STps->rw >= ST_WRITING && !STp->pos_unknown) {
4623
4624 #if DEBUG
4625                 if (debugging) {
4626                         printk(OSST_DEB_MSG "%s:D: File length %ld bytes.\n",
4627                                                name, (long)(filp->f_pos));
4628                         printk(OSST_DEB_MSG "%s:D: Async write waits %d, finished %d.\n",
4629                                                name, STp->nbr_waits, STp->nbr_finished);
4630                 }
4631 #endif
4632                 result = osst_write_trailer(STp, &SRpnt, !(STp->rew_at_close));
4633 #if DEBUG
4634                 if (debugging)
4635                         printk(OSST_DEB_MSG "%s:D: Buffer flushed, %d EOF(s) written\n",
4636                                                name, 1+STp->two_fm);
4637 #endif
4638         }
4639         else if (!STp->rew_at_close) {
4640                 STps = &(STp->ps[STp->partition]);
4641                 if (!STm->sysv || STps->rw != ST_READING) {
4642                         if (STp->can_bsr)
4643                                 result = osst_flush_buffer(STp, &SRpnt, 0); /* this is the default path */
4644                         else if (STps->eof == ST_FM_HIT) {
4645                                 result = cross_eof(STp, &SRpnt, FALSE);
4646                                         if (result) {
4647                                                 if (STps->drv_file >= 0)
4648                                                         STps->drv_file++;
4649                                                 STps->drv_block = 0;
4650                                                 STps->eof = ST_FM;
4651                                         }
4652                                         else
4653                                                 STps->eof = ST_NOEOF;
4654                         }
4655                 }
4656                 else if ((STps->eof == ST_NOEOF &&
4657                           !(result = cross_eof(STp, &SRpnt, TRUE))) ||
4658                          STps->eof == ST_FM_HIT) {
4659                         if (STps->drv_file >= 0)
4660                                 STps->drv_file++;
4661                         STps->drv_block = 0;
4662                         STps->eof = ST_FM;
4663                 }
4664         }
4665
4666 out:
4667         if (STp->rew_at_close) {
4668                 result2 = osst_position_tape_and_confirm(STp, &SRpnt, STp->first_data_ppos);
4669                 STps->drv_file = STps->drv_block = STp->frame_seq_number = STp->logical_blk_num = 0;
4670                 if (result == 0 && result2 < 0)
4671                         result = result2;
4672         }
4673         if (SRpnt) scsi_release_request(SRpnt);
4674
4675         if (STp->recover_count) {
4676                 printk(KERN_INFO "%s:I: %d recovered errors in", name, STp->recover_count);
4677                 if (STp->write_count)
4678                         printk(" %d frames written", STp->write_count);
4679                 if (STp->read_count)
4680                         printk(" %d frames read", STp->read_count);
4681                 printk("\n");
4682                 STp->recover_count = 0;
4683         }
4684         STp->write_count = 0;
4685         STp->read_count  = 0;
4686
4687         return result;
4688 }
4689
4690
4691 /* Close the device and release it */
4692 static int os_scsi_tape_close(struct inode * inode, struct file * filp)
4693 {
4694         int result = 0;
4695         OS_Scsi_Tape * STp = filp->private_data;
4696         Scsi_Request * SRpnt = NULL;
4697
4698         if (SRpnt) scsi_release_request(SRpnt);
4699
4700         if (STp->door_locked == ST_LOCKED_AUTO)
4701                 do_door_lock(STp, 0);
4702
4703         if (STp->raw)
4704                 STp->header_ok = 0;
4705         
4706         normalize_buffer(STp->buffer);
4707         write_lock(&os_scsi_tapes_lock);
4708         STp->in_use = 0;
4709         write_unlock(&os_scsi_tapes_lock);
4710
4711         scsi_device_put(STp->device);
4712
4713         return result;
4714 }
4715
4716
4717 /* The ioctl command */
4718 static int osst_ioctl(struct inode * inode,struct file * file,
4719          unsigned int cmd_in, unsigned long arg)
4720 {
4721         int            i, cmd_nr, cmd_type, retval = 0;
4722         unsigned int   blk;
4723         ST_mode      * STm;
4724         ST_partstat  * STps;
4725         Scsi_Request * SRpnt = NULL;
4726         OS_Scsi_Tape * STp   = file->private_data;
4727         char         * name  = tape_name(STp);
4728         void __user *p = (void __user *)arg;
4729
4730         if (down_interruptible(&STp->lock))
4731                 return -ERESTARTSYS;
4732
4733 #if DEBUG
4734         if (debugging && !STp->in_use) {
4735                 printk(OSST_DEB_MSG "%s:D: Incorrect device.\n", name);
4736                 retval = (-EIO);
4737                 goto out;
4738         }
4739 #endif
4740         STm = &(STp->modes[STp->current_mode]);
4741         STps = &(STp->ps[STp->partition]);
4742
4743         /*
4744          * If we are in the middle of error recovery, don't let anyone
4745          * else try and use this device.  Also, if error recovery fails, it
4746          * may try and take the device offline, in which case all further
4747          * access to the device is prohibited.
4748          */
4749         if( !scsi_block_when_processing_errors(STp->device) ) {
4750                 retval = (-ENXIO);
4751                 goto out;
4752         }
4753
4754         cmd_type = _IOC_TYPE(cmd_in);
4755         cmd_nr   = _IOC_NR(cmd_in);
4756 #if DEBUG
4757         printk(OSST_DEB_MSG "%s:D: Ioctl %d,%d in %s mode\n", name,
4758                             cmd_type, cmd_nr, STp->raw?"raw":"normal");
4759 #endif
4760         if (cmd_type == _IOC_TYPE(MTIOCTOP) && cmd_nr == _IOC_NR(MTIOCTOP)) {
4761                 struct mtop mtc;
4762                 int    auto_weof = 0;
4763
4764                 if (_IOC_SIZE(cmd_in) != sizeof(mtc)) {
4765                         retval = (-EINVAL);
4766                         goto out;
4767                 }
4768
4769                 i = copy_from_user((char *) &mtc, p, sizeof(struct mtop));
4770                 if (i) {
4771                         retval = (-EFAULT);
4772                         goto out;
4773                 }
4774
4775                 if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
4776                         printk(KERN_WARNING "%s:W: MTSETDRVBUFFER only allowed for root.\n", name);
4777                         retval = (-EPERM);
4778                         goto out;
4779                 }
4780
4781                 if (!STm->defined && (mtc.mt_op != MTSETDRVBUFFER && (mtc.mt_count & MT_ST_OPTIONS) == 0)) {
4782                         retval = (-ENXIO);
4783                         goto out;
4784                 }
4785
4786                 if (!STp->pos_unknown) {
4787
4788                         if (STps->eof == ST_FM_HIT) {
4789                                 if (mtc.mt_op == MTFSF || mtc.mt_op == MTFSFM|| mtc.mt_op == MTEOM) {
4790                                         mtc.mt_count -= 1;
4791                                         if (STps->drv_file >= 0)
4792                                                 STps->drv_file += 1;
4793                                 }
4794                                 else if (mtc.mt_op == MTBSF || mtc.mt_op == MTBSFM) {
4795                                         mtc.mt_count += 1;
4796                                         if (STps->drv_file >= 0)
4797                                                 STps->drv_file += 1;
4798                                 }
4799                         }
4800
4801                         if (mtc.mt_op == MTSEEK) {
4802                                 /* Old position must be restored if partition will be changed */
4803                                 i = !STp->can_partitions || (STp->new_partition != STp->partition);
4804                         }
4805                         else {
4806                                 i = mtc.mt_op == MTREW   || mtc.mt_op == MTOFFL ||
4807                                     mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM  ||
4808                                     mtc.mt_op == MTLOCK  || mtc.mt_op == MTLOAD ||
4809                                     mtc.mt_op == MTFSF   || mtc.mt_op == MTFSFM ||
4810                                     mtc.mt_op == MTBSF   || mtc.mt_op == MTBSFM ||
4811                                     mtc.mt_op == MTCOMPRESSION;
4812                         }
4813                         i = osst_flush_buffer(STp, &SRpnt, i);
4814                         if (i < 0) {
4815                                 retval = i;
4816                                 goto out;
4817                         }
4818                 }
4819                 else {
4820                         /*
4821                          * If there was a bus reset, block further access
4822                          * to this device.  If the user wants to rewind the tape,
4823                          * then reset the flag and allow access again.
4824                          */
4825                         if(mtc.mt_op != MTREW   &&
4826                            mtc.mt_op != MTOFFL  &&
4827                            mtc.mt_op != MTRETEN &&
4828                            mtc.mt_op != MTERASE &&
4829                            mtc.mt_op != MTSEEK  &&
4830                            mtc.mt_op != MTEOM)   {
4831                                 retval = (-EIO);
4832                                 goto out;
4833                         }
4834                         reset_state(STp);
4835                         /* remove this when the midlevel properly clears was_reset */
4836                         STp->device->was_reset = 0;
4837                 }
4838
4839                 if (mtc.mt_op != MTCOMPRESSION  && mtc.mt_op != MTLOCK         &&
4840                     mtc.mt_op != MTNOP          && mtc.mt_op != MTSETBLK       &&
4841                     mtc.mt_op != MTSETDENSITY   && mtc.mt_op != MTSETDRVBUFFER && 
4842                     mtc.mt_op != MTMKPART       && mtc.mt_op != MTSETPART      &&
4843                     mtc.mt_op != MTWEOF         && mtc.mt_op != MTWSM           ) {
4844
4845                         /*
4846                          * The user tells us to move to another position on the tape.
4847                          * If we were appending to the tape content, that would leave
4848                          * the tape without proper end, in that case write EOD and
4849                          * update the header to reflect its position.
4850                          */
4851 #if DEBUG
4852                         printk(KERN_WARNING "%s:D: auto_weod %s at ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n", name,
4853                                         STps->rw >= ST_WRITING ? "write" : STps->rw == ST_READING ? "read" : "idle",
4854                                         STp->first_frame_position, STp->eod_frame_ppos, STp->frame_seq_number,
4855                                         STp->logical_blk_num, STps->drv_file, STps->drv_block );
4856 #endif
4857                         if (STps->rw >= ST_WRITING && STp->first_frame_position >= STp->eod_frame_ppos) {
4858                                 auto_weof = ((STp->write_type != OS_WRITE_NEW_MARK) &&
4859                                                         !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
4860                                 i = osst_write_trailer(STp, &SRpnt,
4861                                                         !(mtc.mt_op == MTREW || mtc.mt_op == MTOFFL));
4862 #if DEBUG
4863                                 printk(KERN_WARNING "%s:D: post trailer xeof=%d,ffp=%d,efp=%d,fsn=%d,lbn=%d,fn=%d,bn=%d\n",
4864                                                 name, auto_weof, STp->first_frame_position, STp->eod_frame_ppos,
4865                                                 STp->frame_seq_number, STp->logical_blk_num, STps->drv_file, STps->drv_block );
4866 #endif
4867                                 if (i < 0) {
4868                                         retval = i;
4869                                         goto out;
4870                                 }
4871                         }
4872                         STps->rw = ST_IDLE;
4873                 }
4874
4875                 if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
4876                         do_door_lock(STp, 0);  /* Ignore result! */
4877
4878                 if (mtc.mt_op == MTSETDRVBUFFER &&
4879                    (mtc.mt_count & MT_ST_OPTIONS) != 0) {
4880                         retval = osst_set_options(STp, mtc.mt_count);
4881                         goto out;
4882                 }
4883
4884                 if (mtc.mt_op == MTSETPART) {
4885                         if (mtc.mt_count >= STp->nbr_partitions)
4886                                 retval = -EINVAL;
4887                         else {
4888                                 STp->new_partition = mtc.mt_count;
4889                                 retval = 0;
4890                         }
4891                         goto out;
4892                 }
4893
4894                 if (mtc.mt_op == MTMKPART) {
4895                         if (!STp->can_partitions) {
4896                                 retval = (-EINVAL);
4897                                 goto out;
4898                         }
4899                         if ((i = osst_int_ioctl(STp, &SRpnt, MTREW, 0)) < 0 /*||
4900                             (i = partition_tape(inode, mtc.mt_count)) < 0*/) {
4901                                 retval = i;
4902                                 goto out;
4903                         }
4904                         for (i=0; i < ST_NBR_PARTITIONS; i++) {
4905                                 STp->ps[i].rw = ST_IDLE;
4906                                 STp->ps[i].at_sm = 0;
4907                                 STp->ps[i].last_block_valid = FALSE;
4908                         }
4909                         STp->partition = STp->new_partition = 0;
4910                         STp->nbr_partitions = 1;  /* Bad guess ?-) */
4911                         STps->drv_block = STps->drv_file = 0;
4912                         retval = 0;
4913                         goto out;
4914                 }
4915
4916                 if (mtc.mt_op == MTSEEK) {
4917                         if (STp->raw)
4918                                 i = osst_set_frame_position(STp, &SRpnt, mtc.mt_count, 0);
4919                         else
4920                                 i = osst_seek_sector(STp, &SRpnt, mtc.mt_count);
4921                         if (!STp->can_partitions)
4922                                 STp->ps[0].rw = ST_IDLE;
4923                         retval = i;
4924                         goto out;
4925                 }
4926  
4927                 if (mtc.mt_op == MTLOCK || mtc.mt_op == MTUNLOCK) {
4928                         retval = do_door_lock(STp, (mtc.mt_op == MTLOCK));
4929                         goto out;
4930                 }
4931
4932                 if (auto_weof)
4933                         cross_eof(STp, &SRpnt, FALSE);
4934
4935                 if (mtc.mt_op == MTCOMPRESSION)
4936                         retval = -EINVAL;       /* OnStream drives don't have compression hardware */
4937                 else
4938                         /* MTBSF MTBSFM MTBSR MTBSS MTEOM MTERASE MTFSF MTFSFB MTFSR MTFSS
4939                          * MTLOAD MTOFFL MTRESET MTRETEN MTREW MTUNLOAD MTWEOF MTWSM */
4940                         retval = osst_int_ioctl(STp, &SRpnt, mtc.mt_op, mtc.mt_count);
4941                 goto out;
4942         }
4943
4944         if (!STm->defined) {
4945                 retval = (-ENXIO);
4946                 goto out;
4947         }
4948
4949         if ((i = osst_flush_buffer(STp, &SRpnt, FALSE)) < 0) {
4950                 retval = i;
4951                 goto out;
4952         }
4953
4954         if (cmd_type == _IOC_TYPE(MTIOCGET) && cmd_nr == _IOC_NR(MTIOCGET)) {
4955                 struct mtget mt_status;
4956
4957                 if (_IOC_SIZE(cmd_in) != sizeof(struct mtget)) {
4958                          retval = (-EINVAL);
4959                          goto out;
4960                 }
4961
4962                 mt_status.mt_type = MT_ISONSTREAM_SC;
4963                 mt_status.mt_erreg = STp->recover_erreg << MT_ST_SOFTERR_SHIFT;
4964                 mt_status.mt_dsreg =
4965                         ((STp->block_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK) |
4966                         ((STp->density    << MT_ST_DENSITY_SHIFT) & MT_ST_DENSITY_MASK);
4967                 mt_status.mt_blkno = STps->drv_block;
4968                 mt_status.mt_fileno = STps->drv_file;
4969                 if (STp->block_size != 0) {
4970                         if (STps->rw == ST_WRITING)
4971                                 mt_status.mt_blkno += (STp->buffer)->buffer_bytes / STp->block_size;
4972                         else if (STps->rw == ST_READING)
4973                                 mt_status.mt_blkno -= ((STp->buffer)->buffer_bytes +
4974                                                         STp->block_size - 1) / STp->block_size;
4975                 }
4976
4977                 mt_status.mt_gstat = 0;
4978                 if (STp->drv_write_prot)
4979                         mt_status.mt_gstat |= GMT_WR_PROT(0xffffffff);
4980                 if (mt_status.mt_blkno == 0) {
4981                         if (mt_status.mt_fileno == 0)
4982                                 mt_status.mt_gstat |= GMT_BOT(0xffffffff);
4983                         else
4984                                 mt_status.mt_gstat |= GMT_EOF(0xffffffff);
4985                 }
4986                 mt_status.mt_resid = STp->partition;
4987                 if (STps->eof == ST_EOM_OK || STps->eof == ST_EOM_ERROR)
4988                         mt_status.mt_gstat |= GMT_EOT(0xffffffff);
4989                 else if (STps->eof >= ST_EOM_OK)
4990                         mt_status.mt_gstat |= GMT_EOD(0xffffffff);
4991                 if (STp->density == 1)
4992                         mt_status.mt_gstat |= GMT_D_800(0xffffffff);
4993                 else if (STp->density == 2)
4994                         mt_status.mt_gstat |= GMT_D_1600(0xffffffff);
4995                 else if (STp->density == 3)
4996                         mt_status.mt_gstat |= GMT_D_6250(0xffffffff);
4997                 if (STp->ready == ST_READY)
4998                         mt_status.mt_gstat |= GMT_ONLINE(0xffffffff);
4999                 if (STp->ready == ST_NO_TAPE)
5000                         mt_status.mt_gstat |= GMT_DR_OPEN(0xffffffff);
5001                 if (STps->at_sm)
5002                         mt_status.mt_gstat |= GMT_SM(0xffffffff);
5003                 if (STm->do_async_writes || (STm->do_buffer_writes && STp->block_size != 0) ||
5004                     STp->drv_buffer != 0)
5005                         mt_status.mt_gstat |= GMT_IM_REP_EN(0xffffffff);
5006
5007                 i = copy_to_user(p, &mt_status, sizeof(struct mtget));
5008                 if (i) {
5009                         retval = (-EFAULT);
5010                         goto out;
5011                 }
5012
5013                 STp->recover_erreg = 0;  /* Clear after read */
5014                 retval = 0;
5015                 goto out;
5016         } /* End of MTIOCGET */
5017
5018         if (cmd_type == _IOC_TYPE(MTIOCPOS) && cmd_nr == _IOC_NR(MTIOCPOS)) {
5019                 struct mtpos mt_pos;
5020
5021                 if (_IOC_SIZE(cmd_in) != sizeof(struct mtpos)) {
5022                         retval = (-EINVAL);
5023                         goto out;
5024                 }
5025                 if (STp->raw)
5026                         blk = osst_get_frame_position(STp, &SRpnt);
5027                 else
5028                         blk = osst_get_sector(STp, &SRpnt);
5029                 if (blk < 0) {
5030                         retval = blk;
5031                         goto out;
5032                 }
5033                 mt_pos.mt_blkno = blk;
5034                 i = copy_to_user(p, &mt_pos, sizeof(struct mtpos));
5035                 if (i)
5036                         retval = -EFAULT;
5037                 goto out;
5038         }
5039         if (SRpnt) scsi_release_request(SRpnt);
5040
5041         up(&STp->lock);
5042
5043         return scsi_ioctl(STp->device, cmd_in, p);
5044
5045 out:
5046         if (SRpnt) scsi_release_request(SRpnt);
5047
5048         up(&STp->lock);
5049
5050         return retval;
5051 }
5052
5053 \f
5054 /* Memory handling routines */
5055
5056 /* Try to allocate a new tape buffer skeleton. Caller must not hold os_scsi_tapes_lock */
5057 static OSST_buffer * new_tape_buffer( int from_initialization, int need_dma, int max_sg )
5058 {
5059         int i, priority;
5060         OSST_buffer *tb;
5061
5062         if (from_initialization)
5063                 priority = GFP_ATOMIC;
5064         else
5065                 priority = GFP_KERNEL;
5066
5067         i = sizeof(OSST_buffer) + (osst_max_sg_segs - 1) * sizeof(struct scatterlist);
5068         tb = (OSST_buffer *)kmalloc(i, priority);
5069         if (!tb) {
5070                 printk(KERN_NOTICE "osst :I: Can't allocate new tape buffer.\n");
5071                 return NULL;
5072         }
5073         memset(tb, 0, i);
5074         tb->sg_segs = tb->orig_sg_segs = 0;
5075         tb->use_sg = max_sg;
5076         tb->in_use = TRUE;
5077         tb->dma = need_dma;
5078         tb->buffer_size = 0;
5079 #if DEBUG
5080         if (debugging) 
5081                 printk(OSST_DEB_MSG
5082                         "osst :D: Allocated tape buffer skeleton (%d bytes, %d segments, dma: %d).\n",
5083                            i, max_sg, need_dma);
5084 #endif
5085         return tb;
5086 }
5087
5088 /* Try to allocate a temporary (while a user has the device open) enlarged tape buffer */
5089 static int enlarge_buffer(OSST_buffer *STbuffer, int need_dma)
5090 {
5091         int segs, nbr, max_segs, b_size, priority, order, got;
5092
5093         if (STbuffer->buffer_size >= OS_FRAME_SIZE)
5094                 return TRUE;
5095
5096         if (STbuffer->sg_segs) {
5097                 printk(KERN_WARNING "osst :A: Buffer not previously normalized.\n");
5098                 normalize_buffer(STbuffer);
5099         }
5100         /* See how many segments we can use -- need at least two */
5101         nbr = max_segs = STbuffer->use_sg;
5102         if (nbr <= 2)
5103                 return FALSE;
5104
5105         priority = GFP_KERNEL;
5106         if (need_dma)
5107                 priority |= GFP_DMA;
5108
5109         priority |= __GFP_NOWARN;
5110
5111         /* Try to allocate the first segment up to OS_DATA_SIZE and the others
5112            big enough to reach the goal (code assumes no segments in place) */
5113         for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) {
5114                 STbuffer->sg[0].page = alloc_pages(priority, order);
5115                 STbuffer->sg[0].offset = 0;
5116                 if (STbuffer->sg[0].page != NULL) {
5117                     STbuffer->sg[0].length = b_size;
5118                     STbuffer->b_data = page_address(STbuffer->sg[0].page);
5119                     break;
5120                 }
5121         }
5122         if (STbuffer->sg[0].page == NULL) {
5123                 printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n");
5124                 return FALSE;
5125         }
5126         /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */
5127         for (segs=STbuffer->sg_segs=1, got=b_size;
5128              segs < max_segs && got < OS_FRAME_SIZE; ) {
5129                 STbuffer->sg[segs].page =
5130                                 alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
5131                 STbuffer->sg[segs].offset = 0;
5132                 if (STbuffer->sg[segs].page == NULL) {
5133                         if (OS_FRAME_SIZE - got <= (max_segs - segs) * b_size / 2 && order) {
5134                                 b_size /= 2;  /* Large enough for the rest of the buffers */
5135                                 order--;
5136                                 continue;
5137                         }
5138                         printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
5139                                                 OS_FRAME_SIZE);
5140 #if DEBUG
5141                         STbuffer->buffer_size = got;
5142 #endif
5143                         normalize_buffer(STbuffer);
5144                         return FALSE;
5145                 }
5146                 STbuffer->sg[segs].length = (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size;
5147                 got += STbuffer->sg[segs].length;
5148                 STbuffer->buffer_size = got;
5149                 STbuffer->sg_segs = ++segs;
5150         }
5151 #if DEBUG
5152         if (debugging) {
5153                 printk(OSST_DEB_MSG
5154                            "osst :D: Expanded tape buffer (%d bytes, %d->%d segments, dma: %d, at: %p).\n",
5155                            got, STbuffer->orig_sg_segs, STbuffer->sg_segs, need_dma, STbuffer->b_data);
5156                 printk(OSST_DEB_MSG
5157                            "osst :D: segment sizes: first %d at %p, last %d bytes at %p.\n",
5158                            STbuffer->sg[0].length, page_address(STbuffer->sg[0].page),
5159                            STbuffer->sg[segs-1].length, page_address(STbuffer->sg[segs-1].page));
5160         }
5161 #endif
5162
5163         return TRUE;
5164 }
5165
5166
5167 /* Release the segments */
5168 static void normalize_buffer(OSST_buffer *STbuffer)
5169 {
5170   int i, order, b_size;
5171
5172         for (i=0; i < STbuffer->sg_segs; i++) {
5173
5174                 for (b_size = PAGE_SIZE, order = 0;
5175                      b_size < STbuffer->sg[i].length;
5176                      b_size *= 2, order++);
5177
5178                 __free_pages(STbuffer->sg[i].page, order);
5179                 STbuffer->buffer_size -= STbuffer->sg[i].length;
5180         }
5181 #if DEBUG
5182         if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
5183                 printk(OSST_DEB_MSG "osst :D: Buffer at %p normalized to %d bytes (segs %d).\n",
5184                              STbuffer->b_data, STbuffer->buffer_size, STbuffer->sg_segs);
5185 #endif
5186         STbuffer->sg_segs = STbuffer->orig_sg_segs = 0;
5187 }
5188
5189
5190 /* Move data from the user buffer to the tape buffer. Returns zero (success) or
5191    negative error code. */
5192 static int append_to_buffer(const char __user *ubp, OSST_buffer *st_bp, int do_count)
5193 {
5194         int i, cnt, res, offset;
5195
5196         for (i=0, offset=st_bp->buffer_bytes;
5197              i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5198         offset -= st_bp->sg[i].length;
5199         if (i == st_bp->sg_segs) {  /* Should never happen */
5200                 printk(KERN_WARNING "osst :A: Append_to_buffer offset overflow.\n");
5201                 return (-EIO);
5202         }
5203         for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5204                 cnt = st_bp->sg[i].length - offset < do_count ?
5205                       st_bp->sg[i].length - offset : do_count;
5206                 res = copy_from_user(page_address(st_bp->sg[i].page) + offset, ubp, cnt);
5207                 if (res)
5208                         return (-EFAULT);
5209                 do_count -= cnt;
5210                 st_bp->buffer_bytes += cnt;
5211                 ubp += cnt;
5212                 offset = 0;
5213         }
5214         if (do_count) {  /* Should never happen */
5215                 printk(KERN_WARNING "osst :A: Append_to_buffer overflow (left %d).\n",
5216                        do_count);
5217                 return (-EIO);
5218         }
5219         return 0;
5220 }
5221
5222
5223 /* Move data from the tape buffer to the user buffer. Returns zero (success) or
5224    negative error code. */
5225 static int from_buffer(OSST_buffer *st_bp, char __user *ubp, int do_count)
5226 {
5227         int i, cnt, res, offset;
5228
5229         for (i=0, offset=st_bp->read_pointer;
5230              i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5231                 offset -= st_bp->sg[i].length;
5232         if (i == st_bp->sg_segs) {  /* Should never happen */
5233                 printk(KERN_WARNING "osst :A: From_buffer offset overflow.\n");
5234                 return (-EIO);
5235         }
5236         for ( ; i < st_bp->sg_segs && do_count > 0; i++) {
5237                 cnt = st_bp->sg[i].length - offset < do_count ?
5238                       st_bp->sg[i].length - offset : do_count;
5239                 res = copy_to_user(ubp, page_address(st_bp->sg[i].page) + offset, cnt);
5240                 if (res)
5241                         return (-EFAULT);
5242                 do_count -= cnt;
5243                 st_bp->buffer_bytes -= cnt;
5244                 st_bp->read_pointer += cnt;
5245                 ubp += cnt;
5246                 offset = 0;
5247         }
5248         if (do_count) {  /* Should never happen */
5249                 printk(KERN_WARNING "osst :A: From_buffer overflow (left %d).\n", do_count);
5250                 return (-EIO);
5251         }
5252         return 0;
5253 }
5254
5255 /* Sets the tail of the buffer after fill point to zero.
5256    Returns zero (success) or negative error code.        */
5257 static int osst_zero_buffer_tail(OSST_buffer *st_bp)
5258 {
5259         int     i, offset, do_count, cnt;
5260
5261         for (i = 0, offset = st_bp->buffer_bytes;
5262              i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
5263                 offset -= st_bp->sg[i].length;
5264         if (i == st_bp->sg_segs) {  /* Should never happen */
5265                 printk(KERN_WARNING "osst :A: Zero_buffer offset overflow.\n");
5266                 return (-EIO);
5267         }
5268         for (do_count = OS_DATA_SIZE - st_bp->buffer_bytes;
5269              i < st_bp->sg_segs && do_count > 0; i++) {
5270                 cnt = st_bp->sg[i].length - offset < do_count ?
5271                       st_bp->sg[i].length - offset : do_count ;
5272                 memset(page_address(st_bp->sg[i].page) + offset, 0, cnt);
5273                 do_count -= cnt;
5274                 offset = 0;
5275         }
5276         if (do_count) {  /* Should never happen */
5277                 printk(KERN_WARNING "osst :A: Zero_buffer overflow (left %d).\n", do_count);
5278                 return (-EIO);
5279         }
5280         return 0;
5281 }
5282
5283 /* Copy a osst 32K chunk of memory into the buffer.
5284    Returns zero (success) or negative error code.  */
5285 static int osst_copy_to_buffer(OSST_buffer *st_bp, unsigned char *ptr)
5286 {
5287         int     i, cnt, do_count = OS_DATA_SIZE;
5288
5289         for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5290                 cnt = st_bp->sg[i].length < do_count ?
5291                       st_bp->sg[i].length : do_count ;
5292                 memcpy(page_address(st_bp->sg[i].page), ptr, cnt);
5293                 do_count -= cnt;
5294                 ptr      += cnt;
5295         }
5296         if (do_count || i != st_bp->sg_segs-1) {  /* Should never happen */
5297                 printk(KERN_WARNING "osst :A: Copy_to_buffer overflow (left %d at sg %d).\n",
5298                                          do_count, i);
5299                 return (-EIO);
5300         }
5301         return 0;
5302 }
5303
5304 /* Copy a osst 32K chunk of memory from the buffer.
5305    Returns zero (success) or negative error code.  */
5306 static int osst_copy_from_buffer(OSST_buffer *st_bp, unsigned char *ptr)
5307 {
5308         int     i, cnt, do_count = OS_DATA_SIZE;
5309
5310         for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) {
5311                 cnt = st_bp->sg[i].length < do_count ?
5312                       st_bp->sg[i].length : do_count ;
5313                 memcpy(ptr, page_address(st_bp->sg[i].page), cnt);
5314                 do_count -= cnt;
5315                 ptr      += cnt;
5316         }
5317         if (do_count || i != st_bp->sg_segs-1) {  /* Should never happen */
5318                 printk(KERN_WARNING "osst :A: Copy_from_buffer overflow (left %d at sg %d).\n",
5319                                          do_count, i);
5320                 return (-EIO);
5321         }
5322         return 0;
5323 }
5324
5325 \f
5326 /* Module housekeeping */
5327
5328 static void validate_options (void)
5329 {
5330   if (max_dev > 0)
5331                 osst_max_dev = max_dev;  
5332   if (write_threshold_kbs > 0)
5333                 osst_write_threshold = write_threshold_kbs * ST_KILOBYTE;
5334   if (osst_write_threshold > osst_buffer_size)
5335                 osst_write_threshold = osst_buffer_size;
5336   if (max_sg_segs >= OSST_FIRST_SG)
5337                 osst_max_sg_segs = max_sg_segs;
5338 #if DEBUG
5339   printk(OSST_DEB_MSG "osst :D: max tapes %d, write threshold %d, max s/g segs %d.\n",
5340                            osst_max_dev, osst_write_threshold, osst_max_sg_segs);
5341 #endif
5342 }
5343         
5344 #ifndef MODULE
5345 /* Set the boot options. Syntax: osst=xxx,yyy,...
5346    where xxx is write threshold in 1024 byte blocks,
5347    and   yyy is number of s/g segments to use. */
5348 static int __init osst_setup (char *str)
5349 {
5350   int i, ints[5];
5351   char *stp;
5352
5353   stp = get_options(str, ARRAY_SIZE(ints), ints);
5354         
5355   if (ints[0] > 0) {
5356         for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
5357                   *parms[i].val = ints[i + 1];
5358   } else {
5359         while (stp != NULL) {
5360                 for (i = 0; i < ARRAY_SIZE(parms); i++) {
5361                         int len = strlen(parms[i].name);
5362                         if (!strncmp(stp, parms[i].name, len) &&
5363                             (*(stp + len) == ':' || *(stp + len) == '=')) {
5364                                 *parms[i].val =
5365                                         simple_strtoul(stp + len + 1, NULL, 0);
5366                                 break;
5367                         }
5368                 }
5369                 if (i >= sizeof(parms) / sizeof(struct osst_dev_parm))
5370                         printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
5371                                stp);
5372                 stp = strchr(stp, ',');
5373                 if (stp)
5374                         stp++;
5375         }
5376   }
5377
5378   return 1;
5379 }
5380
5381 __setup("osst=", osst_setup);
5382
5383 #endif
5384
5385 static struct file_operations osst_fops = {
5386         .owner =        THIS_MODULE,
5387         .read =         osst_read,
5388         .write =        osst_write,
5389         .ioctl =        osst_ioctl,
5390         .open =         os_scsi_tape_open,
5391         .flush =        os_scsi_tape_flush,
5392         .release =      os_scsi_tape_close,
5393 };
5394
5395 static int osst_supports(Scsi_Device * SDp)
5396 {
5397         struct  osst_support_data {
5398                 char *vendor;
5399                 char *model;
5400                 char *rev;
5401                 char *driver_hint; /* Name of the correct driver, NULL if unknown */
5402         };
5403
5404 static  struct  osst_support_data support_list[] = {
5405                 /* {"XXX", "Yy-", "", NULL},  example */
5406                 SIGS_FROM_OSST,
5407                 {NULL, }};
5408
5409         struct  osst_support_data *rp;
5410
5411         /* We are willing to drive OnStream SC-x0 as well as the
5412          *       * IDE, ParPort, FireWire, USB variants, if accessible by
5413          *               * emulation layer (ide-scsi, usb-storage, ...) */
5414
5415         for (rp=&(support_list[0]); rp->vendor != NULL; rp++)
5416                 if (!strncmp(rp->vendor, SDp->vendor, strlen(rp->vendor)) &&
5417                     !strncmp(rp->model, SDp->model, strlen(rp->model)) &&
5418                     !strncmp(rp->rev, SDp->rev, strlen(rp->rev))) 
5419                         return 1;
5420         return 0;
5421 }
5422
5423 /*
5424  * osst startup / cleanup code
5425  */
5426
5427 static int osst_probe(struct device *dev)
5428 {
5429         Scsi_Device    * SDp = to_scsi_device(dev);
5430         OS_Scsi_Tape   * tpnt;
5431         ST_mode        * STm;
5432         ST_partstat    * STps;
5433         OSST_buffer    * buffer;
5434         struct gendisk * drive;
5435         int              i, mode, dev_num;
5436
5437         if (SDp->type != TYPE_TAPE || !osst_supports(SDp))
5438                 return -ENODEV;
5439
5440         drive = alloc_disk(1);
5441         if (!drive) {
5442                 printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n");
5443                 return -ENODEV;
5444         }
5445
5446         /* if this is the first attach, build the infrastructure */
5447         write_lock(&os_scsi_tapes_lock);
5448         if (os_scsi_tapes == NULL) {
5449                 os_scsi_tapes =
5450                         (OS_Scsi_Tape **)kmalloc(osst_max_dev * sizeof(OS_Scsi_Tape *),
5451                                    GFP_ATOMIC);
5452                 if (os_scsi_tapes == NULL) {
5453                         write_unlock(&os_scsi_tapes_lock);
5454                         printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
5455                         goto out_put_disk;
5456                 }
5457                 for (i=0; i < osst_max_dev; ++i) os_scsi_tapes[i] = NULL;
5458         }
5459         
5460         if (osst_nr_dev >= osst_max_dev) {
5461                 write_unlock(&os_scsi_tapes_lock);
5462                 printk(KERN_ERR "osst :E: Too many tape devices (max. %d).\n", osst_max_dev);
5463                 goto out_put_disk;
5464         }
5465
5466         /* find a free minor number */
5467         for (i=0; os_scsi_tapes[i] && i<osst_max_dev; i++);
5468         if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)");
5469         dev_num = i;
5470
5471         /* allocate a OS_Scsi_Tape for this device */
5472         tpnt = (OS_Scsi_Tape *)kmalloc(sizeof(OS_Scsi_Tape), GFP_ATOMIC);
5473         if (tpnt == NULL) {
5474                 write_unlock(&os_scsi_tapes_lock);
5475                 printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n");
5476                 goto out_put_disk;
5477         }
5478         memset(tpnt, 0, sizeof(OS_Scsi_Tape));
5479
5480         /* allocate a buffer for this device */
5481         i = SDp->host->sg_tablesize;
5482         if (osst_max_sg_segs < i)
5483                 i = osst_max_sg_segs;
5484         buffer = new_tape_buffer(TRUE, SDp->host->unchecked_isa_dma, i);
5485         if (buffer == NULL) {
5486                 write_unlock(&os_scsi_tapes_lock);
5487                 printk(KERN_ERR "osst :E: Unable to allocate a tape buffer, device not attached.\n");
5488                 kfree(tpnt);
5489                 goto out_put_disk;
5490         }
5491         os_scsi_tapes[dev_num] = tpnt;
5492         tpnt->buffer = buffer;
5493         tpnt->device = SDp;
5494         drive->private_data = &tpnt->driver;
5495         sprintf(drive->disk_name, "osst%d", dev_num);
5496         tpnt->driver = &osst_template;
5497         tpnt->drive = drive;
5498         tpnt->in_use = 0;
5499         tpnt->capacity = 0xfffff;
5500         tpnt->dirty = 0;
5501         tpnt->drv_buffer = 1;  /* Try buffering if no mode sense */
5502         tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
5503         tpnt->density = 0;
5504         tpnt->do_auto_lock = OSST_AUTO_LOCK;
5505         tpnt->can_bsr = OSST_IN_FILE_POS;
5506         tpnt->can_partitions = 0;
5507         tpnt->two_fm = OSST_TWO_FM;
5508         tpnt->fast_mteom = OSST_FAST_MTEOM;
5509         tpnt->scsi2_logical = OSST_SCSI2LOGICAL; /* FIXME */
5510         tpnt->write_threshold = osst_write_threshold;
5511         tpnt->default_drvbuffer = 0xff; /* No forced buffering */
5512         tpnt->partition = 0;
5513         tpnt->new_partition = 0;
5514         tpnt->nbr_partitions = 0;
5515         tpnt->min_block = 512;
5516         tpnt->max_block = OS_DATA_SIZE;
5517         tpnt->timeout = OSST_TIMEOUT;
5518         tpnt->long_timeout = OSST_LONG_TIMEOUT;
5519
5520         /* Recognize OnStream tapes */
5521         /* We don't need to test for OnStream, as this has been done in detect () */
5522         tpnt->os_fw_rev = osst_parse_firmware_rev (SDp->rev);
5523         tpnt->omit_blklims = 1;
5524
5525         tpnt->poll = (strncmp(SDp->model, "DI-", 3) == 0) || 
5526                      (strncmp(SDp->model, "FW-", 3) == 0) || OSST_FW_NEED_POLL(tpnt->os_fw_rev,SDp);
5527         tpnt->frame_in_buffer = 0;
5528         tpnt->header_ok = 0;
5529         tpnt->linux_media = 0;
5530         tpnt->header_cache = NULL;
5531
5532         for (i=0; i < ST_NBR_MODES; i++) {
5533                 STm = &(tpnt->modes[i]);
5534                 STm->defined = FALSE;
5535                 STm->sysv = OSST_SYSV;
5536                 STm->defaults_for_writes = 0;
5537                 STm->do_async_writes = OSST_ASYNC_WRITES;
5538                 STm->do_buffer_writes = OSST_BUFFER_WRITES;
5539                 STm->do_read_ahead = OSST_READ_AHEAD;
5540                 STm->default_compression = ST_DONT_TOUCH;
5541                 STm->default_blksize = 512;
5542                 STm->default_density = (-1);  /* No forced density */
5543         }
5544
5545         for (i=0; i < ST_NBR_PARTITIONS; i++) {
5546                 STps = &(tpnt->ps[i]);
5547                 STps->rw = ST_IDLE;
5548                 STps->eof = ST_NOEOF;
5549                 STps->at_sm = 0;
5550                 STps->last_block_valid = FALSE;
5551                 STps->drv_block = (-1);
5552                 STps->drv_file = (-1);
5553         }
5554
5555         tpnt->current_mode = 0;
5556         tpnt->modes[0].defined = TRUE;
5557         tpnt->modes[2].defined = TRUE;
5558         tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = FALSE;
5559
5560         init_MUTEX(&tpnt->lock);
5561         osst_nr_dev++;
5562         write_unlock(&os_scsi_tapes_lock);
5563
5564         for (mode = 0; mode < ST_NBR_MODES; ++mode) {
5565                 /*  Rewind entry  */
5566                 devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)),
5567                                 S_IFCHR | S_IRUGO | S_IWUGO,
5568                                 "%s/ot%s", SDp->devfs_name, osst_formats[mode]);
5569
5570                 /*  No-rewind entry  */
5571                 devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5) + 128),
5572                                 S_IFCHR | S_IRUGO | S_IWUGO,
5573                                 "%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
5574         }
5575         drive->number = devfs_register_tape(SDp->devfs_name);
5576
5577         printk(KERN_INFO
5578                 "osst :I: Attached OnStream %.5s tape at scsi%d, channel %d, id %d, lun %d as %s\n",
5579                 SDp->model, SDp->host->host_no, SDp->channel, SDp->id, SDp->lun, tape_name(tpnt));
5580
5581         return 0;
5582
5583 out_put_disk:
5584         put_disk(drive);
5585         return -ENODEV;
5586 };
5587
5588 static int osst_remove(struct device *dev)
5589 {
5590         Scsi_Device  * SDp = to_scsi_device(dev);
5591         OS_Scsi_Tape * tpnt;
5592         int i, mode;
5593
5594         if ((SDp->type != TYPE_TAPE) || (osst_nr_dev <= 0))
5595                 return 0;
5596
5597         write_lock(&os_scsi_tapes_lock);
5598         for(i=0; i < osst_max_dev; i++) {
5599                 if((tpnt = os_scsi_tapes[i]) && (tpnt->device == SDp)) {
5600                         tpnt->device = NULL;
5601                         for (mode = 0; mode < ST_NBR_MODES; ++mode) {
5602                                 devfs_remove("%s/ot%s", SDp->devfs_name, osst_formats[mode]);
5603                                 devfs_remove("%s/ot%sn", SDp->devfs_name, osst_formats[mode]);
5604                         }
5605                         devfs_unregister_tape(tpnt->drive->number);
5606                         put_disk(tpnt->drive);
5607                         os_scsi_tapes[i] = NULL;
5608                         osst_nr_dev--;
5609                         write_unlock(&os_scsi_tapes_lock);
5610                         if (tpnt->header_cache != NULL) vfree(tpnt->header_cache);
5611                         if (tpnt->buffer) {
5612                                 normalize_buffer(tpnt->buffer);
5613                                 kfree(tpnt->buffer);
5614                         }
5615                         kfree(tpnt);
5616                         return 0;
5617                 }
5618         }
5619         write_unlock(&os_scsi_tapes_lock);
5620         return 0;
5621 }
5622
5623 static int __init init_osst(void) 
5624 {
5625         printk(KERN_INFO "osst :I: Tape driver with OnStream support version %s\nosst :I: %s\n", osst_version, cvsid);
5626
5627         validate_options();
5628         
5629         if ((register_chrdev(OSST_MAJOR,"osst", &osst_fops) < 0) || scsi_register_driver(&osst_template.gendrv)) {
5630                 printk(KERN_ERR "osst :E: Unable to register major %d for OnStream tapes\n", OSST_MAJOR);
5631                 return 1;
5632         }
5633
5634         return 0;
5635 }
5636
5637 static void __exit exit_osst (void)
5638 {
5639         int i;
5640         OS_Scsi_Tape * STp;
5641
5642         scsi_unregister_driver(&osst_template.gendrv);
5643         unregister_chrdev(OSST_MAJOR, "osst");
5644
5645         if (os_scsi_tapes) {
5646                 for (i=0; i < osst_max_dev; ++i) {
5647                         if (!(STp = os_scsi_tapes[i])) continue;
5648                         /* This is defensive, supposed to happen during detach */
5649                         if (STp->header_cache)
5650                                 vfree(STp->header_cache);
5651                         if (STp->buffer) {
5652                                 normalize_buffer(STp->buffer);
5653                                 kfree(STp->buffer);
5654                         }
5655                         put_disk(STp->drive);
5656                         kfree(STp);
5657                 }
5658                 kfree(os_scsi_tapes);
5659         }
5660         printk(KERN_INFO "osst :I: Unloaded.\n");
5661 }
5662
5663 module_init(init_osst);
5664 module_exit(exit_osst);