xref: /csrg-svn/sys/vax/stand/idc.c (revision 9186)
1*9186Ssam /*	idc.c	4.3	82/11/13	*/
26969Ssam 
36969Ssam /*
46969Ssam  * IDC (RB730)
56969Ssam  *
66969Ssam  * This driver is full of kludges!
76969Ssam  * It depends heavily on the 1K file system.
86969Ssam  */
96969Ssam 
106969Ssam #include "../h/param.h"
116969Ssam #include "../h/inode.h"
126969Ssam #include "../h/pte.h"
137445Sroot #include "../h/fs.h"
14*9186Ssam 
15*9186Ssam #include "../vaxuba/idcreg.h"
16*9186Ssam #include "../vaxuba/ubareg.h"
17*9186Ssam 
186969Ssam #include "saio.h"
196969Ssam #include "savax.h"
206969Ssam 
216969Ssam u_short	idcstd[] = { 0175606 };
226969Ssam short	rb02_off[] = { 0, 400, 0, -1, -1, -1, -1, -1 };
236969Ssam short	rb80_off[] = { 0, 37, 0, -1, -1, -1, 115, 305 };
246969Ssam 
256969Ssam int idc_type[4];
266969Ssam 
276969Ssam idcopen(io)
286969Ssam 	register struct iob *io;
296969Ssam {
306969Ssam 	register struct idcdevice *idcaddr;
316969Ssam 	register int i;
326969Ssam 
336969Ssam 	idcaddr = (struct idcdevice *)((caddr_t)ubauba(io->i_unit) + 0x200);
346969Ssam 	if (io->i_boff < 0 || io->i_boff > 7)
356969Ssam 		_stop("idc bad unit");
366969Ssam 	idcaddr->idcmpr = IDCGS_GETSTAT;
376969Ssam 	idcaddr->idccsr = IDC_GETSTAT|(io->i_unit<<8);
386969Ssam 	idcwait(idcaddr);
396969Ssam 	i = idcaddr->idcmpr;
406969Ssam 	idcaddr->idccsr = IDC_CRDY|(1<<(io->i_unit+16));
416969Ssam 	idcwait(idcaddr);
426969Ssam 	idcaddr->idccsr = (io->i_unit<<8)|IDC_RHDR;
436969Ssam 	idcwait(idcaddr);
446969Ssam 	if (idcaddr->idccsr & IDC_ERR) {
456969Ssam 		printf("idc error: idccsr %x\n", idcaddr->idccsr);
466969Ssam 		_stop("idc fatal error");
476969Ssam 	}
486969Ssam 	i = idcaddr->idcmpr;
496969Ssam 	i = idcaddr->idcmpr;
506969Ssam 	if (idcaddr->idccsr & IDC_R80) {
516969Ssam 		idc_type[io->i_unit] = 1;
526969Ssam 		io->i_boff = rb80_off[io->i_boff];
536969Ssam 	} else {
546969Ssam 		idc_type[io->i_unit] = 0;
556969Ssam 		io->i_boff = rb02_off[io->i_boff];
566969Ssam 	}
576969Ssam 	if (io->i_boff < 0)
586969Ssam 		_stop("idc bad unit");
596969Ssam }
606969Ssam 
616969Ssam idcstrategy(io, func)
626969Ssam 	register struct iob *io;
636969Ssam {
646969Ssam 	register struct idcdevice *idcaddr;
656969Ssam 	int com;
666969Ssam 	daddr_t bn;
676969Ssam 	short dn, cn, sn, tn;
686969Ssam 	int ubinfo, errcnt = 0;
696969Ssam 
706969Ssam 	idcaddr = (struct idcdevice *)((caddr_t)ubauba(io->i_unit) + 0x200);
716969Ssam retry:
726969Ssam 	ubinfo = ubasetup(io, 1);
736969Ssam 	bn = io->i_bn;
746969Ssam 	dn = io->i_unit;
756969Ssam 	if (io->i_cc != 1024) printf("idc: count %d != 1024\n", io->i_cc);
766969Ssam 	if (idc_type[dn]) {
776969Ssam 		cn = bn/(NRB80SECT*NRB80TRK);
786969Ssam 		sn = bn%NRB80SECT;
796969Ssam 		tn = (bn / NRB80SECT) % NRB80TRK;
806969Ssam 		if (sn == NRB80SECT)
816969Ssam 			io->i_cc = 512;
826969Ssam 	} else {
836969Ssam 		bn *= 2;
846969Ssam 		cn = bn/(NRB02SECT*NRB02TRK);
856969Ssam 		sn = bn%NRB02SECT;
866969Ssam 		tn = (bn / NRB02SECT) % NRB02TRK;
876969Ssam 	}
886969Ssam 	cn += io->i_boff;
896969Ssam 	idcaddr->idccsr = IDC_CRDY|IDC_SEEK|(dn<<8)|(1<<(dn+16));
906969Ssam 	idcaddr->idcdar = (cn<<16)|(tn<<8)|sn;
916969Ssam 	idcaddr->idccsr = IDC_SEEK|(dn<<8);
926969Ssam 	idcwait(idcaddr);
936969Ssam 	idcaddr->idccsr &= ~IDC_ATTN;
946969Ssam 	com = dn<<8;
956969Ssam 	if (func == READ)
966969Ssam 		com |= IDC_READ;
976969Ssam 	else
986969Ssam 		com |= IDC_WRITE;
996969Ssam 	idcaddr->idccsr = IDC_CRDY|com;
1006969Ssam 	idcaddr->idcbar = ubinfo&0x3ffff;
1016969Ssam 	idcaddr->idcbcr = -io->i_cc;
1026969Ssam 	idcaddr->idcdar = (cn<<16)|(tn<<8)|sn;
1036969Ssam 	idcaddr->idccsr = com;
1046969Ssam 	idcwait(idcaddr);
1056969Ssam 	ubafree(io, ubinfo);
1066969Ssam 	if (idcaddr->idccsr & IDC_ERR) {
1076969Ssam 		printf("idc error: (cyl,trk,sec)=(%d,%d,%d) csr=%b\n",
1086969Ssam 		    cn, tn, sn, idcaddr->idccsr, IDCCSR_BITS);
1096969Ssam 		if (errcnt == 10) {
1106969Ssam 			printf("idc: unrecovered error\n");
1116969Ssam 			return (-1);
1126969Ssam 		}
1136969Ssam 		errcnt++;
1146969Ssam 		goto retry;
1156969Ssam 	}
1166969Ssam 	if (errcnt)
1176969Ssam 		printf("idc: recovered by retry\n");
1186969Ssam 	if (idc_type[dn] && sn == NRB80SECT) {
1196969Ssam 		io->i_bn++;
1206969Ssam 		goto retry;
1216969Ssam 	}
1226969Ssam 	return (1024);
1236969Ssam }
1246969Ssam 
1256969Ssam idcwait(idcaddr)
1266969Ssam 	register struct idcdevice *idcaddr;
1276969Ssam {
1286969Ssam 	register int i;
1296969Ssam 
1306969Ssam 	while ((idcaddr->idccsr & (IDC_CRDY|IDC_DRDY)) != (IDC_CRDY|IDC_DRDY))
1316969Ssam 		for (i = 10; i; i--)
1326969Ssam 			;
1336969Ssam }
134