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