1 /* 2 * drivers/s390/char/tape_std.c 3 * standard tape device functions for ibm tapes. 4 * 5 * S390 and zSeries version 6 * Copyright (C) 2001,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation 7 * Author(s): Carsten Otte <cotte@de.ibm.com> 8 * Michael Holzheu <holzheu@de.ibm.com> 9 * Tuan Ngo-Anh <ngoanh@de.ibm.com> 10 * Martin Schwidefsky <schwidefsky@de.ibm.com> 11 * Stefan Bader <shbader@de.ibm.com> 12 */ 13 14 #include <linux/stddef.h> 15 #include <linux/kernel.h> 16 #include <linux/bio.h> 17 #include <linux/timer.h> 18 19 #include <asm/types.h> 20 #include <asm/idals.h> 21 #include <asm/ebcdic.h> 22 #include <asm/tape390.h> 23 24 #define TAPE_DBF_AREA tape_core_dbf 25 26 #include "tape.h" 27 #include "tape_std.h" 28 29 #define PRINTK_HEADER "TAPE_STD: " 30 31 /* 32 * tape_std_assign 33 */ 34 static void 35 tape_std_assign_timeout(unsigned long data) 36 { 37 struct tape_request * request; 38 struct tape_device * device; 39 int rc; 40 41 request = (struct tape_request *) data; 42 if ((device = request->device) == NULL) 43 BUG(); 44 45 DBF_EVENT(3, "%08x: Assignment timeout. Device busy.\n", 46 device->cdev_id); 47 rc = tape_cancel_io(device, request); 48 if(rc) 49 PRINT_ERR("(%s): Assign timeout: Cancel failed with rc = %i\n", 50 dev_name(&device->cdev->dev), rc); 51 52 } 53 54 int 55 tape_std_assign(struct tape_device *device) 56 { 57 int rc; 58 struct timer_list timeout; 59 struct tape_request *request; 60 61 request = tape_alloc_request(2, 11); 62 if (IS_ERR(request)) 63 return PTR_ERR(request); 64 65 request->op = TO_ASSIGN; 66 tape_ccw_cc(request->cpaddr, ASSIGN, 11, request->cpdata); 67 tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL); 68 69 /* 70 * The assign command sometimes blocks if the device is assigned 71 * to another host (actually this shouldn't happen but it does). 72 * So we set up a timeout for this call. 73 */ 74 init_timer(&timeout); 75 timeout.function = tape_std_assign_timeout; 76 timeout.data = (unsigned long) request; 77 timeout.expires = jiffies + 2 * HZ; 78 add_timer(&timeout); 79 80 rc = tape_do_io_interruptible(device, request); 81 82 del_timer(&timeout); 83 84 if (rc != 0) { 85 PRINT_WARN("%s: assign failed - device might be busy\n", 86 dev_name(&device->cdev->dev)); 87 DBF_EVENT(3, "%08x: assign failed - device might be busy\n", 88 device->cdev_id); 89 } else { 90 DBF_EVENT(3, "%08x: Tape assigned\n", device->cdev_id); 91 } 92 tape_free_request(request); 93 return rc; 94 } 95 96 /* 97 * tape_std_unassign 98 */ 99 int 100 tape_std_unassign (struct tape_device *device) 101 { 102 int rc; 103 struct tape_request *request; 104 105 if (device->tape_state == TS_NOT_OPER) { 106 DBF_EVENT(3, "(%08x): Can't unassign device\n", 107 device->cdev_id); 108 PRINT_WARN("(%s): Can't unassign device - device gone\n", 109 dev_name(&device->cdev->dev)); 110 return -EIO; 111 } 112 113 request = tape_alloc_request(2, 11); 114 if (IS_ERR(request)) 115 return PTR_ERR(request); 116 117 request->op = TO_UNASSIGN; 118 tape_ccw_cc(request->cpaddr, UNASSIGN, 11, request->cpdata); 119 tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL); 120 121 if ((rc = tape_do_io(device, request)) != 0) { 122 DBF_EVENT(3, "%08x: Unassign failed\n", device->cdev_id); 123 PRINT_WARN("%s: Unassign failed\n", 124 dev_name(&device->cdev->dev)); 125 } else { 126 DBF_EVENT(3, "%08x: Tape unassigned\n", device->cdev_id); 127 } 128 tape_free_request(request); 129 return rc; 130 } 131 132 /* 133 * TAPE390_DISPLAY: Show a string on the tape display. 134 */ 135 int 136 tape_std_display(struct tape_device *device, struct display_struct *disp) 137 { 138 struct tape_request *request; 139 int rc; 140 141 request = tape_alloc_request(2, 17); 142 if (IS_ERR(request)) { 143 DBF_EVENT(3, "TAPE: load display failed\n"); 144 return PTR_ERR(request); 145 } 146 request->op = TO_DIS; 147 148 *(unsigned char *) request->cpdata = disp->cntrl; 149 DBF_EVENT(5, "TAPE: display cntrl=%04x\n", disp->cntrl); 150 memcpy(((unsigned char *) request->cpdata) + 1, disp->message1, 8); 151 memcpy(((unsigned char *) request->cpdata) + 9, disp->message2, 8); 152 ASCEBC(((unsigned char*) request->cpdata) + 1, 16); 153 154 tape_ccw_cc(request->cpaddr, LOAD_DISPLAY, 17, request->cpdata); 155 tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL); 156 157 rc = tape_do_io_interruptible(device, request); 158 tape_free_request(request); 159 return rc; 160 } 161 162 /* 163 * Read block id. 164 */ 165 int 166 tape_std_read_block_id(struct tape_device *device, __u64 *id) 167 { 168 struct tape_request *request; 169 int rc; 170 171 request = tape_alloc_request(3, 8); 172 if (IS_ERR(request)) 173 return PTR_ERR(request); 174 request->op = TO_RBI; 175 /* setup ccws */ 176 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 177 tape_ccw_cc(request->cpaddr + 1, READ_BLOCK_ID, 8, request->cpdata); 178 tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL); 179 /* execute it */ 180 rc = tape_do_io(device, request); 181 if (rc == 0) 182 /* Get result from read buffer. */ 183 *id = *(__u64 *) request->cpdata; 184 tape_free_request(request); 185 return rc; 186 } 187 188 int 189 tape_std_terminate_write(struct tape_device *device) 190 { 191 int rc; 192 193 if(device->required_tapemarks == 0) 194 return 0; 195 196 DBF_LH(5, "tape%d: terminate write %dxEOF\n", device->first_minor, 197 device->required_tapemarks); 198 199 rc = tape_mtop(device, MTWEOF, device->required_tapemarks); 200 if (rc) 201 return rc; 202 203 device->required_tapemarks = 0; 204 return tape_mtop(device, MTBSR, 1); 205 } 206 207 /* 208 * MTLOAD: Loads the tape. 209 * The default implementation just wait until the tape medium state changes 210 * to MS_LOADED. 211 */ 212 int 213 tape_std_mtload(struct tape_device *device, int count) 214 { 215 return wait_event_interruptible(device->state_change_wq, 216 (device->medium_state == MS_LOADED)); 217 } 218 219 /* 220 * MTSETBLK: Set block size. 221 */ 222 int 223 tape_std_mtsetblk(struct tape_device *device, int count) 224 { 225 struct idal_buffer *new; 226 227 DBF_LH(6, "tape_std_mtsetblk(%d)\n", count); 228 if (count <= 0) { 229 /* 230 * Just set block_size to 0. tapechar_read/tapechar_write 231 * will realloc the idal buffer if a bigger one than the 232 * current is needed. 233 */ 234 device->char_data.block_size = 0; 235 return 0; 236 } 237 if (device->char_data.idal_buf != NULL && 238 device->char_data.idal_buf->size == count) 239 /* We already have a idal buffer of that size. */ 240 return 0; 241 242 if (count > MAX_BLOCKSIZE) { 243 DBF_EVENT(3, "Invalid block size (%d > %d) given.\n", 244 count, MAX_BLOCKSIZE); 245 PRINT_ERR("Invalid block size (%d > %d) given.\n", 246 count, MAX_BLOCKSIZE); 247 return -EINVAL; 248 } 249 250 /* Allocate a new idal buffer. */ 251 new = idal_buffer_alloc(count, 0); 252 if (IS_ERR(new)) 253 return -ENOMEM; 254 if (device->char_data.idal_buf != NULL) 255 idal_buffer_free(device->char_data.idal_buf); 256 device->char_data.idal_buf = new; 257 device->char_data.block_size = count; 258 259 DBF_LH(6, "new blocksize is %d\n", device->char_data.block_size); 260 261 return 0; 262 } 263 264 /* 265 * MTRESET: Set block size to 0. 266 */ 267 int 268 tape_std_mtreset(struct tape_device *device, int count) 269 { 270 DBF_EVENT(6, "TCHAR:devreset:\n"); 271 device->char_data.block_size = 0; 272 return 0; 273 } 274 275 /* 276 * MTFSF: Forward space over 'count' file marks. The tape is positioned 277 * at the EOT (End of Tape) side of the file mark. 278 */ 279 int 280 tape_std_mtfsf(struct tape_device *device, int mt_count) 281 { 282 struct tape_request *request; 283 struct ccw1 *ccw; 284 285 request = tape_alloc_request(mt_count + 2, 0); 286 if (IS_ERR(request)) 287 return PTR_ERR(request); 288 request->op = TO_FSF; 289 /* setup ccws */ 290 ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 291 device->modeset_byte); 292 ccw = tape_ccw_repeat(ccw, FORSPACEFILE, mt_count); 293 ccw = tape_ccw_end(ccw, NOP, 0, NULL); 294 295 /* execute it */ 296 return tape_do_io_free(device, request); 297 } 298 299 /* 300 * MTFSR: Forward space over 'count' tape blocks (blocksize is set 301 * via MTSETBLK. 302 */ 303 int 304 tape_std_mtfsr(struct tape_device *device, int mt_count) 305 { 306 struct tape_request *request; 307 struct ccw1 *ccw; 308 int rc; 309 310 request = tape_alloc_request(mt_count + 2, 0); 311 if (IS_ERR(request)) 312 return PTR_ERR(request); 313 request->op = TO_FSB; 314 /* setup ccws */ 315 ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 316 device->modeset_byte); 317 ccw = tape_ccw_repeat(ccw, FORSPACEBLOCK, mt_count); 318 ccw = tape_ccw_end(ccw, NOP, 0, NULL); 319 320 /* execute it */ 321 rc = tape_do_io(device, request); 322 if (rc == 0 && request->rescnt > 0) { 323 DBF_LH(3, "FSR over tapemark\n"); 324 rc = 1; 325 } 326 tape_free_request(request); 327 328 return rc; 329 } 330 331 /* 332 * MTBSR: Backward space over 'count' tape blocks. 333 * (blocksize is set via MTSETBLK. 334 */ 335 int 336 tape_std_mtbsr(struct tape_device *device, int mt_count) 337 { 338 struct tape_request *request; 339 struct ccw1 *ccw; 340 int rc; 341 342 request = tape_alloc_request(mt_count + 2, 0); 343 if (IS_ERR(request)) 344 return PTR_ERR(request); 345 request->op = TO_BSB; 346 /* setup ccws */ 347 ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 348 device->modeset_byte); 349 ccw = tape_ccw_repeat(ccw, BACKSPACEBLOCK, mt_count); 350 ccw = tape_ccw_end(ccw, NOP, 0, NULL); 351 352 /* execute it */ 353 rc = tape_do_io(device, request); 354 if (rc == 0 && request->rescnt > 0) { 355 DBF_LH(3, "BSR over tapemark\n"); 356 rc = 1; 357 } 358 tape_free_request(request); 359 360 return rc; 361 } 362 363 /* 364 * MTWEOF: Write 'count' file marks at the current position. 365 */ 366 int 367 tape_std_mtweof(struct tape_device *device, int mt_count) 368 { 369 struct tape_request *request; 370 struct ccw1 *ccw; 371 372 request = tape_alloc_request(mt_count + 2, 0); 373 if (IS_ERR(request)) 374 return PTR_ERR(request); 375 request->op = TO_WTM; 376 /* setup ccws */ 377 ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 378 device->modeset_byte); 379 ccw = tape_ccw_repeat(ccw, WRITETAPEMARK, mt_count); 380 ccw = tape_ccw_end(ccw, NOP, 0, NULL); 381 382 /* execute it */ 383 return tape_do_io_free(device, request); 384 } 385 386 /* 387 * MTBSFM: Backward space over 'count' file marks. 388 * The tape is positioned at the BOT (Begin Of Tape) side of the 389 * last skipped file mark. 390 */ 391 int 392 tape_std_mtbsfm(struct tape_device *device, int mt_count) 393 { 394 struct tape_request *request; 395 struct ccw1 *ccw; 396 397 request = tape_alloc_request(mt_count + 2, 0); 398 if (IS_ERR(request)) 399 return PTR_ERR(request); 400 request->op = TO_BSF; 401 /* setup ccws */ 402 ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 403 device->modeset_byte); 404 ccw = tape_ccw_repeat(ccw, BACKSPACEFILE, mt_count); 405 ccw = tape_ccw_end(ccw, NOP, 0, NULL); 406 407 /* execute it */ 408 return tape_do_io_free(device, request); 409 } 410 411 /* 412 * MTBSF: Backward space over 'count' file marks. The tape is positioned at 413 * the EOT (End of Tape) side of the last skipped file mark. 414 */ 415 int 416 tape_std_mtbsf(struct tape_device *device, int mt_count) 417 { 418 struct tape_request *request; 419 struct ccw1 *ccw; 420 int rc; 421 422 request = tape_alloc_request(mt_count + 2, 0); 423 if (IS_ERR(request)) 424 return PTR_ERR(request); 425 request->op = TO_BSF; 426 /* setup ccws */ 427 ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 428 device->modeset_byte); 429 ccw = tape_ccw_repeat(ccw, BACKSPACEFILE, mt_count); 430 ccw = tape_ccw_end(ccw, NOP, 0, NULL); 431 /* execute it */ 432 rc = tape_do_io_free(device, request); 433 if (rc == 0) { 434 rc = tape_mtop(device, MTFSR, 1); 435 if (rc > 0) 436 rc = 0; 437 } 438 return rc; 439 } 440 441 /* 442 * MTFSFM: Forward space over 'count' file marks. 443 * The tape is positioned at the BOT (Begin Of Tape) side 444 * of the last skipped file mark. 445 */ 446 int 447 tape_std_mtfsfm(struct tape_device *device, int mt_count) 448 { 449 struct tape_request *request; 450 struct ccw1 *ccw; 451 int rc; 452 453 request = tape_alloc_request(mt_count + 2, 0); 454 if (IS_ERR(request)) 455 return PTR_ERR(request); 456 request->op = TO_FSF; 457 /* setup ccws */ 458 ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 459 device->modeset_byte); 460 ccw = tape_ccw_repeat(ccw, FORSPACEFILE, mt_count); 461 ccw = tape_ccw_end(ccw, NOP, 0, NULL); 462 /* execute it */ 463 rc = tape_do_io_free(device, request); 464 if (rc == 0) { 465 rc = tape_mtop(device, MTBSR, 1); 466 if (rc > 0) 467 rc = 0; 468 } 469 470 return rc; 471 } 472 473 /* 474 * MTREW: Rewind the tape. 475 */ 476 int 477 tape_std_mtrew(struct tape_device *device, int mt_count) 478 { 479 struct tape_request *request; 480 481 request = tape_alloc_request(3, 0); 482 if (IS_ERR(request)) 483 return PTR_ERR(request); 484 request->op = TO_REW; 485 /* setup ccws */ 486 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 487 device->modeset_byte); 488 tape_ccw_cc(request->cpaddr + 1, REWIND, 0, NULL); 489 tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL); 490 491 /* execute it */ 492 return tape_do_io_free(device, request); 493 } 494 495 /* 496 * MTOFFL: Rewind the tape and put the drive off-line. 497 * Implement 'rewind unload' 498 */ 499 int 500 tape_std_mtoffl(struct tape_device *device, int mt_count) 501 { 502 struct tape_request *request; 503 504 request = tape_alloc_request(3, 0); 505 if (IS_ERR(request)) 506 return PTR_ERR(request); 507 request->op = TO_RUN; 508 /* setup ccws */ 509 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 510 tape_ccw_cc(request->cpaddr + 1, REWIND_UNLOAD, 0, NULL); 511 tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL); 512 513 /* execute it */ 514 return tape_do_io_free(device, request); 515 } 516 517 /* 518 * MTNOP: 'No operation'. 519 */ 520 int 521 tape_std_mtnop(struct tape_device *device, int mt_count) 522 { 523 struct tape_request *request; 524 525 request = tape_alloc_request(2, 0); 526 if (IS_ERR(request)) 527 return PTR_ERR(request); 528 request->op = TO_NOP; 529 /* setup ccws */ 530 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 531 tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL); 532 /* execute it */ 533 return tape_do_io_free(device, request); 534 } 535 536 /* 537 * MTEOM: positions at the end of the portion of the tape already used 538 * for recordind data. MTEOM positions after the last file mark, ready for 539 * appending another file. 540 */ 541 int 542 tape_std_mteom(struct tape_device *device, int mt_count) 543 { 544 int rc; 545 546 /* 547 * Seek from the beginning of tape (rewind). 548 */ 549 if ((rc = tape_mtop(device, MTREW, 1)) < 0) 550 return rc; 551 552 /* 553 * The logical end of volume is given by two sewuential tapemarks. 554 * Look for this by skipping to the next file (over one tapemark) 555 * and then test for another one (fsr returns 1 if a tapemark was 556 * encountered). 557 */ 558 do { 559 if ((rc = tape_mtop(device, MTFSF, 1)) < 0) 560 return rc; 561 if ((rc = tape_mtop(device, MTFSR, 1)) < 0) 562 return rc; 563 } while (rc == 0); 564 565 return tape_mtop(device, MTBSR, 1); 566 } 567 568 /* 569 * MTRETEN: Retension the tape, i.e. forward space to end of tape and rewind. 570 */ 571 int 572 tape_std_mtreten(struct tape_device *device, int mt_count) 573 { 574 struct tape_request *request; 575 int rc; 576 577 request = tape_alloc_request(4, 0); 578 if (IS_ERR(request)) 579 return PTR_ERR(request); 580 request->op = TO_FSF; 581 /* setup ccws */ 582 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 583 tape_ccw_cc(request->cpaddr + 1,FORSPACEFILE, 0, NULL); 584 tape_ccw_cc(request->cpaddr + 2, NOP, 0, NULL); 585 tape_ccw_end(request->cpaddr + 3, CCW_CMD_TIC, 0, request->cpaddr); 586 /* execute it, MTRETEN rc gets ignored */ 587 rc = tape_do_io_interruptible(device, request); 588 tape_free_request(request); 589 return tape_mtop(device, MTREW, 1); 590 } 591 592 /* 593 * MTERASE: erases the tape. 594 */ 595 int 596 tape_std_mterase(struct tape_device *device, int mt_count) 597 { 598 struct tape_request *request; 599 600 request = tape_alloc_request(6, 0); 601 if (IS_ERR(request)) 602 return PTR_ERR(request); 603 request->op = TO_DSE; 604 /* setup ccws */ 605 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 606 tape_ccw_cc(request->cpaddr + 1, REWIND, 0, NULL); 607 tape_ccw_cc(request->cpaddr + 2, ERASE_GAP, 0, NULL); 608 tape_ccw_cc(request->cpaddr + 3, DATA_SEC_ERASE, 0, NULL); 609 tape_ccw_cc(request->cpaddr + 4, REWIND, 0, NULL); 610 tape_ccw_end(request->cpaddr + 5, NOP, 0, NULL); 611 612 /* execute it */ 613 return tape_do_io_free(device, request); 614 } 615 616 /* 617 * MTUNLOAD: Rewind the tape and unload it. 618 */ 619 int 620 tape_std_mtunload(struct tape_device *device, int mt_count) 621 { 622 return tape_mtop(device, MTOFFL, mt_count); 623 } 624 625 /* 626 * MTCOMPRESSION: used to enable compression. 627 * Sets the IDRC on/off. 628 */ 629 int 630 tape_std_mtcompression(struct tape_device *device, int mt_count) 631 { 632 struct tape_request *request; 633 634 if (mt_count < 0 || mt_count > 1) { 635 DBF_EXCEPTION(6, "xcom parm\n"); 636 if (*device->modeset_byte & 0x08) 637 PRINT_INFO("(%s) Compression is currently on\n", 638 dev_name(&device->cdev->dev)); 639 else 640 PRINT_INFO("(%s) Compression is currently off\n", 641 dev_name(&device->cdev->dev)); 642 PRINT_INFO("Use 1 to switch compression on, 0 to " 643 "switch it off\n"); 644 return -EINVAL; 645 } 646 request = tape_alloc_request(2, 0); 647 if (IS_ERR(request)) 648 return PTR_ERR(request); 649 request->op = TO_NOP; 650 /* setup ccws */ 651 if (mt_count == 0) 652 *device->modeset_byte &= ~0x08; 653 else 654 *device->modeset_byte |= 0x08; 655 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 656 tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL); 657 /* execute it */ 658 return tape_do_io_free(device, request); 659 } 660 661 /* 662 * Read Block 663 */ 664 struct tape_request * 665 tape_std_read_block(struct tape_device *device, size_t count) 666 { 667 struct tape_request *request; 668 669 /* 670 * We have to alloc 4 ccws in order to be able to transform request 671 * into a read backward request in error case. 672 */ 673 request = tape_alloc_request(4, 0); 674 if (IS_ERR(request)) { 675 DBF_EXCEPTION(6, "xrbl fail"); 676 return request; 677 } 678 request->op = TO_RFO; 679 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 680 tape_ccw_end_idal(request->cpaddr + 1, READ_FORWARD, 681 device->char_data.idal_buf); 682 DBF_EVENT(6, "xrbl ccwg\n"); 683 return request; 684 } 685 686 /* 687 * Read Block backward transformation function. 688 */ 689 void 690 tape_std_read_backward(struct tape_device *device, struct tape_request *request) 691 { 692 /* 693 * We have allocated 4 ccws in tape_std_read, so we can now 694 * transform the request to a read backward, followed by a 695 * forward space block. 696 */ 697 request->op = TO_RBA; 698 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 699 tape_ccw_cc_idal(request->cpaddr + 1, READ_BACKWARD, 700 device->char_data.idal_buf); 701 tape_ccw_cc(request->cpaddr + 2, FORSPACEBLOCK, 0, NULL); 702 tape_ccw_end(request->cpaddr + 3, NOP, 0, NULL); 703 DBF_EVENT(6, "xrop ccwg");} 704 705 /* 706 * Write Block 707 */ 708 struct tape_request * 709 tape_std_write_block(struct tape_device *device, size_t count) 710 { 711 struct tape_request *request; 712 713 request = tape_alloc_request(2, 0); 714 if (IS_ERR(request)) { 715 DBF_EXCEPTION(6, "xwbl fail\n"); 716 return request; 717 } 718 request->op = TO_WRI; 719 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 720 tape_ccw_end_idal(request->cpaddr + 1, WRITE_CMD, 721 device->char_data.idal_buf); 722 DBF_EVENT(6, "xwbl ccwg\n"); 723 return request; 724 } 725 726 /* 727 * This routine is called by frontend after an ENOSP on write 728 */ 729 void 730 tape_std_process_eov(struct tape_device *device) 731 { 732 /* 733 * End of volume: We have to backspace the last written record, then 734 * we TRY to write a tapemark and then backspace over the written TM 735 */ 736 if (tape_mtop(device, MTBSR, 1) == 0 && 737 tape_mtop(device, MTWEOF, 1) == 0) { 738 tape_mtop(device, MTBSR, 1); 739 } 740 } 741 742 EXPORT_SYMBOL(tape_std_assign); 743 EXPORT_SYMBOL(tape_std_unassign); 744 EXPORT_SYMBOL(tape_std_display); 745 EXPORT_SYMBOL(tape_std_read_block_id); 746 EXPORT_SYMBOL(tape_std_mtload); 747 EXPORT_SYMBOL(tape_std_mtsetblk); 748 EXPORT_SYMBOL(tape_std_mtreset); 749 EXPORT_SYMBOL(tape_std_mtfsf); 750 EXPORT_SYMBOL(tape_std_mtfsr); 751 EXPORT_SYMBOL(tape_std_mtbsr); 752 EXPORT_SYMBOL(tape_std_mtweof); 753 EXPORT_SYMBOL(tape_std_mtbsfm); 754 EXPORT_SYMBOL(tape_std_mtbsf); 755 EXPORT_SYMBOL(tape_std_mtfsfm); 756 EXPORT_SYMBOL(tape_std_mtrew); 757 EXPORT_SYMBOL(tape_std_mtoffl); 758 EXPORT_SYMBOL(tape_std_mtnop); 759 EXPORT_SYMBOL(tape_std_mteom); 760 EXPORT_SYMBOL(tape_std_mtreten); 761 EXPORT_SYMBOL(tape_std_mterase); 762 EXPORT_SYMBOL(tape_std_mtunload); 763 EXPORT_SYMBOL(tape_std_mtcompression); 764 EXPORT_SYMBOL(tape_std_read_block); 765 EXPORT_SYMBOL(tape_std_read_backward); 766 EXPORT_SYMBOL(tape_std_write_block); 767 EXPORT_SYMBOL(tape_std_process_eov); 768