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