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