Пример #1
0
Файл: ld.c Проект: MarginC/kame
int
ldsize(dev_t dev)
{
	struct ld_softc *sc;
	int part, unit, omask, size;

	unit = DISKUNIT(dev);
	if ((sc = device_lookup(&ld_cd, unit)) == NULL)
		return (ENODEV);
	if ((sc->sc_flags & LDF_ENABLED) == 0)
		return (ENODEV);
	part = DISKPART(dev);

	omask = sc->sc_dk.dk_openmask & (1 << part);

	if (omask == 0 && ldopen(dev, 0, S_IFBLK, NULL) != 0)
		return (-1);
	else if (sc->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
		size = -1;
	else
		size = sc->sc_dk.dk_label->d_partitions[part].p_size *
		    (sc->sc_dk.dk_label->d_secsize / DEV_BSIZE);
	if (omask == 0 && ldclose(dev, 0, S_IFBLK, NULL) != 0)
		return (-1);

	return (size);
}
Пример #2
0
int
vndclose(dev_t dev, int flags, int mode, struct proc *p)
{
	int unit = DISKUNIT(dev);
	struct vnd_softc *sc;
	int part;

	DNPRINTF(VDB_FOLLOW, "vndclose(%x, %x, %x, %p)\n", dev, flags, mode, p);

	if (unit >= numvnd)
		return (ENXIO);
	sc = &vnd_softc[unit];

	disk_lock_nointr(&sc->sc_dk);

	part = DISKPART(dev);

	disk_closepart(&sc->sc_dk, part, mode);

#if 0
	if (sc->sc_dk.dk_openmask == 0)
		sc->sc_flags &= ~VNF_HAVELABEL;
#endif

	disk_unlock(&sc->sc_dk);
	return (0);
}
Пример #3
0
static struct biosdisk_info *
fd2biosinfo(struct proc *p, struct file *fp)
{
	struct vnode *vp;
	const char *blkname;
	char diskname[16];
	int i;
	struct nativedisk_info *nip;
	struct disklist *dl = x86_alldisks;

	if (fp->f_type != DTYPE_VNODE)
		return NULL;
	vp = (struct vnode *)fp->f_data;

	if (vp->v_type != VBLK)
		return NULL;

	blkname = devsw_blk2name(major(vp->v_rdev));
	snprintf(diskname, sizeof diskname, "%s%llu", blkname,
	    (unsigned long long)DISKUNIT(vp->v_rdev));

	for (i = 0; i < dl->dl_nnativedisks; i++) {
		nip = &dl->dl_nativedisks[i];
		if (strcmp(diskname, nip->ni_devname))
			continue;
		if (nip->ni_nmatches != 0)
			return &dl->dl_biosdisks[nip->ni_biosmatches[0]];
	}

	return NULL;
}
Пример #4
0
int
rdopen(dev_t dev, int flag, int fmt, struct proc *p)
{
	struct rd_softc *sc;
	u_int unit, part;
	int error;

	unit = DISKUNIT(dev);
	part = DISKPART(dev);

	sc = rdlookup(unit);
	if (sc == NULL)
		return (ENXIO);

	if ((error = disk_lock(&sc->sc_dk)) != 0)
		goto unref;

	if (sc->sc_dk.dk_openmask == 0) {
		/* Load the partition info if not already loaded. */
		if ((error = rdgetdisklabel(dev, sc, sc->sc_dk.dk_label, 0))
		    != 0)
			goto unlock;
	}

	error = disk_openpart(&sc->sc_dk, part, fmt, 1);

 unlock:
	disk_unlock(&sc->sc_dk);
 unref:
	device_unref(&sc->sc_dev);
	return (error);
}
Пример #5
0
/*
 * I/O controls.
 */
int
rxioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
{
	int unit = DISKUNIT(dev);
	struct disklabel *lp;
	struct rx_softc *rx = device_lookup_private(&rx_cd, unit);
	int error = 0;

	lp = rx->ra_disk.dk_label;

	switch (cmd) {

	case DIOCGDINFO:
		memcpy(data, lp, sizeof (struct disklabel));
		break;

	case DIOCGPART:
		((struct partinfo *)data)->disklab = lp;
		((struct partinfo *)data)->part =
		    &lp->d_partitions[DISKPART(dev)];
		break;


	case DIOCWDINFO:
	case DIOCSDINFO:
	case DIOCWLABEL:
		break;

	default:
		error = ENOTTY;
		break;
	}
	return (error);
}
Пример #6
0
void
cdminphys(struct buf *bp)
{
	struct cd_softc *cd;
	long max;

	cd = cdlookup(DISKUNIT(bp->b_dev));
	if (cd == NULL)
		return;

	/*
	 * If the device is ancient, we want to make sure that
	 * the transfer fits into a 6-byte cdb.
	 *
	 * XXX Note that the SCSI-I spec says that 256-block transfers
	 * are allowed in a 6-byte read/write, and are specified
	 * by setting the "length" to 0.  However, we're conservative
	 * here, allowing only 255-block transfers in case an
	 * ancient device gets confused by length == 0.  A length of 0
	 * in a 10-byte read/write actually means 0 blocks.
	 */
	if (cd->flags & CDF_ANCIENT) {
		max = cd->sc_dk.dk_label->d_secsize * 0xff;

		if (bp->b_bcount > max)
			bp->b_bcount = max;
	}

	(*cd->sc_link->adapter->scsi_minphys)(bp);

	device_unref(&cd->sc_dev);
}
Пример #7
0
static inline struct ra_softc *
mscp_device_lookup(dev_t dev)
{
	struct ra_softc *ra;
	int unit;

	unit = DISKUNIT(dev);
#if NRA
	if (cdevsw_lookup(dev) == &ra_cdevsw)
		ra = device_lookup_private(&ra_cd, unit);
	else
#endif
#if NRACD
	if (cdevsw_lookup(dev) == &racd_cdevsw)
		ra = device_lookup_private(&racd_cd, unit);
	else
#endif
#if NRX
	if (cdevsw_lookup(dev) == &rx_cdevsw)
		ra = device_lookup_private(&rx_cd, unit);
	else
#endif
		panic("mscp_device_lookup: unexpected major %"PRIu32" unit %u",
		    major(dev), unit);
	return ra;
}
Пример #8
0
daddr_t
wdsize(dev_t dev)
{
	struct wd_softc *wd;
	struct disklabel *lp;
	int part, omask;
	daddr_t size;

	WDCDEBUG_PRINT(("wdsize\n"), DEBUG_FUNCS);

	wd = wdlookup(DISKUNIT(dev));
	if (wd == NULL)
		return (-1);

	part = DISKPART(dev);
	omask = wd->sc_dk.dk_openmask & (1 << part);

	if (omask == 0 && wdopen(dev, 0, S_IFBLK, NULL) != 0) {
		size = -1;
		goto exit;
	}

	lp = wd->sc_dk.dk_label;
	size = DL_SECTOBLK(lp, DL_GETPSIZE(&lp->d_partitions[part]));
	if (omask == 0 && wdclose(dev, 0, S_IFBLK, NULL) != 0)
		size = -1;

 exit:
	device_unref(&wd->sc_dev);
	return (size);
}
Пример #9
0
int
prestoopen(dev_t dev, int flag, int fmt, struct proc *proc)
{
	int unit, part;
	struct presto_softc *sc;

	unit = DISKUNIT(dev);
	sc = (struct presto_softc *)device_lookup(&presto_cd, unit);
	if (sc == NULL)
		return (ENXIO);

	/* only allow valid partitions */
	part = DISKPART(dev);
	if (part != RAW_PART &&
	    (part >= sc->sc_dk.dk_label->d_npartitions ||
	    sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED))
		return (ENXIO);

	/* update open masks */
	switch (fmt) {
	case S_IFCHR:
		sc->sc_dk.dk_copenmask |= (1 << part);
		break;
	case S_IFBLK:
		sc->sc_dk.dk_bopenmask |= (1 << part);
		break;
	}
	sc->sc_dk.dk_openmask = sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;

	return (0);
}
/*
 * Returns the hibernate write I/O function to use on this machine
 */
hibio_fn
get_hibernate_io_function(void)
{
	char *blkname = findblkname(major(swdevt[0].sw_dev));

	if (blkname == NULL)
		return NULL;
#if NWD > 0
	if (strcmp(blkname, "wd") == 0) {
		extern int wd_hibernate_io(dev_t dev, daddr_t blkno,
		    vaddr_t addr, size_t size, int op, void *page);
		return wd_hibernate_io;
	}
#endif
#if NAHCI > 0 && NSD > 0
	if (strcmp(blkname, "sd") == 0) {
		extern struct cfdriver sd_cd;
		extern int ahci_hibernate_io(dev_t dev, daddr_t blkno,
		    vaddr_t addr, size_t size, int op, void *page);
		struct device *dv;

		dv = disk_lookup(&sd_cd, DISKUNIT(swdevt[0].sw_dev));
		if (dv && dv->dv_parent && dv->dv_parent->dv_parent &&
		    strcmp(dv->dv_parent->dv_parent->dv_cfdata->cf_driver->cd_name,
		    "ahci") == 0)
			return ahci_hibernate_io;
	}
#endif
	return NULL;
}
Пример #11
0
int
edmcaclose(dev_t dev, int flag, int fmt, struct lwp *l)
{
    struct ed_softc *wd = device_lookup_private(&ed_cd, DISKUNIT(dev));
    int part = DISKPART(dev);

    ATADEBUG_PRINT(("edmcaclose\n"), DEBUG_FUNCS);

    mutex_enter(&wd->sc_dk.dk_openlock);

    switch (fmt) {
    case S_IFCHR:
        wd->sc_dk.dk_copenmask &= ~(1 << part);
        break;
    case S_IFBLK:
        wd->sc_dk.dk_bopenmask &= ~(1 << part);
        break;
    }
    wd->sc_dk.dk_openmask =
        wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;

    if (wd->sc_dk.dk_openmask == 0) {
#if 0
        wd_flushcache(wd, AT_WAIT);
#endif
        /* XXXX Must wait for I/O to complete! */

        if (! (wd->sc_flags & WDF_KLABEL))
            wd->sc_flags &= ~WDF_LOADED;
    }

    mutex_exit(&wd->sc_dk.dk_openlock);

    return 0;
}
Пример #12
0
int
wdclose(dev_t dev, int flag, int fmt, struct proc *p)
{
	struct wd_softc *wd;
	int part = DISKPART(dev);

	wd = wdlookup(DISKUNIT(dev));
	if (wd == NULL)
		return ENXIO;

	WDCDEBUG_PRINT(("wdclose\n"), DEBUG_FUNCS);

	disk_lock_nointr(&wd->sc_dk);

	disk_closepart(&wd->sc_dk, part, fmt);

	if (wd->sc_dk.dk_openmask == 0) {
		wd_flushcache(wd, 0);
		/* XXXX Must wait for I/O to complete! */
	}

	disk_unlock(&wd->sc_dk);

	device_unref(&wd->sc_dev);
	return (0);
}
Пример #13
0
int
edmcasize(dev_t dev)
{
    struct ed_softc *wd;
    int part, omask;
    int size;

    ATADEBUG_PRINT(("edsize\n"), DEBUG_FUNCS);

    wd = device_lookup_private(&ed_cd, DISKUNIT(dev));
    if (wd == NULL)
        return (-1);

    part = DISKPART(dev);
    omask = wd->sc_dk.dk_openmask & (1 << part);

    if (omask == 0 && edmcaopen(dev, 0, S_IFBLK, NULL) != 0)
        return (-1);
    if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)
        size = -1;
    else
        size = wd->sc_dk.dk_label->d_partitions[part].p_size *
               (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE);
    if (omask == 0 && edmcaclose(dev, 0, S_IFBLK, NULL) != 0)
        return (-1);
    return (size);
}
Пример #14
0
int
ofdisk_size(dev_t dev)
{
	struct ofdisk_softc *of;
	struct disklabel *lp;
	int size, part, omask;

	of = device_lookup_private(&ofdisk_cd, DISKUNIT(dev));
	if (of == NULL)
		return ENXIO;

	part = DISKPART(dev);
	omask = of->sc_dk.dk_openmask & (1 << part);
	lp = of->sc_dk.dk_label;

	if (omask == 0 && ofdisk_open(dev, 0, S_IFBLK, curlwp) != 0)
		return -1;

	if (lp->d_partitions[part].p_fstype != FS_SWAP)
		size = -1;
	else
		size = lp->d_partitions[part].p_size *
		    (lp->d_secsize / DEV_BSIZE);

	if (omask == 0 && ofdisk_close(dev, 0, S_IFBLK, curlwp) != 0)
		return -1;

	return size;
}
Пример #15
0
Файл: ld.c Проект: MarginC/kame
/* ARGSUSED */
int
ldclose(dev_t dev, int flags, int fmt, struct proc *p)
{
	struct ld_softc *sc;
	int part, unit;

	unit = DISKUNIT(dev);
	part = DISKPART(dev);
	sc = device_lookup(&ld_cd, unit);
	ldlock(sc);

	switch (fmt) {
	case S_IFCHR:
		sc->sc_dk.dk_copenmask &= ~(1 << part);
		break;
	case S_IFBLK:
		sc->sc_dk.dk_bopenmask &= ~(1 << part);
		break;
	}
	sc->sc_dk.dk_openmask =
	    sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;

	if (sc->sc_dk.dk_openmask == 0 && sc->sc_flush != NULL)
		if ((*sc->sc_flush)(sc) != 0)
			printf("%s: unable to flush cache\n",
			    sc->sc_dv.dv_xname);

	ldunlock(sc);
	return (0);
}
Пример #16
0
int
ofdisk_close(dev_t dev, int flags, int fmt, struct lwp *l)
{
	struct ofdisk_softc *of =
		device_lookup_private(&ofdisk_cd, DISKUNIT(dev));

	mutex_enter(&of->sc_dk.dk_openlock);

	switch (fmt) {
	case S_IFCHR:
		of->sc_dk.dk_copenmask &= ~(1 << DISKPART(dev));
		break;
	case S_IFBLK:
		of->sc_dk.dk_bopenmask &= ~(1 << DISKPART(dev));
		break;
	}
	of->sc_dk.dk_openmask = of->sc_dk.dk_copenmask | of->sc_dk.dk_bopenmask;

#ifdef	FIRMWORKSBUGS
	/*
	 * This is a hack to get the firmware to flush its buffers.
	 */
	OF_seek(of->sc_ihandle, 0);
#endif
	if (!of->sc_dk.dk_openmask) {
		OF_close(of->sc_ihandle);
		of->sc_ihandle = 0;
	}

	mutex_exit(&of->sc_dk.dk_openlock);
	return 0;
}
Пример #17
0
int
rdioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
{
	struct rd_softc *sc;
	struct disklabel *lp;
	int error = 0;

	sc = rdlookup(DISKUNIT(dev));
	if (sc == NULL)
		return (ENXIO);

	switch (cmd) {
	case DIOCRLDINFO:
		lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK);
		rdgetdisklabel(dev, sc, lp, 0);
		bcopy(lp, sc->sc_dk.dk_label, sizeof(*lp));
		free(lp, M_TEMP);
		goto done;

	case DIOCGPDINFO:
		rdgetdisklabel(dev, sc, (struct disklabel *)data, 1);
		goto done;

	case DIOCGDINFO:
		*(struct disklabel *)data = *(sc->sc_dk.dk_label);
		goto done;

	case DIOCGPART:
		((struct partinfo *)data)->disklab = sc->sc_dk.dk_label;
		((struct partinfo *)data)->part =
		    &sc->sc_dk.dk_label->d_partitions[DISKPART(dev)];
		goto done;

	case DIOCWDINFO:
	case DIOCSDINFO:
		if ((fflag & FWRITE) == 0) {
			error = EBADF;
			goto done;
		}

		if ((error = disk_lock(&sc->sc_dk)) != 0)
			goto done;

		error = setdisklabel(sc->sc_dk.dk_label,
		    (struct disklabel *)data, sc->sc_dk.dk_openmask);
		if (error == 0) {
			if (cmd == DIOCWDINFO)
				error = writedisklabel(DISKLABELDEV(dev),
				    rdstrategy, sc->sc_dk.dk_label);
		}

		disk_unlock(&sc->sc_dk);
		goto done;
	}

 done:
	device_unref(&sc->sc_dev);
	return (error);
}
Пример #18
0
/*
 * Attempt to read a disk label from a device
 * using the indicated strategy routine.
 * The label must be partly set up before this:
 * secpercyl, secsize and anything required for a block i/o read
 * operation in the driver's strategy/start routines
 * must be filled in before calling us.
 *
 * If dos partition table requested, attempt to load it and
 * find disklabel inside a DOS partition.
 *
 * We would like to check if each MBR has a valid DOSMBR_SIGNATURE, but
 * we cannot because it doesn't always exist. So.. we assume the
 * MBR is valid.
 */
