18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * standard tape device functions for ibm tapes. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * S390 and zSeries version 68c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2001, 2002 78c2ecf20Sopenharmony_ci * Author(s): Carsten Otte <cotte@de.ibm.com> 88c2ecf20Sopenharmony_ci * Michael Holzheu <holzheu@de.ibm.com> 98c2ecf20Sopenharmony_ci * Tuan Ngo-Anh <ngoanh@de.ibm.com> 108c2ecf20Sopenharmony_ci * Martin Schwidefsky <schwidefsky@de.ibm.com> 118c2ecf20Sopenharmony_ci * Stefan Bader <shbader@de.ibm.com> 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define KMSG_COMPONENT "tape" 158c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <linux/stddef.h> 188c2ecf20Sopenharmony_ci#include <linux/kernel.h> 198c2ecf20Sopenharmony_ci#include <linux/bio.h> 208c2ecf20Sopenharmony_ci#include <linux/timer.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include <asm/types.h> 238c2ecf20Sopenharmony_ci#include <asm/idals.h> 248c2ecf20Sopenharmony_ci#include <asm/ebcdic.h> 258c2ecf20Sopenharmony_ci#include <asm/tape390.h> 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci#define TAPE_DBF_AREA tape_core_dbf 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include "tape.h" 308c2ecf20Sopenharmony_ci#include "tape_std.h" 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* 338c2ecf20Sopenharmony_ci * tape_std_assign 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_cistatic void 368c2ecf20Sopenharmony_citape_std_assign_timeout(struct timer_list *t) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci struct tape_request * request = from_timer(request, t, timer); 398c2ecf20Sopenharmony_ci struct tape_device * device = request->device; 408c2ecf20Sopenharmony_ci int rc; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci BUG_ON(!device); 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci DBF_EVENT(3, "%08x: Assignment timeout. Device busy.\n", 458c2ecf20Sopenharmony_ci device->cdev_id); 468c2ecf20Sopenharmony_ci rc = tape_cancel_io(device, request); 478c2ecf20Sopenharmony_ci if(rc) 488c2ecf20Sopenharmony_ci DBF_EVENT(3, "(%08x): Assign timeout: Cancel failed with rc = " 498c2ecf20Sopenharmony_ci "%i\n", device->cdev_id, rc); 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ciint 538c2ecf20Sopenharmony_citape_std_assign(struct tape_device *device) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci int rc; 568c2ecf20Sopenharmony_ci struct tape_request *request; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci request = tape_alloc_request(2, 11); 598c2ecf20Sopenharmony_ci if (IS_ERR(request)) 608c2ecf20Sopenharmony_ci return PTR_ERR(request); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci request->op = TO_ASSIGN; 638c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr, ASSIGN, 11, request->cpdata); 648c2ecf20Sopenharmony_ci tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* 678c2ecf20Sopenharmony_ci * The assign command sometimes blocks if the device is assigned 688c2ecf20Sopenharmony_ci * to another host (actually this shouldn't happen but it does). 698c2ecf20Sopenharmony_ci * So we set up a timeout for this call. 708c2ecf20Sopenharmony_ci */ 718c2ecf20Sopenharmony_ci timer_setup(&request->timer, tape_std_assign_timeout, 0); 728c2ecf20Sopenharmony_ci mod_timer(&request->timer, jiffies + msecs_to_jiffies(2000)); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci rc = tape_do_io_interruptible(device, request); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci del_timer_sync(&request->timer); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci if (rc != 0) { 798c2ecf20Sopenharmony_ci DBF_EVENT(3, "%08x: assign failed - device might be busy\n", 808c2ecf20Sopenharmony_ci device->cdev_id); 818c2ecf20Sopenharmony_ci } else { 828c2ecf20Sopenharmony_ci DBF_EVENT(3, "%08x: Tape assigned\n", device->cdev_id); 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci tape_free_request(request); 858c2ecf20Sopenharmony_ci return rc; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci/* 898c2ecf20Sopenharmony_ci * tape_std_unassign 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_ciint 928c2ecf20Sopenharmony_citape_std_unassign (struct tape_device *device) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci int rc; 958c2ecf20Sopenharmony_ci struct tape_request *request; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci if (device->tape_state == TS_NOT_OPER) { 988c2ecf20Sopenharmony_ci DBF_EVENT(3, "(%08x): Can't unassign device\n", 998c2ecf20Sopenharmony_ci device->cdev_id); 1008c2ecf20Sopenharmony_ci return -EIO; 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci request = tape_alloc_request(2, 11); 1048c2ecf20Sopenharmony_ci if (IS_ERR(request)) 1058c2ecf20Sopenharmony_ci return PTR_ERR(request); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci request->op = TO_UNASSIGN; 1088c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr, UNASSIGN, 11, request->cpdata); 1098c2ecf20Sopenharmony_ci tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci if ((rc = tape_do_io(device, request)) != 0) { 1128c2ecf20Sopenharmony_ci DBF_EVENT(3, "%08x: Unassign failed\n", device->cdev_id); 1138c2ecf20Sopenharmony_ci } else { 1148c2ecf20Sopenharmony_ci DBF_EVENT(3, "%08x: Tape unassigned\n", device->cdev_id); 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci tape_free_request(request); 1178c2ecf20Sopenharmony_ci return rc; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci/* 1218c2ecf20Sopenharmony_ci * TAPE390_DISPLAY: Show a string on the tape display. 1228c2ecf20Sopenharmony_ci */ 1238c2ecf20Sopenharmony_ciint 1248c2ecf20Sopenharmony_citape_std_display(struct tape_device *device, struct display_struct *disp) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci struct tape_request *request; 1278c2ecf20Sopenharmony_ci int rc; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci request = tape_alloc_request(2, 17); 1308c2ecf20Sopenharmony_ci if (IS_ERR(request)) { 1318c2ecf20Sopenharmony_ci DBF_EVENT(3, "TAPE: load display failed\n"); 1328c2ecf20Sopenharmony_ci return PTR_ERR(request); 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci request->op = TO_DIS; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci *(unsigned char *) request->cpdata = disp->cntrl; 1378c2ecf20Sopenharmony_ci DBF_EVENT(5, "TAPE: display cntrl=%04x\n", disp->cntrl); 1388c2ecf20Sopenharmony_ci memcpy(((unsigned char *) request->cpdata) + 1, disp->message1, 8); 1398c2ecf20Sopenharmony_ci memcpy(((unsigned char *) request->cpdata) + 9, disp->message2, 8); 1408c2ecf20Sopenharmony_ci ASCEBC(((unsigned char*) request->cpdata) + 1, 16); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr, LOAD_DISPLAY, 17, request->cpdata); 1438c2ecf20Sopenharmony_ci tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci rc = tape_do_io_interruptible(device, request); 1468c2ecf20Sopenharmony_ci tape_free_request(request); 1478c2ecf20Sopenharmony_ci return rc; 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci/* 1518c2ecf20Sopenharmony_ci * Read block id. 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_ciint 1548c2ecf20Sopenharmony_citape_std_read_block_id(struct tape_device *device, __u64 *id) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci struct tape_request *request; 1578c2ecf20Sopenharmony_ci int rc; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci request = tape_alloc_request(3, 8); 1608c2ecf20Sopenharmony_ci if (IS_ERR(request)) 1618c2ecf20Sopenharmony_ci return PTR_ERR(request); 1628c2ecf20Sopenharmony_ci request->op = TO_RBI; 1638c2ecf20Sopenharmony_ci /* setup ccws */ 1648c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 1658c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr + 1, READ_BLOCK_ID, 8, request->cpdata); 1668c2ecf20Sopenharmony_ci tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL); 1678c2ecf20Sopenharmony_ci /* execute it */ 1688c2ecf20Sopenharmony_ci rc = tape_do_io(device, request); 1698c2ecf20Sopenharmony_ci if (rc == 0) 1708c2ecf20Sopenharmony_ci /* Get result from read buffer. */ 1718c2ecf20Sopenharmony_ci *id = *(__u64 *) request->cpdata; 1728c2ecf20Sopenharmony_ci tape_free_request(request); 1738c2ecf20Sopenharmony_ci return rc; 1748c2ecf20Sopenharmony_ci} 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ciint 1778c2ecf20Sopenharmony_citape_std_terminate_write(struct tape_device *device) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci int rc; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci if(device->required_tapemarks == 0) 1828c2ecf20Sopenharmony_ci return 0; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci DBF_LH(5, "tape%d: terminate write %dxEOF\n", device->first_minor, 1858c2ecf20Sopenharmony_ci device->required_tapemarks); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci rc = tape_mtop(device, MTWEOF, device->required_tapemarks); 1888c2ecf20Sopenharmony_ci if (rc) 1898c2ecf20Sopenharmony_ci return rc; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci device->required_tapemarks = 0; 1928c2ecf20Sopenharmony_ci return tape_mtop(device, MTBSR, 1); 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci/* 1968c2ecf20Sopenharmony_ci * MTLOAD: Loads the tape. 1978c2ecf20Sopenharmony_ci * The default implementation just wait until the tape medium state changes 1988c2ecf20Sopenharmony_ci * to MS_LOADED. 1998c2ecf20Sopenharmony_ci */ 2008c2ecf20Sopenharmony_ciint 2018c2ecf20Sopenharmony_citape_std_mtload(struct tape_device *device, int count) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci return wait_event_interruptible(device->state_change_wq, 2048c2ecf20Sopenharmony_ci (device->medium_state == MS_LOADED)); 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci/* 2088c2ecf20Sopenharmony_ci * MTSETBLK: Set block size. 2098c2ecf20Sopenharmony_ci */ 2108c2ecf20Sopenharmony_ciint 2118c2ecf20Sopenharmony_citape_std_mtsetblk(struct tape_device *device, int count) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci struct idal_buffer *new; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci DBF_LH(6, "tape_std_mtsetblk(%d)\n", count); 2168c2ecf20Sopenharmony_ci if (count <= 0) { 2178c2ecf20Sopenharmony_ci /* 2188c2ecf20Sopenharmony_ci * Just set block_size to 0. tapechar_read/tapechar_write 2198c2ecf20Sopenharmony_ci * will realloc the idal buffer if a bigger one than the 2208c2ecf20Sopenharmony_ci * current is needed. 2218c2ecf20Sopenharmony_ci */ 2228c2ecf20Sopenharmony_ci device->char_data.block_size = 0; 2238c2ecf20Sopenharmony_ci return 0; 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci if (device->char_data.idal_buf != NULL && 2268c2ecf20Sopenharmony_ci device->char_data.idal_buf->size == count) 2278c2ecf20Sopenharmony_ci /* We already have a idal buffer of that size. */ 2288c2ecf20Sopenharmony_ci return 0; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci if (count > MAX_BLOCKSIZE) { 2318c2ecf20Sopenharmony_ci DBF_EVENT(3, "Invalid block size (%d > %d) given.\n", 2328c2ecf20Sopenharmony_ci count, MAX_BLOCKSIZE); 2338c2ecf20Sopenharmony_ci return -EINVAL; 2348c2ecf20Sopenharmony_ci } 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci /* Allocate a new idal buffer. */ 2378c2ecf20Sopenharmony_ci new = idal_buffer_alloc(count, 0); 2388c2ecf20Sopenharmony_ci if (IS_ERR(new)) 2398c2ecf20Sopenharmony_ci return -ENOMEM; 2408c2ecf20Sopenharmony_ci if (device->char_data.idal_buf != NULL) 2418c2ecf20Sopenharmony_ci idal_buffer_free(device->char_data.idal_buf); 2428c2ecf20Sopenharmony_ci device->char_data.idal_buf = new; 2438c2ecf20Sopenharmony_ci device->char_data.block_size = count; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci DBF_LH(6, "new blocksize is %d\n", device->char_data.block_size); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci return 0; 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci/* 2518c2ecf20Sopenharmony_ci * MTRESET: Set block size to 0. 2528c2ecf20Sopenharmony_ci */ 2538c2ecf20Sopenharmony_ciint 2548c2ecf20Sopenharmony_citape_std_mtreset(struct tape_device *device, int count) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci DBF_EVENT(6, "TCHAR:devreset:\n"); 2578c2ecf20Sopenharmony_ci device->char_data.block_size = 0; 2588c2ecf20Sopenharmony_ci return 0; 2598c2ecf20Sopenharmony_ci} 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci/* 2628c2ecf20Sopenharmony_ci * MTFSF: Forward space over 'count' file marks. The tape is positioned 2638c2ecf20Sopenharmony_ci * at the EOT (End of Tape) side of the file mark. 2648c2ecf20Sopenharmony_ci */ 2658c2ecf20Sopenharmony_ciint 2668c2ecf20Sopenharmony_citape_std_mtfsf(struct tape_device *device, int mt_count) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci struct tape_request *request; 2698c2ecf20Sopenharmony_ci struct ccw1 *ccw; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci request = tape_alloc_request(mt_count + 2, 0); 2728c2ecf20Sopenharmony_ci if (IS_ERR(request)) 2738c2ecf20Sopenharmony_ci return PTR_ERR(request); 2748c2ecf20Sopenharmony_ci request->op = TO_FSF; 2758c2ecf20Sopenharmony_ci /* setup ccws */ 2768c2ecf20Sopenharmony_ci ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 2778c2ecf20Sopenharmony_ci device->modeset_byte); 2788c2ecf20Sopenharmony_ci ccw = tape_ccw_repeat(ccw, FORSPACEFILE, mt_count); 2798c2ecf20Sopenharmony_ci ccw = tape_ccw_end(ccw, NOP, 0, NULL); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci /* execute it */ 2828c2ecf20Sopenharmony_ci return tape_do_io_free(device, request); 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci/* 2868c2ecf20Sopenharmony_ci * MTFSR: Forward space over 'count' tape blocks (blocksize is set 2878c2ecf20Sopenharmony_ci * via MTSETBLK. 2888c2ecf20Sopenharmony_ci */ 2898c2ecf20Sopenharmony_ciint 2908c2ecf20Sopenharmony_citape_std_mtfsr(struct tape_device *device, int mt_count) 2918c2ecf20Sopenharmony_ci{ 2928c2ecf20Sopenharmony_ci struct tape_request *request; 2938c2ecf20Sopenharmony_ci struct ccw1 *ccw; 2948c2ecf20Sopenharmony_ci int rc; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci request = tape_alloc_request(mt_count + 2, 0); 2978c2ecf20Sopenharmony_ci if (IS_ERR(request)) 2988c2ecf20Sopenharmony_ci return PTR_ERR(request); 2998c2ecf20Sopenharmony_ci request->op = TO_FSB; 3008c2ecf20Sopenharmony_ci /* setup ccws */ 3018c2ecf20Sopenharmony_ci ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 3028c2ecf20Sopenharmony_ci device->modeset_byte); 3038c2ecf20Sopenharmony_ci ccw = tape_ccw_repeat(ccw, FORSPACEBLOCK, mt_count); 3048c2ecf20Sopenharmony_ci ccw = tape_ccw_end(ccw, NOP, 0, NULL); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci /* execute it */ 3078c2ecf20Sopenharmony_ci rc = tape_do_io(device, request); 3088c2ecf20Sopenharmony_ci if (rc == 0 && request->rescnt > 0) { 3098c2ecf20Sopenharmony_ci DBF_LH(3, "FSR over tapemark\n"); 3108c2ecf20Sopenharmony_ci rc = 1; 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci tape_free_request(request); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci return rc; 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci/* 3188c2ecf20Sopenharmony_ci * MTBSR: Backward space over 'count' tape blocks. 3198c2ecf20Sopenharmony_ci * (blocksize is set via MTSETBLK. 3208c2ecf20Sopenharmony_ci */ 3218c2ecf20Sopenharmony_ciint 3228c2ecf20Sopenharmony_citape_std_mtbsr(struct tape_device *device, int mt_count) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci struct tape_request *request; 3258c2ecf20Sopenharmony_ci struct ccw1 *ccw; 3268c2ecf20Sopenharmony_ci int rc; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci request = tape_alloc_request(mt_count + 2, 0); 3298c2ecf20Sopenharmony_ci if (IS_ERR(request)) 3308c2ecf20Sopenharmony_ci return PTR_ERR(request); 3318c2ecf20Sopenharmony_ci request->op = TO_BSB; 3328c2ecf20Sopenharmony_ci /* setup ccws */ 3338c2ecf20Sopenharmony_ci ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 3348c2ecf20Sopenharmony_ci device->modeset_byte); 3358c2ecf20Sopenharmony_ci ccw = tape_ccw_repeat(ccw, BACKSPACEBLOCK, mt_count); 3368c2ecf20Sopenharmony_ci ccw = tape_ccw_end(ccw, NOP, 0, NULL); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci /* execute it */ 3398c2ecf20Sopenharmony_ci rc = tape_do_io(device, request); 3408c2ecf20Sopenharmony_ci if (rc == 0 && request->rescnt > 0) { 3418c2ecf20Sopenharmony_ci DBF_LH(3, "BSR over tapemark\n"); 3428c2ecf20Sopenharmony_ci rc = 1; 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci tape_free_request(request); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci return rc; 3478c2ecf20Sopenharmony_ci} 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci/* 3508c2ecf20Sopenharmony_ci * MTWEOF: Write 'count' file marks at the current position. 3518c2ecf20Sopenharmony_ci */ 3528c2ecf20Sopenharmony_ciint 3538c2ecf20Sopenharmony_citape_std_mtweof(struct tape_device *device, int mt_count) 3548c2ecf20Sopenharmony_ci{ 3558c2ecf20Sopenharmony_ci struct tape_request *request; 3568c2ecf20Sopenharmony_ci struct ccw1 *ccw; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci request = tape_alloc_request(mt_count + 2, 0); 3598c2ecf20Sopenharmony_ci if (IS_ERR(request)) 3608c2ecf20Sopenharmony_ci return PTR_ERR(request); 3618c2ecf20Sopenharmony_ci request->op = TO_WTM; 3628c2ecf20Sopenharmony_ci /* setup ccws */ 3638c2ecf20Sopenharmony_ci ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 3648c2ecf20Sopenharmony_ci device->modeset_byte); 3658c2ecf20Sopenharmony_ci ccw = tape_ccw_repeat(ccw, WRITETAPEMARK, mt_count); 3668c2ecf20Sopenharmony_ci ccw = tape_ccw_end(ccw, NOP, 0, NULL); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci /* execute it */ 3698c2ecf20Sopenharmony_ci return tape_do_io_free(device, request); 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci/* 3738c2ecf20Sopenharmony_ci * MTBSFM: Backward space over 'count' file marks. 3748c2ecf20Sopenharmony_ci * The tape is positioned at the BOT (Begin Of Tape) side of the 3758c2ecf20Sopenharmony_ci * last skipped file mark. 3768c2ecf20Sopenharmony_ci */ 3778c2ecf20Sopenharmony_ciint 3788c2ecf20Sopenharmony_citape_std_mtbsfm(struct tape_device *device, int mt_count) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci struct tape_request *request; 3818c2ecf20Sopenharmony_ci struct ccw1 *ccw; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci request = tape_alloc_request(mt_count + 2, 0); 3848c2ecf20Sopenharmony_ci if (IS_ERR(request)) 3858c2ecf20Sopenharmony_ci return PTR_ERR(request); 3868c2ecf20Sopenharmony_ci request->op = TO_BSF; 3878c2ecf20Sopenharmony_ci /* setup ccws */ 3888c2ecf20Sopenharmony_ci ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 3898c2ecf20Sopenharmony_ci device->modeset_byte); 3908c2ecf20Sopenharmony_ci ccw = tape_ccw_repeat(ccw, BACKSPACEFILE, mt_count); 3918c2ecf20Sopenharmony_ci ccw = tape_ccw_end(ccw, NOP, 0, NULL); 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci /* execute it */ 3948c2ecf20Sopenharmony_ci return tape_do_io_free(device, request); 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci/* 3988c2ecf20Sopenharmony_ci * MTBSF: Backward space over 'count' file marks. The tape is positioned at 3998c2ecf20Sopenharmony_ci * the EOT (End of Tape) side of the last skipped file mark. 4008c2ecf20Sopenharmony_ci */ 4018c2ecf20Sopenharmony_ciint 4028c2ecf20Sopenharmony_citape_std_mtbsf(struct tape_device *device, int mt_count) 4038c2ecf20Sopenharmony_ci{ 4048c2ecf20Sopenharmony_ci struct tape_request *request; 4058c2ecf20Sopenharmony_ci struct ccw1 *ccw; 4068c2ecf20Sopenharmony_ci int rc; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci request = tape_alloc_request(mt_count + 2, 0); 4098c2ecf20Sopenharmony_ci if (IS_ERR(request)) 4108c2ecf20Sopenharmony_ci return PTR_ERR(request); 4118c2ecf20Sopenharmony_ci request->op = TO_BSF; 4128c2ecf20Sopenharmony_ci /* setup ccws */ 4138c2ecf20Sopenharmony_ci ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 4148c2ecf20Sopenharmony_ci device->modeset_byte); 4158c2ecf20Sopenharmony_ci ccw = tape_ccw_repeat(ccw, BACKSPACEFILE, mt_count); 4168c2ecf20Sopenharmony_ci ccw = tape_ccw_end(ccw, NOP, 0, NULL); 4178c2ecf20Sopenharmony_ci /* execute it */ 4188c2ecf20Sopenharmony_ci rc = tape_do_io_free(device, request); 4198c2ecf20Sopenharmony_ci if (rc == 0) { 4208c2ecf20Sopenharmony_ci rc = tape_mtop(device, MTFSR, 1); 4218c2ecf20Sopenharmony_ci if (rc > 0) 4228c2ecf20Sopenharmony_ci rc = 0; 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci return rc; 4258c2ecf20Sopenharmony_ci} 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci/* 4288c2ecf20Sopenharmony_ci * MTFSFM: Forward space over 'count' file marks. 4298c2ecf20Sopenharmony_ci * The tape is positioned at the BOT (Begin Of Tape) side 4308c2ecf20Sopenharmony_ci * of the last skipped file mark. 4318c2ecf20Sopenharmony_ci */ 4328c2ecf20Sopenharmony_ciint 4338c2ecf20Sopenharmony_citape_std_mtfsfm(struct tape_device *device, int mt_count) 4348c2ecf20Sopenharmony_ci{ 4358c2ecf20Sopenharmony_ci struct tape_request *request; 4368c2ecf20Sopenharmony_ci struct ccw1 *ccw; 4378c2ecf20Sopenharmony_ci int rc; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci request = tape_alloc_request(mt_count + 2, 0); 4408c2ecf20Sopenharmony_ci if (IS_ERR(request)) 4418c2ecf20Sopenharmony_ci return PTR_ERR(request); 4428c2ecf20Sopenharmony_ci request->op = TO_FSF; 4438c2ecf20Sopenharmony_ci /* setup ccws */ 4448c2ecf20Sopenharmony_ci ccw = tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 4458c2ecf20Sopenharmony_ci device->modeset_byte); 4468c2ecf20Sopenharmony_ci ccw = tape_ccw_repeat(ccw, FORSPACEFILE, mt_count); 4478c2ecf20Sopenharmony_ci ccw = tape_ccw_end(ccw, NOP, 0, NULL); 4488c2ecf20Sopenharmony_ci /* execute it */ 4498c2ecf20Sopenharmony_ci rc = tape_do_io_free(device, request); 4508c2ecf20Sopenharmony_ci if (rc == 0) { 4518c2ecf20Sopenharmony_ci rc = tape_mtop(device, MTBSR, 1); 4528c2ecf20Sopenharmony_ci if (rc > 0) 4538c2ecf20Sopenharmony_ci rc = 0; 4548c2ecf20Sopenharmony_ci } 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci return rc; 4578c2ecf20Sopenharmony_ci} 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci/* 4608c2ecf20Sopenharmony_ci * MTREW: Rewind the tape. 4618c2ecf20Sopenharmony_ci */ 4628c2ecf20Sopenharmony_ciint 4638c2ecf20Sopenharmony_citape_std_mtrew(struct tape_device *device, int mt_count) 4648c2ecf20Sopenharmony_ci{ 4658c2ecf20Sopenharmony_ci struct tape_request *request; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci request = tape_alloc_request(3, 0); 4688c2ecf20Sopenharmony_ci if (IS_ERR(request)) 4698c2ecf20Sopenharmony_ci return PTR_ERR(request); 4708c2ecf20Sopenharmony_ci request->op = TO_REW; 4718c2ecf20Sopenharmony_ci /* setup ccws */ 4728c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, 4738c2ecf20Sopenharmony_ci device->modeset_byte); 4748c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr + 1, REWIND, 0, NULL); 4758c2ecf20Sopenharmony_ci tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL); 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci /* execute it */ 4788c2ecf20Sopenharmony_ci return tape_do_io_free(device, request); 4798c2ecf20Sopenharmony_ci} 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci/* 4828c2ecf20Sopenharmony_ci * MTOFFL: Rewind the tape and put the drive off-line. 4838c2ecf20Sopenharmony_ci * Implement 'rewind unload' 4848c2ecf20Sopenharmony_ci */ 4858c2ecf20Sopenharmony_ciint 4868c2ecf20Sopenharmony_citape_std_mtoffl(struct tape_device *device, int mt_count) 4878c2ecf20Sopenharmony_ci{ 4888c2ecf20Sopenharmony_ci struct tape_request *request; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci request = tape_alloc_request(3, 0); 4918c2ecf20Sopenharmony_ci if (IS_ERR(request)) 4928c2ecf20Sopenharmony_ci return PTR_ERR(request); 4938c2ecf20Sopenharmony_ci request->op = TO_RUN; 4948c2ecf20Sopenharmony_ci /* setup ccws */ 4958c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 4968c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr + 1, REWIND_UNLOAD, 0, NULL); 4978c2ecf20Sopenharmony_ci tape_ccw_end(request->cpaddr + 2, NOP, 0, NULL); 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci /* execute it */ 5008c2ecf20Sopenharmony_ci return tape_do_io_free(device, request); 5018c2ecf20Sopenharmony_ci} 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci/* 5048c2ecf20Sopenharmony_ci * MTNOP: 'No operation'. 5058c2ecf20Sopenharmony_ci */ 5068c2ecf20Sopenharmony_ciint 5078c2ecf20Sopenharmony_citape_std_mtnop(struct tape_device *device, int mt_count) 5088c2ecf20Sopenharmony_ci{ 5098c2ecf20Sopenharmony_ci struct tape_request *request; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci request = tape_alloc_request(2, 0); 5128c2ecf20Sopenharmony_ci if (IS_ERR(request)) 5138c2ecf20Sopenharmony_ci return PTR_ERR(request); 5148c2ecf20Sopenharmony_ci request->op = TO_NOP; 5158c2ecf20Sopenharmony_ci /* setup ccws */ 5168c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 5178c2ecf20Sopenharmony_ci tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL); 5188c2ecf20Sopenharmony_ci /* execute it */ 5198c2ecf20Sopenharmony_ci return tape_do_io_free(device, request); 5208c2ecf20Sopenharmony_ci} 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci/* 5238c2ecf20Sopenharmony_ci * MTEOM: positions at the end of the portion of the tape already used 5248c2ecf20Sopenharmony_ci * for recordind data. MTEOM positions after the last file mark, ready for 5258c2ecf20Sopenharmony_ci * appending another file. 5268c2ecf20Sopenharmony_ci */ 5278c2ecf20Sopenharmony_ciint 5288c2ecf20Sopenharmony_citape_std_mteom(struct tape_device *device, int mt_count) 5298c2ecf20Sopenharmony_ci{ 5308c2ecf20Sopenharmony_ci int rc; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci /* 5338c2ecf20Sopenharmony_ci * Seek from the beginning of tape (rewind). 5348c2ecf20Sopenharmony_ci */ 5358c2ecf20Sopenharmony_ci if ((rc = tape_mtop(device, MTREW, 1)) < 0) 5368c2ecf20Sopenharmony_ci return rc; 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci /* 5398c2ecf20Sopenharmony_ci * The logical end of volume is given by two sewuential tapemarks. 5408c2ecf20Sopenharmony_ci * Look for this by skipping to the next file (over one tapemark) 5418c2ecf20Sopenharmony_ci * and then test for another one (fsr returns 1 if a tapemark was 5428c2ecf20Sopenharmony_ci * encountered). 5438c2ecf20Sopenharmony_ci */ 5448c2ecf20Sopenharmony_ci do { 5458c2ecf20Sopenharmony_ci if ((rc = tape_mtop(device, MTFSF, 1)) < 0) 5468c2ecf20Sopenharmony_ci return rc; 5478c2ecf20Sopenharmony_ci if ((rc = tape_mtop(device, MTFSR, 1)) < 0) 5488c2ecf20Sopenharmony_ci return rc; 5498c2ecf20Sopenharmony_ci } while (rc == 0); 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci return tape_mtop(device, MTBSR, 1); 5528c2ecf20Sopenharmony_ci} 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci/* 5558c2ecf20Sopenharmony_ci * MTRETEN: Retension the tape, i.e. forward space to end of tape and rewind. 5568c2ecf20Sopenharmony_ci */ 5578c2ecf20Sopenharmony_ciint 5588c2ecf20Sopenharmony_citape_std_mtreten(struct tape_device *device, int mt_count) 5598c2ecf20Sopenharmony_ci{ 5608c2ecf20Sopenharmony_ci struct tape_request *request; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci request = tape_alloc_request(4, 0); 5638c2ecf20Sopenharmony_ci if (IS_ERR(request)) 5648c2ecf20Sopenharmony_ci return PTR_ERR(request); 5658c2ecf20Sopenharmony_ci request->op = TO_FSF; 5668c2ecf20Sopenharmony_ci /* setup ccws */ 5678c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 5688c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr + 1,FORSPACEFILE, 0, NULL); 5698c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr + 2, NOP, 0, NULL); 5708c2ecf20Sopenharmony_ci tape_ccw_end(request->cpaddr + 3, CCW_CMD_TIC, 0, request->cpaddr); 5718c2ecf20Sopenharmony_ci /* execute it, MTRETEN rc gets ignored */ 5728c2ecf20Sopenharmony_ci tape_do_io_interruptible(device, request); 5738c2ecf20Sopenharmony_ci tape_free_request(request); 5748c2ecf20Sopenharmony_ci return tape_mtop(device, MTREW, 1); 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci/* 5788c2ecf20Sopenharmony_ci * MTERASE: erases the tape. 5798c2ecf20Sopenharmony_ci */ 5808c2ecf20Sopenharmony_ciint 5818c2ecf20Sopenharmony_citape_std_mterase(struct tape_device *device, int mt_count) 5828c2ecf20Sopenharmony_ci{ 5838c2ecf20Sopenharmony_ci struct tape_request *request; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci request = tape_alloc_request(6, 0); 5868c2ecf20Sopenharmony_ci if (IS_ERR(request)) 5878c2ecf20Sopenharmony_ci return PTR_ERR(request); 5888c2ecf20Sopenharmony_ci request->op = TO_DSE; 5898c2ecf20Sopenharmony_ci /* setup ccws */ 5908c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 5918c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr + 1, REWIND, 0, NULL); 5928c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr + 2, ERASE_GAP, 0, NULL); 5938c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr + 3, DATA_SEC_ERASE, 0, NULL); 5948c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr + 4, REWIND, 0, NULL); 5958c2ecf20Sopenharmony_ci tape_ccw_end(request->cpaddr + 5, NOP, 0, NULL); 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci /* execute it */ 5988c2ecf20Sopenharmony_ci return tape_do_io_free(device, request); 5998c2ecf20Sopenharmony_ci} 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci/* 6028c2ecf20Sopenharmony_ci * MTUNLOAD: Rewind the tape and unload it. 6038c2ecf20Sopenharmony_ci */ 6048c2ecf20Sopenharmony_ciint 6058c2ecf20Sopenharmony_citape_std_mtunload(struct tape_device *device, int mt_count) 6068c2ecf20Sopenharmony_ci{ 6078c2ecf20Sopenharmony_ci return tape_mtop(device, MTOFFL, mt_count); 6088c2ecf20Sopenharmony_ci} 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci/* 6118c2ecf20Sopenharmony_ci * MTCOMPRESSION: used to enable compression. 6128c2ecf20Sopenharmony_ci * Sets the IDRC on/off. 6138c2ecf20Sopenharmony_ci */ 6148c2ecf20Sopenharmony_ciint 6158c2ecf20Sopenharmony_citape_std_mtcompression(struct tape_device *device, int mt_count) 6168c2ecf20Sopenharmony_ci{ 6178c2ecf20Sopenharmony_ci struct tape_request *request; 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci if (mt_count < 0 || mt_count > 1) { 6208c2ecf20Sopenharmony_ci DBF_EXCEPTION(6, "xcom parm\n"); 6218c2ecf20Sopenharmony_ci return -EINVAL; 6228c2ecf20Sopenharmony_ci } 6238c2ecf20Sopenharmony_ci request = tape_alloc_request(2, 0); 6248c2ecf20Sopenharmony_ci if (IS_ERR(request)) 6258c2ecf20Sopenharmony_ci return PTR_ERR(request); 6268c2ecf20Sopenharmony_ci request->op = TO_NOP; 6278c2ecf20Sopenharmony_ci /* setup ccws */ 6288c2ecf20Sopenharmony_ci if (mt_count == 0) 6298c2ecf20Sopenharmony_ci *device->modeset_byte &= ~0x08; 6308c2ecf20Sopenharmony_ci else 6318c2ecf20Sopenharmony_ci *device->modeset_byte |= 0x08; 6328c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 6338c2ecf20Sopenharmony_ci tape_ccw_end(request->cpaddr + 1, NOP, 0, NULL); 6348c2ecf20Sopenharmony_ci /* execute it */ 6358c2ecf20Sopenharmony_ci return tape_do_io_free(device, request); 6368c2ecf20Sopenharmony_ci} 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci/* 6398c2ecf20Sopenharmony_ci * Read Block 6408c2ecf20Sopenharmony_ci */ 6418c2ecf20Sopenharmony_cistruct tape_request * 6428c2ecf20Sopenharmony_citape_std_read_block(struct tape_device *device, size_t count) 6438c2ecf20Sopenharmony_ci{ 6448c2ecf20Sopenharmony_ci struct tape_request *request; 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci /* 6478c2ecf20Sopenharmony_ci * We have to alloc 4 ccws in order to be able to transform request 6488c2ecf20Sopenharmony_ci * into a read backward request in error case. 6498c2ecf20Sopenharmony_ci */ 6508c2ecf20Sopenharmony_ci request = tape_alloc_request(4, 0); 6518c2ecf20Sopenharmony_ci if (IS_ERR(request)) { 6528c2ecf20Sopenharmony_ci DBF_EXCEPTION(6, "xrbl fail"); 6538c2ecf20Sopenharmony_ci return request; 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci request->op = TO_RFO; 6568c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 6578c2ecf20Sopenharmony_ci tape_ccw_end_idal(request->cpaddr + 1, READ_FORWARD, 6588c2ecf20Sopenharmony_ci device->char_data.idal_buf); 6598c2ecf20Sopenharmony_ci DBF_EVENT(6, "xrbl ccwg\n"); 6608c2ecf20Sopenharmony_ci return request; 6618c2ecf20Sopenharmony_ci} 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci/* 6648c2ecf20Sopenharmony_ci * Read Block backward transformation function. 6658c2ecf20Sopenharmony_ci */ 6668c2ecf20Sopenharmony_civoid 6678c2ecf20Sopenharmony_citape_std_read_backward(struct tape_device *device, struct tape_request *request) 6688c2ecf20Sopenharmony_ci{ 6698c2ecf20Sopenharmony_ci /* 6708c2ecf20Sopenharmony_ci * We have allocated 4 ccws in tape_std_read, so we can now 6718c2ecf20Sopenharmony_ci * transform the request to a read backward, followed by a 6728c2ecf20Sopenharmony_ci * forward space block. 6738c2ecf20Sopenharmony_ci */ 6748c2ecf20Sopenharmony_ci request->op = TO_RBA; 6758c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 6768c2ecf20Sopenharmony_ci tape_ccw_cc_idal(request->cpaddr + 1, READ_BACKWARD, 6778c2ecf20Sopenharmony_ci device->char_data.idal_buf); 6788c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr + 2, FORSPACEBLOCK, 0, NULL); 6798c2ecf20Sopenharmony_ci tape_ccw_end(request->cpaddr + 3, NOP, 0, NULL); 6808c2ecf20Sopenharmony_ci DBF_EVENT(6, "xrop ccwg");} 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci/* 6838c2ecf20Sopenharmony_ci * Write Block 6848c2ecf20Sopenharmony_ci */ 6858c2ecf20Sopenharmony_cistruct tape_request * 6868c2ecf20Sopenharmony_citape_std_write_block(struct tape_device *device, size_t count) 6878c2ecf20Sopenharmony_ci{ 6888c2ecf20Sopenharmony_ci struct tape_request *request; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci request = tape_alloc_request(2, 0); 6918c2ecf20Sopenharmony_ci if (IS_ERR(request)) { 6928c2ecf20Sopenharmony_ci DBF_EXCEPTION(6, "xwbl fail\n"); 6938c2ecf20Sopenharmony_ci return request; 6948c2ecf20Sopenharmony_ci } 6958c2ecf20Sopenharmony_ci request->op = TO_WRI; 6968c2ecf20Sopenharmony_ci tape_ccw_cc(request->cpaddr, MODE_SET_DB, 1, device->modeset_byte); 6978c2ecf20Sopenharmony_ci tape_ccw_end_idal(request->cpaddr + 1, WRITE_CMD, 6988c2ecf20Sopenharmony_ci device->char_data.idal_buf); 6998c2ecf20Sopenharmony_ci DBF_EVENT(6, "xwbl ccwg\n"); 7008c2ecf20Sopenharmony_ci return request; 7018c2ecf20Sopenharmony_ci} 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci/* 7048c2ecf20Sopenharmony_ci * This routine is called by frontend after an ENOSP on write 7058c2ecf20Sopenharmony_ci */ 7068c2ecf20Sopenharmony_civoid 7078c2ecf20Sopenharmony_citape_std_process_eov(struct tape_device *device) 7088c2ecf20Sopenharmony_ci{ 7098c2ecf20Sopenharmony_ci /* 7108c2ecf20Sopenharmony_ci * End of volume: We have to backspace the last written record, then 7118c2ecf20Sopenharmony_ci * we TRY to write a tapemark and then backspace over the written TM 7128c2ecf20Sopenharmony_ci */ 7138c2ecf20Sopenharmony_ci if (tape_mtop(device, MTBSR, 1) == 0 && 7148c2ecf20Sopenharmony_ci tape_mtop(device, MTWEOF, 1) == 0) { 7158c2ecf20Sopenharmony_ci tape_mtop(device, MTBSR, 1); 7168c2ecf20Sopenharmony_ci } 7178c2ecf20Sopenharmony_ci} 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_assign); 7208c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_unassign); 7218c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_display); 7228c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_read_block_id); 7238c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtload); 7248c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtsetblk); 7258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtreset); 7268c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtfsf); 7278c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtfsr); 7288c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtbsr); 7298c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtweof); 7308c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtbsfm); 7318c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtbsf); 7328c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtfsfm); 7338c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtrew); 7348c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtoffl); 7358c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtnop); 7368c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mteom); 7378c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtreten); 7388c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mterase); 7398c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtunload); 7408c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_mtcompression); 7418c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_read_block); 7428c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_read_backward); 7438c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_write_block); 7448c2ecf20Sopenharmony_ciEXPORT_SYMBOL(tape_std_process_eov); 745