PageRenderTime 97ms CodeModel.GetById 54ms RepoModel.GetById 0ms app.codeStats 1ms

/src/netbsd/src/sys/dev/qbus/ts.c

https://bitbucket.org/killerpenguinassassins/open_distrib_devel
C | 1064 lines | 688 code | 112 blank | 264 comment | 93 complexity | f879885ef6abc2f92b948e2db6d8928a MD5 | raw file
Possible License(s): CC0-1.0, MIT, LGPL-2.0, LGPL-3.0, WTFPL, GPL-2.0, BSD-2-Clause, AGPL-3.0, CC-BY-SA-3.0, MPL-2.0, JSON, BSD-3-Clause-No-Nuclear-License-2014, LGPL-2.1, CPL-1.0, AGPL-1.0, 0BSD, ISC, Apache-2.0, GPL-3.0, IPL-1.0, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. /* $NetBSD: ts.c,v 1.28 2010/12/15 00:08:43 matt Exp $ */
  2. /*-
  3. * Copyright (c) 1991 The Regents of the University of California.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the University nor the names of its contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  22. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * @(#)tmscp.c 7.16 (Berkeley) 5/9/91
  31. */
  32. /*
  33. * sccsid = "@(#)tmscp.c 1.24 (ULTRIX) 1/21/86";
  34. */
  35. /************************************************************************
  36. * *
  37. * Licensed from Digital Equipment Corporation *
  38. * Copyright (c) *
  39. * Digital Equipment Corporation *
  40. * Maynard, Massachusetts *
  41. * 1985, 1986 *
  42. * All rights reserved. *
  43. * *
  44. * The Information in this software is subject to change *
  45. * without notice and should not be construed as a commitment *
  46. * by Digital Equipment Corporation. Digital makes no *
  47. * representations about the suitability of this software for *
  48. * any purpose. It is supplied "As Is" without expressed or *
  49. * implied warranty. *
  50. * *
  51. * If the Regents of the University of California or its *
  52. * licensees modify the software in a manner creating *
  53. * derivative copyright rights, appropriate copyright *
  54. * legends may be placed on the derivative work in addition *
  55. * to that set forth above. *
  56. * *
  57. ************************************************************************/
  58. /*
  59. * TSV05/TS05 device driver, written by Bertram Barth.
  60. *
  61. * should be TS11 compatible (untested)
  62. */
  63. #include <sys/cdefs.h>
  64. __KERNEL_RCSID(0, "$NetBSD: ts.c,v 1.28 2010/12/15 00:08:43 matt Exp $");
  65. #undef TSDEBUG
  66. /*
  67. * TODO:
  68. *
  69. * Keep track of tape position so that lseek et al works.
  70. * Use tprintf to inform the user, not the system console.
  71. */
  72. #include <sys/param.h>
  73. #include <sys/systm.h>
  74. #include <sys/kernel.h>
  75. #include <sys/buf.h>
  76. #include <sys/bufq.h>
  77. #include <sys/conf.h>
  78. #include <sys/device.h>
  79. #include <sys/errno.h>
  80. #include <sys/file.h>
  81. #include <sys/syslog.h>
  82. #include <sys/ioctl.h>
  83. #include <sys/mtio.h>
  84. #include <sys/uio.h>
  85. #include <sys/proc.h>
  86. #include <sys/bus.h>
  87. #include <dev/qbus/ubareg.h>
  88. #include <dev/qbus/ubavar.h>
  89. #include <dev/qbus/tsreg.h>
  90. #include "ioconf.h"
  91. struct ts {
  92. struct cmd cmd; /* command packet */
  93. struct chr chr; /* characteristics packet */
  94. struct status status; /* status packet */
  95. };
  96. /*
  97. * Software status, per controller.
  98. * also status per tape-unit, since only one unit per controller
  99. * (thus we have no struct ts_info)
  100. */
  101. struct ts_softc {
  102. device_t sc_dev; /* Autoconf ... */
  103. struct uba_softc *sc_uh; /* the parent UBA */
  104. struct uba_unit sc_unit; /* Struct common for UBA to talk */
  105. struct evcnt sc_intrcnt; /* Interrupt counting */
  106. struct ubinfo sc_ui; /* mapping info for struct ts */
  107. struct uba_unit sc_uu; /* Struct for UBA to communicate */
  108. bus_space_tag_t sc_iot;
  109. bus_addr_t sc_ioh;
  110. bus_dma_tag_t sc_dmat;
  111. bus_dmamap_t sc_dmam;
  112. volatile struct ts *sc_vts; /* Memory address of ts struct */
  113. struct ts *sc_bts; /* Unibus address of ts struct */
  114. int sc_type; /* TS11 or TS05? */
  115. short sc_waddr; /* Value to write to TSDB */
  116. struct bufq_state *sc_bufq; /* pending I/O requests */
  117. short sc_mapped; /* Unibus map allocated ? */
  118. short sc_state; /* see below: ST_xxx */
  119. short sc_rtc; /* retry count for lcmd */
  120. short sc_openf; /* lock against multiple opens */
  121. short sc_liowf; /* last operation was write */
  122. struct buf ts_cbuf; /* internal cmd buffer (for ioctls) */
  123. };
  124. #define TS_WCSR(csr, val) \
  125. bus_space_write_2(sc->sc_iot, sc->sc_ioh, csr, val)
  126. #define TS_RCSR(csr) \
  127. bus_space_read_2(sc->sc_iot, sc->sc_ioh, csr)
  128. #define LOWORD(x) ((int)(x) & 0xffff)
  129. #define HIWORD(x) (((int)(x) >> 16) & 0x3f)
  130. #define TYPE_TS11 0
  131. #define TYPE_TS05 1
  132. #define TYPE_TU80 2
  133. #define TS_INVALID 0
  134. #define TS_INIT 1
  135. #define TS_RUNNING 2
  136. #define TS_FASTREPOS 3
  137. static void tsintr(void *);
  138. static void tsinit(struct ts_softc *);
  139. static void tscommand(struct ts_softc *, dev_t, int, int);
  140. static int tsstart(struct ts_softc *, int);
  141. static void tswchar(struct ts_softc *);
  142. static bool tsreset(struct ts_softc *);
  143. static int tsmatch(device_t, cfdata_t, void *);
  144. static void tsattach(device_t, device_t, void *);
  145. static int tsready(struct uba_unit *);
  146. CFATTACH_DECL_NEW(ts, sizeof(struct ts_softc),
  147. tsmatch, tsattach, NULL, NULL);
  148. dev_type_open(tsopen);
  149. dev_type_close(tsclose);
  150. dev_type_read(tsread);
  151. dev_type_write(tswrite);
  152. dev_type_ioctl(tsioctl);
  153. dev_type_strategy(tsstrategy);
  154. dev_type_dump(tsdump);
  155. const struct bdevsw ts_bdevsw = {
  156. tsopen, tsclose, tsstrategy, tsioctl, tsdump, nosize, D_TAPE
  157. };
  158. const struct cdevsw ts_cdevsw = {
  159. tsopen, tsclose, tsread, tswrite, tsioctl,
  160. nostop, notty, nopoll, nommap, nokqfilter, D_TAPE
  161. };
  162. /* Bits in minor device */
  163. #define TS_UNIT(dev) (minor(dev)&03)
  164. #define TS_HIDENSITY 010
  165. #define TS_PRI LOG_INFO
  166. /*
  167. * Probe for device. If found, try to raise an interrupt.
  168. */
  169. int
  170. tsmatch(device_t parent, cfdata_t match, void *aux)
  171. {
  172. struct device tsdev;
  173. struct ts_softc ssc;
  174. struct ts_softc *sc = &ssc;
  175. struct uba_attach_args *ua = aux;
  176. int i;
  177. sc->sc_iot = ua->ua_iot;
  178. sc->sc_ioh = ua->ua_ioh;
  179. sc->sc_mapped = 0;
  180. sc->sc_dev = &tsdev;
  181. sc->sc_uh = device_private(parent);
  182. strcpy(sc->sc_dev->dv_xname, "ts");
  183. /* Try to reset the device */
  184. for (i = 0; i < 3; i++) {
  185. if (tsreset(sc))
  186. break;
  187. }
  188. if (i == 3)
  189. return 0;
  190. tsinit(sc);
  191. tswchar(sc); /* write charact. to enable interrupts */
  192. /* completion of this will raise the intr. */
  193. DELAY(1000000); /* Wait for interrupt */
  194. ubmemfree(sc->sc_uh, &sc->sc_ui);
  195. return 1;
  196. }
  197. /*
  198. */
  199. void
  200. tsattach(device_t parent, device_t self, void *aux)
  201. {
  202. struct ts_softc *sc = device_private(self);
  203. struct uba_attach_args *ua = aux;
  204. int error;
  205. const char *t;
  206. sc->sc_dev = self;
  207. sc->sc_uh = device_private(parent);
  208. sc->sc_iot = ua->ua_iot;
  209. sc->sc_ioh = ua->ua_ioh;
  210. sc->sc_dmat = ua->ua_dmat;
  211. sc->sc_uu.uu_dev = self;
  212. sc->sc_uu.uu_ready = tsready;
  213. tsinit(sc); /* reset and map */
  214. error = bus_dmamap_create(sc->sc_dmat, (64*1024), 16, (64*1024),
  215. 0, BUS_DMA_NOWAIT, &sc->sc_dmam);
  216. if (error) {
  217. aprint_error(": failed create DMA map %d\n", error);
  218. return;
  219. }
  220. bufq_alloc(&sc->sc_bufq, "fcfs", 0);
  221. /*
  222. * write the characteristics (again)
  223. */
  224. sc->sc_state = TS_INIT; /* tsintr() checks this ... */
  225. tswchar(sc);
  226. if (tsleep(sc, PRIBIO, "tsattach", 100)) {
  227. aprint_error(": failed SET CHARACTERISTICS\n");
  228. return;
  229. }
  230. sc->sc_state = TS_RUNNING;
  231. if (sc->sc_uh->uh_type == UBA_UBA) {
  232. if (sc->sc_vts->status.xst2 & TS_SF_TU80) {
  233. sc->sc_type = TYPE_TU80;
  234. t = "TU80";
  235. } else {
  236. sc->sc_type = TYPE_TS11;
  237. t = "TS11";
  238. }
  239. } else {
  240. sc->sc_type = TYPE_TS05;
  241. t = "TS05";
  242. }
  243. aprint_normal(": %s\n", t);
  244. aprint_normal_dev(sc->sc_dev,
  245. "rev %d, extended features %s, transport %s\n",
  246. (sc->sc_vts->status.xst2 & TS_SF_MCRL) >> 2,
  247. (sc->sc_vts->status.xst2 & TS_SF_EFES ? "enabled" : "disabled"),
  248. (TS_RCSR(TSSR) & TS_OFL ? "offline" : "online"));
  249. uba_intr_establish(ua->ua_icookie, ua->ua_cvec, tsintr,
  250. sc, &sc->sc_intrcnt);
  251. evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
  252. device_xname(sc->sc_dev), "intr");
  253. }
  254. /*
  255. * Initialize a TS device. Set up UBA mapping registers,
  256. * initialize data structures, what else ???
  257. */
  258. void
  259. tsinit(struct ts_softc *sc)
  260. {
  261. if (sc->sc_mapped == 0) {
  262. /*
  263. * Map the communications area and command and message
  264. * buffer into Unibus address space.
  265. */
  266. sc->sc_ui.ui_size = sizeof(struct ts);
  267. if (ubmemalloc(sc->sc_uh, &sc->sc_ui, UBA_CANTWAIT))
  268. return;
  269. sc->sc_vts = (void *)sc->sc_ui.ui_vaddr;
  270. sc->sc_bts = (void *)sc->sc_ui.ui_baddr;
  271. sc->sc_waddr = sc->sc_ui.ui_baddr |
  272. ((sc->sc_ui.ui_baddr >> 16) & 3);
  273. sc->sc_mapped = 1;
  274. }
  275. tsreset(sc);
  276. }
  277. /*
  278. * Execute a (ioctl) command on the tape drive a specified number of times.
  279. * This routine sets up a buffer and calls the strategy routine which
  280. * issues the command to the controller.
  281. */
  282. void
  283. tscommand(struct ts_softc *sc, dev_t dev, int cmd, int count)
  284. {
  285. struct buf *bp;
  286. #ifdef TSDEBUG
  287. printf("tscommand (%x, %d)\n", cmd, count);
  288. #endif
  289. bp = &sc->ts_cbuf;
  290. mutex_enter(&bufcache_lock);
  291. while (bp->b_cflags & BC_BUSY) {
  292. /*
  293. * This special check is because BC_BUSY never
  294. * gets cleared in the non-waiting rewind case. ???
  295. */
  296. if (bp->b_bcount == 0 && (bp->b_oflags & BO_DONE))
  297. break;
  298. if (bbusy(bp, false, 0, NULL) == 0)
  299. break;
  300. /* check MOT-flag !!! */
  301. }
  302. bp->b_flags = B_READ;
  303. mutex_exit(&bufcache_lock);
  304. /*
  305. * Load the buffer. The b_count field gets used to hold the command
  306. * count. the b_resid field gets used to hold the command mneumonic.
  307. * These 2 fields are "known" to be "safe" to use for this purpose.
  308. * (Most other drivers also use these fields in this way.)
  309. */
  310. bp->b_dev = dev;
  311. bp->b_bcount = count;
  312. bp->b_resid = cmd;
  313. bp->b_blkno = 0;
  314. bp->b_oflags = 0;
  315. bp->b_objlock = &buffer_lock;
  316. tsstrategy(bp);
  317. /*
  318. * In case of rewind from close, don't wait.
  319. * This is the only case where count can be 0.
  320. */
  321. if (count == 0)
  322. return;
  323. biowait(bp);
  324. mutex_enter(&bufcache_lock);
  325. cv_broadcast(&bp->b_busy);
  326. bp->b_cflags = 0;
  327. mutex_exit(&bufcache_lock);
  328. }
  329. /*
  330. * Start an I/O operation on TS05 controller
  331. */
  332. int
  333. tsstart(struct ts_softc *sc, int isloaded)
  334. {
  335. struct buf *bp;
  336. int cmd;
  337. bp = bufq_peek(sc->sc_bufq);
  338. if (bp == NULL) {
  339. return 0;
  340. }
  341. #ifdef TSDEBUG
  342. printf("buf: %p bcount %ld blkno %d\n", bp, bp->b_bcount, bp->b_blkno);
  343. #endif
  344. /*
  345. * Check if command is an ioctl or not (ie. read or write).
  346. * If it's an ioctl then just set the flags for later use;
  347. * For other commands attempt to setup a buffer pointer.
  348. */
  349. if (bp == &sc->ts_cbuf) {
  350. switch ((int)bp->b_resid) {
  351. case MTWEOF:
  352. cmd = TS_CMD_WTM;
  353. break;
  354. case MTFSF:
  355. cmd = TS_CMD_STMF;
  356. sc->sc_vts->cmd.cw1 = bp->b_bcount;
  357. break;
  358. case MTBSF:
  359. cmd = TS_CMD_STMR;
  360. sc->sc_vts->cmd.cw1 = bp->b_bcount;
  361. break;
  362. case MTFSR:
  363. cmd = TS_CMD_SRF;
  364. sc->sc_vts->cmd.cw1 = bp->b_bcount;
  365. break;
  366. case MTBSR:
  367. cmd = TS_CMD_SRR;
  368. sc->sc_vts->cmd.cw1 = bp->b_bcount;
  369. break;
  370. case MTREW:
  371. cmd = TS_CMD_RWND;
  372. break;
  373. case MTOFFL:
  374. cmd = TS_CMD_RWUL;
  375. break;
  376. case MTNOP:
  377. cmd = TS_CMD_STAT;
  378. break;
  379. default:
  380. aprint_error_dev(sc->sc_dev, "bad ioctl %d\n",
  381. (int)bp->b_resid);
  382. /* Need a no-op. get status */
  383. cmd = TS_CMD_STAT;
  384. } /* end switch (bp->b_resid) */
  385. } else {
  386. if (isloaded == 0) {
  387. /*
  388. * now we try to map the buffer into uba map space (???)
  389. */
  390. if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmam,
  391. bp->b_data,
  392. bp->b_bcount, bp->b_proc, BUS_DMA_NOWAIT)) {
  393. uba_enqueue(&sc->sc_uu);
  394. return 0;
  395. }
  396. sc->sc_rtc = 0;
  397. }
  398. sc->sc_vts->cmd.cw1 = LOWORD(sc->sc_dmam->dm_segs[0].ds_addr);
  399. sc->sc_vts->cmd.cw2 = HIWORD(sc->sc_dmam->dm_segs[0].ds_addr);
  400. sc->sc_vts->cmd.cw3 = bp->b_bcount;
  401. bp->b_error = 0; /* Used for error count */
  402. #ifdef TSDEBUG
  403. printf("tsstart-1: err %d\n", bp->b_error);
  404. #endif
  405. if (bp->b_flags & B_READ)
  406. cmd = TS_CMD_RNF;
  407. else
  408. cmd = TS_CMD_WD;
  409. }
  410. /*
  411. * Now that the command-buffer is setup, give it to the controller
  412. */
  413. sc->sc_vts->cmd.cmdr = TS_CF_ACK | TS_CF_IE | cmd;
  414. #ifdef TSDEBUG
  415. printf("tsstart: sending cmdr %x\n", sc->sc_vts->cmd.cmdr);
  416. #endif
  417. TS_WCSR(TSDB, sc->sc_waddr);
  418. return 1;
  419. }
  420. /*
  421. * Called when there are free uba resources.
  422. */
  423. int
  424. tsready(struct uba_unit *uu)
  425. {
  426. struct ts_softc *sc = device_private(uu->uu_dev);
  427. struct buf *bp = bufq_peek(sc->sc_bufq);
  428. if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmam, bp->b_data,
  429. bp->b_bcount, bp->b_proc, BUS_DMA_NOWAIT))
  430. return 0;
  431. tsstart(sc, 1);
  432. return 1;
  433. }
  434. /*
  435. * initialize the controller by sending WRITE CHARACTERISTICS command.
  436. * contents of command- and message-buffer are assembled during this
  437. * function.
  438. */
  439. void
  440. tswchar(struct ts_softc *sc)
  441. {
  442. /*
  443. * assemble and send "WRITE CHARACTERISTICS" command
  444. */
  445. sc->sc_vts->cmd.cmdr = TS_CF_ACK | TS_CF_IE | TS_CMD_WCHAR;
  446. sc->sc_vts->cmd.cw1 = LOWORD(&sc->sc_bts->chr);
  447. sc->sc_vts->cmd.cw2 = HIWORD(&sc->sc_bts->chr);
  448. sc->sc_vts->cmd.cw3 = 010; /* size of charact.-data */
  449. sc->sc_vts->chr.sadrl = LOWORD(&sc->sc_bts->status);
  450. sc->sc_vts->chr.sadrh = HIWORD(&sc->sc_bts->status);
  451. sc->sc_vts->chr.onesix = (sc->sc_type == TYPE_TS05 ? 020 : 016);
  452. sc->sc_vts->chr.chrw = TS_WC_ESS;
  453. sc->sc_vts->chr.xchrw = TS_WCX_HSP|TS_WCX_RBUF|TS_WCX_WBUF;
  454. TS_WCSR(TSDB, sc->sc_waddr);
  455. }
  456. /*
  457. * Reset the TS11. Return 1 if failed, 0 if succeeded.
  458. */
  459. bool
  460. tsreset(struct ts_softc *sc)
  461. {
  462. int timeout;
  463. /*
  464. * reset ctlr by writing into TSSR, then write characteristics
  465. */
  466. timeout = 0; /* timeout in 10 seconds */
  467. TS_WCSR(TSSR, 0); /* start initialization */
  468. while ((TS_RCSR(TSSR) & TS_SSR) == 0) {
  469. DELAY(10000);
  470. if (timeout++ > 1000)
  471. return false;
  472. }
  473. return true;
  474. }
  475. static void
  476. prtstat(struct ts_softc *sc, int sr)
  477. {
  478. char buf[100];
  479. snprintb(buf, sizeof(buf), TS_TSSR_BITS, sr);
  480. aprint_normal_dev(sc->sc_dev, "TSSR=%s\n", buf);
  481. snprintb(buf, sizeof(buf), TS_XST0_BITS, sc->sc_vts->status.xst0);
  482. aprint_normal_dev(sc->sc_dev, "XST0=%s\n", buf);
  483. }
  484. /*
  485. * TSV05/TS05 interrupt routine
  486. */
  487. static void
  488. tsintr(void *arg)
  489. {
  490. struct ts_softc *sc = arg;
  491. struct buf *bp;
  492. unsigned short sr = TS_RCSR(TSSR); /* save TSSR */
  493. unsigned short mh = sc->sc_vts->status.hdr; /* and msg-header */
  494. /* clear the message header ??? */
  495. short ccode = sc->sc_vts->cmd.cmdr & TS_CF_CCODE;
  496. bp = bufq_peek(sc->sc_bufq);
  497. #ifdef TSDEBUG
  498. {
  499. char buf[100];
  500. snprintb(buf, sizeof(buf), TS_TSSR_BITS, sr);
  501. printf("tsintr: sr %x mh %x\n", sr, mh);
  502. printf("srbits: %s\n", buf);
  503. }
  504. #endif
  505. /*
  506. * There are two different things which can (and should) be checked:
  507. * the actual (internal) state and the device's result (tssr/msg.hdr)
  508. *
  509. * For each state there's only one "normal" interrupt. Anything else
  510. * has to be checked more intensively. Thus in a first run according
  511. * to the internal state the expected interrupt is checked/handled.
  512. *
  513. * In a second run the remaining (not yet handled) interrupts are
  514. * checked according to the drive's result.
  515. */
  516. switch (sc->sc_state) {
  517. case TS_INVALID:
  518. /*
  519. * Ignore unsolicited interrupts.
  520. */
  521. log(LOG_WARNING, "%s: stray intr [%x,%x]\n",
  522. device_xname(sc->sc_dev), sr, mh);
  523. return;
  524. case TS_INIT:
  525. /*
  526. * Init phase ready.
  527. */
  528. wakeup(sc);
  529. return;
  530. case TS_RUNNING:
  531. case TS_FASTREPOS:
  532. /*
  533. * Here we expect interrupts indicating the end of
  534. * commands or indicating problems.
  535. */
  536. /*
  537. * Anything else is handled outside this switch ...
  538. */
  539. break;
  540. default:
  541. aprint_error_dev(sc->sc_dev,
  542. "unexpected interrupt during state %d [%x,%x]\n",
  543. sc->sc_state, sr, mh);
  544. return;
  545. }
  546. /*
  547. * now we check the termination class.
  548. */
  549. switch (sr & TS_TC) {
  550. case TS_TC_NORM:
  551. /*
  552. * Normal termination -- The operation is completed
  553. * witout incident.
  554. */
  555. if (sc->sc_state == TS_FASTREPOS) {
  556. #ifdef TSDEBUG
  557. printf("Fast repos interrupt\n");
  558. #endif
  559. /* Fast repos succeeded, start normal data xfer */
  560. sc->sc_state = TS_RUNNING;
  561. tsstart(sc, 1);
  562. return;
  563. }
  564. sc->sc_liowf = (ccode == TS_CC_WRITE);
  565. break;
  566. case TS_TC_ATTN:
  567. /*
  568. * Attention condition -- this code indicates that the
  569. * drive has undergone a status change, such as going
  570. * off-line or coming on-line.
  571. * (Without EAI enabled, no Attention interrupts occur.
  572. * drive status changes are signaled by the VCK flag.)
  573. */
  574. return;
  575. case TS_TC_TSA:
  576. /*
  577. * Tape Status Alert -- A status condition is encountered
  578. * that may have significance to the program. Bits of
  579. * interest in the extended status registers include
  580. * TMK, EOT and RLL.
  581. */
  582. #ifdef TSDEBUG
  583. {
  584. char buf[100];
  585. snprintb(buf, sizeof(buf),
  586. TS_XST0_BITS, sc->sc_vts->status.xst0);
  587. printf("TSA: sr %x bits %s\n",
  588. sc->sc_vts->status.xst0, buf);
  589. }
  590. #endif
  591. if (sc->sc_vts->status.xst0 & TS_SF_TMK) {
  592. #ifdef TSDEBUG
  593. printf(("Tape Mark detected"));
  594. #endif
  595. /* Read to end-of-file. No error. */
  596. break;
  597. }
  598. if (sc->sc_vts->status.xst0 & TS_SF_EOT) {
  599. /* End of tape. Bad. */
  600. #ifdef TSDEBUG
  601. printf("TS_TC_TSA: EOT\n");
  602. #endif
  603. if (bp != NULL)
  604. bp->b_error = EIO;
  605. break;
  606. }
  607. if (sc->sc_vts->status.xst0 & TS_SF_RLS)
  608. break;
  609. #ifndef TSDEBUG
  610. {
  611. char buf[100];
  612. snprintb(buf, sizeof(buf),
  613. TS_XST0_BITS, sc->sc_vts->status.xst0);
  614. printf("TSA: sr %x bits %s\n",
  615. sc->sc_vts->status.xst0, buf);
  616. }
  617. #endif
  618. break;
  619. case TS_TC_FR:
  620. /*
  621. * Function Reject -- The specified function was not
  622. * initiated. Bits of interest include OFL, VCK, BOT,
  623. * WLE, ILC and ILA.
  624. */
  625. if (sr & TS_OFL)
  626. printf("tape is off-line.\n");
  627. #ifdef TSDEBUG
  628. {
  629. char buf[100];
  630. snprintb(buf, sizeof(buf),
  631. TS_XST0_BITS, sc->sc_vts->status.xst0);
  632. printf("FR: sr %x bits %s\n",
  633. sc->sc_vts->status.xst0, buf);
  634. }
  635. #endif
  636. if (sc->sc_vts->status.xst0 & TS_SF_VCK)
  637. printf("Volume check\n");
  638. if (sc->sc_vts->status.xst0 & TS_SF_BOT)
  639. printf("Start of tape.\n");
  640. if (sc->sc_vts->status.xst0 & TS_SF_WLE)
  641. printf("Write Lock Error\n");
  642. if (sc->sc_vts->status.xst0 & TS_SF_EOT)
  643. printf("End of tape.\n");
  644. break;
  645. case TS_TC_TPD:
  646. /*
  647. * Recoverable Error -- Tape position is a record beyond
  648. * what its position was when the function was initiated.
  649. * Suggested recovery procedure is to log the error and
  650. * issue the appropriate retry command.
  651. *
  652. * Do a fast repositioning one record back.
  653. */
  654. sc->sc_state = TS_FASTREPOS;
  655. #ifdef TSDEBUG
  656. printf("TS_TC_TPD: errcnt %d\n", sc->sc_rtc);
  657. #endif
  658. if (sc->sc_rtc++ == 8) {
  659. aprint_error_dev(sc->sc_dev, "failed 8 retries\n");
  660. prtstat(sc, sr);
  661. if (bp != NULL)
  662. bp->b_error = EIO;
  663. break;
  664. }
  665. sc->sc_vts->cmd.cmdr = TS_CF_ACK | TS_CF_IE | TS_CMD_SRR;
  666. sc->sc_vts->cmd.cw1 = 1;
  667. TS_WCSR(TSDB, sc->sc_waddr);
  668. return;
  669. case TS_TC_TNM:
  670. /*
  671. * Recoverable Error -- Tape position has not changed.
  672. * Suggested recovery procedure is to log the error and
  673. * reissue the original command.
  674. */
  675. if (sc->sc_rtc++ == 8) {
  676. aprint_error_dev(sc->sc_dev, "failed 8 retries\n");
  677. prtstat(sc, sr);
  678. if (bp != NULL)
  679. bp->b_error = EIO;
  680. break;
  681. }
  682. tsstart(sc, 1);
  683. return;
  684. case TS_TC_TPL:
  685. /*
  686. * Unrecoverable Error -- Tape position has been lost.
  687. * No valid recovery procedures exist unless the tape
  688. * has labels or sequence numbers.
  689. */
  690. aprint_error_dev(sc->sc_dev, "tape position lost\n");
  691. if (bp != NULL)
  692. bp->b_error = EIO;
  693. break;
  694. case TS_TC_FCE:
  695. /*
  696. * Fatal subsytem Error -- The subsytem is incapable
  697. * of properly performing commands, or at least its
  698. * integrity is seriously questionable. Refer to the
  699. * fatal class code field in the TSSR register for
  700. * additional information on the type of fatal error.
  701. */
  702. aprint_error_dev(sc->sc_dev, "fatal controller error\n");
  703. prtstat(sc, sr);
  704. break;
  705. default:
  706. aprint_error_dev(sc->sc_dev,
  707. "error 0x%x, resetting controller\n", sr & TS_TC);
  708. tsreset(sc);
  709. }
  710. if ((bp = bufq_get(sc->sc_bufq)) != NULL) {
  711. #ifdef TSDEBUG
  712. printf("tsintr2: que %p\n", bufq_peek(sc->sc_bufq));
  713. #endif
  714. if (bp != &sc->ts_cbuf) { /* no ioctl */
  715. bus_dmamap_unload(sc->sc_dmat, sc->sc_dmam);
  716. uba_done(sc->sc_uh);
  717. }
  718. bp->b_resid = sc->sc_vts->status.rbpcr;
  719. biodone (bp);
  720. }
  721. tsstart(sc, 0);
  722. }
  723. /*
  724. * Open a ts device and set the unit online. If the controller is not
  725. * in the run state, call init to initialize the ts controller first.
  726. */
  727. int
  728. tsopen(dev_t dev, int flag, int type, struct lwp *l)
  729. {
  730. struct ts_softc *sc = device_lookup_private(&ts_cd, TS_UNIT(dev));
  731. if (sc == NULL)
  732. return ENXIO;
  733. if (sc->sc_state < TS_RUNNING)
  734. return ENXIO;
  735. if (sc->sc_openf)
  736. return EBUSY;
  737. sc->sc_openf = 1;
  738. /*
  739. * check if transport is really online.
  740. * (without attention-interrupts enabled, we really don't know
  741. * the actual state of the transport. Thus we call get-status
  742. * (ie. MTNOP) once and check the actual status.)
  743. */
  744. if (TS_RCSR(TSSR) & TS_OFL) {
  745. uprintf("%s: transport is offline.\n", device_xname(sc->sc_dev));
  746. sc->sc_openf = 0;
  747. return EIO; /* transport is offline */
  748. }
  749. tscommand(sc, dev, MTNOP, 1);
  750. if ((flag & FWRITE) && (sc->sc_vts->status.xst0 & TS_SF_WLK)) {
  751. uprintf("%s: no write ring.\n", device_xname(sc->sc_dev));
  752. sc->sc_openf = 0;
  753. return EROFS;
  754. }
  755. if (sc->sc_vts->status.xst0 & TS_SF_VCK) {
  756. sc->sc_vts->cmd.cmdr = TS_CF_CVC|TS_CF_ACK;
  757. TS_WCSR(TSDB, sc->sc_waddr);
  758. }
  759. tscommand(sc, dev, MTNOP, 1);
  760. #ifdef TSDEBUG
  761. {
  762. char buf[100];
  763. snprintb(buf, sizeof(buf),
  764. TS_XST0_BITS, sc->sc_vts->status.xst0);
  765. printf("tsopen: xst0 %s\n", buf);
  766. }
  767. #endif
  768. sc->sc_liowf = 0;
  769. return 0;
  770. }
  771. /*
  772. * Close tape device.
  773. *
  774. * If tape was open for writing or last operation was
  775. * a write, then write two EOF's and backspace over the last one.
  776. * Unless this is a non-rewinding special file, rewind the tape.
  777. *
  778. * Make the tape available to others, by clearing openf flag.
  779. */
  780. int
  781. tsclose(dev_t dev, int flag, int type, struct lwp *l)
  782. {
  783. struct ts_softc *sc = device_lookup_private(&ts_cd, TS_UNIT(dev));
  784. if (flag == FWRITE || ((flag & FWRITE) && sc->sc_liowf)) {
  785. /*
  786. * We are writing two tape marks (EOT), but place the tape
  787. * before the second one, so that another write operation
  788. * will overwrite the second one and leave and EOF-mark.
  789. */
  790. tscommand(sc, dev, MTWEOF, 1); /* Write Tape Mark */
  791. tscommand(sc, dev, MTWEOF, 1); /* Write Tape Mark */
  792. tscommand(sc, dev, MTBSF, 1); /* Skip Tape Marks Reverse */
  793. }
  794. if ((dev & T_NOREWIND) == 0)
  795. tscommand(sc, dev, MTREW, 0);
  796. sc->sc_openf = 0;
  797. sc->sc_liowf = 0;
  798. return 0;
  799. }
  800. /*
  801. * Manage buffers and perform block mode read and write operations.
  802. */
  803. void
  804. tsstrategy(struct buf *bp)
  805. {
  806. struct ts_softc *sc = device_lookup_private(&ts_cd, TS_UNIT(bp->b_dev));
  807. bool empty;
  808. int s;
  809. #ifdef TSDEBUG
  810. printf("buf: %p bcount %ld blkno %d\n", bp, bp->b_bcount, bp->b_blkno);
  811. #endif
  812. s = splbio ();
  813. empty = (bufq_peek(sc->sc_bufq) == NULL);
  814. bufq_put(sc->sc_bufq, bp);
  815. if (empty)
  816. tsstart(sc, 0);
  817. splx(s);
  818. }
  819. /*
  820. * Catch ioctl commands, and call the "command" routine to do them.
  821. */
  822. int
  823. tsioctl(dev_t dev,
  824. u_long cmd,
  825. void *data,
  826. int flag,
  827. struct lwp *l)
  828. {
  829. struct buf *bp;
  830. struct ts_softc * const sc = device_lookup_private(&ts_cd, TS_UNIT(dev));
  831. struct mtop *mtop; /* mag tape cmd op to perform */
  832. struct mtget *mtget; /* mag tape struct to get info in */
  833. int callcount; /* number of times to call routine */
  834. int scount; /* number of files/records to space */
  835. int spaceop = 0; /* flag for skip/space operation */
  836. int error = 0;
  837. #ifdef TSDEBUG
  838. printf("tsioctl (%x, %lx, %p, %d)\n", dev, cmd, data, flag);
  839. #endif
  840. bp = &sc->ts_cbuf;
  841. switch (cmd) {
  842. case MTIOCTOP: /* do a mag tape op */
  843. mtop = (struct mtop *)data;
  844. switch (mtop->mt_op) {
  845. case MTWEOF: /* write an end-of-file record */
  846. callcount = mtop->mt_count;
  847. scount = 1;
  848. break;
  849. case MTFSR: /* forward space record */
  850. case MTBSR: /* backward space record */
  851. spaceop = 1;
  852. case MTFSF: /* forward space file */
  853. case MTBSF: /* backward space file */
  854. callcount = 1;
  855. scount = mtop->mt_count;
  856. break;
  857. case MTREW: /* rewind */
  858. case MTOFFL: /* rewind and put the drive offline */
  859. case MTNOP: /* no operation, sets status only */
  860. callcount = 1;
  861. scount = 1; /* wait for this rewind */
  862. break;
  863. case MTRETEN: /* retension */
  864. case MTERASE: /* erase entire tape */
  865. case MTEOM: /* forward to end of media */
  866. case MTNBSF: /* backward space to begin of file */
  867. case MTCACHE: /* enable controller cache */
  868. case MTNOCACHE: /* disable controller cache */
  869. case MTSETBSIZ: /* set block size; 0 for variable */
  870. case MTSETDNSTY: /* set density code for current mode */
  871. printf("ioctl %d not implemented.\n", mtop->mt_op);
  872. return (ENXIO);
  873. default:
  874. #ifdef TSDEBUG
  875. printf("invalid ioctl %d\n", mtop->mt_op);
  876. #endif
  877. return (ENXIO);
  878. } /* switch (mtop->mt_op) */
  879. if (callcount <= 0 || scount <= 0) {
  880. #ifdef TSDEBUG
  881. printf("invalid values %d/%d\n", callcount, scount);
  882. #endif
  883. return (EINVAL);
  884. }
  885. do {
  886. tscommand(sc, dev, mtop->mt_op, scount);
  887. if (spaceop && bp->b_resid) {
  888. #ifdef TSDEBUG
  889. printf(("spaceop didn't complete\n"));
  890. #endif
  891. return (EIO);
  892. }
  893. if (bp->b_error != 0) {
  894. #ifdef TSDEBUG
  895. printf("error in ioctl %d\n", mtop->mt_op);
  896. #endif
  897. break;
  898. }
  899. } while (--callcount > 0);
  900. if (bp->b_error != 0)
  901. error = bp->b_error;
  902. return (error);
  903. case MTIOCGET: /* get tape status */
  904. mtget = (struct mtget *)data;
  905. mtget->mt_type = MT_ISTS;
  906. mtget->mt_dsreg = TS_RCSR(TSSR);
  907. mtget->mt_erreg = sc->sc_vts->status.xst0;
  908. mtget->mt_resid = 0; /* ??? */
  909. mtget->mt_density = 0; /* ??? */
  910. break;
  911. case MTIOCIEOT: /* ignore EOT error */
  912. #ifdef TSDEBUG
  913. printf(("MTIOCIEOT not implemented.\n"));
  914. #endif
  915. return (ENXIO);
  916. case MTIOCEEOT: /* enable EOT error */
  917. #ifdef TSDEBUG
  918. printf(("MTIOCEEOT not implemented.\n"));
  919. #endif
  920. return (ENXIO);
  921. default:
  922. #ifdef TSDEBUG
  923. printf("invalid ioctl cmd 0x%lx\n", cmd);
  924. #endif
  925. return (ENXIO);
  926. }
  927. return (0);
  928. }
  929. /*
  930. *
  931. */
  932. int
  933. tsread(dev_t dev, struct uio *uio, int flag)
  934. {
  935. return (physio (tsstrategy, NULL, dev, B_READ, minphys, uio));
  936. }
  937. /*
  938. *
  939. */
  940. int
  941. tswrite(dev_t dev, struct uio *uio, int flag)
  942. {
  943. return (physio (tsstrategy, NULL, dev, B_WRITE, minphys, uio));
  944. }
  945. /*
  946. *
  947. */
  948. int
  949. tsdump(dev_t dev, daddr_t blkno, void *va, size_t size)
  950. {
  951. return EIO;
  952. }