subr_disk.c revision 50728
12061Sjkh/*
226504Sjhay * ----------------------------------------------------------------------------
32061Sjkh * "THE BEER-WARE LICENSE" (Revision 42):
42061Sjkh * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
515603Smarkm * can do whatever you want with this stuff. If we meet some day, and you think
63197Scsgr * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
720710Sasami * ----------------------------------------------------------------------------
820710Sasami *
93197Scsgr * $FreeBSD: head/sys/kern/subr_disk.c 50728 1999-09-01 05:38:09Z phk $
102061Sjkh *
1112483Speter */
122160Scsgr
132834Swollman#include <sys/param.h>
142061Sjkh#include <sys/systm.h>
152061Sjkh#include <sys/kernel.h>
162160Scsgr#include <sys/buf.h>
1717308Speter#include <sys/conf.h>
1819320Sadam#include <sys/disk.h>
1921536Sjmacd#include <sys/malloc.h>
2025399Sjb#include <sys/vnode.h>
2125980Sasami#include <machine/md_var.h>
221594Srgrimes
2317308SpeterMALLOC_DEFINE(M_DISK, "disk", "disk data");
2417308Speter
2517308Speterstatic d_strategy_t diskstrategy;
2617308Speterstatic d_open_t diskopen;
2717308Speterstatic d_close_t diskclose;
2817308Speterstatic d_ioctl_t diskioctl;
2917308Speterstatic d_psize_t diskpsize;
3019175Sbde
3119175Sbdestatic struct cdevsw disk_cdevsw = {
3219175Sbde	/* open */      diskopen,
3319175Sbde	/* close */     diskclose,
3417308Speter	/* read */      physread,
3525647Sbde	/* write */     physwrite,
3617308Speter	/* ioctl */     diskioctl,
372061Sjkh	/* stop */      nostop,
382061Sjkh	/* reset */     noreset,
391594Srgrimes	/* devtotty */  nodevtotty,
4025313Sbde	/* poll */      nopoll,
4125313Sbde	/* mmap */      nommap,
4225313Sbde	/* strategy */  diskstrategy,
4325313Sbde	/* name */      "disk",
4425313Sbde	/* parms */     noparms,
4525313Sbde	/* maj */       -1,
4625313Sbde	/* dump */      nodump,
4725313Sbde	/* psize */     diskpsize,
487407Srgrimes	/* flags */     D_DISK,
497108Sphk	/* maxio */     0,
507108Sphk	/* bmaj */      -1,
517108Sphk};
527407Srgrimes
537407Srgrimesdev_t
547407Srgrimesdisk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw)
557108Sphk{
562061Sjkh	dev_t dev;
572061Sjkh	struct cdevsw *cds;
582061Sjkh
5917308Speter	dev = makedev(cdevsw->d_maj, 0);
602061Sjkh	cds = devsw(dev);
612061Sjkh	if (!cds) {
622061Sjkh		/* Build the "real" cdevsw */
632061Sjkh		MALLOC(cds, struct cdevsw *, sizeof(*cds), M_DISK, M_WAITOK);
642061Sjkh		*cds = disk_cdevsw;
653197Scsgr		cds->d_name = cdevsw->d_name;
662626Scsgr		cds->d_maj = cdevsw->d_maj;
672626Scsgr		cds->d_bmaj = cdevsw->d_bmaj;
682061Sjkh		cds->d_flags = cdevsw->d_flags & ~D_TRACKCLOSE;
692061Sjkh		cds->d_dump = cdevsw->d_dump;
702061Sjkh
712061Sjkh		cdevsw_add(cds);
722061Sjkh	}
732061Sjkh
7419320Sadam	printf("Creating DISK %s%d\n", cds->d_name, unit);
752061Sjkh	dev = make_dev(cds, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART),
762061Sjkh	    0, 0, 0, "r%s%d", cds->d_name, unit);
772061Sjkh
782061Sjkh	bzero(dp, sizeof(*dp));
792061Sjkh	dp->d_devsw = cdevsw;
802061Sjkh	dev->si_disk = dp;
812061Sjkh	dp->d_dev = dev;
822061Sjkh	dp->d_flags = flags;
832061Sjkh	return (dev);
842061Sjkh}
852061Sjkh
862834Swollmanint
872834Swollmandisk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize)
882834Swollman{
892834Swollman	struct disk *dp;
902834Swollman	struct disklabel *dl;
912834Swollman	u_int boff;
921594Srgrimes
934486Sphk	dp = dev->si_disk;
944486Sphk	if (!dp)
954486Sphk		return (ENXIO);
964486Sphk	if (!dp->d_slice)
974486Sphk		return (ENXIO);
982061Sjkh	dl = dsgetlabel(dev, dp->d_slice);
992061Sjkh	if (!dl)
10025979Sjkh		return (ENXIO);
10125979Sjkh	*count = (u_long)Maxmem * PAGE_SIZE / dl->d_secsize;
10225979Sjkh	if (dumplo < 0 ||
10325979Sjkh	    (dumplo + *count > dl->d_partitions[dkpart(dev)].p_size))
1042061Sjkh		return (EINVAL);
10525979Sjkh	boff = dl->d_partitions[dkpart(dev)].p_offset +
1062061Sjkh	    dp->d_slice->dss_slices[dkslice(dev)].ds_offset;
1072061Sjkh	*blkno = boff + dumplo;
10817308Speter	*secsize = dl->d_secsize;
1092061Sjkh	return (0);
1102061Sjkh
1112061Sjkh}
1122061Sjkh
1132061Sjkhvoid
11412483Speterdisk_invalidate (struct disk *disk)
11512483Speter{
11612483Speter	dsgone(&disk->d_slice);
11712483Speter}
1182061Sjkh
1192061Sjkhvoid
1208854Srgrimesdisk_delete(dev_t dev)
1212061Sjkh{
1222061Sjkh	return;
12312483Speter}
1242061Sjkh
12518714Sache/*
12618714Sache * The cdevsw functions
12718714Sache */
12817308Speter
12917308Speterstatic int
13017308Speterdiskopen(dev_t dev, int oflags, int devtype, struct proc *p)
13117308Speter{
13221536Sjmacd	dev_t pdev;
13315603Smarkm	struct disk *dp;
13417308Speter	int error;
13517308Speter
13617308Speter	error = 0;
13717308Speter	pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
13817308Speter
13917308Speter	dp = pdev->si_disk;
14017308Speter	if (!dp)
14117308Speter		return (ENXIO);
14217308Speter
14318362Sjkh	dev->si_disk = dp;
14419966Sache	dev->si_drv1 = pdev->si_drv1;
14518362Sjkh	dev->si_drv2 = pdev->si_drv2;
14617308Speter
14717308Speter	if (!dsisopen(dp->d_slice))
14817308Speter		error = dp->d_devsw->d_open(dev, oflags, devtype, p);
14917308Speter
15017308Speter	if (error)
15117308Speter		return(error);
15216550Sjkh
1532061Sjkh	error = dsopen(dev, devtype, dp->d_flags, &dp->d_slice, &dp->d_label);
15417308Speter
1552061Sjkh	if (!dsisopen(dp->d_slice))
15617308Speter		dp->d_devsw->d_close(dev, oflags, devtype, p);
1572061Sjkh
15817308Speter	return(error);
15917308Speter}
16017308Speter
16117308Speterstatic int
16217308Speterdiskclose(dev_t dev, int fflag, int devtype, struct proc *p)
16317308Speter{
16417466Speter	struct disk *dp;
16517308Speter	int error;
16617308Speter
16717466Speter	error = 0;
16817308Speter	dp = dev->si_disk;
16917308Speter	dsclose(dev, devtype, dp->d_slice);
17017308Speter	if (dsisopen(dp->d_slice))
17117308Speter		error = dp->d_devsw->d_close(dev, fflag, devtype, p);
17217466Speter	return (error);
17317308Speter}
17417308Speter
17517308Speterstatic void
17617308Speterdiskstrategy(struct buf *bp)
17717308Speter{
17817308Speter	dev_t pdev;
17917308Speter	struct disk *dp;
18017308Speter
18117308Speter	dp = bp->b_dev->si_disk;
18217308Speter	if (!dp) {
18317308Speter		pdev = dkmodpart(dkmodslice(bp->b_dev, WHOLE_DISK_SLICE), RAW_PART);
18417308Speter		dp = pdev->si_disk;
18517308Speter		bp->b_dev->si_drv1 = pdev->si_drv1;
18617308Speter		bp->b_dev->si_drv2 = pdev->si_drv2;
18717308Speter		/* XXX: don't set bp->b_dev->si_disk (?) */
18817308Speter	} else {
18917308Speter		pdev = dp->d_dev;
19017308Speter	}
19117308Speter
19217308Speter	if (!dp) {
19317308Speter		bp->b_error = ENXIO;
19417308Speter		bp->b_flags |= B_ERROR;
19517308Speter		biodone(bp);
19617308Speter		return;
19717308Speter	}
19817308Speter
19917308Speter	if (dscheck(bp, dp->d_slice) < 0) {
20018392Speter		biodone(bp);
20117308Speter		return;
20217308Speter	}
20317308Speter
20417308Speter	dp->d_devsw->d_strategy(bp);
20517962Speter	return;
20617308Speter
20717962Speter}
20817962Speter
20917962Speterstatic int
21017962Speterdiskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
21117962Speter{
21217962Speter	struct disk *dp;
21317962Speter	int error;
21417962Speter
21517962Speter	dp = dev->si_disk;
21617962Speter	error = dsioctl(dev, cmd, data, fflag, &dp->d_slice);
21717962Speter	if (error == ENOIOCTL)
21817962Speter		error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, p);
21917962Speter	return (error);
22017962Speter}
22117962Speter
22217308Speterstatic int
22316550Sjkhdiskpsize(dev_t dev)
22417308Speter{
22517308Speter	struct disk *dp;
22617308Speter	dev_t pdev;
22717308Speter
22816550Sjkh	dp = dev->si_disk;
22916550Sjkh	if (!dp) {
23017308Speter		pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
23117308Speter		dp = pdev->si_disk;
23219966Sache		dev->si_drv1 = pdev->si_drv1;
23317962Speter		dev->si_drv2 = pdev->si_drv2;
2342061Sjkh		/* XXX: don't set bp->b_dev->si_disk (?) */
23517308Speter	}
23617308Speter	return (dssize(dev, &dp->d_slice));
23717308Speter}
23817308Speter