xref: /csrg-svn/sys/vax/stand/mt.c (revision 33408)
123235Smckusick /*
229304Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323235Smckusick  * All rights reserved.  The Berkeley software License Agreement
423235Smckusick  * specifies the terms and conditions for redistribution.
523235Smckusick  *
6*33408Skarels  *	@(#)mt.c	7.2 (Berkeley) 01/28/88
723235Smckusick  */
85151Ssam 
95151Ssam /*
105151Ssam  * TM78/TU78 tape driver
1110776Ssam  * Made to work reliably by by Jeffrey R. Schwab (Purdue)
125151Ssam  */
139806Ssam #include "../machine/pte.h"
145151Ssam 
15*33408Skarels #include "param.h"
16*33408Skarels #include "inode.h"
17*33408Skarels #include "fs.h"
189186Ssam 
199186Ssam #include "../vaxmba/mtreg.h"
209186Ssam #include "../vaxmba/mbareg.h"
219186Ssam 
225151Ssam #include "saio.h"
235151Ssam #include "savax.h"
245151Ssam 
255151Ssam short	mttypes[] =
265151Ssam 	{ MBDT_TU78, 0 };
275151Ssam 
285151Ssam #define	MASKREG(reg)	((reg)&0xffff)
295151Ssam 
305151Ssam mtopen(io)
315151Ssam 	register struct iob *io;
325151Ssam {
335151Ssam 	register int skip;
3410776Ssam 	register struct mtdevice *mtaddr =
3510776Ssam 		(struct mtdevice *)mbadrv(io->i_unit);
36*33408Skarels 	register int i;
375151Ssam 
38*33408Skarels 	if (mbainit(UNITTOMBA(io->i_unit)) == 0)
39*33408Skarels 		return (ENXIO);
405151Ssam 	for (i = 0; mttypes[i]; i++)
415151Ssam 		if (mttypes[i] == (mtaddr->mtdt&MBDT_TYPE))
425151Ssam 			goto found;
43*33408Skarels 	printf("not a tape\n");
44*33408Skarels 	return (ENXIO);
455151Ssam found:
465151Ssam 	mtaddr->mtid = MTID_CLR;
475151Ssam 	DELAY(250);
485151Ssam 	while ((mtaddr->mtid & MTID_RDY) == 0)
495151Ssam 		;
5010776Ssam 
5110776Ssam 	/* clear any attention bits present on open */
5210776Ssam 	i = mtaddr->mtner;
5310776Ssam 	mtaddr->mtas = mtaddr->mtas;
5410776Ssam 
555151Ssam 	mtstrategy(io, MT_REW);
565151Ssam 	skip = io->i_boff;
575151Ssam 	while (skip--) {
585151Ssam 		io->i_cc = -1;
595151Ssam 		mtstrategy(io, MT_SFORWF);
605151Ssam 	}
61*33408Skarels 	return (0);
625151Ssam }
635151Ssam 
645151Ssam mtclose(io)
655151Ssam 	register struct iob *io;
665151Ssam {
675151Ssam 
685151Ssam 	mtstrategy(io, MT_REW);
695151Ssam }
705151Ssam 
715151Ssam mtstrategy(io, func)
725151Ssam 	register struct iob *io;
735151Ssam 	int func;
745151Ssam {
755151Ssam 	register int errcnt, s, ic;
765151Ssam 	register struct mtdevice *mtaddr =
775151Ssam 	    (struct mtdevice *)mbadrv(io->i_unit);
7810776Ssam 	struct mba_regs *mba = mbamba(io->i_unit);
795151Ssam 
805151Ssam 	errcnt = 0;
815151Ssam retry:
8210776Ssam 	/* code to trap for attention up prior to start of command */
8310776Ssam 	if ((mtaddr->mtas & 0xffff) != 0) {
8410776Ssam 		printf("mt unexpected attention er=%x - continuing\n",
8510776Ssam 			MASKREG(mtaddr->mtner));
8610776Ssam 		mtaddr->mtas = mtaddr->mtas;
8710776Ssam 	}
8810776Ssam 
895151Ssam 	if (func == READ || func == WRITE) {
905151Ssam 		mtaddr->mtca = 1<<2;	/* 1 record */
915151Ssam 		mtaddr->mtbc = io->i_cc;
925151Ssam 		mbastart(io, func);
9310776Ssam 		/* wait for mba to go idle and read result status */
9410776Ssam 		while((mba->mba_sr & MBSR_DTBUSY) != 0)
9510776Ssam 			;
9610776Ssam 		ic = mtaddr->mter & MTER_INTCODE;
975151Ssam 	} else {
985151Ssam 		mtaddr->mtncs[0] = (-io->i_cc << 8)|func|MT_GO;
995151Ssam 	rwait:
1005151Ssam 		do
1015151Ssam 			s = mtaddr->mtas&0xffff;
1025151Ssam 		while (s == 0);
10310776Ssam 		ic = mtaddr->mtner & MTER_INTCODE;
1045151Ssam 		mtaddr->mtas = mtaddr->mtas;	/* clear attention */
1055151Ssam 	}
1065151Ssam 	switch (ic) {
1075151Ssam 	case MTER_TM:
1085151Ssam 	case MTER_EOT:
1095151Ssam 	case MTER_LEOT:
1105151Ssam 		return (0);
1115151Ssam 
1125151Ssam 	case MTER_DONE:
11310776Ssam 		/* make sure a record was read */
11410776Ssam 		if ((mtaddr->mtca & (1 << 2)) != 0) {
11510776Ssam 			printf("mt record count not decremented - retrying\n");
11610776Ssam 			goto retry;
11710776Ssam 		}
1185151Ssam 		break;
1195151Ssam 
1205151Ssam 	case MTER_RWDING:
1215151Ssam 		goto rwait;
1225151Ssam 	default:
12310776Ssam 		printf("mt hard error: er=%x\n",
1245151Ssam 		    MASKREG(mtaddr->mter));
1255151Ssam 		mtaddr->mtid = MTID_CLR;
1265151Ssam 		DELAY(250);
1275151Ssam 		while ((mtaddr->mtid & MTID_RDY) == 0)
1285151Ssam 			;
1295151Ssam 		return (-1);
1305151Ssam 
1315151Ssam 	case MTER_RETRY:
13210776Ssam 		printf("mt error: er=%x\n", MASKREG(mtaddr->mter));
1335151Ssam 		if (errcnt == 10) {
1345151Ssam 			printf("mt: unrecovered error\n");
1355151Ssam 			return (-1);
1365151Ssam 		}
1375151Ssam 		errcnt++;
1385151Ssam 		goto retry;
1395151Ssam 	}
1405151Ssam 	if (errcnt)
1415151Ssam 		printf("mt: recovered by retry\n");
1425151Ssam 	return (io->i_cc);	/* NO PARTIAL RECORD READS!!! */
1435151Ssam }
144