Commit | Line | Data |
---|---|---|
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 | ||
20 | struct 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 | ||
51 | struct 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 | |
90 | int 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 | ||
98 | struct buf hptab; | |
99 | struct buf rhpbuf; | |
100 | struct buf hputab[NHP]; | |
101 | char 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 | |
129 | daddr_t dkblock(); | |
130 | #endif | |
131 | ||
132 | hpstrategy(bp) | |
133 | register 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 | ||
177 | hpustart(unit) | |
178 | register 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 | ||
225 | search: | |
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 | ||
236 | done: | |
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 | ||
244 | hpstart() | |
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 | ||
252 | loop: | |
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 | ||
304 | hpintr(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 | ||
367 | hpread(dev) | |
368 | { | |
369 | ||
370 | physio(hpstrategy, &rhpbuf, dev, B_READ, minphys); | |
371 | } | |
372 | ||
373 | hpwrite(dev) | |
374 | { | |
375 | ||
376 | physio(hpstrategy, &rhpbuf, dev, B_WRITE, minphys); | |
377 | } | |
378 | ||
379 | hpecc(rp, bp) | |
380 | register struct device *rp; | |
381 | register 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 | ||
439 | short | |
440 | piget(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 | ||
455 | piput(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 | } |