tape_std.c 19 KB

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