xref: /csrg-svn/sys/vax/stand/idc.c (revision 33408)
123228Smckusick /*
229301Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323228Smckusick  * All rights reserved.  The Berkeley software License Agreement
423228Smckusick  * specifies the terms and conditions for redistribution.
523228Smckusick  *
6*33408Skarels  *	@(#)idc.c	7.2 (Berkeley) 01/28/88
723228Smckusick  */
86969Ssam 
96969Ssam /*
106969Ssam  * IDC (RB730)
116969Ssam  */
129804Ssam #include "../machine/pte.h"
136969Ssam 
14*33408Skarels #include "param.h"
15*33408Skarels #include "inode.h"
16*33408Skarels #include "fs.h"
179186Ssam 
189186Ssam #include "../vaxuba/idcreg.h"
199186Ssam #include "../vaxuba/ubareg.h"
209186Ssam 
216969Ssam #include "saio.h"
226969Ssam #include "savax.h"
236969Ssam 
246969Ssam u_short	idcstd[] = { 0175606 };
256969Ssam short	rb02_off[] = { 0, 400, 0, -1, -1, -1, -1, -1 };
266969Ssam short	rb80_off[] = { 0, 37, 0, -1, -1, -1, 115, 305 };
276969Ssam 
286969Ssam int idc_type[4];
296969Ssam 
306969Ssam idcopen(io)
316969Ssam 	register struct iob *io;
326969Ssam {
336969Ssam 	register struct idcdevice *idcaddr;
346969Ssam 	register int i;
356969Ssam 
366969Ssam 	idcaddr = (struct idcdevice *)((caddr_t)ubauba(io->i_unit) + 0x200);
37*33408Skarels 	if ((unsigned)io->i_boff > 7) {
38*33408Skarels 		printf("idc bad unit");
39*33408Skarels 		return (EUNIT);
40*33408Skarels 	}
416969Ssam 	idcaddr->idcmpr = IDCGS_GETSTAT;
426969Ssam 	idcaddr->idccsr = IDC_GETSTAT|(io->i_unit<<8);
436969Ssam 	idcwait(idcaddr);
446969Ssam 	i = idcaddr->idcmpr;
456969Ssam 	idcaddr->idccsr = IDC_CRDY|(1<<(io->i_unit+16));
466969Ssam 	idcwait(idcaddr);
476969Ssam 	idcaddr->idccsr = (io->i_unit<<8)|IDC_RHDR;
486969Ssam 	idcwait(idcaddr);
496969Ssam 	if (idcaddr->idccsr & IDC_ERR) {
506969Ssam 		printf("idc error: idccsr %x\n", idcaddr->idccsr);
51*33408Skarels 		return (EIO);
526969Ssam 	}
536969Ssam 	i = idcaddr->idcmpr;
546969Ssam 	i = idcaddr->idcmpr;
556969Ssam 	if (idcaddr->idccsr & IDC_R80) {
566969Ssam 		idc_type[io->i_unit] = 1;
5715712Skarels 		io->i_boff = rb80_off[io->i_boff] * NRB80SECT * NRB80TRK;
586969Ssam 	} else {
596969Ssam 		idc_type[io->i_unit] = 0;
6015712Skarels 		io->i_boff = rb02_off[io->i_boff] * NRB02SECT/2 * NRB02TRK;
616969Ssam 	}
62*33408Skarels 	if (io->i_boff < 0) {
63*33408Skarels 		printf("idc%d: bad unit type", io->i_unit);
64*33408Skarels 		return (EUNIT);
65*33408Skarels 	}
66*33408Skarels 	return (0);
676969Ssam }
686969Ssam 
696969Ssam idcstrategy(io, func)
706969Ssam 	register struct iob *io;
716969Ssam {
726969Ssam 	register struct idcdevice *idcaddr;
736969Ssam 	int com;
746969Ssam 	daddr_t bn;
756969Ssam 	short dn, cn, sn, tn;
769305Sfeldman 	short ccleft, thiscc = 0;
776969Ssam 	int ubinfo, errcnt = 0;
786969Ssam 
796969Ssam 	idcaddr = (struct idcdevice *)((caddr_t)ubauba(io->i_unit) + 0x200);
806969Ssam 	ubinfo = ubasetup(io, 1);
816969Ssam 	bn = io->i_bn;
829305Sfeldman 	ccleft = io->i_cc;
839305Sfeldman retry:
846969Ssam 	dn = io->i_unit;
856969Ssam 	if (idc_type[dn]) {
866969Ssam 		cn = bn/(NRB80SECT*NRB80TRK);
876969Ssam 		sn = bn%NRB80SECT;
886969Ssam 		tn = (bn / NRB80SECT) % NRB80TRK;
899305Sfeldman 		thiscc = (NRB80SECT - sn) * 512;
906969Ssam 	} else {
919305Sfeldman 		cn = 2*bn/(NRB02SECT*NRB02TRK);
929305Sfeldman 		sn = (2*bn)%NRB02SECT;
939305Sfeldman 		tn = (2*bn / NRB02SECT) % NRB02TRK;
949305Sfeldman 		thiscc = (NRB02SECT - sn) * 256;
956969Ssam 	}
969305Sfeldman 	thiscc = MIN(thiscc, ccleft);
979305Sfeldman 	ccleft -= thiscc;
986969Ssam 	idcaddr->idccsr = IDC_CRDY|IDC_SEEK|(dn<<8)|(1<<(dn+16));
996969Ssam 	idcaddr->idcdar = (cn<<16)|(tn<<8)|sn;
1006969Ssam 	idcaddr->idccsr = IDC_SEEK|(dn<<8);
1016969Ssam 	idcwait(idcaddr);
1026969Ssam 	idcaddr->idccsr &= ~IDC_ATTN;
1036969Ssam 	com = dn<<8;
1046969Ssam 	if (func == READ)
1056969Ssam 		com |= IDC_READ;
1066969Ssam 	else
1076969Ssam 		com |= IDC_WRITE;
1086969Ssam 	idcaddr->idccsr = IDC_CRDY|com;
1096969Ssam 	idcaddr->idcbar = ubinfo&0x3ffff;
1109305Sfeldman 	idcaddr->idcbcr = -thiscc;
1116969Ssam 	idcaddr->idcdar = (cn<<16)|(tn<<8)|sn;
1126969Ssam 	idcaddr->idccsr = com;
1136969Ssam 	idcwait(idcaddr);
1146969Ssam 	if (idcaddr->idccsr & IDC_ERR) {
11515712Skarels 		printf("idc%d error: (cyl,trk,sec)=(%d,%d,%d) csr=%b\n",
11615712Skarels 		    dn, cn, tn, sn, idcaddr->idccsr, IDCCSR_BITS);
1176969Ssam 		if (errcnt == 10) {
1186969Ssam 			printf("idc: unrecovered error\n");
1199305Sfeldman 			ubafree(io, ubinfo);
1206969Ssam 			return (-1);
1216969Ssam 		}
1226969Ssam 		errcnt++;
1236969Ssam 		goto retry;
1246969Ssam 	}
1256969Ssam 	if (errcnt)
1266969Ssam 		printf("idc: recovered by retry\n");
1279305Sfeldman 	if (ccleft) {
12812150Sedward 		bn += thiscc/NBPG;
1299305Sfeldman 		ubinfo += thiscc;
1306969Ssam 		goto retry;
1316969Ssam 	}
1329305Sfeldman 	ubafree(io, ubinfo);
1339305Sfeldman 	return (io->i_cc);
1346969Ssam }
1356969Ssam 
1366969Ssam idcwait(idcaddr)
1376969Ssam 	register struct idcdevice *idcaddr;
1386969Ssam {
1396969Ssam 	register int i;
1406969Ssam 
1416969Ssam 	while ((idcaddr->idccsr & (IDC_CRDY|IDC_DRDY)) != (IDC_CRDY|IDC_DRDY))
1426969Ssam 		for (i = 10; i; i--)
1436969Ssam 			;
1446969Ssam }
14510024Ssam 
14610024Ssam /*ARGSUSED*/
14710024Ssam idcioctl(io, cmd, arg)
14810024Ssam 	struct iob *io;
14910024Ssam 	int cmd;
15010024Ssam 	caddr_t arg;
15110024Ssam {
15210024Ssam 
15310024Ssam 	return (ECMD);
15410024Ssam }
155