xref: /original-bsd/sys/pmax/dev/tz.c (revision 68549010)
1 /*
2  * Copyright (c) 1992 Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Ralph Campbell.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)tz.c	7.2 (Berkeley) 03/07/92
11  *
12  * from: $Header: /sprite/src/kernel/dev/RCS/devSCSITape.c,
13  *	v 8.14 89/07/31 17:26:13 mendel Exp $ SPRITE (Berkeley)
14  */
15 
16 /*
17  * SCSI CCS (Command Command Set) tape driver.
18  */
19 #include "tz.h"
20 #if NTZ > 0
21 
22 #include "param.h"
23 #include "systm.h"
24 #include "buf.h"
25 #include "errno.h"
26 #include "file.h"
27 #include "ioctl.h"
28 #include "mtio.h"
29 #include "syslog.h"
30 
31 #include "device.h"
32 #include "scsi.h"
33 
34 int	tzprobe();
35 void	tzstart(), tzdone();
36 
37 struct	driver tzdriver = {
38 	"tz", tzprobe, tzstart, tzdone,
39 };
40 
41 struct	tz_softc {
42 	struct	scsi_device *sc_sd;	/* physical unit info */
43 	int	sc_flags;		/* see below */
44 	struct	buf sc_tab;		/* queue of pending operations */
45 	struct	buf sc_buf;		/* buf for doing I/O */
46 	struct	buf sc_errbuf;		/* buf for doing REQUEST_SENSE */
47 	struct	ScsiCmd sc_cmd;		/* command for controller */
48 	ScsiGroup0Cmd sc_rwcmd;		/* SCSI cmd for read/write */
49 	struct	scsi_fmt_cdb sc_cdb;	/* SCSI cmd if not read/write */
50 	struct	scsi_fmt_sense sc_sense;	/* sense data from last cmd */
51 } tz_softc[NTZ];
52 
53 /* sc_flags values */
54 #define	TZF_ALIVE		0x01	/* drive found and ready */
55 #define	TZF_SENSEINPROGRESS	0x02	/* REQUEST_SENSE command in progress */
56 #define	TZF_ALTCMD		0x04	/* alternate command in progress */
57 #define	TZF_WRITTEN		0x08	/* tape has been written to */
58 #define	TZF_OPEN		0x10	/* device is open */
59 #define	TZF_WAIT		0x20	/* waiting for sc_tab to drain */
60 
61 /* bits in minor device */
62 #define	tzunit(x)	(minor(x) >> 1)	/* tz%d unit number */
63 #define TZ_NOREWIND	0x1		/* don't rewind on close */
64 
65 #define	INF	(daddr_t)1000000L	/* a block number that won't exist */
66 
67 #ifdef DEBUG
68 int	tzdebug = 1;
69 #endif
70 
71 /*
72  * Test to see if device is present.
73  * Return true if found and initialized ok.
74  */
75 tzprobe(sd)
76 	struct scsi_device *sd;
77 {
78 	register struct tz_softc *sc = &tz_softc[sd->sd_unit];
79 	register int i;
80 	ScsiInquiryData inqbuf;
81 	ScsiClass7Sense *sp;
82 
83 	printf("tzprobe()\n"); /* XXX */
84 	/* init some parameters that don't change */
85 	sc->sc_sd = sd;
86 	sc->sc_cmd.sd = sd;
87 	sc->sc_cmd.unit = sd->sd_unit;
88 	sc->sc_rwcmd.unitNumber = sd->sd_slave;
89 /*	sc->sc_rwcmd.highAddr = 1;	/* count in blocks */
90 
91 	/* try to find out what type of device this is */
92 	sc->sc_flags = TZF_ALTCMD;	/* force use of sc_cdb */
93 	sc->sc_cdb.len = sizeof(ScsiGroup0Cmd);
94 	scsiGroup0Cmd(SCSI_INQUIRY, sd->sd_slave, 0, sizeof(inqbuf),
95 		(ScsiGroup0Cmd *)sc->sc_cdb.cdb);
96 	sc->sc_buf.b_flags = B_BUSY | B_READ;
97 	sc->sc_buf.b_bcount = sizeof(inqbuf);
98 	sc->sc_buf.b_un.b_addr = (caddr_t)&inqbuf;
99 	sc->sc_buf.av_forw = (struct buf *)0;
100 	sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf;
101 	tzstart(sd->sd_unit);
102 	if (biowait(&sc->sc_buf) ||
103 	    (i = sizeof(inqbuf) - sc->sc_buf.b_resid) < 5)
104 		goto bad;
105 	if (inqbuf.type != SCSI_TAPE_TYPE)
106 		goto bad;
107 
108 	/* check for device ready to clear UNIT_ATTN */
109 	sc->sc_cdb.len = sizeof(ScsiGroup0Cmd);
110 	scsiGroup0Cmd(SCSI_TEST_UNIT_READY, sd->sd_slave, 0, 0,
111 		(ScsiGroup0Cmd *)sc->sc_cdb.cdb);
112 	sc->sc_buf.b_flags = B_BUSY | B_READ;
113 	sc->sc_buf.b_bcount = 0;
114 	sc->sc_buf.b_un.b_addr = (caddr_t)0;
115 	sc->sc_buf.av_forw = (struct buf *)0;
116 	sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf;
117 	tzstart(sd->sd_unit);
118 	(void) biowait(&sc->sc_buf);
119 
120 	sc->sc_flags = TZF_ALIVE;
121 	sc->sc_buf.b_flags = 0;
122 	printf("tz%d at %s%d drive %d slave %d\n", sd->sd_unit,
123 		sd->sd_cdriver->d_name, sd->sd_ctlr, sd->sd_drive,
124 		sd->sd_slave);
125 	return (1);
126 
127 bad:
128 	/* doesn't exist or not a CCS device */
129 	sc->sc_flags = 0;
130 	sc->sc_buf.b_flags = 0;
131 	return (0);
132 }
133 
134 /*
135  * Perform a special tape command on a SCSI Tape drive.
136  */
137 tzcommand(dev, command, code, count)
138 	dev_t dev;
139 	int command;
140 	int code;
141 	int count;
142 {
143 	register struct tz_softc *sc = &tz_softc[tzunit(dev)];
144 	int s, error;
145 
146 	s = splbio();
147 	while (sc->sc_tab.b_actf) {
148 		sc->sc_flags |= TZF_WAIT;
149 		sleep(&sc->sc_flags, PZERO);
150 	}
151 	sc->sc_flags |= TZF_ALTCMD;	/* force use of sc_cdb */
152 	sc->sc_cdb.len = sizeof(ScsiGroup0Cmd);
153 	scsiGroup0Cmd(command, sc->sc_sd->sd_slave,
154 		(code << 16) | ((count >> 8) & 0xFFFF), count & 0xFF,
155 		(ScsiGroup0Cmd *)sc->sc_cdb.cdb);
156 	sc->sc_buf.b_flags = B_BUSY | B_READ;
157 	sc->sc_buf.b_bcount = 0;
158 	sc->sc_buf.b_un.b_addr = (caddr_t)0;
159 	sc->sc_buf.av_forw = (struct buf *)0;
160 	sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf;
161 	tzstart(sc->sc_sd->sd_unit);
162 	error = biowait(&sc->sc_buf);
163 	sc->sc_flags &= ~TZF_ALTCMD;	/* force use of sc_cdb */
164 	sc->sc_buf.b_flags = 0;
165 	splx(s);
166 	return (error);
167 }
168 
169 void
170 tzstart(unit)
171 	int unit;
172 {
173 	register struct tz_softc *sc = &tz_softc[unit];
174 	register struct buf *bp = sc->sc_tab.b_actf;
175 	register int n;
176 
177 	sc->sc_cmd.buf = bp->b_un.b_addr;
178 	sc->sc_cmd.buflen = bp->b_bcount;
179 
180 	if (sc->sc_flags & (TZF_SENSEINPROGRESS | TZF_ALTCMD)) {
181 		sc->sc_cmd.flags = !(bp->b_flags & B_READ) ?
182 			SCSICMD_DATA_TO_DEVICE : 0;
183 		sc->sc_cmd.cmd = sc->sc_cdb.cdb;
184 		sc->sc_cmd.cmdlen = sc->sc_cdb.len;
185 	} else {
186 		if (bp->b_flags & B_READ) {
187 			sc->sc_cmd.flags = 0;
188 			sc->sc_rwcmd.command = SCSI_READ;
189 		} else {
190 			sc->sc_cmd.flags = SCSICMD_DATA_TO_DEVICE;
191 			sc->sc_rwcmd.command = SCSI_WRITE;
192 		}
193 		sc->sc_cmd.cmd = (u_char *)&sc->sc_rwcmd;
194 		sc->sc_cmd.cmdlen = sizeof(sc->sc_rwcmd);
195 		n = howmany(bp->b_bcount, 512);
196 		sc->sc_rwcmd.midAddr = n >> 16;
197 		sc->sc_rwcmd.lowAddr = n >> 8;
198 		sc->sc_rwcmd.blockCount = n;
199 		if ((bp->b_bcount & (512 - 1)) != 0)
200 			printf("tz%d: partial block xfer -- %x bytes\n",
201 				unit, bp->b_bcount);
202 	}
203 
204 	printf("tzstart(%d) flags %x, addr %x sz %d\n", unit,
205 		sc->sc_flags, sc->sc_cmd.buf, sc->sc_cmd.buflen); /* XXX */
206 	/* tell controller to start this command */
207 	if (sc->sc_cmd.cmd[0] == SCSI_READ)
208 	(*sc->sc_sd->sd_cdriver->d_start)(&sc->sc_cmd);
209 }
210 
211 /*
212  * This is called by the controller driver when the command is done.
213  */
214 void
215 tzdone(unit, error, resid, status)
216 	int unit;
217 	int error;		/* error number from errno.h */
218 	int resid;		/* amount not transfered */
219 	int status;		/* SCSI status byte */
220 {
221 	register struct tz_softc *sc = &tz_softc[unit];
222 	register struct buf *bp = sc->sc_tab.b_actf;
223 	extern int cold;
224 
225 	printf("tzdone(%d, %d, %d, %x) %x flags %x\n", unit, error, resid,
226 		status, sc, sc->sc_flags); /* XXX */
227 	if (bp == NULL) {
228 		printf("tz%d: bp == NULL\n", unit);
229 		return;
230 	}
231 	if (sc->sc_flags & TZF_SENSEINPROGRESS) {
232 		sc->sc_flags &= ~TZF_SENSEINPROGRESS;
233 		sc->sc_tab.b_actf = bp = bp->b_actf;	/* remove sc_errbuf */
234 		if (bp == 0) {
235 			panic("tzdone"); /* XXX */
236 		}
237 
238 		if (error || (status & SCSI_STATUS_CHECKCOND)) {
239 #ifdef DEBUG
240 			if (tzdebug)
241 				printf("tz%d: error reading sense data: error %d scsi status 0x%x\n",
242 					unit, error, status);
243 #endif
244 			/*
245 			 * We got an error during the REQUEST_SENSE,
246 			 * fill in no sense for data.
247 			 */
248 			sc->sc_sense.sense[0] = 0x70;
249 			sc->sc_sense.sense[2] = SCSI_CLASS7_NO_SENSE;
250 		} else if (!cold
251 #ifdef DEBUG
252 			|| tzdebug
253 #endif
254 		) {
255 			printf("tz%d: ", unit);
256 			scsiPrintSense((ScsiClass7Sense *)sc->sc_sense.sense,
257 				sizeof(sc->sc_sense.sense) - resid);
258 		}
259 	} else if (error || (status & SCSI_STATUS_CHECKCOND)) {
260 #ifdef DEBUG
261 		if (tzdebug)
262 			printf("tz%d: error %d scsi status 0x%x\n",
263 				unit, error, status);
264 #endif
265 		/* save error info */
266 		sc->sc_sense.status = status;
267 		bp->b_flags |= B_ERROR;
268 		bp->b_error = error;
269 		bp->b_resid = resid;
270 
271 		if (status & SCSI_STATUS_CHECKCOND) {
272 			/*
273 			 * Start a REQUEST_SENSE command.
274 			 * Since we are called at interrupt time, we can't
275 			 * wait for the command to finish; that's why we use
276 			 * the sc_flags field.
277 			 */
278 			sc->sc_flags |= TZF_SENSEINPROGRESS;
279 			sc->sc_cdb.len = sizeof(ScsiGroup0Cmd);
280 			scsiGroup0Cmd(SCSI_REQUEST_SENSE, sc->sc_sd->sd_slave,
281 				0, sizeof(sc->sc_sense.sense),
282 				(ScsiGroup0Cmd *)sc->sc_cdb.cdb);
283 			sc->sc_errbuf.b_flags = B_BUSY | B_READ;
284 			sc->sc_errbuf.b_bcount = sizeof(sc->sc_sense.sense);
285 			sc->sc_errbuf.b_un.b_addr = (caddr_t)sc->sc_sense.sense;
286 			sc->sc_errbuf.av_forw = bp;
287 			sc->sc_tab.b_actf = &sc->sc_errbuf;
288 			tzstart(unit);
289 			return;
290 		}
291 	} else {
292 		sc->sc_sense.status = status;
293 		bp->b_resid = resid;
294 	}
295 
296 	sc->sc_tab.b_actf = bp->b_actf;
297 	biodone(bp);
298 	if (sc->sc_tab.b_actf)
299 		tzstart(unit);
300 	else {
301 		sc->sc_tab.b_active = 0;
302 		if (sc->sc_flags & TZF_WAIT) {
303 			sc->sc_flags &= ~TZF_WAIT;
304 			wakeup(&sc->sc_flags);
305 		}
306 	}
307 }
308 
309 tzopen(dev, flags)
310 	dev_t dev;
311 	int flags;
312 {
313 	register int unit = tzunit(dev);
314 	register struct tz_softc *sc = &tz_softc[unit];
315 	int error;
316 
317 	if (unit >= NTZ)
318 		return (ENXIO);
319 	if (!(sc->sc_flags & TZF_ALIVE)) {
320 		/* check again, tape may have been turned off at boot time */
321 		if (!tzprobe(sc->sc_sd))
322 			return (ENXIO);
323 	}
324 	if (sc->sc_flags & TZF_OPEN)
325 		return (EBUSY);
326 
327 	/* clear UNIT_ATTENTION */
328 	error = tzcommand(dev, SCSI_TEST_UNIT_READY, 0, 0);
329 	if (error) {
330 		ScsiClass7Sense *sp = (ScsiClass7Sense *)sc->sc_sense.sense;
331 
332 		/* return error if last error was not UNIT_ATTENTION */
333 		if (!(sc->sc_sense.status & SCSI_STATUS_CHECKCOND) ||
334 		    sp->error7 != 0x70 || sp->key != SCSI_CLASS7_UNIT_ATTN)
335 			return (error);
336 	}
337 
338 #ifdef notdef
339 	if ((flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL)) {
340 		sc->sc_openf = 0;
341 		uprintf("tz%d: no write ring\n", unit);
342 		return (EIO);
343 	}
344 	sc->sc_ctty = (caddr_t)(u.u_procp->p_flag & SCTTY ?
345 			u.u_procp->p_session->s_ttyp : 0);
346 #endif
347 	sc->sc_flags = TZF_ALIVE | TZF_OPEN;
348 	return (0);
349 }
350 
351 tzclose(dev, flag)
352 	dev_t dev;
353 	int flag;
354 {
355 	register struct tz_softc *sc = &tz_softc[tzunit(dev)];
356 
357 	if (!(sc->sc_flags & TZF_OPEN))
358 		return (0);
359 	if (flag == FWRITE ||
360 	    ((flag & FWRITE) && (sc->sc_flags & TZF_WRITTEN))) {
361 		(void) tzcommand(dev, SCSI_WRITE_EOF, 0, 1);
362 	}
363 	if ((minor(dev) & TZ_NOREWIND) == 0)
364 		(void) tzcommand(dev, SCSI_REWIND, 0, 0);
365 	sc->sc_flags &= ~(TZF_OPEN | TZF_WRITTEN);
366 	return (0);
367 }
368 
369 tzioctl(dev, cmd, data, flag)
370 	dev_t dev;
371 	int cmd;
372 	caddr_t data;
373 	int flag;
374 {
375 	register struct tz_softc *sc = &tz_softc[tzunit(dev)];
376 	register struct buf *bp = &sc->sc_buf;
377 	struct mtop *mtop;
378 	struct mtget *mtget;
379 	int code, count;
380 	static tzops[] = {
381 		SCSI_WRITE_EOF, SCSI_SPACE, SCSI_SPACE, SCSI_SPACE, SCSI_SPACE,
382 		SCSI_REWIND, SCSI_REWIND, SCSI_TEST_UNIT_READY
383 	};
384 
385 	switch (cmd) {
386 
387 	case MTIOCTOP:	/* tape operation */
388 		mtop = (struct mtop *)data;
389 		if ((unsigned)mtop->mt_op < MTREW && mtop->mt_count <= 0)
390 			return (EINVAL);
391 		switch (mtop->mt_op) {
392 
393 		case MTWEOF:
394 			code = 0;
395 			count = mtop->mt_count;
396 			break;
397 
398 		case MTFSF:
399 			code = 1;
400 			count = mtop->mt_count;
401 			break;
402 
403 		case MTBSF:
404 			code = 1;
405 			count = -mtop->mt_count;
406 			break;
407 
408 		case MTFSR:
409 			code = 0;
410 			break;
411 
412 		case MTBSR:
413 			code = 0;
414 			count = -mtop->mt_count;
415 			break;
416 
417 		case MTREW:
418 		case MTOFFL:
419 		case MTNOP:
420 			code = 0;
421 			count = 0;
422 			break;
423 
424 		default:
425 			return (EINVAL);
426 		}
427 		return (tzcommand(dev, tzops[mtop->mt_op], code, count));
428 
429 	case MTIOCGET:
430 		mtget = (struct mtget *)data;
431 		mtget->mt_dsreg = 0;
432 		mtget->mt_erreg = sc->sc_sense.status;
433 		mtget->mt_resid = 0;
434 		mtget->mt_type = 0;
435 		break;
436 
437 	default:
438 		return (EINVAL);
439 	}
440 	return (0);
441 }
442 
443 void
444 tzstrategy(bp)
445 	register struct buf *bp;
446 {
447 	register int unit = tzunit(bp->b_dev);
448 	register struct tz_softc *sc = &tz_softc[unit];
449 	register struct buf *dp;
450 	register int s;
451 
452 	bp->av_forw = NULL;
453 	dp = &sc->sc_tab;
454 	s = splbio();
455 	if (dp->b_actf == NULL)
456 		dp->b_actf = bp;
457 	else
458 		dp->b_actl->av_forw = bp;
459 	dp->b_actl = bp;
460 	if (dp->b_active == 0) {
461 		dp->b_active = 1;
462 		tzstart(unit);
463 	}
464 	splx(s);
465 }
466 #endif
467