1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)rl.c 7.1 (Berkeley) 06/05/86 7 */ 8 9 /* 10 * Standalone RL02 disk driver 11 */ 12 #include "../machine/pte.h" 13 14 #include "../h/param.h" 15 #include "../h/inode.h" 16 #include "../h/fs.h" 17 18 #include "../vaxuba/rlreg.h" 19 #include "../vaxuba/ubareg.h" 20 21 #include "saio.h" 22 #include "savax.h" 23 24 u_short rlstd[] = { 0774400 }; 25 short rl_off[] = { 0, 361, 0, -1, -1, -1, -1, -1 }; 26 27 /* struct to keep state info about the controller */ 28 struct rl_stat { 29 short rl_dn; /* drive number */ 30 short rl_cylnhd; /* cylinder and head */ 31 u_short rl_bleft; /* bytes left to transfer */ 32 u_short rl_bpart; /* bytes transferred */ 33 } rl_stat[] = { -1, 0, 0, 0}; 34 35 rlopen(io) 36 register struct iob *io; 37 { 38 register struct rldevice *rladdr = 39 (struct rldevice *)ubamem(io->i_unit, rlstd[0]); 40 register struct rl_stat *st = &rl_stat[0]; 41 register int ctr = 0; 42 43 if (rl_off[io->i_boff] == -1 || 44 io->i_boff < 0 || io->i_boff > 7) 45 _stop("rl bad unit"); 46 47 /* 48 * DEC reports that: 49 * For some unknown reason the RL02 (seems to be only drive 1) 50 * does not return a valid drive status the first time that a 51 * GET STATUS request is issued for the drive, in fact it can 52 * take up to three or more GET STATUS requests to obtain the 53 * correct status. 54 * In order to overcome this, the driver has been modified to 55 * issue a GET STATUS request and validate the drive status 56 * returned. If a valid status is not returned after eight 57 * attempts, then an error message is printed. 58 */ 59 do { 60 rladdr->rlda.getstat = RL_RESET; 61 rladdr->rlcs = (io->i_unit <<8) | RL_GETSTAT; /* Get status*/ 62 rlwait(rladdr); 63 } while( (rladdr->rlmp.getstat&RLMP_STATUS) != RLMP_STATOK && ++ctr<8 ); 64 65 if ((rladdr->rlcs & RL_DE) || (ctr >= 8)) 66 _stop("rl unit does not respond"); 67 68 if ((rladdr->rlmp.getstat & RLMP_DT) == 0 ) /* NO RL01'S */ 69 _stop("rl01 unit not supported"); 70 71 /* Determine disk posistion */ 72 rladdr->rlcs = (io->i_unit << 8) | RL_RHDR; 73 rlwait(rladdr); 74 75 /* save disk drive posistion */ 76 st->rl_cylnhd = (rladdr->rlmp.readhdr & 0177700) >> 6; 77 st->rl_dn = io->i_unit; 78 79 /* byte offset for cylinder desired */ 80 io->i_boff = rl_off[io->i_boff] * NRLBPSC * NRLTRKS * NRLSECT; 81 } 82 83 rlstrategy(io, func) 84 register struct iob *io; 85 { 86 register struct rldevice *rladdr = 87 (struct rldevice *)ubamem(io->i_unit, rlstd[0]); 88 register struct rl_stat *st = &rl_stat[0]; 89 int com; 90 daddr_t bn; 91 short cn, sn, head; 92 int diff, ubinfo, ubaddr, errcnt = 0; 93 94 retry: 95 ubinfo = ubasetup(io, 1); 96 bn = io->i_bn; /* block number */ 97 cn = bn / 40; /* 40 512 byte blocks per cylinder */ 98 sn = (bn % 20) << 1; 99 head = (bn / 20) & 1; 100 st->rl_bleft = io->i_cc; /* total number of bytes to trans */ 101 ubaddr = ubinfo; 102 103 stupid_rl: 104 /* find out how many cylinders to seek */ 105 diff = (st->rl_cylnhd >> 1) - cn; 106 if ( diff == 0 && (st->rl_cylnhd & 1) == head ) 107 goto noseek; 108 109 /* first time or we switched drives */ 110 st->rl_dn = io->i_unit; /* drive number */ 111 112 if ( diff < 0 ) 113 rladdr->rlda.seek = -diff<<7 | RLDA_HGH | head << 4; 114 else 115 rladdr->rlda.seek = diff<<7 | RLDA_LOW | head << 4; 116 rladdr->rlcs = (st->rl_dn << 8) | RL_SEEK; 117 118 /* reset position of drive */ 119 st->rl_cylnhd = (cn << 1) | head; 120 121 noseek: 122 /* wait for controller and drive */ 123 while( (rladdr->rlcs & RL_DCRDY) != RL_DCRDY) 124 continue; 125 126 /* calculate the max number of bytes we can trans */ 127 st->rl_bpart = NRLSECT * NRLBPSC - (sn * NRLBPSC); 128 if ( st->rl_bleft < st->rl_bpart ) 129 st->rl_bpart = st->rl_bleft; 130 131 rladdr->rlda.rw = (st->rl_cylnhd << 6) | sn; 132 rladdr->rlmp.rw = -(st->rl_bpart >> 1); 133 rladdr->rlba = ubaddr; 134 135 com = (st->rl_dn << 8) | ((ubaddr>>12)&RL_BAE); 136 137 if (func == READ) 138 com |= RL_READ; 139 else 140 com |= RL_WRITE; 141 rladdr->rlcs = com; 142 143 /* wait for controller and drive */ 144 while( (rladdr->rlcs & RL_DCRDY) != RL_DCRDY) 145 continue; 146 147 if (rladdr->rlcs & RL_ERR) { 148 int status; 149 150 if ( rladdr->rlcs & RL_DE ) { 151 rladdr->rlda.getstat = RL_GSTAT; 152 rladdr->rlcs = (st->rl_dn << 8) | RL_GETSTAT; 153 rlwait(rladdr); 154 status = rladdr->rlmp.getstat; 155 rladdr->rlda.getstat = RL_RESET; 156 rladdr->rlcs = (st->rl_dn <<8) | RL_GETSTAT; 157 rlwait(rladdr); 158 } 159 printf("rl error: (cyl,head,sec)=(%d,%d,%d) cs=%b mp=%b\n", 160 cn, head, sn, rladdr->rlcs & 0xffff, RLCS_BITS, 161 status, RLER_BITS); 162 163 /* Determine disk posistion */ 164 rladdr->rlcs = (st->rl_dn << 8) | RL_RHDR; 165 rlwait(rladdr); 166 167 /* save disk drive posistion */ 168 st->rl_cylnhd = (rladdr->rlmp.readhdr & 0177700) >> 6; 169 170 if (errcnt == 10) { 171 printf("rl: unrecovered error\n"); 172 return (-1); 173 } 174 errcnt++; 175 goto retry; 176 } 177 178 /* do we have to finish off the rest of the transfer? */ 179 if ( (st->rl_bleft -= st->rl_bpart) > 0 ) { 180 /* increment head and/or cylinder */ 181 if ( ++head > 1 ) { 182 cn++; /* want next cyl, head 0 sector 0 */ 183 head = 0; 184 } 185 186 /* we always want sector to be zero */ 187 sn = 0; 188 189 /* 190 * standalone code for ubafree does what regular 191 * ubapurge does and we want to purge last transfer 192 */ 193 ubafree(io, ubinfo); 194 195 ubaddr = ubinfo + io->i_cc - st->rl_bleft; 196 197 goto stupid_rl; 198 } 199 200 ubafree(io, ubinfo); 201 202 if (errcnt) 203 printf("rl: recovered by retry\n"); 204 return (io->i_cc); 205 } 206 207 rlwait(rladdr) 208 register struct rldevice *rladdr; 209 { 210 211 while ((rladdr->rlcs & RL_CRDY) == 0) 212 continue; 213 } 214 215 rlioctl(io, cmd, arg) 216 struct iob *io; 217 int cmd; 218 caddr_t arg; 219 { 220 221 return (ECMD); 222 } 223