Add support for wedges to the ATA disk driver.

This commit is contained in:
thorpej 2004-09-25 03:34:02 +00:00
parent ef92b0de59
commit cc79c7aeb0
2 changed files with 68 additions and 28 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: wd.c,v 1.293 2004/09/16 20:52:43 bouyer Exp $ */
/* $NetBSD: wd.c,v 1.294 2004/09/25 03:34:02 thorpej Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved.
@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.293 2004/09/16 20:52:43 bouyer Exp $");
__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.294 2004/09/25 03:34:02 thorpej Exp $");
#ifndef ATADEBUG
#define ATADEBUG
@ -195,7 +195,7 @@ void wd_shutdown(void *);
int wd_getcache(struct wd_softc *, int *);
int wd_setcache(struct wd_softc *, int);
struct dkdriver wddkdriver = { wdstrategy };
struct dkdriver wddkdriver = { wdstrategy, minphys };
#ifdef HAS_BAD144_HANDLING
static void bad144intern(struct wd_softc *);
@ -275,8 +275,6 @@ wdattach(struct device *parent, struct device *self, void *aux)
const struct wd_quirk *wdq;
ATADEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE);
lockinit(&wd->sc_lock, PRIBIO | PCATCH, "wdlock", 0, 0);
callout_init(&wd->sc_restart_ch);
bufq_alloc(&wd->sc_q, BUFQ_DISK_DEFAULT_STRAT()|BUFQ_SORT_RAWBLOCK);
#ifdef WD_SOFTBADSECT
@ -389,6 +387,9 @@ wdattach(struct device *parent, struct device *self, void *aux)
rnd_attach_source(&wd->rnd_source, wd->sc_dev.dv_xname,
RND_TYPE_DISK, 0);
#endif
/* Discover wedges on this disk. */
dkwedge_discover(&wd->sc_dk);
}
int
@ -428,6 +429,9 @@ wddetach(struct device *self, int flags)
vdevgone(cmaj, mn, mn, VCHR);
}
/* Delete all of our wedges. */
dkwedge_delall(&sc->sc_dk);
s = splbio();
/* Kill off any queued buffers. */
@ -465,7 +469,6 @@ wddetach(struct device *self, int flags)
rnd_detach_source(&sc->rnd_source);
#endif
lockmgr(&sc->sc_lock, LK_DRAIN, NULL);
sc->drvp->drive_flags = 0; /* no drive any more here */
return (0);
@ -870,16 +873,27 @@ wdopen(dev_t dev, int flag, int fmt, struct proc *p)
if ((wd->sc_dev.dv_flags & DVF_ACTIVE) == 0)
return (ENODEV);
part = WDPART(dev);
if ((error = lockmgr(&wd->sc_dk.dk_openlock, LK_EXCLUSIVE, NULL)) != 0)
return (error);
/*
* If there are wedges, and this is not RAW_PART, then we
* need to fail.
*/
if (wd->sc_dk.dk_nwedges != 0 && part != RAW_PART) {
error = EBUSY;
goto bad1;
}
/*
* If this is the first open of this device, add a reference
* to the adapter.
*/
if (wd->sc_dk.dk_openmask == 0 &&
(error = wd->atabus->ata_addref(wd->drvp)) != 0)
return (error);
if ((error = lockmgr(&wd->sc_lock, LK_EXCLUSIVE, NULL)) != 0)
goto bad4;
goto bad1;
if (wd->sc_dk.dk_openmask != 0) {
/*
@ -888,7 +902,7 @@ wdopen(dev_t dev, int flag, int fmt, struct proc *p)
*/
if ((wd->sc_flags & WDF_LOADED) == 0) {
error = EIO;
goto bad3;
goto bad2;
}
} else {
if ((wd->sc_flags & WDF_LOADED) == 0) {
@ -902,14 +916,12 @@ wdopen(dev_t dev, int flag, int fmt, struct proc *p)
}
}
part = WDPART(dev);
/* Check that the partition exists. */
if (part != RAW_PART &&
(part >= wd->sc_dk.dk_label->d_npartitions ||
wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
error = ENXIO;
goto bad;
goto bad2;
}
/* Insure only one open at a time. */
@ -924,18 +936,14 @@ wdopen(dev_t dev, int flag, int fmt, struct proc *p)
wd->sc_dk.dk_openmask =
wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;
lockmgr(&wd->sc_lock, LK_RELEASE, NULL);
(void) lockmgr(&wd->sc_dk.dk_openlock, LK_RELEASE, NULL);
return 0;
bad:
if (wd->sc_dk.dk_openmask == 0) {
}
bad3:
lockmgr(&wd->sc_lock, LK_RELEASE, NULL);
bad4:
bad2:
if (wd->sc_dk.dk_openmask == 0)
wd->atabus->ata_delref(wd->drvp);
bad1:
(void) lockmgr(&wd->sc_dk.dk_openlock, LK_RELEASE, NULL);
return error;
}
@ -947,7 +955,8 @@ wdclose(dev_t dev, int flag, int fmt, struct proc *p)
int error;
ATADEBUG_PRINT(("wdclose\n"), DEBUG_FUNCS);
if ((error = lockmgr(&wd->sc_lock, LK_EXCLUSIVE, NULL)) != 0)
if ((error = lockmgr(&wd->sc_dk.dk_openlock, LK_EXCLUSIVE, NULL)) != 0)
return error;
switch (fmt) {
@ -970,7 +979,7 @@ wdclose(dev_t dev, int flag, int fmt, struct proc *p)
wd->atabus->ata_delref(wd->drvp);
}
lockmgr(&wd->sc_lock, LK_RELEASE, NULL);
(void) lockmgr(&wd->sc_dk.dk_openlock, LK_RELEASE, NULL);
return 0;
}
@ -1236,7 +1245,8 @@ wdioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, struct proc *p)
#endif
lp = (struct disklabel *)addr;
if ((error = lockmgr(&wd->sc_lock, LK_EXCLUSIVE, NULL)) != 0)
if ((error = lockmgr(&wd->sc_dk.dk_openlock, LK_EXCLUSIVE,
NULL)) != 0)
goto bad;
wd->sc_flags |= WDF_LABELLING;
@ -1260,7 +1270,7 @@ wdioctl(dev_t dev, u_long xfer, caddr_t addr, int flag, struct proc *p)
}
wd->sc_flags &= ~WDF_LABELLING;
lockmgr(&wd->sc_lock, LK_RELEASE, NULL);
(void) lockmgr(&wd->sc_dk.dk_openlock, LK_RELEASE, NULL);
bad:
#ifdef __HAVE_OLD_DISKLABEL
if (newlabel != NULL)
@ -1385,6 +1395,37 @@ bad:
return(error);
}
case DIOCAWEDGE:
{
struct dkwedge_info *dkw = (void *) addr;
if ((flag & FWRITE) == 0)
return (EBADF);
/* If the ioctl happens here, the parent is us. */
strcpy(dkw->dkw_parent, wd->sc_dev.dv_xname);
return (dkwedge_add(dkw));
}
case DIOCDWEDGE:
{
struct dkwedge_info *dkw = (void *) addr;
if ((flag & FWRITE) == 0)
return (EBADF);
/* If the ioctl happens here, the parent is us. */
strcpy(dkw->dkw_parent, wd->sc_dev.dv_xname);
return (dkwedge_del(dkw));
}
case DIOCLWEDGES:
{
struct dkwedge_list *dkwl = (void *) addr;
return (dkwedge_list(&wd->sc_dk, dkwl, p));
}
default:
return ENOTTY;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: wdvar.h,v 1.27 2004/08/30 09:34:42 drochner Exp $ */
/* $NetBSD: wdvar.h,v 1.28 2004/09/25 03:34:02 thorpej Exp $ */
/*
* Copyright (c) 1998, 2001 Manuel Bouyer.
@ -40,7 +40,6 @@ struct wd_softc {
/* General disk infos */
struct device sc_dev;
struct disk sc_dk;
struct lock sc_lock;
struct bufq_state sc_q;
struct callout sc_restart_ch;
int sc_quirks; /* any quirks drive might have */