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