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