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