subr_disk.c revision 51822
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 51822 1999-09-30 19:03:25Z phk $ 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 3250565Sphkdev_t 3351215Sphkdisk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw, struct cdevsw *proto) 3450565Sphk{ 3550565Sphk dev_t dev; 3650565Sphk 3751198Sphk bzero(dp, sizeof(*dp)); 3851198Sphk 3950565Sphk dev = makedev(cdevsw->d_maj, 0); 4051198Sphk if (!devsw(dev)) { 4151215Sphk *proto = *cdevsw; 4251215Sphk proto->d_open = diskopen; 4351215Sphk proto->d_close = diskclose; 4451215Sphk proto->d_ioctl = diskioctl; 4551215Sphk proto->d_strategy = diskstrategy; 4651215Sphk proto->d_psize = diskpsize; 4751215Sphk cdevsw_add(proto); 4850565Sphk } 4950565Sphk 5051198Sphk printf("Creating DISK %s%d\n", cdevsw->d_name, unit); 5151243Sphk dev = make_dev(proto, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART), 5251198Sphk 0, 0, 0, "r%s%d", cdevsw->d_name, unit); 5350565Sphk 5450565Sphk dev->si_disk = dp; 5550565Sphk dp->d_dev = dev; 5650728Sphk dp->d_flags = flags; 5751215Sphk dp->d_devsw = cdevsw; 5850565Sphk return (dev); 5950565Sphk} 6050565Sphk 6150728Sphkint 6250728Sphkdisk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize) 6350728Sphk{ 6450728Sphk struct disk *dp; 6550728Sphk struct disklabel *dl; 6650728Sphk u_int boff; 6750728Sphk 6850728Sphk dp = dev->si_disk; 6950728Sphk if (!dp) 7050728Sphk return (ENXIO); 7150728Sphk if (!dp->d_slice) 7250728Sphk return (ENXIO); 7350728Sphk dl = dsgetlabel(dev, dp->d_slice); 7450728Sphk if (!dl) 7550728Sphk return (ENXIO); 7650728Sphk *count = (u_long)Maxmem * PAGE_SIZE / dl->d_secsize; 7750728Sphk if (dumplo < 0 || 7850728Sphk (dumplo + *count > dl->d_partitions[dkpart(dev)].p_size)) 7950728Sphk return (EINVAL); 8050728Sphk boff = dl->d_partitions[dkpart(dev)].p_offset + 8150728Sphk dp->d_slice->dss_slices[dkslice(dev)].ds_offset; 8250728Sphk *blkno = boff + dumplo; 8350728Sphk *secsize = dl->d_secsize; 8450728Sphk return (0); 8550728Sphk 8650728Sphk} 8750728Sphk 8850728Sphkvoid 8950728Sphkdisk_invalidate (struct disk *disk) 9050728Sphk{ 9150728Sphk dsgone(&disk->d_slice); 9250728Sphk} 9350728Sphk 9450565Sphkvoid 9550565Sphkdisk_delete(dev_t dev) 9650565Sphk{ 9750565Sphk return; 9850565Sphk} 9950565Sphk 10050728Sphk/* 10150728Sphk * The cdevsw functions 10250728Sphk */ 10350728Sphk 10450565Sphkstatic int 10550565Sphkdiskopen(dev_t dev, int oflags, int devtype, struct proc *p) 10650565Sphk{ 10750565Sphk dev_t pdev; 10850565Sphk struct disk *dp; 10950565Sphk int error; 11050565Sphk 11150728Sphk error = 0; 11250565Sphk pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 11350728Sphk 11450565Sphk dp = pdev->si_disk; 11550565Sphk if (!dp) 11650565Sphk return (ENXIO); 11750728Sphk 11850565Sphk dev->si_disk = dp; 11950728Sphk dev->si_drv1 = pdev->si_drv1; 12050728Sphk dev->si_drv2 = pdev->si_drv2; 12150728Sphk 12250728Sphk if (!dsisopen(dp->d_slice)) 12351215Sphk error = dp->d_devsw->d_open(dev, oflags, devtype, p); 12450565Sphk 12550728Sphk if (error) 12650728Sphk return(error); 12750728Sphk 12850728Sphk error = dsopen(dev, devtype, dp->d_flags, &dp->d_slice, &dp->d_label); 12950565Sphk 13050728Sphk if (!dsisopen(dp->d_slice)) 13151215Sphk dp->d_devsw->d_close(dev, oflags, devtype, p); 13250728Sphk 13350565Sphk return(error); 13450565Sphk} 13550565Sphk 13650565Sphkstatic int 13750565Sphkdiskclose(dev_t dev, int fflag, int devtype, struct proc *p) 13850565Sphk{ 13950565Sphk struct disk *dp; 14050565Sphk int error; 14150565Sphk 14250565Sphk error = 0; 14350565Sphk dp = dev->si_disk; 14451822Sphk dsclose(dev, devtype, dp->d_slice); 14551822Sphk if (!dsisopen(dp->d_slice)) 14651215Sphk error = dp->d_devsw->d_close(dev, fflag, devtype, p); 14750565Sphk return (error); 14850565Sphk} 14950565Sphk 15050565Sphkstatic void 15150565Sphkdiskstrategy(struct buf *bp) 15250565Sphk{ 15350565Sphk dev_t pdev; 15450565Sphk struct disk *dp; 15550565Sphk 15650565Sphk dp = bp->b_dev->si_disk; 15750565Sphk if (!dp) { 15850565Sphk pdev = dkmodpart(dkmodslice(bp->b_dev, WHOLE_DISK_SLICE), RAW_PART); 15950565Sphk dp = pdev->si_disk; 16050565Sphk bp->b_dev->si_drv1 = pdev->si_drv1; 16150565Sphk bp->b_dev->si_drv2 = pdev->si_drv2; 16250565Sphk /* XXX: don't set bp->b_dev->si_disk (?) */ 16350565Sphk } else { 16450565Sphk pdev = dp->d_dev; 16550565Sphk } 16650565Sphk 16750565Sphk if (!dp) { 16850565Sphk bp->b_error = ENXIO; 16950565Sphk bp->b_flags |= B_ERROR; 17050565Sphk biodone(bp); 17150565Sphk return; 17250565Sphk } 17350565Sphk 17450565Sphk if (dscheck(bp, dp->d_slice) < 0) { 17550565Sphk biodone(bp); 17650565Sphk return; 17750565Sphk } 17850565Sphk 17951215Sphk dp->d_devsw->d_strategy(bp); 18050565Sphk return; 18150565Sphk 18250565Sphk} 18350565Sphk 18450565Sphkstatic int 18550565Sphkdiskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) 18650565Sphk{ 18750565Sphk struct disk *dp; 18850565Sphk int error; 18950565Sphk 19050565Sphk dp = dev->si_disk; 19150565Sphk error = dsioctl(dev, cmd, data, fflag, &dp->d_slice); 19250565Sphk if (error == ENOIOCTL) 19351215Sphk error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, p); 19450565Sphk return (error); 19550565Sphk} 19650565Sphk 19750565Sphkstatic int 19850565Sphkdiskpsize(dev_t dev) 19950565Sphk{ 20050565Sphk struct disk *dp; 20150728Sphk dev_t pdev; 20250565Sphk 20350565Sphk dp = dev->si_disk; 20450728Sphk if (!dp) { 20550728Sphk pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 20650728Sphk dp = pdev->si_disk; 20750728Sphk dev->si_drv1 = pdev->si_drv1; 20850728Sphk dev->si_drv2 = pdev->si_drv2; 20950728Sphk /* XXX: don't set bp->b_dev->si_disk (?) */ 21050728Sphk } 21150565Sphk return (dssize(dev, &dp->d_slice)); 21250565Sphk} 21351111Sjulian 21451111SjulianSYSCTL_DECL(_debug_sizeof); 21551111Sjulian 21651111SjulianSYSCTL_INT(_debug_sizeof, OID_AUTO, disklabel, CTLFLAG_RD, 21751111Sjulian 0, sizeof(struct disklabel), "sizeof(struct disklabel)"); 21851111Sjulian 21951111SjulianSYSCTL_INT(_debug_sizeof, OID_AUTO, diskslices, CTLFLAG_RD, 22051111Sjulian 0, sizeof(struct diskslices), "sizeof(struct diskslices)"); 22151111Sjulian 22251111SjulianSYSCTL_INT(_debug_sizeof, OID_AUTO, disk, CTLFLAG_RD, 22351111Sjulian 0, sizeof(struct disk), "sizeof(struct disk)"); 224