Commit | Line | Data |
---|---|---|
736772ef | 1 | /* hp.c 4.14 81/02/25 */ |
04b9d53d | 2 | |
66b4fb09 | 3 | #include "hp.h" |
a5cc519e | 4 | #if NHP > 0 |
04b9d53d | 5 | /* |
804f6eab | 6 | * HP disk driver for RP0x+RM0x |
04b9d53d BJ |
7 | */ |
8 | ||
9 | #include "../h/param.h" | |
10 | #include "../h/systm.h" | |
41888f16 | 11 | #include "../h/dk.h" |
04b9d53d BJ |
12 | #include "../h/buf.h" |
13 | #include "../h/conf.h" | |
14 | #include "../h/dir.h" | |
15 | #include "../h/user.h" | |
16 | #include "../h/map.h" | |
80e7c811 | 17 | #include "../h/pte.h" |
04b9d53d BJ |
18 | #include "../h/mba.h" |
19 | #include "../h/mtpr.h" | |
80e7c811 | 20 | #include "../h/vm.h" |
e3b4b145 | 21 | #include "../h/cmap.h" |
04b9d53d | 22 | |
b81fd3e8 | 23 | #include "../h/hpreg.h" |
04b9d53d | 24 | |
b81fd3e8 BJ |
25 | /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ |
26 | struct size { | |
04b9d53d BJ |
27 | daddr_t nblocks; |
28 | int cyloff; | |
b81fd3e8 | 29 | } hp_sizes[8] = { |
5c777efe BJ |
30 | 15884, 0, /* A=cyl 0 thru 37 */ |
31 | 33440, 38, /* B=cyl 38 thru 117 */ | |
32 | 340670, 0, /* C=cyl 0 thru 814 */ | |
04b9d53d | 33 | 0, 0, |
04b9d53d BJ |
34 | 0, 0, |
35 | 0, 0, | |
5c777efe | 36 | 291346, 118, /* G=cyl 118 thru 814 */ |
04b9d53d | 37 | 0, 0, |
04b9d53d | 38 | }, rm_sizes[8] = { |
5c777efe BJ |
39 | 15884, 0, /* A=cyl 0 thru 99 */ |
40 | 33440, 100, /* B=cyl 100 thru 309 */ | |
41 | 131680, 0, /* C=cyl 0 thru 822 */ | |
e3b4b145 | 42 | 2720, 291, |
04b9d53d BJ |
43 | 0, 0, |
44 | 0, 0, | |
5c777efe | 45 | 82080, 310, /* G=cyl 310 thru 822 */ |
04b9d53d | 46 | 0, 0, |
5c777efe BJ |
47 | }, rm5_sizes[8] = { |
48 | 15884, 0, /* A=cyl 0 thru 26 */ | |
49 | 33440, 27, /* B=cyl 27 thru 81 */ | |
50 | 500992, 0, /* C=cyl 0 thru 823 */ | |
51 | 15884, 562, /* D=cyl 562 thru 588 */ | |
52 | 55936, 589, /* E=cyl 589 thru 680 */ | |
53 | 86944, 681, /* F=cyl 681 thru 823 */ | |
54 | 159296, 562, /* G=cyl 562 thru 823 */ | |
55 | 291346, 82, /* H=cyl 82 thru 561 */ | |
b81fd3e8 BJ |
56 | }, rm80_sizes[8] = { |
57 | 15884, 0, /* A=cyl 0 thru 36 */ | |
58 | 33440, 37, /* B=cyl 37 thru 114 */ | |
59 | 242606, 0, /* C=cyl 0 thru 558 */ | |
60 | 0, 0, | |
61 | 0, 0, | |
62 | 0, 0, | |
63 | 82080, 115, /* G=cyl 115 thru 304 */ | |
64 | 110236, 305, /* H=cyl 305 thru 558 */ | |
04b9d53d | 65 | }; |
b81fd3e8 | 66 | /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ |
04b9d53d | 67 | |
b81fd3e8 BJ |
68 | #define _hpSDIST 2 |
69 | #define _hpRDIST 3 | |
70 | ||
71 | int hpSDIST = _hpSDIST; | |
72 | int hpRDIST = _hpRDIST; | |
73 | ||
74 | short hptypes[] = | |
75 | { MBDT_RM03, MBDT_RM05, MBDT_RP06, MBDT_RM80, 0 }; | |
76 | struct mba_info *hpinfo[NHP]; | |
77 | int hpdkinit(),hpustart(),hpstart(),hpdtint(); | |
78 | struct mba_driver hpdriver = | |
79 | { hpdkinit, hpustart, hpstart, hpdtint, 0, hptypes, hpinfo }; | |
80 | ||
81 | struct hpst { | |
82 | short nsect; | |
83 | short ntrak; | |
84 | short nspc; | |
85 | short ncyl; | |
86 | struct size *sizes; | |
87 | } hpst[] = { | |
88 | 32, 5, 32*5, 823, rm_sizes, /* RM03 */ | |
89 | 32, 19, 32*19, 823, rm5_sizes, /* RM05 */ | |
90 | 22, 19, 22*19, 815, hp_sizes, /* RP06 */ | |
91 | 31, 14, 31*14, 559, rm80_sizes /* RM80 */ | |
92 | }; | |
93 | ||
804f6eab BJ |
94 | u_char hp_offset[16] = { |
95 | HP_P400, HP_M400, HP_P400, HP_M400, HP_P800, HP_M800, HP_P800, HP_M800, | |
96 | HP_P1200, HP_M1200, HP_P1200, HP_M1200, 0, 0, 0, 0, | |
04b9d53d BJ |
97 | }; |
98 | ||
804f6eab | 99 | struct buf rhpbuf[NHP]; |
04b9d53d BJ |
100 | |
101 | #define b_cylin b_resid | |
102 | ||
103 | #ifdef INTRLVE | |
104 | daddr_t dkblock(); | |
105 | #endif | |
106 | ||
71236e46 BJ |
107 | int hpseek; |
108 | ||
109 | hpdkinit(mi) | |
110 | struct mba_info *mi; | |
111 | { | |
112 | register struct hpst *st = &hpst[mi->mi_type]; | |
113 | ||
114 | if (mi->mi_dk >= 0) | |
115 | dk_mspw[mi->mi_dk] = 1.0 / HZ / (st->nsect * 256); | |
116 | } | |
117 | ||
04b9d53d | 118 | hpstrategy(bp) |
b81fd3e8 | 119 | register struct buf *bp; |
04b9d53d | 120 | { |
b81fd3e8 BJ |
121 | register struct mba_info *mi; |
122 | register struct hpst *st; | |
123 | register int unit; | |
04b9d53d | 124 | long sz, bn; |
b81fd3e8 | 125 | int xunit = minor(bp->b_dev) & 07; |
04b9d53d | 126 | |
04b9d53d BJ |
127 | sz = bp->b_bcount; |
128 | sz = (sz+511) >> 9; | |
129 | unit = dkunit(bp); | |
b81fd3e8 BJ |
130 | if (unit >= NHP) |
131 | goto bad; | |
132 | mi = hpinfo[unit]; | |
3f3a34c3 | 133 | if (mi == 0 || mi->mi_alive == 0) |
b81fd3e8 BJ |
134 | goto bad; |
135 | st = &hpst[mi->mi_type]; | |
136 | if (bp->b_blkno < 0 || | |
137 | (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) | |
138 | goto bad; | |
139 | bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; | |
81263dba | 140 | (void) spl5(); |
b81fd3e8 BJ |
141 | disksort(&mi->mi_tab, bp); |
142 | if (mi->mi_tab.b_active == 0) | |
143 | mbustart(mi); | |
81263dba | 144 | (void) spl0(); |
b81fd3e8 BJ |
145 | return; |
146 | ||
147 | bad: | |
148 | bp->b_flags |= B_ERROR; | |
149 | iodone(bp); | |
150 | return; | |
04b9d53d BJ |
151 | } |
152 | ||
b81fd3e8 BJ |
153 | hpustart(mi) |
154 | register struct mba_info *mi; | |
04b9d53d | 155 | { |
804f6eab | 156 | register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; |
b81fd3e8 BJ |
157 | register struct buf *bp = mi->mi_tab.b_actf; |
158 | register struct hpst *st; | |
04b9d53d | 159 | daddr_t bn; |
b81fd3e8 | 160 | int sn, dist, flags; |
04b9d53d | 161 | |
804f6eab | 162 | if ((hpaddr->hpcs1&HP_DVA) == 0) |
b81fd3e8 | 163 | return (MBU_BUSY); |
804f6eab BJ |
164 | if ((hpaddr->hpds & HP_VV) == 0) { |
165 | hpaddr->hpcs1 = HP_DCLR|HP_GO; | |
166 | hpaddr->hpcs1 = HP_PRESET|HP_GO; | |
167 | hpaddr->hpof = HP_FMT22; | |
04b9d53d | 168 | } |
71236e46 | 169 | if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1) |
b81fd3e8 | 170 | return (MBU_DODATA); |
804f6eab | 171 | if ((hpaddr->hpds & (HP_DPR|HP_MOL)) != (HP_DPR|HP_MOL)) |
b81fd3e8 | 172 | return (MBU_DODATA); |
3f3a34c3 BJ |
173 | st = &hpst[mi->mi_type]; |
174 | bn = dkblock(bp); | |
175 | sn = bn%st->nspc; | |
176 | sn = (sn+st->nsect-hpSDIST)%st->nsect; | |
b81fd3e8 | 177 | if (bp->b_cylin == (hpaddr->hpdc & 0xffff)) { |
71236e46 | 178 | if (hpseek) |
b81fd3e8 | 179 | return (MBU_DODATA); |
b81fd3e8 BJ |
180 | dist = ((hpaddr->hpla & 0xffff)>>6) - st->nsect + 1; |
181 | if (dist < 0) | |
182 | dist += st->nsect; | |
183 | if (dist > st->nsect - hpRDIST) | |
184 | return (MBU_DODATA); | |
0801d37f BJ |
185 | } else |
186 | hpaddr->hpdc = bp->b_cylin; | |
71236e46 | 187 | if (hpseek) |
804f6eab | 188 | hpaddr->hpcs1 = HP_SEEK|HP_GO; |
41888f16 BJ |
189 | else { |
190 | hpaddr->hpda = sn; | |
804f6eab | 191 | hpaddr->hpcs1 = HP_SEARCH|HP_GO; |
41888f16 | 192 | } |
b81fd3e8 | 193 | return (MBU_STARTED); |
04b9d53d BJ |
194 | } |
195 | ||
b81fd3e8 BJ |
196 | hpstart(mi) |
197 | register struct mba_info *mi; | |
04b9d53d | 198 | { |
804f6eab | 199 | register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; |
b81fd3e8 BJ |
200 | register struct buf *bp = mi->mi_tab.b_actf; |
201 | register struct hpst *st = &hpst[mi->mi_type]; | |
04b9d53d | 202 | daddr_t bn; |
b81fd3e8 | 203 | int sn, tn; |
04b9d53d | 204 | |
04b9d53d | 205 | bn = dkblock(bp); |
b81fd3e8 BJ |
206 | sn = bn%st->nspc; |
207 | tn = sn/st->nsect; | |
3f3a34c3 | 208 | sn %= st->nsect; |
b81fd3e8 | 209 | if (mi->mi_tab.b_errcnt >= 16 && (bp->b_flags&B_READ) != 0) { |
804f6eab BJ |
210 | hpaddr->hpof = hp_offset[mi->mi_tab.b_errcnt & 017] | HP_FMT22; |
211 | hpaddr->hpcs1 = HP_OFFSET|HP_GO; | |
212 | while (hpaddr->hpds & HP_PIP) | |
04b9d53d | 213 | ; |
b81fd3e8 | 214 | mbclrattn(mi); |
04b9d53d | 215 | } |
b81fd3e8 | 216 | hpaddr->hpdc = bp->b_cylin; |
04b9d53d | 217 | hpaddr->hpda = (tn << 8) + sn; |
04b9d53d BJ |
218 | } |
219 | ||
736772ef | 220 | hpdtint(mi, mbasr) |
b81fd3e8 | 221 | register struct mba_info *mi; |
736772ef | 222 | int mbasr; |
04b9d53d | 223 | { |
804f6eab | 224 | register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; |
b81fd3e8 BJ |
225 | register struct buf *bp = mi->mi_tab.b_actf; |
226 | ||
804f6eab | 227 | while ((hpaddr->hpds & HP_DRY) == 0) /* shouldn't happen */ |
b81fd3e8 | 228 | printf("hp dry not set\n"); |
736772ef | 229 | if (hpaddr->hpds & HP_ERR || mbasr & MBAEBITS) |
804f6eab BJ |
230 | if (++mi->mi_tab.b_errcnt < 28 && (hpaddr->hper1&HP_WLE) == 0) { |
231 | if ((hpaddr->hper1&0xffff) != HP_DCK) { | |
232 | hpaddr->hpcs1 = HP_DCLR|HP_GO; | |
b81fd3e8 | 233 | if ((mi->mi_tab.b_errcnt&07) == 4) { |
804f6eab BJ |
234 | hpaddr->hpcs1 = HP_RECAL|HP_GO; |
235 | while (hpaddr->hpds & HP_PIP) | |
b81fd3e8 BJ |
236 | ; |
237 | mbclrattn(mi); | |
238 | } | |
239 | return (MBD_RETRY); | |
240 | } else if (hpecc(mi)) | |
241 | return (MBD_RESTARTED); | |
242 | } else { | |
048a27b2 BJ |
243 | if (hpaddr->hper1&HP_WLE) |
244 | printf("hp%d is write locked\n", dkunit(bp)); | |
245 | else | |
736772ef BJ |
246 | harderr(bp); |
247 | printf("hp%d mbasr %b er1 %b er2 %b\n", | |
248 | dkunit(bp), mbasr, mbasr_bits, | |
249 | hpaddr->hper1, HPER1_BITS, | |
250 | hpaddr->hper2, HPER2_BITS); | |
251 | hpaddr->hpcs1 = HP_DCLR|HP_GO; | |
b81fd3e8 | 252 | bp->b_flags |= B_ERROR; |
04b9d53d | 253 | } |
b81fd3e8 BJ |
254 | bp->b_resid = -(mi->mi_mba->mba_bcr) & 0xffff; |
255 | if (mi->mi_tab.b_errcnt) { | |
804f6eab BJ |
256 | hpaddr->hpcs1 = HP_RTC|HP_GO; |
257 | while (hpaddr->hpds & HP_PIP) | |
b81fd3e8 BJ |
258 | ; |
259 | mbclrattn(mi); | |
04b9d53d | 260 | } |
804f6eab | 261 | hpaddr->hpcs1 = HP_RELEASE|HP_GO; |
b81fd3e8 | 262 | return (MBD_DONE); |
04b9d53d BJ |
263 | } |
264 | ||
265 | hpread(dev) | |
804f6eab | 266 | dev_t dev; |
04b9d53d | 267 | { |
804f6eab | 268 | register int unit = minor(dev) >> 3; |
04b9d53d | 269 | |
804f6eab BJ |
270 | if (unit >= NHP) |
271 | u.u_error = ENXIO; | |
272 | else | |
273 | physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys); | |
04b9d53d BJ |
274 | } |
275 | ||
276 | hpwrite(dev) | |
804f6eab | 277 | dev_t dev; |
04b9d53d | 278 | { |
804f6eab | 279 | register int unit = minor(dev) >> 3; |
04b9d53d | 280 | |
804f6eab BJ |
281 | if (unit >= NHP) |
282 | u.u_error = ENXIO; | |
283 | else | |
284 | physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys); | |
04b9d53d BJ |
285 | } |
286 | ||
b81fd3e8 BJ |
287 | hpecc(mi) |
288 | register struct mba_info *mi; | |
04b9d53d | 289 | { |
b81fd3e8 | 290 | register struct mba_regs *mbp = mi->mi_mba; |
804f6eab | 291 | register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv; |
b81fd3e8 BJ |
292 | register struct buf *bp = mi->mi_tab.b_actf; |
293 | register struct hpst *st; | |
80e7c811 BJ |
294 | register int i; |
295 | caddr_t addr; | |
296 | int reg, bit, byte, npf, mask, o; | |
b81fd3e8 | 297 | int bn, cn, tn, sn; |
80e7c811 | 298 | struct pte mpte; |
fa1d69d6 | 299 | int bcr; |
80e7c811 | 300 | |
fa1d69d6 BJ |
301 | bcr = mbp->mba_bcr & 0xffff; |
302 | if (bcr) | |
303 | bcr |= 0xffff0000; /* sxt */ | |
acecdc5c | 304 | npf = btop(bcr + bp->b_bcount) - 1; |
f9b6e695 | 305 | reg = npf; |
80e7c811 BJ |
306 | o = (int)bp->b_un.b_addr & PGOFSET; |
307 | printf("%D ", bp->b_blkno + npf); | |
04b9d53d BJ |
308 | prdev("ECC", bp->b_dev); |
309 | mask = rp->hpec2&0xffff; | |
310 | if (mask == 0) { | |
804f6eab | 311 | rp->hpof = HP_FMT22; |
80e7c811 | 312 | return (0); |
04b9d53d | 313 | } |
80e7c811 | 314 | |
80e7c811 | 315 | i = (rp->hpec1&0xffff) - 1; /* -1 makes 0 origin */ |
acecdc5c | 316 | bit = i&07; |
80e7c811 BJ |
317 | i = (i&~07)>>3; |
318 | byte = i + o; | |
80e7c811 BJ |
319 | while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { |
320 | mpte = mbp->mba_map[reg+btop(byte)]; | |
321 | addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET); | |
322 | putmemc(addr, getmemc(addr)^(mask<<bit)); | |
323 | byte++; | |
324 | i++; | |
325 | bit -= 8; | |
04b9d53d | 326 | } |
b81fd3e8 | 327 | mi->mi_hd->mh_active++; /* Either complete or continuing */ |
acecdc5c | 328 | if (bcr == 0) |
80e7c811 | 329 | return (0); |
804f6eab BJ |
330 | #ifdef notdef |
331 | rp->hper1 = 0; | |
332 | rp->hpcs1 = HP_RCOM|HP_GO; | |
333 | #else | |
334 | rp->hpcs1 = HP_DCLR|HP_GO; | |
80e7c811 | 335 | bn = dkblock(bp); |
b81fd3e8 | 336 | st = &hpst[mi->mi_type]; |
80e7c811 | 337 | cn = bp->b_cylin; |
b81fd3e8 BJ |
338 | sn = bn%(st->nspc) + npf + 1; |
339 | tn = sn/st->nsect; | |
340 | sn %= st->nsect; | |
341 | cn += tn/st->ntrak; | |
342 | tn %= st->ntrak; | |
80e7c811 BJ |
343 | rp->hpdc = cn; |
344 | rp->hpda = (tn<<8) + sn; | |
345 | mbp->mba_sr = -1; | |
346 | mbp->mba_var = (int)ptob(reg+1) + o; | |
804f6eab BJ |
347 | rp->hpcs1 = HP_RCOM|HP_GO; |
348 | #endif | |
80e7c811 | 349 | return (1); |
04b9d53d | 350 | } |
e3b4b145 BJ |
351 | |
352 | #define DBSIZE 20 | |
353 | ||
354 | hpdump(dev) | |
355 | dev_t dev; | |
356 | { | |
b81fd3e8 BJ |
357 | register struct mba_info *mi; |
358 | register struct mba_regs *mba; | |
804f6eab | 359 | struct hpdevice *hpaddr; |
e3b4b145 | 360 | char *start; |
b81fd3e8 BJ |
361 | int num, unit; |
362 | register struct hpst *st; | |
e3b4b145 BJ |
363 | |
364 | num = maxfree; | |
365 | start = 0; | |
366 | unit = minor(dev) >> 3; | |
367 | if (unit >= NHP) { | |
368 | printf("bad unit\n"); | |
369 | return (-1); | |
370 | } | |
b81fd3e8 BJ |
371 | #define phys(a,b) ((b)((int)(a)&0x7fffffff)) |
372 | mi = phys(hpinfo[unit],struct mba_info *); | |
804f6eab | 373 | if (mi == 0 || mi->mi_alive == 0) { |
b81fd3e8 BJ |
374 | printf("dna\n"); |
375 | return (-1); | |
376 | } | |
377 | mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; | |
378 | mba->mba_cr = MBAINIT; | |
804f6eab BJ |
379 | hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive]; |
380 | if ((hpaddr->hpds & HP_VV) == 0) { | |
381 | hpaddr->hpcs1 = HP_DCLR|HP_GO; | |
382 | hpaddr->hpcs1 = HP_PRESET|HP_GO; | |
383 | hpaddr->hpof = HP_FMT22; | |
e3b4b145 | 384 | } |
b81fd3e8 BJ |
385 | st = &hpst[mi->mi_type]; |
386 | if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks) { | |
387 | printf("oor\n"); | |
e3b4b145 BJ |
388 | return (-1); |
389 | } | |
e3b4b145 | 390 | while (num > 0) { |
b81fd3e8 | 391 | register struct pte *hpte = mba->mba_map; |
e3b4b145 | 392 | register int i; |
b81fd3e8 | 393 | int blk, cn, sn, tn; |
e3b4b145 BJ |
394 | daddr_t bn; |
395 | ||
396 | blk = num > DBSIZE ? DBSIZE : num; | |
397 | bn = dumplo + btop(start); | |
b81fd3e8 BJ |
398 | cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff; |
399 | sn = bn%st->nspc; | |
400 | tn = sn/st->nsect; | |
401 | sn = sn%st->nsect; | |
e3b4b145 BJ |
402 | hpaddr->hpdc = cn; |
403 | hpaddr->hpda = (tn << 8) + sn; | |
404 | for (i = 0; i < blk; i++) | |
405 | *(int *)hpte++ = (btop(start)+i) | PG_V; | |
b81fd3e8 BJ |
406 | mba->mba_sr = -1; |
407 | mba->mba_bcr = -(blk*NBPG); | |
408 | mba->mba_var = 0; | |
804f6eab BJ |
409 | hpaddr->hpcs1 = HP_WCOM | HP_GO; |
410 | while ((hpaddr->hpds & HP_DRY) == 0) | |
e3b4b145 | 411 | ; |
804f6eab | 412 | if (hpaddr->hpds&HP_ERR) { |
b81fd3e8 | 413 | printf("dskerr: (%d,%d,%d) ds=%x er=%x\n", |
e3b4b145 BJ |
414 | cn, tn, sn, hpaddr->hpds, hpaddr->hper1); |
415 | return (-1); | |
416 | } | |
417 | start += blk*NBPG; | |
418 | num -= blk; | |
419 | } | |
420 | return (0); | |
421 | } | |
a5cc519e | 422 | #endif |