int
readdisklabel(dev_t dev, void (*strat)(struct buf *),
    struct disklabel *lp, int spoofonly)
{
	bios_diskinfo_t *pdi;
	struct buf *bp = NULL;
	dev_t devno;
	int error;

	if ((error = initdisklabel(lp)))
		goto done;

	/* Look for any BIOS geometry information we should honour. */
	devno = chrtoblk(dev);
	if (devno == NODEV)
		devno = dev;
	pdi = bios_getdiskinfo(MAKEBOOTDEV(major(devno), 0, 0, DISKUNIT(devno),
	    RAW_PART));
	if (pdi != NULL && pdi->bios_heads > 0 && pdi->bios_sectors > 0) {
#ifdef DEBUG
		printf("Disk GEOM %u/%u/%u -> BIOS GEOM %u/%u/%u\n",
		    lp->d_ntracks, lp->d_nsectors, lp->d_ncylinders,
		    pdi->bios_heads, pdi->bios_sectors,
		    DL_GETDSIZE(lp) / (pdi->bios_heads * pdi->bios_sectors));
#endif
		lp->d_ntracks = pdi->bios_heads;
		lp->d_nsectors = pdi->bios_sectors;
		lp->d_secpercyl = pdi->bios_sectors * pdi->bios_heads;
		lp->d_ncylinders = DL_GETDSIZE(lp) / lp->d_secpercyl;
	}

