Tue Feb 12 13:43:40 2019 UTC ()
Fix PR kern/53949:

Fix inconsistent/incomplete file mark handling to conform again
to mtio(4) at close(2) time. This was necessary as the PREVENT/ALLOW
bracket was reduced from a whole mount session to cover only the
open(2)/close(2) time on ~2002-03-22. The rationale was to allow
robots and humans to change the media during a mount session.

Unfortunately this lead to file marks being written to potentially other
media at the beginning on drives that used the two file marks as EOM
pattern. In order for that to happen the media had to be removed after
data and at most one file mark had been written before removal.

The mount error message has been clarified and a warning about
potential data/file mark lossage on UNIT ATTENTION
during an active mount session with unfinished file marks has been
added.

While there, fix, but disable the commented SUN compatibility to write
final file marks by opening and immediately closing the device
in O_WRONLY mode. That code has not been working since around 1998.
It can now be enabled with options ST_SUNCOMPAT.

Additionally debug output coverage has been extended.


(kardel)
diff -r1.235 -r1.236 src/sys/dev/scsipi/st.c

cvs diff -r1.235 -r1.236 src/sys/dev/scsipi/st.c (expand / switch to unified diff)

--- src/sys/dev/scsipi/st.c 2019/02/03 03:19:28 1.235
+++ src/sys/dev/scsipi/st.c 2019/02/12 13:43:40 1.236
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: st.c,v 1.235 2019/02/03 03:19:28 mrg Exp $ */ 1/* $NetBSD: st.c,v 1.236 2019/02/12 13:43:40 kardel Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc. 4 * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum. 8 * by Charles M. Hannum.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -40,27 +40,27 @@ @@ -40,27 +40,27 @@
40 * organisations permission to use or modify this software. 40 * organisations permission to use or modify this software.
41 * 41 *
42 * TFS supplies this software to be publicly redistributed 42 * TFS supplies this software to be publicly redistributed
43 * on the understanding that TFS is not responsible for the correct 43 * on the understanding that TFS is not responsible for the correct
44 * functioning of this software in any circumstances. 44 * functioning of this software in any circumstances.
45 * 45 *
46 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 46 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
47 * major changes by Julian Elischer (julian@jules.dialix.oz.au) May 1993 47 * major changes by Julian Elischer (julian@jules.dialix.oz.au) May 1993
48 * 48 *
49 * A lot of rewhacking done by mjacob (mjacob@nas.nasa.gov). 49 * A lot of rewhacking done by mjacob (mjacob@nas.nasa.gov).
50 */ 50 */
51 51
52#include <sys/cdefs.h> 52#include <sys/cdefs.h>
53__KERNEL_RCSID(0, "$NetBSD: st.c,v 1.235 2019/02/03 03:19:28 mrg Exp $"); 53__KERNEL_RCSID(0, "$NetBSD: st.c,v 1.236 2019/02/12 13:43:40 kardel Exp $");
54 54
55#ifdef _KERNEL_OPT 55#ifdef _KERNEL_OPT
56#include "opt_scsi.h" 56#include "opt_scsi.h"
57#endif 57#endif
58 58
59#include <sys/param.h> 59#include <sys/param.h>
60#include <sys/systm.h> 60#include <sys/systm.h>
61#include <sys/fcntl.h> 61#include <sys/fcntl.h>
62#include <sys/errno.h> 62#include <sys/errno.h>
63#include <sys/ioctl.h> 63#include <sys/ioctl.h>
64#include <sys/malloc.h> 64#include <sys/malloc.h>
65#include <sys/buf.h> 65#include <sys/buf.h>
66#include <sys/bufq.h> 66#include <sys/bufq.h>
@@ -605,28 +605,50 @@ stopen(dev_t dev, int flags, int mode, s @@ -605,28 +605,50 @@ stopen(dev_t dev, int flags, int mode, s
605 error = scsipi_test_unit_ready(periph, sflags); 605 error = scsipi_test_unit_ready(periph, sflags);
606 if (error == 0 || stmode == CTRL_MODE) 606 if (error == 0 || stmode == CTRL_MODE)
607 break; 607 break;
608 608
609 /* 609 /*
610 * We had an error. 610 * We had an error.
611 * 611 *
612 * If we're already mounted or we aren't configured for 612 * If we're already mounted or we aren't configured for
613 * a mount delay, or the error isn't a NOT READY error, 613 * a mount delay, or the error isn't a NOT READY error,
614 * skip to the error exit now. 614 * skip to the error exit now.
615 */ 615 */
616 if ((st->flags & ST_MOUNTED) || ST_MOUNT_DELAY == 0 || 616 if ((st->flags & ST_MOUNTED) || ST_MOUNT_DELAY == 0 ||
617 (st->mt_key != SKEY_NOT_READY)) { 617 (st->mt_key != SKEY_NOT_READY)) {
618 device_printf(st->sc_dev, "mount error (key=%d)\n", 618 device_printf(st->sc_dev,
619 st->mt_key); 619 "mount error (sense key=%d) - "
 620 "terminating mount session\n",
 621 st->mt_key);
 622 /*
 623 * the following should not trigger unless
 624 * something serious happened while the device
 625 * was open (PREVENT MEDIUM REMOVAL in effect)
 626 */
 627 if (st->flags & ST_WRITTEN &&
 628 st->mt_key == SKEY_UNIT_ATTENTION) {
 629 /*
 630 * device / media state may have changed
 631 * refrain from writing missing file marks
 632 * onto potentially newly inserted/formatted
 633 * media (e. g. emergency EJECT/RESET/etc.)
 634 */
 635 st->flags &= ~(ST_WRITTEN|ST_FM_WRITTEN);
 636
 637 device_printf(st->sc_dev,
 638 "CAUTION: file marks/data may be missing"
 639 " - ASC = 0x%02x, ASCQ = 0x%02x\n",
 640 st->asc, st->ascq);
 641 }
620 goto bad; 642 goto bad;
621 } 643 }
622 644
623 /* clear any latched errors. */ 645 /* clear any latched errors. */
624 st->mt_resid = 0; 646 st->mt_resid = 0;
625 st->mt_erreg = 0; 647 st->mt_erreg = 0;
626 st->asc = 0; 648 st->asc = 0;
627 st->ascq = 0; 649 st->ascq = 0;
628 650
629 /* 651 /*
630 * Fake that we have the device open so 652 * Fake that we have the device open so
631 * we block other apps from getting in. 653 * we block other apps from getting in.
632 */ 654 */
@@ -717,35 +739,50 @@ stclose(dev_t dev, int flags, int mode,  @@ -717,35 +739,50 @@ stclose(dev_t dev, int flags, int mode,
717 * 739 *
718 * This is for SUN compatibility. Actually, the Sun way of 740 * This is for SUN compatibility. Actually, the Sun way of
719 * things is to: 741 * things is to:
720 * 742 *
721 * only write filemarks if there are fmks to be written and 743 * only write filemarks if there are fmks to be written and
722 * - open for write (possibly read/write) 744 * - open for write (possibly read/write)
723 * - the last operation was a write 745 * - the last operation was a write
724 * or: 746 * or:
725 * - opened for wronly 747 * - opened for wronly
726 * - no data was written (including filemarks) 748 * - no data was written (including filemarks)
727 */ 749 */
728 750
729 stxx = st->flags & (ST_WRITTEN | ST_FM_WRITTEN); 751 stxx = st->flags & (ST_WRITTEN | ST_FM_WRITTEN);
730 if (((flags & FWRITE) && stxx == ST_WRITTEN) || 752 if ((flags & FWRITE) != 0) {
731 ((flags & O_ACCMODE) == FWRITE && stxx == 0)) { 753 int nm = 0;
732 int nm; 754#ifdef ST_SUNCOMPAT
 755 /*
 756 * on request only
 757 * original compat code has not been working
 758 * since ~1998
 759 */
 760 if ((flags & O_ACCMODE) == FWRITE && (stxx == 0)) {
 761 st->flags |= ST_WRITTEN;
 762 SC_DEBUG(st->sc_periph, SCSIPI_DB3,
 763 ("SUN compatibility: write FM(s) at close\n"));
 764 }
 765#endif
733 error = st_check_eod(st, FALSE, &nm, 0); 766 error = st_check_eod(st, FALSE, &nm, 0);
 767 SC_DEBUG(st->sc_periph, SCSIPI_DB3,
 768 ("wrote %d FM(s) at close error=%d\n", nm, error));
734 } 769 }
735 770
736 /* Allow robots to eject tape if needed. */ 771 /* Allow robots to eject tape if needed. */
737 scsipi_prevent(periph, SPAMR_ALLOW, 772 if (!(st->quirks & ST_Q_NOPREVENT)) {
738 XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_NOT_READY); 773 scsipi_prevent(periph, SPAMR_ALLOW,
 774 XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_NOT_READY);
 775 }
739 776
740 switch (STMODE(dev)) { 777 switch (STMODE(dev)) {
741 case NORMAL_MODE: 778 case NORMAL_MODE:
742 st_unmount(st, NOEJECT); 779 st_unmount(st, NOEJECT);
743 break; 780 break;
744 case NOREW_MODE: 781 case NOREW_MODE:
745 case CTRL_MODE: 782 case CTRL_MODE:
746 /* 783 /*
747 * Leave mounted unless media seems to have been removed. 784 * Leave mounted unless media seems to have been removed.
748 * 785 *
749 * Otherwise, if we're to terminate a tape with more than one 786 * Otherwise, if we're to terminate a tape with more than one
750 * filemark [ and because we're not rewinding here ], backspace 787 * filemark [ and because we're not rewinding here ], backspace
751 * one filemark so that later appends will see an unbroken 788 * one filemark so that later appends will see an unbroken
@@ -759,38 +796,48 @@ stclose(dev_t dev, int flags, int mode,  @@ -759,38 +796,48 @@ stclose(dev_t dev, int flags, int mode,
759 /* 796 /*
760 * ST_WRITTEN was preserved from above. 797 * ST_WRITTEN was preserved from above.
761 * 798 *
762 * All we need to know here is: 799 * All we need to know here is:
763 * 800 *
764 * Were we writing this tape and was the last 801 * Were we writing this tape and was the last
765 * operation a write? 802 * operation a write?
766 * 803 *
767 * Are there supposed to be 2FM at EOD? 804 * Are there supposed to be 2FM at EOD?
768 * 805 *
769 * If both statements are true, then we backspace 806 * If both statements are true, then we backspace
770 * one filemark. 807 * one filemark.
771 */ 808 */
 809 stxx &= ~ST_FM_WRITTEN;
772 stxx |= (st->flags & ST_2FM_AT_EOD); 810 stxx |= (st->flags & ST_2FM_AT_EOD);
773 if ((flags & FWRITE) != 0 && 811 if ((flags & FWRITE) != 0 &&
774 (stxx == (ST_2FM_AT_EOD|ST_WRITTEN))) { 812 (stxx == (ST_2FM_AT_EOD|ST_WRITTEN))) {
775 error = st_space(st, -1, SP_FILEMARKS, 0); 813 error = st_space(st, -1, SP_FILEMARKS, 0);
 814 SC_DEBUG(st->sc_periph, SCSIPI_DB3, ("st_space(-1) error=%d\n", error));
 815 } else {
 816 SC_DEBUG(st->sc_periph, SCSIPI_DB3, ("no backspacing - flags = 0x%x, stxx=0x%x, st->flags=0x%x\n", flags, stxx, st->flags));
776 } 817 }
 818 } else {
 819 SC_DEBUG(st->sc_periph, SCSIPI_DB3, ("error %d from st_check_eod\n", error));
777 } 820 }
 821
778 break; 822 break;
779 case EJECT_MODE: 823 case EJECT_MODE:
780 st_unmount(st, EJECT); 824 st_unmount(st, EJECT);
781 break; 825 break;
782 } 826 }
783 827
 828 KASSERTMSG((st->flags & ST_WRITTEN) == 0,
 829 "pending ST_WRITTEN flag NOT cleared (flags=0x%x)", st->flags);
 830
784 scsipi_wait_drain(periph); 831 scsipi_wait_drain(periph);
785 832
786 scsipi_adapter_delref(adapt); 833 scsipi_adapter_delref(adapt);
787 periph->periph_flags &= ~PERIPH_OPEN; 834 periph->periph_flags &= ~PERIPH_OPEN;
788 835
789 return error; 836 return error;
790} 837}
791 838
792/* 839/*
793 * Start a new mount session. 840 * Start a new mount session.
794 * Copy in all the default parameters from the selected device mode. 841 * Copy in all the default parameters from the selected device mode.
795 * and try guess any that seem to be defaulted. 842 * and try guess any that seem to be defaulted.
796 */ 843 */
@@ -898,27 +945,27 @@ static void @@ -898,27 +945,27 @@ static void
898st_unmount(struct st_softc *st, boolean eject) 945st_unmount(struct st_softc *st, boolean eject)
899{ 946{
900 struct scsipi_periph *periph = st->sc_periph; 947 struct scsipi_periph *periph = st->sc_periph;
901 int nmarks; 948 int nmarks;
902 949
903 if ((st->flags & ST_MOUNTED) == 0) 950 if ((st->flags & ST_MOUNTED) == 0)
904 return; 951 return;
905 SC_DEBUG(periph, SCSIPI_DB1, ("unmounting\n")); 952 SC_DEBUG(periph, SCSIPI_DB1, ("unmounting\n"));
906 st_check_eod(st, FALSE, &nmarks, XS_CTL_IGNORE_NOT_READY); 953 st_check_eod(st, FALSE, &nmarks, XS_CTL_IGNORE_NOT_READY);
907 st_rewind(st, 0, XS_CTL_IGNORE_NOT_READY); 954 st_rewind(st, 0, XS_CTL_IGNORE_NOT_READY);
908 955
909 /* 956 /*
910 * Section 9.3.3 of the SCSI specs states that a device shall return 957 * Section 9.3.3 of the SCSI specs states that a device shall return
911 * the density value specified in the last succesfull MODE SELECT 958 * the density value specified in the last successful MODE SELECT
912 * after an unload operation, in case it is not able to 959 * after an unload operation, in case it is not able to
913 * automatically determine the density of the new medium. 960 * automatically determine the density of the new medium.
914 * 961 *
915 * So we instruct the device to use the default density, which will 962 * So we instruct the device to use the default density, which will
916 * prevent the use of stale density values (in particular, 963 * prevent the use of stale density values (in particular,
917 * in st_touch_tape(). 964 * in st_touch_tape().
918 */ 965 */
919 st->density = 0; 966 st->density = 0;
920 if (st->ops(st, ST_OPS_MODESELECT, 0) != 0) { 967 if (st->ops(st, ST_OPS_MODESELECT, 0) != 0) {
921 aprint_error_dev(st->sc_dev, 968 aprint_error_dev(st->sc_dev,
922 "WARNING: cannot revert to default density\n"); 969 "WARNING: cannot revert to default density\n");
923 } 970 }
924 971
@@ -1056,26 +1103,28 @@ ststrategy(struct buf *bp) @@ -1056,26 +1103,28 @@ ststrategy(struct buf *bp)
1056 struct st_softc *st = device_lookup_private(&st_cd, STUNIT(bp->b_dev)); 1103 struct st_softc *st = device_lookup_private(&st_cd, STUNIT(bp->b_dev));
1057 struct scsipi_periph *periph = st->sc_periph; 1104 struct scsipi_periph *periph = st->sc_periph;
1058 struct scsipi_channel *chan = periph->periph_channel; 1105 struct scsipi_channel *chan = periph->periph_channel;
1059 1106
1060 SC_DEBUG(periph, SCSIPI_DB1, 1107 SC_DEBUG(periph, SCSIPI_DB1,
1061 ("ststrategy %d bytes @ blk %" PRId64 "\n", bp->b_bcount, 1108 ("ststrategy %d bytes @ blk %" PRId64 "\n", bp->b_bcount,
1062 bp->b_blkno)); 1109 bp->b_blkno));
1063 /* If it's a null transfer, return immediately */ 1110 /* If it's a null transfer, return immediately */
1064 if (bp->b_bcount == 0) 1111 if (bp->b_bcount == 0)
1065 goto abort; 1112 goto abort;
1066 1113
1067 /* If offset is negative, error */ 1114 /* If offset is negative, error */
1068 if (bp->b_blkno < 0) { 1115 if (bp->b_blkno < 0) {
 1116 SC_DEBUG(periph, SCSIPI_DB3,
 1117 ("EINVAL: ststrategy negative blockcount %ld\n", bp->b_blkno));
1069 bp->b_error = EINVAL; 1118 bp->b_error = EINVAL;
1070 goto abort; 1119 goto abort;
1071 } 1120 }
1072 1121
1073 /* Odd sized request on fixed drives are verboten */ 1122 /* Odd sized request on fixed drives are verboten */
1074 if (st->flags & ST_FIXEDBLOCKS) { 1123 if (st->flags & ST_FIXEDBLOCKS) {
1075 if (bp->b_bcount % st->blksize) { 1124 if (bp->b_bcount % st->blksize) {
1076 aprint_error_dev(st->sc_dev, "bad request, must be multiple of %d\n", 1125 aprint_error_dev(st->sc_dev, "bad request, must be multiple of %d\n",
1077 st->blksize); 1126 st->blksize);
1078 bp->b_error = EIO; 1127 bp->b_error = EIO;
1079 goto abort; 1128 goto abort;
1080 } 1129 }
1081 } 1130 }
@@ -1353,37 +1402,45 @@ stdone(struct scsipi_xfer *xs, int error @@ -1353,37 +1402,45 @@ stdone(struct scsipi_xfer *xs, int error
1353 mutex_exit(&st->sc_iolock); 1402 mutex_exit(&st->sc_iolock);
1354 1403
1355 rnd_add_uint32(&st->rnd_source, bp->b_blkno); 1404 rnd_add_uint32(&st->rnd_source, bp->b_blkno);
1356 1405
1357 biodone(bp); 1406 biodone(bp);
1358 } 1407 }
1359} 1408}
1360 1409
1361static int 1410static int
1362stread(dev_t dev, struct uio *uio, int iomode) 1411stread(dev_t dev, struct uio *uio, int iomode)
1363{ 1412{
1364 struct st_softc *st = device_lookup_private(&st_cd, STUNIT(dev)); 1413 struct st_softc *st = device_lookup_private(&st_cd, STUNIT(dev));
1365 1414
1366 return physio(ststrategy, NULL, dev, B_READ, 1415 int r = physio(ststrategy, NULL, dev, B_READ,
1367 st->sc_periph->periph_channel->chan_adapter->adapt_minphys, uio); 1416 st->sc_periph->periph_channel->chan_adapter->adapt_minphys, uio);
 1417
 1418 SC_DEBUG(st->sc_periph, SCSIPI_DB1, ("[stread: result=%d]\n", r));
 1419
 1420 return r;
1368} 1421}
1369 1422
1370static int 1423static int
1371stwrite(dev_t dev, struct uio *uio, int iomode) 1424stwrite(dev_t dev, struct uio *uio, int iomode)
1372{ 1425{
1373 struct st_softc *st = device_lookup_private(&st_cd, STUNIT(dev)); 1426 struct st_softc *st = device_lookup_private(&st_cd, STUNIT(dev));
1374 1427
1375 return physio(ststrategy, NULL, dev, B_WRITE, 1428 int r = physio(ststrategy, NULL, dev, B_WRITE,
1376 st->sc_periph->periph_channel->chan_adapter->adapt_minphys, uio); 1429 st->sc_periph->periph_channel->chan_adapter->adapt_minphys, uio);
 1430
 1431 SC_DEBUG(st->sc_periph, SCSIPI_DB1, ("[stwrite: result=%d]\n", r));
 1432
 1433 return r;
1377} 1434}
1378 1435
1379/* 1436/*
1380 * Perform special action on behalf of the user; 1437 * Perform special action on behalf of the user;
1381 * knows about the internals of this device 1438 * knows about the internals of this device
1382 */ 1439 */
1383static int 1440static int
1384stioctl(dev_t dev, u_long cmd, void *arg, int flag, struct lwp *l) 1441stioctl(dev_t dev, u_long cmd, void *arg, int flag, struct lwp *l)
1385{ 1442{
1386 int error = 0; 1443 int error = 0;
1387 int unit; 1444 int unit;
1388 int number, nmarks, dsty; 1445 int number, nmarks, dsty;
1389 int flags; 1446 int flags;
@@ -1776,28 +1833,32 @@ st_space(struct st_softc *st, int number @@ -1776,28 +1833,32 @@ st_space(struct st_softc *st, int number
1776/* 1833/*
1777 * write N filemarks 1834 * write N filemarks
1778 */ 1835 */
1779static int 1836static int
1780st_write_filemarks(struct st_softc *st, int number, int flags) 1837st_write_filemarks(struct st_softc *st, int number, int flags)
1781{ 1838{
1782 int error; 1839 int error;
1783 struct scsi_write_filemarks cmd; 1840 struct scsi_write_filemarks cmd;
1784 1841
1785 /* 1842 /*
1786 * It's hard to write a negative number of file marks. 1843 * It's hard to write a negative number of file marks.
1787 * Don't try. 1844 * Don't try.
1788 */ 1845 */
1789 if (number < 0) 1846 if (number < 0) {
 1847 SC_DEBUG(st->sc_periph, SCSIPI_DB3,
 1848 ("EINVAL: st_write_filemarks not writing %d file marks\n", number));
1790 return EINVAL; 1849 return EINVAL;
 1850 }
 1851
1791 switch (number) { 1852 switch (number) {
1792 case 0: /* really a command to sync the drive's buffers */ 1853 case 0: /* really a command to sync the drive's buffers */
1793 break; 1854 break;
1794 case 1: 1855 case 1:
1795 if (st->flags & ST_FM_WRITTEN) /* already have one down */ 1856 if (st->flags & ST_FM_WRITTEN) /* already have one down */
1796 st->flags &= ~ST_WRITTEN; 1857 st->flags &= ~ST_WRITTEN;
1797 else 1858 else
1798 st->flags |= ST_FM_WRITTEN; 1859 st->flags |= ST_FM_WRITTEN;
1799 st->flags &= ~ST_PER_ACTION; 1860 st->flags &= ~ST_PER_ACTION;
1800 break; 1861 break;
1801 default: 1862 default:
1802 st->flags &= ~(ST_PER_ACTION | ST_WRITTEN); 1863 st->flags &= ~(ST_PER_ACTION | ST_WRITTEN);
1803 } 1864 }
@@ -1972,28 +2033,31 @@ st_rdpos(struct st_softc *st, int hard,  @@ -1972,28 +2033,31 @@ st_rdpos(struct st_softc *st, int hard,
1972 cmd.byte1 = 1; 2033 cmd.byte1 = 1;
1973 2034
1974 error = scsipi_command(st->sc_periph, (void *)&cmd, sizeof(cmd), 2035 error = scsipi_command(st->sc_periph, (void *)&cmd, sizeof(cmd),
1975 (void *)&posdata, sizeof(posdata), ST_RETRIES, ST_CTL_TIME, NULL, 2036 (void *)&posdata, sizeof(posdata), ST_RETRIES, ST_CTL_TIME, NULL,
1976 XS_CTL_SILENT | XS_CTL_DATA_IN); 2037 XS_CTL_SILENT | XS_CTL_DATA_IN);
1977 2038
1978 if (error == 0) { 2039 if (error == 0) {
1979#if 0 2040#if 0
1980 printf("posdata:"); 2041 printf("posdata:");
1981 for (hard = 0; hard < sizeof(posdata); hard++) 2042 for (hard = 0; hard < sizeof(posdata); hard++)
1982 printf("%02x ", posdata[hard] & 0xff); 2043 printf("%02x ", posdata[hard] & 0xff);
1983 printf("\n"); 2044 printf("\n");
1984#endif 2045#endif
1985 if (posdata[0] & 0x4) /* Block Position Unknown */ 2046 if (posdata[0] & 0x4) { /* Block Position Unknown */
 2047 SC_DEBUG(st->sc_periph, SCSIPI_DB3,
 2048 ("EINVAL: strdpos block position unknown\n"));
1986 error = EINVAL; 2049 error = EINVAL;
 2050 }
1987 else 2051 else
1988 *blkptr = _4btol(&posdata[4]); 2052 *blkptr = _4btol(&posdata[4]);
1989 } 2053 }
1990 return error; 2054 return error;
1991} 2055}
1992 2056
1993static int 2057static int
1994st_setpos(struct st_softc *st, int hard, uint32_t *blkptr) 2058st_setpos(struct st_softc *st, int hard, uint32_t *blkptr)
1995{ 2059{
1996 int error; 2060 int error;
1997 struct scsi_tape_locate cmd; 2061 struct scsi_tape_locate cmd;
1998 2062
1999 /* 2063 /*