Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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