	/* get a buffer and initialize it */
	bp = geteblk((int)lp->d_secsize);
	bp->b_dev = dev;

	error = readdoslabel(bp, strat, lp, NULL, spoofonly);
	if (error == 0)
		goto done;

#if defined(CD9660)
	error = iso_disklabelspoof(dev, strat, lp);
	if (error == 0)
		goto done;
#endif
#if defined(UDF)
	error = udf_disklabelspoof(dev, strat, lp);
	if (error == 0)
		goto done;
#endif

done:
	if (bp) {
		bp->b_flags |= B_INVAL;
		brelse(bp);
	}
	disk_change = 1;
	return (error);
}
Пример #19
0
int
rlopen(dev_t dev, int flag, int fmt, struct lwp *l)
{
	struct rl_softc * const rc = device_lookup_private(&rl_cd, DISKUNIT(dev));
	struct rlc_softc *sc;
	int error, part, mask;
	struct disklabel *dl;
	const char *msg;

	/*
	 * Make sure this is a reasonable open request.
	 */
	if (rc == NULL)
		return ENXIO;

	sc = rc->rc_rlc;
	part = DISKPART(dev);

	mutex_enter(&rc->rc_disk.dk_openlock);

	/*
	 * If there are wedges, and this is not RAW_PART, then we
	 * need to fail.
	 */
	if (rc->rc_disk.dk_nwedges != 0 && part != RAW_PART) {
		error = EBUSY;
		goto bad1;
	}

	/* Check that the disk actually is useable */
	msg = rlstate(sc, rc->rc_hwid);
	if (msg == NULL || msg == rlstates[RLMP_UNLOAD] ||
	    msg == rlstates[RLMP_SPUNDOWN]) {
		error = ENXIO;
		goto bad1;
	}
	/*
	 * If this is the first open; read in where on the disk we are.
	 */
	dl = rc->rc_disk.dk_label;
	if (rc->rc_state == DK_CLOSED) {
		u_int16_t mp;
		int maj;
		RL_WREG(RL_CS, RLCS_RHDR|(rc->rc_hwid << RLCS_USHFT));
		waitcrdy(sc);
		mp = RL_RREG(RL_MP);
		rc->rc_head = ((mp & RLMP_HS) == RLMP_HS);
		rc->rc_cyl = (mp >> 7) & 0777;
		rc->rc_state = DK_OPEN;
		/* Get disk label */
		maj = cdevsw_lookup_major(&rl_cdevsw);
		if ((msg = readdisklabel(MAKEDISKDEV(maj,
		    device_unit(rc->rc_dev), RAW_PART), rlstrategy, dl, NULL)))
			aprint_normal_dev(rc->rc_dev, "%s", msg);
		aprint_normal_dev(rc->rc_dev, "size %d sectors\n",
		    dl->d_secperunit);
	}
Пример #20
0
static void
ofminphys(struct buf *bp)
{
	struct ofdisk_softc *of =
		device_lookup_private(&ofdisk_cd, DISKUNIT(bp->b_dev));

	if (bp->b_bcount > of->max_transfer)
		bp->b_bcount = of->max_transfer;
}
Пример #21
0
Файл: ld.c Проект: MarginC/kame
/*
 * Take a dump.
 */
int
lddump(dev_t dev, daddr_t blkno, caddr_t va, size_t size)
{
	struct ld_softc *sc;
	struct disklabel *lp;
	int unit, part, nsects, sectoff, towrt, nblk, maxblkcnt, rv;
	static int dumping;

	unit = DISKUNIT(dev);
	if ((sc = device_lookup(&ld_cd, unit)) == NULL)
		return (ENXIO);
	if ((sc->sc_flags & LDF_ENABLED) == 0)
		return (ENODEV);
	if (sc->sc_dump == NULL)
		return (ENXIO);

	/* Check if recursive dump; if so, punt. */
	if (dumping)
		return (EFAULT);
	dumping = 1;

	/* Convert to disk sectors.  Request must be a multiple of size. */
	part = DISKPART(dev);
	lp = sc->sc_dk.dk_label;
	if ((size % lp->d_secsize) != 0)
		return (EFAULT);
	towrt = size / lp->d_secsize;
	blkno = dbtob(blkno) / lp->d_secsize;	/* blkno in DEV_BSIZE units */

	nsects = lp->d_partitions[part].p_size;
	sectoff = lp->d_partitions[part].p_offset;

	/* Check transfer bounds against partition size. */
	if ((blkno < 0) || ((blkno + towrt) > nsects))
		return (EINVAL);

	/* Offset block number to start of partition. */
	blkno += sectoff;

	/* Start dumping and return when done. */
	maxblkcnt = sc->sc_maxxfer / sc->sc_secsize - 1;
	while (towrt > 0) {
		nblk = min(maxblkcnt, towrt);

		if ((rv = (*sc->sc_dump)(sc, va, blkno, nblk)) != 0)
			return (rv);

		towrt -= nblk;
		blkno += nblk;
		va += nblk * sc->sc_secsize;
	}

	dumping = 0;
	return (0);
}
Пример #22
0
/*
 * Actually translate the requested transfer into one the physical driver
 * can understand.  The transfer is described by a buf and will include
 * only one physical transfer.
 */
void
sdstrategy(struct buf *bp)
{
	struct sd_softc *sc;
	int s;

	sc = sdlookup(DISKUNIT(bp->b_dev));
	if (sc == NULL) {
		bp->b_error = ENXIO;
		goto bad;
	}
	if (sc->flags & SDF_DYING) {
		bp->b_error = ENXIO;
		goto bad;
	}

	SC_DEBUG(sc->sc_link, SDEV_DB2, ("sdstrategy: %ld bytes @ blk %lld\n",
	    bp->b_bcount, (long long)bp->b_blkno));
	/*
	 * If the device has been made invalid, error out
	 */
	if ((sc->sc_link->flags & SDEV_MEDIA_LOADED) == 0) {
		if (sc->sc_link->flags & SDEV_OPEN)
			bp->b_error = EIO;
		else
			bp->b_error = ENODEV;
		goto bad;
	}

	/* Validate the request. */
	if (bounds_check_with_label(bp, sc->sc_dk.dk_label) == -1)
		goto done;

	/* Place it in the queue of disk activities for this disk. */
	bufq_queue(&sc->sc_bufq, bp);

	/*
	 * Tell the device to get going on the transfer if it's
	 * not doing anything, otherwise just wait for completion
	 */
	scsi_xsh_add(&sc->sc_xsh);

	device_unref(&sc->sc_dev);
	return;

 bad:
	bp->b_flags |= B_ERROR;
	bp->b_resid = bp->b_bcount;
 done:
	s = splbio();
	biodone(bp);
	splx(s);
	if (sc != NULL)
		device_unref(&sc->sc_dev);
}
Пример #23
0
Файл: ld.c Проект: MarginC/kame
/*
 * Adjust the size of a transfer.
 */
static void
ldminphys(struct buf *bp)
{
	struct ld_softc *sc;

	sc = device_lookup(&ld_cd, DISKUNIT(bp->b_dev));

	if (bp->b_bcount > sc->sc_maxxfer)
		bp->b_bcount = sc->sc_maxxfer;
	minphys(bp);
}
Пример #24
0
Файл: ld.c Проект: MarginC/kame
void
ldenddetach(struct ld_softc *sc)
{
	struct buf *bp;
	int s, bmaj, cmaj, mn;

	if ((sc->sc_flags & LDF_ENABLED) == 0)
		return;

	/* Wait for commands queued with the hardware to complete. */
	if (sc->sc_queuecnt != 0)
		if (tsleep(&sc->sc_queuecnt, PRIBIO, "lddtch", 30 * hz))
			printf("%s: not drained\n", sc->sc_dv.dv_xname);

	/* Locate the major numbers. */
	for (bmaj = 0; bmaj <= nblkdev; bmaj++)
		if (bdevsw[bmaj].d_open == ldopen)
			break;
	for (cmaj = 0; cmaj <= nchrdev; cmaj++)
		if (cdevsw[cmaj].d_open == ldopen)
			break;

	/* Kill off any queued buffers. */
	s = splbio();
	while ((bp = BUFQ_FIRST(&sc->sc_bufq)) != NULL) {
		BUFQ_REMOVE(&sc->sc_bufq, bp);
		bp->b_error = EIO;
		bp->b_flags |= B_ERROR;
		bp->b_resid = bp->b_bcount;
		biodone(bp);
	}
	splx(s);

	/* Nuke the vnodes for any open instances. */
	mn = DISKUNIT(sc->sc_dv.dv_unit);
	vdevgone(bmaj, mn, mn + (MAXPARTITIONS - 1), VBLK);
	vdevgone(cmaj, mn, mn + (MAXPARTITIONS - 1), VCHR);
	
	/* Detach from the disk list. */
	disk_detach(&sc->sc_dk);

#if NRND > 0
	/* Unhook the entropy source. */
	rnd_detach_source(&sc->sc_rnd_source);
#endif

	/* Flush the device's cache. */
	if (sc->sc_flush != NULL)
		if ((*sc->sc_flush)(sc) != 0)
			printf("%s: unable to flush cache\n",
			    sc->sc_dv.dv_xname);
}
Пример #25
0
/*
 * Close the device. Only called if we are the last occurrence of an open
 * device.  Convenient now but usually a pain.
 */
int
sdclose(dev_t dev, int flag, int fmt, struct proc *p)
{
    struct sd_softc *sc;
    int part = DISKPART(dev);
    int error;

    sc = sdlookup(DISKUNIT(dev));
    if (sc == NULL)
        return (ENXIO);
    if (sc->flags & SDF_DYING) {
        device_unref(&sc->sc_dev);
        return (ENXIO);
    }

    if ((error = sdlock(sc)) != 0) {
        device_unref(&sc->sc_dev);
        return (error);
    }

    switch (fmt) {
    case S_IFCHR:
        sc->sc_dk.dk_copenmask &= ~(1 << part);
        break;
    case S_IFBLK:
        sc->sc_dk.dk_bopenmask &= ~(1 << part);
        break;
    }
    sc->sc_dk.dk_openmask = sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;

    if (sc->sc_dk.dk_openmask == 0) {
        if ((sc->flags & SDF_DIRTY) != 0)
            sd_flush(sc, 0);

        if ((sc->sc_link->flags & SDEV_REMOVABLE) != 0)
            scsi_prevent(sc->sc_link, PR_ALLOW,
                         SCSI_IGNORE_ILLEGAL_REQUEST |
                         SCSI_IGNORE_NOT_READY | SCSI_SILENT);
        sc->sc_link->flags &= ~(SDEV_OPEN | SDEV_MEDIA_LOADED);

        if (sc->sc_link->flags & SDEV_EJECTING) {
            scsi_start(sc->sc_link, SSS_STOP|SSS_LOEJ, 0);
            sc->sc_link->flags &= ~SDEV_EJECTING;
        }

        timeout_del(&sc->sc_timeout);
    }

    sdunlock(sc);
    device_unref(&sc->sc_dev);
    return 0;
}
Пример #26
0
void
ofdisk_strategy(struct buf *bp)
{
	struct ofdisk_softc *of =
		device_lookup_private(&ofdisk_cd, DISKUNIT(bp->b_dev));
	struct partition *p;
	u_quad_t off;
	int read;
	int (*OF_io)(int, void *, int);
	daddr_t blkno = bp->b_blkno;

	bp->b_resid = 0;
	if (bp->b_bcount == 0)
		goto done;

	OF_io = bp->b_flags & B_READ ? OF_read : 
		(int(*)(int, void*, int))OF_write;

	if (DISKPART(bp->b_dev) != RAW_PART) {
		if (bounds_check_with_label(&of->sc_dk, bp, 0) <= 0) {
			bp->b_resid = bp->b_bcount;
			goto done;
		}
		p = &of->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
		blkno = bp->b_blkno + p->p_offset;
	}

	disk_busy(&of->sc_dk);

	off = (u_quad_t)blkno * DEV_BSIZE;
	read = -1;
	do {
		if (OF_seek(of->sc_ihandle, off) < 0)
			break;
		read = OF_io(of->sc_ihandle, bp->b_data, bp->b_bcount);
	} while (read == -2);

	if (read < 0) {
		bp->b_error = EIO;
		bp->b_resid = bp->b_bcount;
	} else
		bp->b_resid = bp->b_bcount - read;

	disk_unbusy(&of->sc_dk, bp->b_bcount - bp->b_resid,
	    (bp->b_flags & B_READ));

done:
	biodone(bp);
}
Пример #27
0
/*
 * Read/write routine for a buffer.  Validates the arguments and schedules the
 * transfer.  Does not wait for the transfer to complete.
 */
void
wdstrategy(struct buf *bp)
{
	struct wd_softc *wd;
	int s;

	wd = wdlookup(DISKUNIT(bp->b_dev));
	if (wd == NULL) {
		bp->b_error = ENXIO;
		goto bad;
	}

	WDCDEBUG_PRINT(("wdstrategy (%s)\n", wd->sc_dev.dv_xname),
	    DEBUG_XFERS);

	/* If device invalidated (e.g. media change, door open), error. */
	if ((wd->sc_flags & WDF_LOADED) == 0) {
		bp->b_error = EIO;
		goto bad;
	}

	/* Validate the request. */
	if (bounds_check_with_label(bp, wd->sc_dk.dk_label) == -1)
		goto done;

	/* Check that the number of sectors can fit in a byte. */
	if ((bp->b_bcount / wd->sc_dk.dk_label->d_secsize) >= (1 << NBBY)) {
		bp->b_error = EINVAL;
		goto bad;
	}

	/* Queue transfer on drive, activate drive and controller if idle. */
	bufq_queue(&wd->sc_bufq, bp);
	s = splbio();
	wdstart(wd);
	splx(s);
	device_unref(&wd->sc_dev);
	return;

 bad:
	bp->b_flags |= B_ERROR;
	bp->b_resid = bp->b_bcount;
 done:
	s = splbio();
	biodone(bp);
	splx(s);
	if (wd != NULL)
		device_unref(&wd->sc_dev);
}
Пример #28
0
void
rdstrategy(struct buf *bp)
{
	struct rd_softc *sc;
	struct partition *p;
	size_t off, xfer;
	caddr_t addr;
	int s;

	sc = rdlookup(DISKUNIT(bp->b_dev));
	if (sc == NULL) {
		bp->b_error = ENXIO;
		goto bad;
	}

	/* Validate the request. */
	if (bounds_check_with_label(bp, sc->sc_dk.dk_label) == -1)
		goto done;

	/* Do the transfer. */
	/* XXX: Worry about overflow when computing off? */

	p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)];
	off = DL_GETPOFFSET(p) * sc->sc_dk.dk_label->d_secsize +
	    (u_int64_t)bp->b_blkno * DEV_BSIZE;
	if (off > rd_root_size)
		off = rd_root_size;
	xfer = bp->b_bcount;
	if (xfer > rd_root_size - off)
		xfer = rd_root_size - off;
	addr = rd_root_image + off;
	if (bp->b_flags & B_READ)
		memcpy(bp->b_data, addr, xfer);
	else
		memcpy(addr, bp->b_data, xfer);
	bp->b_resid = bp->b_bcount - xfer;
	goto done;

 bad:
	bp->b_flags |= B_ERROR;
	bp->b_resid = bp->b_bcount;
 done:
	s = splbio();
	biodone(bp);
	splx(s);
	if (sc != NULL)
		device_unref(&sc->sc_dev);
}
Пример #29
0
/*
 * Close the device. Only called if we are the last occurrence of an open
 * device.
 */
