1*11111Ssam /* rl.c 4.2 83/02/16 */ 210775Ssam 310775Ssam /* 410775Ssam * Standalone RL02 disk driver 510775Ssam */ 610775Ssam #include "../machine/pte.h" 710775Ssam 810775Ssam #include "../h/param.h" 910775Ssam #include "../h/inode.h" 1010775Ssam #include "../h/fs.h" 1110775Ssam 1210775Ssam #include "../vaxuba/rlreg.h" 1310775Ssam #include "../vaxuba/ubareg.h" 1410775Ssam 1510775Ssam #include "saio.h" 1610775Ssam #include "savax.h" 1710775Ssam 1810775Ssam u_short rlstd[] = { 0774400 }; 1910775Ssam short rl_off[] = { 0, 361, 0, -1, -1, -1, -1, -1 }; 2010775Ssam 2110775Ssam /* struct to keep state info about the controller */ 2210775Ssam struct rl_stat { 2310775Ssam short rl_dn; /* drive number */ 2410775Ssam short rl_cylnhd; /* cylinder and head */ 2510775Ssam u_short rl_bleft; /* bytes left to transfer */ 2610775Ssam u_short rl_bpart; /* bytes transferred */ 2710775Ssam } rl_stat[] = { -1, 0, 0, 0}; 2810775Ssam 2910775Ssam rlopen(io) 3010775Ssam register struct iob *io; 3110775Ssam { 3210775Ssam register struct rldevice *rladdr = 3310775Ssam (struct rldevice *)ubamem(io->i_unit, rlstd[0]); 3410775Ssam register struct rl_stat *st = &rl_stat[0]; 3510775Ssam register int ctr = 0; 3610775Ssam 3710775Ssam if (rl_off[io->i_boff] == -1 || 3810775Ssam io->i_boff < 0 || io->i_boff > 7) 3910775Ssam _stop("rl bad unit"); 4010775Ssam 4110775Ssam /* 4210775Ssam * DEC reports that: 4310775Ssam * For some unknown reason the RL02 (seems to be only drive 1) 4410775Ssam * does not return a valid drive status the first time that a 4510775Ssam * GET STATUS request is issued for the drive, in fact it can 4610775Ssam * take up to three or more GET STATUS requests to obtain the 4710775Ssam * correct status. 4810775Ssam * In order to overcome this, the driver has been modified to 4910775Ssam * issue a GET STATUS request and validate the drive status 5010775Ssam * returned. If a valid status is not returned after eight 5110775Ssam * attempts, then an error message is printed. 5210775Ssam */ 5310775Ssam do { 5410775Ssam rladdr->rlda.getstat = RL_RESET; 5510775Ssam rladdr->rlcs = (io->i_unit <<8) | RL_GETSTAT; /* Get status*/ 5610775Ssam rlwait(rladdr); 5710775Ssam } while( (rladdr->rlmp.getstat&RLMP_STATUS) != RLMP_STATOK && ++ctr<8 ); 5810775Ssam 5910775Ssam if ((rladdr->rlcs & RL_DE) || (ctr >= 8)) 6010775Ssam _stop("rl unit does not respond"); 6110775Ssam 6210775Ssam if ((rladdr->rlmp.getstat & RLMP_DT) == 0 ) /* NO RL01'S */ 6310775Ssam _stop("rl01 unit not supported"); 6410775Ssam 6510775Ssam /* Determine disk posistion */ 6610775Ssam rladdr->rlcs = (io->i_unit << 8) | RL_RHDR; 6710775Ssam rlwait(rladdr); 6810775Ssam 6910775Ssam /* save disk drive posistion */ 7010775Ssam st->rl_cylnhd = (rladdr->rlmp.readhdr & 0177700) >> 6; 7110775Ssam st->rl_dn = io->i_unit; 7210775Ssam 7310775Ssam /* byte offset for cylinder desired */ 7410775Ssam io->i_boff = rl_off[io->i_boff] * NRLBPSC * NRLTRKS * NRLSECT; 7510775Ssam } 7610775Ssam 7710775Ssam rlstrategy(io, func) 7810775Ssam register struct iob *io; 7910775Ssam { 8010775Ssam register struct rldevice *rladdr = 8110775Ssam (struct rldevice *)ubamem(io->i_unit, rlstd[0]); 8210775Ssam register struct rl_stat *st = &rl_stat[0]; 8310775Ssam int com; 8410775Ssam daddr_t bn; 8510775Ssam short cn, sn, head; 8610775Ssam int diff, ubinfo, ubaddr, errcnt = 0; 8710775Ssam 8810775Ssam retry: 8910775Ssam ubinfo = ubasetup(io, 1); 9010775Ssam bn = io->i_bn; /* block number */ 9110775Ssam cn = bn / 40; /* 40 512 byte blocks per cylinder */ 9210775Ssam sn = (bn % 20) << 1; 9310775Ssam head = (bn / 20) & 1; 9410775Ssam st->rl_bleft = io->i_cc; /* total number of bytes to trans */ 9510775Ssam ubaddr = ubinfo; 9610775Ssam 9710775Ssam stupid_rl: 9810775Ssam /* find out how many cylinders to seek */ 9910775Ssam diff = (st->rl_cylnhd >> 1) - cn; 10010775Ssam if ( diff == 0 && (st->rl_cylnhd & 1) == head ) 10110775Ssam goto noseek; 10210775Ssam 10310775Ssam /* first time or we switched drives */ 10410775Ssam st->rl_dn = io->i_unit; /* drive number */ 10510775Ssam 10610775Ssam if ( diff < 0 ) 10710775Ssam rladdr->rlda.seek = -diff<<7 | RLDA_HGH | head << 4; 10810775Ssam else 10910775Ssam rladdr->rlda.seek = diff<<7 | RLDA_LOW | head << 4; 11010775Ssam rladdr->rlcs = (st->rl_dn << 8) | RL_SEEK; 11110775Ssam 11210775Ssam /* reset position of drive */ 11310775Ssam st->rl_cylnhd = (cn << 1) | head; 11410775Ssam 11510775Ssam noseek: 11610775Ssam /* wait for controller and drive */ 11710775Ssam while( (rladdr->rlcs & RL_DCRDY) != RL_DCRDY) 11810775Ssam continue; 11910775Ssam 12010775Ssam /* calculate the max number of bytes we can trans */ 12110775Ssam st->rl_bpart = NRLSECT * NRLBPSC - (sn * NRLBPSC); 12210775Ssam if ( st->rl_bleft < st->rl_bpart ) 12310775Ssam st->rl_bpart = st->rl_bleft; 12410775Ssam 12510775Ssam rladdr->rlda.rw = (st->rl_cylnhd << 6) | sn; 12610775Ssam rladdr->rlmp.rw = -(st->rl_bpart >> 1); 12710775Ssam rladdr->rlba = ubaddr; 12810775Ssam 12910775Ssam com = (st->rl_dn << 8) | ((ubaddr>>12)&RL_BAE); 13010775Ssam 13110775Ssam if (func == READ) 13210775Ssam com |= RL_READ; 13310775Ssam else 13410775Ssam com |= RL_WRITE; 13510775Ssam rladdr->rlcs = com; 13610775Ssam 13710775Ssam /* wait for controller and drive */ 13810775Ssam while( (rladdr->rlcs & RL_DCRDY) != RL_DCRDY) 13910775Ssam continue; 14010775Ssam 14110775Ssam if (rladdr->rlcs & RL_ERR) { 14210775Ssam int status; 14310775Ssam 14410775Ssam if ( rladdr->rlcs & RL_DE ) { 14510775Ssam rladdr->rlda.getstat = RL_GSTAT; 14610775Ssam rladdr->rlcs = (st->rl_dn << 8) | RL_GETSTAT; 14710775Ssam rlwait(rladdr); 14810775Ssam status = rladdr->rlmp.getstat; 14910775Ssam rladdr->rlda.getstat = RL_RESET; 15010775Ssam rladdr->rlcs = (st->rl_dn <<8) | RL_GETSTAT; 15110775Ssam rlwait(rladdr); 15210775Ssam } 15310775Ssam printf("rl error: (cyl,head,sec)=(%d,%d,%d) cs=%b mp=%b\n", 15410775Ssam cn, head, sn, rladdr->rlcs & 0xffff, RLCS_BITS, 15510775Ssam status, RLER_BITS); 15610775Ssam 15710775Ssam /* Determine disk posistion */ 15810775Ssam rladdr->rlcs = (st->rl_dn << 8) | RL_RHDR; 15910775Ssam rlwait(rladdr); 16010775Ssam 16110775Ssam /* save disk drive posistion */ 16210775Ssam st->rl_cylnhd = (rladdr->rlmp.readhdr & 0177700) >> 6; 16310775Ssam 16410775Ssam if (errcnt == 10) { 16510775Ssam printf("rl: unrecovered error\n"); 16610775Ssam return (-1); 16710775Ssam } 16810775Ssam errcnt++; 16910775Ssam goto retry; 17010775Ssam } 17110775Ssam 17210775Ssam /* do we have to finish off the rest of the transfer? */ 17310775Ssam if ( (st->rl_bleft -= st->rl_bpart) > 0 ) { 17410775Ssam /* increment head and/or cylinder */ 17510775Ssam if ( ++head > 1 ) { 17610775Ssam cn++; /* want next cyl, head 0 sector 0 */ 17710775Ssam head = 0; 17810775Ssam } 17910775Ssam 18010775Ssam /* we always want sector to be zero */ 18110775Ssam sn = 0; 18210775Ssam 18310775Ssam /* 18410775Ssam * standalone code for ubafree does what regular 18510775Ssam * ubapurge does and we want to purge last transfer 18610775Ssam */ 18710775Ssam ubafree(io, ubinfo); 18810775Ssam 18910775Ssam ubaddr = ubinfo + io->i_cc - st->rl_bleft; 19010775Ssam 19110775Ssam goto stupid_rl; 19210775Ssam } 19310775Ssam 19410775Ssam ubafree(io, ubinfo); 19510775Ssam 19610775Ssam if (errcnt) 19710775Ssam printf("rl: recovered by retry\n"); 19810775Ssam return (io->i_cc); 19910775Ssam } 20010775Ssam 20110775Ssam rlwait(rladdr) 20210775Ssam register struct rldevice *rladdr; 20310775Ssam { 20410775Ssam 20510775Ssam while ((rladdr->rlcs & RL_CRDY) == 0) 20610775Ssam continue; 20710775Ssam } 208*11111Ssam 209*11111Ssam rlioctl(io, cmd, arg) 210*11111Ssam struct iob *io; 211*11111Ssam int cmd; 212*11111Ssam caddr_t arg; 213*11111Ssam { 214*11111Ssam 215*11111Ssam return (ECMD); 216*11111Ssam } 217