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