xref: /csrg-svn/sys/luna68k/dev/st.c (revision 57127)
1 /*
2  * Copyright (c) 1992 OMRON Corporation.
3  * Copyright (c) 1992 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * OMRON Corporation.
8  *
9  * %sccs.include.redist.c%
10  *
11  *	@(#)st.c	7.5 (Berkeley) 12/14/92
12  */
13 
14 /*
15  * st.c -- TEAC MT-2ST/N60 SCSI TAPE UNIT Device Driver
16  * remaked by A.Fujita, MAR-22-1992
17  */
18 
19 /*
20  * SCSI CCS (Command Command Set) disk driver.
21  */
22 #include "st.h"
23 #if NST > 0
24 
25 #include <sys/param.h>
26 #include <sys/systm.h>
27 #include <sys/buf.h>
28 #include <sys/file.h>
29 #include <sys/proc.h>
30 #include <sys/mtio.h>
31 #include <sys/tprintf.h>
32 
33 #include <luna68k/dev/device.h>
34 #include <luna68k/dev/scsireg.h>
35 #include <luna68k/dev/scsivar.h>
36 
37 extern int scsi_test_unit_rdy();
38 extern int scsi_request_sense();
39 extern int scsi_immed_command();
40 extern char *scsi_status();
41 
42 extern int scgo();
43 extern void scfree();
44 
45 char *sense_key();
46 
47 int	stinit(), ststrategy(), ststart(), stintr();
48 
49 struct	driver stdriver = {
50 	stinit, "st", ststart, (int (*)()) 0, stintr, (int (*)()) 0
51 };
52 
53 struct	st_softc {
54 	struct	hp_device *sc_hd;
55 	struct	scsi_queue sc_dq;
56 	int	sc_flags;
57 	short	sc_type;	/* drive type */
58 	short	sc_punit;	/* physical unit (scsi lun) */
59 	tpr_t	sc_ctty;
60 } st_softc[NST];
61 
62 /* softc flags */
63 #define STF_ALIVE	0x0001
64 #define STF_OPEN	0x0002
65 #define STF_WMODE	0x0004
66 #define STF_WRTTN	0x0008
67 #define STF_CMD		0x0010
68 #define STF_LEOT	0x0020
69 #define STF_MOVED	0x0040
70 
71 u_char xsense_buff[60];
72 
73 struct scsi_fmt_cdb st_read_cmd  = { 6, CMD_READ  };
74 struct scsi_fmt_cdb st_write_cmd = { 6, CMD_WRITE };
75 
76 struct buf sttab[NST];
77 struct buf stbuf[NST];
78 
79 #define	stunit(x)	(minor(x) & 3)
80 #define	stpunit(x)	((x) & 7)
81 
82 #define STDEV_NOREWIND	0x04
83 
84 #define	STRETRY		2	/* IO retry count */
85 
86 struct st_iostat {
87 	int imax;
88 	int imin;
89 	int omax;
90 	int omin;
91 };
92 
93 struct st_iostat st_iostat[NST];
94 
95 
96 /*
97  * Initialize
98  */
99 
100 int
101 stinit(hd)
102 	register struct hp_device *hd;
103 {
104 	register struct st_softc *sc = &st_softc[hd->hp_unit];
105 
106 	sc->sc_hd = hd;
107 	sc->sc_punit = stpunit(hd->hp_flags);
108 	sc->sc_type = stident(sc, hd);
109 	if (sc->sc_type < 0)
110 		return(0);
111 	sc->sc_dq.dq_ctlr = hd->hp_ctlr;
112 	sc->sc_dq.dq_unit = hd->hp_unit;
113 	sc->sc_dq.dq_slave = hd->hp_slave;
114 	sc->sc_dq.dq_driver = &stdriver;
115 	sc->sc_flags = STF_ALIVE;
116 	return(1);
117 }
118 
119 static struct scsi_inquiry inqbuf;
120 static struct scsi_fmt_cdb inq = {
121 	6,
122 	CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
123 };
124 
125 int
126 stident(sc, hd)
127 	struct st_softc *sc;
128 	struct hp_device *hd;
129 {
130 	char idstr[32];
131 	int unit;
132 	register int ctlr, slave;
133 	register int i, stat;
134 	register int tries = 10;
135 
136 	ctlr = hd->hp_ctlr;
137 	slave = hd->hp_slave;
138 	unit = sc->sc_punit;
139 
140 	/*
141 	 * See if unit exists and is a disk then read block size & nblocks.
142 	 */
143 	while ((stat = scsi_immed_command(ctlr, slave, unit,
144 				  &inq, (u_char *)&inqbuf, sizeof(inqbuf))) != 0) {
145 		if (stat < 0 || --tries < 0)
146 			return (-1);
147 		DELAY(1000);
148 	}
149 
150 	switch (inqbuf.type) {
151 	case 1:		/* tape */
152 		break;
153 	default:	/* not a disk */
154 		printf("stident: inqbuf.type = %d\n", inqbuf.type);
155 		return (-1);
156 	}
157 
158 	bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
159 	for (i = 27; i > 23; --i)
160 		if (idstr[i] != ' ')
161 			break;
162 	idstr[i+1] = 0;
163 	for (i = 23; i > 7; --i)
164 		if (idstr[i] != ' ')
165 			break;
166 	idstr[i+1] = 0;
167 	for (i = 7; i >= 0; --i)
168 		if (idstr[i] != ' ')
169 			break;
170 	idstr[i+1] = 0;
171 	printf("st%d: %s %s rev %s\n", hd->hp_unit, idstr, &idstr[8],
172 	       &idstr[24]);
173 
174 	return(inqbuf.type);
175 }
176 
177 
178 /*
179  * Open
180  */
181 
182 int
183 stopen(dev, flag, type, p)
184 	dev_t dev;
185 	int flag, type;
186 	struct proc *p;
187 {
188 	register int unit = stunit(dev);
189 	register struct st_softc *sc = &st_softc[unit];
190 	register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff;
191 	int ctlr  = sc->sc_dq.dq_ctlr;
192 	int slave = sc->sc_dq.dq_slave;
193 	int stat, retry = 9;
194 
195 	if (unit >= NST || (sc->sc_flags & STF_ALIVE) == 0)
196 		return(-1);
197 	if (sc->sc_flags & STF_OPEN)
198 		return(-1);
199 
200 	sc->sc_ctty = tprintf_open(p);
201 
202 	/* drive ready ? */
203 	while ((stat = scsi_test_unit_rdy(ctlr, slave, 0)) != 0) {
204 		scsi_request_sense(ctlr, slave, 0, sp, 8);
205 
206 		if (stat != STS_CHECKCOND) {
207 			tprintf(sc->sc_ctty,
208 				"st%d:[stopen]   %s\n", unit, scsi_status(stat));
209 			tprintf_close(sc->sc_ctty);
210 			return(EIO);
211 		}
212 
213 		if (retry-- < 0) {
214 			tprintf(sc->sc_ctty,
215 				"st%d:[stopen]   %s\n", unit, sense_key(sp->key));
216 			tprintf_close(sc->sc_ctty);
217 			return(EIO);
218 		}
219 
220 		DELAY(1000000);
221 	}
222 
223 	sc->sc_flags |= STF_OPEN;
224 	if (flag & FWRITE)
225 		sc->sc_flags |= STF_WMODE;
226 	sc->sc_flags &= ~STF_MOVED;
227 
228 	return(0);
229 }
230 
231 /*ARGSUSED*/
232 stclose(dev)
233 	dev_t dev;
234 {
235 	register int unit = stunit(dev);
236 	register struct st_softc *sc = &st_softc[unit];
237 	register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff;
238 	int ctlr  = sc->sc_hd->hp_ctlr;
239 	int slave = sc->sc_hd->hp_slave;
240 	int stat, retry = 9;
241 
242 	if ((sc->sc_flags & (STF_WMODE|STF_WRTTN)) == (STF_WMODE|STF_WRTTN)) {
243 		st_write_EOF(dev);
244 	}
245 
246 	if ((minor(dev) & STDEV_NOREWIND) == 0) {
247 		st_rewind(dev);
248 	}
249 
250 	sc->sc_flags &= ~(STF_OPEN|STF_WMODE|STF_WRTTN);
251 
252 	tprintf_close(sc->sc_ctty);
253 
254 	return(0);
255 }
256 
257 /*
258  * Strategy
259  */
260 
261 int
262 ststrategy(bp)
263 	register struct buf *bp;
264 {
265 	register int unit = stunit(bp->b_dev);
266 	register struct buf *dp = &sttab[unit];
267 	int s;
268 
269 	bp->av_forw = NULL;
270 
271 	s = splbio();
272 
273 	if (dp->b_actf == NULL)
274 		dp->b_actf = bp;
275 	else
276 		dp->b_actl->av_forw = bp;
277 
278 	dp->b_actl = bp;
279 
280 	if (dp->b_active == 0) {
281 		dp->b_active = 1;
282 		stustart(unit);
283 	}
284 
285 	splx(s);
286 }
287 
288 int
289 stustart(unit)
290 	register int unit;
291 {
292 	register struct st_softc *sc = &st_softc[unit];
293 	register struct hp_device *hp = sc->sc_hd;
294 	register struct scsi_queue *dq = &sc->sc_dq;
295 	register struct buf *bp = sttab[unit].b_actf;
296 	register struct scsi_fmt_cdb *cmd;
297 	long nblks;
298 
299 	cmd = bp->b_flags & B_READ ? &st_read_cmd : &st_write_cmd;
300 	cmd->cdb[1] = 1;		/* unknown setup */
301 
302 	if (bp->b_flags & B_READ)
303 		sc->sc_flags &= ~STF_WRTTN;
304 	else
305 		sc->sc_flags |= STF_WRTTN;
306 
307 	nblks = bp->b_bcount >> DEV_BSHIFT;
308 
309 	if (bp->b_bcount % DEV_BSIZE) {
310 		tprintf(sc->sc_ctty,
311 			"st%d:[stustart] I/O not block aligned %d/%ld\n",
312 			unit, DEV_BSIZE, bp->b_bcount);
313 
314 		bp->b_flags |= B_ERROR;
315 		bp->b_error = EIO;
316 
317 		sttab[unit].b_errcnt = 0;
318 		sttab[unit].b_actf = bp->b_actf;
319 
320 		bp->b_resid = 0;
321 
322 		biodone(bp);
323 
324 		if (sttab[unit].b_actf) {
325 			stustart(unit);
326 		} else {
327 			sttab[unit].b_active = 0;
328 		}
329 	}
330 
331 	*(u_char *)(&cmd->cdb[2]) = (u_char) (nblks >> 16);
332 	*(u_char *)(&cmd->cdb[3]) = (u_char) (nblks >>  8);
333 	*(u_char *)(&cmd->cdb[4]) = (u_char)  nblks;
334 
335 	cmd->cdb[5] = 0;		/* unknown setup */
336 
337 	sc->sc_flags |= STF_MOVED;
338 
339 	dq->dq_cdb = cmd;
340 	dq->dq_bp  = bp;
341 	dq->dq_flags = 0;		/* No Disconnect */
342 
343 	if (screq(dq))
344 		ststart(unit);
345 }
346 
347 int
348 ststart(unit)
349 	register int unit;
350 {
351 	register struct st_softc *sc = &st_softc[unit];
352 	register struct hp_device *hp = sc->sc_hd;
353 
354 	scstart(hp->hp_ctlr);
355 }
356 
357 /*
358  * Interrupt
359  */
360 
361 char *
362 sense_key(key)
363 	int key;
364 {
365 	if (key == 0)
366 		return("No Sense");
367 	else if (key == 2)
368 		return("Not Ready");
369 	else if (key == 3)
370 		return("Medium Error");
371 	else if (key == 4)
372 		return("Hardware Error");
373 	else if (key == 5)
374 		return("Illegal Request");
375 	else if (key == 6)
376 		return("Unit Attention");
377 	else if (key == 7)
378 		return("Data Protect");
379 	else if (key == 8)
380 		return("No Data");
381 	else if (key == 11)
382 		return("Aborted Command");
383 	else if (key == 13)
384 		return("Volume Overflow");
385 	else
386 		return("Unknown Error");
387 }
388 
389 int
390 stintr(unit, stat)
391 	register int unit;
392 	int stat;
393 {
394 	register struct st_softc *sc = &st_softc[unit];
395 	register struct scsi_xsense *xp = (struct scsi_xsense *) xsense_buff;
396 	register struct scsi_queue *dq = &sc->sc_dq;
397 	register struct buf *bp = dq->dq_bp;
398 	int ctlr  = dq->dq_ctlr;
399 	int slave = dq->dq_slave;
400 
401 	if (bp->b_flags & B_READ) {
402 		st_iostat[unit].imin = min(dq->dq_imin, st_iostat[unit].imin);
403 		if (dq->dq_imax > st_iostat[unit].imax) {
404 			st_iostat[unit].imax = dq->dq_imax;
405 #ifdef ST_IOSTAT
406 			printf("stintr: st%d  INPUT	MAX = %d, MIN = %d\n",
407 			       unit, st_iostat[unit].imax, st_iostat[unit].imin);
408 #endif
409 		}
410 	} else {
411 		st_iostat[unit].omin = min(dq->dq_omin, st_iostat[unit].omin);
412 		if (dq->dq_omax > st_iostat[unit].omax) {
413 			st_iostat[unit].omax = dq->dq_omax;
414 #ifdef ST_IOSTAT
415 			printf("stintr: st%d  OUTPUT	MAX = %d, MIN = %d\n",
416 			       unit, st_iostat[unit].omax, st_iostat[unit].omin);
417 #endif
418 		}
419 	}
420 	if (stat < 0) {
421 		bp->b_flags |= B_ERROR;
422 		bp->b_error = EIO;
423 		goto done;
424 	}
425 
426 	switch (stat) {
427 	/* scsi command completed ok */
428 	case 0:
429 		bp->b_resid = 0;
430 		break;
431 
432 	/* more status */
433 	case STS_CHECKCOND:
434 		scsi_request_sense(ctlr, slave, 0, xp, 8);
435 #ifdef DEBUG
436 		printf("stintr: xsense_buff[0] = 0x%s\n", hexstr(xsense_buff[0], 2));
437 		printf("stintr: xsense_buff[2] = 0x%s\n", hexstr(xsense_buff[2], 2));
438 		printf("stintr: Sense Key = [%s]\n", sense_key(xp->key));
439 #endif
440 		if (xp->valid) {
441 			bp->b_resid = (u_long)((xp->info1 << 24) |
442 					       (xp->info2 << 16) |
443 					       (xp->info3 << 8) |
444 					       (xp->info4));
445 			bp->b_resid <<= DEV_BSHIFT;
446 		}
447 
448 		if (xp->filemark) {		/* End of File */
449 /*
450 			tprintf(sc->sc_ctty, "st%d:[stintr]   End of File\n", unit);
451 			bp->b_flags |= B_ERROR;
452 			bp->b_error = EIO;
453  */
454 			break;
455 		}
456 
457 		if (xp->key) {
458 			tprintf(sc->sc_ctty, "st%d:[stintr]   %s\n", unit, sense_key(xp->key));
459 			bp->b_flags |= B_ERROR;
460 			bp->b_error = EIO;
461 			break;
462 		}
463 
464 		if (xp->eom) {		/* End of TAPE */
465 			tprintf(sc->sc_ctty, "st%d:[stintr]   End of Tape\n", unit);
466 			bp->b_flags |= B_ERROR;
467 			bp->b_error = ENOSPC;
468 			break;
469 		}
470 
471 		tprintf(sc->sc_ctty, "st%d:[stintr]   unknown scsi error\n", unit);
472 		bp->b_flags |= B_ERROR;
473 		bp->b_error = EIO;
474 		break;
475 
476 	default:
477 		tprintf(sc->sc_ctty, "st%d:[stintr]   stintr unknown stat 0x%x\n", unit, stat);
478 		break;
479 	}
480 
481 done:
482 	sttab[unit].b_errcnt = 0;
483 	sttab[unit].b_actf = bp->b_actf;
484 
485 	bp->b_resid = 0;
486 
487 	biodone(bp);
488 
489 	scfree(&sc->sc_dq);
490 
491 	if (sttab[unit].b_actf) {
492 		stustart(unit);
493 	} else {
494 		sttab[unit].b_active = 0;
495 	}
496 }
497 
498 
499 /*
500  * RAW Device Routines
501  */
502 
503 
504 stread(dev, uio)
505 	dev_t dev;
506 	struct uio *uio;
507 {
508 	int unit = stunit(dev);
509 
510 	return(physio(ststrategy, &stbuf[unit], dev, B_READ, minphys, uio));
511 }
512 
513 stwrite(dev, uio)
514 	dev_t dev;
515 	struct uio *uio;
516 {
517 	int unit = stunit(dev);
518 
519 	return(physio(ststrategy, &stbuf[unit], dev, B_WRITE, minphys, uio));
520 }
521 
522 int
523 stioctl(dev, cmd, data, flag, p)
524 	dev_t dev;
525 	int cmd;
526 	caddr_t data;
527 	int flag;
528 	struct proc *p;
529 {
530 	return(ENXIO);
531 }
532 
533 struct scsi_fmt_cdb st_cmd;
534 
535 st_rewind(dev)
536 	dev_t dev;
537 {
538 	register int unit = stunit(dev);
539 	register struct st_softc *sc = &st_softc[unit];
540 	register struct scsi_fmt_cdb *cdb = &st_cmd;
541 	register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff;
542 	int ctlr, slave, stat;
543 	int retry = 9;
544 
545 	ctlr  = sc->sc_hd->hp_ctlr;
546 	slave = sc->sc_hd->hp_slave;
547 
548 	cdb->len = 6;
549 
550 	cdb->cdb[0] = CMD_REWIND;
551 
552 	cdb->cdb[1] = 1;	/* command finished soon */
553 
554 	cdb->cdb[2] = 0;
555 	cdb->cdb[3] = 0;
556 	cdb->cdb[4] = 0;
557 
558 	cdb->cdb[5] = 0;		/* unknown setup */
559 
560  rewind:
561 	stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0);
562 
563 	if (stat == 0) {
564 		return(1);
565 	} else {
566 		tprintf(sc->sc_ctty, "st%d:[st_rewind]   rewind error\n", unit);
567 		scsi_request_sense(ctlr, slave, 0, sp, 8);
568 		tprintf(sc->sc_ctty,
569 			"st%d:[st_rewind]   status = 0x%x, sens key = 0x%x\n",
570 			unit, stat, sp->key);
571 
572 		if (retry > 0) {
573 			DELAY(1000000);
574 			retry--;
575 			goto rewind;
576 		}
577 
578 		return(0);
579 	}
580 }
581 
582 st_write_EOF(dev)
583 	dev_t dev;
584 {
585 	register int unit = stunit(dev);
586 	register struct st_softc *sc = &st_softc[unit];
587 	register struct scsi_fmt_cdb *cdb = &st_cmd;
588 	int ctlr, slave, stat;
589 	int marks = 1;
590 
591 	ctlr  = sc->sc_hd->hp_ctlr;
592 	slave = sc->sc_hd->hp_slave;
593 
594 	cdb->len = 6;
595 
596 	cdb->cdb[0] = CMD_WRITE_FILEMARK;
597 
598 	cdb->cdb[1] = 0;
599 
600 	cdb->cdb[2] = 0;
601 	cdb->cdb[3] = 0;
602 	cdb->cdb[4] = marks;
603 
604 	cdb->cdb[5] = 0;		/* unknown setup */
605 
606 	stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0);
607 
608 	if (stat == 0)
609 		return(1);
610 
611 	tprintf(sc->sc_ctty, "st%d:[st_write_EOF]   write EOF error\n", unit);
612 
613 	return(0);
614 }
615 
616 /*
617  * Dump
618  */
619 
620 int
621 stdump(dev)
622 	dev_t dev;
623 {
624 }
625 #endif
626