subr_disk.c revision 51111
150565Sphk/* 250565Sphk * ---------------------------------------------------------------------------- 350565Sphk * "THE BEER-WARE LICENSE" (Revision 42): 450565Sphk * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you 550565Sphk * can do whatever you want with this stuff. If we meet some day, and you think 650565Sphk * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 750565Sphk * ---------------------------------------------------------------------------- 850565Sphk * 950565Sphk * $FreeBSD: head/sys/kern/subr_disk.c 51111 1999-09-09 19:08:44Z julian $ 1050565Sphk * 1150565Sphk */ 1250565Sphk 1350565Sphk#include <sys/param.h> 1450565Sphk#include <sys/systm.h> 1550565Sphk#include <sys/kernel.h> 1651111Sjulian#include <sys/sysctl.h> 1750565Sphk#include <sys/buf.h> 1850565Sphk#include <sys/conf.h> 1950565Sphk#include <sys/disk.h> 2050565Sphk#include <sys/malloc.h> 2150728Sphk#include <sys/vnode.h> 2250728Sphk#include <machine/md_var.h> 2350565Sphk 2450565SphkMALLOC_DEFINE(M_DISK, "disk", "disk data"); 2550565Sphk 2650565Sphkstatic d_strategy_t diskstrategy; 2750565Sphkstatic d_open_t diskopen; 2850565Sphkstatic d_close_t diskclose; 2950565Sphkstatic d_ioctl_t diskioctl; 3050565Sphkstatic d_psize_t diskpsize; 3150565Sphk 3250565Sphkstatic struct cdevsw disk_cdevsw = { 3350565Sphk /* open */ diskopen, 3450565Sphk /* close */ diskclose, 3550565Sphk /* read */ physread, 3650565Sphk /* write */ physwrite, 3750565Sphk /* ioctl */ diskioctl, 3850565Sphk /* stop */ nostop, 3950565Sphk /* reset */ noreset, 4050565Sphk /* devtotty */ nodevtotty, 4150565Sphk /* poll */ nopoll, 4250565Sphk /* mmap */ nommap, 4350565Sphk /* strategy */ diskstrategy, 4450565Sphk /* name */ "disk", 4550565Sphk /* parms */ noparms, 4650565Sphk /* maj */ -1, 4750565Sphk /* dump */ nodump, 4850565Sphk /* psize */ diskpsize, 4950565Sphk /* flags */ D_DISK, 5050565Sphk /* maxio */ 0, 5150565Sphk /* bmaj */ -1, 5250565Sphk}; 5350565Sphk 5450565Sphkdev_t 5550728Sphkdisk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw) 5650565Sphk{ 5750565Sphk dev_t dev; 5850565Sphk struct cdevsw *cds; 5950565Sphk 6050565Sphk dev = makedev(cdevsw->d_maj, 0); 6150565Sphk cds = devsw(dev); 6250565Sphk if (!cds) { 6350565Sphk /* Build the "real" cdevsw */ 6450565Sphk MALLOC(cds, struct cdevsw *, sizeof(*cds), M_DISK, M_WAITOK); 6550565Sphk *cds = disk_cdevsw; 6650728Sphk cds->d_name = cdevsw->d_name; 6750728Sphk cds->d_maj = cdevsw->d_maj; 6850728Sphk cds->d_bmaj = cdevsw->d_bmaj; 6950728Sphk cds->d_flags = cdevsw->d_flags & ~D_TRACKCLOSE; 7050728Sphk cds->d_dump = cdevsw->d_dump; 7150565Sphk 7250565Sphk cdevsw_add(cds); 7350565Sphk } 7450565Sphk 7550565Sphk printf("Creating DISK %s%d\n", cds->d_name, unit); 7650565Sphk dev = make_dev(cds, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART), 7750565Sphk 0, 0, 0, "r%s%d", cds->d_name, unit); 7850565Sphk 7950728Sphk bzero(dp, sizeof(*dp)); 8050728Sphk dp->d_devsw = cdevsw; 8150565Sphk dev->si_disk = dp; 8250565Sphk dp->d_dev = dev; 8350728Sphk dp->d_flags = flags; 8450565Sphk return (dev); 8550565Sphk} 8650565Sphk 8750728Sphkint 8850728Sphkdisk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize) 8950728Sphk{ 9050728Sphk struct disk *dp; 9150728Sphk struct disklabel *dl; 9250728Sphk u_int boff; 9350728Sphk 9450728Sphk dp = dev->si_disk; 9550728Sphk if (!dp) 9650728Sphk return (ENXIO); 9750728Sphk if (!dp->d_slice) 9850728Sphk return (ENXIO); 9950728Sphk dl = dsgetlabel(dev, dp->d_slice); 10050728Sphk if (!dl) 10150728Sphk return (ENXIO); 10250728Sphk *count = (u_long)Maxmem * PAGE_SIZE / dl->d_secsize; 10350728Sphk if (dumplo < 0 || 10450728Sphk (dumplo + *count > dl->d_partitions[dkpart(dev)].p_size)) 10550728Sphk return (EINVAL); 10650728Sphk boff = dl->d_partitions[dkpart(dev)].p_offset + 10750728Sphk dp->d_slice->dss_slices[dkslice(dev)].ds_offset; 10850728Sphk *blkno = boff + dumplo; 10950728Sphk *secsize = dl->d_secsize; 11050728Sphk return (0); 11150728Sphk 11250728Sphk} 11350728Sphk 11450728Sphkvoid 11550728Sphkdisk_invalidate (struct disk *disk) 11650728Sphk{ 11750728Sphk dsgone(&disk->d_slice); 11850728Sphk} 11950728Sphk 12050565Sphkvoid 12150565Sphkdisk_delete(dev_t dev) 12250565Sphk{ 12350565Sphk return; 12450565Sphk} 12550565Sphk 12650728Sphk/* 12750728Sphk * The cdevsw functions 12850728Sphk */ 12950728Sphk 13050565Sphkstatic int 13150565Sphkdiskopen(dev_t dev, int oflags, int devtype, struct proc *p) 13250565Sphk{ 13350565Sphk dev_t pdev; 13450565Sphk struct disk *dp; 13550565Sphk int error; 13650565Sphk 13750728Sphk error = 0; 13850565Sphk pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 13950728Sphk 14050565Sphk dp = pdev->si_disk; 14150565Sphk if (!dp) 14250565Sphk return (ENXIO); 14350728Sphk 14450565Sphk dev->si_disk = dp; 14550728Sphk dev->si_drv1 = pdev->si_drv1; 14650728Sphk dev->si_drv2 = pdev->si_drv2; 14750728Sphk 14850728Sphk if (!dsisopen(dp->d_slice)) 14950565Sphk error = dp->d_devsw->d_open(dev, oflags, devtype, p); 15050565Sphk 15150728Sphk if (error) 15250728Sphk return(error); 15350728Sphk 15450728Sphk error = dsopen(dev, devtype, dp->d_flags, &dp->d_slice, &dp->d_label); 15550565Sphk 15650728Sphk if (!dsisopen(dp->d_slice)) 15750565Sphk dp->d_devsw->d_close(dev, oflags, devtype, p); 15850728Sphk 15950565Sphk return(error); 16050565Sphk} 16150565Sphk 16250565Sphkstatic int 16350565Sphkdiskclose(dev_t dev, int fflag, int devtype, struct proc *p) 16450565Sphk{ 16550565Sphk struct disk *dp; 16650565Sphk int error; 16750565Sphk 16850565Sphk error = 0; 16950565Sphk dp = dev->si_disk; 17050565Sphk dsclose(dev, devtype, dp->d_slice); 17150728Sphk if (dsisopen(dp->d_slice)) 17250565Sphk error = dp->d_devsw->d_close(dev, fflag, devtype, p); 17350565Sphk return (error); 17450565Sphk} 17550565Sphk 17650565Sphkstatic void 17750565Sphkdiskstrategy(struct buf *bp) 17850565Sphk{ 17950565Sphk dev_t pdev; 18050565Sphk struct disk *dp; 18150565Sphk 18250565Sphk dp = bp->b_dev->si_disk; 18350565Sphk if (!dp) { 18450565Sphk pdev = dkmodpart(dkmodslice(bp->b_dev, WHOLE_DISK_SLICE), RAW_PART); 18550565Sphk dp = pdev->si_disk; 18650565Sphk bp->b_dev->si_drv1 = pdev->si_drv1; 18750565Sphk bp->b_dev->si_drv2 = pdev->si_drv2; 18850565Sphk /* XXX: don't set bp->b_dev->si_disk (?) */ 18950565Sphk } else { 19050565Sphk pdev = dp->d_dev; 19150565Sphk } 19250565Sphk 19350565Sphk if (!dp) { 19450565Sphk bp->b_error = ENXIO; 19550565Sphk bp->b_flags |= B_ERROR; 19650565Sphk biodone(bp); 19750565Sphk return; 19850565Sphk } 19950565Sphk 20050565Sphk if (dscheck(bp, dp->d_slice) < 0) { 20150565Sphk biodone(bp); 20250565Sphk return; 20350565Sphk } 20450565Sphk 20550565Sphk dp->d_devsw->d_strategy(bp); 20650565Sphk return; 20750565Sphk 20850565Sphk} 20950565Sphk 21050565Sphkstatic int 21150565Sphkdiskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) 21250565Sphk{ 21350565Sphk struct disk *dp; 21450565Sphk int error; 21550565Sphk 21650565Sphk dp = dev->si_disk; 21750565Sphk error = dsioctl(dev, cmd, data, fflag, &dp->d_slice); 21850565Sphk if (error == ENOIOCTL) 21950565Sphk error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, p); 22050565Sphk return (error); 22150565Sphk} 22250565Sphk 22350565Sphkstatic int 22450565Sphkdiskpsize(dev_t dev) 22550565Sphk{ 22650565Sphk struct disk *dp; 22750728Sphk dev_t pdev; 22850565Sphk 22950565Sphk dp = dev->si_disk; 23050728Sphk if (!dp) { 23150728Sphk pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 23250728Sphk dp = pdev->si_disk; 23350728Sphk dev->si_drv1 = pdev->si_drv1; 23450728Sphk dev->si_drv2 = pdev->si_drv2; 23550728Sphk /* XXX: don't set bp->b_dev->si_disk (?) */ 23650728Sphk } 23750565Sphk return (dssize(dev, &dp->d_slice)); 23850565Sphk} 23951111Sjulian 24051111SjulianSYSCTL_DECL(_debug_sizeof); 24151111Sjulian 24251111SjulianSYSCTL_INT(_debug_sizeof, OID_AUTO, disklabel, CTLFLAG_RD, 24351111Sjulian 0, sizeof(struct disklabel), "sizeof(struct disklabel)"); 24451111Sjulian 24551111SjulianSYSCTL_INT(_debug_sizeof, OID_AUTO, diskslices, CTLFLAG_RD, 24651111Sjulian 0, sizeof(struct diskslices), "sizeof(struct diskslices)"); 24751111Sjulian 24851111SjulianSYSCTL_INT(_debug_sizeof, OID_AUTO, disk, CTLFLAG_RD, 24951111Sjulian 0, sizeof(struct disk), "sizeof(struct disk)"); 250