|
|
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.