xref: /original-bsd/sys/pmax/dev/tz.c (revision e59fb703)
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.1 (Berkeley) 01/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 	extern int sii_debug; /* XXX */
177 
178 	sc->sc_cmd.buf = bp->b_un.b_addr;
179 	sc->sc_cmd.buflen = bp->b_bcount;
180 
181 	if (sc->sc_flags & (TZF_SENSEINPROGRESS | TZF_ALTCMD)) {
182 		sc->sc_cmd.dataToDevice = !(bp->b_flags & B_READ);
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.dataToDevice = 0;
188 			sc->sc_rwcmd.command = SCSI_READ;
189 		} else {
190 			sc->sc_cmd.dataToDevice = 1;
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 		sii_debug = 5; /* XXX */
209 	(*sc->sc_sd->sd_cdriver->d_start)(&sc->sc_cmd);
210 }
211 
212 /*
213  * This is called by the controller driver when the command is done.
214  */
215 void
216 tzdone(unit, error, resid, status)
217 	int unit;
218 	int error;		/* error number from errno.h */
219 	int resid;		/* amount not transfered */
220 	int status;		/* SCSI status byte */
221 {
222 	register struct tz_softc *sc = &tz_softc[unit];
223 	register struct buf *bp = sc->sc_tab.b_actf;
224 	extern int cold;
225 	extern int sii_debug; /* XXX */
226 
227 	printf("tzdone(%d, %d, %d, %x) %x flags %x\n", unit, error, resid,
228 		status, sc, sc->sc_flags); /* XXX */
229 	if (bp == NULL) {
230 		printf("tz%d: bp == NULL\n", unit);
231 		return;
232 	}
233 	if (sc->sc_flags & TZF_SENSEINPROGRESS) {
234 		sc->sc_flags &= ~TZF_SENSEINPROGRESS;
235 		sc->sc_tab.b_actf = bp = bp->b_actf;	/* remove sc_errbuf */
236 		if (bp == 0) {
237 			sii_DumpLog();
238 			panic("tzdone"); /* XXX */
239 		}
240 
241 		if (error || (status & SCSI_STATUS_CHECKCOND)) {
242 #ifdef DEBUG
243 			if (tzdebug)
244 				printf("tz%d: error reading sense data: error %d scsi status 0x%x\n",
245 					unit, error, status);
246 #endif
247 			/*
248 			 * We got an error during the REQUEST_SENSE,
249 			 * fill in no sense for data.
250 			 */
251 			sc->sc_sense.sense[0] = 0x70;
252 			sc->sc_sense.sense[2] = SCSI_CLASS7_NO_SENSE;
253 		} else if (!cold
254 #ifdef DEBUG
255 			|| tzdebug
256 #endif
257 		) {
258 			printf("tz%d: ", unit);
259 			scsiPrintSense((ScsiClass7Sense *)sc->sc_sense.sense,
260 				sizeof(sc->sc_sense.sense) - resid);
261 		}
262 	} else if (error || (status & SCSI_STATUS_CHECKCOND)) {
263 #ifdef DEBUG
264 		if (tzdebug)
265 			printf("tz%d: error %d scsi status 0x%x\n",
266 				unit, error, status);
267 #endif
268 		/* save error info */
269 		sc->sc_sense.status = status;
270 		bp->b_flags |= B_ERROR;
271 		bp->b_error = error;
272 		bp->b_resid = resid;
273 
274 		if (status & SCSI_STATUS_CHECKCOND) {
275 			/*
276 			 * Start a REQUEST_SENSE command.
277 			 * Since we are called at interrupt time, we can't
278 			 * wait for the command to finish; that's why we use
279 			 * the sc_flags field.
280 			 */
281 			sc->sc_flags |= TZF_SENSEINPROGRESS;
282 			sc->sc_cdb.len = sizeof(ScsiGroup0Cmd);
283 			scsiGroup0Cmd(SCSI_REQUEST_SENSE, sc->sc_sd->sd_slave,
284 				0, sizeof(sc->sc_sense.sense),
285 				(ScsiGroup0Cmd *)sc->sc_cdb.cdb);
286 			sc->sc_errbuf.b_flags = B_BUSY | B_READ;
287 			sc->sc_errbuf.b_bcount = sizeof(sc->sc_sense.sense);
288 			sc->sc_errbuf.b_un.b_addr = (caddr_t)sc->sc_sense.sense;
289 			sc->sc_errbuf.av_forw = bp;
290 			sc->sc_tab.b_actf = &sc->sc_errbuf;
291 			tzstart(unit);
292 			return;
293 		}
294 	} else {
295 		sc->sc_sense.status = status;
296 		bp->b_resid = resid;
297 	}
298 
299 	sc->sc_tab.b_actf = bp->b_actf;
300 	biodone(bp);
301 	if (sc->sc_tab.b_actf)
302 		tzstart(unit);
303 	else {
304 		sii_debug = 1; /* XXX */
305 		sc->sc_tab.b_active = 0;
306 		if (sc->sc_flags & TZF_WAIT) {
307 			sc->sc_flags &= ~TZF_WAIT;
308 			wakeup(&sc->sc_flags);
309 		}
310 	}
311 }
312 
313 tzopen(dev, flags)
314 	dev_t dev;
315 	int flags;
316 {
317 	register int unit = tzunit(dev);
318 	register struct tz_softc *sc = &tz_softc[unit];
319 	int error;
320 
321 	if (unit >= NTZ)
322 		return (ENXIO);
323 	if (!(sc->sc_flags & TZF_ALIVE)) {
324 		/* check again, tape may have been turned off at boot time */
325 		if (!tzprobe(sc->sc_sd))
326 			return (ENXIO);
327 	}
328 	if (sc->sc_flags & TZF_OPEN)
329 		return (EBUSY);
330 
331 	/* clear UNIT_ATTENTION */
332 	error = tzcommand(dev, SCSI_TEST_UNIT_READY, 0, 0);
333 	if (error) {
334 		ScsiClass7Sense *sp = (ScsiClass7Sense *)sc->sc_sense.sense;
335 
336 		/* return error if last error was not UNIT_ATTENTION */
337 		if (!(sc->sc_sense.status & SCSI_STATUS_CHECKCOND) ||
338 		    sp->error7 != 0x70 || sp->key != SCSI_CLASS7_UNIT_ATTN)
339 			return (error);
340 	}
341 
342 #ifdef notdef
343 	if ((flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL)) {
344 		sc->sc_openf = 0;
345 		uprintf("tu%d: no write ring\n", tuunit);
346 		return (EIO);
347 	}
348 	sc->sc_ctty = (caddr_t)(u.u_procp->p_flag & SCTTY ?
349 			u.u_procp->p_session->s_ttyp : 0);
350 #endif
351 	sc->sc_flags = TZF_ALIVE | TZF_OPEN;
352 	return (0);
353 }
354 
355 tzclose(dev, flag)
356 	dev_t dev;
357 	int flag;
358 {
359 	register struct tz_softc *sc = &tz_softc[tzunit(dev)];
360 
361 	if (!(sc->sc_flags & TZF_OPEN))
362 		return (0);
363 	if (flag == FWRITE ||
364 	    ((flag & FWRITE) && (sc->sc_flags & TZF_WRITTEN))) {
365 		(void) tzcommand(dev, SCSI_WRITE_EOF, 0, 1);
366 	}
367 	if ((minor(dev) & TZ_NOREWIND) == 0)
368 		(void) tzcommand(dev, SCSI_REWIND, 0, 0);
369 	sc->sc_flags &= ~(TZF_OPEN | TZF_WRITTEN);
370 	return (0);
371 }
372 
373 tzioctl(dev, cmd, data, flag)
374 	dev_t dev;
375 	int cmd;
376 	caddr_t data;
377 	int flag;
378 {
379 	register struct tz_softc *sc = &tz_softc[tzunit(dev)];
380 	register struct buf *bp = &sc->sc_buf;
381 	struct mtop *mtop;
382 	struct mtget *mtget;
383 	int code, count;
384 	static tzops[] = {
385 		SCSI_WRITE_EOF, SCSI_SPACE, SCSI_SPACE, SCSI_SPACE, SCSI_SPACE,
386 		SCSI_REWIND, SCSI_REWIND, SCSI_TEST_UNIT_READY
387 	};
388 
389 	switch (cmd) {
390 
391 	case MTIOCTOP:	/* tape operation */
392 		mtop = (struct mtop *)data;
393 		if ((unsigned)mtop->mt_op < MTREW && mtop->mt_count <= 0)
394 			return (EINVAL);
395 		switch (mtop->mt_op) {
396 
397 		case MTWEOF:
398 			code = 0;
399 			count = mtop->mt_count;
400 			break;
401 
402 		case MTFSF:
403 			code = 1;
404 			count = mtop->mt_count;
405 			break;
406 
407 		case MTBSF:
408 			code = 1;
409 			count = -mtop->mt_count;
410 			break;
411 
412 		case MTFSR:
413 			code = 0;
414 			break;
415 
416 		case MTBSR:
417 			code = 0;
418 			count = -mtop->mt_count;
419 			break;
420 
421 		case MTREW:
422 		case MTOFFL:
423 		case MTNOP:
424 			code = 0;
425 			count = 0;
426 			break;
427 
428 		default:
429 			return (EINVAL);
430 		}
431 		return (tzcommand(dev, tzops[mtop->mt_op], code, count));
432 
433 	case MTIOCGET:
434 		mtget = (struct mtget *)data;
435 		mtget->mt_dsreg = 0;
436 		mtget->mt_erreg = sc->sc_sense.status;
437 		mtget->mt_resid = 0;
438 		mtget->mt_type = 0;
439 		break;
440 
441 	default:
442 		return (EINVAL);
443 	}
444 	return (0);
445 }
446 
447 void
448 tzstrategy(bp)
449 	register struct buf *bp;
450 {
451 	register int unit = tzunit(bp->b_dev);
452 	register struct tz_softc *sc = &tz_softc[unit];
453 	register struct buf *dp;
454 	register int s;
455 
456 	bp->av_forw = NULL;
457 	dp = &sc->sc_tab;
458 	s = splbio();
459 	if (dp->b_actf == NULL)
460 		dp->b_actf = bp;
461 	else
462 		dp->b_actl->av_forw = bp;
463 	dp->b_actl = bp;
464 	if (dp->b_active == 0) {
465 		dp->b_active = 1;
466 		tzstart(unit);
467 	}
468 	splx(s);
469 }
470 #endif
471