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