Annotation of src/sys/dev/scsipi/st.c, Revision 1.114.2.6
1.114.2.5 bouyer 1: /* $NetBSD$ */
1.35 cgd 2:
1.101 mycroft 3: /*-
4: * Copyright (c) 1998 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Charles M. Hannum.
1.20 mycroft 9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
1.101 mycroft 20: * This product includes software developed by the NetBSD
21: * Foundation, Inc. and its contributors.
22: * 4. Neither the name of The NetBSD Foundation nor the names of its
23: * contributors may be used to endorse or promote products derived
24: * from this software without specific prior written permission.
1.20 mycroft 25: *
1.101 mycroft 26: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
1.20 mycroft 37: */
38:
39: /*
40: * Originally written by Julian Elischer (julian@tfs.com)
1.7 deraadt 41: * for TRW Financial Systems for use under the MACH(2.5) operating system.
1.1 cgd 42: *
43: * TRW Financial Systems, in accordance with their agreement with Carnegie
44: * Mellon University, makes this software available to CMU to distribute
45: * or use in any manner that they see fit as long as this message is kept with
46: * the software. For this reason TFS also grants any other persons or
47: * organisations permission to use or modify this software.
48: *
49: * TFS supplies this software to be publicly redistributed
50: * on the understanding that TFS is not responsible for the correct
51: * functioning of this software in any circumstances.
1.8 cgd 52: *
1.20 mycroft 53: * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
54: * major changes by Julian Elischer (julian@jules.dialix.oz.au) May 1993
1.95 mjacob 55: *
56: * A lot of rewhacking done by mjacob (mjacob@nas.nasa.gov).
1.1 cgd 57: */
1.74 enami 58:
1.93 mjacob 59: #include "opt_scsi.h"
1.82 explorer 60: #include "rnd.h"
1.1 cgd 61:
1.17 mycroft 62: #include <sys/types.h>
63: #include <sys/param.h>
64: #include <sys/systm.h>
1.20 mycroft 65: #include <sys/fcntl.h>
1.17 mycroft 66: #include <sys/errno.h>
1.20 mycroft 67: #include <sys/ioctl.h>
1.17 mycroft 68: #include <sys/malloc.h>
69: #include <sys/buf.h>
70: #include <sys/proc.h>
71: #include <sys/user.h>
72: #include <sys/mtio.h>
1.20 mycroft 73: #include <sys/device.h>
1.65 christos 74: #include <sys/conf.h>
1.114.2.4 bouyer 75: #include <sys/kernel.h>
1.82 explorer 76: #if NRND > 0
1.80 explorer 77: #include <sys/rnd.h>
1.82 explorer 78: #endif
1.17 mycroft 79:
1.73 bouyer 80: #include <dev/scsipi/scsipi_all.h>
81: #include <dev/scsipi/scsi_all.h>
82: #include <dev/scsipi/scsi_tape.h>
83: #include <dev/scsipi/scsiconf.h>
1.1 cgd 84:
1.20 mycroft 85: /* Defines for device specific stuff */
86: #define DEF_FIXED_BSIZE 512
87: #define ST_RETRIES 4 /* only on non IO commands */
88:
89: #define STMODE(z) ( minor(z) & 0x03)
90: #define STDSTY(z) ((minor(z) >> 2) & 0x03)
91: #define STUNIT(z) ((minor(z) >> 4) )
1.94 mjacob 92:
93: #define NORMAL_MODE 0
94: #define NOREW_MODE 1
95: #define EJECT_MODE 2
96: #define CTRL_MODE 3
1.83 mycroft 97:
98: #define FALSE 0
99: #define TRUE 1
1.1 cgd 100:
1.90 mjacob 101: #define ST_IO_TIME (3 * 60 * 1000) /* 3 minutes */
102: #define ST_CTL_TIME (30 * 1000) /* 30 seconds */
103: #define ST_SPC_TIME (4 * 60 * 60 * 1000) /* 4 hours */
104:
1.114.2.4 bouyer 105: #ifndef ST_MOUNT_DELAY
106: #define ST_MOUNT_DELAY 0
107: #endif
108:
1.67 thorpej 109: /*
1.20 mycroft 110: * Define various devices that we know mis-behave in some way,
111: * and note how they are bad, so we can correct for them
112: */
113: struct modes {
1.44 mycroft 114: u_int quirks; /* same definitions as in quirkdata */
115: int blksize;
116: u_int8_t density;
1.20 mycroft 117: };
118:
1.44 mycroft 119: struct quirkdata {
120: u_int quirks;
121: #define ST_Q_FORCE_BLKSIZE 0x0001
122: #define ST_Q_SENSE_HELP 0x0002 /* must do READ for good MODE SENSE */
123: #define ST_Q_IGNORE_LOADS 0x0004
124: #define ST_Q_BLKSIZE 0x0008 /* variable-block media_blksize > 0 */
1.67 thorpej 125: #define ST_Q_UNIMODAL 0x0010 /* unimode drive rejects mode select */
1.114.2.4 bouyer 126: #define ST_Q_NOPREVENT 0x0020 /* does not support PREVENT */
1.114.2.5 bouyer 127: #define ST_Q_ERASE_NOIMM 0x0040 /* drive rejects ERASE/w Immed bit */
1.36 mycroft 128: u_int page_0_size;
129: #define MAX_PAGE_0_SIZE 64
1.20 mycroft 130: struct modes modes[4];
131: };
132:
1.44 mycroft 133: struct st_quirk_inquiry_pattern {
1.73 bouyer 134: struct scsipi_inquiry_pattern pattern;
1.44 mycroft 135: struct quirkdata quirkdata;
136: };
137:
138: struct st_quirk_inquiry_pattern st_quirk_patterns[] = {
1.59 christos 139: {{T_SEQUENTIAL, T_REMOV,
140: " ", " ", " "}, {0, 0, {
141: {ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 0-3 */
142: {ST_Q_FORCE_BLKSIZE, 512, QIC_24}, /* minor 4-7 */
143: {ST_Q_FORCE_BLKSIZE, 0, HALFINCH_1600}, /* minor 8-11 */
144: {ST_Q_FORCE_BLKSIZE, 0, HALFINCH_6250} /* minor 12-15 */
145: }}},
146: {{T_SEQUENTIAL, T_REMOV,
147: "TANDBERG", " TDC 3600 ", ""}, {0, 12, {
148: {0, 0, 0}, /* minor 0-3 */
149: {ST_Q_FORCE_BLKSIZE, 0, QIC_525}, /* minor 4-7 */
150: {0, 0, QIC_150}, /* minor 8-11 */
151: {0, 0, QIC_120} /* minor 12-15 */
152: }}},
153: {{T_SEQUENTIAL, T_REMOV,
154: "TANDBERG", " TDC 3800 ", ""}, {0, 0, {
1.104 mjacob 155: {ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 0-3 */
156: {0, 0, QIC_525}, /* minor 4-7 */
157: {0, 0, QIC_150}, /* minor 8-11 */
158: {0, 0, QIC_120} /* minor 12-15 */
159: }}},
160: /*
161: * lacking a manual for the 4200, it's not clear what the
162: * specific density codes should be- the device is a 2.5GB
163: * capable QIC drive, those density codes aren't readily
164: * availabel. The 'default' will just have to do.
165: */
166: {{T_SEQUENTIAL, T_REMOV,
167: "TANDBERG", " TDC 4200 ", ""}, {0, 0, {
1.59 christos 168: {ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 0-3 */
169: {0, 0, QIC_525}, /* minor 4-7 */
170: {0, 0, QIC_150}, /* minor 8-11 */
171: {0, 0, QIC_120} /* minor 12-15 */
172: }}},
1.44 mycroft 173: /*
174: * At least -005 and -007 need this. I'll assume they all do unless I
175: * hear otherwise. - mycroft, 31MAR1994
176: */
1.59 christos 177: {{T_SEQUENTIAL, T_REMOV,
178: "ARCHIVE ", "VIPER 2525 25462", ""}, {0, 0, {
179: {ST_Q_SENSE_HELP, 0, 0}, /* minor 0-3 */
180: {ST_Q_SENSE_HELP, 0, QIC_525}, /* minor 4-7 */
181: {0, 0, QIC_150}, /* minor 8-11 */
182: {0, 0, QIC_120} /* minor 12-15 */
183: }}},
1.44 mycroft 184: /*
185: * One user reports that this works for his tape drive. It probably
186: * needs more work. - mycroft, 09APR1994
187: */
1.59 christos 188: {{T_SEQUENTIAL, T_REMOV,
189: "SANKYO ", "CP525 ", ""}, {0, 0, {
190: {ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 0-3 */
191: {ST_Q_FORCE_BLKSIZE, 512, QIC_525}, /* minor 4-7 */
192: {0, 0, QIC_150}, /* minor 8-11 */
193: {0, 0, QIC_120} /* minor 12-15 */
194: }}},
195: {{T_SEQUENTIAL, T_REMOV,
196: "ANRITSU ", "DMT780 ", ""}, {0, 0, {
197: {ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 0-3 */
198: {ST_Q_FORCE_BLKSIZE, 512, QIC_525}, /* minor 4-7 */
199: {0, 0, QIC_150}, /* minor 8-11 */
200: {0, 0, QIC_120} /* minor 12-15 */
201: }}},
202: {{T_SEQUENTIAL, T_REMOV,
1.114.2.5 bouyer 203: "ARCHIVE ", "VIPER 150 21247", ""}, {ST_Q_ERASE_NOIMM, 12, {
1.86 is 204: {ST_Q_SENSE_HELP, 0, 0}, /* minor 0-3 */
1.59 christos 205: {0, 0, QIC_150}, /* minor 4-7 */
206: {0, 0, QIC_120}, /* minor 8-11 */
207: {0, 0, QIC_24} /* minor 12-15 */
208: }}},
209: {{T_SEQUENTIAL, T_REMOV,
1.114.2.5 bouyer 210: "ARCHIVE ", "VIPER 150 21531", ""}, {ST_Q_ERASE_NOIMM, 12, {
1.88 pk 211: {ST_Q_SENSE_HELP, 0, 0}, /* minor 0-3 */
212: {0, 0, QIC_150}, /* minor 4-7 */
213: {0, 0, QIC_120}, /* minor 8-11 */
214: {0, 0, QIC_24} /* minor 12-15 */
215: }}},
216: {{T_SEQUENTIAL, T_REMOV,
1.59 christos 217: "WANGTEK ", "5099ES SCSI", ""}, {0, 0, {
218: {ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 0-3 */
219: {0, 0, QIC_11}, /* minor 4-7 */
220: {0, 0, QIC_24}, /* minor 8-11 */
221: {0, 0, QIC_24} /* minor 12-15 */
222: }}},
223: {{T_SEQUENTIAL, T_REMOV,
224: "WANGTEK ", "5150ES SCSI", ""}, {0, 0, {
225: {ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 0-3 */
226: {0, 0, QIC_24}, /* minor 4-7 */
227: {0, 0, QIC_120}, /* minor 8-11 */
228: {0, 0, QIC_150} /* minor 12-15 */
229: }}},
230: {{T_SEQUENTIAL, T_REMOV,
231: "WANGTEK ", "5525ES SCSI REV7", ""}, {0, 0, {
232: {0, 0, 0}, /* minor 0-3 */
233: {ST_Q_BLKSIZE, 0, QIC_525}, /* minor 4-7 */
234: {0, 0, QIC_150}, /* minor 8-11 */
235: {0, 0, QIC_120} /* minor 12-15 */
236: }}},
237: {{T_SEQUENTIAL, T_REMOV,
238: "WangDAT ", "Model 1300 ", ""}, {0, 0, {
239: {0, 0, 0}, /* minor 0-3 */
240: {ST_Q_FORCE_BLKSIZE, 512, DDS}, /* minor 4-7 */
241: {ST_Q_FORCE_BLKSIZE, 1024, DDS}, /* minor 8-11 */
242: {ST_Q_FORCE_BLKSIZE, 0, DDS} /* minor 12-15 */
243: }}},
244: {{T_SEQUENTIAL, T_REMOV,
245: "EXABYTE ", "EXB-8200 ", "263H"}, {0, 5, {
246: {0, 0, 0}, /* minor 0-3 */
247: {0, 0, 0}, /* minor 4-7 */
248: {0, 0, 0}, /* minor 8-11 */
249: {0, 0, 0} /* minor 12-15 */
250: }}},
1.67 thorpej 251: {{T_SEQUENTIAL, T_REMOV,
1.114.2.5 bouyer 252: "STK", "9490", ""},
1.112 mjacob 253: {ST_Q_FORCE_BLKSIZE, 0, {
1.90 mjacob 254: {0, 0, 0}, /* minor 0-3 */
255: {0, 0, 0}, /* minor 4-7 */
256: {0, 0, 0}, /* minor 8-11 */
257: {0, 0, 0} /* minor 12-15 */
258: }}},
259: {{T_SEQUENTIAL, T_REMOV,
260: "STK", "SD-3", ""},
1.112 mjacob 261: {ST_Q_FORCE_BLKSIZE, 0, {
1.90 mjacob 262: {0, 0, 0}, /* minor 0-3 */
263: {0, 0, 0}, /* minor 4-7 */
264: {0, 0, 0}, /* minor 8-11 */
265: {0, 0, 0} /* minor 12-15 */
266: }}},
267: {{T_SEQUENTIAL, T_REMOV,
1.78 mjacob 268: "IBM", "03590", ""}, {ST_Q_IGNORE_LOADS, 0, {
269: {0, 0, 0}, /* minor 0-3 */
270: {0, 0, 0}, /* minor 4-7 */
271: {0, 0, 0}, /* minor 8-11 */
272: {0, 0, 0} /* minor 12-15 */
273: }}},
274: {{T_SEQUENTIAL, T_REMOV,
1.67 thorpej 275: "HP ", "T4000s ", ""}, {ST_Q_UNIMODAL, 0, {
276: {0, 0, QIC_3095}, /* minor 0-3 */
277: {0, 0, QIC_3095}, /* minor 4-7 */
278: {0, 0, QIC_3095}, /* minor 8-11 */
279: {0, 0, QIC_3095}, /* minor 12-15 */
280: }}},
1.36 mycroft 281: #if 0
1.59 christos 282: {{T_SEQUENTIAL, T_REMOV,
283: "EXABYTE ", "EXB-8200 ", ""}, {0, 12, {
284: {0, 0, 0}, /* minor 0-3 */
285: {0, 0, 0}, /* minor 4-7 */
286: {0, 0, 0}, /* minor 8-11 */
287: {0, 0, 0} /* minor 12-15 */
288: }}},
1.36 mycroft 289: #endif
1.114.2.4 bouyer 290: {{T_SEQUENTIAL, T_REMOV,
291: "TEAC ", "MT-2ST/N50 ", ""}, {ST_Q_IGNORE_LOADS, 0, {
292: {0, 0, 0}, /* minor 0-3 */
293: {0, 0, 0}, /* minor 4-7 */
294: {0, 0, 0}, /* minor 8-11 */
295: {0, 0, 0} /* minor 12-15 */
296: }}},
297: {{T_SEQUENTIAL, T_REMOV,
298: "OnStream", "ADR50 Drive", ""}, {ST_Q_UNIMODAL, 0, {
299: {ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 0-3 */
300: {ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 4-7 */
301: {ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 8-11 */
302: {ST_Q_FORCE_BLKSIZE, 512, 0}, /* minor 12-15 */
303: }}},
304: {{T_SEQUENTIAL, T_REMOV,
305: "NCR H621", "0-STD-03-46F880 ", ""}, {ST_Q_NOPREVENT, 0, {
306: {0, 0, 0}, /* minor 0-3 */
307: {0, 0, 0}, /* minor 4-7 */
308: {0, 0, 0}, /* minor 8-11 */
309: {0, 0, 0} /* minor 12-15 */
310: }}},
1.20 mycroft 311: };
312:
313: #define NOEJECT 0
314: #define EJECT 1
315:
1.44 mycroft 316: struct st_softc {
1.20 mycroft 317: struct device sc_dev;
1.76 enami 318: /*--------------------present operating parameters, flags etc.---------------*/
319: int flags; /* see below */
320: u_int quirks; /* quirks for the open mode */
321: int blksize; /* blksize we are using */
322: u_int8_t density; /* present density */
323: u_int page_0_size; /* size of page 0 data */
1.44 mycroft 324: u_int last_dsty; /* last density opened */
1.90 mjacob 325: short mt_resid; /* last (short) resid */
326: short mt_erreg; /* last error (sense key) seen */
1.114.2.4 bouyer 327: #define mt_key mt_erreg
328: u_int8_t asc; /* last asc code seen */
329: u_int8_t ascq; /* last asc code seen */
1.76 enami 330: /*--------------------device/scsi parameters---------------------------------*/
1.114.2.1 thorpej 331: struct scsipi_periph *sc_periph;/* our link to the adpter etc. */
1.76 enami 332: /*--------------------parameters reported by the device ---------------------*/
1.44 mycroft 333: int blkmin; /* min blk size */
334: int blkmax; /* max blk size */
1.76 enami 335: struct quirkdata *quirkdata; /* if we have a rogue entry */
336: /*--------------------parameters reported by the device for this media-------*/
1.44 mycroft 337: u_long numblks; /* nominal blocks capacity */
338: int media_blksize; /* 0 if not ST_FIXEDBLOCKS */
339: u_int8_t media_density; /* this is what it said when asked */
1.76 enami 340: /*--------------------quirks for the whole drive-----------------------------*/
1.20 mycroft 341: u_int drive_quirks; /* quirks of this drive */
1.44 mycroft 342: /*--------------------How we should set up when opening each minor device----*/
1.20 mycroft 343: struct modes modes[4]; /* plus more for each mode */
1.44 mycroft 344: u_int8_t modeflags[4]; /* flags for the modes */
1.20 mycroft 345: #define DENSITY_SET_BY_USER 0x01
346: #define DENSITY_SET_BY_QUIRK 0x02
347: #define BLKSIZE_SET_BY_USER 0x04
348: #define BLKSIZE_SET_BY_QUIRK 0x08
1.76 enami 349: /*--------------------storage for sense data returned by the drive-----------*/
1.36 mycroft 350: u_char sense_data[MAX_PAGE_0_SIZE]; /*
351: * additional sense data needed
352: * for mode sense/select.
353: */
1.114.2.4 bouyer 354: struct buf_queue buf_queue; /* the queue of pending IO */
1.76 enami 355: /* operations */
1.82 explorer 356: #if NRND > 0
1.80 explorer 357: rndsource_element_t rnd_source;
1.82 explorer 358: #endif
1.20 mycroft 359: };
360:
1.59 christos 361:
1.70 cgd 362: int stmatch __P((struct device *, struct cfdata *, void *));
1.59 christos 363: void stattach __P((struct device *, struct device *, void *));
1.73 bouyer 364: void st_identify_drive __P((struct st_softc *,
1.76 enami 365: struct scsipi_inquiry_pattern *));
1.59 christos 366: void st_loadquirks __P((struct st_softc *));
1.114.2.6! bouyer 367: int st_mount_tape __P((dev_t, int));
1.59 christos 368: void st_unmount __P((struct st_softc *, boolean));
369: int st_decide_mode __P((struct st_softc *, boolean));
1.114.2.1 thorpej 370: void ststart __P((struct scsipi_periph *));
1.80 explorer 371: void stdone __P((struct scsipi_xfer *));
1.59 christos 372: int st_read __P((struct st_softc *, char *, int, int));
373: int st_read_block_limits __P((struct st_softc *, int));
374: int st_mode_sense __P((struct st_softc *, int));
375: int st_mode_select __P((struct st_softc *, int));
1.75 mjacob 376: int st_cmprss __P((struct st_softc *, int));
1.59 christos 377: int st_space __P((struct st_softc *, int, u_int, int));
378: int st_write_filemarks __P((struct st_softc *, int, int));
379: int st_check_eod __P((struct st_softc *, boolean, int *, int));
380: int st_load __P((struct st_softc *, u_int, int));
381: int st_rewind __P((struct st_softc *, u_int, int));
1.73 bouyer 382: int st_interpret_sense __P((struct scsipi_xfer *));
1.59 christos 383: int st_touch_tape __P((struct st_softc *));
384: int st_erase __P((struct st_softc *, int full, int flags));
1.75 mjacob 385: int st_rdpos __P((struct st_softc *, int, u_int32_t *));
386: int st_setpos __P((struct st_softc *, int, u_int32_t *));
1.20 mycroft 387:
1.63 thorpej 388: struct cfattach st_ca = {
389: sizeof(struct st_softc), stmatch, stattach
390: };
391:
1.87 thorpej 392: extern struct cfdriver st_cd;
1.20 mycroft 393:
1.114.2.1 thorpej 394: const struct scsipi_periphsw st_switch = {
1.20 mycroft 395: st_interpret_sense,
396: ststart,
397: NULL,
1.96 mjacob 398: stdone
1.20 mycroft 399: };
400:
1.41 mycroft 401: #define ST_INFO_VALID 0x0001
402: #define ST_BLOCK_SET 0x0002 /* block size, mode set by ioctl */
1.99 mjacob 403: #define ST_WRITTEN 0x0004 /* data has been written, EOD needed */
1.41 mycroft 404: #define ST_FIXEDBLOCKS 0x0008
405: #define ST_AT_FILEMARK 0x0010
1.93 mjacob 406: #define ST_EIO_PENDING 0x0020 /* error reporting deferred until next op */
1.76 enami 407: #define ST_NEW_MOUNT 0x0040 /* still need to decide mode */
1.41 mycroft 408: #define ST_READONLY 0x0080 /* st_mode_sense says write protected */
409: #define ST_FM_WRITTEN 0x0100 /*
1.20 mycroft 410: * EOF file mark written -- used with
411: * ~ST_WRITTEN to indicate that multiple file
412: * marks have been written
413: */
1.41 mycroft 414: #define ST_BLANK_READ 0x0200 /* BLANK CHECK encountered already */
415: #define ST_2FM_AT_EOD 0x0400 /* write 2 file marks at EOD */
416: #define ST_MOUNTED 0x0800 /* Device is presently mounted */
1.57 thorpej 417: #define ST_DONTBUFFER 0x1000 /* Disable buffering/caching */
1.93 mjacob 418: #define ST_EARLYWARN 0x2000 /* Do (deferred) EOM for variable mode */
419: #define ST_EOM_PENDING 0x4000 /* EOM reporting deferred until next op */
1.20 mycroft 420:
1.93 mjacob 421: #define ST_PER_ACTION (ST_AT_FILEMARK | ST_EIO_PENDING | ST_EOM_PENDING | \
422: ST_BLANK_READ)
1.76 enami 423: #define ST_PER_MOUNT (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
424: ST_FIXEDBLOCKS | ST_READONLY | ST_FM_WRITTEN | \
1.44 mycroft 425: ST_2FM_AT_EOD | ST_PER_ACTION)
426:
1.93 mjacob 427: #if defined(ST_ENABLE_EARLYWARN)
428: #define ST_INIT_FLAGS ST_EARLYWARN
429: #else
430: #define ST_INIT_FLAGS 0
431: #endif
432:
1.73 bouyer 433: struct scsipi_inquiry_pattern st_patterns[] = {
1.44 mycroft 434: {T_SEQUENTIAL, T_REMOV,
435: "", "", ""},
436: };
437:
438: int
439: stmatch(parent, match, aux)
440: struct device *parent;
1.70 cgd 441: struct cfdata *match;
442: void *aux;
1.44 mycroft 443: {
1.73 bouyer 444: struct scsipibus_attach_args *sa = aux;
1.44 mycroft 445: int priority;
446:
1.73 bouyer 447: (void)scsipi_inqmatch(&sa->sa_inqbuf,
1.44 mycroft 448: (caddr_t)st_patterns, sizeof(st_patterns)/sizeof(st_patterns[0]),
449: sizeof(st_patterns[0]), &priority);
450: return (priority);
451: }
1.1 cgd 452:
1.3 deraadt 453: /*
454: * The routine called by the low level scsi routine when it discovers
455: * A device suitable for this driver
456: */
1.51 mycroft 457: void
1.20 mycroft 458: stattach(parent, self, aux)
459: struct device *parent, *self;
460: void *aux;
1.1 cgd 461: {
1.44 mycroft 462: struct st_softc *st = (void *)self;
1.73 bouyer 463: struct scsipibus_attach_args *sa = aux;
1.114.2.1 thorpej 464: struct scsipi_periph *periph = sa->sa_periph;
1.1 cgd 465:
1.114.2.3 thorpej 466: SC_DEBUG(periph, SCSIPI_DB2, ("stattach: "));
1.1 cgd 467:
1.20 mycroft 468: /*
469: * Store information needed to contact our base driver
470: */
1.114.2.1 thorpej 471: st->sc_periph = periph;
472: periph->periph_dev = &st->sc_dev;
473: periph->periph_switch = &st_switch;
1.3 deraadt 474:
1.20 mycroft 475: /*
1.93 mjacob 476: * Set initial flags
477: */
478:
479: st->flags = ST_INIT_FLAGS;
480:
481: /*
1.20 mycroft 482: * Check if the drive is a known criminal and take
483: * Any steps needed to bring it into line
484: */
1.73 bouyer 485: st_identify_drive(st, &sa->sa_inqbuf);
1.3 deraadt 486: /*
1.114.2.6! bouyer 487: * Use the subdriver to request information regarding the drive.
1.3 deraadt 488: */
1.69 christos 489: printf("\n");
490: printf("%s: %s", st->sc_dev.dv_xname, st->quirkdata ? "rogue, " : "");
1.114.2.1 thorpej 491: if (scsipi_test_unit_ready(periph,
1.114 thorpej 492: XS_CTL_DISCOVERY | XS_CTL_SILENT | XS_CTL_IGNORE_MEDIA_CHANGE) ||
1.44 mycroft 493: st_mode_sense(st,
1.114 thorpej 494: XS_CTL_DISCOVERY | XS_CTL_SILENT | XS_CTL_IGNORE_MEDIA_CHANGE))
1.69 christos 495: printf("drive empty\n");
1.20 mycroft 496: else {
1.114.2.4 bouyer 497: printf("density code %d, ", st->media_density);
1.44 mycroft 498: if (st->media_blksize > 0)
1.69 christos 499: printf("%d-byte", st->media_blksize);
1.20 mycroft 500: else
1.69 christos 501: printf("variable");
502: printf(" blocks, write-%s\n",
1.20 mycroft 503: (st->flags & ST_READONLY) ? "protected" : "enabled");
504: }
1.1 cgd 505:
1.3 deraadt 506: /*
1.20 mycroft 507: * Set up the buf queue for this device
1.3 deraadt 508: */
1.114.2.4 bouyer 509: BUFQ_INIT(&st->buf_queue);
1.80 explorer 510:
1.82 explorer 511: #if NRND > 0
1.110 explorer 512: rnd_attach_source(&st->rnd_source, st->sc_dev.dv_xname,
513: RND_TYPE_TAPE, 0);
1.82 explorer 514: #endif
1.20 mycroft 515: }
516:
517: /*
518: * Use the inquiry routine in 'scsi_base' to get drive info so we can
519: * Further tailor our behaviour.
520: */
521: void
1.44 mycroft 522: st_identify_drive(st, inqbuf)
523: struct st_softc *st;
1.73 bouyer 524: struct scsipi_inquiry_pattern *inqbuf;
1.44 mycroft 525: {
526: struct st_quirk_inquiry_pattern *finger;
527: int priority;
528:
1.73 bouyer 529: finger = (struct st_quirk_inquiry_pattern *)scsipi_inqmatch(inqbuf,
1.44 mycroft 530: (caddr_t)st_quirk_patterns,
1.76 enami 531: sizeof(st_quirk_patterns) / sizeof(st_quirk_patterns[0]),
1.44 mycroft 532: sizeof(st_quirk_patterns[0]), &priority);
533: if (priority != 0) {
534: st->quirkdata = &finger->quirkdata;
535: st->drive_quirks = finger->quirkdata.quirks;
536: st->quirks = finger->quirkdata.quirks; /* start value */
537: st->page_0_size = finger->quirkdata.page_0_size;
538: st_loadquirks(st);
1.20 mycroft 539: }
540: }
541:
542: /*
543: * initialise the subdevices to the default (QUIRK) state.
544: * this will remove any setting made by the system operator or previous
545: * operations.
546: */
547: void
548: st_loadquirks(st)
1.44 mycroft 549: struct st_softc *st;
1.20 mycroft 550: {
551: int i;
552: struct modes *mode;
553: struct modes *mode2;
554:
1.44 mycroft 555: mode = st->quirkdata->modes;
1.20 mycroft 556: mode2 = st->modes;
557: for (i = 0; i < 4; i++) {
558: bzero(mode2, sizeof(struct modes));
559: st->modeflags[i] &= ~(BLKSIZE_SET_BY_QUIRK |
560: DENSITY_SET_BY_QUIRK | BLKSIZE_SET_BY_USER |
561: DENSITY_SET_BY_USER);
1.44 mycroft 562: if ((mode->quirks | st->drive_quirks) & ST_Q_FORCE_BLKSIZE) {
563: mode2->blksize = mode->blksize;
1.20 mycroft 564: st->modeflags[i] |= BLKSIZE_SET_BY_QUIRK;
565: }
566: if (mode->density) {
567: mode2->density = mode->density;
568: st->modeflags[i] |= DENSITY_SET_BY_QUIRK;
569: }
1.114.2.5 bouyer 570: mode2->quirks |= mode->quirks;
1.20 mycroft 571: mode++;
572: mode2++;
573: }
1.1 cgd 574: }
575:
1.3 deraadt 576: /*
1.20 mycroft 577: * open the device.
578: */
1.76 enami 579: int
1.59 christos 580: stopen(dev, flags, mode, p)
1.20 mycroft 581: dev_t dev;
1.27 mycroft 582: int flags;
1.59 christos 583: int mode;
584: struct proc *p;
1.1 cgd 585: {
1.59 christos 586: u_int stmode, dsty;
1.114.2.4 bouyer 587: int error, sflags, unit, tries, ntries;
1.44 mycroft 588: struct st_softc *st;
1.114.2.1 thorpej 589: struct scsipi_periph *periph;
590: struct scsipi_adapter *adapt;
1.1 cgd 591:
1.20 mycroft 592: unit = STUNIT(dev);
1.63 thorpej 593: if (unit >= st_cd.cd_ndevs)
1.76 enami 594: return (ENXIO);
1.63 thorpej 595: st = st_cd.cd_devs[unit];
1.76 enami 596: if (st == NULL)
597: return (ENXIO);
1.3 deraadt 598:
1.59 christos 599: stmode = STMODE(dev);
1.41 mycroft 600: dsty = STDSTY(dev);
1.114.2.1 thorpej 601:
602: periph = st->sc_periph;
603: adapt = periph->periph_channel->chan_adapter;
1.41 mycroft 604:
1.114.2.3 thorpej 605: SC_DEBUG(periph, SCSIPI_DB1, ("open: dev=0x%x (unit %d (of %d))\n", dev,
1.63 thorpej 606: unit, st_cd.cd_ndevs));
1.20 mycroft 607:
1.96 mjacob 608:
1.41 mycroft 609: /*
610: * Only allow one at a time
611: */
1.114.2.1 thorpej 612: if (periph->periph_flags & PERIPH_OPEN) {
1.69 christos 613: printf("%s: already open\n", st->sc_dev.dv_xname);
1.76 enami 614: return (EBUSY);
1.41 mycroft 615: }
1.20 mycroft 616:
1.114.2.1 thorpej 617: if ((error = scsipi_adapter_addref(adapt)) != 0)
1.106 thorpej 618: return (error);
619:
1.3 deraadt 620: /*
1.96 mjacob 621: * clear any latched errors.
622: */
623: st->mt_resid = 0;
624: st->mt_erreg = 0;
1.114.2.4 bouyer 625: st->asc = 0;
626: st->ascq = 0;
1.96 mjacob 627:
628: /*
1.114.2.4 bouyer 629: * Catch any unit attention errors. Be silent about this
630: * unless we're already mounted. We ignore media change
631: * if we're in control mode or not mounted yet.
1.3 deraadt 632: */
1.114.2.4 bouyer 633: if ((st->flags & ST_MOUNTED) == 0 || stmode == CTRL_MODE) {
634: #ifdef SCSIDEBUG
635: sflags = XS_CTL_IGNORE_MEDIA_CHANGE;
636: #else
637: sflags = XS_CTL_SILENT|XS_CTL_IGNORE_MEDIA_CHANGE;
638: #endif
639: } else
640: sflags = 0;
641:
642: /*
643: * If we're already mounted or we aren't configured for
644: * a mount delay, only try a test unit ready once. Otherwise,
645: * try up to ST_MOUNT_DELAY times with a rest interval of
646: * one second between each try.
647: */
648:
649: if ((st->flags & ST_MOUNTED) || ST_MOUNT_DELAY == 0) {
650: ntries = 1;
651: } else {
652: ntries = ST_MOUNT_DELAY;
1.96 mjacob 653: }
1.114.2.4 bouyer 654:
1.114.2.6! bouyer 655: for (error = tries = 0; tries < ntries; tries++) {
! 656: int slpintr, oflags;
1.114.2.4 bouyer 657:
1.114.2.6! bouyer 658: /*
! 659: * If we had no error, or we're opening the control mode
! 660: * device, we jump out right away.
! 661: */
! 662:
! 663: error = scsipi_test_unit_ready(periph, sflags);
! 664: if (error == 0 || stmode == CTRL_MODE) {
! 665: break;
! 666: }
! 667:
! 668: /*
! 669: * We had an error.
! 670: *
! 671: * If we're already mounted or we aren't configured for
! 672: * a mount delay, or the error isn't a NOT READY error,
! 673: * skip to the error exit now.
! 674: */
! 675: if ((st->flags & ST_MOUNTED) || ST_MOUNT_DELAY == 0 ||
! 676: (st->mt_key != SKEY_NOT_READY)) {
! 677: goto bad;
! 678: }
! 679:
! 680: /*
! 681: * clear any latched errors.
! 682: */
! 683: st->mt_resid = 0;
! 684: st->mt_erreg = 0;
! 685: st->asc = 0;
! 686: st->ascq = 0;
! 687:
! 688: /*
! 689: * Fake that we have the device open so
! 690: * we block other apps from getting in.
! 691: */
! 692:
! 693: oflags = periph->periph_flags;
! 694: periph->periph_flags |= PERIPH_OPEN;
! 695:
! 696: slpintr = tsleep(&lbolt, PUSER|PCATCH, "stload", 0);
! 697:
! 698: periph->periph_flags = oflags; /* restore flags */
! 699: if (slpintr) {
! 700: goto bad;
! 701: }
! 702: }
1.114.2.4 bouyer 703:
1.41 mycroft 704:
1.3 deraadt 705: /*
1.96 mjacob 706: * If the mode is 3 (e.g. minor = 3,7,11,15) then the device has
707: * been opened to set defaults and perform other, usually non-I/O
708: * related, operations. In this case, do a quick check to see
709: * whether the unit actually had a tape loaded (this will be known
710: * as to whether or not we got a NOT READY for the above
711: * unit attention). If a tape is there, go do a mount sequence.
1.3 deraadt 712: */
1.114.2.4 bouyer 713: if (stmode == CTRL_MODE && st->mt_key == SKEY_NOT_READY) {
714: periph->periph_flags |= PERIPH_OPEN;
1.76 enami 715: return (0);
1.94 mjacob 716: }
1.20 mycroft 717:
1.3 deraadt 718: /*
1.114.2.4 bouyer 719: * If we get this far and had an error set, that means we failed
720: * to pass the 'test unit ready' test for the non-controlmode device,
721: * so we bounce the open.
722: */
723:
724: if (error)
725: return (error);
726:
727: /*
728: * Else, we're now committed to saying we're open.
729: */
730:
731: periph->periph_flags |= PERIPH_OPEN; /* unit attn are now errors */
732:
733: /*
1.96 mjacob 734: * If it's a different mode, or if the media has been
1.20 mycroft 735: * invalidated, unmount the tape from the previous
736: * session but continue with open processing
737: */
1.114.2.1 thorpej 738: if (st->last_dsty != dsty ||
739: (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)
1.20 mycroft 740: st_unmount(st, NOEJECT);
1.3 deraadt 741:
742: /*
1.51 mycroft 743: * If we are not mounted, then we should start a new
1.20 mycroft 744: * mount session.
1.3 deraadt 745: */
1.114.2.5 bouyer 746: if (!(st->flags & ST_MOUNTED)) {
747: if ((error = st_mount_tape(dev, flags)) != 0)
748: goto bad;
1.20 mycroft 749: st->last_dsty = dsty;
1.3 deraadt 750: }
1.1 cgd 751:
1.114.2.3 thorpej 752: SC_DEBUG(periph, SCSIPI_DB2, ("open complete\n"));
1.76 enami 753: return (0);
1.1 cgd 754:
1.41 mycroft 755: bad:
1.44 mycroft 756: st_unmount(st, NOEJECT);
1.114.2.1 thorpej 757: scsipi_adapter_delref(adapt);
758: periph->periph_flags &= ~PERIPH_OPEN;
1.76 enami 759: return (error);
1.20 mycroft 760: }
1.1 cgd 761:
1.20 mycroft 762: /*
763: * close the device.. only called if we are the LAST
764: * occurence of an open device
765: */
1.76 enami 766: int
1.59 christos 767: stclose(dev, flags, mode, p)
1.20 mycroft 768: dev_t dev;
1.59 christos 769: int flags;
770: int mode;
771: struct proc *p;
1.20 mycroft 772: {
1.97 mjacob 773: int stxx, error = 0;
1.63 thorpej 774: struct st_softc *st = st_cd.cd_devs[STUNIT(dev)];
1.114.2.1 thorpej 775: struct scsipi_periph *periph = st->sc_periph;
776: struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
1.1 cgd 777:
1.114.2.3 thorpej 778: SC_DEBUG(st->sc_periph, SCSIPI_DB1, ("closing\n"));
1.96 mjacob 779:
780: /*
781: * Make sure that a tape opened in write-only mode will have
782: * file marks written on it when closed, even if not written to.
783: *
784: * This is for SUN compatibility. Actually, the Sun way of
785: * things is to:
786: *
787: * only write filemarks if there are fmks to be written and
788: * - open for write (possibly read/write)
789: * - the last operation was a write
790: * or:
791: * - opened for wronly
792: * - no data was written (including filemarks)
793: */
794:
795: stxx = st->flags & (ST_WRITTEN | ST_FM_WRITTEN);
1.99 mjacob 796: if (((flags & FWRITE) && stxx == ST_WRITTEN) ||
797: ((flags & O_ACCMODE) == FWRITE && stxx == 0)) {
798: int nm;
799: error = st_check_eod(st, FALSE, &nm, 0);
800: }
801:
1.41 mycroft 802: switch (STMODE(dev)) {
1.94 mjacob 803: case NORMAL_MODE:
1.20 mycroft 804: st_unmount(st, NOEJECT);
805: break;
1.94 mjacob 806: case NOREW_MODE:
1.96 mjacob 807: case CTRL_MODE:
1.99 mjacob 808: /*
809: * Leave mounted unless media seems to have been removed.
810: *
811: * Otherwise, if we're to terminate a tape with more than one
812: * filemark [ and because we're not rewinding here ], backspace
813: * one filemark so that later appends will see an unbroken
814: * sequence of:
815: *
816: * file - FMK - file - FMK ... file - FMK FMK (EOM)
817: */
1.114.2.1 thorpej 818: if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
1.20 mycroft 819: st_unmount(st, NOEJECT);
1.99 mjacob 820: } else if (error == 0) {
821: /*
822: * ST_WRITTEN was preserved from above.
823: *
824: * All we need to know here is:
825: *
826: * Were we writing this tape and was the last
827: * operation a write?
828: *
829: * Are there supposed to be 2FM at EOD?
1.114.2.5 bouyer 830: *
1.99 mjacob 831: * If both statements are true, then we backspace
832: * one filemark.
833: */
834: stxx |= (st->flags & ST_2FM_AT_EOD);
835: if ((flags & FWRITE) != 0 &&
836: (stxx == (ST_2FM_AT_EOD|ST_WRITTEN))) {
837: error = st_space(st, -1, SP_FILEMARKS, 0);
838: }
839: }
1.20 mycroft 840: break;
1.94 mjacob 841: case EJECT_MODE:
1.20 mycroft 842: st_unmount(st, EJECT);
843: break;
844: }
1.107 thorpej 845:
1.114.2.1 thorpej 846: scsipi_wait_drain(periph);
1.106 thorpej 847:
1.114.2.1 thorpej 848: scsipi_adapter_delref(adapt);
849: periph->periph_flags &= ~PERIPH_OPEN;
1.41 mycroft 850:
1.97 mjacob 851: return (error);
1.20 mycroft 852: }
1.1 cgd 853:
1.20 mycroft 854: /*
855: * Start a new mount session.
856: * Copy in all the default parameters from the selected device mode.
857: * and try guess any that seem to be defaulted.
858: */
859: int
1.114.2.6! bouyer 860: st_mount_tape(dev, flags)
! 861: dev_t dev;
! 862: int flags;
1.114.2.1 thorpej 863: {
1.114.2.6! bouyer 864: int unit;
! 865: u_int dsty;
! 866: struct st_softc *st;
! 867: struct scsipi_periph *periph;
1.20 mycroft 868: int error = 0;
1.1 cgd 869:
1.114.2.6! bouyer 870: unit = STUNIT(dev);
! 871: dsty = STDSTY(dev);
! 872: st = st_cd.cd_devs[unit];
! 873: periph = st->sc_periph;
! 874:
1.20 mycroft 875: if (st->flags & ST_MOUNTED)
1.76 enami 876: return (0);
1.1 cgd 877:
1.114.2.3 thorpej 878: SC_DEBUG(periph, SCSIPI_DB1, ("mounting\n "));
1.20 mycroft 879: st->flags |= ST_NEW_MOUNT;
880: st->quirks = st->drive_quirks | st->modes[dsty].quirks;
881: /*
882: * If the media is new, then make sure we give it a chance to
883: * to do a 'load' instruction. (We assume it is new.)
884: */
1.114.2.4 bouyer 885: if ((error = st_load(st, LD_LOAD, XS_CTL_SILENT)) != 0)
1.76 enami 886: return (error);
1.20 mycroft 887: /*
888: * Throw another dummy instruction to catch
1.90 mjacob 889: * 'Unit attention' errors. Many drives give
890: * these after doing a Load instruction (with
891: * the MEDIUM MAY HAVE CHANGED asc/ascq).
1.20 mycroft 892: */
1.114.2.1 thorpej 893: scsipi_test_unit_ready(periph, XS_CTL_SILENT); /* XXX */
1.1 cgd 894:
1.3 deraadt 895: /*
1.20 mycroft 896: * Some devices can't tell you much until they have been
897: * asked to look at the media. This quirk does this.
898: */
1.28 mycroft 899: if (st->quirks & ST_Q_SENSE_HELP)
1.59 christos 900: if ((error = st_touch_tape(st)) != 0)
1.76 enami 901: return (error);
1.20 mycroft 902: /*
1.3 deraadt 903: * Load the physical device parameters
1.20 mycroft 904: * loads: blkmin, blkmax
905: */
1.59 christos 906: if ((error = st_read_block_limits(st, 0)) != 0)
1.76 enami 907: return (error);
1.20 mycroft 908: /*
909: * Load the media dependent parameters
1.44 mycroft 910: * includes: media_blksize,media_density,numblks
1.20 mycroft 911: * As we have a tape in, it should be reflected here.
912: * If not you may need the "quirk" above.
913: */
1.59 christos 914: if ((error = st_mode_sense(st, 0)) != 0)
1.76 enami 915: return (error);
1.20 mycroft 916: /*
917: * If we have gained a permanent density from somewhere,
918: * then use it in preference to the one supplied by
919: * default by the driver.
1.3 deraadt 920: */
1.20 mycroft 921: if (st->modeflags[dsty] & (DENSITY_SET_BY_QUIRK | DENSITY_SET_BY_USER))
922: st->density = st->modes[dsty].density;
923: else
924: st->density = st->media_density;
925: /*
926: * If we have gained a permanent blocksize
927: * then use it in preference to the one supplied by
928: * default by the driver.
929: */
930: st->flags &= ~ST_FIXEDBLOCKS;
1.76 enami 931: if (st->modeflags[dsty] &
932: (BLKSIZE_SET_BY_QUIRK | BLKSIZE_SET_BY_USER)) {
1.44 mycroft 933: st->blksize = st->modes[dsty].blksize;
934: if (st->blksize)
1.20 mycroft 935: st->flags |= ST_FIXEDBLOCKS;
936: } else {
1.59 christos 937: if ((error = st_decide_mode(st, FALSE)) != 0)
1.76 enami 938: return (error);
1.20 mycroft 939: }
1.59 christos 940: if ((error = st_mode_select(st, 0)) != 0) {
1.69 christos 941: printf("%s: cannot set selected mode\n", st->sc_dev.dv_xname);
1.76 enami 942: return (error);
1.20 mycroft 943: }
1.114.2.4 bouyer 944: if (!(st->quirks & ST_Q_NOPREVENT)) {
945: scsipi_prevent(periph, PR_PREVENT,
946: XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_NOT_READY);
947: }
1.20 mycroft 948: st->flags &= ~ST_NEW_MOUNT;
949: st->flags |= ST_MOUNTED;
1.114.2.1 thorpej 950: periph->periph_flags |= PERIPH_MEDIA_LOADED; /* move earlier? */
1.1 cgd 951:
1.76 enami 952: return (0);
1.1 cgd 953: }
954:
1.3 deraadt 955: /*
1.20 mycroft 956: * End the present mount session.
957: * Rewind, and optionally eject the tape.
958: * Reset various flags to indicate that all new
959: * operations require another mount operation
960: */
961: void
962: st_unmount(st, eject)
1.44 mycroft 963: struct st_softc *st;
1.20 mycroft 964: boolean eject;
1.1 cgd 965: {
1.114.2.1 thorpej 966: struct scsipi_periph *periph = st->sc_periph;
1.20 mycroft 967: int nmarks;
968:
1.114.2.1 thorpej 969: if ((st->flags & ST_MOUNTED) == 0)
1.20 mycroft 970: return;
1.114.2.3 thorpej 971: SC_DEBUG(periph, SCSIPI_DB1, ("unmounting\n"));
1.114 thorpej 972: st_check_eod(st, FALSE, &nmarks, XS_CTL_IGNORE_NOT_READY);
973: st_rewind(st, 0, XS_CTL_IGNORE_NOT_READY);
1.114.2.5 bouyer 974:
975: /*
976: * Section 9.3.3 of the SCSI specs states that a device shall return
977: * the density value specified in the last succesfull MODE SELECT
978: * after an unload operation, in case it is not able to
979: * automatically determine the density of the new medium.
980: *
981: * So we instruct the device to use the default density, which will
982: * prevent the use of stale density values (in particular,
983: * in st_touch_tape().
984: */
985: st->density = 0;
986: if (st_mode_select(st, 0) != 0) {
987: printf("%s: WARNING: cannot revert to default density\n",
988: st->sc_dev.dv_xname);
989: }
990:
1.114.2.1 thorpej 991: scsipi_prevent(periph, PR_ALLOW,
1.114 thorpej 992: XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_NOT_READY);
1.20 mycroft 993: if (eject)
1.114 thorpej 994: st_load(st, LD_UNLOAD, XS_CTL_IGNORE_NOT_READY);
1.20 mycroft 995: st->flags &= ~(ST_MOUNTED | ST_NEW_MOUNT);
1.114.2.1 thorpej 996: periph->periph_flags &= ~PERIPH_MEDIA_LOADED;
1.20 mycroft 997: }
998:
999: /*
1000: * Given all we know about the device, media, mode, 'quirks' and
1001: * initial operation, make a decision as to how we should be set
1002: * to run (regarding blocking and EOD marks)
1003: */
1.51 mycroft 1004: int
1.20 mycroft 1005: st_decide_mode(st, first_read)
1.44 mycroft 1006: struct st_softc *st;
1.20 mycroft 1007: boolean first_read;
1008: {
1009:
1.114.2.3 thorpej 1010: SC_DEBUG(st->sc_periph, SCSIPI_DB2, ("starting block mode decision\n"));
1.20 mycroft 1011:
1012: /*
1013: * If the drive can only handle fixed-length blocks and only at
1014: * one size, perhaps we should just do that.
1015: */
1016: if (st->blkmin && (st->blkmin == st->blkmax)) {
1017: st->flags |= ST_FIXEDBLOCKS;
1.44 mycroft 1018: st->blksize = st->blkmin;
1.114.2.3 thorpej 1019: SC_DEBUG(st->sc_periph, SCSIPI_DB3,
1.20 mycroft 1020: ("blkmin == blkmax of %d\n", st->blkmin));
1021: goto done;
1022: }
1023: /*
1024: * If the tape density mandates (or even suggests) use of fixed
1025: * or variable-length blocks, comply.
1026: */
1027: switch (st->density) {
1028: case HALFINCH_800:
1029: case HALFINCH_1600:
1030: case HALFINCH_6250:
1031: case DDS:
1032: st->flags &= ~ST_FIXEDBLOCKS;
1.44 mycroft 1033: st->blksize = 0;
1.114.2.3 thorpej 1034: SC_DEBUG(st->sc_periph, SCSIPI_DB3,
1035: ("density specified variable\n"));
1.20 mycroft 1036: goto done;
1037: case QIC_11:
1038: case QIC_24:
1039: case QIC_120:
1040: case QIC_150:
1041: case QIC_525:
1042: case QIC_1320:
1.114.2.4 bouyer 1043: case QIC_3095:
1044: case QIC_3220:
1.20 mycroft 1045: st->flags |= ST_FIXEDBLOCKS;
1.44 mycroft 1046: if (st->media_blksize > 0)
1047: st->blksize = st->media_blksize;
1.20 mycroft 1048: else
1.44 mycroft 1049: st->blksize = DEF_FIXED_BSIZE;
1.114.2.3 thorpej 1050: SC_DEBUG(st->sc_periph, SCSIPI_DB3,
1051: ("density specified fixed\n"));
1.20 mycroft 1052: goto done;
1053: }
1054: /*
1055: * If we're about to read the tape, perhaps we should choose
1056: * fixed or variable-length blocks and block size according to
1057: * what the drive found on the tape.
1058: */
1059: if (first_read &&
1.44 mycroft 1060: (!(st->quirks & ST_Q_BLKSIZE) || (st->media_blksize == 0) ||
1061: (st->media_blksize == DEF_FIXED_BSIZE) ||
1062: (st->media_blksize == 1024))) {
1063: if (st->media_blksize > 0)
1064: st->flags |= ST_FIXEDBLOCKS;
1065: else
1.20 mycroft 1066: st->flags &= ~ST_FIXEDBLOCKS;
1.44 mycroft 1067: st->blksize = st->media_blksize;
1.114.2.3 thorpej 1068: SC_DEBUG(st->sc_periph, SCSIPI_DB3,
1.44 mycroft 1069: ("Used media_blksize of %d\n", st->media_blksize));
1.20 mycroft 1070: goto done;
1071: }
1072: /*
1073: * We're getting no hints from any direction. Choose variable-
1074: * length blocks arbitrarily.
1075: */
1076: st->flags &= ~ST_FIXEDBLOCKS;
1.44 mycroft 1077: st->blksize = 0;
1.114.2.3 thorpej 1078: SC_DEBUG(st->sc_periph, SCSIPI_DB3,
1.20 mycroft 1079: ("Give up and default to variable mode\n"));
1.44 mycroft 1080:
1.20 mycroft 1081: done:
1082: /*
1083: * Decide whether or not to write two file marks to signify end-
1084: * of-data. Make the decision as a function of density. If
1085: * the decision is not to use a second file mark, the SCSI BLANK
1086: * CHECK condition code will be recognized as end-of-data when
1087: * first read.
1088: * (I think this should be a by-product of fixed/variable..julian)
1089: */
1090: switch (st->density) {
1091: /* case 8 mm: What is the SCSI density code for 8 mm, anyway? */
1092: case QIC_11:
1093: case QIC_24:
1094: case QIC_120:
1095: case QIC_150:
1096: case QIC_525:
1097: case QIC_1320:
1.114.2.4 bouyer 1098: case QIC_3095:
1099: case QIC_3220:
1.20 mycroft 1100: st->flags &= ~ST_2FM_AT_EOD;
1.1 cgd 1101: break;
1102: default:
1.20 mycroft 1103: st->flags |= ST_2FM_AT_EOD;
1.1 cgd 1104: }
1.76 enami 1105: return (0);
1.1 cgd 1106: }
1107:
1.3 deraadt 1108: /*
1109: * Actually translate the requested transfer into
1110: * one the physical driver can understand
1111: * The transfer is described by a buf and will include
1112: * only one physical transfer.
1113: */
1.51 mycroft 1114: void
1.20 mycroft 1115: ststrategy(bp)
1116: struct buf *bp;
1.1 cgd 1117: {
1.63 thorpej 1118: struct st_softc *st = st_cd.cd_devs[STUNIT(bp->b_dev)];
1.53 mycroft 1119: int s;
1.1 cgd 1120:
1.114.2.3 thorpej 1121: SC_DEBUG(st->sc_periph, SCSIPI_DB1,
1.66 christos 1122: ("ststrategy %ld bytes @ blk %d\n", bp->b_bcount, bp->b_blkno));
1.20 mycroft 1123: /*
1124: * If it's a null transfer, return immediatly
1125: */
1.40 mycroft 1126: if (bp->b_bcount == 0)
1.3 deraadt 1127: goto done;
1.109 bouyer 1128:
1129: /* If offset is negative, error */
1130: if (bp->b_blkno < 0) {
1131: bp->b_error = EINVAL;
1132: goto bad;
1133: }
1134:
1.3 deraadt 1135: /*
1136: * Odd sized request on fixed drives are verboten
1137: */
1.20 mycroft 1138: if (st->flags & ST_FIXEDBLOCKS) {
1.44 mycroft 1139: if (bp->b_bcount % st->blksize) {
1.69 christos 1140: printf("%s: bad request, must be multiple of %d\n",
1.44 mycroft 1141: st->sc_dev.dv_xname, st->blksize);
1.20 mycroft 1142: bp->b_error = EIO;
1143: goto bad;
1144: }
1145: }
1146: /*
1147: * as are out-of-range requests on variable drives.
1148: */
1.29 mycroft 1149: else if (bp->b_bcount < st->blkmin ||
1.76 enami 1150: (st->blkmax && bp->b_bcount > st->blkmax)) {
1.69 christos 1151: printf("%s: bad request, must be between %d and %d\n",
1.20 mycroft 1152: st->sc_dev.dv_xname, st->blkmin, st->blkmax);
1.1 cgd 1153: bp->b_error = EIO;
1154: goto bad;
1155: }
1.53 mycroft 1156: s = splbio();
1.1 cgd 1157:
1.3 deraadt 1158: /*
1.20 mycroft 1159: * Place it in the queue of activities for this tape
1160: * at the end (a bit silly because we only have on user..
1161: * (but it could fork()))
1.3 deraadt 1162: */
1.114.2.4 bouyer 1163: BUFQ_INSERT_TAIL(&st->buf_queue, bp);
1.1 cgd 1164:
1.3 deraadt 1165: /*
1166: * Tell the device to get going on the transfer if it's
1.20 mycroft 1167: * not doing anything, otherwise just wait for completion
1168: * (All a bit silly if we're only allowing 1 open but..)
1.3 deraadt 1169: */
1.114.2.1 thorpej 1170: ststart(st->sc_periph);
1.1 cgd 1171:
1.53 mycroft 1172: splx(s);
1.1 cgd 1173: return;
1174: bad:
1175: bp->b_flags |= B_ERROR;
1176: done:
1.3 deraadt 1177: /*
1178: * Correctly set the buf to indicate a completed xfer
1179: */
1.56 pk 1180: bp->b_resid = bp->b_bcount;
1181: biodone(bp);
1.1 cgd 1182: return;
1183: }
1184:
1.3 deraadt 1185: /*
1186: * ststart looks to see if there is a buf waiting for the device
1187: * and that the device is not already busy. If both are true,
1.20 mycroft 1188: * It dequeues the buf and creates a scsi command to perform the
1.73 bouyer 1189: * transfer required. The transfer request will call scsipi_done
1.3 deraadt 1190: * on completion, which will in turn call this routine again
1191: * so that the next queued transfer is performed.
1192: * The bufs are queued by the strategy routine (ststrategy)
1193: *
1194: * This routine is also called after other non-queued requests
1195: * have been made of the scsi driver, to ensure that the queue
1196: * continues to be drained.
1.20 mycroft 1197: * ststart() is called at splbio
1198: */
1.76 enami 1199: void
1.114.2.1 thorpej 1200: ststart(periph)
1201: struct scsipi_periph *periph;
1.1 cgd 1202: {
1.114.2.1 thorpej 1203: struct st_softc *st = (void *)periph->periph_dev;
1.114.2.4 bouyer 1204: struct buf *bp;
1.3 deraadt 1205: struct scsi_rw_tape cmd;
1.111 mycroft 1206: int flags, error;
1.3 deraadt 1207:
1.114.2.3 thorpej 1208: SC_DEBUG(periph, SCSIPI_DB2, ("ststart "));
1.3 deraadt 1209: /*
1210: * See if there is a buf to do and we are not already
1211: * doing one
1212: */
1.114.2.1 thorpej 1213: while (periph->periph_active < periph->periph_openings) {
1.20 mycroft 1214: /* if a special awaits, let it proceed first */
1.114.2.1 thorpej 1215: if (periph->periph_flags & PERIPH_WAITING) {
1216: periph->periph_flags &= ~PERIPH_WAITING;
1217: wakeup((caddr_t)periph);
1.20 mycroft 1218: return;
1219: }
1220:
1.114.2.4 bouyer 1221: if ((bp = BUFQ_FIRST(&st->buf_queue)) == NULL)
1.61 mycroft 1222: return;
1.114.2.4 bouyer 1223: BUFQ_REMOVE(&st->buf_queue, bp);
1.20 mycroft 1224:
1225: /*
1.114.2.4 bouyer 1226: * If the device has been unmounted by the user
1227: * then throw away all requests until done.
1.20 mycroft 1228: */
1.114.2.1 thorpej 1229: if ((st->flags & ST_MOUNTED) == 0 ||
1230: (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
1.20 mycroft 1231: /* make sure that one implies the other.. */
1.114.2.1 thorpej 1232: periph->periph_flags &= ~PERIPH_MEDIA_LOADED;
1.33 chopps 1233: bp->b_flags |= B_ERROR;
1234: bp->b_error = EIO;
1.71 thorpej 1235: bp->b_resid = bp->b_bcount;
1.33 chopps 1236: biodone(bp);
1237: continue;
1.20 mycroft 1238: }
1239: /*
1.93 mjacob 1240: * only FIXEDBLOCK devices have pending I/O or space operations.
1.20 mycroft 1241: */
1242: if (st->flags & ST_FIXEDBLOCKS) {
1243: /*
1244: * If we are at a filemark but have not reported it yet
1245: * then we should report it now
1246: */
1247: if (st->flags & ST_AT_FILEMARK) {
1248: if ((bp->b_flags & B_READ) == B_WRITE) {
1249: /*
1250: * Handling of ST_AT_FILEMARK in
1251: * st_space will fill in the right file
1252: * mark count.
1253: * Back up over filemark
1254: */
1.33 chopps 1255: if (st_space(st, 0, SP_FILEMARKS, 0)) {
1256: bp->b_flags |= B_ERROR;
1257: bp->b_error = EIO;
1258: biodone(bp);
1259: continue;
1260: }
1.20 mycroft 1261: } else {
1262: bp->b_resid = bp->b_bcount;
1263: bp->b_error = 0;
1264: bp->b_flags &= ~B_ERROR;
1265: st->flags &= ~ST_AT_FILEMARK;
1266: biodone(bp);
1267: continue; /* seek more work */
1268: }
1269: }
1.93 mjacob 1270: }
1271: /*
1272: * If we are at EOM but have not reported it
1.114.2.5 bouyer 1273: * yet then we should report it now.
1.93 mjacob 1274: */
1275: if (st->flags & (ST_EOM_PENDING|ST_EIO_PENDING)) {
1276: bp->b_resid = bp->b_bcount;
1.20 mycroft 1277: if (st->flags & ST_EIO_PENDING) {
1278: bp->b_error = EIO;
1279: bp->b_flags |= B_ERROR;
1280: }
1.93 mjacob 1281: st->flags &= ~(ST_EOM_PENDING|ST_EIO_PENDING);
1282: biodone(bp);
1283: continue; /* seek more work */
1.20 mycroft 1284: }
1.28 mycroft 1285:
1.20 mycroft 1286: /*
1.114.2.1 thorpej 1287: * Fill out the scsi command
1.20 mycroft 1288: */
1289: bzero(&cmd, sizeof(cmd));
1.114.2.1 thorpej 1290: flags = XS_CTL_NOSLEEP | XS_CTL_ASYNC;
1.20 mycroft 1291: if ((bp->b_flags & B_READ) == B_WRITE) {
1.44 mycroft 1292: cmd.opcode = WRITE;
1.20 mycroft 1293: st->flags &= ~ST_FM_WRITTEN;
1.114.2.1 thorpej 1294: flags |= XS_CTL_DATA_OUT;
1.20 mycroft 1295: } else {
1.44 mycroft 1296: cmd.opcode = READ;
1.114.2.1 thorpej 1297: flags |= XS_CTL_DATA_IN;
1.20 mycroft 1298: }
1.28 mycroft 1299:
1.20 mycroft 1300: /*
1301: * Handle "fixed-block-mode" tape drives by using the
1302: * block count instead of the length.
1303: */
1304: if (st->flags & ST_FIXEDBLOCKS) {
1.28 mycroft 1305: cmd.byte2 |= SRW_FIXED;
1.64 mycroft 1306: _lto3b(bp->b_bcount / st->blksize, cmd.len);
1.28 mycroft 1307: } else
1.64 mycroft 1308: _lto3b(bp->b_bcount, cmd.len);
1.28 mycroft 1309:
1.20 mycroft 1310: /*
1311: * go ask the adapter to do all this for us
1312: */
1.114.2.1 thorpej 1313: error = scsipi_command(periph,
1.76 enami 1314: (struct scsipi_generic *)&cmd, sizeof(cmd),
1315: (u_char *)bp->b_data, bp->b_bcount,
1.114.2.1 thorpej 1316: 0, ST_IO_TIME, bp, flags);
1.111 mycroft 1317: if (error) {
1318: printf("%s: not queued, error %d\n",
1319: st->sc_dev.dv_xname, error);
1320: }
1.20 mycroft 1321: } /* go back and see if we can cram more work in.. */
1.80 explorer 1322: }
1323:
1324: void
1325: stdone(xs)
1326: struct scsipi_xfer *xs;
1327: {
1.114.2.1 thorpej 1328: struct st_softc *st = (void *)xs->xs_periph->periph_dev;
1.80 explorer 1329:
1.96 mjacob 1330: if (xs->bp != NULL) {
1331: if ((xs->bp->b_flags & B_READ) == B_WRITE) {
1332: st->flags |= ST_WRITTEN;
1.99 mjacob 1333: } else {
1334: st->flags &= ~ST_WRITTEN;
1.96 mjacob 1335: }
1336: #if NRND > 0
1.80 explorer 1337: rnd_add_uint32(&st->rnd_source, xs->bp->b_blkno);
1.96 mjacob 1338: #endif
1339: }
1.49 mycroft 1340: }
1341:
1342: int
1.59 christos 1343: stread(dev, uio, iomode)
1.49 mycroft 1344: dev_t dev;
1345: struct uio *uio;
1.59 christos 1346: int iomode;
1.49 mycroft 1347: {
1.63 thorpej 1348: struct st_softc *st = st_cd.cd_devs[STUNIT(dev)];
1.49 mycroft 1349:
1.51 mycroft 1350: return (physio(ststrategy, NULL, dev, B_READ,
1.114.2.1 thorpej 1351: st->sc_periph->periph_channel->chan_adapter->adapt_minphys, uio));
1.49 mycroft 1352: }
1353:
1354: int
1.59 christos 1355: stwrite(dev, uio, iomode)
1.49 mycroft 1356: dev_t dev;
1357: struct uio *uio;
1.59 christos 1358: int iomode;
1.49 mycroft 1359: {
1.63 thorpej 1360: struct st_softc *st = st_cd.cd_devs[STUNIT(dev)];
1.49 mycroft 1361:
1.51 mycroft 1362: return (physio(ststrategy, NULL, dev, B_WRITE,
1.114.2.1 thorpej 1363: st->sc_periph->periph_channel->chan_adapter->adapt_minphys, uio));
1.20 mycroft 1364: }
1.1 cgd 1365:
1.20 mycroft 1366: /*
1367: * Perform special action on behalf of the user;
1368: * knows about the internals of this device
1369: */
1.51 mycroft 1370: int
1.44 mycroft 1371: stioctl(dev, cmd, arg, flag, p)
1.20 mycroft 1372: dev_t dev;
1.39 cgd 1373: u_long cmd;
1.20 mycroft 1374: caddr_t arg;
1375: int flag;
1.44 mycroft 1376: struct proc *p;
1.20 mycroft 1377: {
1378: int error = 0;
1379: int unit;
1380: int number, nmarks, dsty;
1.27 mycroft 1381: int flags;
1.44 mycroft 1382: struct st_softc *st;
1383: int hold_blksize;
1384: u_int8_t hold_density;
1.20 mycroft 1385: struct mtop *mt = (struct mtop *) arg;
1.1 cgd 1386:
1.3 deraadt 1387: /*
1.20 mycroft 1388: * Find the device that the user is talking about
1.3 deraadt 1389: */
1.20 mycroft 1390: flags = 0; /* give error messages, act on errors etc. */
1391: unit = STUNIT(dev);
1392: dsty = STDSTY(dev);
1.63 thorpej 1393: st = st_cd.cd_devs[unit];
1.44 mycroft 1394: hold_blksize = st->blksize;
1.20 mycroft 1395: hold_density = st->density;
1396:
1.75 mjacob 1397: switch ((u_int) cmd) {
1.20 mycroft 1398:
1399: case MTIOCGET: {
1400: struct mtget *g = (struct mtget *) arg;
1.90 mjacob 1401: /*
1402: * (to get the current state of READONLY)
1403: */
1.114 thorpej 1404: error = st_mode_sense(st, XS_CTL_SILENT);
1.114.2.5 bouyer 1405: if (error) {
1406: /*
1407: * Ignore the error if in control mode;
1408: * this is mandated by st(4).
1409: */
1410: if (STMODE(dev) != CTRL_MODE)
1411: break;
1412: error = 0;
1413: }
1.114.2.3 thorpej 1414: SC_DEBUG(st->sc_periph, SCSIPI_DB1, ("[ioctl: get status]\n"));
1.20 mycroft 1415: bzero(g, sizeof(struct mtget));
1416: g->mt_type = 0x7; /* Ultrix compat *//*? */
1.44 mycroft 1417: g->mt_blksiz = st->blksize;
1.20 mycroft 1418: g->mt_density = st->density;
1.44 mycroft 1419: g->mt_mblksiz[0] = st->modes[0].blksize;
1420: g->mt_mblksiz[1] = st->modes[1].blksize;
1421: g->mt_mblksiz[2] = st->modes[2].blksize;
1422: g->mt_mblksiz[3] = st->modes[3].blksize;
1.20 mycroft 1423: g->mt_mdensity[0] = st->modes[0].density;
1424: g->mt_mdensity[1] = st->modes[1].density;
1425: g->mt_mdensity[2] = st->modes[2].density;
1426: g->mt_mdensity[3] = st->modes[3].density;
1.90 mjacob 1427: if (st->flags & ST_READONLY)
1428: g->mt_dsreg |= MT_DS_RDONLY;
1429: if (st->flags & ST_MOUNTED)
1430: g->mt_dsreg |= MT_DS_MOUNTED;
1431: g->mt_resid = st->mt_resid;
1432: g->mt_erreg = st->mt_erreg;
1433: /*
1434: * clear latched errors.
1435: */
1436: st->mt_resid = 0;
1437: st->mt_erreg = 0;
1.114.2.4 bouyer 1438: st->asc = 0;
1439: st->ascq = 0;
1.20 mycroft 1440: break;
1.1 cgd 1441: }
1.20 mycroft 1442: case MTIOCTOP: {
1.1 cgd 1443:
1.114.2.3 thorpej 1444: SC_DEBUG(st->sc_periph, SCSIPI_DB1,
1.76 enami 1445: ("[ioctl: op=0x%x count=0x%x]\n", mt->mt_op,
1446: mt->mt_count));
1.1 cgd 1447:
1448: /* compat: in U*x it is a short */
1449: number = mt->mt_count;
1.20 mycroft 1450: switch ((short) (mt->mt_op)) {
1.1 cgd 1451: case MTWEOF: /* write an end-of-file record */
1.20 mycroft 1452: error = st_write_filemarks(st, number, flags);
1.1 cgd 1453: break;
1.20 mycroft 1454: case MTBSF: /* backward space file */
1455: number = -number;
1.1 cgd 1456: case MTFSF: /* forward space file */
1.28 mycroft 1457: error = st_check_eod(st, FALSE, &nmarks, flags);
1.20 mycroft 1458: if (!error)
1459: error = st_space(st, number - nmarks,
1460: SP_FILEMARKS, flags);
1.1 cgd 1461: break;
1.20 mycroft 1462: case MTBSR: /* backward space record */
1463: number = -number;
1.1 cgd 1464: case MTFSR: /* forward space record */
1.28 mycroft 1465: error = st_check_eod(st, TRUE, &nmarks, flags);
1.20 mycroft 1466: if (!error)
1467: error = st_space(st, number, SP_BLKS, flags);
1.1 cgd 1468: break;
1469: case MTREW: /* rewind */
1.28 mycroft 1470: error = st_rewind(st, 0, flags);
1.1 cgd 1471: break;
1472: case MTOFFL: /* rewind and put the drive offline */
1.20 mycroft 1473: st_unmount(st, EJECT);
1.1 cgd 1474: break;
1475: case MTNOP: /* no operation, sets status only */
1.22 mycroft 1476: break;
1.23 mycroft 1477: case MTRETEN: /* retension the tape */
1.28 mycroft 1478: error = st_load(st, LD_RETENSION, flags);
1.24 mycroft 1479: if (!error)
1480: error = st_load(st, LD_LOAD, flags);
1.23 mycroft 1481: break;
1.22 mycroft 1482: case MTEOM: /* forward space to end of media */
1.28 mycroft 1483: error = st_check_eod(st, FALSE, &nmarks, flags);
1.22 mycroft 1484: if (!error)
1485: error = st_space(st, 1, SP_EOM, flags);
1486: break;
1.1 cgd 1487: case MTCACHE: /* enable controller cache */
1.57 thorpej 1488: st->flags &= ~ST_DONTBUFFER;
1489: goto try_new_value;
1.1 cgd 1490: case MTNOCACHE: /* disable controller cache */
1.57 thorpej 1491: st->flags |= ST_DONTBUFFER;
1492: goto try_new_value;
1493: case MTERASE: /* erase volume */
1494: error = st_erase(st, number, flags);
1.1 cgd 1495: break;
1.20 mycroft 1496: case MTSETBSIZ: /* Set block size for device */
1497: #ifdef NOTYET
1498: if (!(st->flags & ST_NEW_MOUNT)) {
1499: uprintf("re-mount tape before changing blocksize");
1500: error = EINVAL;
1501: break;
1502: }
1503: #endif
1.76 enami 1504: if (number == 0)
1.20 mycroft 1505: st->flags &= ~ST_FIXEDBLOCKS;
1.76 enami 1506: else {
1.20 mycroft 1507: if ((st->blkmin || st->blkmax) &&
1508: (number < st->blkmin ||
1509: number > st->blkmax)) {
1510: error = EINVAL;
1511: break;
1512: }
1513: st->flags |= ST_FIXEDBLOCKS;
1514: }
1.44 mycroft 1515: st->blksize = number;
1.20 mycroft 1516: st->flags |= ST_BLOCK_SET; /*XXX */
1517: goto try_new_value;
1518:
1519: case MTSETDNSTY: /* Set density for device and mode */
1.94 mjacob 1520: /*
1521: * Any number >= 0 and <= 0xff is legal. Numbers
1522: * above 0x80 are 'vendor unique'.
1523: */
1524: if (number < 0 || number > 255) {
1.20 mycroft 1525: error = EINVAL;
1.57 thorpej 1526: break;
1527: } else
1.20 mycroft 1528: st->density = number;
1529: goto try_new_value;
1530:
1.75 mjacob 1531: case MTCMPRESS:
1532: error = st_cmprss(st, number);
1533: break;
1534:
1.93 mjacob 1535: case MTEWARN:
1536: if (number)
1537: st->flags |= ST_EARLYWARN;
1538: else
1539: st->flags &= ~ST_EARLYWARN;
1540: break;
1541:
1.1 cgd 1542: default:
1.20 mycroft 1543: error = EINVAL;
1.1 cgd 1544: }
1545: break;
1.20 mycroft 1546: }
1.1 cgd 1547: case MTIOCIEOT:
1548: case MTIOCEEOT:
1.20 mycroft 1549: break;
1.75 mjacob 1550:
1551: case MTIOCRDSPOS:
1552: error = st_rdpos(st, 0, (u_int32_t *) arg);
1553: break;
1554:
1555: case MTIOCRDHPOS:
1556: error = st_rdpos(st, 1, (u_int32_t *) arg);
1557: break;
1558:
1559: case MTIOCSLOCATE:
1560: error = st_setpos(st, 0, (u_int32_t *) arg);
1561: break;
1562:
1563: case MTIOCHLOCATE:
1564: error = st_setpos(st, 1, (u_int32_t *) arg);
1565: break;
1566:
1.93 mjacob 1567:
1.20 mycroft 1568: default:
1.114.2.1 thorpej 1569: error = scsipi_do_ioctl(st->sc_periph, dev, cmd, arg,
1.92 drochner 1570: flag, p);
1.1 cgd 1571: break;
1572: }
1.76 enami 1573: return (error);
1.20 mycroft 1574: /*-----------------------------*/
1575: try_new_value:
1576: /*
1577: * Check that the mode being asked for is aggreeable to the
1578: * drive. If not, put it back the way it was.
1.114.2.5 bouyer 1579: *
1580: * If in control mode, we can make (persistent) mode changes
1581: * even if no medium is loaded (see st(4)).
1.20 mycroft 1582: */
1.114.2.5 bouyer 1583: if ((STMODE(dev) != CTRL_MODE || (st->flags & ST_MOUNTED) != 0) &&
1584: (error = st_mode_select(st, 0)) != 0) {
1585: /* put it back as it was */
1.69 christos 1586: printf("%s: cannot set selected mode\n", st->sc_dev.dv_xname);
1.20 mycroft 1587: st->density = hold_density;
1.44 mycroft 1588: st->blksize = hold_blksize;
1589: if (st->blksize)
1.20 mycroft 1590: st->flags |= ST_FIXEDBLOCKS;
1591: else
1592: st->flags &= ~ST_FIXEDBLOCKS;
1.76 enami 1593: return (error);
1.20 mycroft 1594: }
1595: /*
1596: * As the drive liked it, if we are setting a new default,
1597: * set it into the structures as such.
1.51 mycroft 1598: *
1.94 mjacob 1599: * The means for deciding this are not finalised yet- but
1600: * if the device was opened in Control Mode, the values
1601: * are persistent now across mounts.
1.20 mycroft 1602: */
1.94 mjacob 1603: if (STMODE(dev) == CTRL_MODE) {
1.20 mycroft 1604: switch ((short) (mt->mt_op)) {
1605: case MTSETBSIZ:
1.44 mycroft 1606: st->modes[dsty].blksize = st->blksize;
1.20 mycroft 1607: st->modeflags[dsty] |= BLKSIZE_SET_BY_USER;
1608: break;
1609: case MTSETDNSTY:
1610: st->modes[dsty].density = st->density;
1611: st->modeflags[dsty] |= DENSITY_SET_BY_USER;
1612: break;
1613: }
1614: }
1.76 enami 1615: return (0);
1.1 cgd 1616: }
1617:
1.3 deraadt 1618: /*
1.20 mycroft 1619: * Do a synchronous read.
1620: */
1.51 mycroft 1621: int
1.20 mycroft 1622: st_read(st, buf, size, flags)
1.44 mycroft 1623: struct st_softc *st;
1624: int size;
1.27 mycroft 1625: int flags;
1.20 mycroft 1626: char *buf;
1.1 cgd 1627: {
1.28 mycroft 1628: struct scsi_rw_tape cmd;
1.1 cgd 1629:
1.20 mycroft 1630: /*
1631: * If it's a null transfer, return immediatly
1632: */
1633: if (size == 0)
1.76 enami 1634: return (0);
1.28 mycroft 1635: bzero(&cmd, sizeof(cmd));
1.44 mycroft 1636: cmd.opcode = READ;
1.20 mycroft 1637: if (st->flags & ST_FIXEDBLOCKS) {
1.28 mycroft 1638: cmd.byte2 |= SRW_FIXED;
1.64 mycroft 1639: _lto3b(size / (st->blksize ? st->blksize : DEF_FIXED_BSIZE),
1.28 mycroft 1640: cmd.len);
1.20 mycroft 1641: } else
1.64 mycroft 1642: _lto3b(size, cmd.len);
1.114.2.1 thorpej 1643: return (scsipi_command(st->sc_periph,
1.76 enami 1644: (struct scsipi_generic *)&cmd, sizeof(cmd),
1.114 thorpej 1645: (u_char *)buf, size, 0, ST_IO_TIME, NULL, flags | XS_CTL_DATA_IN));
1.1 cgd 1646: }
1647:
1.3 deraadt 1648: /*
1649: * Ask the drive what it's min and max blk sizes are.
1.20 mycroft 1650: */
1.51 mycroft 1651: int
1.28 mycroft 1652: st_read_block_limits(st, flags)
1.44 mycroft 1653: struct st_softc *st;
1.27 mycroft 1654: int flags;
1.1 cgd 1655: {
1.28 mycroft 1656: struct scsi_block_limits cmd;
1657: struct scsi_block_limits_data block_limits;
1.114.2.1 thorpej 1658: struct scsipi_periph *periph = st->sc_periph;
1.20 mycroft 1659: int error;
1.3 deraadt 1660:
1661: /*
1662: * do a 'Read Block Limits'
1663: */
1.28 mycroft 1664: bzero(&cmd, sizeof(cmd));
1.44 mycroft 1665: cmd.opcode = READ_BLOCK_LIMITS;
1.1 cgd 1666:
1.3 deraadt 1667: /*
1.20 mycroft 1668: * do the command, update the global values
1.3 deraadt 1669: */
1.114.2.1 thorpej 1670: error = scsipi_command(periph, (struct scsipi_generic *)&cmd,
1.76 enami 1671: sizeof(cmd), (u_char *)&block_limits, sizeof(block_limits),
1.114.2.4 bouyer 1672: ST_RETRIES, ST_CTL_TIME, NULL,
1673: flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK);
1.59 christos 1674: if (error)
1.76 enami 1675: return (error);
1.3 deraadt 1676:
1.64 mycroft 1677: st->blkmin = _2btol(block_limits.min_length);
1678: st->blkmax = _3btol(block_limits.max_length);
1.1 cgd 1679:
1.114.2.3 thorpej 1680: SC_DEBUG(periph, SCSIPI_DB3,
1.44 mycroft 1681: ("(%d <= blksize <= %d)\n", st->blkmin, st->blkmax));
1.76 enami 1682: return (0);
1.1 cgd 1683: }
1.3 deraadt 1684:
1685: /*
1686: * Get the scsi driver to send a full inquiry to the
1.51 mycroft 1687: * device and use the results to fill out the global
1.3 deraadt 1688: * parameter structure.
1.20 mycroft 1689: *
1690: * called from:
1691: * attach
1692: * open
1693: * ioctl (to reset original blksize)
1694: */
1.51 mycroft 1695: int
1.20 mycroft 1696: st_mode_sense(st, flags)
1.44 mycroft 1697: struct st_softc *st;
1.27 mycroft 1698: int flags;
1.1 cgd 1699: {
1.73 bouyer 1700: u_int scsipi_sense_len;
1.20 mycroft 1701: int error;
1.28 mycroft 1702: struct scsi_mode_sense cmd;
1.73 bouyer 1703: struct scsipi_sense {
1.20 mycroft 1704: struct scsi_mode_header header;
1.44 mycroft 1705: struct scsi_blk_desc blk_desc;
1.36 mycroft 1706: u_char sense_data[MAX_PAGE_0_SIZE];
1.73 bouyer 1707: } scsipi_sense;
1.114.2.1 thorpej 1708: struct scsipi_periph *periph = st->sc_periph;
1.20 mycroft 1709:
1.73 bouyer 1710: scsipi_sense_len = 12 + st->page_0_size;
1.3 deraadt 1711:
1712: /*
1.51 mycroft 1713: * Set up a mode sense
1.3 deraadt 1714: */
1.28 mycroft 1715: bzero(&cmd, sizeof(cmd));
1.73 bouyer 1716: cmd.opcode = SCSI_MODE_SENSE;
1717: cmd.length = scsipi_sense_len;
1.3 deraadt 1718:
1719: /*
1720: * do the command, but we don't need the results
1.20 mycroft 1721: * just print them for our interest's sake, if asked,
1722: * or if we need it as a template for the mode select
1723: * store it away.
1724: */
1.114.2.1 thorpej 1725: error = scsipi_command(periph, (struct scsipi_generic *)&cmd,
1.76 enami 1726: sizeof(cmd), (u_char *)&scsipi_sense, scsipi_sense_len,
1.114.2.4 bouyer 1727: ST_RETRIES, ST_CTL_TIME, NULL,
1728: flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK);
1.59 christos 1729: if (error)
1.76 enami 1730: return (error);
1.20 mycroft 1731:
1.73 bouyer 1732: st->numblks = _3btol(scsipi_sense.blk_desc.nblocks);
1733: st->media_blksize = _3btol(scsipi_sense.blk_desc.blklen);
1734: st->media_density = scsipi_sense.blk_desc.density;
1735: if (scsipi_sense.header.dev_spec & SMH_DSP_WRITE_PROT)
1.20 mycroft 1736: st->flags |= ST_READONLY;
1.90 mjacob 1737: else
1738: st->flags &= ~ST_READONLY;
1.114.2.3 thorpej 1739: SC_DEBUG(periph, SCSIPI_DB3,
1.114.2.4 bouyer 1740: ("density code %d, %d-byte blocks, write-%s, ",
1.44 mycroft 1741: st->media_density, st->media_blksize,
1.20 mycroft 1742: st->flags & ST_READONLY ? "protected" : "enabled"));
1.114.2.3 thorpej 1743: SC_DEBUG(periph, SCSIPI_DB3,
1.20 mycroft 1744: ("%sbuffered\n",
1.73 bouyer 1745: scsipi_sense.header.dev_spec & SMH_DSP_BUFF_MODE ? "" : "un"));
1.36 mycroft 1746: if (st->page_0_size)
1.76 enami 1747: bcopy(scsipi_sense.sense_data, st->sense_data,
1748: st->page_0_size);
1.114.2.1 thorpej 1749: periph->periph_flags |= PERIPH_MEDIA_LOADED;
1.76 enami 1750: return (0);
1.1 cgd 1751: }
1752:
1.3 deraadt 1753: /*
1.20 mycroft 1754: * Send a filled out parameter structure to the drive to
1755: * set it into the desire modes etc.
1756: */
1.51 mycroft 1757: int
1.20 mycroft 1758: st_mode_select(st, flags)
1.44 mycroft 1759: struct st_softc *st;
1.27 mycroft 1760: int flags;
1.1 cgd 1761: {
1.36 mycroft 1762: u_int scsi_select_len;
1.28 mycroft 1763: struct scsi_mode_select cmd;
1.36 mycroft 1764: struct scsi_select {
1.20 mycroft 1765: struct scsi_mode_header header;
1.44 mycroft 1766: struct scsi_blk_desc blk_desc;
1.36 mycroft 1767: u_char sense_data[MAX_PAGE_0_SIZE];
1768: } scsi_select;
1.114.2.1 thorpej 1769: struct scsipi_periph *periph = st->sc_periph;
1.36 mycroft 1770:
1771: scsi_select_len = 12 + st->page_0_size;
1.67 thorpej 1772:
1773: /*
1774: * This quirk deals with drives that have only one valid mode
1775: * and think this gives them license to reject all mode selects,
1776: * even if the selected mode is the one that is supported.
1777: */
1778: if (st->quirks & ST_Q_UNIMODAL) {
1.114.2.3 thorpej 1779: SC_DEBUG(periph, SCSIPI_DB3,
1.67 thorpej 1780: ("not setting density 0x%x blksize 0x%x\n",
1781: st->density, st->blksize));
1.76 enami 1782: return (0);
1.67 thorpej 1783: }
1.3 deraadt 1784:
1785: /*
1786: * Set up for a mode select
1787: */
1.28 mycroft 1788: bzero(&cmd, sizeof(cmd));
1.73 bouyer 1789: cmd.opcode = SCSI_MODE_SELECT;
1.36 mycroft 1790: cmd.length = scsi_select_len;
1.28 mycroft 1791:
1.36 mycroft 1792: bzero(&scsi_select, scsi_select_len);
1.44 mycroft 1793: scsi_select.header.blk_desc_len = sizeof(struct scsi_blk_desc);
1.57 thorpej 1794: scsi_select.header.dev_spec &= ~SMH_DSP_BUFF_MODE;
1.36 mycroft 1795: scsi_select.blk_desc.density = st->density;
1.57 thorpej 1796: if (st->flags & ST_DONTBUFFER)
1797: scsi_select.header.dev_spec |= SMH_DSP_BUFF_MODE_OFF;
1798: else
1799: scsi_select.header.dev_spec |= SMH_DSP_BUFF_MODE_ON;
1.20 mycroft 1800: if (st->flags & ST_FIXEDBLOCKS)
1.64 mycroft 1801: _lto3b(st->blksize, scsi_select.blk_desc.blklen);
1.36 mycroft 1802: if (st->page_0_size)
1803: bcopy(st->sense_data, scsi_select.sense_data, st->page_0_size);
1.28 mycroft 1804:
1.3 deraadt 1805: /*
1806: * do the command
1807: */
1.114.2.1 thorpej 1808: return (scsipi_command(periph, (struct scsipi_generic *)&cmd,
1.76 enami 1809: sizeof(cmd), (u_char *)&scsi_select, scsi_select_len,
1.114.2.4 bouyer 1810: ST_RETRIES, ST_CTL_TIME, NULL,
1811: flags | XS_CTL_DATA_OUT | XS_CTL_DATA_ONSTACK));
1.57 thorpej 1812: }
1813:
1.75 mjacob 1814: int
1815: st_cmprss(st, onoff)
1816: struct st_softc *st;
1817: int onoff;
1818: {
1819: u_int scsi_dlen;
1820: struct scsi_mode_select mcmd;
1821: struct scsi_mode_sense scmd;
1822: struct scsi_select {
1823: struct scsi_mode_header header;
1824: struct scsi_blk_desc blk_desc;
1.76 enami 1825: u_char pdata[max(sizeof(struct scsi_tape_dev_conf_page),
1826: sizeof(struct scsi_tape_dev_compression_page))];
1.75 mjacob 1827: } scsi_pdata;
1828: struct scsi_tape_dev_conf_page *ptr;
1829: struct scsi_tape_dev_compression_page *cptr;
1.114.2.1 thorpej 1830: struct scsipi_periph *periph = st->sc_periph;
1.75 mjacob 1831: int error, ison, flags;
1832:
1.76 enami 1833: scsi_dlen = sizeof(scsi_pdata);
1.75 mjacob 1834: bzero(&scsi_pdata, scsi_dlen);
1835:
1836: /*
1837: * Set up for a mode sense.
1838: * Do DATA COMPRESSION page first.
1839: */
1.76 enami 1840: bzero(&scmd, sizeof(scmd));
1.75 mjacob 1841: scmd.opcode = SCSI_MODE_SENSE;
1842: scmd.page = SMS_PAGE_CTRL_CURRENT | 0xf;
1843: scmd.length = scsi_dlen;
1844:
1.114 thorpej 1845: flags = XS_CTL_SILENT;
1.75 mjacob 1846:
1847: /*
1848: * Do the MODE SENSE command...
1849: */
1850: again:
1.90 mjacob 1851: bzero(&scsi_pdata, scsi_dlen);
1.114.2.1 thorpej 1852: error = scsipi_command(periph,
1.114.2.5 bouyer 1853: (struct scsipi_generic *)&scmd, sizeof(scmd),
1.76 enami 1854: (u_char *)&scsi_pdata, scsi_dlen,
1.114.2.4 bouyer 1855: ST_RETRIES, ST_CTL_TIME, NULL,
1856: flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK);
1.75 mjacob 1857:
1858: if (error) {
1859: if (scmd.byte2 != SMS_DBD) {
1860: scmd.byte2 = SMS_DBD;
1861: goto again;
1862: }
1.90 mjacob 1863: /*
1864: * Try a different page?
1865: */
1866: if (scmd.page == (SMS_PAGE_CTRL_CURRENT | 0xf)) {
1867: scmd.page = SMS_PAGE_CTRL_CURRENT | 0x10;
1868: scmd.byte2 = 0;
1869: goto again;
1870: }
1.76 enami 1871: return (error);
1.75 mjacob 1872: }
1873:
1.76 enami 1874: if (scsi_pdata.header.blk_desc_len)
1.75 mjacob 1875: ptr = (struct scsi_tape_dev_conf_page *) scsi_pdata.pdata;
1.76 enami 1876: else
1.75 mjacob 1877: ptr = (struct scsi_tape_dev_conf_page *) &scsi_pdata.blk_desc;
1878:
1879: if ((scmd.page & SMS_PAGE_CODE) == 0xf) {
1880: cptr = (struct scsi_tape_dev_compression_page *) ptr;
1881: ison = (cptr->dce_dcc & DCP_DCE) != 0;
1882: if (onoff)
1883: cptr->dce_dcc |= DCP_DCE;
1884: else
1885: cptr->dce_dcc &= ~DCP_DCE;
1886: cptr->pagecode &= ~0x80;
1887: } else {
1888: ison = (ptr->sel_comp_alg != 0);
1889: if (onoff)
1890: ptr->sel_comp_alg = 1;
1891: else
1892: ptr->sel_comp_alg = 0;
1893: ptr->pagecode &= ~0x80;
1.90 mjacob 1894: ptr->byte2 = 0;
1895: ptr->active_partition = 0;
1896: ptr->wb_full_ratio = 0;
1897: ptr->rb_empty_ratio = 0;
1898: ptr->byte8 &= ~0x30;
1899: ptr->gap_size = 0;
1900: ptr->byte10 &= ~0xe7;
1901: ptr->ew_bufsize[0] = 0;
1902: ptr->ew_bufsize[1] = 0;
1903: ptr->ew_bufsize[2] = 0;
1904: ptr->reserved = 0;
1.75 mjacob 1905: }
1.76 enami 1906: onoff = onoff ? 1 : 0;
1.75 mjacob 1907: /*
1908: * There might be a virtue in actually doing the MODE SELECTS,
1909: * but let's not clog the bus over it.
1910: */
1911: if (onoff == ison)
1912: return (0);
1913:
1914: /*
1915: * Set up for a mode select
1916: */
1917:
1918: scsi_pdata.header.data_length = 0;
1919: scsi_pdata.header.medium_type = 0;
1920: if ((st->flags & ST_DONTBUFFER) == 0)
1921: scsi_pdata.header.dev_spec = SMH_DSP_BUFF_MODE_ON;
1922: else
1923: scsi_pdata.header.dev_spec = 0;
1924:
1925: bzero(&mcmd, sizeof(mcmd));
1926: mcmd.opcode = SCSI_MODE_SELECT;
1927: mcmd.byte2 = SMS_PF;
1928: mcmd.length = scsi_dlen;
1929: if (scsi_pdata.header.blk_desc_len) {
1930: scsi_pdata.blk_desc.density = 0;
1931: scsi_pdata.blk_desc.nblocks[0] = 0;
1932: scsi_pdata.blk_desc.nblocks[1] = 0;
1933: scsi_pdata.blk_desc.nblocks[2] = 0;
1934: }
1935:
1936: /*
1.76 enami 1937: * Do the command
1.75 mjacob 1938: */
1.114.2.1 thorpej 1939: error = scsipi_command(periph,
1.76 enami 1940: (struct scsipi_generic *)&mcmd, sizeof(mcmd),
1941: (u_char *)&scsi_pdata, scsi_dlen,
1.114.2.4 bouyer 1942: ST_RETRIES, ST_CTL_TIME, NULL,
1943: flags | XS_CTL_DATA_OUT | XS_CTL_DATA_ONSTACK);
1.75 mjacob 1944:
1945: if (error && (scmd.page & SMS_PAGE_CODE) == 0xf) {
1946: /*
1947: * Try DEVICE CONFIGURATION page.
1948: */
1949: scmd.page = SMS_PAGE_CTRL_CURRENT | 0x10;
1950: goto again;
1951: }
1952: return (error);
1953: }
1.57 thorpej 1954: /*
1955: * issue an erase command
1956: */
1957: int
1958: st_erase(st, full, flags)
1959: struct st_softc *st;
1960: int full, flags;
1961: {
1.90 mjacob 1962: int tmo;
1.57 thorpej 1963: struct scsi_erase cmd;
1964:
1965: /*
1966: * Full erase means set LONG bit in erase command, which asks
1967: * the drive to erase the entire unit. Without this bit, we're
1968: * asking the drive to write an erase gap.
1969: */
1970: bzero(&cmd, sizeof(cmd));
1971: cmd.opcode = ERASE;
1.90 mjacob 1972: if (full) {
1.114.2.5 bouyer 1973: cmd.byte2 = SE_LONG;
1.90 mjacob 1974: tmo = ST_SPC_TIME;
1975: } else {
1976: tmo = ST_IO_TIME;
1977: }
1.57 thorpej 1978:
1979: /*
1.114.2.5 bouyer 1980: * XXX We always do this asynchronously, for now, unless the device
1981: * has the ST_Q_ERASE_NOIMM quirk. How long should we wait if we
1982: * want to (eventually) to it synchronously?
1.57 thorpej 1983: */
1.114.2.5 bouyer 1984: if ((st->quirks & ST_Q_ERASE_NOIMM) == 0)
1985: cmd.byte2 |= SE_IMMED;
1986:
1.114.2.1 thorpej 1987: return (scsipi_command(st->sc_periph,
1.76 enami 1988: (struct scsipi_generic *)&cmd, sizeof(cmd),
1.90 mjacob 1989: 0, 0, ST_RETRIES, tmo, NULL, flags));
1.1 cgd 1990: }
1991:
1.3 deraadt 1992: /*
1993: * skip N blocks/filemarks/seq filemarks/eom
1.20 mycroft 1994: */
1.51 mycroft 1995: int
1.20 mycroft 1996: st_space(st, number, what, flags)
1.44 mycroft 1997: struct st_softc *st;
1.20 mycroft 1998: u_int what;
1.27 mycroft 1999: int flags;
1.20 mycroft 2000: int number;
1.1 cgd 2001: {
1.28 mycroft 2002: struct scsi_space cmd;
1.20 mycroft 2003: int error;
1.1 cgd 2004:
1.20 mycroft 2005: switch (what) {
2006: case SP_BLKS:
2007: if (st->flags & ST_PER_ACTION) {
2008: if (number > 0) {
2009: st->flags &= ~ST_PER_ACTION;
1.76 enami 2010: return (EIO);
1.20 mycroft 2011: } else if (number < 0) {
2012: if (st->flags & ST_AT_FILEMARK) {
2013: /*
2014: * Handling of ST_AT_FILEMARK
2015: * in st_space will fill in the
2016: * right file mark count.
2017: */
2018: error = st_space(st, 0, SP_FILEMARKS,
1.76 enami 2019: flags);
1.20 mycroft 2020: if (error)
1.76 enami 2021: return (error);
1.20 mycroft 2022: }
2023: if (st->flags & ST_BLANK_READ) {
2024: st->flags &= ~ST_BLANK_READ;
1.76 enami 2025: return (EIO);
1.20 mycroft 2026: }
1.93 mjacob 2027: st->flags &= ~(ST_EIO_PENDING|ST_EOM_PENDING);
1.20 mycroft 2028: }
2029: }
2030: break;
2031: case SP_FILEMARKS:
2032: if (st->flags & ST_EIO_PENDING) {
2033: if (number > 0) {
1.22 mycroft 2034: /* pretend we just discovered the error */
1.20 mycroft 2035: st->flags &= ~ST_EIO_PENDING;
1.76 enami 2036: return (EIO);
1.20 mycroft 2037: } else if (number < 0) {
2038: /* back away from the error */
2039: st->flags &= ~ST_EIO_PENDING;
2040: }
2041: }
2042: if (st->flags & ST_AT_FILEMARK) {
2043: st->flags &= ~ST_AT_FILEMARK;
2044: number--;
2045: }
2046: if ((st->flags & ST_BLANK_READ) && (number < 0)) {
2047: /* back away from unwritten tape */
2048: st->flags &= ~ST_BLANK_READ;
2049: number++; /* XXX dubious */
2050: }
1.22 mycroft 2051: break;
2052: case SP_EOM:
1.93 mjacob 2053: if (st->flags & ST_EOM_PENDING) {
2054: /* we're already there */
2055: st->flags &= ~ST_EOM_PENDING;
2056: return (0);
2057: }
1.22 mycroft 2058: if (st->flags & ST_EIO_PENDING) {
2059: /* pretend we just discovered the error */
2060: st->flags &= ~ST_EIO_PENDING;
1.76 enami 2061: return (EIO);
1.22 mycroft 2062: }
2063: if (st->flags & ST_AT_FILEMARK)
2064: st->flags &= ~ST_AT_FILEMARK;
2065: break;
1.20 mycroft 2066: }
2067: if (number == 0)
1.76 enami 2068: return (0);
1.28 mycroft 2069:
2070: bzero(&cmd, sizeof(cmd));
1.44 mycroft 2071: cmd.opcode = SPACE;
1.28 mycroft 2072: cmd.byte2 = what;
1.64 mycroft 2073: _lto3b(number, cmd.number);
1.28 mycroft 2074:
1.114.2.1 thorpej 2075: return (scsipi_command(st->sc_periph,
1.76 enami 2076: (struct scsipi_generic *)&cmd, sizeof(cmd),
1.90 mjacob 2077: 0, 0, 0, ST_SPC_TIME, NULL, flags));
1.1 cgd 2078: }
1.3 deraadt 2079:
2080: /*
2081: * write N filemarks
1.20 mycroft 2082: */
1.51 mycroft 2083: int
1.20 mycroft 2084: st_write_filemarks(st, number, flags)
1.44 mycroft 2085: struct st_softc *st;
1.27 mycroft 2086: int flags;
1.20 mycroft 2087: int number;
1.1 cgd 2088: {
1.28 mycroft 2089: struct scsi_write_filemarks cmd;
1.1 cgd 2090:
1.20 mycroft 2091: /*
2092: * It's hard to write a negative number of file marks.
2093: * Don't try.
2094: */
2095: if (number < 0)
1.76 enami 2096: return (EINVAL);
1.20 mycroft 2097: switch (number) {
2098: case 0: /* really a command to sync the drive's buffers */
2099: break;
2100: case 1:
2101: if (st->flags & ST_FM_WRITTEN) /* already have one down */
2102: st->flags &= ~ST_WRITTEN;
2103: else
2104: st->flags |= ST_FM_WRITTEN;
2105: st->flags &= ~ST_PER_ACTION;
2106: break;
2107: default:
2108: st->flags &= ~(ST_PER_ACTION | ST_WRITTEN);
2109: }
1.28 mycroft 2110:
2111: bzero(&cmd, sizeof(cmd));
1.44 mycroft 2112: cmd.opcode = WRITE_FILEMARKS;
1.64 mycroft 2113: _lto3b(number, cmd.number);
1.28 mycroft 2114:
1.114.2.1 thorpej 2115: return (scsipi_command(st->sc_periph,
1.76 enami 2116: (struct scsipi_generic *)&cmd, sizeof(cmd),
1.90 mjacob 2117: 0, 0, 0, ST_IO_TIME * 4, NULL, flags));
1.1 cgd 2118: }
1.3 deraadt 2119:
2120: /*
1.20 mycroft 2121: * Make sure the right number of file marks is on tape if the
2122: * tape has been written. If the position argument is true,
2123: * leave the tape positioned where it was originally.
2124: *
2125: * nmarks returns the number of marks to skip (or, if position
2126: * true, which were skipped) to get back original position.
2127: */
1.51 mycroft 2128: int
1.28 mycroft 2129: st_check_eod(st, position, nmarks, flags)
1.44 mycroft 2130: struct st_softc *st;
1.20 mycroft 2131: boolean position;
2132: int *nmarks;
1.27 mycroft 2133: int flags;
1.1 cgd 2134: {
1.20 mycroft 2135: int error;
1.1 cgd 2136:
1.20 mycroft 2137: switch (st->flags & (ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD)) {
2138: default:
2139: *nmarks = 0;
1.76 enami 2140: return (0);
1.20 mycroft 2141: case ST_WRITTEN:
2142: case ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD:
2143: *nmarks = 1;
2144: break;
2145: case ST_WRITTEN | ST_2FM_AT_EOD:
2146: *nmarks = 2;
1.1 cgd 2147: }
1.20 mycroft 2148: error = st_write_filemarks(st, *nmarks, flags);
2149: if (position && !error)
2150: error = st_space(st, -*nmarks, SP_FILEMARKS, flags);
1.76 enami 2151: return (error);
1.1 cgd 2152: }
1.3 deraadt 2153:
2154: /*
1.23 mycroft 2155: * load/unload/retension
1.20 mycroft 2156: */
1.51 mycroft 2157: int
1.20 mycroft 2158: st_load(st, type, flags)
1.44 mycroft 2159: struct st_softc *st;
1.20 mycroft 2160: u_int type;
1.27 mycroft 2161: int flags;
1.1 cgd 2162: {
1.112 mjacob 2163: int error;
1.28 mycroft 2164: struct scsi_load cmd;
1.1 cgd 2165:
1.20 mycroft 2166: if (type != LD_LOAD) {
2167: int nmarks;
2168:
1.28 mycroft 2169: error = st_check_eod(st, FALSE, &nmarks, flags);
1.112 mjacob 2170: if (error) {
2171: printf("%s: failed to write closing filemarks at "
2172: "unload, errno=%d\n", st->sc_dev.dv_xname, error);
1.76 enami 2173: return (error);
1.112 mjacob 2174: }
1.1 cgd 2175: }
1.90 mjacob 2176: if (st->quirks & ST_Q_IGNORE_LOADS) {
2177: if (type == LD_LOAD) {
2178: /*
2179: * If we ignore loads, at least we should try a rewind.
2180: */
2181: return st_rewind(st, 0, flags);
2182: }
1.112 mjacob 2183: /* otherwise, we should do what's asked of us */
1.90 mjacob 2184: }
1.28 mycroft 2185:
2186: bzero(&cmd, sizeof(cmd));
1.44 mycroft 2187: cmd.opcode = LOAD;
1.28 mycroft 2188: cmd.how = type;
2189:
1.114.2.1 thorpej 2190: error = scsipi_command(st->sc_periph,
1.76 enami 2191: (struct scsipi_generic *)&cmd, sizeof(cmd),
1.112 mjacob 2192: 0, 0, ST_RETRIES, ST_SPC_TIME, NULL, flags);
2193: if (error) {
2194: printf("%s: error %d in st_load (op %d)\n",
2195: st->sc_dev.dv_xname, error, type);
2196: }
2197: return (error);
1.1 cgd 2198: }
1.3 deraadt 2199:
2200: /*
2201: * Rewind the device
1.20 mycroft 2202: */
1.51 mycroft 2203: int
1.28 mycroft 2204: st_rewind(st, immediate, flags)
1.44 mycroft 2205: struct st_softc *st;
1.28 mycroft 2206: u_int immediate;
1.27 mycroft 2207: int flags;
1.1 cgd 2208: {
1.28 mycroft 2209: struct scsi_rewind cmd;
1.20 mycroft 2210: int error;
2211: int nmarks;
2212:
1.28 mycroft 2213: error = st_check_eod(st, FALSE, &nmarks, flags);
1.112 mjacob 2214: if (error) {
2215: printf("%s: failed to write closing filemarks at "
2216: "rewind, errno=%d\n", st->sc_dev.dv_xname, error);
1.76 enami 2217: return (error);
1.112 mjacob 2218: }
1.20 mycroft 2219: st->flags &= ~ST_PER_ACTION;
1.28 mycroft 2220:
2221: bzero(&cmd, sizeof(cmd));
1.44 mycroft 2222: cmd.opcode = REWIND;
1.28 mycroft 2223: cmd.byte2 = immediate;
2224:
1.114.2.1 thorpej 2225: error = scsipi_command(st->sc_periph,
1.90 mjacob 2226: (struct scsipi_generic *)&cmd, sizeof(cmd), 0, 0, ST_RETRIES,
1.112 mjacob 2227: immediate ? ST_CTL_TIME: ST_SPC_TIME, NULL, flags);
2228: if (error) {
2229: printf("%s: error %d trying to rewind\n",
2230: st->sc_dev.dv_xname, error);
2231: }
2232: return (error);
1.1 cgd 2233: }
1.3 deraadt 2234:
1.75 mjacob 2235: int
2236: st_rdpos(st, hard, blkptr)
2237: struct st_softc *st;
2238: int hard;
2239: u_int32_t *blkptr;
2240: {
2241: int error;
2242: u_int8_t posdata[20];
2243: struct scsi_tape_read_position cmd;
2244:
2245: /*
2246: * First flush any pending writes...
2247: */
1.114 thorpej 2248: error = st_write_filemarks(st, 0, XS_CTL_SILENT);
1.77 mjacob 2249:
2250: /*
2251: * The latter case is for 'write protected' tapes
2252: * which are too stupid to recognize a zero count
2253: * for writing filemarks as a no-op.
2254: */
1.108 tron 2255: if (error != 0 && error != EACCES && error != EROFS)
1.75 mjacob 2256: return (error);
2257:
1.76 enami 2258: bzero(&cmd, sizeof(cmd));
2259: bzero(&posdata, sizeof(posdata));
1.75 mjacob 2260: cmd.opcode = READ_POSITION;
2261: if (hard)
2262: cmd.byte1 = 1;
2263:
1.114.2.1 thorpej 2264: error = scsipi_command(st->sc_periph,
1.76 enami 2265: (struct scsipi_generic *)&cmd, sizeof(cmd), (u_char *)&posdata,
1.90 mjacob 2266: sizeof(posdata), ST_RETRIES, ST_CTL_TIME, NULL,
1.114.2.4 bouyer 2267: XS_CTL_SILENT | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK);
1.75 mjacob 2268:
2269: if (error == 0) {
2270: #if 0
2271: printf("posdata:");
1.76 enami 2272: for (hard = 0; hard < sizeof(posdata); hard++)
1.75 mjacob 2273: printf("%02x ", posdata[hard] & 0xff);
2274: printf("\n");
2275: #endif
2276: if (posdata[0] & 0x4) /* Block Position Unknown */
2277: error = EINVAL;
1.79 enami 2278: else
1.75 mjacob 2279: *blkptr = _4btol(&posdata[4]);
2280: }
2281: return (error);
2282: }
2283:
2284: int
2285: st_setpos(st, hard, blkptr)
2286: struct st_softc *st;
2287: int hard;
2288: u_int32_t *blkptr;
2289: {
2290: int error;
1.98 drochner 2291: struct scsi_tape_locate cmd;
1.75 mjacob 2292:
2293: /*
1.77 mjacob 2294: * First flush any pending writes. Strictly speaking,
2295: * we're not supposed to have to worry about this,
2296: * but let's be untrusting.
1.75 mjacob 2297: */
1.114 thorpej 2298: error = st_write_filemarks(st, 0, XS_CTL_SILENT);
1.77 mjacob 2299:
2300: /*
2301: * The latter case is for 'write protected' tapes
2302: * which are too stupid to recognize a zero count
2303: * for writing filemarks as a no-op.
2304: */
1.108 tron 2305: if (error != 0 && error != EACCES && error != EROFS)
1.75 mjacob 2306: return (error);
2307:
1.76 enami 2308: bzero(&cmd, sizeof(cmd));
1.75 mjacob 2309: cmd.opcode = LOCATE;
2310: if (hard)
1.98 drochner 2311: cmd.byte2 = 1 << 2;
2312: _lto4b(*blkptr, cmd.blkaddr);
1.114.2.1 thorpej 2313: error = scsipi_command(st->sc_periph,
1.98 drochner 2314: (struct scsipi_generic *)&cmd, sizeof(cmd),
2315: NULL, 0, ST_RETRIES, ST_SPC_TIME, NULL, 0);
1.75 mjacob 2316: /*
2317: * XXX: Note file && block number position now unknown (if
2318: * XXX: these things ever start being maintained in this driver)
2319: */
2320: return (error);
2321: }
2322:
2323:
1.3 deraadt 2324: /*
1.91 mjacob 2325: * Look at the returned sense and act on the error and determine
2326: * the unix error number to pass back..., 0 (== report no error),
2327: * -1 = retry the operation, -2 continue error processing.
1.20 mycroft 2328: */
1.51 mycroft 2329: int
1.20 mycroft 2330: st_interpret_sense(xs)
1.73 bouyer 2331: struct scsipi_xfer *xs;
1.1 cgd 2332: {
1.114.2.1 thorpej 2333: struct scsipi_periph *periph = xs->xs_periph;
1.73 bouyer 2334: struct scsipi_sense_data *sense = &xs->sense.scsi_sense;
1.20 mycroft 2335: struct buf *bp = xs->bp;
1.114.2.1 thorpej 2336: struct st_softc *st = (void *)periph->periph_dev;
2337: int retval = EJUSTRETURN;
1.114 thorpej 2338: int doprint = ((xs->xs_control & XS_CTL_SILENT) == 0);
1.44 mycroft 2339: u_int8_t key;
1.56 pk 2340: int32_t info;
1.3 deraadt 2341:
2342: /*
1.90 mjacob 2343: * If it isn't a extended or extended/deferred error, let
2344: * the generic code handle it.
1.3 deraadt 2345: */
1.90 mjacob 2346: if ((sense->error_code & SSD_ERRCODE) != 0x70 &&
2347: (sense->error_code & SSD_ERRCODE) != 0x71) { /* DEFFERRED */
1.91 mjacob 2348: return (retval);
1.90 mjacob 2349: }
2350:
1.64 mycroft 2351: if (sense->error_code & SSD_ERRCODE_VALID)
2352: info = _4btol(sense->info);
2353: else
1.20 mycroft 2354: info = xs->datalen; /* bad choice if fixed blocks */
1.90 mjacob 2355: key = sense->flags & SSD_KEY;
2356: st->mt_erreg = key;
1.114.2.4 bouyer 2357: st->asc = sense->add_sense_code;
2358: st->ascq = sense->add_sense_code_qual;
1.90 mjacob 2359: st->mt_resid = (short) info;
1.96 mjacob 2360:
2361: /*
2362: * If the device is not open yet, let generic handle
2363: */
1.114.2.1 thorpej 2364: if ((periph->periph_flags & PERIPH_OPEN) == 0) {
1.96 mjacob 2365: return (retval);
2366: }
2367:
1.90 mjacob 2368:
1.20 mycroft 2369: if (st->flags & ST_FIXEDBLOCKS) {
1.44 mycroft 2370: xs->resid = info * st->blksize;
1.64 mycroft 2371: if (sense->flags & SSD_EOM) {
1.93 mjacob 2372: if ((st->flags & ST_EARLYWARN) == 0)
2373: st->flags |= ST_EIO_PENDING;
2374: st->flags |= ST_EOM_PENDING;
1.20 mycroft 2375: if (bp)
2376: bp->b_resid = xs->resid;
2377: }
1.64 mycroft 2378: if (sense->flags & SSD_FILEMARK) {
1.20 mycroft 2379: st->flags |= ST_AT_FILEMARK;
2380: if (bp)
2381: bp->b_resid = xs->resid;
2382: }
1.64 mycroft 2383: if (sense->flags & SSD_ILI) {
1.20 mycroft 2384: st->flags |= ST_EIO_PENDING;
2385: if (bp)
2386: bp->b_resid = xs->resid;
1.44 mycroft 2387: if (sense->error_code & SSD_ERRCODE_VALID &&
1.114 thorpej 2388: (xs->xs_control & XS_CTL_SILENT) == 0)
1.90 mjacob 2389: printf("%s: block wrong size, %d blocks "
2390: "residual\n", st->sc_dev.dv_xname, info);
1.3 deraadt 2391:
1.20 mycroft 2392: /*
2393: * This quirk code helps the drive read
2394: * the first tape block, regardless of
2395: * format. That is required for these
2396: * drives to return proper MODE SENSE
2397: * information.
2398: */
1.28 mycroft 2399: if ((st->quirks & ST_Q_SENSE_HELP) &&
1.114.2.1 thorpej 2400: (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)
1.44 mycroft 2401: st->blksize -= 512;
1.6 mycroft 2402: }
1.3 deraadt 2403: /*
1.85 mjacob 2404: * If data wanted and no data was tranfered, do it immediatly
1.3 deraadt 2405: */
1.85 mjacob 2406: if (xs->datalen && xs->resid >= xs->datalen) {
1.20 mycroft 2407: if (st->flags & ST_EIO_PENDING)
1.76 enami 2408: return (EIO);
1.20 mycroft 2409: if (st->flags & ST_AT_FILEMARK) {
2410: if (bp)
2411: bp->b_resid = xs->resid;
1.114.2.1 thorpej 2412: return (0);
1.20 mycroft 2413: }
2414: }
2415: } else { /* must be variable mode */
1.90 mjacob 2416: if (sense->flags & SSD_EOM) {
2417: /*
2418: * The current semantics of this
2419: * driver requires EOM detection
1.93 mjacob 2420: * to return EIO unless early
2421: * warning detection is enabled
2422: * for variable mode (this is always
2423: * on for fixed block mode).
1.90 mjacob 2424: */
1.93 mjacob 2425: if (st->flags & ST_EARLYWARN) {
2426: st->flags |= ST_EOM_PENDING;
1.114.2.1 thorpej 2427: retval = 0;
1.93 mjacob 2428: } else {
2429: retval = EIO;
2430: }
1.90 mjacob 2431:
2432: /*
2433: * If it's an unadorned EOM detection,
2434: * suppress printing an error.
2435: */
2436: if (key == SKEY_NO_SENSE) {
2437: doprint = 0;
2438: }
2439: } else if (sense->flags & SSD_FILEMARK) {
1.114.2.1 thorpej 2440: retval = 0;
1.90 mjacob 2441: } else if (sense->flags & SSD_ILI) {
1.20 mycroft 2442: if (info < 0) {
1.3 deraadt 2443: /*
1.90 mjacob 2444: * The tape record was bigger than the read
2445: * we issued.
1.3 deraadt 2446: */
1.114 thorpej 2447: if ((xs->xs_control & XS_CTL_SILENT) == 0) {
1.90 mjacob 2448: printf("%s: %d-byte tape record too big"
2449: " for %d-byte user buffer\n",
1.20 mycroft 2450: st->sc_dev.dv_xname,
1.90 mjacob 2451: xs->datalen - info, xs->datalen);
2452: }
2453: retval = EIO;
2454: } else {
1.114.2.1 thorpej 2455: retval = 0;
1.20 mycroft 2456: }
1.3 deraadt 2457: }
1.90 mjacob 2458: xs->resid = info;
2459: if (bp)
2460: bp->b_resid = info;
1.20 mycroft 2461: }
1.1 cgd 2462:
1.114.2.3 thorpej 2463: #ifdef SCSIPI_DEBUG
2464: if (retval == 0 && key == SKEY_NO_SENSE)
1.90 mjacob 2465: doprint = 0;
2466: #endif
2467: if (key == SKEY_BLANK_CHECK) {
1.20 mycroft 2468: /*
2469: * This quirk code helps the drive read the
2470: * first tape block, regardless of format. That
2471: * is required for these drives to return proper
2472: * MODE SENSE information.
2473: */
1.28 mycroft 2474: if ((st->quirks & ST_Q_SENSE_HELP) &&
1.114.2.1 thorpej 2475: (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
1.20 mycroft 2476: /* still starting */
1.44 mycroft 2477: st->blksize -= 512;
1.20 mycroft 2478: } else if (!(st->flags & (ST_2FM_AT_EOD | ST_BLANK_READ))) {
2479: st->flags |= ST_BLANK_READ;
2480: xs->resid = xs->datalen;
2481: if (bp) {
2482: bp->b_resid = xs->resid;
2483: /* return an EOF */
1.1 cgd 2484: }
1.114.2.1 thorpej 2485: retval = 0;
1.1 cgd 2486: }
2487: }
1.114.2.5 bouyer 2488:
2489: /*
2490: * If generic sense processing will continue, we should not
2491: * print sense info here.
2492: */
1.114.2.6! bouyer 2493: if (retval == EJUSTRETURN)
1.114.2.5 bouyer 2494: doprint = 0;
2495:
1.90 mjacob 2496: if (doprint) {
1.114.2.5 bouyer 2497: #ifdef SCSIVERBOSE
1.105 bouyer 2498: scsipi_print_sense(xs, 0);
1.90 mjacob 2499: #else
1.114.2.1 thorpej 2500: scsipi_printaddr(periph);
1.103 mjacob 2501: printf("Sense Key 0x%02x", key);
1.90 mjacob 2502: if ((sense->error_code & SSD_ERRCODE_VALID) != 0) {
1.114.2.5 bouyer 2503: switch (key) {
1.90 mjacob 2504: case SKEY_NOT_READY:
2505: case SKEY_ILLEGAL_REQUEST:
2506: case SKEY_UNIT_ATTENTION:
2507: case SKEY_WRITE_PROTECT:
2508: break;
2509: case SKEY_BLANK_CHECK:
2510: printf(", requested size: %d (decimal)", info);
1.114.2.5 bouyer 2511: break;
1.90 mjacob 2512: case SKEY_ABORTED_COMMAND:
2513: if (xs->retries)
2514: printf(", retrying");
2515: printf(", cmd 0x%x, info 0x%x",
2516: xs->cmd->opcode, info);
2517: break;
2518: default:
2519: printf(", info = %d (decimal)", info);
2520: }
1.114.2.5 bouyer 2521: }
1.90 mjacob 2522: if (sense->extra_len != 0) {
1.114.2.5 bouyer 2523: int n;
2524: printf(", data =");
1.90 mjacob 2525: for (n = 0; n < sense->extra_len; n++)
2526: printf(" %02x", sense->cmd_spec_info[n]);
1.114.2.5 bouyer 2527: }
1.90 mjacob 2528: printf("\n");
2529: #endif
1.114.2.5 bouyer 2530: }
1.90 mjacob 2531: return (retval);
1.20 mycroft 2532: }
2533:
2534: /*
2535: * The quirk here is that the drive returns some value to st_mode_sense
2536: * incorrectly until the tape has actually passed by the head.
2537: *
2538: * The method is to set the drive to large fixed-block state (user-specified
2539: * density and 1024-byte blocks), then read and rewind to get it to sense the
2540: * tape. If that doesn't work, try 512-byte fixed blocks. If that doesn't
2541: * work, as a last resort, try variable- length blocks. The result will be
2542: * the ability to do an accurate st_mode_sense.
2543: *
2544: * We know we can do a rewind because we just did a load, which implies rewind.
2545: * Rewind seems preferable to space backward if we have a virgin tape.
2546: *
2547: * The rest of the code for this quirk is in ILI processing and BLANK CHECK
2548: * error processing, both part of st_interpret_sense.
2549: */
2550: int
2551: st_touch_tape(st)
1.44 mycroft 2552: struct st_softc *st;
1.20 mycroft 2553: {
1.44 mycroft 2554: char *buf;
2555: int readsize;
1.20 mycroft 2556: int error;
2557:
2558: buf = malloc(1024, M_TEMP, M_NOWAIT);
1.76 enami 2559: if (buf == NULL)
2560: return (ENOMEM);
1.20 mycroft 2561:
1.59 christos 2562: if ((error = st_mode_sense(st, 0)) != 0)
1.20 mycroft 2563: goto bad;
1.114.2.5 bouyer 2564:
2565: /*
2566: * If the block size is already known from the
2567: * sense data, use it. Else start probing at 1024.
2568: */
2569: if (st->media_blksize > 0)
2570: st->blksize = st->media_blksize;
2571: else
2572: st->blksize = 1024;
2573:
1.20 mycroft 2574: do {
1.44 mycroft 2575: switch (st->blksize) {
1.20 mycroft 2576: case 512:
2577: case 1024:
1.44 mycroft 2578: readsize = st->blksize;
1.20 mycroft 2579: st->flags |= ST_FIXEDBLOCKS;
2580: break;
2581: default:
1.44 mycroft 2582: readsize = 1;
1.20 mycroft 2583: st->flags &= ~ST_FIXEDBLOCKS;
2584: }
1.114.2.5 bouyer 2585: if ((error = st_mode_select(st, XS_CTL_SILENT)) != 0) {
2586: /*
2587: * The device did not agree with the proposed
2588: * block size. If we exhausted our options,
2589: * return failure, else try another.
2590: */
2591: if (readsize == 1)
2592: goto bad;
2593: st->blksize -= 512;
2594: continue;
2595: }
1.114 thorpej 2596: st_read(st, buf, readsize, XS_CTL_SILENT); /* XXX */
1.59 christos 2597: if ((error = st_rewind(st, 0, 0)) != 0) {
1.20 mycroft 2598: bad: free(buf, M_TEMP);
1.76 enami 2599: return (error);
1.20 mycroft 2600: }
1.44 mycroft 2601: } while (readsize != 1 && readsize > st->blksize);
2602:
1.20 mycroft 2603: free(buf, M_TEMP);
1.76 enami 2604: return (0);
1.31 mycroft 2605: }
2606:
2607: int
1.48 cgd 2608: stdump(dev, blkno, va, size)
2609: dev_t dev;
2610: daddr_t blkno;
2611: caddr_t va;
2612: size_t size;
1.31 mycroft 2613: {
2614:
2615: /* Not implemented. */
1.76 enami 2616: return (ENXIO);
1.1 cgd 2617: }
CVSweb <webmaster@jp.NetBSD.org>