123228Smckusick /*
235052Skarels * Copyright (c) 1982, 1986, 1988 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*49100Sbostic * @(#)idc.c 7.7 (Berkeley) 05/04/91
723228Smckusick */
86969Ssam
96969Ssam /*
106969Ssam * IDC (RB730)
116969Ssam */
126969Ssam
1345803Sbostic #include "sys/param.h"
149186Ssam
1545803Sbostic #include "../include/pte.h"
1645803Sbostic #include "../uba/idcreg.h"
1745803Sbostic #include "../uba/ubareg.h"
189186Ssam
1945803Sbostic #include "stand/saio.h"
206969Ssam #include "savax.h"
216969Ssam
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
2533527Sbostic #define MAXCTLR 1
2633527Sbostic #define MAXUNIT 4
2733527Sbostic #define MAXPART 8
286969Ssam
2933527Sbostic int idc_type[MAXUNIT];
3033527Sbostic
idcopen(io)316969Ssam idcopen(io)
326969Ssam register struct iob *io;
336969Ssam {
346969Ssam register struct idcdevice *idcaddr;
356969Ssam register int i;
366969Ssam
3735052Skarels if (io->i_adapt != 0)
3833527Sbostic return (EADAPT);
3933527Sbostic if ((u_int)io->i_ctlr >= MAXCTLR)
4033527Sbostic return (ECTLR);
4133527Sbostic if ((u_int)io->i_unit >= MAXUNIT)
4233408Skarels return (EUNIT);
4333527Sbostic if ((u_int)io->i_part >= MAXPART)
4433527Sbostic return (EPART);
4533527Sbostic idcaddr = (struct idcdevice *)((caddr_t)ubauba(io->i_adapt) + 0x200);
466969Ssam idcaddr->idcmpr = IDCGS_GETSTAT;
476969Ssam idcaddr->idccsr = IDC_GETSTAT|(io->i_unit<<8);
486969Ssam idcwait(idcaddr);
496969Ssam i = idcaddr->idcmpr;
506969Ssam idcaddr->idccsr = IDC_CRDY|(1<<(io->i_unit+16));
516969Ssam idcwait(idcaddr);
526969Ssam idcaddr->idccsr = (io->i_unit<<8)|IDC_RHDR;
536969Ssam idcwait(idcaddr);
546969Ssam if (idcaddr->idccsr & IDC_ERR) {
556969Ssam printf("idc error: idccsr %x\n", idcaddr->idccsr);
5633408Skarels return (EIO);
576969Ssam }
586969Ssam i = idcaddr->idcmpr;
596969Ssam i = idcaddr->idcmpr;
606969Ssam if (idcaddr->idccsr & IDC_R80) {
616969Ssam idc_type[io->i_unit] = 1;
6233527Sbostic io->i_boff = rb80_off[io->i_part] * NRB80SECT * NRB80TRK;
636969Ssam } else {
646969Ssam idc_type[io->i_unit] = 0;
6533527Sbostic io->i_boff = rb02_off[io->i_part] * NRB02SECT/2 * NRB02TRK;
666969Ssam }
6733408Skarels return (0);
686969Ssam }
696969Ssam
idcstrategy(io,func)706969Ssam idcstrategy(io, func)
716969Ssam register struct iob *io;
726969Ssam {
736969Ssam register struct idcdevice *idcaddr;
746969Ssam int com;
756969Ssam daddr_t bn;
766969Ssam short dn, cn, sn, tn;
779305Sfeldman short ccleft, thiscc = 0;
786969Ssam int ubinfo, errcnt = 0;
796969Ssam
8033527Sbostic idcaddr = (struct idcdevice *)((caddr_t)ubauba(io->i_adapt) + 0x200);
816969Ssam ubinfo = ubasetup(io, 1);
826969Ssam bn = io->i_bn;
839305Sfeldman ccleft = io->i_cc;
849305Sfeldman retry:
856969Ssam dn = io->i_unit;
866969Ssam if (idc_type[dn]) {
876969Ssam cn = bn/(NRB80SECT*NRB80TRK);
886969Ssam sn = bn%NRB80SECT;
896969Ssam tn = (bn / NRB80SECT) % NRB80TRK;
909305Sfeldman thiscc = (NRB80SECT - sn) * 512;
916969Ssam } else {
929305Sfeldman cn = 2*bn/(NRB02SECT*NRB02TRK);
939305Sfeldman sn = (2*bn)%NRB02SECT;
949305Sfeldman tn = (2*bn / NRB02SECT) % NRB02TRK;
959305Sfeldman thiscc = (NRB02SECT - sn) * 256;
966969Ssam }
979305Sfeldman thiscc = MIN(thiscc, ccleft);
989305Sfeldman ccleft -= thiscc;
996969Ssam idcaddr->idccsr = IDC_CRDY|IDC_SEEK|(dn<<8)|(1<<(dn+16));
1006969Ssam idcaddr->idcdar = (cn<<16)|(tn<<8)|sn;
1016969Ssam idcaddr->idccsr = IDC_SEEK|(dn<<8);
1026969Ssam idcwait(idcaddr);
1036969Ssam idcaddr->idccsr &= ~IDC_ATTN;
1046969Ssam com = dn<<8;
105*49100Sbostic if (func == F_READ)
1066969Ssam com |= IDC_READ;
1076969Ssam else
1086969Ssam com |= IDC_WRITE;
1096969Ssam idcaddr->idccsr = IDC_CRDY|com;
1106969Ssam idcaddr->idcbar = ubinfo&0x3ffff;
1119305Sfeldman idcaddr->idcbcr = -thiscc;
1126969Ssam idcaddr->idcdar = (cn<<16)|(tn<<8)|sn;
1136969Ssam idcaddr->idccsr = com;
1146969Ssam idcwait(idcaddr);
1156969Ssam if (idcaddr->idccsr & IDC_ERR) {
11615712Skarels printf("idc%d error: (cyl,trk,sec)=(%d,%d,%d) csr=%b\n",
11715712Skarels dn, cn, tn, sn, idcaddr->idccsr, IDCCSR_BITS);
11833527Sbostic if (errcnt++ == 10) {
1196969Ssam printf("idc: unrecovered error\n");
1209305Sfeldman ubafree(io, ubinfo);
1216969Ssam return (-1);
1226969Ssam }
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
13633527Sbostic static
idcwait(idcaddr)1376969Ssam idcwait(idcaddr)
1386969Ssam register struct idcdevice *idcaddr;
1396969Ssam {
1406969Ssam while ((idcaddr->idccsr & (IDC_CRDY|IDC_DRDY)) != (IDC_CRDY|IDC_DRDY))
14133527Sbostic DELAY(10);
1426969Ssam }
143