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