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*45803Sbostic * @(#)idc.c 7.6 (Berkeley) 12/16/90 723228Smckusick */ 86969Ssam 96969Ssam /* 106969Ssam * IDC (RB730) 116969Ssam */ 126969Ssam 13*45803Sbostic #include "sys/param.h" 149186Ssam 15*45803Sbostic #include "../include/pte.h" 16*45803Sbostic #include "../uba/idcreg.h" 17*45803Sbostic #include "../uba/ubareg.h" 189186Ssam 19*45803Sbostic #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 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 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; 1056969Ssam if (func == 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 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