-/* $OpenBSD: scsiconf.c,v 1.51 2000/04/08 19:19:33 csapuntz Exp $ */
+/* $OpenBSD: scsiconf.c,v 1.52 2000/04/18 05:53:17 csapuntz Exp $ */
/* $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $ */
/*
int scsibusmatch __P((struct device *, void *, void *));
void scsibusattach __P((struct device *, struct device *, void *));
+int scsibusactivate __P((struct device *, enum devact));
+int scsibusdetach __P((struct device *, int));
+void scsibuszeroref __P((struct device *));
+
int scsibussubmatch __P((struct device *, void *, void *));
+
+
struct cfattach scsibus_ca = {
- sizeof(struct scsibus_softc), scsibusmatch, scsibusattach
+ sizeof(struct scsibus_softc), scsibusmatch, scsibusattach,
+ scsibusdetach, scsibusactivate, scsibuszeroref
};
struct cfdriver scsibus_cd = {
scsi_probe_bus(sb->sc_dev.dv_unit, -1, -1);
}
+
+int
+scsibusactivate(dev, act)
+ struct device *dev;
+ enum devact act;
+{
+ return (config_activate_children(dev, act));
+}
+
+int
+scsibusdetach (dev, type)
+ struct device *dev;
+ int type;
+{
+ return (config_detach_children(dev, type));
+}
+
+void
+scsibuszeroref(dev)
+ struct device *dev;
+{
+ struct scsibus_softc *sb = (struct scsibus_softc *)dev;
+ int i;
+
+ for (i = 0; i < sb->sc_buswidth; i++) {
+ if (sb->sc_link[i] != NULL)
+ free(sb->sc_link[i], M_DEVBUF);
+ }
+
+ free(sb->sc_link, M_DEVBUF);
+}
+
+
+
int
scsibussubmatch(parent, match, aux)
struct device *parent;
-/* $OpenBSD: sd.c,v 1.42 2000/04/08 19:19:33 csapuntz Exp $ */
+/* $OpenBSD: sd.c,v 1.43 2000/04/18 05:53:17 csapuntz Exp $ */
/* $NetBSD: sd.c,v 1.111 1997/04/02 02:29:41 mycroft Exp $ */
/*-
#include <ufs/ffs/fs.h> /* for BBSIZE and SBSIZE */
+#include <sys/vnode.h>
+
#define SDOUTSTANDING 4
#define SDUNIT(dev) DISKUNIT(dev)
+#define SDMINOR(unit, part) DISKMINOR(unit, part)
#define SDPART(dev) DISKPART(dev)
#define MAKESDDEV(maj, unit, part) MAKEDISKDEV(maj, unit, part)
int sdmatch __P((struct device *, void *, void *));
void sdattach __P((struct device *, struct device *, void *));
-int sdlock __P((struct sd_softc *));
-void sdunlock __P((struct sd_softc *));
+int sdactivate __P((struct device *, enum devact));
+int sddetach __P((struct device *, int));
+void sdzeroref __P((struct device *));
+
void sdminphys __P((struct buf *));
void sdgetdisklabel __P((dev_t, struct sd_softc *, struct disklabel *,
struct cpu_disklabel *, int));
void viscpy __P((u_char *, u_char *, int));
struct cfattach sd_ca = {
- sizeof(struct sd_softc), sdmatch, sdattach
+ sizeof(struct sd_softc), sdmatch, sdattach,
+ sddetach, sdactivate, sdzeroref
};
struct cfdriver sd_cd = {
extern struct sd_ops sd_scsibus_ops;
extern struct sd_ops sd_atapibus_ops;
+#define sdlock(softc) disk_lock(&(softc)->sc_dk)
+#define sdunlock(softc) disk_unlock(&(softc)->sc_dk)
+#define sdlookup(unit) (struct sd_softc *)device_lookup(&sd_cd, (unit))
+
int
sdmatch(parent, match, aux)
struct device *parent;
}
printf("\n");
-#ifdef notyet
/*
* Establish a shutdown hook so that we can ensure that
* our data has actually made it onto the platter at
shutdownhook_establish(sd_shutdown, sd)) == NULL)
printf("%s: WARNING: unable to establish shutdown hook\n",
sd->sc_dev.dv_xname);
-#endif
}
-/*
- * Wait interruptibly for an exclusive lock.
- *
- * XXX
- * Several drivers do this; it should be abstracted and made MP-safe.
- */
int
-sdlock(sd)
- struct sd_softc *sd;
+sdactivate(self, act)
+ struct device *self;
+ enum devact act;
{
- int error;
+ int rv = 0;
+
+ switch (act) {
+ case DVACT_ACTIVATE:
+ break;
+
+ case DVACT_DEACTIVATE:
+ /*
+ * Nothing to do; we key off the device's DVF_ACTIVATE.
+ */
+ break;
+ }
+ return (rv);
+}
+
+
+int
+sddetach(self, flags)
+ struct device *self;
+ int flags;
+{
+ struct sd_softc *sc = (struct sd_softc *)self;
+ struct buf *dp, *bp;
+ int s, bmaj, cmaj, mn;
- while ((sd->flags & SDF_LOCKED) != 0) {
- sd->flags |= SDF_WANTED;
- if ((error = tsleep(sd, PRIBIO | PCATCH, "sdlck", 0)) != 0)
- return error;
+ /* Remove unprocessed buffers from queue */
+ s = splbio();
+ for (dp = &sc->buf_queue; (bp = dp->b_actf) != NULL; ) {
+ dp->b_actf = bp->b_actf;
+
+ bp->b_error = ENXIO;
+ bp->b_flags |= B_ERROR;
+ biodone(bp);
}
- sd->flags |= SDF_LOCKED;
- return 0;
+ splx(s);
+
+ /* locate the major number */
+ mn = SDMINOR(self->dv_unit, 0);
+
+ for (bmaj = 0; bmaj < nblkdev; bmaj++)
+ if (bdevsw[bmaj].d_open == sdopen)
+ vdevgone(bmaj, mn, mn + MAXPARTITIONS - 1, VBLK);
+ for (cmaj = 0; cmaj < nchrdev; cmaj++)
+ if (cdevsw[cmaj].d_open == sdopen)
+ vdevgone(cmaj, mn, mn + MAXPARTITIONS - 1, VCHR);
+
+ /* Get rid of the shutdown hook. */
+ if (sc->sc_sdhook != NULL)
+ shutdownhook_disestablish(sc->sc_sdhook);
+
+#if NRND > 0
+ /* Unhook the entropy source. */
+ rnd_detach_source(&sc->rnd_source);
+#endif
+
+ return (0);
}
-/*
- * Unlock and wake up any waiters.
- */
void
-sdunlock(sd)
- struct sd_softc *sd;
+sdzeroref(self)
+ struct device *self;
{
+ struct sd_softc *sd = (struct sd_softc *)self;
- sd->flags &= ~SDF_LOCKED;
- if ((sd->flags & SDF_WANTED) != 0) {
- sd->flags &= ~SDF_WANTED;
- wakeup(sd);
- }
+ /* Detach disk. */
+ disk_detach(&sd->sc_dk);
}
/*
int error;
unit = SDUNIT(dev);
- if (unit >= sd_cd.cd_ndevs)
- return ENXIO;
- sd = sd_cd.cd_devs[unit];
- if (!sd)
+ sd = sdlookup(unit);
+ if (sd == NULL)
return ENXIO;
sc_link = sd->sc_link;
("sdopen: dev=0x%x (unit %d (of %d), partition %d)\n", dev, unit,
sd_cd.cd_ndevs, part));
- if ((error = sdlock(sd)) != 0)
+ if ((error = sdlock(sd)) != 0) {
+ device_unref(&sd->sc_dev);
return error;
+ }
if (sd->sc_dk.dk_openmask != 0) {
/*
SC_DEBUG(sc_link, SDEV_DB3, ("open complete\n"));
sdunlock(sd);
+ device_unref(&sd->sc_dev);
return 0;
bad2:
bad3:
sdunlock(sd);
+ device_unref(&sd->sc_dev);
return error;
}
int flag, fmt;
struct proc *p;
{
- struct sd_softc *sd = sd_cd.cd_devs[SDUNIT(dev)];
+ struct sd_softc *sd;
int part = SDPART(dev);
int error;
+ sd = sdlookup(SDUNIT(dev));
+ if (sd == NULL)
+ return ENXIO;
+
if ((error = sdlock(sd)) != 0)
return error;
}
sdunlock(sd);
+ device_unref(&sd->sc_dev);
return 0;
}
sdstrategy(bp)
struct buf *bp;
{
- struct sd_softc *sd = sd_cd.cd_devs[SDUNIT(bp->b_dev)];
+ struct sd_softc *sd;
int s;
+ sd = sdlookup(SDUNIT(bp->b_dev));
+ if (sd == NULL) {
+ bp->b_error = ENXIO;
+ goto bad;
+ }
+
SC_DEBUG(sd->sc_link, SDEV_DB2, ("sdstrategy "));
SC_DEBUG(sd->sc_link, SDEV_DB1,
("%ld bytes @ blk %d\n", bp->b_bcount, bp->b_blkno));
sdstart(sd);
splx(s);
+
+ device_unref(&sd->sc_dev);
return;
bad:
*/
bp->b_resid = bp->b_bcount;
biodone(bp);
+
+ if (sd != NULL)
+ device_unref(&sd->sc_dev);
}
/*
sdminphys(bp)
struct buf *bp;
{
- struct sd_softc *sd = sd_cd.cd_devs[SDUNIT(bp->b_dev)];
+ struct sd_softc *sd;
long max;
+ sd = sdlookup(SDUNIT(bp->b_dev));
+ if (sd == NULL)
+ return; /* XXX - right way to fail this? */
+
/*
* If the device is ancient, we want to make sure that
* the transfer fits into a 6-byte cdb.
}
(*sd->sc_link->adapter->scsi_minphys)(bp);
+
+ device_unref(&sd->sc_dev);
}
int
int flag;
struct proc *p;
{
- struct sd_softc *sd = sd_cd.cd_devs[SDUNIT(dev)];
- int error;
+ struct sd_softc *sd;
+ int error = 0;
int part = SDPART(dev);
+ sd = sdlookup(SDUNIT(dev));
+ if (sd == NULL)
+ return ENXIO;
+
SC_DEBUG(sd->sc_link, SDEV_DB2, ("sdioctl 0x%lx ", cmd));
/*
break;
/* FALLTHROUGH */
default:
- if ((sd->sc_link->flags & SDEV_OPEN) == 0)
- return (ENODEV);
- else
- return (EIO);
+ if ((sd->sc_link->flags & SDEV_OPEN) == 0) {
+ error = ENODEV;
+ goto exit;
+ } else {
+ error = EIO;
+ goto exit;
+ }
}
}
case DIOCRLDINFO:
sdgetdisklabel(dev, sd, sd->sc_dk.dk_label,
sd->sc_dk.dk_cpulabel, 0);
- return 0;
+ goto exit;
case DIOCGPDINFO: {
struct cpu_disklabel osdep;
sdgetdisklabel(dev, sd, (struct disklabel *)addr,
&osdep, 1);
- return 0;
+ goto exit;
}
case DIOCGDINFO:
*(struct disklabel *)addr = *(sd->sc_dk.dk_label);
- return 0;
+ goto exit;
case DIOCGPART:
((struct partinfo *)addr)->disklab = sd->sc_dk.dk_label;
((struct partinfo *)addr)->part =
&sd->sc_dk.dk_label->d_partitions[SDPART(dev)];
- return 0;
+ goto exit;
case DIOCWDINFO:
case DIOCSDINFO:
- if ((flag & FWRITE) == 0)
- return EBADF;
+ if ((flag & FWRITE) == 0) {
+ error = EBADF;
+ goto exit;
+ }
if ((error = sdlock(sd)) != 0)
- return error;
+ goto exit;
sd->flags |= SDF_LABELLING;
error = setdisklabel(sd->sc_dk.dk_label,
sd->flags &= ~SDF_LABELLING;
sdunlock(sd);
- return error;
+ goto exit;
case DIOCWLABEL:
- if ((flag & FWRITE) == 0)
- return EBADF;
+ if ((flag & FWRITE) == 0) {
+ error = EBADF;
+ goto exit;
+ }
if (*(int *)addr)
sd->flags |= SDF_WLABEL;
else
sd->flags &= ~SDF_WLABEL;
- return 0;
+ goto exit;
case DIOCLOCK:
- return scsi_prevent(sd->sc_link,
+ error = scsi_prevent(sd->sc_link,
(*(int *)addr) ? PR_PREVENT : PR_ALLOW, 0);
+ goto exit;
case MTIOCTOP:
- if (((struct mtop *)addr)->mt_op != MTOFFL)
- return EIO;
+ if (((struct mtop *)addr)->mt_op != MTOFFL) {
+ error = EIO;
+ goto exit;
+ }
/* FALLTHROUGH */
case DIOCEJECT:
- if ((sd->sc_link->flags & SDEV_REMOVABLE) == 0)
- return ENOTTY;
+ if ((sd->sc_link->flags & SDEV_REMOVABLE) == 0) {
+ error = ENOTTY;
+ goto exit;
+ }
sd->sc_link->flags |= SDEV_EJECTING;
- return 0;
+ goto exit;
case SCIOCREASSIGN:
- if ((flag & FWRITE) == 0)
- return EBADF;
+ if ((flag & FWRITE) == 0) {
+ error = EBADF;
+ goto exit;
+ }
error = sd_reassign_blocks(sd, (*(int *)addr));
- return error;
+ goto exit;
default:
- if (part != RAW_PART)
- return ENOTTY;
- return scsi_do_ioctl(sd->sc_link, dev, cmd, addr, flag, p);
+ if (part != RAW_PART) {
+ error = ENOTTY;
+ goto exit;
+ }
+ error = scsi_do_ioctl(sd->sc_link, dev, cmd, addr, flag, p);
}
-#ifdef DIAGNOSTIC
- panic("sdioctl: impossible");
-#endif
+ exit:
+ device_unref(&sd->sc_dev);
+ return (error);
}
/*
dev_t dev;
{
struct sd_softc *sd;
- int part, unit, omask;
+ int part, omask;
int size;
- unit = SDUNIT(dev);
- if (unit >= sd_cd.cd_ndevs)
- return -1;
- sd = sd_cd.cd_devs[unit];
+ sd = sdlookup(SDUNIT(dev));
if (sd == NULL)
return -1;
part = SDPART(dev);
omask = sd->sc_dk.dk_openmask & (1 << part);
- if (omask == 0 && sdopen(dev, 0, S_IFBLK, NULL) != 0)
- return -1;
+ if (omask == 0 && sdopen(dev, 0, S_IFBLK, NULL) != 0) {
+ size = -1;
+ goto exit;
+ }
if ((sd->sc_link->flags & SDEV_MEDIA_LOADED) == 0)
size = -1;
else if (sd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
size = sd->sc_dk.dk_label->d_partitions[part].p_size *
(sd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
if (omask == 0 && sdclose(dev, 0, S_IFBLK, NULL) != 0)
- return -1;
+ size = -1;
+
+ exit:
+ device_unref(&sd->sc_dev);
return size;
}