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