123228Smckusick /* 2*35052Skarels * 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*35052Skarels * @(#)idc.c 7.4 (Berkeley) 07/09/88 723228Smckusick */ 86969Ssam 96969Ssam /* 106969Ssam * IDC (RB730) 116969Ssam */ 126969Ssam 1333408Skarels #include "param.h" 1433408Skarels #include "inode.h" 1533408Skarels #include "fs.h" 169186Ssam 17*35052Skarels #include "../vax/pte.h" 189186Ssam #include "../vaxuba/idcreg.h" 199186Ssam #include "../vaxuba/ubareg.h" 209186Ssam 216969Ssam #include "saio.h" 226969Ssam #include "savax.h" 236969Ssam 246969Ssam short rb02_off[] = { 0, 400, 0, -1, -1, -1, -1, -1 }; 256969Ssam short rb80_off[] = { 0, 37, 0, -1, -1, -1, 115, 305 }; 266969Ssam 2733527Sbostic #define MAXCTLR 1 2833527Sbostic #define MAXUNIT 4 2933527Sbostic #define MAXPART 8 306969Ssam 3133527Sbostic int idc_type[MAXUNIT]; 3233527Sbostic 336969Ssam idcopen(io) 346969Ssam register struct iob *io; 356969Ssam { 366969Ssam register struct idcdevice *idcaddr; 376969Ssam register int i; 386969Ssam 39*35052Skarels if (io->i_adapt != 0) 4033527Sbostic return (EADAPT); 4133527Sbostic if ((u_int)io->i_ctlr >= MAXCTLR) 4233527Sbostic return (ECTLR); 4333527Sbostic if ((u_int)io->i_unit >= MAXUNIT) 4433408Skarels return (EUNIT); 4533527Sbostic if ((u_int)io->i_part >= MAXPART) 4633527Sbostic return (EPART); 4733527Sbostic idcaddr = (struct idcdevice *)((caddr_t)ubauba(io->i_adapt) + 0x200); 486969Ssam idcaddr->idcmpr = IDCGS_GETSTAT; 496969Ssam idcaddr->idccsr = IDC_GETSTAT|(io->i_unit<<8); 506969Ssam idcwait(idcaddr); 516969Ssam i = idcaddr->idcmpr; 526969Ssam idcaddr->idccsr = IDC_CRDY|(1<<(io->i_unit+16)); 536969Ssam idcwait(idcaddr); 546969Ssam idcaddr->idccsr = (io->i_unit<<8)|IDC_RHDR; 556969Ssam idcwait(idcaddr); 566969Ssam if (idcaddr->idccsr & IDC_ERR) { 576969Ssam printf("idc error: idccsr %x\n", idcaddr->idccsr); 5833408Skarels return (EIO); 596969Ssam } 606969Ssam i = idcaddr->idcmpr; 616969Ssam i = idcaddr->idcmpr; 626969Ssam if (idcaddr->idccsr & IDC_R80) { 636969Ssam idc_type[io->i_unit] = 1; 6433527Sbostic io->i_boff = rb80_off[io->i_part] * NRB80SECT * NRB80TRK; 656969Ssam } else { 666969Ssam idc_type[io->i_unit] = 0; 6733527Sbostic io->i_boff = rb02_off[io->i_part] * NRB02SECT/2 * NRB02TRK; 686969Ssam } 6933408Skarels return (0); 706969Ssam } 716969Ssam 726969Ssam idcstrategy(io, func) 736969Ssam register struct iob *io; 746969Ssam { 756969Ssam register struct idcdevice *idcaddr; 766969Ssam int com; 776969Ssam daddr_t bn; 786969Ssam short dn, cn, sn, tn; 799305Sfeldman short ccleft, thiscc = 0; 806969Ssam int ubinfo, errcnt = 0; 816969Ssam 8233527Sbostic idcaddr = (struct idcdevice *)((caddr_t)ubauba(io->i_adapt) + 0x200); 836969Ssam ubinfo = ubasetup(io, 1); 846969Ssam bn = io->i_bn; 859305Sfeldman ccleft = io->i_cc; 869305Sfeldman retry: 876969Ssam dn = io->i_unit; 886969Ssam if (idc_type[dn]) { 896969Ssam cn = bn/(NRB80SECT*NRB80TRK); 906969Ssam sn = bn%NRB80SECT; 916969Ssam tn = (bn / NRB80SECT) % NRB80TRK; 929305Sfeldman thiscc = (NRB80SECT - sn) * 512; 936969Ssam } else { 949305Sfeldman cn = 2*bn/(NRB02SECT*NRB02TRK); 959305Sfeldman sn = (2*bn)%NRB02SECT; 969305Sfeldman tn = (2*bn / NRB02SECT) % NRB02TRK; 979305Sfeldman thiscc = (NRB02SECT - sn) * 256; 986969Ssam } 999305Sfeldman thiscc = MIN(thiscc, ccleft); 1009305Sfeldman ccleft -= thiscc; 1016969Ssam idcaddr->idccsr = IDC_CRDY|IDC_SEEK|(dn<<8)|(1<<(dn+16)); 1026969Ssam idcaddr->idcdar = (cn<<16)|(tn<<8)|sn; 1036969Ssam idcaddr->idccsr = IDC_SEEK|(dn<<8); 1046969Ssam idcwait(idcaddr); 1056969Ssam idcaddr->idccsr &= ~IDC_ATTN; 1066969Ssam com = dn<<8; 1076969Ssam if (func == READ) 1086969Ssam com |= IDC_READ; 1096969Ssam else 1106969Ssam com |= IDC_WRITE; 1116969Ssam idcaddr->idccsr = IDC_CRDY|com; 1126969Ssam idcaddr->idcbar = ubinfo&0x3ffff; 1139305Sfeldman idcaddr->idcbcr = -thiscc; 1146969Ssam idcaddr->idcdar = (cn<<16)|(tn<<8)|sn; 1156969Ssam idcaddr->idccsr = com; 1166969Ssam idcwait(idcaddr); 1176969Ssam if (idcaddr->idccsr & IDC_ERR) { 11815712Skarels printf("idc%d error: (cyl,trk,sec)=(%d,%d,%d) csr=%b\n", 11915712Skarels dn, cn, tn, sn, idcaddr->idccsr, IDCCSR_BITS); 12033527Sbostic if (errcnt++ == 10) { 1216969Ssam printf("idc: unrecovered error\n"); 1229305Sfeldman ubafree(io, ubinfo); 1236969Ssam return (-1); 1246969Ssam } 1256969Ssam goto retry; 1266969Ssam } 1276969Ssam if (errcnt) 1286969Ssam printf("idc: recovered by retry\n"); 1299305Sfeldman if (ccleft) { 13012150Sedward bn += thiscc/NBPG; 1319305Sfeldman ubinfo += thiscc; 1326969Ssam goto retry; 1336969Ssam } 1349305Sfeldman ubafree(io, ubinfo); 1359305Sfeldman return (io->i_cc); 1366969Ssam } 1376969Ssam 13833527Sbostic static 1396969Ssam idcwait(idcaddr) 1406969Ssam register struct idcdevice *idcaddr; 1416969Ssam { 1426969Ssam while ((idcaddr->idccsr & (IDC_CRDY|IDC_DRDY)) != (IDC_CRDY|IDC_DRDY)) 14333527Sbostic DELAY(10); 1446969Ssam } 145