1: /*
2: * SCCS id @(#)rl.c 2.1 (Berkeley) 11/20/83
3: */
4:
5: /*
6: * RL01/RL02 disk driver
7: */
8:
9: #include "rl.h"
10: #if NRL > 0
11: #include "param.h"
12: #include <sys/buf.h>
13: #include <sys/dir.h>
14: #include <sys/user.h>
15: #include <sys/systm.h>
16: #include <sys/conf.h>
17: #include <sys/rlreg.h>
18:
19: #define RL01_NBLKS 10240 /* Number of UNIX blocks for an RL01 drive */
20: #define RL02_NBLKS 20480 /* Number of UNIX blocks for an RL02 drive */
21: #define RL_CYLSZ 10240 /* bytes per cylinder */
22: #define RL_SECSZ 256 /* bytes per sector */
23:
24: #define rlwait(r) while (((r)->rlcs & RL_CRDY) == 0)
25:
26: struct rldevice *RLADDR;
27:
28: struct buf rrlbuf;
29: struct buf rltab;
30:
31: struct rl_softc {
32: short cn[4]; /* location of heads for each drive */
33: short type[4]; /* parameter dependent on drive type (RL01/2) */
34: short dn; /* drive number */
35: short com; /* read or write command word */
36: short chn; /* cylinder and head number */
37: u_short bleft; /* bytes left to be transferred */
38: u_short bpart; /* number of bytes transferred */
39: short sn; /* sector number */
40: union {
41: short w[2];
42: long l;
43: } rl_un; /* address of memory for transfer */
44:
45: } rl = {-1,-1,-1,-1, -1,-1,-1,-1}; /* initialize cn[] and type[] */
46:
47: rlattach(addr, unit)
48: struct rldevice *addr;
49: {
50: if (unit != 0)
51: return(0);
52: RLADDR = addr;
53: return(1);
54: }
55:
56: rlstrategy(bp)
57: register struct buf *bp;
58: {
59: register struct rldevice *rp;
60: int s, nblocks, drive, ctr;
61:
62: if ((rp = RLADDR) == (struct rldevice *) NULL) {
63: bp->b_error = ENXIO;
64: goto bad;
65: }
66:
67: /*
68: * We must determine what type of drive we are talking to in order
69: * to determine how many blocks are on the device. The rl.type[]
70: * array has been initialized with -1's so that we may test first
71: * contact with a particular drive and do this determination only once.
72: *
73: * For some unknown reason the RL02 (seems to be
74: * only drive 1) does not return a valid drive status
75: * the first time that a GET STATUS request is issued
76: * for the drive, in fact it can take up to three or more
77: * GET STATUS requests to obtain the correct status.
78: * In order to overcome this "HACK" the driver has been
79: * modified to issue a GET STATUS request, validate the
80: * drive status returned, and then use it to determine the
81: * drive type. If a valid status is not returned after eight
82: * attempts, then an error message is printed.
83: */
84: if (rl.type[minor(bp->b_dev)] < 0) {
85: drive = minor(bp->b_dev);
86: ctr = 0;
87: do { /* get status and reset when first touching this drive */
88: rp->rlda = RLDA_RESET | RLDA_GS;
89: rp->rlcs = (drive << 8) | RL_GETSTATUS; /* set up csr */
90: rlwait(rp);
91: } while (((rp->rlmp & 0177477) != 035) && (++ctr < 8));
92: if (ctr >= 8) {
93: printf("rl%d: can't get status\n", drive);
94: rl.type[drive] = RL02_NBLKS; /* assume RL02 */
95: } else if (rp->rlmp & RLMP_DTYP) {
96: rl.type[drive] = RL02_NBLKS; /* drive is RL02 */
97: #ifdef DISTRIBUTION_BINARY
98: /*
99: * HACK-- for the 2.9 distribution binary,
100: * patch the swplo value if swapping on an RL02.
101: */
102: if ((bdevsw[major(swapdev)].d_strategy == rlstrategy)
103: && (drive == minor(swapdev)) && (swplo == (8000-1)))
104: swplo = (daddr_t) (17000 - 1);
105: #endif
106: } else
107: rl.type[drive] = RL01_NBLKS; /* drive RL01 */
108: }
109: /* determine nblocks based upon which drive this is */
110: nblocks = rl.type[minor(bp->b_dev)];
111: if(bp->b_blkno >= nblocks) {
112: if((bp->b_blkno == nblocks) && (bp->b_flags & B_READ))
113: bp->b_resid = bp->b_bcount;
114: else
115: {
116: bp->b_error = ENXIO;
117: bad:
118: bp->b_flags |= B_ERROR;
119: }
120: iodone(bp);
121: return;
122: }
123: #ifdef UNIBUS_MAP
124: mapalloc(bp);
125: #endif
126:
127: bp->av_forw = NULL;
128: s = spl5();
129: if(rltab.b_actf == NULL)
130: rltab.b_actf = bp;
131: else
132: rltab.b_actl->av_forw = bp;
133: rltab.b_actl = bp;
134: if(rltab.b_active == NULL)
135: rlstart();
136: splx(s);
137: }
138:
139: rlstart()
140: {
141: register struct rl_softc *rlp = &rl;
142: register struct buf *bp;
143:
144: if ((bp = rltab.b_actf) == NULL)
145: return;
146: rltab.b_active++;
147: rlp->dn = minor(bp->b_dev);
148: rlp->chn = bp->b_blkno / 20;
149: rlp->sn = (bp->b_blkno % 20) << 1;
150: rlp->bleft = bp->b_bcount;
151: rlp->rl_un.w[0] = bp->b_xmem & 3;
152: rlp->rl_un.w[1] = (int) bp->b_un.b_addr;
153: rlp->com = (rlp->dn << 8) | RL_IE;
154: if (bp->b_flags & B_READ)
155: rlp->com |= RL_RCOM;
156: else
157: rlp->com |= RL_WCOM;
158: rlio();
159: }
160:
161: rlintr()
162: {
163: register struct buf *bp;
164: register struct rldevice *rladdr = RLADDR;
165: register status;
166:
167: if (rltab.b_active == NULL)
168: return;
169: bp = rltab.b_actf;
170: #ifdef RL_DKN
171: dk_busy &= ~(1 << RL_DKN);
172: #endif RL_DKN
173: if (rladdr->rlcs & RL_CERR) {
174: if (rladdr->rlcs & RL_HARDERR) {
175: if(rltab.b_errcnt > 2) {
176: #ifdef UCB_DEVERR
177: harderr(bp, "rl");
178: printf("cs=%b da=%b\n", rladdr->rlcs, RL_BITS,
179: rladdr->rlda, RLDA_BITS);
180: #else
181: deverror(bp, rladdr->rlcs, rladdr->rlda);
182: #endif UCB_DEVERR
183: }
184: }
185: if (rladdr->rlcs & RL_DRE) {
186: rladdr->rlda = RLDA_GS;
187: rladdr->rlcs = (rl.dn << 8) | RL_GETSTATUS;
188: rlwait(rladdr);
189: status = rladdr->rlmp;
190: if(rltab.b_errcnt > 2) {
191: #ifdef UCB_DEVERR
192: harderr(bp, "rl");
193: printf("mp=%b da=%b\n", status, RLMP_BITS,
194: rladdr->rlda, RLDA_BITS);
195: #else
196: deverror(bp, status, rladdr->rlda);
197: #endif
198: }
199: rladdr->rlda = RLDA_RESET | RLDA_GS;
200: rladdr->rlcs = (rl.dn << 8) | RL_GETSTATUS;
201: rlwait(rladdr);
202: if(status & RLMP_VCHK) {
203: rlstart();
204: return;
205: }
206: }
207: if (++rltab.b_errcnt <= 10) {
208: rl.cn[rl.dn] = -1;
209: rlstart();
210: return;
211: }
212: else
213: {
214: bp->b_flags |= B_ERROR;
215: rl.bpart = rl.bleft;
216: }
217: }
218:
219: if ((rl.bleft -= rl.bpart) > 0) {
220: rl.rl_un.l += rl.bpart;
221: rl.sn=0;
222: rl.chn++;
223: rlio();
224: return;
225: }
226: bp->b_resid = 0;
227: rltab.b_active = NULL;
228: rltab.b_errcnt = 0;
229: rltab.b_actf = bp->av_forw;
230: iodone(bp);
231: rlstart();
232: }
233:
234: rlio()
235: {
236:
237: register struct rldevice *rladdr = RLADDR;
238: register dif;
239: register head;
240:
241: #ifdef RL_DKN
242: dk_busy |= 1 << RL_DKN;
243: dk_numb[RL_DKN]++;
244: head = rl.bpart >> 6;
245: dk_wds[RL_DKN] += head;
246: #endif RL_DKN
247:
248: /*
249: * When the device is first touched, find where the heads are and
250: * what type of drive it is.
251: * rl.cn[] is initialized as -1 and this indicates that we have not
252: * touched this drive before.
253: */
254: if (rl.cn[rl.dn] < 0) {
255: /* find where the heads are */
256: rladdr->rlcs = (rl.dn << 8) | RL_RHDR;
257: rlwait(rladdr);
258: rl.cn[rl.dn] = ((rladdr->rlmp) >> 6) & 01777;
259: }
260: dif =(rl.cn[rl.dn] >> 1) - (rl.chn >> 1);
261: head = (rl.chn & 1) << 4;
262: if (dif < 0)
263: rladdr->rlda = (-dif << 7) | RLDA_SEEKHI | head;
264: else
265: rladdr->rlda = (dif << 7) | RLDA_SEEKLO | head;
266: rladdr->rlcs = (rl.dn << 8) | RL_SEEK;
267: rl.cn[rl.dn] = rl.chn;
268: if (rl.bleft < (rl.bpart = RL_CYLSZ - (rl.sn * RL_SECSZ)))
269: rl.bpart = rl.bleft;
270: rlwait(rladdr);
271: rladdr->rlda = (rl.chn << 6) | rl.sn;
272: rladdr->rlba = rl.rl_un.w[1];
273: rladdr->rlmp = -(rl.bpart >> 1);
274: rladdr->rlcs = rl.com | rl.rl_un.w[0] << 4;
275: }
276:
277: rlread(dev)
278: dev_t dev;
279: {
280: physio(rlstrategy, &rrlbuf, dev, B_READ);
281: }
282:
283: rlwrite(dev)
284: dev_t dev;
285: {
286: physio(rlstrategy, &rrlbuf, dev, B_WRITE);
287: }
288: #endif NRL
Defined functions
rlio
defined in line
234; used 2 times
Defined variables
rl
defined in line
45; used 43 times
rltab
defined in line
29; used 17 times
Defined struct's
Defined macros