123238Smckusick /* 235052Skarels * Copyright (c) 1982, 1986, 1988 Regents of the University of California. 323238Smckusick * All rights reserved. The Berkeley software License Agreement 423238Smckusick * specifies the terms and conditions for redistribution. 523238Smckusick * 6*45803Sbostic * @(#)rl.c 7.8 (Berkeley) 12/16/90 723238Smckusick */ 810775Ssam 910775Ssam /* 1010775Ssam * Standalone RL02 disk driver 1110775Ssam */ 1210775Ssam 13*45803Sbostic #include "sys/param.h" 1410775Ssam 15*45803Sbostic #include "../include/pte.h" 16*45803Sbostic #include "../uba/rlreg.h" 17*45803Sbostic #include "../uba/ubareg.h" 1810775Ssam 19*45803Sbostic #include "stand/saio.h" 2010775Ssam #include "savax.h" 2110775Ssam 2233542Sbostic #define MAXPART 8 2333542Sbostic #define MAXCTLR 1 /* all addresses must be specified */ 2433542Sbostic u_short rlstd[MAXCTLR] = { 0774400 }; 2510775Ssam short rl_off[] = { 0, 361, 0, -1, -1, -1, -1, -1 }; 2610775Ssam 2710775Ssam /* struct to keep state info about the controller */ 2810775Ssam struct rl_stat { 2910775Ssam short rl_dn; /* drive number */ 3010775Ssam short rl_cylnhd; /* cylinder and head */ 3110775Ssam u_short rl_bleft; /* bytes left to transfer */ 3210775Ssam u_short rl_bpart; /* bytes transferred */ 3333542Sbostic } rl_stat[MAXCTLR] = { -1, 0, 0, 0 }; 3410775Ssam 3510775Ssam rlopen(io) 3610775Ssam register struct iob *io; 3710775Ssam { 3833542Sbostic register struct rldevice *rladdr; 3933542Sbostic register struct rl_stat *st; 4010775Ssam register int ctr = 0; 4110775Ssam 4235052Skarels if ((u_int)io->i_adapt >= nuba) 4335052Skarels return (EADAPT); 4433542Sbostic if ((u_int)io->i_ctlr >= MAXCTLR) 4533542Sbostic return (ECTLR); 4633542Sbostic rladdr = (struct rldevice *)ubamem(io->i_adapt, rlstd[io->i_ctlr]); 4733549Sbostic if (badaddr((char *)rladdr, sizeof(short))) 4833408Skarels return (ENXIO); 4933542Sbostic if ((u_int)io->i_part >= MAXPART || rl_off[io->i_part] == -1) 5033542Sbostic return (EPART); 5110775Ssam 5210775Ssam /* 5310775Ssam * DEC reports that: 5410775Ssam * For some unknown reason the RL02 (seems to be only drive 1) 5510775Ssam * does not return a valid drive status the first time that a 5610775Ssam * GET STATUS request is issued for the drive, in fact it can 5710775Ssam * take up to three or more GET STATUS requests to obtain the 5810775Ssam * correct status. 5910775Ssam * In order to overcome this, the driver has been modified to 6010775Ssam * issue a GET STATUS request and validate the drive status 6110775Ssam * returned. If a valid status is not returned after eight 6210775Ssam * attempts, then an error message is printed. 6310775Ssam */ 6410775Ssam do { 6510775Ssam rladdr->rlda.getstat = RL_RESET; 6610775Ssam rladdr->rlcs = (io->i_unit <<8) | RL_GETSTAT; /* Get status*/ 6710775Ssam rlwait(rladdr); 6833408Skarels } while ((rladdr->rlmp.getstat&RLMP_STATUS) != RLMP_STATOK && ++ctr<8); 6910775Ssam 7033408Skarels if ((rladdr->rlcs & RL_DE) || (ctr >= 8)) { 7133542Sbostic printf("rl: unit does not respond\n"); 7233408Skarels return (EUNIT); 7333408Skarels } 7410775Ssam 7533408Skarels if ((rladdr->rlmp.getstat & RLMP_DT) == 0) { /* NO RL01'S */ 7633408Skarels printf("rl01 unit not supported\n"); 7733542Sbostic return (ENXIO); 7833408Skarels } 7910775Ssam 8010775Ssam /* Determine disk posistion */ 8110775Ssam rladdr->rlcs = (io->i_unit << 8) | RL_RHDR; 8210775Ssam rlwait(rladdr); 8310775Ssam 8410775Ssam /* save disk drive posistion */ 8533542Sbostic st = &rl_stat[io->i_ctlr]; 8610775Ssam st->rl_cylnhd = (rladdr->rlmp.readhdr & 0177700) >> 6; 8710775Ssam st->rl_dn = io->i_unit; 8810775Ssam 8910775Ssam /* byte offset for cylinder desired */ 9033542Sbostic io->i_boff = rl_off[io->i_part] * NRLBPSC * NRLTRKS * NRLSECT; 9133408Skarels return (0); 9210775Ssam } 9310775Ssam 9410775Ssam rlstrategy(io, func) 9510775Ssam register struct iob *io; 9610775Ssam { 9733542Sbostic register struct rldevice *rladdr; 9833542Sbostic register struct rl_stat *st; 9910775Ssam int com; 10010775Ssam daddr_t bn; 10110775Ssam short cn, sn, head; 10234981Sbostic int diff, ubinfo, ubaaddr, errcnt = 0; 10310775Ssam 10433542Sbostic rladdr = (struct rldevice *)ubamem(io->i_adapt, rlstd[io->i_ctlr]); 10533542Sbostic st = &rl_stat[io->i_ctlr]; 10610775Ssam retry: 10710775Ssam ubinfo = ubasetup(io, 1); 10810775Ssam bn = io->i_bn; /* block number */ 10910775Ssam cn = bn / 40; /* 40 512 byte blocks per cylinder */ 11010775Ssam sn = (bn % 20) << 1; 11110775Ssam head = (bn / 20) & 1; 11210775Ssam st->rl_bleft = io->i_cc; /* total number of bytes to trans */ 11334981Sbostic ubaaddr = ubinfo; 11410775Ssam 11510775Ssam stupid_rl: 11610775Ssam /* find out how many cylinders to seek */ 11710775Ssam diff = (st->rl_cylnhd >> 1) - cn; 11833542Sbostic if (diff == 0 && (st->rl_cylnhd & 1) == head) 11910775Ssam goto noseek; 12010775Ssam 12110775Ssam /* first time or we switched drives */ 12210775Ssam st->rl_dn = io->i_unit; /* drive number */ 12310775Ssam 12433542Sbostic if (diff < 0) 12510775Ssam rladdr->rlda.seek = -diff<<7 | RLDA_HGH | head << 4; 12610775Ssam else 12710775Ssam rladdr->rlda.seek = diff<<7 | RLDA_LOW | head << 4; 12810775Ssam rladdr->rlcs = (st->rl_dn << 8) | RL_SEEK; 12910775Ssam 13010775Ssam /* reset position of drive */ 13110775Ssam st->rl_cylnhd = (cn << 1) | head; 13210775Ssam 13310775Ssam noseek: 13410775Ssam /* wait for controller and drive */ 13510775Ssam while( (rladdr->rlcs & RL_DCRDY) != RL_DCRDY) 13610775Ssam continue; 13710775Ssam 13810775Ssam /* calculate the max number of bytes we can trans */ 13910775Ssam st->rl_bpart = NRLSECT * NRLBPSC - (sn * NRLBPSC); 14033542Sbostic if (st->rl_bleft < st->rl_bpart) 14110775Ssam st->rl_bpart = st->rl_bleft; 14210775Ssam 14310775Ssam rladdr->rlda.rw = (st->rl_cylnhd << 6) | sn; 14410775Ssam rladdr->rlmp.rw = -(st->rl_bpart >> 1); 14534981Sbostic rladdr->rlba = ubaaddr; 14610775Ssam 14734981Sbostic com = (st->rl_dn << 8) | ((ubaaddr>>12)&RL_BAE); 14810775Ssam 14910775Ssam if (func == READ) 15010775Ssam com |= RL_READ; 15110775Ssam else 15210775Ssam com |= RL_WRITE; 15310775Ssam rladdr->rlcs = com; 15410775Ssam 15510775Ssam /* wait for controller and drive */ 15610775Ssam while( (rladdr->rlcs & RL_DCRDY) != RL_DCRDY) 15710775Ssam continue; 15810775Ssam 15910775Ssam if (rladdr->rlcs & RL_ERR) { 16010775Ssam int status; 16110775Ssam 16233542Sbostic if (rladdr->rlcs & RL_DE) { 16310775Ssam rladdr->rlda.getstat = RL_GSTAT; 16410775Ssam rladdr->rlcs = (st->rl_dn << 8) | RL_GETSTAT; 16510775Ssam rlwait(rladdr); 16610775Ssam status = rladdr->rlmp.getstat; 16710775Ssam rladdr->rlda.getstat = RL_RESET; 16810775Ssam rladdr->rlcs = (st->rl_dn <<8) | RL_GETSTAT; 16910775Ssam rlwait(rladdr); 17010775Ssam } 17110775Ssam printf("rl error: (cyl,head,sec)=(%d,%d,%d) cs=%b mp=%b\n", 17210775Ssam cn, head, sn, rladdr->rlcs & 0xffff, RLCS_BITS, 17310775Ssam status, RLER_BITS); 17410775Ssam 17510775Ssam /* Determine disk posistion */ 17610775Ssam rladdr->rlcs = (st->rl_dn << 8) | RL_RHDR; 17710775Ssam rlwait(rladdr); 17810775Ssam 17910775Ssam /* save disk drive posistion */ 18010775Ssam st->rl_cylnhd = (rladdr->rlmp.readhdr & 0177700) >> 6; 18110775Ssam 18233542Sbostic if (errcnt++ == 10) { 18310775Ssam printf("rl: unrecovered error\n"); 18410775Ssam return (-1); 18510775Ssam } 18610775Ssam goto retry; 18710775Ssam } 18810775Ssam 18910775Ssam /* do we have to finish off the rest of the transfer? */ 19033542Sbostic if ((st->rl_bleft -= st->rl_bpart) > 0) { 19110775Ssam /* increment head and/or cylinder */ 19233542Sbostic if (++head > 1) { 19310775Ssam cn++; /* want next cyl, head 0 sector 0 */ 19410775Ssam head = 0; 19510775Ssam } 19610775Ssam 19710775Ssam /* we always want sector to be zero */ 19810775Ssam sn = 0; 19910775Ssam 20010775Ssam /* 20110775Ssam * standalone code for ubafree does what regular 20210775Ssam * ubapurge does and we want to purge last transfer 20310775Ssam */ 20410775Ssam ubafree(io, ubinfo); 20510775Ssam 20634981Sbostic ubaaddr = ubinfo + io->i_cc - st->rl_bleft; 20710775Ssam 20810775Ssam goto stupid_rl; 20910775Ssam } 21010775Ssam 21110775Ssam ubafree(io, ubinfo); 21210775Ssam 21310775Ssam if (errcnt) 21410775Ssam printf("rl: recovered by retry\n"); 21510775Ssam return (io->i_cc); 21610775Ssam } 21710775Ssam 21833542Sbostic static 21910775Ssam rlwait(rladdr) 22010775Ssam register struct rldevice *rladdr; 22110775Ssam { 22233542Sbostic while ((rladdr->rlcs & RL_CRDY) == 0); 22310775Ssam } 224