int
cdclose(dev_t dev, int flag, int fmt, struct proc *p)
{
	struct cd_softc *cd;
	int part = DISKPART(dev);
	int error;

	cd = cdlookup(DISKUNIT(dev));
	if (cd == NULL)
		return ENXIO;

	if ((error = cdlock(cd)) != 0) {
		device_unref(&cd->sc_dev);
		return error;
	}

	switch (fmt) {
	case S_IFCHR:
		cd->sc_dk.dk_copenmask &= ~(1 << part);
		break;
	case S_IFBLK:
		cd->sc_dk.dk_bopenmask &= ~(1 << part);
		break;
	}
	cd->sc_dk.dk_openmask = cd->sc_dk.dk_copenmask | cd->sc_dk.dk_bopenmask;

	if (cd->sc_dk.dk_openmask == 0) {
		/* XXXX Must wait for I/O to complete! */

		scsi_prevent(cd->sc_link, PR_ALLOW,
		    SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY |
		    SCSI_SILENT);
		cd->sc_link->flags &= ~(SDEV_OPEN | SDEV_MEDIA_LOADED);

		if (cd->sc_link->flags & SDEV_EJECTING) {
			scsi_start(cd->sc_link, SSS_STOP|SSS_LOEJ, 0);

			cd->sc_link->flags &= ~SDEV_EJECTING;
		}

		timeout_del(&cd->sc_timeout);
	}

	cdunlock(cd);

	device_unref(&cd->sc_dev);
	return 0;
}
Пример #30
0
void
prestostrategy(struct buf *bp)
{
	int unit, part;
	struct presto_softc *sc;
	size_t offset, count;
	int s;

	unit = DISKUNIT(bp->b_dev);
	sc = (struct presto_softc *)device_lookup(&presto_cd, unit);

	/* Sort rogue requests out */
	if (sc == NULL || bp->b_blkno < 0 ||
	    (bp->b_bcount % sc->sc_dk.dk_label->d_secsize) != 0) {
		bp->b_error = EINVAL;
		goto bad;
	}

	/* Do not write on "no trespassing" areas... */
	part = DISKPART(bp->b_dev);
	if (part != RAW_PART &&
	    bounds_check_with_label(bp, sc->sc_dk.dk_label,
	    sc->sc_dk.dk_cpulabel, 1) <= 0)
		goto bad;

	/* Bound the request size, then move data between buf and nvram */
	bp->b_resid = bp->b_bcount;
	offset = (bp->b_blkno << DEV_BSHIFT) + PSERVE_OFFSET;
	count = bp->b_bcount;
	if (count > (sc->sc_memsize - offset))
		count = (sc->sc_memsize - offset);
	if (ISSET(bp->b_flags, B_READ))
		bcopy(sc->sc_mem + offset, bp->b_data, count);
	else
		bcopy(bp->b_data, sc->sc_mem + offset, count);
	bp->b_resid -= count;
	goto done;

bad:
	bp->b_flags |= B_ERROR;
	bp->b_resid = bp->b_bcount;

done:
	s = splbio();
	biodone(bp);
	splx(s);
}