subr_disk.c revision 51198
1/* 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 * 9 * $FreeBSD: head/sys/kern/subr_disk.c 51198 1999-09-12 09:16:00Z phk $ 10 * 11 */ 12 13#include <sys/param.h> 14#include <sys/systm.h> 15#include <sys/kernel.h> 16#include <sys/sysctl.h> 17#include <sys/buf.h> 18#include <sys/conf.h> 19#include <sys/disk.h> 20#include <sys/malloc.h> 21#include <sys/vnode.h> 22#include <machine/md_var.h> 23 24MALLOC_DEFINE(M_DISK, "disk", "disk data"); 25 26static d_strategy_t diskstrategy; 27static d_open_t diskopen; 28static d_close_t diskclose; 29static d_ioctl_t diskioctl; 30static d_psize_t diskpsize; 31 32dev_t 33disk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw) 34{ 35 dev_t dev; 36 struct cdevsw *cds; 37 38 MALLOC(cds, struct cdevsw *, sizeof(*cds), M_DISK, M_WAITOK); 39 40 bzero(dp, sizeof(*dp)); 41 42 dev = makedev(cdevsw->d_maj, 0); 43 if (!devsw(dev)) { 44 dp->d_open = cdevsw->d_open; 45 cdevsw->d_open = diskopen; 46 dp->d_close = cdevsw->d_close; 47 cdevsw->d_close = diskclose; 48 dp->d_ioctl = cdevsw->d_ioctl; 49 cdevsw->d_ioctl = diskioctl; 50 dp->d_strategy = cdevsw->d_strategy; 51 cdevsw->d_strategy = diskstrategy; 52 dp->d_psize = cdevsw->d_psize; 53 cdevsw->d_psize = diskpsize; 54 cdevsw_add(cdevsw); 55 } 56 57 printf("Creating DISK %s%d\n", cdevsw->d_name, unit); 58 dev = make_dev(cdevsw, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART), 59 0, 0, 0, "r%s%d", cdevsw->d_name, unit); 60 61 dev->si_disk = dp; 62 dp->d_dev = dev; 63 dp->d_flags = flags; 64 return (dev); 65} 66 67int 68disk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize) 69{ 70 struct disk *dp; 71 struct disklabel *dl; 72 u_int boff; 73 74 dp = dev->si_disk; 75 if (!dp) 76 return (ENXIO); 77 if (!dp->d_slice) 78 return (ENXIO); 79 dl = dsgetlabel(dev, dp->d_slice); 80 if (!dl) 81 return (ENXIO); 82 *count = (u_long)Maxmem * PAGE_SIZE / dl->d_secsize; 83 if (dumplo < 0 || 84 (dumplo + *count > dl->d_partitions[dkpart(dev)].p_size)) 85 return (EINVAL); 86 boff = dl->d_partitions[dkpart(dev)].p_offset + 87 dp->d_slice->dss_slices[dkslice(dev)].ds_offset; 88 *blkno = boff + dumplo; 89 *secsize = dl->d_secsize; 90 return (0); 91 92} 93 94void 95disk_invalidate (struct disk *disk) 96{ 97 dsgone(&disk->d_slice); 98} 99 100void 101disk_delete(dev_t dev) 102{ 103 return; 104} 105 106/* 107 * The cdevsw functions 108 */ 109 110static int 111diskopen(dev_t dev, int oflags, int devtype, struct proc *p) 112{ 113 dev_t pdev; 114 struct disk *dp; 115 int error; 116 117 error = 0; 118 pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 119 120 dp = pdev->si_disk; 121 if (!dp) 122 return (ENXIO); 123 124 dev->si_disk = dp; 125 dev->si_drv1 = pdev->si_drv1; 126 dev->si_drv2 = pdev->si_drv2; 127 128 if (!dsisopen(dp->d_slice)) 129 error = dp->d_open(dev, oflags, devtype, p); 130 131 if (error) 132 return(error); 133 134 error = dsopen(dev, devtype, dp->d_flags, &dp->d_slice, &dp->d_label); 135 136 if (!dsisopen(dp->d_slice)) 137 dp->d_close(dev, oflags, devtype, p); 138 139 return(error); 140} 141 142static int 143diskclose(dev_t dev, int fflag, int devtype, struct proc *p) 144{ 145 struct disk *dp; 146 int error; 147 148 error = 0; 149 dp = dev->si_disk; 150 dsclose(dev, devtype, dp->d_slice); 151 if (dsisopen(dp->d_slice)) 152 error = dp->d_close(dev, fflag, devtype, p); 153 return (error); 154} 155 156static void 157diskstrategy(struct buf *bp) 158{ 159 dev_t pdev; 160 struct disk *dp; 161 162 dp = bp->b_dev->si_disk; 163 if (!dp) { 164 pdev = dkmodpart(dkmodslice(bp->b_dev, WHOLE_DISK_SLICE), RAW_PART); 165 dp = pdev->si_disk; 166 bp->b_dev->si_drv1 = pdev->si_drv1; 167 bp->b_dev->si_drv2 = pdev->si_drv2; 168 /* XXX: don't set bp->b_dev->si_disk (?) */ 169 } else { 170 pdev = dp->d_dev; 171 } 172 173 if (!dp) { 174 bp->b_error = ENXIO; 175 bp->b_flags |= B_ERROR; 176 biodone(bp); 177 return; 178 } 179 180 if (dscheck(bp, dp->d_slice) < 0) { 181 biodone(bp); 182 return; 183 } 184 185 dp->d_strategy(bp); 186 return; 187 188} 189 190static int 191diskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) 192{ 193 struct disk *dp; 194 int error; 195 196 dp = dev->si_disk; 197 error = dsioctl(dev, cmd, data, fflag, &dp->d_slice); 198 if (error == ENOIOCTL) 199 error = dp->d_ioctl(dev, cmd, data, fflag, p); 200 return (error); 201} 202 203static int 204diskpsize(dev_t dev) 205{ 206 struct disk *dp; 207 dev_t pdev; 208 209 dp = dev->si_disk; 210 if (!dp) { 211 pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 212 dp = pdev->si_disk; 213 dev->si_drv1 = pdev->si_drv1; 214 dev->si_drv2 = pdev->si_drv2; 215 /* XXX: don't set bp->b_dev->si_disk (?) */ 216 } 217 return (dssize(dev, &dp->d_slice)); 218} 219 220SYSCTL_DECL(_debug_sizeof); 221 222SYSCTL_INT(_debug_sizeof, OID_AUTO, disklabel, CTLFLAG_RD, 223 0, sizeof(struct disklabel), "sizeof(struct disklabel)"); 224 225SYSCTL_INT(_debug_sizeof, OID_AUTO, diskslices, CTLFLAG_RD, 226 0, sizeof(struct diskslices), "sizeof(struct diskslices)"); 227 228SYSCTL_INT(_debug_sizeof, OID_AUTO, disk, CTLFLAG_RD, 229 0, sizeof(struct disk), "sizeof(struct disk)"); 230