-/* vd.c 7.1 88/05/21 */
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Computer Consoles Inc.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#)vd.c 7.9 (Berkeley) %G%
+ */
#include "dk.h"
#if NVD > 0
struct vba_ctlr *vdminfo[NVD];
struct vba_device *vddinfo[NDK];
int vdprobe(), vdslave(), vdattach(), vddgo(), vdstrategy();
-long vdaddr[] = { 0xffff2000, 0xffff2100, 0xffff2200, 0xffff2300, 0 };
+long vdstd[] = { 0xffff2000, 0xffff2100, 0xffff2200, 0xffff2300, 0 };
struct vba_driver vddriver =
- { vdprobe, vdslave, vdattach, vddgo, vdaddr, "dk", vddinfo, "vd", vdminfo };
+ { vdprobe, vdslave, vdattach, vddgo, vdstd, "dk", vddinfo, "vd", vdminfo };
/*
* Per-controller state.
#define VD_STARTED 0x2 /* start command issued */
#define VD_DOSEEKS 0x4 /* should overlap seeks */
#define VD_SCATGATH 0x8 /* can do scatter-gather commands (correctly) */
+#define VD_LOCKED 0x10 /* locked for direct controller access */
+#define VD_WAIT 0x20 /* someone needs direct controller access */
u_short vd_type; /* controller type */
u_short vd_wticks; /* timeout */
struct mdcb vd_mdcb; /* master command block */
vdaddr->vdtcf_dcb = AM_ENPDA;
vdaddr->vdtcf_trail = AM_ENPDA;
vdaddr->vdtcf_data = AM_ENPDA;
- vdaddr->vdccf = CCF_SEN | CCF_DER | CCF_STS |
+ vdaddr->vdccf = CCF_SEN | CCF_DIU | CCF_STS |
XMD_32BIT | BSZ_16WRD |
CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR;
}
vd->vd_dcbphys = vtoph((struct proc *)0, (unsigned)&vd->vd_dcb);
vm->um_addr = reg; /* XXX */
s = spl7();
- if (!vdcmd(vm, VDOP_INIT, 10) || !vdcmd(vm, VDOP_DIAG, 10)) {
+ 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");
splx(s);
}
if (vd->vd_type == VDTYPE_SMDE) {
vd->vd_dcb.trail.idtrail.date = 0;
- if (vdcmd(vm, VDOP_IDENT, 10)) {
+ if (vdcmd(vm, VDOP_IDENT, 10, 0)) {
uncache(&vd->vd_dcb.trail.idtrail.date);
if (vd->vd_dcb.trail.idtrail.date != 0)
vd->vd_flags |= VD_SCATGATH;
struct vdsoftc *vd = &vdsoftc[vi->ui_ctlr];
if ((vd->vd_flags&VD_INIT) == 0) {
- printf("vd%d: %s controller%s\n", vi->ui_ctlr,
- vd->vd_type == VDTYPE_VDDC ? "VDDC" : "SMDE",
- (vd->vd_flags & VD_SCATGATH) ? " with scatter-gather" : "");
+ printf("vd%d: %s controller", vi->ui_ctlr,
+ vd->vd_type == VDTYPE_VDDC ? "VDDC" : "SMDE");
+ if (vd->vd_flags & VD_SCATGATH) {
+ char rev[5];
+
+ bcopy((caddr_t)&vd->vd_dcb.trail.idtrail.rev, rev,
+ sizeof(vd->vd_dcb.trail.idtrail.rev));
+ printf(" firmware rev %s (%d-%d-%d)", rev,
+ (vd->vd_dcb.trail.idtrail.date >> 8) & 0xff,
+ vd->vd_dcb.trail.idtrail.date & 0xff,
+ (vd->vd_dcb.trail.idtrail.date >> 16) & 0xffff);
+ }
+ printf("\n");
vd->vd_flags |= VD_INIT;
}
lp->d_ntracks = 23;
lp->d_ncylinders = 850;
lp->d_secpercyl = 66*23;
+ lp->d_rpm = 3600;
+ lp->d_npartitions = 1;
+ lp->d_partitions[0].p_offset = 0;
+ lp->d_partitions[0].p_size = LABELSECTOR + 1;
/*
* Initialize invariant portion of
return (0);
}
+/* ARGSUSED */
vdclose(dev, flags, fmt)
dev_t dev;
int flags, fmt;
dk = &dksoftc[unit];
if (flags & O_NDELAY) {
dk->dk_state = OPENRAW;
- return;
+ return (0);
}
dk->dk_state = RDLABEL;
lp = &dklabel[unit];
dk->dk_state = OPENRAW;
}
#ifdef COMPAT_42
+ vdlock(vi->ui_ctlr);
if (vdmaptype(vi, lp))
dk->dk_state = OPEN;
+ vdunlock(vi->ui_ctlr);
#endif
} else {
/*
* Now that we have the label, configure
* the correct drive parameters.
*/
+ vdlock(vi->ui_ctlr);
if (vdreset_drive(vi))
dk->dk_state = OPEN;
else {
dk->dk_state = CLOSED;
error = ENXIO;
}
+ vdunlock(vi->ui_ctlr);
}
#ifndef SECSIZE
vd_setsecsize(dk, lp);
register struct dksoftc *dk;
register struct disklabel *lp;
register struct dcb **dcbp;
- struct mdcb *mdcb;
struct buf *dp;
int sn, tn;
vd->vd_dcb.trail.rwtrail.wcount = (bp->b_bcount+1) >> 1;
setupaddr:
vd->vd_dcb.trail.rwtrail.memadr =
- vbasetup(bp, &vd->vd_rbuf, lp->d_secsize);
+ vbasetup(bp, &vd->vd_rbuf, (int)lp->d_secsize);
break;
case VDOP_RAS:
case VDOP_GAW:
- vd->vd_dcb.trailcnt += vba_sgsetup(bp, &vd->vd_rbuf,
+ vd->vd_dcb.trailcnt += vd_sgsetup(bp, &vd->vd_rbuf,
&vd->vd_dcb.trail.sgtrail);
break;
}
VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type);
}
+/*
+ * Wait for controller to finish current operation
+ * so that direct controller accesses can be done.
+ */
+vdlock(ctlr)
+{
+ register struct vba_ctlr *vm = vdminfo[ctlr];
+ register struct vdsoftc *vd = &vdsoftc[ctlr];
+ int s;
+
+ s = spl7();
+ while (vm->um_tab.b_active || vd->vd_flags & VD_LOCKED) {
+ vd->vd_flags |= VD_WAIT;
+ sleep((caddr_t)vd, PRIBIO);
+ }
+ vd->vd_flags |= VD_LOCKED;
+ splx(s);
+}
+
+/*
+ * Continue normal operations after pausing for
+ * munging the controller directly.
+ */
+vdunlock(ctlr)
+{
+ register struct vba_ctlr *vm = vdminfo[ctlr];
+ register struct vdsoftc *vd = &vdsoftc[ctlr];
+
+ vd->vd_flags &= ~VD_LOCKED;
+ if (vd->vd_flags & VD_WAIT) {
+ vd->vd_flags &= ~VD_WAIT;
+ wakeup((caddr_t)vd);
+ } else if (vm->um_tab.b_actf || vm->um_tab.b_seekf)
+ vdstart(vm);
+}
+
#define DONTCARE (DCBS_DSE|DCBS_DSL|DCBS_TOP|DCBS_TOM|DCBS_FAIL|DCBS_DONE)
/*
* Handle a disk interrupt.
register struct vba_device *vi;
register struct vdsoftc *vd = &vdsoftc[ctlr];
register status;
- int ecode, timedout;
+ int timedout;
struct dksoftc *dk;
if (!vm->um_tab.b_active) {
dp = vm->um_tab.b_actf;
bp = dp->b_actf;
vi = vddinfo[vdunit(bp->b_dev)];
+ dk = &dksoftc[vi->ui_unit];
if (vi->ui_dk >= 0)
dk_busy &= ~(1<<vi->ui_dk);
timedout = (vd->vd_wticks >= VDMAXTIME);
dk->dk_ecode = vd->vd_dcb.err_code;
}
if (status & VDERR_HARD || timedout) {
- if (vd->vd_type == VDTYPE_SMDE) {
+ if (vd->vd_type == VDTYPE_SMDE)
uncache(&vd->vd_dcb.err_code);
- ecode = vd->vd_dcb.err_code;
- }
if (status & DCBS_WPT) {
/*
* Give up on write locked devices immediately.
printf("\n");
}
} else if (status & DCBS_SOFT)
- vdsofterr(vd, bp, &vd->vd_dcb);
+ vdsofterr(bp, &vd->vd_dcb);
vd->vd_wticks = 0;
if (vm->um_tab.b_active) {
vm->um_tab.b_active = 0;
*/
if (dp->b_actf)
vdustart(vi);
- else if ((dk = &dksoftc[vi->ui_unit])->dk_openpart == 0)
+ else if (dk->dk_openpart == 0)
wakeup((caddr_t)dk);
}
/*
* If there are devices ready to
* transfer, start the controller.
*/
- if (vm->um_tab.b_actf || vm->um_tab.b_seekf)
+ if (vd->vd_flags & VD_WAIT) {
+ vd->vd_flags &= ~VD_WAIT;
+ wakeup((caddr_t)vd);
+ } else if (vm->um_tab.b_actf || vm->um_tab.b_seekf)
vdstart(vm);
}
register struct dcb *dcb;
{
int unit = vdunit(bp->b_dev), status = dcb->operrsta;
- int part = vdpart(bp->b_dev);
register struct disklabel *lp = &dklabel[unit];
- char partname = 'a' + part;
- int sn;
+ int blkdone;
if (vd->vd_wticks < VDMAXTIME)
status &= ~DONTCARE;
-/* generic
- sn = bp->b_blkno + lp->d_partitions[part].p_offset;
-*/
- sn = ((dcb->err_cyl & 0xfff) * lp->d_ntracks + dcb->err_trk)
- * lp->d_nsectors + dcb->err_sec;
- printf("dk%d%c: %s bn [%d-%d) (sn %d), status %b",
- unit, partname, what, bp->b_blkno,
- bp->b_blkno + (bp->b_bcount - 1)/DEV_BSIZE, sn, status, VDERRBITS);
+ blkdone = ((((dcb->err_cyl & 0xfff) * lp->d_ntracks + dcb->err_trk) *
+ lp->d_nsectors + dcb->err_sec -
+ lp->d_partitions[vdpart(bp->b_dev)].p_offset) >>
+ dksoftc[unit].dk_bshift) - bp->b_blkno;
+ diskerr(bp, "dk", what, LOG_PRINTF, blkdone, lp);
+ printf(", status %b", status, VDERRBITS);
if (vd->vd_type == VDTYPE_SMDE)
printf(" ecode %x", dcb->err_code);
- printf("\n(error sec %d trk %d cyl %d wcount %d)", dcb->err_sec,
- dcb->err_trk, dcb->err_cyl, dcb->err_wcount);
}
-vdsofterr(vd, bp, dcb)
- struct vdsoftc *vd;
+vdsofterr(bp, dcb)
register struct buf *bp;
register struct dcb *dcb;
{
- int unit = vdunit(bp->b_dev), status = dcb->operrsta;
- int part = vdpart(bp->b_dev);
- char partname = 'a' + part;
- int sn = (bp->b_blkno << dksoftc[unit].dk_bshift) +
- dklabel[unit].d_partitions[part].p_offset;
-
- if (status != (DCBS_CCD|DCBS_SOFT|DCBS_ERR|DCBS_DONE))
- log(LOG_WARNING,
- "dk%d%c: soft error sn %d bn %d, status %b ecode %x\n",
- unit, partname, sn, bp->b_blkno, status, VDERRBITS,
+ int unit = vdunit(bp->b_dev);
+ struct disklabel *lp = &dklabel[unit];
+ int status = dcb->operrsta;
+ int blkdone;
+
+ blkdone = ((((dcb->err_cyl & 0xfff) * lp->d_ntracks + dcb->err_trk) *
+ lp->d_nsectors + dcb->err_sec -
+ lp->d_partitions[vdpart(bp->b_dev)].p_offset) >>
+ dksoftc[unit].dk_bshift) - bp->b_blkno;
+
+ if (status != (DCBS_CCD|DCBS_SOFT|DCBS_ERR|DCBS_DONE)) {
+ diskerr(bp, "dk", "soft error", LOG_WARNING, blkdone, lp);
+ addlog(", status %b ecode %x\n", status, VDERRBITS,
dcb->err_code);
- else
- log(LOG_WARNING, "dk%d%c: soft ecc sn %d bn %d\n",
- unit, part, sn, bp->b_blkno);
+ } else {
+ diskerr(bp, "dk", "soft ecc", LOG_WARNING, blkdone, lp);
+ addlog("\n");
+ }
}
vdioctl(dev, cmd, data, flag)
register int unit = vdunit(dev);
register struct disklabel *lp = &dklabel[unit];
register struct dksoftc *dk = &dksoftc[unit];
- int error = 0, wlab, vdformat();
+ int error = 0, vdformat();
switch (cmd) {
break;
case DIOCWDINFO:
- /* simulate opening partition 0 so write succeeds */
- dk->dk_openpart |= (1 << 0); /* XXX */
- wlab = dk->dk_wlabel;
- dk->dk_wlabel = 1;
if ((flag & FWRITE) == 0)
error = EBADF;
else if ((error = setdisklabel(lp, (struct disklabel *)data,
(dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart)) == 0) {
- dk->dk_state = OPEN;
+ int wlab;
+
+ if (error == 0 && dk->dk_state == OPENRAW &&
+ vdreset_drive(vddinfo[unit]))
+ dk->dk_state = OPEN;
+ /* simulate opening partition 0 so write succeeds */
+ dk->dk_openpart |= (1 << 0); /* XXX */
+ wlab = dk->dk_wlabel;
+ dk->dk_wlabel = 1;
error = writedisklabel(dev, vdstrategy, lp);
+ dk->dk_openpart = dk->dk_copenpart | dk->dk_bopenpart;
+ dk->dk_wlabel = wlab;
}
- dk->dk_openpart = dk->dk_copenpart | dk->dk_bopenpart;
- dk->dk_wlabel = wlab;
break;
case DIOCWFORMAT:
{
register struct vdsoftc *vd;
register struct vba_ctlr *vm;
- register int ctlr, unit;
+ register int ctlr;
int s;
timeout(vdwatch, (caddr_t)0, hz);
vdaddr->vdccf = CCF_STS | XMD_32BIT | BSZ_16WRD |
CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR;
}
- if (!vdcmd(vm, VDOP_INIT, 10) || !vdcmd(vm, VDOP_DIAG, 10)) {
+ if (!vdcmd(vm, VDOP_INIT, 10, 0) || !vdcmd(vm, VDOP_DIAG, 10, 0)) {
printf("%s cmd failed\n",
vd->vd_dcb.opcode == VDOP_INIT ? "init" : "diag");
return;
printf(" during config\n");
return (0);
}
+/*
+uncache(&vd->vd_dcb.err_code);
+printf("vdreset_drive %d, error %b, ecode %x, status %x => ",
+ vi->ui_unit, vd->vd_dcb.operrsta, VDERRBITS, vd->vd_dcb.err_code,
+ vdaddr->vdstatus[vi->ui_slave]);
+uncache(&vdaddr->vdstatus[vi->ui_slave]);
+printf("%x =>", vdaddr->vdstatus[vi->ui_slave]);
+{ int status = vd->vd_dcb.operrsta;
+vdcmd(vm, VDOP_STATUS, 5, vi->ui_slave);
+vd->vd_dcb.operrsta = status;
+}
+uncache(&vdaddr->vdstatus[vi->ui_slave]);
+printf("%x\n", vdaddr->vdstatus[vi->ui_slave]);
+*/
if (vd->vd_dcb.operrsta & VDERR_HARD) {
if (vd->vd_type == VDTYPE_SMDE) {
if (lp->d_devflags == 0) {
vd->vd_flags |= VD_STARTED;
started = (vdcmd(vm, VDOP_START, 10) == 1);
DELAY(62000000);
- printf("done");
+ printf("done\n");
lp->d_devflags = 0;
if (started)
goto top;
/*
* Perform a command w/o trailer.
*/
-vdcmd(vm, cmd, t)
+vdcmd(vm, cmd, t, slave)
register struct vba_ctlr *vm;
{
register struct vdsoftc *vd = &vdsoftc[vm->um_ctlr];
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 = 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;
{ 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 */
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 */
}
lp->d_npartitions = 8;
lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
- lp->d_rpm = 3600;
bcopy(p->name, lp->d_typename, 4);
return (1);
}