tape_std.c 18 KB

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