1: /*
2: * Copyright (c) 1986 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 2.6 (2.11BSD) 1997/11/7
7: */
8:
9: /*
10: * RL disk driver
11: *
12: * Modified to handle disklabels - 1995/06/15
13: * RL driver modified for the standalone shell.
14: * Armando P. Stettner Digital Equipment Corp. July, 1980
15: */
16:
17: #include "../h/param.h"
18: #include "../pdpuba/rlreg.h"
19: #include "saio.h"
20:
21: #define NRL 2
22:
23: struct rldevice *RLcsr[NRL + 1] =
24: {
25: (struct rldevice *)0174400,
26: (struct rldevice *)0,
27: (struct rldevice *)-1
28: };
29:
30: #define BLKRL1 10240 /* Number of UNIX blocks for an RL01 drive */
31: #define BLKRL2 20480 /* Number of UNIX blocks for an RL02 drive */
32: #define RLCYLSZ 10240 /* bytes per cylinder */
33: #define RLSECSZ 256 /* bytes per sector */
34:
35: struct Rldrives
36: {
37: int cn[4]; /* location of heads for each drive */
38: int type[4]; /* # blocks on drive (RL01/02) */
39: int com; /* read or write command word */
40: int chn; /* cylinder and head number */
41: unsigned int bleft; /* bytes left to be transferred */
42: unsigned int bpart; /* number of bytes transferred */
43: int sn; /* sector number */
44: union {
45: int w[2];
46: long l;
47: } addr; /* address of memory for transfer */
48:
49: } rl[NRL] = {{-1,-1,-1,-1,-1,-1,-1,-1},
50: {-1,-1,-1,-1,-1,-1,-1,-1}}; /* initialize cn[] and type[] */
51:
52: rlstrategy(io, func)
53: register struct iob *io;
54: int func;
55: {
56: int drive = io->i_unit;
57: int dif;
58: int head;
59: int bae, lo16;
60: int ctlr = io->i_ctlr;
61: register struct rldevice *rladdr;
62: register struct Rldrives *rlp;
63:
64: rladdr = RLcsr[ctlr];
65: rlp = &rl[ctlr];
66:
67: dif = deveovchk(io);
68: if (dif <= 0)
69: return(dif);
70:
71: iomapadr(io->i_ma, &bae, &lo16);
72: rlp->chn = io->i_bn/20;
73: rlp->sn = (io->i_bn%20) << 1;
74: rlp->bleft = io->i_cc;
75: rlp->addr.w[0] = bae;
76: rlp->addr.w[1] = lo16;
77: rlp->com = (drive << 8);
78: if (func == READ)
79: rlp->com |= RL_RCOM;
80: else
81: rlp->com |= RL_WCOM;
82: reading:
83: /*
84: * One has to seek an RL head, relativily.
85: */
86: dif =(rlp->cn[drive] >> 1) - (rlp->chn >>1);
87: head = (rlp->chn & 1) << 4;
88: if (dif < 0)
89: rladdr->rlda = (-dif <<7) | RLDA_SEEKHI | head;
90: else
91: rladdr->rlda = (dif << 7) | RLDA_SEEKLO | head;
92: rladdr->rlcs = (drive << 8) | RL_SEEK;
93: rlp->cn[drive] = rlp->chn; /* keep current, our notion of where the heads are */
94: if (rlp->bleft < (rlp->bpart = RLCYLSZ - (rl->sn * RLSECSZ)))
95: rlp->bpart = rlp->bleft;
96: while ((rladdr->rlcs&RL_CRDY) == 0)
97: continue;
98: rladdr->rlda = (rlp->chn << 6) | rlp->sn;
99: rladdr->rlba = (caddr_t) rlp->addr.w[1];
100: rladdr->rlmp = -(rlp->bpart >> 1);
101: rladdr->rlcs = rlp->com | rlp->addr.w[0] << 4;
102: while ((rladdr->rlcs & RL_CRDY) == 0) /* wait for completion */
103: continue;
104: if (rladdr->rlcs < 0) {
105: /* check error bit */
106: if (rladdr->rlcs & 040000) {
107: /* Drive error */
108: /*
109: * get status from drive
110: */
111: rladdr->rlda = RLDA_GS;
112: rladdr->rlcs = (drive << 8) | RL_GETSTATUS;
113: while ((rladdr->rlcs & RL_CRDY) == 0) /* wait for controller */
114: continue;
115: }
116: printf("%s err cy=%d, hd=%d, sc=%d, rlcs=%o, rlmp=%o\n",
117: devname(io), rlp->chn>>01, rlp->chn&01, rlp->sn,
118: rladdr->rlcs, rladdr->rlmp);
119: return(-1);
120: }
121: /*
122: * Determine if there is more to read to satisfy this request.
123: * This is to compensate for the lack of spiraling reads.
124: */
125: if ((rlp->bleft -= rlp->bpart) > 0) {
126: rlp->addr.l += rlp->bpart;
127: rlp->sn = 0;
128: rlp->chn++;
129: goto reading; /* read some more */
130: }
131: return(io->i_cc);
132: }
133:
134: rlopen(io)
135: register struct iob *io;
136: {
137:
138: if (io->i_unit > 3)
139: return(-1);
140: if (genopen(NRL, io) < 0)
141: return(-1);
142: rlgsts(io); /* get status and head position */
143: if (devlabel(io, READLABEL) < 0)
144: return(-1);
145: io->i_boff = io->i_label.d_partitions[io->i_part].p_offset;
146: return(0);
147: }
148:
149: /*
150: * We must determine what type of drive we are talking to in order
151: * to determine how many blocks are on the device. The rl.type[]
152: * array has been initialized with -1's so that we may test first
153: * contact with a particular drive and do this determination only once.
154: *
155: * RL02 GET STATUS BAND-AID - Fred Canter 10/14/80
156: *
157: * For some unknown reason the RL02 (seems to be
158: * only drive 1) does not return a valid drive status
159: * the first time that a GET STATUS request is issued
160: * for the drive, in fact it can take up to three or more
161: * GET STATUS requests to obtain the correct status.
162: * In order to overcome this "HACK" the driver has been
163: * modified to issue a GET STATUS request, validate the
164: * drive status returned, and then use it to determine the
165: * drive type. If a valid status is not returned after eight
166: * attempts, then an error message is printed.
167: */
168:
169: rlgsts(io)
170: struct iob *io;
171: {
172: int ctr;
173: int drive = io->i_unit;
174: int ctlr = io->i_ctlr;
175: register struct Rldrives *rlp = &rl[ctlr];
176: register struct rldevice *rladdr = RLcsr[ctlr];
177:
178:
179: if (rlp->type[drive] < 0) {
180: ctr = 0;
181: do {
182: /* load this register; what a dumb controller */
183: rladdr->rlda = RLDA_RESET|RLDA_GS;
184: /* set up csr */
185: rladdr->rlcs = (drive << 8) | RL_GETSTATUS;
186: while ((rladdr->rlcs & RL_CRDY) == 0) /* wait for it */
187: continue;
188: } while (((rladdr->rlmp & 0177477) != 035) && (++ctr < 8));
189: if (ctr >= 8)
190: printf("\nCan't get %s sts\n", devname(io));
191: if (rladdr->rlmp & RLMP_DTYP)
192: rlp->type[drive] = BLKRL2; /* drive is RL02 */
193: else
194: rlp->type[drive] = BLKRL1; /* drive RL01 */
195: /*
196: * When device is first touched, find out where the heads are.
197: */
198: rladdr->rlcs = (drive << 8) | RL_RHDR;
199: while ((rladdr->rlcs&RL_CRDY) == 0)
200: continue;
201: rlp->cn[drive] = ((rladdr->rlmp) >> 6) & 01777;
202: }
203: return;
204: }
205:
206: /*
207: * This generates a default label. 'rlopen' has already been called so
208: * we can use the 'types' field as the number of sectors on the device.
209: */
210:
211: rllabel(io)
212: register struct iob *io;
213: {
214: register struct disklabel *lp = &io->i_label;
215: daddr_t nblks = rl[io->i_ctlr].type[io->i_unit];
216:
217: lp->d_type = DTYPE_DEC;
218: lp->d_partitions[0].p_size = nblks;
219: lp->d_nsectors = 20; /* sectors per track */
220: lp->d_ntracks = 2; /* tracks per cylinder */
221: lp->d_secpercyl = 40; /* sectors per cylinder */
222: lp->d_ncylinders = nblks / (20 * 2);
223: lp->d_secperunit = nblks;
224: return(0);
225: }
Defined functions
Defined variables
RLcsr
defined in line
23; used 3 times
rl
defined in line
49; used 4 times
Defined struct's
Defined macros
NRL
defined in line
21; used 3 times