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