VOID=>void
[unix-history] / usr / src / sys / vax / mba / hp.c
CommitLineData
81263dba 1/* hp.c 3.3 %H% */
04b9d53d
BJ
2
3/*
4 * RP04/RP06/RM03 disk driver
5 */
6
7#include "../h/param.h"
8#include "../h/systm.h"
9#include "../h/buf.h"
10#include "../h/conf.h"
11#include "../h/dir.h"
12#include "../h/user.h"
13#include "../h/map.h"
14#include "../h/mba.h"
15#include "../h/mtpr.h"
16#include "../h/pte.h"
17
18#define DK_N 0
19
20struct device
21{
22 int hpcs1; /* control and Status register 1 */
23 int hpds; /* Drive Status */
24 int hper1; /* Error register 1 */
25 int hpmr; /* Maintenance */
26 int hpas; /* Attention Summary */
27 int hpda; /* Desired address register */
28 int hpdt; /* Drive type */
29 int hpla; /* Look ahead */
30 int hpsn; /* serial number */
31 int hpof; /* Offset register */
32 int hpdc; /* Desired Cylinder address register */
33 int hpcc; /* Current Cylinder */
34 int hper2; /* Error register 2 */
35 int hper3; /* Error register 3 */
36 int hpec1; /* Burst error bit position */
37 int hpec2; /* Burst error bit pattern */
38};
39
40#define HPADDR ((struct device *)(MBA0 + MBA_ERB))
41#define NHP 1
42#define RP 022
43#define RM 024
44#define NSECT 22
45#define NTRAC 19
46#define NRMSECT 32
47#define NRMTRAC 5
48#define SDIST 2
49#define RDIST 6
50
51struct size
52{
53 daddr_t nblocks;
54 int cyloff;
55} hp_sizes[8] =
56{
57 15884, 0, /* cyl 0 thru 37 */
58 33440, 38, /* cyl 38 thru 117 */
59 8360, 98, /* cyl 98 thru 117 */
60#ifdef ERNIE
61 15884, 118, /* cyl 118 thru 155 */
62 66880, 156, /* cyl 156 thru 315 */
63 0, 0,
64 291346, 118, /* cyl 118 thru 814, (like distrib) */
65 208582, 316, /* cyl 316 thru 814 */
66#else
67 0, 0,
68 0, 0,
69 0, 0,
70 291346, 118, /* cyl 118 thru 814 */
71 0, 0,
72#endif
73}, rm_sizes[8] = {
74 15884, 0, /* cyl 0 thru 99 */
75 33440, 100, /* cyl 100 thru 309 */
76 0, 0,
77 0, 0,
78 0, 0,
79 0, 0,
80 82080, 310, /* cyl 310 thru 822 */
81 0, 0,
82};
83
84#define P400 020
85#define M400 0220
86#define P800 040
87#define M800 0240
88#define P1200 060
89#define M1200 0260
90int hp_offset[16] =
91{
92 P400, M400, P400, M400,
93 P800, M800, P800, M800,
94 P1200, M1200, P1200, M1200,
95 0, 0, 0, 0,
96};
97
98struct buf hptab;
99struct buf rhpbuf;
100struct buf hputab[NHP];
101char hp_type[NHP]; /* drive type */
102
103#define GO 01
104#define PRESET 020
105#define RTC 016
106#define OFFSET 014
107#define SEARCH 030
108#define RECAL 06
109#define DCLR 010
110#define WCOM 060
111#define RCOM 070
112
113#define IE 0100
114#define PIP 020000
115#define DRY 0200
116#define ERR 040000
117#define TRE 040000
118#define DCK 0100000
119#define WLE 04000
120#define ECH 0100
121#define VV 0100
122#define DPR 0400
123#define MOL 010000
124#define FMT22 010000
125
126#define b_cylin b_resid
127
128#ifdef INTRLVE
129daddr_t dkblock();
130#endif
131
132hpstrategy(bp)
133register struct buf *bp;
134{
135 register struct buf *dp;
136 register unit, xunit, nspc;
137 long sz, bn;
138 struct size *sizes;
139
140 xunit = minor(bp->b_dev) & 077;
141 sz = bp->b_bcount;
142 sz = (sz+511) >> 9;
143 unit = dkunit(bp);
144 if (hp_type[unit] == 0) {
145 struct device *hpaddr;
146
147 /* determine device type */
148 hpaddr = (struct device *)((int*)HPADDR + 32*unit);
149 hp_type[unit] = hpaddr->hpdt;
150 }
151 if (hp_type[unit] == RM) {
152 sizes = rm_sizes;
153 nspc = NRMSECT*NRMTRAC;
154 } else {
155 sizes = hp_sizes;
156 nspc = NSECT*NTRAC;
157 }
158 if (unit >= NHP ||
159 bp->b_blkno < 0 ||
160 (bn = dkblock(bp))+sz > sizes[xunit&07].nblocks) {
161 bp->b_flags |= B_ERROR;
162 iodone(bp);
163 return;
164 }
165 bp->b_cylin = bn/nspc + sizes[xunit&07].cyloff;
166 dp = &hputab[unit];
81263dba 167 (void) spl5();
04b9d53d
BJ
168 disksort(dp, bp);
169 if (dp->b_active == 0) {
170 hpustart(unit);
171 if(hptab.b_active == 0)
172 hpstart();
173 }
81263dba 174 (void) spl0();
04b9d53d
BJ
175}
176
177hpustart(unit)
178register unit;
179{
180 register struct buf *bp, *dp;
181 register struct device *hpaddr;
182 daddr_t bn;
183 int sn, cn, csn;
184
185 ((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
186 HPADDR->hpas = 1<<unit;
187
188 if(unit >= NHP)
189 return;
190/*
191 dk_busy &= ~(1<<(unit+DK_N));
192*/
193 dp = &hputab[unit];
194 if((bp=dp->b_actf) == NULL)
195 return;
196 hpaddr = (struct device *)((int *)HPADDR + 32*unit);
197 if((hpaddr->hpds & VV) == 0) {
198 hpaddr->hpcs1 = PRESET|GO;
199 hpaddr->hpof = FMT22;
200 }
201 if(dp->b_active)
202 goto done;
203 dp->b_active++;
204 if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL))
205 goto done;
206
207 bn = dkblock(bp);
208 cn = bp->b_cylin;
209 if(hp_type[unit] == RM) {
210 sn = bn%(NRMSECT*NRMTRAC);
211 sn = (sn+NRMSECT-SDIST)%NRMSECT;
212 } else {
213 sn = bn%(NSECT*NTRAC);
214 sn = (sn+NSECT-SDIST)%NSECT;
215 }
216
217 if(cn - (hpaddr->hpdc & 0xffff))
218 goto search;
219 csn = ((hpaddr->hpla & 0xffff)>>6) - sn + SDIST - 1;
220 if(csn < 0)
221 csn += NSECT;
222 if(csn > NSECT-RDIST)
223 goto done;
224
225search:
226 hpaddr->hpdc = cn;
227 hpaddr->hpda = sn;
228 hpaddr->hpcs1 = SEARCH|GO;
229/*
230 unit += DK_N;
231 dk_busy |= 1<<unit;
232 dk_numb[unit] += 1;
233*/
234 return;
235
236done:
237 dp->b_forw = NULL;
238 if(hptab.b_actf == NULL)
239 hptab.b_actf = dp; else
240 hptab.b_actl->b_forw = dp;
241 hptab.b_actl = dp;
242}
243
244hpstart()
245{
246 register struct buf *bp, *dp;
247 register unit;
248 register struct device *hpaddr;
249 daddr_t bn;
250 int dn, sn, tn, cn, nspc, ns;
251
252loop:
253 if ((dp = hptab.b_actf) == NULL)
254 return;
255 if ((bp = dp->b_actf) == NULL) {
256 hptab.b_actf = dp->b_forw;
257 goto loop;
258 }
259 hptab.b_active++;
260 unit = minor(bp->b_dev) & 077;
261 dn = dkunit(bp);
262 bn = dkblock(bp);
263 if (hp_type[dn] == RM) {
264 nspc = NRMSECT*NRMTRAC;
265 ns = NRMSECT;
266 cn = rm_sizes[unit&07].cyloff;
267 } else {
268 nspc = NSECT*NTRAC;
269 ns = NSECT;
270 cn = hp_sizes[unit&07].cyloff;
271 }
272 cn += bn/nspc;
273 sn = bn%nspc;
274 tn = sn/ns;
275 sn = sn%ns;
276
277 hpaddr = (struct device *)((int *)HPADDR + 32*dn);
278 if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL)) {
279 hptab.b_active = 0;
280 hptab.b_errcnt = 0;
281 dp->b_actf = bp->av_forw;
282 bp->b_flags |= B_ERROR;
283 iodone(bp);
284 goto loop;
285 }
286 if(hptab.b_errcnt >= 16) {
287 hpaddr->hpof = hp_offset[hptab.b_errcnt & 017] | FMT22;
288 ((struct mba_regs *)MBA0)->mba_cr &= ~MBAIE;
289 hpaddr->hpcs1 = OFFSET|GO;
290 while(hpaddr->hpds & PIP)
291 ;
292 ((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
293 }
294 hpaddr->hpdc = cn;
295 hpaddr->hpda = (tn << 8) + sn;
296 mbastart(bp, (int *)hpaddr);
297
298 dk_busy |= 1<<(DK_N /*+NHP*/);
299 dk_numb[DK_N /*+NHP*/] += 1;
300 unit = bp->b_bcount>>6;
301 dk_wds[DK_N /*+NHP*/] += unit;
302}
303
304hpintr(mbastat, as)
305{
306 register struct buf *bp, *dp;
307 register unit;
308 register struct device *hpaddr;
309
310 if(hptab.b_active) {
311 dk_busy &= ~(1<<(DK_N /*+NHP*/));
312 dp = hptab.b_actf;
313 bp = dp->b_actf;
314 unit = dkunit(bp);
315 hpaddr = (struct device *)((int *)HPADDR + 32*unit);
316 if (hpaddr->hpds & ERR || mbastat & MBAEBITS) { /* error bit */
317 while((hpaddr->hpds & DRY) == 0)
318 ;
319 if(++hptab.b_errcnt > 28 || hpaddr->hper1&WLE)
320 bp->b_flags |= B_ERROR; else
321 hptab.b_active = 0;
322 if(hptab.b_errcnt > 27)
323 deverror(bp, mbastat, hpaddr->hper1);
324 if ((hpaddr->hper1&0xffff) == DCK) {
325 if (hpecc(hpaddr, bp))
326 return;
327 }
328 hpaddr->hpcs1 = DCLR|GO;
329 if((hptab.b_errcnt&07) == 4) {
330 ((struct mba_regs *)MBA0)->mba_cr &= ~MBAIE;
331 hpaddr->hpcs1 = RECAL|GO;
332 while(hpaddr->hpds & PIP)
333 ;
334 ((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
335 }
336 }
337 if(hptab.b_active) {
338 if(hptab.b_errcnt) {
339 ((struct mba_regs *)MBA0)->mba_cr &= ~MBAIE;
340 hpaddr->hpcs1 = RTC|GO;
341 while(hpaddr->hpds & PIP)
342 ;
343 ((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
344 }
345 hptab.b_active = 0;
346 hptab.b_errcnt = 0;
347 hptab.b_actf = dp->b_forw;
348 dp->b_active = 0;
349 dp->b_errcnt = 0;
350 dp->b_actf = bp->av_forw;
351 bp->b_resid = -(((struct mba_regs *)MBA0)->mba_bcr) & 0xffff;
352 iodone(bp);
353 if(dp->b_actf)
354 hpustart(unit);
355 }
356 as &= ~(1<<unit);
357 } else {
358 if(as == 0)
359 ((struct mba_regs *)MBA0)->mba_cr |= MBAIE;
360 }
361 for(unit=0; unit<NHP; unit++)
362 if(as & (1<<unit))
363 hpustart(unit);
364 hpstart();
365}
366
367hpread(dev)
368{
369
370 physio(hpstrategy, &rhpbuf, dev, B_READ, minphys);
371}
372
373hpwrite(dev)
374{
375
376 physio(hpstrategy, &rhpbuf, dev, B_WRITE, minphys);
377}
378
379hpecc(rp, bp)
380register struct device *rp;
381register struct buf *bp;
382{
383 register i;
384 register b, n, map, mix;
385 register char *cp;
386 register mask;
387 short piget();
5f3edb0e 388 extern char buffers[NBUF][BSIZE];
04b9d53d
BJ
389
390 b = (((((struct mba_regs *)MBA0)->mba_bcr&0xffff) +
391 (bp->b_bcount) - 1)>>9)&0177;
392 printf("%D ", bp->b_blkno+b);
393 prdev("ECC", bp->b_dev);
394 mask = rp->hpec2&0xffff;
395 if (mask == 0) {
396 rp->hpof = FMT22;
397 return(0);
398 }
399 i = (rp->hpec1&0xffff) - 1;
400 n = i&017;
401 i = (i&~017)>>3;
402 if (bp->b_flags&B_PHYS)
403 map = 128 + b;
404 else
405 map = ((bp->b_un.b_addr - (char *)buffers)>>9) + b;
406 mix = i + ((int)bp->b_un.b_addr&0x1ff);
407 i += b<<9;
408 if ( i < bp->b_bcount) {
409 cp = (char *)((((int *)MBA0_MAP)[map+(mix>>9)]&0x1fffff)<<9)+(mix&0x1ff);
410 piput((int)cp,piget((int)cp)^(mask<<n));
411 }
412 mix += 2;
413 i += 2;
414 if (i < bp->b_bcount) {
415 cp = (char *)((((int *)MBA0_MAP)[map+(mix>>9)]&0x1fffff)<<9)+(mix&0x1ff);
416 piput((int)cp,piget((int)cp)^(mask>>(16-n)));
417 }
418 hptab.b_active++;
419 if (((struct mba_regs *)MBA0)->mba_bcr) {
420 i = bp->b_blkno%(NSECT*NTRAC);
421 i = ((i/NSECT)<<8)+(i%NSECT);
422 i = NSECT*(i>>8) + (i&0377) + b + 1;
423 if (i >= NSECT*NTRAC) {
424 i -= NSECT*NTRAC;
425 rp->hpdc = bp->b_cylin + 1;
426 } else
427 rp->hpdc = bp->b_cylin;
428 rp->hpda = ((i/NSECT)<<8) + (i%NSECT);
429 rp->hpcs1 = DCLR|GO;
430 ((struct mba_regs *)MBA0)->mba_sr = -1;
431 ((struct mba_regs *)MBA0)->mba_var =
432 ((map+1)<<9)|((int)bp->b_un.b_addr&0x1ff);
433 rp->hpcs1 = RCOM|GO;
434 return(1);
435 } else
436 return(0);
437}
438
439short
440piget(pad)
441{
442 register b, savemap;
443 register short s;
444
445 savemap = (int)mmap;
446 b = (pad>>9)&0x7fffff;
447 *(int *)mmap = b|(PG_V|PG_KR);
448 mtpr(TBIS, vmmap);
449 s = *(short *)&vmmap[pad&0x1ff];
450 *(int *)mmap = savemap;
451 mtpr(TBIS, vmmap);
452 return(s);
453}
454
455piput(pad, val)
456{
457 register b, savemap;
458 register short *p;
459
460 savemap = (int)mmap;
461 b = (pad>>9)&0x7fffff;
462 *(int *)mmap = b|(PG_V|PG_KW);
463 mtpr(TBIS, vmmap);
464 p = (short *)&vmmap[pad&0x1ff];
465 *p = val;
466 *(int *)mmap = savemap;
467 mtpr(TBIS, vmmap);
468}