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