all nonexistent slaves aren't on formatter 0!
[unix-history] / usr / src / sys / vax / mba / hp.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
f62a5b87 6 * @(#)hp.c 7.5 (Berkeley) %G%
da7c5cc6 7 */
b70e4030
BJ
8
9#ifdef HPDEBUG
6ac24ecd 10int hpdebug;
b70e4030
BJ
11#endif
12#ifdef HPBDEBUG
13int hpbdebug;
14#endif
04b9d53d 15
66b4fb09 16#include "hp.h"
a5cc519e 17#if NHP > 0
04b9d53d 18/*
b19f1d3a 19 * HP disk driver for RP0x+RMxx+ML11
1b81ee79
BJ
20 *
21 * TODO:
b70e4030 22 * see if DCLR and/or RELEASE set attention status
04b9d53d 23 */
969e52ef
JB
24#include "param.h"
25#include "systm.h"
a4a97100 26#include "dkstat.h"
969e52ef
JB
27#include "buf.h"
28#include "conf.h"
29#include "dir.h"
a4a97100 30#include "file.h"
969e52ef
JB
31#include "user.h"
32#include "map.h"
c895c266 33#include "../vax/mtpr.h"
969e52ef
JB
34#include "vm.h"
35#include "cmap.h"
36#include "dkbad.h"
a4a97100 37#include "disklabel.h"
969e52ef
JB
38#include "ioctl.h"
39#include "uio.h"
6943fe60 40#include "syslog.h"
41a38591 41#include "stat.h"
04b9d53d 42
41a38591 43#include "../machine/pte.h"
f13af4da 44#include "../vax/dkio.h"
969e52ef
JB
45#include "mbareg.h"
46#include "mbavar.h"
47#include "hpreg.h"
04b9d53d 48
a4a97100
MK
49#define COMPAT_42
50#define B_FORMAT B_XXX
04b9d53d 51
822a683f 52/*
a4a97100
MK
53 * Table of supported Massbus drive types.
54 * When using unlabeled packs, slot numbers here
55 * are used as indices into the partition tables.
56 * Slots are left for those drives divined from other means
822a683f
SL
57 * (e.g. SI, AMPEX, etc.).
58 */
59short hptypes[] = {
60#define HPDT_RM03 0
61 MBDT_RM03,
62#define HPDT_RM05 1
63 MBDT_RM05,
64#define HPDT_RP06 2
65 MBDT_RP06,
66#define HPDT_RM80 3
67 MBDT_RM80,
28b0477e
SL
68#define HPDT_RP04 4
69 MBDT_RP04,
70#define HPDT_RP05 5
822a683f 71 MBDT_RP05,
28b0477e 72#define HPDT_RP07 6
822a683f 73 MBDT_RP07,
28b0477e 74#define HPDT_ML11A 7
822a683f 75 MBDT_ML11A,
28b0477e 76#define HPDT_ML11B 8
822a683f 77 MBDT_ML11B,
28b0477e 78#define HPDT_9775 9
822a683f 79 -1,
28b0477e 80#define HPDT_9730 10
822a683f 81 -1,
28b0477e 82#define HPDT_CAPRICORN 11
822a683f 83 -1,
28b0477e 84#define HPDT_EAGLE 12
e74d4c15 85 -1,
28b0477e 86#define HPDT_9300 13
f68569f0 87 -1,
28b0477e 88#define HPDT_RM02 14
e6cb5212
MK
89 MBDT_RM02, /* beware, actually mapped */
90#define HPDT_2361 15
91 -1,
822a683f
SL
92 0
93};
a4a97100 94
4a4e3072 95struct mba_device *hpinfo[NHP];
41a38591 96int hpattach(),hpustart(),hpstart(),hpdtint(),hpstrategy();
b81fd3e8 97struct mba_driver hpdriver =
4a4e3072
BJ
98 { hpattach, 0, hpustart, hpstart, hpdtint, 0,
99 hptypes, "hp", 0, hpinfo };
b81fd3e8 100
804f6eab 101u_char hp_offset[16] = {
d565635a
BJ
102 HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400,
103 HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800,
104 HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200,
105 0, 0, 0, 0,
04b9d53d
BJ
106};
107
804f6eab 108struct buf rhpbuf[NHP];
a4a97100 109struct disklabel hplabel[NHP];
b70e4030 110struct dkbad hpbad[NHP];
c983ca83
SL
111
112struct hpsoftc {
c983ca83 113 u_char sc_recal; /* recalibrate state */
c983ca83 114 u_char sc_doseeks; /* perform explicit seeks */
a4a97100
MK
115 int sc_state; /* open fsm */
116 long sc_openpart; /* bit mask of open subunits */
41a38591
MK
117 long sc_copenpart; /* bit mask of open character subunits */
118 long sc_bopenpart; /* bit mask of open block subunits */
c983ca83 119 daddr_t sc_mlsize; /* ML11 size */
5c93d6ba 120 int sc_blkdone; /* amount sucessfully transfered */
e0d48442 121 daddr_t sc_badbn; /* replacement block number */
c983ca83 122} hpsoftc[NHP];
04b9d53d 123
a4a97100
MK
124/*
125 * Drive states. Used during steps of open/initialization.
126 * States < OPEN (> 0) are transient, during an open operation.
127 * OPENRAW is used for unlabeled disks,
128 * to inhibit bad-sector forwarding or allow format operations.
129 */
130#define CLOSED 0 /* disk is closed. */
131#define WANTOPEN 1 /* open requested, not started */
132#define WANTOPENRAW 2 /* open requested, no label */
133#define RDLABEL 3 /* reading pack label */
134#define RDBADTBL 4 /* reading bad-sector table */
135#define OPEN 5 /* initialized and ready */
136#define OPENRAW 6 /* open, no label or badsect */
137
04b9d53d
BJ
138#define b_cylin b_resid
139
b19f1d3a 140/* #define ML11 0 to remove ML11 support */
a4a97100
MK
141#define ML11(type) ((type) == HPDT_ML11A)
142#define RP06(type) (hptypes[type] <= MBDT_RP06)
143#define RM80(type) ((type) == HPDT_RM80)
b19f1d3a 144
99f676cf 145#define hpunit(dev) (minor(dev) >> 3)
a4a97100
MK
146#define hppart(dev) (minor(dev) & 07)
147#define hpminor(unit, part) (((unit) << 3) | (part))
148
0be277a1 149#define MASKREG(reg) ((reg)&0xffff)
8011f5df
MK
150#ifdef lint
151#define HPWAIT(mi, addr) (hpwait(mi))
152#else
6943fe60 153#define HPWAIT(mi, addr) (((addr)->hpds & HPDS_DRY) || hpwait(mi))
8011f5df 154#endif
0be277a1 155
4a4e3072
BJ
156/*ARGSUSED*/
157hpattach(mi, slave)
a4a97100 158 struct mba_device *mi;
71236e46 159{
a4a97100 160 register int unit = mi->mi_unit;
822a683f 161
a4a97100
MK
162 /*
163 * Try to initialize device and read pack label.
164 */
165 if (hpinit(hpminor(unit, 0), 0) == 0) {
54c92e75 166 printf(": %s", hplabel[unit].d_typename);
a4a97100
MK
167#ifdef notyet
168 addswap(makedev(HPMAJOR, hpminor(unit, 0)), &hplabel[unit]);
169#endif
170 } else
54c92e75 171 printf(": offline");
2be84ab1
SL
172}
173
41a38591 174hpopen(dev, flags, fmt)
a4a97100 175 dev_t dev;
41a38591 176 int flags, fmt;
2be84ab1 177{
a4a97100
MK
178 register int unit = hpunit(dev);
179 register struct hpsoftc *sc;
180 register struct disklabel *lp;
181 register struct partition *pp;
182 struct mba_device *mi;
41a38591 183 int s, error, part = hppart(dev), mask = 1 << part;
a4a97100
MK
184 daddr_t start, end;
185
186 if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0)
187 return (ENXIO);
188 sc = &hpsoftc[unit];
189 lp = &hplabel[unit];
822a683f 190
a4a97100
MK
191 s = spl5();
192 while (sc->sc_state != OPEN && sc->sc_state != OPENRAW &&
193 sc->sc_state != CLOSED)
194 sleep ((caddr_t)sc, PZERO+1);
195 splx(s);
196 if (sc->sc_state != OPEN && sc->sc_state != OPENRAW)
197 if (error = hpinit(dev, flags))
198 return (error);
199 if (part >= lp->d_npartitions)
200 return (ENXIO);
822a683f 201 /*
a4a97100
MK
202 * Warn if a partion is opened
203 * that overlaps another partition which is open
204 * unless one is the "raw" partition (whole disk).
822a683f 205 */
a4a97100
MK
206#define RAWPART 2 /* 'c' partition */ /* XXX */
207 if ((sc->sc_openpart & (1 << part)) == 0 &&
208 part != RAWPART) {
209 pp = &lp->d_partitions[part];
210 start = pp->p_offset;
211 end = pp->p_offset + pp->p_size;
212 for (pp = lp->d_partitions;
213 pp < &lp->d_partitions[lp->d_npartitions]; pp++) {
214 if (pp->p_offset + pp->p_size <= start ||
215 pp->p_offset >= end)
216 continue;
217 if (pp - lp->d_partitions == RAWPART)
218 continue;
219 if (sc->sc_openpart & (1 << (pp - lp->d_partitions)))
220 log(LOG_WARNING,
221 "hp%d%c: overlaps open partition (%c)\n",
222 unit, part + 'a',
223 pp - lp->d_partitions + 'a');
822a683f 224 }
2be84ab1 225 }
41a38591
MK
226 switch (fmt) {
227 case S_IFCHR:
228 sc->sc_copenpart |= mask;
229 break;
230 case S_IFBLK:
231 sc->sc_bopenpart |= mask;
232 break;
233 }
234 sc->sc_openpart |= mask;
a4a97100
MK
235 return (0);
236}
822a683f 237
41a38591 238hpclose(dev, flags, fmt)
a4a97100 239 dev_t dev;
41a38591 240 int flags, fmt;
a4a97100
MK
241{
242 register int unit = hpunit(dev);
243 register struct hpsoftc *sc;
244 struct mba_device *mi;
41a38591 245 int s, mask = 1 << hppart(dev);
a4a97100
MK
246
247 sc = &hpsoftc[unit];
248 mi = hpinfo[unit];
41a38591
MK
249 switch (fmt) {
250 case S_IFCHR:
251 sc->sc_copenpart &= ~mask;
252 break;
253 case S_IFBLK:
254 sc->sc_bopenpart &= ~mask;
255 break;
256 }
257 if (((sc->sc_copenpart | sc->sc_bopenpart) & mask) == 0)
258 sc->sc_openpart &= ~mask;
822a683f 259 /*
a4a97100
MK
260 * Should wait for I/O to complete on this partition
261 * even if others are open, but wait for work on blkflush().
822a683f 262 */
a4a97100
MK
263 if (sc->sc_openpart == 0) {
264 s = spl5();
a4a97100 265 while (mi->mi_tab.b_actf)
41a38591 266 sleep((caddr_t)sc, PZERO - 1);
a4a97100
MK
267 splx(s);
268 sc->sc_state = CLOSED;
269 }
41a38591 270 return (0);
a4a97100 271}
2be84ab1 272
a4a97100
MK
273hpinit(dev, flags)
274 dev_t dev;
275 int flags;
276{
277 register struct hpsoftc *sc;
278 register struct buf *bp;
279 register struct disklabel *lp;
a4a97100
MK
280 struct mba_device *mi;
281 struct hpdevice *hpaddr;
282 struct dkbad *db;
41a38591 283 char *msg, *readdisklabel();
a4a97100 284 int unit, i, error = 0;
54c92e75 285 extern int cold;
e6cb5212 286
a4a97100
MK
287 unit = hpunit(dev);
288 sc = &hpsoftc[unit];
289 lp = &hplabel[unit];
290 mi = hpinfo[unit];
291 hpaddr = (struct hpdevice *)mi->mi_drv;
292
f62a5b87 293 sc->sc_state = WANTOPEN;
a4a97100
MK
294 /*
295 * Use the default sizes until we've read the label,
296 * or longer if there isn't one there.
297 */
298 lp->d_secsize = DEV_BSIZE;
299 lp->d_nsectors = 32;
300 lp->d_ntracks = 20;
301 lp->d_secpercyl = 32*20;
822a683f 302
f62a5b87
MK
303 if (flags & O_NDELAY)
304 goto raw;
305
2be84ab1
SL
306 /*
307 * Map all ML11's to the same type. Also calculate
308 * transfer rates based on device characteristics.
a4a97100 309 * Set up dummy label with all that's needed.
2be84ab1 310 */
a4a97100 311 if (mi->mi_type == MBDT_ML11A || mi->mi_type == MBDT_ML11B) {
c983ca83
SL
312 register struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
313 register int trt;
b19f1d3a 314
c983ca83 315 sc->sc_mlsize = hpaddr->hpmr & HPMR_SZ;
b19f1d3a 316 if ((hpaddr->hpmr & HPMR_ARRTYP) == 0)
c983ca83 317 sc->sc_mlsize >>= 2;
b19f1d3a
BJ
318 if (mi->mi_dk >= 0) {
319 trt = (hpaddr->hpmr & HPMR_TRT) >> 8;
320 dk_mspw[mi->mi_dk] = 1.0 / (1<<(20-trt));
321 }
a4a97100
MK
322 mi->mi_type = MBDT_ML11A;
323 lp->d_partitions[0].p_size = sc->sc_mlsize;
324 lp->d_secpercyl = sc->sc_mlsize;
f62a5b87 325 goto raw;
b19f1d3a 326 }
71236e46 327
a4a97100
MK
328 /*
329 * Preset, pack acknowledge will be done in hpstart
330 * during first read operation.
331 */
41a38591 332 if (msg = readdisklabel(dev, hpstrategy, lp)) {
54c92e75 333 if (cold)
41a38591 334 printf(": %s", msg);
54c92e75 335 else
41a38591 336 log(LOG_ERR, "hp%d: %s\n", unit, msg);
a4a97100
MK
337#ifdef COMPAT_42
338 mi->mi_type = hpmaptype(mi, lp);
339#else
f62a5b87 340 goto raw;
a4a97100
MK
341#endif
342 }
343
344 /*
345 * Seconds per word = (60 / rpm) / (nsectors * secsize/2)
346 */
347 if (mi->mi_dk >= 0 && lp->d_rpm)
348 dk_mspw[mi->mi_dk] = 120.0 /
349 (lp->d_rpm * lp->d_nsectors * lp->d_secsize);
350 /*
351 * Read bad sector table into memory.
352 */
41a38591
MK
353 bp = geteblk(DEV_BSIZE); /* max sector size */
354 bp->b_dev = dev;
a4a97100
MK
355 sc->sc_state = RDBADTBL;
356 i = 0;
357 do {
358 u.u_error = 0; /* XXX */
359 bp->b_flags = B_BUSY | B_READ;
360 bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i;
361 bp->b_bcount = lp->d_secsize;
362 bp->b_cylin = lp->d_ncylinders - 1;
363 hpstrategy(bp);
364 biowait(bp);
365 } while ((bp->b_flags & B_ERROR) && (i += 2) < 10 &&
366 i < lp->d_nsectors);
367 db = (struct dkbad *)(bp->b_un.b_addr);
368 if ((bp->b_flags & B_ERROR) == 0 && db->bt_mbz == 0 &&
369 db->bt_flag == 0) {
370 hpbad[unit] = *db;
371 sc->sc_state = OPEN;
372 } else {
373 log(LOG_ERR, "hp%d: %s bad-sector file\n", unit,
374 (bp->b_flags & B_ERROR) ? "can't read" : "format error in");
375 u.u_error = 0; /* XXX */
376 sc->sc_state = OPENRAW;
377 }
a4a97100
MK
378 bp->b_flags = B_INVAL | B_AGE;
379 brelse(bp);
41a38591 380done:
a4a97100
MK
381 wakeup((caddr_t)sc);
382 return (error);
f62a5b87
MK
383
384raw:
385 sc->sc_state = OPENRAW;
386 wakeup((caddr_t)sc);
387 return (error);
473a2e47
BJ
388}
389
04b9d53d 390hpstrategy(bp)
b81fd3e8 391 register struct buf *bp;
04b9d53d 392{
4a4e3072 393 register struct mba_device *mi;
a4a97100
MK
394 register struct disklabel *lp;
395 register struct hpsoftc *sc;
b81fd3e8 396 register int unit;
a4a97100
MK
397 daddr_t sz, maxsz;
398 int xunit = hppart(bp->b_dev);
530d0032 399 int s;
04b9d53d 400
a4a97100 401 sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
99f676cf
JB
402 unit = hpunit(bp->b_dev);
403 if (unit >= NHP) {
404 bp->b_error = ENXIO;
b81fd3e8 405 goto bad;
99f676cf 406 }
b81fd3e8 407 mi = hpinfo[unit];
a4a97100
MK
408 sc = &hpsoftc[unit];
409 lp = &hplabel[unit];
99f676cf
JB
410 if (mi == 0 || mi->mi_alive == 0) {
411 bp->b_error = ENXIO;
b81fd3e8 412 goto bad;
99f676cf 413 }
a4a97100
MK
414 if (sc->sc_state < OPEN)
415 goto q;
416 if ((sc->sc_openpart & (1 << xunit)) == 0) {
417 bp->b_error = ENODEV;
418 goto bad;
419 }
420 maxsz = lp->d_partitions[xunit].p_size;
421 if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
422 if (bp->b_blkno == maxsz) {
423 bp->b_resid = bp->b_bcount;
424 goto done;
99f676cf 425 }
a4a97100
MK
426 sz = maxsz - bp->b_blkno;
427 if (sz <= 0) {
99f676cf 428 bp->b_error = EINVAL;
b19f1d3a 429 goto bad;
99f676cf 430 }
a4a97100 431 bp->b_bcount = sz << DEV_BSHIFT;
b19f1d3a 432 }
a4a97100
MK
433 bp->b_cylin = (bp->b_blkno + lp->d_partitions[xunit].p_offset) /
434 lp->d_secpercyl;
435q:
530d0032 436 s = spl5();
b81fd3e8
BJ
437 disksort(&mi->mi_tab, bp);
438 if (mi->mi_tab.b_active == 0)
439 mbustart(mi);
530d0032 440 splx(s);
b81fd3e8
BJ
441 return;
442
443bad:
444 bp->b_flags |= B_ERROR;
99f676cf 445done:
a4a97100 446 biodone(bp);
b81fd3e8 447 return;
04b9d53d
BJ
448}
449
b81fd3e8 450hpustart(mi)
4a4e3072 451 register struct mba_device *mi;
04b9d53d 452{
804f6eab 453 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
b81fd3e8 454 register struct buf *bp = mi->mi_tab.b_actf;
a4a97100 455 register struct disklabel *lp;
c983ca83 456 struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
04b9d53d 457 daddr_t bn;
c5f3bc2a 458 int sn, tn, dist;
04b9d53d 459
a4a97100 460 lp = &hplabel[mi->mi_unit];
b70e4030 461 hpaddr->hpcs1 = 0;
804f6eab 462 if ((hpaddr->hpcs1&HP_DVA) == 0)
b81fd3e8 463 return (MBU_BUSY);
5c93d6ba
MK
464
465 switch (sc->sc_recal) {
466
467 case 1:
8011f5df 468 (void)HPWAIT(mi, hpaddr);
5c93d6ba
MK
469 hpaddr->hpdc = bp->b_cylin;
470 hpaddr->hpcs1 = HP_SEEK|HP_GO;
471 sc->sc_recal++;
472 return (MBU_STARTED);
473 case 2:
474 break;
475 }
476 sc->sc_recal = 0;
a4a97100
MK
477 if ((hpaddr->hpds & HPDS_VV) == 0) {
478 if (sc->sc_state == OPEN && lp->d_flags & D_REMOVABLE) {
479 if (sc->sc_openpart)
480 log(LOG_ERR, "hp%d: volume changed\n",
481 mi->mi_unit);
482 sc->sc_openpart = 0;
483 bp->b_flags |= B_ERROR;
484 return (MBU_NEXT);
485 }
804f6eab 486 hpaddr->hpcs1 = HP_DCLR|HP_GO;
27a897a2
BJ
487 if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive))
488 printf("DCLR attn\n");
804f6eab 489 hpaddr->hpcs1 = HP_PRESET|HP_GO;
a4a97100 490 if (!ML11(mi->mi_type))
b19f1d3a 491 hpaddr->hpof = HPOF_FMT22;
27a897a2 492 mbclrattn(mi);
a4a97100
MK
493 if (sc->sc_state == WANTOPENRAW) {
494 sc->sc_state = OPENRAW;
495 return (MBU_NEXT);
b19f1d3a 496 }
a4a97100
MK
497 if (sc->sc_state == WANTOPEN)
498 sc->sc_state = RDLABEL;
04b9d53d 499 }
5c93d6ba
MK
500 if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1) {
501 if (mi->mi_tab.b_errcnt >= 16 && (bp->b_flags & B_READ)) {
502 hpaddr->hpof =
503 hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22;
504 hpaddr->hpcs1 = HP_OFFSET|HP_GO;
8011f5df 505 (void)HPWAIT(mi, hpaddr);
5c93d6ba
MK
506 mbclrattn(mi);
507 }
b81fd3e8 508 return (MBU_DODATA);
5c93d6ba 509 }
a4a97100 510 if (ML11(mi->mi_type))
b19f1d3a 511 return (MBU_DODATA);
d565635a 512 if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY)
b81fd3e8 513 return (MBU_DODATA);
99f676cf 514 bn = bp->b_blkno;
a4a97100
MK
515 sn = bn % lp->d_secpercyl;
516 tn = sn / lp->d_nsectors;
517 sn = sn % lp->d_nsectors;
0be277a1 518 if (bp->b_cylin == MASKREG(hpaddr->hpdc)) {
5d3fd70b 519 if (sc->sc_doseeks)
b81fd3e8 520 return (MBU_DODATA);
99548a05 521 dist = sn - (MASKREG(hpaddr->hpla) >> 6) - 1;
b81fd3e8 522 if (dist < 0)
a4a97100
MK
523 dist += lp->d_nsectors;
524 if (dist > lp->d_maxdist || dist < lp->d_mindist)
b81fd3e8 525 return (MBU_DODATA);
0801d37f
BJ
526 } else
527 hpaddr->hpdc = bp->b_cylin;
5d3fd70b 528 if (sc->sc_doseeks)
804f6eab 529 hpaddr->hpcs1 = HP_SEEK|HP_GO;
41888f16 530 else {
a4a97100 531 sn = (sn + lp->d_nsectors - lp->d_sdist) % lp->d_nsectors;
c5f3bc2a 532 hpaddr->hpda = (tn << 8) + sn;
804f6eab 533 hpaddr->hpcs1 = HP_SEARCH|HP_GO;
41888f16 534 }
b81fd3e8 535 return (MBU_STARTED);
04b9d53d
BJ
536}
537
b81fd3e8 538hpstart(mi)
4a4e3072 539 register struct mba_device *mi;
04b9d53d 540{
804f6eab 541 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
b81fd3e8 542 register struct buf *bp = mi->mi_tab.b_actf;
a4a97100 543 register struct disklabel *lp = &hplabel[mi->mi_unit];
c983ca83 544 struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
04b9d53d 545 daddr_t bn;
5c93d6ba 546 int sn, tn, cn;
04b9d53d 547
a4a97100 548 if (ML11(mi->mi_type))
5c93d6ba 549 hpaddr->hpda = bp->b_blkno + sc->sc_blkdone;
b19f1d3a 550 else {
5c93d6ba
MK
551 if (bp->b_flags & B_BAD) {
552 bn = sc->sc_badbn;
a4a97100 553 cn = bn / lp->d_secpercyl;
5c93d6ba
MK
554 } else {
555 bn = bp->b_blkno;
556 cn = bp->b_cylin;
557 }
a4a97100 558 sn = bn % lp->d_secpercyl;
5c93d6ba
MK
559 if ((bp->b_flags & B_BAD) == 0)
560 sn += sc->sc_blkdone;
a4a97100
MK
561 tn = sn / lp->d_nsectors;
562 sn %= lp->d_nsectors;
563 cn += tn / lp->d_ntracks;
564 tn %= lp->d_ntracks;
b19f1d3a 565 hpaddr->hpda = (tn << 8) + sn;
5c93d6ba 566 hpaddr->hpdc = cn;
b19f1d3a 567 }
3e3f9c04 568 mi->mi_tab.b_bdone = dbtob(sc->sc_blkdone);
a4a97100 569 if (bp->b_flags & B_FORMAT) {
b19f1d3a
BJ
570 if (bp->b_flags & B_READ)
571 return (HP_RHDR|HP_GO);
572 else
573 return (HP_WHDR|HP_GO);
574 }
575 return (0);
04b9d53d
BJ
576}
577
a0eab615 578hpdtint(mi, mbsr)
4a4e3072 579 register struct mba_device *mi;
a0eab615 580 int mbsr;
04b9d53d 581{
804f6eab 582 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
b81fd3e8 583 register struct buf *bp = mi->mi_tab.b_actf;
705c30ac 584 register int er1, er2;
c983ca83 585 struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
2fdf5fa3 586 int retry = 0;
3e3f9c04
MK
587 int npf;
588 daddr_t bn;
589 int bcr;
b81fd3e8 590
3e3f9c04 591 bcr = MASKREG(-mi->mi_mba->mba_bcr);
a0eab615 592 if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) {
5530f6f7
HS
593 er1 = hpaddr->hper1;
594 er2 = hpaddr->hper2;
3e3f9c04
MK
595 if (bp->b_flags & B_BAD) {
596 npf = bp->b_error;
597 bn = sc->sc_badbn;
598 } else {
599 npf = btop(bp->b_bcount - bcr);
600 if (er1 & (HPER1_DCK | HPER1_ECH))
601 npf--;
602 bn = bp->b_blkno + npf;
603 }
6943fe60
MK
604 if (HPWAIT(mi, hpaddr) == 0)
605 goto hard;
b70e4030 606#ifdef HPDEBUG
6ac24ecd 607 if (hpdebug) {
b70e4030
BJ
608 int dc = hpaddr->hpdc, da = hpaddr->hpda;
609
5c93d6ba
MK
610 log(LOG_DEBUG,
611 "hperr: bp %x cyl %d blk %d blkdone %d as %o dc %x da %x\n",
3e3f9c04 612 bp, bp->b_cylin, bn, sc->sc_blkdone,
5c93d6ba 613 hpaddr->hpas&0xff, MASKREG(dc), MASKREG(da));
3e3f9c04
MK
614 log(LOG_DEBUG,
615 "errcnt %d mbsr=%b er1=%b er2=%b bcr -%d\n",
5c93d6ba
MK
616 mi->mi_tab.b_errcnt, mbsr, mbsr_bits,
617 MASKREG(er1), HPER1_BITS,
3e3f9c04 618 MASKREG(er2), HPER2_BITS, bcr);
6ac24ecd 619 }
b70e4030 620#endif
705c30ac 621 if (er1 & HPER1_HCRC) {
6cee54a8 622 er1 &= ~(HPER1_HCE|HPER1_FER);
705c30ac
BJ
623 er2 &= ~HPER2_BSE;
624 }
c5f3bc2a 625 if (er1 & HPER1_WLE) {
283ffc90 626 log(LOG_WARNING, "hp%d: write locked\n",
99f676cf 627 hpunit(bp->b_dev));
e34bc1ef 628 bp->b_flags |= B_ERROR;
a4a97100 629 } else if (bp->b_flags & B_FORMAT) {
c5f3bc2a 630 goto hard;
a4a97100 631 } else if (RM80(mi->mi_type) && er2&HPER2_SSE) {
e0d48442
RC
632 (void) hpecc(mi, SSE);
633 return (MBD_RESTARTED);
a4a97100 634 } else if ((er2 & HPER2_BSE) && !ML11(mi->mi_type)) {
b19f1d3a 635 if (hpecc(mi, BSE))
0be277a1
SL
636 return (MBD_RESTARTED);
637 goto hard;
a4a97100 638 } else if (MASKREG(er1) == HPER1_FER && RP06(mi->mi_type)) {
c5f3bc2a
MK
639 if (hpecc(mi, BSE))
640 return (MBD_RESTARTED);
641 goto hard;
e0d48442 642 } else if ((er1 & (HPER1_DCK | HPER1_ECH)) == HPER1_DCK &&
5c93d6ba 643 mi->mi_tab.b_errcnt >= 3) {
c5f3bc2a
MK
644 if (hpecc(mi, ECC))
645 return (MBD_RESTARTED);
178922cc
MK
646 /*
647 * ECC corrected. Only log retries below
648 * if we got errors other than soft ECC
649 * (as indicated by additional retries).
650 */
651 if (mi->mi_tab.b_errcnt == 3)
652 mi->mi_tab.b_errcnt = 0;
a4a97100
MK
653 } else if ((er1 & HPER1_HCRC) && !ML11(mi->mi_type) &&
654 hpecc(mi, BSE)) {
8fa6acee 655 /*
f5f43574
HS
656 * HCRC means the header is screwed up and the sector
657 * might well exist in the bad sector table,
658 * better check....
8fa6acee 659 */
a4fdfb62
MK
660 return (MBD_RESTARTED);
661 } else if (++mi->mi_tab.b_errcnt > 27 ||
a4a97100 662 (ML11(mi->mi_type) && mi->mi_tab.b_errcnt > 15) ||
a4fdfb62
MK
663 mbsr & MBSR_HARD ||
664 er1 & HPER1_HARD ||
a4a97100 665 (!ML11(mi->mi_type) && (er2 & HPER2_HARD))) {
b70e4030 666hard:
3e3f9c04 667 bp->b_blkno = bn; /* XXX */
fd2cb420 668 harderr(bp, "hp");
e83ccfd7
BJ
669 if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC)))
670 printf("mbsr=%b ", mbsr, mbsr_bits);
b70e4030 671 printf("er1=%b er2=%b",
5530f6f7
HS
672 MASKREG(hpaddr->hper1), HPER1_BITS,
673 MASKREG(hpaddr->hper2), HPER2_BITS);
a4a97100 674 if (bp->b_flags & B_FORMAT)
f5f43574 675 printf(" (hdr i/o)");
b70e4030 676 printf("\n");
b81fd3e8 677 bp->b_flags |= B_ERROR;
e0d48442 678 bp->b_flags &= ~B_BAD;
e34bc1ef
BJ
679 } else
680 retry = 1;
681 hpaddr->hpcs1 = HP_DCLR|HP_GO;
6610f756 682 if (retry && (mi->mi_tab.b_errcnt & 07) == 4) {
e34bc1ef 683 hpaddr->hpcs1 = HP_RECAL|HP_GO;
c983ca83 684 sc->sc_recal = 1;
5c93d6ba 685 return (MBD_REPOSITION);
04b9d53d 686 }
e34bc1ef 687 }
b70e4030 688#ifdef HPDEBUG
6ac24ecd 689 else
c983ca83 690 if (hpdebug && sc->sc_recal) {
5c93d6ba
MK
691 log(LOG_DEBUG,
692 "recal %d errcnt %d mbsr=%b er1=%b er2=%b\n",
693 sc->sc_recal, mi->mi_tab.b_errcnt, mbsr, mbsr_bits,
6ac24ecd
BJ
694 hpaddr->hper1, HPER1_BITS,
695 hpaddr->hper2, HPER2_BITS);
696 }
b70e4030 697#endif
8011f5df 698 (void)HPWAIT(mi, hpaddr);
5c93d6ba 699 if (retry)
3dbaa9da 700 return (MBD_RETRY);
aeecd470 701 if (mi->mi_tab.b_errcnt >= 16) {
d565635a
BJ
702 /*
703 * This is fast and occurs rarely; we don't
704 * bother with interrupts.
705 */
804f6eab 706 hpaddr->hpcs1 = HP_RTC|HP_GO;
8011f5df 707 (void)HPWAIT(mi, hpaddr);
b81fd3e8 708 mbclrattn(mi);
04b9d53d 709 }
178922cc 710 if (mi->mi_tab.b_errcnt && (bp->b_flags & B_ERROR) == 0)
5c93d6ba
MK
711 log(LOG_INFO, "hp%d%c: %d retries %sing sn%d\n",
712 hpunit(bp->b_dev), 'a'+(minor(bp->b_dev)&07),
713 mi->mi_tab.b_errcnt,
714 (bp->b_flags & B_READ) ? "read" : "writ",
715 (bp->b_flags & B_BAD) ?
716 sc->sc_badbn : bp->b_blkno + sc->sc_blkdone);
e0d48442
RC
717 if ((bp->b_flags & B_BAD) && hpecc(mi, CONT))
718 return (MBD_RESTARTED);
5c93d6ba 719 sc->sc_blkdone = 0;
3e3f9c04 720 bp->b_resid = bcr;
a4a97100 721 if (!ML11(mi->mi_type)) {
b19f1d3a
BJ
722 hpaddr->hpof = HPOF_FMT22;
723 hpaddr->hpcs1 = HP_RELEASE|HP_GO;
724 }
41a38591
MK
725 if (sc->sc_openpart == 0)
726 wakeup((caddr_t)sc);
b81fd3e8 727 return (MBD_DONE);
04b9d53d
BJ
728}
729
6943fe60
MK
730/*
731 * Wait (for a bit) for a drive to come ready;
732 * returns nonzero on success.
733 */
734hpwait(mi)
735 register struct mba_device *mi;
736{
737 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
738 register i = 100000;
739
740 while ((hpaddr->hpds & HPDS_DRY) == 0 && --i)
741 DELAY(10);
742 if (i == 0)
743 printf("hp%d: intr, not ready\n", mi->mi_unit);
744 return (i);
745}
746
deb8980a 747hpread(dev, uio)
804f6eab 748 dev_t dev;
deb8980a 749 struct uio *uio;
04b9d53d 750{
99f676cf 751 register int unit = hpunit(dev);
04b9d53d 752
804f6eab 753 if (unit >= NHP)
23458a62
BJ
754 return (ENXIO);
755 return (physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio));
04b9d53d
BJ
756}
757
406ddcbe 758hpwrite(dev, uio)
804f6eab 759 dev_t dev;
406ddcbe 760 struct uio *uio;
04b9d53d 761{
99f676cf 762 register int unit = hpunit(dev);
04b9d53d 763
804f6eab 764 if (unit >= NHP)
23458a62
BJ
765 return (ENXIO);
766 return (physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys, uio));
04b9d53d
BJ
767}
768
942f05a9 769hpioctl(dev, cmd, data, flag)
b19f1d3a
BJ
770 dev_t dev;
771 int cmd;
942f05a9 772 caddr_t data;
b19f1d3a
BJ
773 int flag;
774{
a4a97100
MK
775 int unit = hpunit(dev);
776 register struct disklabel *lp;
777 register struct format_op *fop;
778 int error = 0;
779 int hpformat();
780
781 lp = &hplabel[unit];
b19f1d3a
BJ
782
783 switch (cmd) {
942f05a9 784
a4a97100
MK
785 case DIOCGDINFO:
786 *(struct disklabel *)data = *lp;
787 break;
788
41a38591
MK
789 case DIOCGPART:
790 ((struct partinfo *)data)->disklab = lp;
791 ((struct partinfo *)data)->part =
792 &lp->d_partitions[hppart(dev)];
a4a97100
MK
793 break;
794
795 case DIOCSDINFO:
796 if ((flag & FWRITE) == 0)
797 error = EBADF;
798 else
799 *lp = *(struct disklabel *)data;
800 break;
801
802 case DIOCWDINFO:
803 if ((flag & FWRITE) == 0) {
804 error = EBADF;
805 break;
806 }
807 {
808 struct buf *bp;
809 struct disklabel *dlp;
810
811 *lp = *(struct disklabel *)data;
812 bp = geteblk(lp->d_secsize);
41a38591 813 bp->b_dev = makedev(major(dev), hpminor(hpunit(dev), 0));
a4a97100
MK
814 bp->b_blkno = LABELSECTOR;
815 bp->b_bcount = lp->d_secsize;
816 bp->b_flags = B_READ;
817 dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET);
818 hpstrategy(bp);
819 biowait(bp);
820 if (bp->b_flags & B_ERROR) {
821 error = u.u_error; /* XXX */
822 u.u_error = 0;
823 goto bad;
824 }
825 *dlp = *lp;
826 bp->b_flags = B_WRITE;
827 hpstrategy(bp);
828 biowait(bp);
829 if (bp->b_flags & B_ERROR) {
830 error = u.u_error; /* XXX */
831 u.u_error = 0;
832 }
833bad:
834 brelse(bp);
835 }
836 break;
837
838#ifdef notyet
839 case DIOCWFORMAT:
840 if ((flag & FWRITE) == 0) {
841 error = EBADF;
842 break;
843 }
844 {
845 struct uio auio;
846 struct iovec aiov;
847
848 fop = (struct format_op *)data;
849 aiov.iov_base = fop->df_buf;
850 aiov.iov_len = fop->df_count;
851 auio.uio_iov = &aiov;
852 auio.uio_iovcnt = 1;
853 auio.uio_resid = fop->df_count;
854 auio.uio_segflg = 0;
855 auio.uio_offset = fop->df_startblk * lp->d_secsize;
856 error = physio(hpformat, &rhpbuf[unit], dev, B_WRITE,
857 minphys, &auio);
858 fop->df_count -= auio.uio_resid;
859 fop->df_reg[0] = sc->sc_status;
860 fop->df_reg[1] = sc->sc_error;
861 }
862 break;
863#endif
864
865 default:
866 error = ENOTTY;
867 break;
868 }
869 return (0);
870}
871
872hpformat(bp)
873 struct buf *bp;
874{
b19f1d3a 875
a4a97100
MK
876 bp->b_flags |= B_FORMAT;
877 return (hpstrategy(bp));
b19f1d3a
BJ
878}
879
b70e4030 880hpecc(mi, flag)
4a4e3072 881 register struct mba_device *mi;
b70e4030 882 int flag;
04b9d53d 883{
b81fd3e8 884 register struct mba_regs *mbp = mi->mi_mba;
804f6eab 885 register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv;
b81fd3e8 886 register struct buf *bp = mi->mi_tab.b_actf;
a4a97100 887 register struct disklabel *lp = &hplabel[mi->mi_unit];
e0d48442 888 struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
b70e4030 889 int npf, o;
b81fd3e8 890 int bn, cn, tn, sn;
fa1d69d6 891 int bcr;
80e7c811 892
6943fe60 893 bcr = MASKREG(-mbp->mba_bcr);
e0d48442 894 if (bp->b_flags & B_BAD)
b70e4030 895 npf = bp->b_error;
28e6a2c6
MK
896 else {
897 npf = bp->b_bcount - bcr;
898 /*
899 * Watch out for fractional sector at end of transfer;
900 * want to round up if finished, otherwise round down.
901 */
902 if (bcr == 0)
903 npf += 511;
904 npf = btodb(npf);
905 }
80e7c811 906 o = (int)bp->b_un.b_addr & PGOFSET;
99f676cf 907 bn = bp->b_blkno;
80e7c811 908 cn = bp->b_cylin;
a4a97100
MK
909 sn = bn % lp->d_secpercyl + npf;
910 tn = sn / lp->d_nsectors;
911 sn %= lp->d_nsectors;
912 cn += tn / lp->d_ntracks;
913 tn %= lp->d_ntracks;
6f888d9a 914 bn += npf;
b70e4030 915 switch (flag) {
ba783028 916 case ECC: {
b70e4030
BJ
917 register int i;
918 caddr_t addr;
919 struct pte mpte;
920 int bit, byte, mask;
921
922 npf--; /* because block in error is previous block */
6943fe60 923 bn--;
e0d48442
RC
924 if (bp->b_flags & B_BAD)
925 bn = sc->sc_badbn;
283ffc90 926 log(LOG_WARNING, "hp%d%c: soft ecc sn%d\n", hpunit(bp->b_dev),
e0d48442 927 'a'+(minor(bp->b_dev)&07), bn);
0be277a1
SL
928 mask = MASKREG(rp->hpec2);
929 i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */
b70e4030
BJ
930 bit = i&07;
931 i = (i&~07)>>3;
932 byte = i + o;
3e3f9c04 933 while (i < 512 && (int)dbtob(npf)+i < bp->b_bcount && bit > -11) {
b70e4030
BJ
934 mpte = mbp->mba_map[npf+btop(byte)];
935 addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET);
936 putmemc(addr, getmemc(addr)^(mask<<bit));
937 byte++;
938 i++;
939 bit -= 8;
940 }
6943fe60 941 if (bcr == 0)
b70e4030 942 return (0);
089adc9d 943 npf++;
b70e4030
BJ
944 break;
945 }
946
947 case SSE:
948 rp->hpof |= HPOF_SSEI;
e0d48442
RC
949 if (bp->b_flags & B_BAD) {
950 bn = sc->sc_badbn;
951 goto fixregs;
952 }
b70e4030
BJ
953 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
954 break;
955
b70e4030 956 case BSE:
a4a97100
MK
957 if (sc->sc_state == OPENRAW)
958 return (0);
e0d48442
RC
959 if (rp->hpof & HPOF_SSEI)
960 sn++;
b70e4030
BJ
961#ifdef HPBDEBUG
962 if (hpbdebug)
5c93d6ba 963 log(LOG_DEBUG, "hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
b70e4030 964#endif
e0d48442
RC
965 if (bp->b_flags & B_BAD)
966 return (0);
b70e4030 967 if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0)
0be277a1 968 return (0);
b70e4030
BJ
969 bp->b_flags |= B_BAD;
970 bp->b_error = npf + 1;
e0d48442 971 rp->hpof &= ~HPOF_SSEI;
a4a97100
MK
972 bn = lp->d_ncylinders * lp->d_secpercyl -
973 lp->d_nsectors - 1 - bn;
e0d48442
RC
974 sc->sc_badbn = bn;
975 fixregs:
a4a97100
MK
976 cn = bn / lp->d_secpercyl;
977 sn = bn % lp->d_secpercyl;
978 tn = sn / lp->d_nsectors;
979 sn %= lp->d_nsectors;
8011f5df
MK
980 bcr = bp->b_bcount - (int)ptob(npf);
981 bcr = MIN(bcr, 512);
982 mbp->mba_bcr = -bcr;
b70e4030
BJ
983#ifdef HPBDEBUG
984 if (hpbdebug)
5c93d6ba 985 log(LOG_DEBUG, "revector to cn %d tn %d sn %d\n", cn, tn, sn);
b70e4030
BJ
986#endif
987 break;
988
989 case CONT:
990#ifdef HPBDEBUG
991 if (hpbdebug)
5c93d6ba 992 log(LOG_DEBUG, "hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
b70e4030 993#endif
b70e4030 994 bp->b_flags &= ~B_BAD;
a4fdfb62 995 if ((int)ptob(npf) >= bp->b_bcount)
0be277a1 996 return (0);
a4fdfb62 997 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
b70e4030 998 break;
b70e4030
BJ
999 }
1000 rp->hpcs1 = HP_DCLR|HP_GO;
e0d48442 1001 if (rp->hpof & HPOF_SSEI)
c9e9b65b 1002 sn++;
80e7c811
BJ
1003 rp->hpdc = cn;
1004 rp->hpda = (tn<<8) + sn;
1005 mbp->mba_sr = -1;
b70e4030
BJ
1006 mbp->mba_var = (int)ptob(npf) + o;
1007 rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO;
1008 mi->mi_tab.b_errcnt = 0; /* error has been corrected */
5c93d6ba 1009 sc->sc_blkdone = npf;
80e7c811 1010 return (1);
04b9d53d 1011}
e3b4b145
BJ
1012
1013#define DBSIZE 20
1014
1015hpdump(dev)
1016 dev_t dev;
1017{
4a4e3072 1018 register struct mba_device *mi;
b81fd3e8 1019 register struct mba_regs *mba;
804f6eab 1020 struct hpdevice *hpaddr;
e3b4b145 1021 char *start;
b81fd3e8 1022 int num, unit;
a4a97100 1023 register struct disklabel *lp;
e3b4b145
BJ
1024
1025 num = maxfree;
1026 start = 0;
99f676cf 1027 unit = hpunit(dev);
1b81ee79
BJ
1028 if (unit >= NHP)
1029 return (ENXIO);
b81fd3e8 1030#define phys(a,b) ((b)((int)(a)&0x7fffffff))
4a4e3072 1031 mi = phys(hpinfo[unit],struct mba_device *);
1b81ee79
BJ
1032 if (mi == 0 || mi->mi_alive == 0)
1033 return (ENXIO);
a4a97100 1034 lp = &hplabel[unit];
b81fd3e8 1035 mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
a0eab615 1036 mba->mba_cr = MBCR_INIT;
804f6eab 1037 hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive];
d565635a 1038 if ((hpaddr->hpds & HPDS_VV) == 0) {
804f6eab
BJ
1039 hpaddr->hpcs1 = HP_DCLR|HP_GO;
1040 hpaddr->hpcs1 = HP_PRESET|HP_GO;
d565635a 1041 hpaddr->hpof = HPOF_FMT22;
e3b4b145 1042 }
943411ce 1043 if (dumplo < 0)
1b81ee79 1044 return (EINVAL);
a4a97100
MK
1045 if (dumplo + num >= lp->d_partitions[hppart(dev)].p_size)
1046 num = lp->d_partitions[hppart(dev)].p_size - dumplo;
e3b4b145 1047 while (num > 0) {
b81fd3e8 1048 register struct pte *hpte = mba->mba_map;
e3b4b145 1049 register int i;
b81fd3e8 1050 int blk, cn, sn, tn;
e3b4b145
BJ
1051 daddr_t bn;
1052
1053 blk = num > DBSIZE ? DBSIZE : num;
1054 bn = dumplo + btop(start);
a4a97100
MK
1055 cn = (bn + lp->d_partitions[hppart(dev)].p_offset) /
1056 lp->d_secpercyl;
1057 sn = bn % lp->d_secpercyl;
1058 tn = sn / lp->d_nsectors;
1059 sn = sn % lp->d_nsectors;
e3b4b145
BJ
1060 hpaddr->hpdc = cn;
1061 hpaddr->hpda = (tn << 8) + sn;
1062 for (i = 0; i < blk; i++)
1063 *(int *)hpte++ = (btop(start)+i) | PG_V;
b81fd3e8
BJ
1064 mba->mba_sr = -1;
1065 mba->mba_bcr = -(blk*NBPG);
1066 mba->mba_var = 0;
804f6eab 1067 hpaddr->hpcs1 = HP_WCOM | HP_GO;
d565635a 1068 while ((hpaddr->hpds & HPDS_DRY) == 0)
c5f3bc2a 1069 DELAY(10);
d565635a 1070 if (hpaddr->hpds&HPDS_ERR)
1b81ee79 1071 return (EIO);
e3b4b145
BJ
1072 start += blk*NBPG;
1073 num -= blk;
1074 }
1075 return (0);
1076}
cf83ab8e
SL
1077
1078hpsize(dev)
1079 dev_t dev;
1080{
a4a97100 1081 register int unit = hpunit(dev);
cf83ab8e 1082 struct mba_device *mi;
cf83ab8e 1083
a4a97100
MK
1084 if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0 ||
1085 hpsoftc[unit].sc_state != OPEN)
cf83ab8e 1086 return (-1);
a4a97100
MK
1087 return ((int)hplabel[unit].d_partitions[hppart(dev)].p_size);
1088}
1089
1090#ifdef COMPAT_42
1091/*
1092 * Compatibility code to fake up pack label
1093 * for unlabeled disks.
1094 */
1095struct size {
1096 daddr_t nblocks;
1097 int cyloff;
1098} rp06_sizes[8] = {
1099 15884, 0, /* A=cyl 0 thru 37 */
1100 33440, 38, /* B=cyl 38 thru 117 */
1101 340670, 0, /* C=cyl 0 thru 814 */
1102 15884, 118, /* D=cyl 118 thru 155 */
1103 55936, 156, /* E=cyl 156 thru 289 */
1104 219384, 290, /* F=cyl 290 thru 814 */
1105 291280, 118, /* G=cyl 118 thru 814 */
1106 0, 0,
1107}, rp05_sizes[8] = {
1108 15884, 0, /* A=cyl 0 thru 37 */
1109 33440, 38, /* B=cyl 38 thru 117 */
1110 171798, 0, /* C=cyl 0 thru 410 */
1111 15884, 118, /* D=cyl 118 thru 155 */
1112 55936, 156, /* E=cyl 156 thru 289 */
1113 50512, 290, /* F=cyl 290 thru 410 */
1114 122408, 118, /* G=cyl 118 thru 410 */
1115 0, 0,
1116}, rm03_sizes[8] = {
1117 15884, 0, /* A=cyl 0 thru 99 */
1118 33440, 100, /* B=cyl 100 thru 308 */
1119 131680, 0, /* C=cyl 0 thru 822 */
1120 15884, 309, /* D=cyl 309 thru 408 */
1121 55936, 409, /* E=cyl 409 thru 758 */
1122 10144, 759, /* F=cyl 759 thru 822 */
1123 82144, 309, /* G=cyl 309 thru 822 */
1124 0, 0,
1125}, rm05_sizes[8] = {
1126 15884, 0, /* A=cyl 0 thru 26 */
1127 33440, 27, /* B=cyl 27 thru 81 */
1128 500384, 0, /* C=cyl 0 thru 822 */
1129 15884, 562, /* D=cyl 562 thru 588 */
1130 55936, 589, /* E=cyl 589 thru 680 */
1131 86240, 681, /* F=cyl 681 thru 822 */
1132 158592, 562, /* G=cyl 562 thru 822 */
1133 291346, 82, /* H=cyl 82 thru 561 */
1134}, rm80_sizes[8] = {
1135 15884, 0, /* A=cyl 0 thru 36 */
1136 33440, 37, /* B=cyl 37 thru 114 */
1137 242606, 0, /* C=cyl 0 thru 558 */
1138 15884, 115, /* D=cyl 115 thru 151 */
1139 55936, 152, /* E=cyl 152 thru 280 */
1140 120559, 281, /* F=cyl 281 thru 558 */
1141 192603, 115, /* G=cyl 115 thru 558 */
1142 0, 0,
1143}, rp07_sizes[8] = {
1144 15884, 0, /* A=cyl 0 thru 9 */
1145 66880, 10, /* B=cyl 10 thru 51 */
1146 1008000, 0, /* C=cyl 0 thru 629 */
1147 15884, 235, /* D=cyl 235 thru 244 */
1148 307200, 245, /* E=cyl 245 thru 436 */
1149 308650, 437, /* F=cyl 437 thru 629 */
1150 631850, 235, /* G=cyl 235 thru 629 */
1151 291346, 52, /* H=cyl 52 thru 234 */
1152}, cdc9775_sizes[8] = {
1153 15884, 0, /* A=cyl 0 thru 12 */
1154 66880, 13, /* B=cyl 13 thru 65 */
1155 1077760, 0, /* C=cyl 0 thru 841 */
1156 15884, 294, /* D=cyl 294 thru 306 */
1157 307200, 307, /* E=cyl 307 thru 546 */
1158 377440, 547, /* F=cyl 547 thru 841 */
1159 701280, 294, /* G=cyl 294 thru 841 */
1160 291346, 66, /* H=cyl 66 thru 293 */
1161}, cdc9730_sizes[8] = {
1162 15884, 0, /* A=cyl 0 thru 49 */
1163 33440, 50, /* B=cyl 50 thru 154 */
1164 263360, 0, /* C=cyl 0 thru 822 */
1165 15884, 155, /* D=cyl 155 thru 204 */
1166 55936, 205, /* E=cyl 205 thru 379 */
1167 141664, 380, /* F=cyl 380 thru 822 */
1168 213664, 155, /* G=cyl 155 thru 822 */
1169 0, 0,
1170}, capricorn_sizes[8] = {
1171 15884, 0, /* A=cyl 0 thru 31 */
1172 33440, 32, /* B=cyl 32 thru 97 */
1173 524288, 0, /* C=cyl 0 thru 1023 */
1174 15884, 668, /* D=cyl 668 thru 699 */
1175 55936, 700, /* E=cyl 700 thru 809 */
1176 109472, 810, /* F=cyl 810 thru 1023 */
1177 182176, 668, /* G=cyl 668 thru 1023 */
1178 291346, 98, /* H=cyl 98 thru 667 */
1179}, eagle_sizes[8] = {
1180 15884, 0, /* A=cyl 0 thru 16 */
1181 66880, 17, /* B=cyl 17 thru 86 */
1182 808320, 0, /* C=cyl 0 thru 841 */
1183 15884, 391, /* D=cyl 391 thru 407 */
1184 307200, 408, /* E=cyl 408 thru 727 */
1185 109296, 728, /* F=cyl 728 thru 841 */
1186 432816, 391, /* G=cyl 391 thru 841 */
1187 291346, 87, /* H=cyl 87 thru 390 */
1188}, ampex_sizes[8] = {
1189 15884, 0, /* A=cyl 0 thru 26 */
1190 33440, 27, /* B=cyl 27 thru 81 */
1191 495520, 0, /* C=cyl 0 thru 814 */
1192 15884, 562, /* D=cyl 562 thru 588 */
1193 55936, 589, /* E=cyl 589 thru 680 */
1194 81312, 681, /* F=cyl 681 thru 814 */
1195 153664, 562, /* G=cyl 562 thru 814 */
1196 291346, 82, /* H=cyl 82 thru 561 */
1197}, fj2361_sizes[8] = {
1198 15884, 0, /* A=cyl 0 thru 12 */
1199 66880, 13, /* B=cyl 13 thru 65 */
1200 1077760, 0, /* C=cyl 0 thru 841 */
1201 15884, 294, /* D=cyl 294 thru 306 */
1202 307200, 307, /* E=cyl 307 thru 546 */
1203 377408, 547, /* F=cyl 547 thru 841 */
1204 701248, 294, /* G=cyl 294 thru 841 */
1205 291346, 66, /* H=cyl 66 thru 293 */
1206};
1207
1208/*
1209 * These variable are all measured in sectors.
1210 * Sdist is how much to "lead" in the search for a desired sector
1211 * (i.e. if want N, search for N-sdist.)
1212 * Maxdist and mindist define the region right before our desired sector within
1213 * which we don't bother searching. We don't search when we are already less
1214 * then maxdist and more than mindist sectors "before" our desired sector.
1215 * Maxdist should be >= sdist.
1216 *
1217 * Beware, sdist, mindist and maxdist are not well tuned
1218 * for many of the drives listed in this table.
1219 * Try patching things with something i/o intensive
1220 * running and watch iostat.
1221 */
1222struct hpst {
1223 short nsect; /* # sectors/track */
1224 short ntrak; /* # tracks/cylinder */
1225 short nspc; /* # sector/cylinders */
1226 short ncyl; /* # cylinders */
1227 struct size *sizes; /* partition tables */
1228 short sdist; /* seek distance metric */
1229 short maxdist; /* boundaries of non-searched area */
1230 short mindist; /* preceding the target sector */
1231 char *name; /* name of disk type */
1232} hpst[] = {
1233 { 32, 5, 32*5, 823, rm03_sizes, 7, 4, 1, "RM03" },
1234 { 32, 19, 32*19, 823, rm05_sizes, 7, 4, 1, "RM05" },
1235 { 22,19, 22*19, 815, rp06_sizes, 7, 4, 1, "RP06"},
1236 { 31, 14, 31*14, 559, rm80_sizes, 7, 4, 1, "RM80"},
1237 { 22, 19, 22*19, 411, rp05_sizes, 7, 4, 1, "RP04"},
1238 { 22, 19, 22*19, 411, rp05_sizes, 7, 4, 1, "RP05"},
1239 { 50, 32, 50*32, 630, rp07_sizes, 15, 8, 3, "RP07"},
1240 { 1, 1, 1, 1, 0, 0, 0, 0, "ML11A"},
1241 { 1, 1, 1, 1, 0, 0, 0, 0, "ML11B" },
1242 { 32, 40, 32*40, 843, cdc9775_sizes, 7, 4, 1, "9775" },
1243 { 32, 10, 32*10, 823, cdc9730_sizes, 7, 4, 1, "9730-160" },
1244 { 32, 16, 32*16, 1024, capricorn_sizes,10,4, 3, "capricorn" },
1245 { 48, 20, 48*20, 842, eagle_sizes, 15, 8, 3, "eagle" },
1246 { 32, 19, 32*19, 815, ampex_sizes, 7, 4, 1, "9300" },
1247 { 64, 20, 64*20, 842, fj2361_sizes, 15, 8, 3, "2361" },
1248};
1249
1250/*
1251 * Map apparent MASSBUS drive type into manufacturer
1252 * specific configuration. For SI controllers this is done
1253 * based on codes in the serial number register. For
1254 * EMULEX controllers, the track and sector attributes are
1255 * used when the drive type is an RM02 (not supported by DEC).
1256 */
1257hpmaptype(mi, lp)
1258 register struct mba_device *mi;
1259 register struct disklabel *lp;
1260{
1261 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
1262 register int type = mi->mi_type;
1263 register struct hpst *st;
1264 register i;
1265
1266 /*
1267 * Model-byte processing for SI controllers.
1268 * NB: Only deals with RM03 and RM05 emulations.
1269 */
1270 if (type == HPDT_RM03 || type == HPDT_RM05) {
1271 int hpsn = hpaddr->hpsn;
1272
1273 if ((hpsn & SIMB_LU) == mi->mi_drive)
1274 switch ((hpsn & SIMB_MB) & ~(SIMB_S6|SIRM03|SIRM05)) {
1275
1276 case SI9775D:
1277 type = HPDT_9775;
1278 break;
1279
1280 case SI9730D:
1281 type = HPDT_9730;
1282 break;
1283
1284 case SI9766:
1285 type = HPDT_RM05;
1286 break;
1287
1288 case SI9762:
1289 type = HPDT_RM03;
1290 break;
1291
1292 case SICAPD:
1293 type = HPDT_CAPRICORN;
1294 break;
1295
1296 case SI9751D:
1297 type = HPDT_EAGLE;
1298 break;
1299 }
1300 }
1301
1302 /*
1303 * EMULEX SC750 or SC780. Poke the holding register.
1304 */
1305 if (type == HPDT_RM02) {
1306 int nsectors, ntracks, ncyl;
1307
1308 hpaddr->hpof = HPOF_FMT22;
1309 mbclrattn(mi);
1310 hpaddr->hpcs1 = HP_NOP;
1311 hpaddr->hphr = HPHR_MAXTRAK;
1312 ntracks = MASKREG(hpaddr->hphr) + 1;
1313 DELAY(100);
1314 hpaddr->hpcs1 = HP_NOP;
1315 hpaddr->hphr = HPHR_MAXSECT;
1316 nsectors = MASKREG(hpaddr->hphr) + 1;
1317 DELAY(100);
1318 hpaddr->hpcs1 = HP_NOP;
1319 hpaddr->hphr = HPHR_MAXCYL;
1320 ncyl = MASKREG(hpaddr->hphr) + 1;
1321 for (type = 0; hptypes[type] != 0; type++)
1322 if (hpst[type].nsect == nsectors &&
1323 hpst[type].ntrak == ntracks &&
1324 hpst[type].ncyl == ncyl)
1325 break;
1326
1327 if (hptypes[type] == 0) {
1328 printf("hp%d: %d sectors, %d tracks, %d cylinders: unknown device\n",
1329 mi->mi_unit, nsectors, ntracks, ncyl);
1330 type = HPDT_RM02;
1331 }
1332 hpaddr->hpcs1 = HP_DCLR|HP_GO;
1333 mbclrattn(mi); /* conservative */
1334 }
1335
1336 /*
1337 * set up minimal disk label.
1338 */
1339 st = &hpst[type];
41a38591 1340 lp->d_secsize = 512;
a4a97100
MK
1341 lp->d_nsectors = st->nsect;
1342 lp->d_ntracks = st->ntrak;
1343 lp->d_secpercyl = st->nspc;
1344 lp->d_ncylinders = st->ncyl;
1345 lp->d_secperunit = st->nspc * st->ncyl;
1346 lp->d_sdist = st->sdist;
1347 lp->d_mindist = st->mindist;
1348 lp->d_maxdist = st->maxdist;
1349 bcopy(hpst[type].name, lp->d_typename, sizeof(lp->d_typename));
1350 lp->d_npartitions = 8;
1351 for (i = 0; i < 8; i++) {
1352 lp->d_partitions[i].p_offset = st->sizes[i].cyloff *
1353 lp->d_secpercyl;
1354 lp->d_partitions[i].p_size = st->sizes[i].nblocks;
1355 }
1356 return (type);
cf83ab8e 1357}
a4a97100 1358#endif COMPAT_42
a5cc519e 1359#endif