The diff below cleans up hp300's hd(4) significantly.
Changes:
- Switch to using bufq instead of disksort() directly.
- Store a pointer to the current active buf in sc_active rather than
copying b_data and b_bcount to sc_addr and sc_resid, respectively.
- Change hdfinish() to return a boolean value to indicate whether or
not there are more bufs in the queue; it's now the caller's job to
dequeue the next buf if necessary.
- Eliminate useless HDF_{OPENING,CLOSING} flags.
- Use disk_openpart() and disk_closepart() instead of reimplementing
the same logic. Also, pass dk_openmask to setdisklabel() in
hdioctl().
- Miscellaneous little cleanups.
- Convert to ANSI function definitions.
I don't even have an hp300 (and "make TARGET=hp300 cross-tools" fails
on amd64), so I'd appreciate if someone could at least compile test
this for me. Even better if you actually have an hd(4) and can verify
it still works. :-)
Thanks!
Index: hdvar.h
===================================================================
RCS file: /home/mdempsky/anoncvs/cvs/src/sys/arch/hp300/dev/hdvar.h,v
retrieving revision 1.11
diff -u -p -r1.11 hdvar.h
--- hdvar.h 5 Jun 2011 18:40:33 -0000 1.11
+++ hdvar.h 6 Jul 2011 08:09:09 -0000
@@ -63,14 +63,13 @@ struct hd_softc {
int sc_punit; /* physical unit on slave */
int sc_flags;
short sc_type;
- char *sc_addr;
- int sc_resid;
int sc_errcnt;
struct hpibqueue sc_hq; /* hpib job queue entry */
struct hd_iocmd sc_ioc;
struct hd_rscmd sc_rsc;
struct hd_stat sc_stat;
- struct buf sc_tab; /* buffer queue */
+ struct bufq sc_bufq; /* buffer queue */
+ struct buf *sc_active; /* active buffer */
#ifdef DEBUG
struct hdstats sc_stats;
#endif
@@ -80,9 +79,7 @@ struct hd_softc {
/* sc_flags values */
#define HDF_SEEK 0x01
#define HDF_SWAIT 0x02
-#define HDF_OPENING 0x04
-#define HDF_CLOSING 0x08
-#define HDF_WANTED 0x10
+#define HDF_WANTED 0x04
#ifdef _KERNEL
extern const struct hdidentinfo hdidentinfo[];
Index: hd.c
===================================================================
RCS file: /home/mdempsky/anoncvs/cvs/src/sys/arch/hp300/dev/hd.c,v
retrieving revision 1.69
diff -u -p -r1.69 hd.c
--- hd.c 6 Jul 2011 04:49:35 -0000 1.69
+++ hd.c 6 Jul 2011 08:14:48 -0000
@@ -230,7 +230,7 @@ const struct hdidentinfo hdidentinfo[] =
{ HD2203AID, 0, "2203A", NHD2203ABPT,
NHD2203ATRK, 1449, 1309896 }
};
-const int numhdidentinfo = sizeof(hdidentinfo) / sizeof(hdidentinfo[0]);
+const int numhdidentinfo = nitems(hdidentinfo);
bdev_decl(hd);
cdev_decl(hd);
@@ -241,7 +241,7 @@ void hdreset(int, int, int);
void hdustart(struct hd_softc *);
int hdgetdisklabel(dev_t, struct hd_softc *, struct disklabel *, int);
void hdrestart(void *);
-struct buf *hdfinish(struct hd_softc *, struct buf *);
+int hdfinish(struct hd_softc *, struct buf *);
void hdstart(void *);
void hdinterrupt(void *);
@@ -266,9 +266,7 @@ struct cfdriver hd_cd = {
#define hdlookup(unit) (struct hd_softc *)device_lookup(&hd_cd, (unit))
int
-hdmatch(parent, match, aux)
- struct device *parent;
- void *match, *aux;
+hdmatch(struct device *parent, void *match, void *aux)
{
struct hpibbus_attach_args *ha = aux;
@@ -276,9 +274,7 @@ hdmatch(parent, match, aux)
}
void
-hdattach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
+hdattach(struct device *parent, struct device *self, void *aux)
{
struct hd_softc *sc = (struct hd_softc *)self;
struct hpibbus_attach_args *ha = aux;
@@ -292,6 +288,7 @@ hdattach(parent, self, aux)
/*
* Initialize and attach the disk structure.
*/
+ bufq_init(&sc->sc_bufq, BUFQ_DEFAULT);
sc->sc_dkdev.dk_name = sc->sc_dev.dv_xname;
disk_attach(&sc->sc_dev, &sc->sc_dkdev);
@@ -316,10 +313,7 @@ hdattach(parent, self, aux)
}
int
-hdident(parent, sc, ha)
- struct device *parent;
- struct hd_softc *sc;
- struct hpibbus_attach_args *ha;
+hdident(struct device *parent, struct hd_softc *sc, struct hpibbus_attach_args
*ha)
{
struct cs80_describe desc;
u_char stat, cmd[3];
@@ -436,8 +430,7 @@ hdident(parent, sc, ha)
}
void
-hdreset(ctlr, slave, punit)
- int ctlr, slave, punit;
+hdreset(int ctlr, int slave, int punit)
{
struct hd_ssmcmd ssmc;
struct hd_srcmd src;
@@ -476,11 +469,7 @@ hdreset(ctlr, slave, punit)
* Read or construct a disklabel
*/
int
-hdgetdisklabel(dev, rs, lp, spoofonly)
- dev_t dev;
- struct hd_softc *rs;
- struct disklabel *lp;
- int spoofonly;
+hdgetdisklabel(dev_t dev, struct hd_softc *rs, struct disklabel *lp, int
spoofonly)
{
bzero(lp, sizeof(struct disklabel));
@@ -522,17 +511,12 @@ hdgetdisklabel(dev, rs, lp, spoofonly)
}
int
-hdopen(dev, flags, mode, p)
- dev_t dev;
- int flags, mode;
- struct proc *p;
+hdopen(dev_t dev, int flags, int mode, struct proc *p)
{
- int unit = DISKUNIT(dev);
struct hd_softc *rs;
- int mask, part;
int error;
- rs = hdlookup(unit);
+ rs = hdlookup(DISKUNIT(dev));
if (rs == NULL)
return (ENXIO);
@@ -540,14 +524,12 @@ hdopen(dev, flags, mode, p)
* Fail open if we tried to attach but the disk did not answer.
*/
if (!ISSET(rs->sc_dkdev.dk_flags, DKF_CONSTRUCTED)) {
- device_unref(&rs->sc_dev);
- return (error);
+ error = ENXIO;
+ goto unref;
}
- if ((error = disk_lock(&rs->sc_dkdev)) != 0) {
- device_unref(&rs->sc_dev);
- return (error);
- }
+ if ((error = disk_lock(&rs->sc_dkdev)) != 0)
+ goto unref;
/*
* On first open, get label and partition info.
@@ -555,71 +537,33 @@ hdopen(dev, flags, mode, p)
* to stop any other opens.
*/
if (rs->sc_dkdev.dk_openmask == 0) {
- rs->sc_flags |= HDF_OPENING;
error = hdgetdisklabel(dev, rs, rs->sc_dkdev.dk_label, 0);
- rs->sc_flags &= ~HDF_OPENING;
if (error == EIO)
- goto out;
+ goto unlock;
}
- part = DISKPART(dev);
- mask = 1 << part;
+ error = disk_openpart(&rs->sc_dkdev, DISKPART(dev), mode, 1);
- /* Check that the partition exists. */
- if (part != RAW_PART &&
- (part > rs->sc_dkdev.dk_label->d_npartitions ||
- rs->sc_dkdev.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
- error = ENXIO;
- goto out;
- }
-
- /* Ensure only one open at a time. */
- switch (mode) {
- case S_IFCHR:
- rs->sc_dkdev.dk_copenmask |= mask;
- break;
- case S_IFBLK:
- rs->sc_dkdev.dk_bopenmask |= mask;
- break;
- }
- rs->sc_dkdev.dk_openmask =
- rs->sc_dkdev.dk_copenmask | rs->sc_dkdev.dk_bopenmask;
-
- error = 0;
-out:
+ unlock:
disk_unlock(&rs->sc_dkdev);
+ unref:
device_unref(&rs->sc_dev);
return (error);
}
int
-hdclose(dev, flag, mode, p)
- dev_t dev;
- int flag, mode;
- struct proc *p;
+hdclose(dev_t dev, int flag, int mode, struct proc *p)
{
- int unit = DISKUNIT(dev);
struct hd_softc *rs;
- struct disk *dk;
- int mask, s;
+ int s;
- rs = hdlookup(unit);
+ rs = hdlookup(DISKUNIT(dev));
if (rs == NULL)
return (ENXIO);
disk_lock_nointr(&rs->sc_dkdev);
- mask = 1 << DISKPART(dev);
- dk = &rs->sc_dkdev;
- switch (mode) {
- case S_IFCHR:
- dk->dk_copenmask &= ~mask;
- break;
- case S_IFBLK:
- dk->dk_bopenmask &= ~mask;
- break;
- }
- dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask;
+ disk_closepart(&rs->sc_dkdev, DISKPART(dev), mode);
/*
* On last close, we wait for all activity to cease since
@@ -627,15 +571,13 @@ hdclose(dev, flag, mode, p)
* Note we don't have to about other closes since we know
* we are the last one.
*/
- if (dk->dk_openmask == 0) {
- rs->sc_flags |= HDF_CLOSING;
+ if (rs->sc_dkdev.dk_openmask == 0) {
s = splbio();
- while (rs->sc_tab.b_active) {
+ while (rs->sc_active != NULL) {
rs->sc_flags |= HDF_WANTED;
- tsleep((caddr_t)&rs->sc_tab, PRIBIO, "hdclose", 0);
+ tsleep(rs, PRIBIO, "hdclose", 0);
}
splx(s);
- rs->sc_flags &= ~(HDF_CLOSING);
}
disk_unlock(&rs->sc_dkdev);
@@ -644,15 +586,12 @@ hdclose(dev, flag, mode, p)
}
void
-hdstrategy(bp)
- struct buf *bp;
+hdstrategy(struct buf *bp)
{
- int unit = DISKUNIT(bp->b_dev);
struct hd_softc *rs;
- struct buf *dp;
int s;
- rs = hdlookup(unit);
+ rs = hdlookup(DISKUNIT(bp->b_dev));
if (rs == NULL) {
bp->b_error = ENXIO;
goto bad;
@@ -669,13 +608,11 @@ hdstrategy(bp)
if (bounds_check_with_label(bp, rs->sc_dkdev.dk_label) == -1)
goto done;
+ bufq_queue(&rs->sc_bufq, bp);
+
s = splbio();
- dp = &rs->sc_tab;
- disksort(dp, bp);
- if (dp->b_active == 0) {
- dp->b_active = 1;
+ if (rs->sc_active == NULL)
hdustart(rs);
- }
splx(s);
device_unref(&rs->sc_dev);
@@ -696,8 +633,7 @@ hdstrategy(bp)
* Called via timeout(9) when handling maintenance releases
*/
void
-hdrestart(arg)
- void *arg;
+hdrestart(void *arg)
{
int s = splbio();
hdustart((struct hd_softc *)arg);
@@ -705,50 +641,44 @@ hdrestart(arg)
}
void
-hdustart(rs)
- struct hd_softc *rs;
+hdustart(struct hd_softc *rs)
{
struct buf *bp;
- bp = rs->sc_tab.b_actf;
- rs->sc_addr = bp->b_data;
- rs->sc_resid = bp->b_bcount;
+ KASSERT(rs->sc_active == NULL);
+ bp = bufq_dequeue(&rs->sc_bufq);
+ rs->sc_active = bp;
if (hpibreq(rs->sc_dev.dv_parent, &rs->sc_hq))
hdstart(rs);
}
-struct buf *
-hdfinish(rs, bp)
- struct hd_softc *rs;
- struct buf *bp;
+int
+hdfinish(struct hd_softc *rs, struct buf *bp)
{
- struct buf *dp = &rs->sc_tab;
int s;
rs->sc_errcnt = 0;
- dp->b_actf = bp->b_actf;
bp->b_resid = 0;
s = splbio();
biodone(bp);
splx(s);
+ rs->sc_active = NULL;
hpibfree(rs->sc_dev.dv_parent, &rs->sc_hq);
- if (dp->b_actf)
- return (dp->b_actf);
- dp->b_active = 0;
+ if (bufq_peek(&rs->sc_bufq))
+ return (1);
if (rs->sc_flags & HDF_WANTED) {
rs->sc_flags &= ~HDF_WANTED;
- wakeup((caddr_t)dp);
+ wakeup(dp);
}
- return (NULL);
+ return (0);
}
void
-hdstart(arg)
- void *arg;
+hdstart(void *arg)
{
struct hd_softc *rs = arg;
struct disklabel *lp;
- struct buf *bp = rs->sc_tab.b_actf;
+ struct buf *bp = rs->sc_active;
int ctlr, slave;
daddr64_t bn;
@@ -773,7 +703,7 @@ again:
rs->sc_ioc.c_addr = HDBTOS(bn);
rs->sc_ioc.c_nop2 = C_NOP;
rs->sc_ioc.c_slen = C_SLEN;
- rs->sc_ioc.c_len = rs->sc_resid;
+ rs->sc_ioc.c_len = bp->b_bcount;
rs->sc_ioc.c_cmd = bp->b_flags & B_READ ? C_READ : C_WRITE;
#ifdef DEBUG
if (hddebug & HDB_IO)
@@ -805,7 +735,7 @@ again:
if (hddebug & HDB_ERROR)
printf("%s: hdstart: cmd %x adr %lx blk %d len %d ecnt %ld\n",
rs->sc_dev.dv_xname, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
- bp->b_blkno, rs->sc_resid, rs->sc_errcnt);
+ bp->b_blkno, bp->b_bcount, rs->sc_errcnt);
rs->sc_stats.hdretries++;
#endif
rs->sc_flags &= ~HDF_SEEK;
@@ -814,24 +744,23 @@ again:
goto again;
printf("%s: hdstart err: err: cmd 0x%x sect %ld blk %d len %d\n",
rs->sc_dev.dv_xname, rs->sc_ioc.c_cmd, rs->sc_ioc.c_addr,
- bp->b_blkno, rs->sc_resid);
+ bp->b_blkno, bp->b_bcount);
bp->b_flags |= B_ERROR;
bp->b_error = EIO;
- bp = hdfinish(rs, bp);
- if (bp) {
- rs->sc_addr = bp->b_data;
- rs->sc_resid = bp->b_bcount;
+ if (hdfinish(rs, bp)) {
+ KASSERT(rs->sc_active == NULL);
+ bp = bufq_dequeue(&rs->sc_bufq);
+ rs->sc_active = bp;
if (hpibreq(rs->sc_dev.dv_parent, &rs->sc_hq))
goto again;
}
}
void
-hdgo(arg)
- void *arg;
+hdgo(void *arg)
{
struct hd_softc *rs = arg;
- struct buf *bp = rs->sc_tab.b_actf;
+ struct buf *bp = rs->sc_active;
int rw, ctlr, slave;
ctlr = rs->sc_dev.dv_parent->dv_unit;
@@ -845,17 +774,16 @@ hdgo(arg)
#ifdef USELEDS
ledcontrol(0, 0, LED_DISK);
#endif
- hpibgo(ctlr, slave, C_EXEC, rs->sc_addr, rs->sc_resid, rw, rw != 0);
+ hpibgo(ctlr, slave, C_EXEC, bp->b_data, bp->b_bcount, rw, rw != 0);
}
/* ARGSUSED */
void
-hdinterrupt(arg)
- void *arg;
+hdinterrupt(void *arg)
{
struct hd_softc *rs = arg;
int unit = rs->sc_dev.dv_unit;
- struct buf *bp = rs->sc_tab.b_actf;
+ struct buf *bp = rs->sc_active;
u_char stat = 13; /* in case hpibrecv fails */
int rv, restart, ctlr, slave;
@@ -920,8 +848,7 @@ hdinterrupt(arg)
}
int
-hdstatus(rs)
- struct hd_softc *rs;
+hdstatus(struct hd_softc *rs)
{
int c, s;
u_char stat;
@@ -970,8 +897,7 @@ hdstatus(rs)
* 0 if we should just quietly give up.
*/
int
-hderror(unit)
- int unit;
+hderror(int unit)
{
struct hd_softc *rs = hd_cd.cd_devs[unit];
struct hd_stat *sp;
@@ -1025,7 +951,7 @@ hderror(unit)
* Note that not all errors report a block number, in that case
* we just use b_blkno.
*/
- bp = rs->sc_tab.b_actf;
+ bp = rs->sc_active;
pbn =
DL_GETPOFFSET(&rs->sc_dkdev.dk_label->d_partitions[DISKPART(bp->b_dev)]);
if ((sp->c_fef & FEF_CU) || (sp->c_fef & FEF_DR) ||
(sp->c_ief & IEF_RRMASK)) {
@@ -1075,39 +1001,25 @@ hderror(unit)
}
int
-hdread(dev, uio, flags)
- dev_t dev;
- struct uio *uio;
- int flags;
+hdread(dev_t dev, struct uio *uio, int flags)
{
-
return (physio(hdstrategy, dev, B_READ, minphys, uio));
}
int
-hdwrite(dev, uio, flags)
- dev_t dev;
- struct uio *uio;
- int flags;
+hdwrite(dev_t dev, struct uio *uio, int flags)
{
-
return (physio(hdstrategy, dev, B_WRITE, minphys, uio));
}
int
-hdioctl(dev, cmd, data, flag, p)
- dev_t dev;
- u_long cmd;
- caddr_t data;
- int flag;
- struct proc *p;
+hdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
{
- int unit = DISKUNIT(dev);
struct disklabel *lp;
struct hd_softc *sc;
int error = 0;
- sc = hdlookup(unit);
+ sc = hdlookup(DISKUNIT(dev));
if (sc == NULL)
return (ENXIO);
@@ -1144,7 +1056,7 @@ hdioctl(dev, cmd, data, flag, p)
goto exit;
error = setdisklabel(sc->sc_dkdev.dk_label,
- (struct disklabel *)data, /* sc->sc_dkdev.dk_openmask */ 0);
+ (struct disklabel *)data, sc->sc_dkdev.dk_openmask);
if (error == 0) {
if (cmd == DIOCWDINFO)
error = writedisklabel(DISKLABELDEV(dev),
@@ -1165,15 +1077,13 @@ exit:
}
daddr64_t
-hdsize(dev)
- dev_t dev;
+hdsize(dev_t dev)
{
struct hd_softc *rs;
- int unit = DISKUNIT(dev);
int part, omask;
int size;
- rs = hdlookup(unit);
+ rs = hdlookup(DISKUNIT(dev));
if (rs == NULL)
return (-1);
@@ -1206,10 +1116,7 @@ out:
#ifdef DEBUG
void
-hdprinterr(str, err, tab)
- const char *str;
- short err;
- const char **tab;
+hdprinterr(const char *str, short err, const char **tab)
{
int i;
int printed;
@@ -1231,11 +1138,7 @@ static int hddoingadump; /* simple mutex
* Non-interrupt driven, non-dma dump routine.
*/
int
-hddump(dev, blkno, va, size)
- dev_t dev;
- daddr64_t blkno;
- caddr_t va;
- size_t size;
+hddump(dev_t dev, daddr64_t blkno, caddr_t va, size_t size)
{
int sectorsize; /* size of a disk sector */
daddr64_t nsects; /* number of sectors in partition */