Commit | Line | Data |
---|---|---|
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 | ||
21 | struct 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 | ||
53 | int hpSDIST = _hpSDIST; | |
54 | int hpRDIST = _hpRDIST; | |
55 | int hpseek; | |
04b9d53d BJ |
56 | |
57 | struct 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 | |
96 | int 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 | ||
104 | struct buf hptab; | |
105 | struct buf rhpbuf; | |
106 | struct buf hputab[NHP]; | |
107 | char 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 | |
136 | daddr_t dkblock(); | |
137 | #endif | |
138 | ||
139 | hpstrategy(bp) | |
140 | register 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 | ||
184 | hpustart(unit) | |
185 | register 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 | ||
234 | search: | |
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 | ||
249 | done: | |
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 | ||
257 | hpstart() | |
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 | ||
265 | loop: | |
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 | ||
317 | hpintr(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 | ||
380 | hpread(dev) | |
381 | { | |
382 | ||
383 | physio(hpstrategy, &rhpbuf, dev, B_READ, minphys); | |
384 | } | |
385 | ||
386 | hpwrite(dev) | |
387 | { | |
388 | ||
389 | physio(hpstrategy, &rhpbuf, dev, B_WRITE, minphys); | |
390 | } | |
391 | ||
392 | hpecc(rp, bp) | |
393 | register struct device *rp; | |
394 | register 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 | ||
452 | short | |
453 | piget(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 | ||
468 | piput(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 | } |