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