📄 vd.c
字号:
register struct format_op *fop; struct uio auio; struct iovec aiov; if ((flag & FWRITE) == 0) { error = EBADF; break; } fop = (struct format_op *)data; aiov.iov_base = fop->df_buf; aiov.iov_len = fop->df_count; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_resid = fop->df_count; auio.uio_segflg = UIO_USERSPACE; auio.uio_offset = fop->df_startblk * lp->d_secsize; /* This assumes one active format operation per disk... */ dk->dk_op = fop->dk_op; dk->dk_althdr = fop->dk_althdr; dk->dk_fmtflags = fop->dk_fmtflags; /* * Don't return errors, as the format op won't get copied * out if we return nonzero. Callers must check the returned * registers and count. */ error = physio(vdformat, (struct buf *)NULL, dev, B_WRITE, minphys, &auio); if (error == EIO) error = 0; fop->df_count -= auio.uio_resid; /* This assumes one active format operation per disk... */ fop->dk_operrsta = dk->dk_operrsta; fop->dk_ecodecnt = dk->dk_ecodecnt; fop->dk_erraddr = dk->dk_erraddr; break; } default: error = ENOTTY; break; } return (error);}vdformat(bp) struct buf *bp;{ bp->b_flags |= B_FORMAT; vdstrategy(bp);}/* * Watch for lost interrupts. */vdwatch(){ register struct vdsoftc *vd; register struct vba_ctlr *vm; register int ctlr; int s; timeout(vdwatch, (caddr_t)0, hz); for (ctlr = 0; ctlr < NVD; ctlr++) { vm = vdminfo[ctlr]; if (vm == 0 || vm->um_alive == 0) continue; vd = &vdsoftc[ctlr]; s = spl7(); if (vm->um_tab.b_active && vd->vd_wticks++ >= VDMAXTIME) { printf("vd%d: lost interrupt\n", ctlr);#ifdef maybe VDABORT((struct vddevice *)vm->um_addr, vd->vd_type);#endif vdintr(ctlr); } splx(s); }}#define DBSIZE 64 /* controller limit with 1K sectors *//* * Crash dump. */vddump(dev) dev_t dev;{ register struct vba_device *vi; register struct vba_ctlr *vm; register struct disklabel *lp; register struct vdsoftc *vd; struct dksoftc *dk; int part, unit, num; u_long start; start = 0; unit = vdunit(dev); if (unit > NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0) return (ENXIO); dk = &dksoftc[unit]; if (dk->dk_state != OPEN && dk->dk_state != OPENRAW && vdinit(vdminor(unit, 0), 0) != 0) return (ENXIO); lp = &dklabel[unit]; part = vdpart(dev); if (part >= lp->d_npartitions) return (ENXIO); vm = vi->ui_mi; vdreset_ctlr(vm); if (dumplo < 0) return (EINVAL); /* * Maxfree is in pages, dumplo is in DEV_BSIZE units. */ num = maxfree * (NBPG / lp->d_secsize); dumplo *= DEV_BSIZE / lp->d_secsize; if (dumplo + num >= lp->d_partitions[vdpart(dev)].p_size) num = lp->d_partitions[vdpart(dev)].p_size - dumplo; vd = &vdsoftc[vm->um_ctlr]; vd->vd_dcb.intflg = DCBINT_NONE; vd->vd_dcb.opcode = VDOP_WD; vd->vd_dcb.devselect = dk->dk_dcb.devselect; vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long); while (num > 0) { int nsec, cn, sn, tn; nsec = MIN(num, DBSIZE); sn = dumplo + start / lp->d_secsize; cn = (sn + lp->d_partitions[vdpart(dev)].p_offset) / lp->d_secpercyl; sn %= lp->d_secpercyl; tn = sn / lp->d_nsectors; sn %= lp->d_nsectors; vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys; vd->vd_dcb.trail.rwtrail.memadr = start; vd->vd_dcb.trail.rwtrail.wcount = (nsec * lp->d_secsize) >> 1; vd->vd_dcb.trail.rwtrail.disk.cylinder = cn; vd->vd_dcb.trail.rwtrail.disk.track = tn; vd->vd_dcb.trail.rwtrail.disk.sector = sn; vd->vd_dcb.operrsta = 0; VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type); if (!vdpoll(vm, 5)) { printf(" during dump\n"); return (EIO); } if (vd->vd_dcb.operrsta & VDERR_HARD) { printf("dk%d: hard error, status=%b\n", unit, vd->vd_dcb.operrsta, VDERRBITS); return (EIO); } start += nsec * lp->d_secsize; num -= nsec; } return (0);}vdsize(dev) dev_t dev;{ register int unit = vdunit(dev); register struct dksoftc *dk; struct vba_device *vi; struct disklabel *lp; if (unit >= NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0 || (dk = &dksoftc[unit])->dk_state != OPEN) return (-1); lp = &dklabel[unit];#ifdef SECSIZE return ((int)lp->d_partitions[vdpart(dev)].p_size);#else SECSIZE return ((int)lp->d_partitions[vdpart(dev)].p_size >> dk->dk_bshift);#endif SECSIZE}/* * Initialize controller. */vdinit_ctlr(vm, vd) struct vba_ctlr *vm; struct vdsoftc *vd;{ register struct vddevice *vdaddr = (struct vddevice *)vm->um_addr; if (vd->vd_type == VDTYPE_SMDE) { vdaddr->vdcsr = 0; vdaddr->vdtcf_mdcb = AM_ENPDA; vdaddr->vdtcf_dcb = AM_ENPDA; vdaddr->vdtcf_trail = AM_ENPDA; vdaddr->vdtcf_data = AM_ENPDA; vdaddr->vdccf = CCF_SEN | CCF_DIU | CCF_STS | CCF_RFE | XMD_32BIT | BSZ_16WRD | CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR; } if (!vdcmd(vm, VDOP_INIT, 10, 0) || !vdcmd(vm, VDOP_DIAG, 10, 0)) { printf("vd%d: %s cmd failed\n", vm->um_ctlr, vd->vd_dcb.opcode == VDOP_INIT ? "init" : "diag"); return (0); } vd->vd_secsize = vdaddr->vdsecsize << 1; return (1);}/* * Perform a controller reset. */vdreset_ctlr(vm) register struct vba_ctlr *vm;{ register struct vddevice *vdaddr = (struct vddevice *)vm->um_addr; register struct vdsoftc *vd = &vdsoftc[vm->um_ctlr]; register int unit; struct vba_device *vi; VDRESET(vdaddr, vd->vd_type); if (vdinit_ctlr(vm, vd) == 0) return; for (unit = 0; unit < NDK; unit++) if ((vi = vddinfo[unit]) && vi->ui_mi == vm && vi->ui_alive) (void) vdreset_drive(vi);}vdreset_drive(vi) register struct vba_device *vi;{ register struct disklabel *lp = &dklabel[vi->ui_unit]; struct vba_ctlr *vm = vdminfo[vi->ui_ctlr]; struct vddevice *vdaddr = (struct vddevice *)vm->um_addr; register struct vdsoftc *vd = &vdsoftc[vi->ui_ctlr]; register struct dksoftc *dk = &dksoftc[vi->ui_unit]; int config_status, config_ecode, saw_drive = 0;#ifdef notdef /* * check for ESDI distribution panel already configured, * e.g. on boot drive, or if PROBE on controller actually * worked. Status will be zero if drive hasn't * been probed yet. */#if STA_ESDI != 0 if ((vdaddr->vdstatus[vi->ui_slave] & STA_TYPE) == STA_ESDI) lp->d_devflags |= VD_ESDI;#endif#endiftop: vd->vd_dcb.opcode = VDOP_CONFIG; /* command */ vd->vd_dcb.intflg = DCBINT_NONE; vd->vd_dcb.nxtdcb = (struct dcb *)0; /* end of chain */ vd->vd_dcb.operrsta = 0; vd->vd_dcb.devselect = vi->ui_slave | lp->d_devflags; vd->vd_dcb.trail.rstrail.ncyl = lp->d_ncylinders; vd->vd_dcb.trail.rstrail.nsurfaces = lp->d_ntracks; if (vd->vd_type == VDTYPE_SMDE) { vd->vd_dcb.trailcnt = sizeof (struct treset) / sizeof (long); vd->vd_dcb.trail.rstrail.nsectors = lp->d_nsectors; vd->vd_dcb.trail.rstrail.slip_sec = lp->d_sparespertrack; vd->vd_dcb.trail.rstrail.recovery = (lp->d_flags & D_REMOVABLE) ? VDRF_NORMAL : (VDRF_NORMAL &~ (VDRF_OSP|VDRF_OSM)); } else vd->vd_dcb.trailcnt = 2; /* XXX */ vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys; vd->vd_mdcb.mdcb_status = 0; VDGO(vdaddr, vd->vd_mdcbphys, vd->vd_type); if (!vdpoll(vm, 5)) { printf(" during config\n"); return (0); } config_status = vd->vd_dcb.operrsta; config_ecode = (u_char)vd->vd_dcb.err_code; if (config_status & VDERR_HARD) { if (vd->vd_type == VDTYPE_SMDE) { /* * If drive status was updated successfully, * STA_US (unit selected) should be set * if the drive is attached and powered up. * (But only if we've guessed right on SMD * vs. ESDI; if that flag is wrong, we won't * see the drive.) If we don't see STA_US * with either SMD or ESDI set for the unit, * we assume that the drive doesn't exist, * and don't wait for it to spin up. */ (void) vdcmd(vm, VDOP_STATUS, 5, vi->ui_slave); uncache(&vdaddr->vdstatus[vi->ui_slave]); if (vdaddr->vdstatus[vi->ui_slave] & STA_US) saw_drive = 1; else if (lp->d_devflags == 0) { lp->d_devflags = VD_ESDI; goto top; } } else saw_drive = 1; if ((config_status & (DCBS_OCYL|DCBS_NRDY)) == 0) printf("dk%d: config error %b ecode %x\n", vi->ui_unit, config_status, VDERRBITS, config_ecode); else if ((vd->vd_flags & VD_STARTED) == 0 && saw_drive) { int started; printf(" starting drives, wait ... "); vd->vd_flags |= VD_STARTED; started = (vdcmd(vm, VDOP_START, 10) == 1); DELAY(62000000); printf("done\n"); lp->d_devflags = 0; if (started) goto top; } return (0); } dk->dk_dcb.devselect |= lp->d_devflags; return (1);}/* * Perform a command w/o trailer. */vdcmd(vm, cmd, t, slave) register struct vba_ctlr *vm;{ register struct vdsoftc *vd = &vdsoftc[vm->um_ctlr]; vd->vd_dcb.opcode = cmd; /* command */ vd->vd_dcb.intflg = DCBINT_NONE; vd->vd_dcb.nxtdcb = (struct dcb *)0; /* end of chain */ vd->vd_dcb.operrsta = 0; vd->vd_dcb.devselect = slave; vd->vd_dcb.trailcnt = 0; vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys; vd->vd_mdcb.mdcb_status = 0; VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type); if (!vdpoll(vm, t)) { printf(" during init\n"); return (0); } return ((vd->vd_dcb.operrsta&VDERR_HARD) == 0);}/* * Poll controller until operation * completes or timeout expires. */vdpoll(vm, t) register struct vba_ctlr *vm; register int t;{ register struct vdsoftc *vd = &vdsoftc[vm->um_ctlr]; register struct vddevice *vdaddr = (struct vddevice *)vm->um_addr; t *= 1000; for (;;) { uncache(&vd->vd_dcb.operrsta); if (vd->vd_dcb.operrsta & (DCBS_DONE|DCBS_ABORT)) break; if (--t <= 0) { printf("vd%d: controller timeout", vm->um_ctlr); VDABORT(vdaddr, vd->vd_type); return (0); } DELAY(1000); } if (vd->vd_type == VDTYPE_SMDE) { do { DELAY(50); uncache(&vdaddr->vdcsr); } while (vdaddr->vdcsr & CS_GO); DELAY(300); uncache(&vd->vd_dcb.err_code); } DELAY(200); uncache(&vd->vd_dcb.operrsta); return (1);}#ifdef COMPAT_42struct vdst { int nsec; /* sectors/track */ int ntrack; /* tracks/cylinder */ int ncyl; /* cylinders */ int secsize; /* sector size */ char *name; /* type name */ struct { int off; /* partition offset in sectors */ int size; /* partition size in sectors */ } parts[8];} vdst[] = { { 66, 23, 850, 512, "NEC 800", {0, 1290300}, /* a cyl 0 - 849 */ }, { 64, 20, 842, 512, "2361a", {0, 61440}, /* a cyl 0 - 47 */ {61440, 67840}, /* b cyl 48 - 100 */ {129280, 942080}, /* c cyl 101 - 836 */ {0, 1071360}, /* d cyl 0 - 836 */ {449280, 311040}, /* e cyl 351 - 593 */ {760320, 311040}, /* f cyl 594 - 836 */ {449280, 622080}, /* g cyl 351 - 836 */ {129280, 320000} /* h cyl 101 - 350 */ }, { 48, 24, 711, 512, "xsd", {0, 61056}, /* a cyl 0 - 52 */ {61056, 61056}, /* b cyl 53 - 105 */ {122112, 691200}, /* c cyl 106 - 705 */ {237312, 576000}, /* d cyl 206 - 705 */ {352512, 460800}, /* e cyl 306 - 705 */ {467712, 345600}, /* f cyl 406 - 705 */ {582912, 230400}, /* g cyl 506 - 705 */ {698112, 115200} /* h cyl 606 - 705 */ }, { 44, 20, 842, 512, "eagle", {0, 52800}, /* egl0a cyl 0 - 59 */ {52800, 66000}, /* egl0b cyl 60 - 134 */ {118800, 617760}, /* egl0c cyl 135 - 836 */ {736560, 4400}, /* egl0d cyl 837 - 841 */ {0, 736560}, /* egl0e cyl 0 - 836 */ {0, 740960}, /* egl0f cyl 0 - 841 */ {118800, 310640}, /* egl0g cyl 135 - 487 */ {429440, 307120} /* egl0h cyl 488 - 836 */ }, { 64, 10, 823, 512, "fuj", {0, 38400}, /* fuj0a cyl 0 - 59 */ {38400, 48000}, /* fuj0b cyl 60 - 134 */ {86400, 437120}, /* fuj0c cyl 135 - 817 */ {159360, 364160}, /* fuj0d cyl 249 - 817 */ {232320, 291200}, /* fuj0e cyl 363 - 817 */ {305280, 218240}, /* fuj0f cyl 477 - 817 */ {378240, 145280}, /* fuj0g cyl 591 - 817 */ {451200, 72320} /* fug0h cyl 705 - 817 */ }, { 32, 24, 711, 512, "xfd", { 0, 40704 }, /* a cyl 0 - 52 */ { 40704, 40704 }, /* b cyl 53 - 105 */ { 81408, 460800 }, /* c cyl 106 - 705 */ { 0, 81408 }, /* d cyl 709 - 710 (a & b) */ { 0, 542208 }, /* e cyl 0 - 705 */ { 40704, 501504 }, /* f cyl 53 - 705 (b & c) */ { 81408, 230400 }, /* g cyl 106 - 405 (1/2 of c) */ { 311808,230400 } /* h cyl 406 - 705 (1/2 of c) */ }, { 32, 19, 823, 512, "smd", {0, 40128}, /* a cyl 0-65 */ {40128, 27360}, /* b cyl 66-110 */ {67488, 429856}, /* c cyl 111-817 */ {139232, 358112}, /* d cyl 229 - 817 */ {210976, 286368}, /* e cyl 347 - 817 */ {282720, 214624}, /* f cyl 465 - 817 */ {354464, 142880}, /* g cyl 583 - 817 */ {426208, 71136} /* h cyl 701 - 817 */ }, { 18, 15, 1224, 1024, "mxd", {0, 21600}, /* a cyl 0-79 */ {21600, 22410}, /* b cyl 80-162 */ {44010, 285120}, /* c cyl 163-1217 */#ifdef notyet {x, 237600}, /* d cyl y - 1217 */ {x, 190080}, /* e cyl y - 1217 */ {x, 142560}, /* f cyl y - 1217 */ {x, 95040}, /* g cyl y - 1217 */ {x, 47520} /* h cyl 701 - 817 */#endif }, { 32, 10, 823, 512, "fsd", {0, 19200}, /* a cyl 0 - 59 */ {19200, 24000}, /* b cyl 60 - 134 */ {43200, 218560}, /* c cyl 135 - 817 */ }};#define NVDST (sizeof (vdst) / sizeof (vdst[0]))/* * Construct a label for an unlabeled pack. We * deduce the drive type by reading from the last * track on successively smaller drives until we * don't get an error. */vdmaptype(vi, lp) register struct vba_device *vi; register struct disklabel *lp;{ register struct vdsoftc *vd; register struct vdst *p; struct vba_ctlr *vm = vi->ui_mi; int i; vd = &vdsoftc[vi->ui_ctlr]; for (p = vdst; p < &vdst[NVDST]; p++) { if (vd->vd_type == VDTYPE_VDDC && p->nsec != 32) continue; lp->d_nsectors = p->nsec; lp->d_ntracks = p->ntrack; lp->d_ncylinders = p->ncyl; lp->d_secsize = p->secsize; DELAY(100000); if (!vdreset_drive(vi)) return (0); DELAY(100000); vd->vd_dcb.opcode = VDOP_RD; vd->vd_dcb.intflg = DCBINT_NONE; vd->vd_dcb.nxtdcb = (struct dcb *)0; /* end of chain */ vd->vd_dcb.devselect = dksoftc[vi->ui_unit].dk_dcb.devselect; vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long); vd->vd_dcb.trail.rwtrail.memadr = vtoph((struct proc *)0, (unsigned)vd->vd_rbuf.vb_rawbuf); vd->vd_dcb.trail.rwtrail.wcount = lp->d_secsize / sizeof(short); vd->vd_dcb.operrsta = 0; vd->vd_dcb.trail.rwtrail.disk.cylinder = p->ncyl - 2; vd->vd_dcb.trail.rwtrail.disk.track = p->ntrack - 1; vd->vd_dcb.trail.rwtrail.disk.sector = p->nsec - 1; vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys; vd->vd_mdcb.mdcb_status = 0; VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type); if (!vdpoll(vm, 60)) printf(" during probe\n"); if ((vd->vd_dcb.operrsta & VDERR_HARD) == 0) break; } if (p >= &vdst[NVDST]) return (0); for (i = 0; i < 8; i++) { lp->d_partitions[i].p_offset = p->parts[i].off; lp->d_partitions[i].p_size = p->parts[i].size; } lp->d_npartitions = 8; lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; bcopy(p->name, lp->d_typename, 4); return (1);}#endif COMPAT_42#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -