0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #define KMSG_COMPONENT "tape"
0015 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
0016
0017 #include <linux/stddef.h>
0018 #include <linux/kernel.h>
0019 #include <linux/bio.h>
0020 #include <linux/timer.h>
0021
0022 #include <asm/types.h>
0023 #include <asm/idals.h>
0024 #include <asm/ebcdic.h>
0025 #include <asm/tape390.h>
0026
0027 #define TAPE_DBF_AREA tape_core_dbf
0028
0029 #include "tape.h"
0030 #include "tape_std.h"
0031
0032
0033
0034
0035 static void
0036 tape_std_assign_timeout(struct timer_list *t)
0037 {
0038 struct tape_request * request = from_timer(request, t, timer);
0039 struct tape_device * device = request->device;
0040 int rc;
0041
0042 BUG_ON(!device);
0043
0044 DBF_EVENT(3, "%08x: Assignment timeout. Device busy.\n",
0045 device->cdev_id);
0046 rc = tape_cancel_io(device, request);
0047 if(rc)
0048 DBF_EVENT(3, "(%08x): Assign timeout: Cancel failed with rc = "
0049 "%i\n", device->cdev_id, rc);
0050 }
0051
0052 int
0053 tape_std_assign(struct tape_device *device)
0054 {
0055 int rc;
0056 struct tape_request *request;
0057
0058 request = tape_alloc_request(2, 11);
0059 if (IS_ERR(request))
0060 return PTR_ERR(request);
0061
0062 request->op = TO_ASSIGN;
0063 tape_ccw_cc(request->cpaddr, ASSIGN, 11, request->cpdata);
0064 tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL);
0065
0066
0067
0068
0069
0070
0071 timer_setup(&request->timer, tape_std_assign_timeout, 0);
0072 mod_timer(&request->timer, jiffies + msecs_to_jiffies(2000));
0073
0074 rc = tape_do_io_interruptible(device, request);
0075
0076 del_timer_sync(&request->timer);
0077
0078 if (rc != 0) {
0079 DBF_EVENT(3, "%08x: assign failed - device might be busy\n",
0080 device->cdev_id);
0081 } else {
0082 DBF_EVENT(3, "%08x: Tape assigned\n", device->cdev_id);
0083 }
0084 tape_free_request(request);
0085 return rc;
0086 }
0087
0088
0089
0090
0091 int
0092 tape_std_unassign (struct tape_device *device)
0093 {
0094 int rc;
0095 struct tape_request *request;
0096
0097 if (device->tape_state == TS_NOT_OPER) {
0098 DBF_EVENT(3, "(%08x): Can't unassign device\n",
0099 device->cdev_id);
0100 return -EIO;
0101 }
0102
0103 request = tape_alloc_request(2, 11);
0104 if (IS_ERR(request))
0105 return PTR_ERR(request);
0106
0107 request->op = TO_UNASSIGN;
0108 tape_ccw_cc(request->cpaddr, UNASSIGN, 11, request->cpdata);
0109 tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL);
0110
0111 if ((rc = tape_do_io(device, request)) != 0) {
0112 DBF_EVENT(3, "%08x: Unassign failed\n", device->cdev_id);
0113 } else {
0114 DBF_EVENT(3, "%08x: Tape unassigned\n", device->cdev_id);
0115 }
0116 tape_free_request(request);
0117 return rc;
0118 }
0119
0120
0121
0122
0123 int
0124 tape_std_display(struct tape_device *device, struct display_struct *disp)
0125 {
0126 struct tape_request *request;
0127 int rc;
0128
0129 request = tape_alloc_request(2, 17);
0130 if (IS_ERR(request)) {
0131 DBF_EVENT(3, "TAPE: load display failed\n");
0132 return PTR_ERR(request);
0133 }
0134 request->op = TO_DIS;
0135
0136 *(unsigned char *) request->cpdata = disp->cntrl;
0137 DBF_EVENT(5, "TAPE: display cntrl=%04x\n", disp->cntrl);
0138 memcpy(((unsigned char *) request->cpdata) + 1, disp->message1, 8);
0139 memcpy(((unsigned char *) request->cpdata) + 9, disp->message2, 8);
0140 ASCEBC(((unsigned char*) request->cpdata) + 1, 16);
0141
0142 tape_ccw_cc(request->cpaddr, LOAD_DISPLAY, 17, request->cpdata);
0143 tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL);
0144
0145 rc = tape_do_io_interruptible(device, request);
0146 tape_free_request(request);
0147 return rc;
0148 }
0149
0150
0151
0152
0153 int
0154 tape_std_read_block_id(struct tape_device *device, __u64 *id)
0155 {
0156 struct tape_request *request;
0157 int rc;
0158
0159 request = tape_alloc_request(3, 8);
0160 if (IS_ERR(request))
0161 return PTR_ERR(request);
0162 request->op = TO_RBI;
0163
0164 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
0165 tape_ccw_cc(request->cpaddr + 1, READ_BLOCK_ID, 8, request->cpdata);
0166 tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL);
0167
0168 rc = tape_do_io(device, request);
0169 if (rc == 0)
0170
0171 *id = *(__u64 *) request->cpdata;
0172 tape_free_request(request);
0173 return rc;
0174 }
0175
0176 int
0177 tape_std_terminate_write(struct tape_device *device)
0178 {
0179 int rc;
0180
0181 if(device->required_tapemarks == 0)
0182 return 0;
0183
0184 DBF_LH(5, "tape%d: terminate write %dxEOF\n", device->first_minor,
0185 device->required_tapemarks);
0186
0187 rc = tape_mtop(device, MTWEOF, device->required_tapemarks);
0188 if (rc)
0189 return rc;
0190
0191 device->required_tapemarks = 0;
0192 return tape_mtop(device, MTBSR, 1);
0193 }
0194
0195
0196
0197
0198
0199
0200 int
0201 tape_std_mtload(struct tape_device *device, int count)
0202 {
0203 return wait_event_interruptible(device->state_change_wq,
0204 (device->medium_state == MS_LOADED));
0205 }
0206
0207
0208
0209
0210 int
0211 tape_std_mtsetblk(struct tape_device *device, int count)
0212 {
0213 struct idal_buffer *new;
0214
0215 DBF_LH(6, "tape_std_mtsetblk(%d)\n", count);
0216 if (count <= 0) {
0217
0218
0219
0220
0221
0222 device->char_data.block_size = 0;
0223 return 0;
0224 }
0225 if (device->char_data.idal_buf != NULL &&
0226 device->char_data.idal_buf->size == count)
0227
0228 return 0;
0229
0230 if (count > MAX_BLOCKSIZE) {
0231 DBF_EVENT(3, "Invalid block size (%d > %d) given.\n",
0232 count, MAX_BLOCKSIZE);
0233 return -EINVAL;
0234 }
0235
0236
0237 new = idal_buffer_alloc(count, 0);
0238 if (IS_ERR(new))
0239 return -ENOMEM;
0240 if (device->char_data.idal_buf != NULL)
0241 idal_buffer_free(device->char_data.idal_buf);
0242 device->char_data.idal_buf = new;
0243 device->char_data.block_size = count;
0244
0245 DBF_LH(6, "new blocksize is %d\n", device->char_data.block_size);
0246
0247 return 0;
0248 }
0249
0250
0251
0252
0253 int
0254 tape_std_mtreset(struct tape_device *device, int count)
0255 {
0256 DBF_EVENT(6, "TCHAR:devreset:\n");
0257 device->char_data.block_size = 0;
0258 return 0;
0259 }
0260
0261
0262
0263
0264
0265 int
0266 tape_std_mtfsf(struct tape_device *device, int mt_count)
0267 {
0268 struct tape_request *request;
0269 struct ccw1 *ccw;
0270
0271 request = tape_alloc_request(mt_count + 2, 0);
0272 if (IS_ERR(request))
0273 return PTR_ERR(request);
0274 request->op = TO_FSF;
0275
0276 ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
0277 device->modeset_byte);
0278 ccw = tape_ccw_repeat(ccw, FORSPACEFILE, mt_count);
0279 ccw = tape_ccw_end(ccw, NOP, 0, NULL);
0280
0281
0282 return tape_do_io_free(device, request);
0283 }
0284
0285
0286
0287
0288
0289 int
0290 tape_std_mtfsr(struct tape_device *device, int mt_count)
0291 {
0292 struct tape_request *request;
0293 struct ccw1 *ccw;
0294 int rc;
0295
0296 request = tape_alloc_request(mt_count + 2, 0);
0297 if (IS_ERR(request))
0298 return PTR_ERR(request);
0299 request->op = TO_FSB;
0300
0301 ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
0302 device->modeset_byte);
0303 ccw = tape_ccw_repeat(ccw, FORSPACEBLOCK, mt_count);
0304 ccw = tape_ccw_end(ccw, NOP, 0, NULL);
0305
0306
0307 rc = tape_do_io(device, request);
0308 if (rc == 0 && request->rescnt > 0) {
0309 DBF_LH(3, "FSR over tapemark\n");
0310 rc = 1;
0311 }
0312 tape_free_request(request);
0313
0314 return rc;
0315 }
0316
0317
0318
0319
0320
0321 int
0322 tape_std_mtbsr(struct tape_device *device, int mt_count)
0323 {
0324 struct tape_request *request;
0325 struct ccw1 *ccw;
0326 int rc;
0327
0328 request = tape_alloc_request(mt_count + 2, 0);
0329 if (IS_ERR(request))
0330 return PTR_ERR(request);
0331 request->op = TO_BSB;
0332
0333 ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
0334 device->modeset_byte);
0335 ccw = tape_ccw_repeat(ccw, BACKSPACEBLOCK, mt_count);
0336 ccw = tape_ccw_end(ccw, NOP, 0, NULL);
0337
0338
0339 rc = tape_do_io(device, request);
0340 if (rc == 0 && request->rescnt > 0) {
0341 DBF_LH(3, "BSR over tapemark\n");
0342 rc = 1;
0343 }
0344 tape_free_request(request);
0345
0346 return rc;
0347 }
0348
0349
0350
0351
0352 int
0353 tape_std_mtweof(struct tape_device *device, int mt_count)
0354 {
0355 struct tape_request *request;
0356 struct ccw1 *ccw;
0357
0358 request = tape_alloc_request(mt_count + 2, 0);
0359 if (IS_ERR(request))
0360 return PTR_ERR(request);
0361 request->op = TO_WTM;
0362
0363 ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
0364 device->modeset_byte);
0365 ccw = tape_ccw_repeat(ccw, WRITETAPEMARK, mt_count);
0366 ccw = tape_ccw_end(ccw, NOP, 0, NULL);
0367
0368
0369 return tape_do_io_free(device, request);
0370 }
0371
0372
0373
0374
0375
0376
0377 int
0378 tape_std_mtbsfm(struct tape_device *device, int mt_count)
0379 {
0380 struct tape_request *request;
0381 struct ccw1 *ccw;
0382
0383 request = tape_alloc_request(mt_count + 2, 0);
0384 if (IS_ERR(request))
0385 return PTR_ERR(request);
0386 request->op = TO_BSF;
0387
0388 ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
0389 device->modeset_byte);
0390 ccw = tape_ccw_repeat(ccw, BACKSPACEFILE, mt_count);
0391 ccw = tape_ccw_end(ccw, NOP, 0, NULL);
0392
0393
0394 return tape_do_io_free(device, request);
0395 }
0396
0397
0398
0399
0400
0401 int
0402 tape_std_mtbsf(struct tape_device *device, int mt_count)
0403 {
0404 struct tape_request *request;
0405 struct ccw1 *ccw;
0406 int rc;
0407
0408 request = tape_alloc_request(mt_count + 2, 0);
0409 if (IS_ERR(request))
0410 return PTR_ERR(request);
0411 request->op = TO_BSF;
0412
0413 ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
0414 device->modeset_byte);
0415 ccw = tape_ccw_repeat(ccw, BACKSPACEFILE, mt_count);
0416 ccw = tape_ccw_end(ccw, NOP, 0, NULL);
0417
0418 rc = tape_do_io_free(device, request);
0419 if (rc == 0) {
0420 rc = tape_mtop(device, MTFSR, 1);
0421 if (rc > 0)
0422 rc = 0;
0423 }
0424 return rc;
0425 }
0426
0427
0428
0429
0430
0431
0432 int
0433 tape_std_mtfsfm(struct tape_device *device, int mt_count)
0434 {
0435 struct tape_request *request;
0436 struct ccw1 *ccw;
0437 int rc;
0438
0439 request = tape_alloc_request(mt_count + 2, 0);
0440 if (IS_ERR(request))
0441 return PTR_ERR(request);
0442 request->op = TO_FSF;
0443
0444 ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
0445 device->modeset_byte);
0446 ccw = tape_ccw_repeat(ccw, FORSPACEFILE, mt_count);
0447 ccw = tape_ccw_end(ccw, NOP, 0, NULL);
0448
0449 rc = tape_do_io_free(device, request);
0450 if (rc == 0) {
0451 rc = tape_mtop(device, MTBSR, 1);
0452 if (rc > 0)
0453 rc = 0;
0454 }
0455
0456 return rc;
0457 }
0458
0459
0460
0461
0462 int
0463 tape_std_mtrew(struct tape_device *device, int mt_count)
0464 {
0465 struct tape_request *request;
0466
0467 request = tape_alloc_request(3, 0);
0468 if (IS_ERR(request))
0469 return PTR_ERR(request);
0470 request->op = TO_REW;
0471
0472 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1,
0473 device->modeset_byte);
0474 tape_ccw_cc(request->cpaddr + 1, REWIND, 0, NULL);
0475 tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL);
0476
0477
0478 return tape_do_io_free(device, request);
0479 }
0480
0481
0482
0483
0484
0485 int
0486 tape_std_mtoffl(struct tape_device *device, int mt_count)
0487 {
0488 struct tape_request *request;
0489
0490 request = tape_alloc_request(3, 0);
0491 if (IS_ERR(request))
0492 return PTR_ERR(request);
0493 request->op = TO_RUN;
0494
0495 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
0496 tape_ccw_cc(request->cpaddr + 1, REWIND_UNLOAD, 0, NULL);
0497 tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL);
0498
0499
0500 return tape_do_io_free(device, request);
0501 }
0502
0503
0504
0505
0506 int
0507 tape_std_mtnop(struct tape_device *device, int mt_count)
0508 {
0509 struct tape_request *request;
0510
0511 request = tape_alloc_request(2, 0);
0512 if (IS_ERR(request))
0513 return PTR_ERR(request);
0514 request->op = TO_NOP;
0515
0516 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
0517 tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL);
0518
0519 return tape_do_io_free(device, request);
0520 }
0521
0522
0523
0524
0525
0526
0527 int
0528 tape_std_mteom(struct tape_device *device, int mt_count)
0529 {
0530 int rc;
0531
0532
0533
0534
0535 if ((rc = tape_mtop(device, MTREW, 1)) < 0)
0536 return rc;
0537
0538
0539
0540
0541
0542
0543
0544 do {
0545 if ((rc = tape_mtop(device, MTFSF, 1)) < 0)
0546 return rc;
0547 if ((rc = tape_mtop(device, MTFSR, 1)) < 0)
0548 return rc;
0549 } while (rc == 0);
0550
0551 return tape_mtop(device, MTBSR, 1);
0552 }
0553
0554
0555
0556
0557 int
0558 tape_std_mtreten(struct tape_device *device, int mt_count)
0559 {
0560 struct tape_request *request;
0561
0562 request = tape_alloc_request(4, 0);
0563 if (IS_ERR(request))
0564 return PTR_ERR(request);
0565 request->op = TO_FSF;
0566
0567 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
0568 tape_ccw_cc(request->cpaddr + 1,FORSPACEFILE, 0, NULL);
0569 tape_ccw_cc(request->cpaddr + 2, NOP, 0, NULL);
0570 tape_ccw_end(request->cpaddr + 3, CCW_CMD_TIC, 0, request->cpaddr);
0571
0572 tape_do_io_interruptible(device, request);
0573 tape_free_request(request);
0574 return tape_mtop(device, MTREW, 1);
0575 }
0576
0577
0578
0579
0580 int
0581 tape_std_mterase(struct tape_device *device, int mt_count)
0582 {
0583 struct tape_request *request;
0584
0585 request = tape_alloc_request(6, 0);
0586 if (IS_ERR(request))
0587 return PTR_ERR(request);
0588 request->op = TO_DSE;
0589
0590 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
0591 tape_ccw_cc(request->cpaddr + 1, REWIND, 0, NULL);
0592 tape_ccw_cc(request->cpaddr + 2, ERASE_GAP, 0, NULL);
0593 tape_ccw_cc(request->cpaddr + 3, DATA_SEC_ERASE, 0, NULL);
0594 tape_ccw_cc(request->cpaddr + 4, REWIND, 0, NULL);
0595 tape_ccw_end(request->cpaddr + 5, NOP, 0, NULL);
0596
0597
0598 return tape_do_io_free(device, request);
0599 }
0600
0601
0602
0603
0604 int
0605 tape_std_mtunload(struct tape_device *device, int mt_count)
0606 {
0607 return tape_mtop(device, MTOFFL, mt_count);
0608 }
0609
0610
0611
0612
0613
0614 int
0615 tape_std_mtcompression(struct tape_device *device, int mt_count)
0616 {
0617 struct tape_request *request;
0618
0619 if (mt_count < 0 || mt_count > 1) {
0620 DBF_EXCEPTION(6, "xcom parm\n");
0621 return -EINVAL;
0622 }
0623 request = tape_alloc_request(2, 0);
0624 if (IS_ERR(request))
0625 return PTR_ERR(request);
0626 request->op = TO_NOP;
0627
0628 if (mt_count == 0)
0629 *device->modeset_byte &= ~0x08;
0630 else
0631 *device->modeset_byte |= 0x08;
0632 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
0633 tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL);
0634
0635 return tape_do_io_free(device, request);
0636 }
0637
0638
0639
0640
0641 struct tape_request *
0642 tape_std_read_block(struct tape_device *device, size_t count)
0643 {
0644 struct tape_request *request;
0645
0646
0647
0648
0649
0650 request = tape_alloc_request(4, 0);
0651 if (IS_ERR(request)) {
0652 DBF_EXCEPTION(6, "xrbl fail");
0653 return request;
0654 }
0655 request->op = TO_RFO;
0656 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
0657 tape_ccw_end_idal(request->cpaddr + 1, READ_FORWARD,
0658 device->char_data.idal_buf);
0659 DBF_EVENT(6, "xrbl ccwg\n");
0660 return request;
0661 }
0662
0663
0664
0665
0666 void
0667 tape_std_read_backward(struct tape_device *device, struct tape_request *request)
0668 {
0669
0670
0671
0672
0673
0674 request->op = TO_RBA;
0675 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
0676 tape_ccw_cc_idal(request->cpaddr + 1, READ_BACKWARD,
0677 device->char_data.idal_buf);
0678 tape_ccw_cc(request->cpaddr + 2, FORSPACEBLOCK, 0, NULL);
0679 tape_ccw_end(request->cpaddr + 3, NOP, 0, NULL);
0680 DBF_EVENT(6, "xrop ccwg");}
0681
0682
0683
0684
0685 struct tape_request *
0686 tape_std_write_block(struct tape_device *device, size_t count)
0687 {
0688 struct tape_request *request;
0689
0690 request = tape_alloc_request(2, 0);
0691 if (IS_ERR(request)) {
0692 DBF_EXCEPTION(6, "xwbl fail\n");
0693 return request;
0694 }
0695 request->op = TO_WRI;
0696 tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte);
0697 tape_ccw_end_idal(request->cpaddr + 1, WRITE_CMD,
0698 device->char_data.idal_buf);
0699 DBF_EVENT(6, "xwbl ccwg\n");
0700 return request;
0701 }
0702
0703
0704
0705
0706 void
0707 tape_std_process_eov(struct tape_device *device)
0708 {
0709
0710
0711
0712
0713 if (tape_mtop(device, MTBSR, 1) == 0 &&
0714 tape_mtop(device, MTWEOF, 1) == 0) {
0715 tape_mtop(device, MTBSR, 1);
0716 }
0717 }
0718
0719 EXPORT_SYMBOL(tape_std_assign);
0720 EXPORT_SYMBOL(tape_std_unassign);
0721 EXPORT_SYMBOL(tape_std_display);
0722 EXPORT_SYMBOL(tape_std_read_block_id);
0723 EXPORT_SYMBOL(tape_std_mtload);
0724 EXPORT_SYMBOL(tape_std_mtsetblk);
0725 EXPORT_SYMBOL(tape_std_mtreset);
0726 EXPORT_SYMBOL(tape_std_mtfsf);
0727 EXPORT_SYMBOL(tape_std_mtfsr);
0728 EXPORT_SYMBOL(tape_std_mtbsr);
0729 EXPORT_SYMBOL(tape_std_mtweof);
0730 EXPORT_SYMBOL(tape_std_mtbsfm);
0731 EXPORT_SYMBOL(tape_std_mtbsf);
0732 EXPORT_SYMBOL(tape_std_mtfsfm);
0733 EXPORT_SYMBOL(tape_std_mtrew);
0734 EXPORT_SYMBOL(tape_std_mtoffl);
0735 EXPORT_SYMBOL(tape_std_mtnop);
0736 EXPORT_SYMBOL(tape_std_mteom);
0737 EXPORT_SYMBOL(tape_std_mtreten);
0738 EXPORT_SYMBOL(tape_std_mterase);
0739 EXPORT_SYMBOL(tape_std_mtunload);
0740 EXPORT_SYMBOL(tape_std_mtcompression);
0741 EXPORT_SYMBOL(tape_std_read_block);
0742 EXPORT_SYMBOL(tape_std_read_backward);
0743 EXPORT_SYMBOL(tape_std_write_block);
0744 EXPORT_SYMBOL(tape_std_process_eov);