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