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