xref: /original-bsd/sys/luna68k/dev/st.c (revision 29d8ef23)
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.3 (Berkeley) 09/01/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 "device.h"
34 #include "scsireg.h"
35 #include "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 	/* drive ready ? */
201 	while ((stat = scsi_test_unit_rdy(ctlr, slave, 0)) != 0) {
202 		scsi_request_sense(ctlr, slave, 0, sp, 8);
203 
204 		if (stat != STS_CHECKCOND) {
205 			printf("st%d: stopen: %s\n", scsi_status(stat));
206 			return(EIO);
207 		}
208 
209 		if (retry-- < 0) {
210 			printf("st%d: stopen: %s\n", sense_key(sp->key));
211 			return(EIO);
212 		}
213 
214 		DELAY(1000000);
215 	}
216 
217 	sc->sc_ctty = tprintf_open(p);
218 
219 	sc->sc_flags |= STF_OPEN;
220 	if (flag & FWRITE)
221 		sc->sc_flags |= STF_WMODE;
222 	sc->sc_flags &= ~STF_MOVED;
223 
224 	return(0);
225 }
226 
227 /*ARGSUSED*/
228 stclose(dev)
229 	dev_t dev;
230 {
231 	register int unit = stunit(dev);
232 	register struct st_softc *sc = &st_softc[unit];
233 	register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff;
234 	int ctlr  = sc->sc_hd->hp_ctlr;
235 	int slave = sc->sc_hd->hp_slave;
236 	int stat, retry = 9;
237 
238 	if ((sc->sc_flags & (STF_WMODE|STF_WRTTN)) == (STF_WMODE|STF_WRTTN)) {
239 		st_write_EOF(dev);
240 	}
241 
242 	if ((minor(dev) & STDEV_NOREWIND) == 0) {
243 		st_rewind(dev);
244 	}
245 
246 	sc->sc_flags &= ~(STF_OPEN|STF_WMODE|STF_WRTTN);
247 
248 	tprintf_close(sc->sc_ctty);
249 
250 	return(0);
251 }
252 
253 /*
254  * Strategy
255  */
256 
257 int
258 ststrategy(bp)
259 	register struct buf *bp;
260 {
261 	register int unit = stunit(bp->b_dev);
262 	register struct buf *dp = &sttab[unit];
263 	int s;
264 
265 	bp->av_forw = NULL;
266 
267 	s = splbio();
268 
269 	if (dp->b_actf == NULL)
270 		dp->b_actf = bp;
271 	else
272 		dp->b_actl->av_forw = bp;
273 
274 	dp->b_actl = bp;
275 
276 	if (dp->b_active == 0) {
277 		dp->b_active = 1;
278 		stustart(unit);
279 	}
280 
281 	splx(s);
282 }
283 
284 int
285 stustart(unit)
286 	register int unit;
287 {
288 	register struct st_softc *sc = &st_softc[unit];
289 	register struct hp_device *hp = sc->sc_hd;
290 	register struct scsi_queue *dq = &sc->sc_dq;
291 	register struct buf *bp = sttab[unit].b_actf;
292 	register struct scsi_fmt_cdb *cmd;
293 	long nblks;
294 
295 	cmd = bp->b_flags & B_READ ? &st_read_cmd : &st_write_cmd;
296 	cmd->cdb[1] = 1;		/* unknown setup */
297 
298 	if (bp->b_flags & B_READ)
299 		sc->sc_flags &= ~STF_WRTTN;
300 	else
301 		sc->sc_flags |= STF_WRTTN;
302 
303 	nblks = bp->b_bcount >> DEV_BSHIFT;
304 
305 	if (bp->b_bcount % DEV_BSIZE) {
306 		tprintf(sc->sc_ctty,
307 			"st%d: I/O not block aligned %d/%ld\n",
308 			unit, DEV_BSIZE, bp->b_bcount);
309 
310 		bp->b_flags |= B_ERROR;
311 		bp->b_error = EIO;
312 
313 		sttab[unit].b_errcnt = 0;
314 		sttab[unit].b_actf = bp->b_actf;
315 
316 		bp->b_resid = 0;
317 
318 		biodone(bp);
319 
320 		if (sttab[unit].b_actf) {
321 			stustart(unit);
322 		} else {
323 			sttab[unit].b_active = 0;
324 		}
325 	}
326 
327 	*(u_char *)(&cmd->cdb[2]) = (u_char) (nblks >> 16);
328 	*(u_char *)(&cmd->cdb[3]) = (u_char) (nblks >>  8);
329 	*(u_char *)(&cmd->cdb[4]) = (u_char)  nblks;
330 
331 	cmd->cdb[5] = 0;		/* unknown setup */
332 
333 	sc->sc_flags |= STF_MOVED;
334 
335 	dq->dq_cdb = cmd;
336 	dq->dq_bp  = bp;
337 	dq->dq_flags = 0;		/* No Disconnect */
338 
339 	if (screq(dq))
340 		ststart(unit);
341 }
342 
343 int
344 ststart(unit)
345 	register int unit;
346 {
347 	register struct st_softc *sc = &st_softc[unit];
348 	register struct hp_device *hp = sc->sc_hd;
349 
350 	scstart(hp->hp_ctlr);
351 }
352 
353 /*
354  * Interrupt
355  */
356 
357 char *
358 sense_key(key)
359 	int key;
360 {
361 	if (key == 0)
362 		return("No Sense");
363 	else if (key == 2)
364 		return("Not Ready");
365 	else if (key == 3)
366 		return("Medium Error");
367 	else if (key == 4)
368 		return("Hardware Error");
369 	else if (key == 5)
370 		return("Illegal Request");
371 	else if (key == 6)
372 		return("Unit Attention");
373 	else if (key == 7)
374 		return("Data Protect");
375 	else if (key == 8)
376 		return("No Data");
377 	else if (key == 11)
378 		return("Aborted Command");
379 	else if (key == 13)
380 		return("Volume Overflow");
381 	else
382 		return("Unknown Error");
383 }
384 
385 int
386 stintr(unit, stat)
387 	register int unit;
388 	int stat;
389 {
390 	register struct st_softc *sc = &st_softc[unit];
391 	register struct scsi_xsense *xp = (struct scsi_xsense *) xsense_buff;
392 	register struct scsi_queue *dq = &sc->sc_dq;
393 	register struct buf *bp = dq->dq_bp;
394 	int ctlr  = dq->dq_ctlr;
395 	int slave = dq->dq_slave;
396 
397 	if (bp->b_flags & B_READ) {
398 		st_iostat[unit].imin = min(dq->dq_imin, st_iostat[unit].imin);
399 		if (dq->dq_imax > st_iostat[unit].imax) {
400 			st_iostat[unit].imax = dq->dq_imax;
401 #ifdef ST_IOSTAT
402 			printf("stintr: st%d  INPUT	MAX = %d, MIN = %d\n",
403 			       unit, st_iostat[unit].imax, st_iostat[unit].imin);
404 #endif
405 		}
406 	} else {
407 		st_iostat[unit].omin = min(dq->dq_omin, st_iostat[unit].omin);
408 		if (dq->dq_omax > st_iostat[unit].omax) {
409 			st_iostat[unit].omax = dq->dq_omax;
410 #ifdef ST_IOSTAT
411 			printf("stintr: st%d  OUTPUT	MAX = %d, MIN = %d\n",
412 			       unit, st_iostat[unit].omax, st_iostat[unit].omin);
413 #endif
414 		}
415 	}
416 	if (stat < 0) {
417 		bp->b_flags |= B_ERROR;
418 		bp->b_error = EIO;
419 		goto done;
420 	}
421 
422 	switch (stat) {
423 	/* scsi command completed ok */
424 	case 0:
425 		bp->b_resid = 0;
426 		break;
427 
428 	/* more status */
429 	case STS_CHECKCOND:
430 		scsi_request_sense(ctlr, slave, 0, xp, 8);
431 #ifdef DEBUG
432 		printf("stintr: xsense_buff[0] = 0x%s\n", hexstr(xsense_buff[0], 2));
433 		printf("stintr: xsense_buff[2] = 0x%s\n", hexstr(xsense_buff[2], 2));
434 		printf("stintr: Sense Key = [%s]\n", sense_key(xp->key));
435 #endif
436 		if (xp->valid) {
437 			bp->b_resid = (u_long)((xp->info1 << 24) |
438 					       (xp->info2 << 16) |
439 					       (xp->info3 << 8) |
440 					       (xp->info4));
441 			bp->b_resid <<= DEV_BSHIFT;
442 		}
443 
444 		if (xp->filemark) {		/* End of File */
445 			tprintf(sc->sc_ctty, "st%d: End of File\n", unit);
446 			bp->b_flags |= B_ERROR;
447 			bp->b_error = EIO;
448 			break;
449 		}
450 
451 		if (xp->key) {
452 			tprintf(sc->sc_ctty, "st%d: %s\n", unit, sense_key(xp->key));
453 			bp->b_flags |= B_ERROR;
454 			bp->b_error = EIO;
455 			break;
456 		}
457 
458 		if (xp->eom) {		/* End of TAPE */
459 			tprintf(sc->sc_ctty, "st%d: End of Tape\n", unit);
460 			bp->b_flags |= B_ERROR;
461 			bp->b_error = ENOSPC;
462 			break;
463 		}
464 
465 		tprintf(sc->sc_ctty, "st%d: unknown scsi error\n", unit);
466 		bp->b_flags |= B_ERROR;
467 		bp->b_error = EIO;
468 		break;
469 
470 	default:
471 		printf("st%d: stintr unknown stat 0x%x\n", unit, stat);
472 		break;
473 	}
474 
475 done:
476 	sttab[unit].b_errcnt = 0;
477 	sttab[unit].b_actf = bp->b_actf;
478 
479 	bp->b_resid = 0;
480 
481 	biodone(bp);
482 
483 	scfree(&sc->sc_dq);
484 
485 	if (sttab[unit].b_actf) {
486 		stustart(unit);
487 	} else {
488 		sttab[unit].b_active = 0;
489 	}
490 }
491 
492 
493 /*
494  * RAW Device Routines
495  */
496 
497 
498 stread(dev, uio)
499 	dev_t dev;
500 	struct uio *uio;
501 {
502 	int unit = stunit(dev);
503 
504 	return(physio(ststrategy, &stbuf[unit], dev, B_READ, minphys, uio));
505 }
506 
507 stwrite(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_WRITE, minphys, uio));
514 }
515 
516 int
517 stioctl(dev, cmd, data, flag, p)
518 	dev_t dev;
519 	int cmd;
520 	caddr_t data;
521 	int flag;
522 	struct proc *p;
523 {
524 	return(ENXIO);
525 }
526 
527 struct scsi_fmt_cdb st_cmd;
528 
529 st_rewind(dev)
530 	dev_t dev;
531 {
532 	register int unit = stunit(dev);
533 	register struct st_softc *sc = &st_softc[unit];
534 	register struct scsi_fmt_cdb *cdb = &st_cmd;
535 	register struct scsi_xsense *sp = (struct scsi_xsense *) xsense_buff;
536 	int ctlr, slave, stat;
537 	int retry = 9;
538 
539 	ctlr  = sc->sc_hd->hp_ctlr;
540 	slave = sc->sc_hd->hp_slave;
541 
542 	cdb->len = 6;
543 
544 	cdb->cdb[0] = CMD_REWIND;
545 
546 	cdb->cdb[1] = 1;	/* command finished soon */
547 
548 	cdb->cdb[2] = 0;
549 	cdb->cdb[3] = 0;
550 	cdb->cdb[4] = 0;
551 
552 	cdb->cdb[5] = 0;		/* unknown setup */
553 
554  rewind:
555 	stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0);
556 
557 	if (stat == 0) {
558 		return(1);
559 	} else {
560 		printf("st: rewind error\n");
561 		scsi_request_sense(ctlr, slave, 0, sp, 8);
562 		printf("st: status = 0x%x, sens key = 0x%x\n", stat, sp->key);
563 
564 		if (retry > 0) {
565 			DELAY(1000000);
566 			retry--;
567 			goto rewind;
568 		}
569 
570 		return(0);
571 	}
572 }
573 
574 st_write_EOF(dev)
575 	dev_t dev;
576 {
577 	register int unit = stunit(dev);
578 	register struct st_softc *sc = &st_softc[unit];
579 	register struct scsi_fmt_cdb *cdb = &st_cmd;
580 	int ctlr, slave, stat;
581 	int marks = 1;
582 
583 	ctlr  = sc->sc_hd->hp_ctlr;
584 	slave = sc->sc_hd->hp_slave;
585 
586 	cdb->len = 6;
587 
588 	cdb->cdb[0] = CMD_WRITE_FILEMARK;
589 
590 	cdb->cdb[1] = 0;
591 
592 	cdb->cdb[2] = 0;
593 	cdb->cdb[3] = 0;
594 	cdb->cdb[4] = marks;
595 
596 	cdb->cdb[5] = 0;		/* unknown setup */
597 
598 	stat = scsi_immed_command(ctlr, slave, 0, cdb, (char *) 0, 0);
599 
600 	if (stat == 0)
601 		return(1);
602 
603 	printf("st: write EOF error\n");
604 
605 	return(0);
606 }
607 
608 /*
609  * Dump
610  */
611 
612 int
613 stdump(dev)
614 	dev_t dev;
615 {
616 }
617 #endif
618