xref: /original-bsd/sys/luna68k/dev/st.c (revision 95ecee29)
1 /*
2  * Copyright (c) 1992 OMRON Corporation.
3  * Copyright (c) 1992, 1993
4  *	The Regents of the University of California.  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	8.2 (Berkeley) 12/06/93
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/screg.h>
35 #include <luna68k/dev/scvar.h>
36 
37 extern int sc_test_unit_rdy();
38 extern int sc_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 	register struct buf *bp;
106 
107 	for (bp = sttab; bp < &sttab[NST]; bp++)
108 		bp->b_actb = &bp->b_actf;
109 	sc->sc_hd = hd;
110 	sc->sc_punit = stpunit(hd->hp_flags);
111 	sc->sc_type = stident(sc, hd);
112 	if (sc->sc_type < 0)
113 		return(0);
114 	sc->sc_dq.dq_ctlr = hd->hp_ctlr;
115 	sc->sc_dq.dq_unit = hd->hp_unit;
116 	sc->sc_dq.dq_slave = hd->hp_slave;
117 	sc->sc_dq.dq_driver = &stdriver;
118 	sc->sc_flags = STF_ALIVE;
119 	return(1);
120 }
121 
122 static struct scsi_inquiry inqbuf;
123 static struct scsi_fmt_cdb inq = {
124 	6,
125 	CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
126 };
127 
128 int
129 stident(sc, hd)
130 	struct st_softc *sc;
131 	struct hp_device *hd;
132 {
133 	char idstr[32];
134 	int unit;
135 	register int ctlr, slave;
136 	register int i, stat;
137 	register int tries = 10;
138 
139 	ctlr = hd->hp_ctlr;
140 	slave = hd->hp_slave;
141 	unit = sc->sc_punit;
142 
143 	/*
144 	 * See if unit exists and is a disk then read block size & nblocks.
145 	 */
146 	while ((stat = scsi_immed_command(ctlr, slave, unit,
147 				  &inq, (u_char *)&inqbuf, sizeof(inqbuf))) != 0) {
148 		if (stat < 0 || --tries < 0)
149 			return (-1);
150 		DELAY(1000);
151 	}
152 
153 	switch (inqbuf.type) {
154 	case 1:		/* tape */
155 		break;
156 	default:	/* not a disk */
157 		printf("stident: inqbuf.type = %d\n", inqbuf.type);
158 		return (-1);
159 	}
160 
161 	bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
162 	for (i = 27; i > 23; --i)
163 		if (idstr[i] != ' ')
164 			break;
165 	idstr[i+1] = 0;
166 	for (i = 23; i > 7; --i)
167 		if (idstr[i] != ' ')
168 			break;
169 	idstr[i+1] = 0;
170 	for (i = 7; i >= 0; --i)
171 		if (idstr[i] != ' ')
172 			break;
173 	idstr[i+1] = 0;
174 	printf("st%d: %s %s rev %s\n", hd->hp_unit, idstr, &idstr[8],
175 	       &idstr[24]);
176 
177 	return(inqbuf.type);
178 }
179 
180 
181 /*
182  * Open
183  */
184 
185 int
186 stopen(dev, flag, type, p)
187 	dev_t dev;
188 	int flag, type;
189 	struct proc *p;
190 {
191 	register int unit = stunit(dev);
192 	register struct st_softc *sc = &st_softc[unit];
193 	register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff;
194 	int ctlr  = sc->sc_dq.dq_ctlr;
195 	int slave = sc->sc_dq.dq_slave;
196 	int stat, retry = 9;
197 
198 	if (unit >= NST || (sc->sc_flags & STF_ALIVE) == 0)
199 		return(-1);
200 	if (sc->sc_flags & STF_OPEN)
201 		return(-1);
202 
203 	sc->sc_ctty = tprintf_open(p);
204 
205 	/* drive ready ? */
206 	while ((stat = sc_test_unit_rdy(ctlr, slave, 0)) != 0) {
207 		sc_request_sense(ctlr, slave, 0, sp, 8);
208 
209 		if (stat != STS_CHECKCOND) {
210 			tprintf(sc->sc_ctty,
211 				"st%d:[stopen]   %s\n", unit, scsi_status(stat));
212 			tprintf_close(sc->sc_ctty);
213 			return(EIO);
214 		}
215 
216 		if (retry-- < 0) {
217 			tprintf(sc->sc_ctty,
218 				"st%d:[stopen]   %s\n", unit, sense_key(sp->key));
219 			tprintf_close(sc->sc_ctty);
220 			return(EIO);
221 		}
222 
223 		DELAY(1000000);
224 	}
225 
226 	sc->sc_flags |= STF_OPEN;
227 	if (flag & FWRITE)
228 		sc->sc_flags |= STF_WMODE;
229 	sc->sc_flags &= ~STF_MOVED;
230 
231 	return(0);
232 }
233 
234 /*ARGSUSED*/
235 stclose(dev)
236 	dev_t dev;
237 {
238 	register int unit = stunit(dev);
239 	register struct st_softc *sc = &st_softc[unit];
240 	register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff;
241 	int ctlr  = sc->sc_hd->hp_ctlr;
242 	int slave = sc->sc_hd->hp_slave;
243 	int stat, retry = 9;
244 
245 	if ((sc->sc_flags & (STF_WMODE|STF_WRTTN)) == (STF_WMODE|STF_WRTTN)) {
246 		st_write_EOF(dev);
247 	}
248 
249 	if ((minor(dev) & STDEV_NOREWIND) == 0) {
250 		st_rewind(dev);
251 	}
252 
253 	sc->sc_flags &= ~(STF_OPEN|STF_WMODE|STF_WRTTN);
254 
255 	tprintf_close(sc->sc_ctty);
256 
257 	return(0);
258 }
259 
260 /*
261  * Strategy
262  */
263 
264 int
265 ststrategy(bp)
266 	register struct buf *bp;
267 {
268 	register int unit = stunit(bp->b_dev);
269 	register struct buf *dp = &sttab[unit];
270 	int s;
271 
272 	bp->b_actf = NULL;
273 	s = splbio();
274 	bp->b_actb = dp->b_actb;
275 	*dp->b_actb = bp;
276 	dp->b_actb = &bp->b_actf;
277 	if (dp->b_active == 0) {
278 		dp->b_active = 1;
279 		stustart(unit);
280 	}
281 
282 	splx(s);
283 }
284 
285 int
286 stustart(unit)
287 	register int unit;
288 {
289 	register struct st_softc *sc = &st_softc[unit];
290 	register struct hp_device *hp = sc->sc_hd;
291 	register struct scsi_queue *dq = &sc->sc_dq;
292 	register struct buf *dp, *bp = sttab[unit].b_actf;
293 	register struct scsi_fmt_cdb *cmd;
294 	long nblks;
295 
296 	cmd = bp->b_flags & B_READ ? &st_read_cmd : &st_write_cmd;
297 	cmd->cdb[1] = 1;		/* unknown setup */
298 
299 	if (bp->b_flags & B_READ)
300 		sc->sc_flags &= ~STF_WRTTN;
301 	else
302 		sc->sc_flags |= STF_WRTTN;
303 
304 	nblks = bp->b_bcount >> DEV_BSHIFT;
305 
306 	if (bp->b_bcount % DEV_BSIZE) {
307 		tprintf(sc->sc_ctty,
308 			"st%d:[stustart] I/O not block aligned %d/%ld\n",
309 			unit, DEV_BSIZE, bp->b_bcount);
310 
311 		bp->b_flags |= B_ERROR;
312 		bp->b_error = EIO;
313 
314 		sttab[unit].b_errcnt = 0;
315 		if (dp = bp->b_actf)
316 			dp->b_actb = bp->b_actb;
317 		else
318 			sttab[unit].b_actb = bp->b_actb;
319 		*bp->b_actb = dp;
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 *dp, *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 		sc_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 	if (dp = bp->b_actf)
484 		dp->b_actb = bp->b_actb;
485 	else
486 		sttab[unit].b_actb = bp->b_actb;
487 	*bp->b_actb = dp;
488 	bp->b_resid = 0;
489 
490 	biodone(bp);
491 
492 	scfree(&sc->sc_dq);
493 
494 	if (sttab[unit].b_actf) {
495 		stustart(unit);
496 	} else {
497 		sttab[unit].b_active = 0;
498 	}
499 }
500 
501 
502 /*
503  * RAW Device Routines
504  */
505 
506 
507 stread(dev, uio)
508 	dev_t dev;
509 	struct uio *uio;
510 {
511 	int unit = stunit(dev);
512 
513 	return(physio(ststrategy, &stbuf[unit], dev, B_READ, minphys, uio));
514 }
515 
516 stwrite(dev, uio)
517 	dev_t dev;
518 	struct uio *uio;
519 {
520 	int unit = stunit(dev);
521 
522 	return(physio(ststrategy, &stbuf[unit], dev, B_WRITE, minphys, uio));
523 }
524 
525 int
526 stioctl(dev, cmd, data, flag, p)
527 	dev_t dev;
528 	int cmd;
529 	caddr_t data;
530 	int flag;
531 	struct proc *p;
532 {
533 	return(ENXIO);
534 }
535 
536 struct scsi_fmt_cdb st_cmd;
537 
538 st_rewind(dev)
539 	dev_t dev;
540 {
541 	register int unit = stunit(dev);
542 	register struct st_softc *sc = &st_softc[unit];
543 	register struct scsi_fmt_cdb *cdb = &st_cmd;
544 	register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff;
545 	int ctlr, slave, stat;
546 	int retry = 9;
547 
548 	ctlr  = sc->sc_hd->hp_ctlr;
549 	slave = sc->sc_hd->hp_slave;
550 
551 	cdb->len = 6;
552 
553 	cdb->cdb[0] = CMD_REWIND;
554 
555 	cdb->cdb[1] = 1;	/* command finished soon */
556 
557 	cdb->cdb[2] = 0;
558 	cdb->cdb[3] = 0;
559 	cdb->cdb[4] = 0;
560 
561 	cdb->cdb[5] = 0;		/* unknown setup */
562 
563  rewind:
564 	stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0);
565 
566 	if (stat == 0) {
567 		return(1);
568 	} else {
569 		tprintf(sc->sc_ctty, "st%d:[st_rewind]   rewind error\n", unit);
570 		sc_request_sense(ctlr, slave, 0, sp, 8);
571 		tprintf(sc->sc_ctty,
572 			"st%d:[st_rewind]   status = 0x%x, sens key = 0x%x\n",
573 			unit, stat, sp->key);
574 
575 		if (retry > 0) {
576 			DELAY(1000000);
577 			retry--;
578 			goto rewind;
579 		}
580 
581 		return(0);
582 	}
583 }
584 
585 st_write_EOF(dev)
586 	dev_t dev;
587 {
588 	register int unit = stunit(dev);
589 	register struct st_softc *sc = &st_softc[unit];
590 	register struct scsi_fmt_cdb *cdb = &st_cmd;
591 	int ctlr, slave, stat;
592 	int marks = 1;
593 
594 	ctlr  = sc->sc_hd->hp_ctlr;
595 	slave = sc->sc_hd->hp_slave;
596 
597 	cdb->len = 6;
598 
599 	cdb->cdb[0] = CMD_WRITE_FILEMARK;
600 
601 	cdb->cdb[1] = 0;
602 
603 	cdb->cdb[2] = 0;
604 	cdb->cdb[3] = 0;
605 	cdb->cdb[4] = marks;
606 
607 	cdb->cdb[5] = 0;		/* unknown setup */
608 
609 	stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0);
610 
611 	if (stat == 0)
612 		return(1);
613 
614 	tprintf(sc->sc_ctty, "st%d:[st_write_EOF]   write EOF error\n", unit);
615 
616 	return(0);
617 }
618 
619 /*
620  * Dump
621  */
622 
623 int
624 stdump(dev)
625 	dev_t dev;
626 {
627 }
628 #endif
629