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