subr_disk.c revision 50728
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 50728 1999-09-01 05:38:09Z phk $ 10 * 11 */ 12 13#include <sys/param.h> 14#include <sys/systm.h> 15#include <sys/kernel.h> 16#include <sys/buf.h> 17#include <sys/conf.h> 18#include <sys/disk.h> 19#include <sys/malloc.h> 20#include <sys/vnode.h> 21#include <machine/md_var.h> 22 23MALLOC_DEFINE(M_DISK, "disk", "disk data"); 24 25static d_strategy_t diskstrategy; 26static d_open_t diskopen; 27static d_close_t diskclose; 28static d_ioctl_t diskioctl; 29static d_psize_t diskpsize; 30 31static struct cdevsw disk_cdevsw = { 32 /* open */ diskopen, 33 /* close */ diskclose, 34 /* read */ physread, 35 /* write */ physwrite, 36 /* ioctl */ diskioctl, 37 /* stop */ nostop, 38 /* reset */ noreset, 39 /* devtotty */ nodevtotty, 40 /* poll */ nopoll, 41 /* mmap */ nommap, 42 /* strategy */ diskstrategy, 43 /* name */ "disk", 44 /* parms */ noparms, 45 /* maj */ -1, 46 /* dump */ nodump, 47 /* psize */ diskpsize, 48 /* flags */ D_DISK, 49 /* maxio */ 0, 50 /* bmaj */ -1, 51}; 52 53dev_t 54disk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw) 55{ 56 dev_t dev; 57 struct cdevsw *cds; 58 59 dev = makedev(cdevsw->d_maj, 0); 60 cds = devsw(dev); 61 if (!cds) { 62 /* Build the "real" cdevsw */ 63 MALLOC(cds, struct cdevsw *, sizeof(*cds), M_DISK, M_WAITOK); 64 *cds = disk_cdevsw; 65 cds->d_name = cdevsw->d_name; 66 cds->d_maj = cdevsw->d_maj; 67 cds->d_bmaj = cdevsw->d_bmaj; 68 cds->d_flags = cdevsw->d_flags & ~D_TRACKCLOSE; 69 cds->d_dump = cdevsw->d_dump; 70 71 cdevsw_add(cds); 72 } 73 74 printf("Creating DISK %s%d\n", cds->d_name, unit); 75 dev = make_dev(cds, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART), 76 0, 0, 0, "r%s%d", cds->d_name, unit); 77 78 bzero(dp, sizeof(*dp)); 79 dp->d_devsw = cdevsw; 80 dev->si_disk = dp; 81 dp->d_dev = dev; 82 dp->d_flags = flags; 83 return (dev); 84} 85 86int 87disk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize) 88{ 89 struct disk *dp; 90 struct disklabel *dl; 91 u_int boff; 92 93 dp = dev->si_disk; 94 if (!dp) 95 return (ENXIO); 96 if (!dp->d_slice) 97 return (ENXIO); 98 dl = dsgetlabel(dev, dp->d_slice); 99 if (!dl) 100 return (ENXIO); 101 *count = (u_long)Maxmem * PAGE_SIZE / dl->d_secsize; 102 if (dumplo < 0 || 103 (dumplo + *count > dl->d_partitions[dkpart(dev)].p_size)) 104 return (EINVAL); 105 boff = dl->d_partitions[dkpart(dev)].p_offset + 106 dp->d_slice->dss_slices[dkslice(dev)].ds_offset; 107 *blkno = boff + dumplo; 108 *secsize = dl->d_secsize; 109 return (0); 110 111} 112 113void 114disk_invalidate (struct disk *disk) 115{ 116 dsgone(&disk->d_slice); 117} 118 119void 120disk_delete(dev_t dev) 121{ 122 return; 123} 124 125/* 126 * The cdevsw functions 127 */ 128 129static int 130diskopen(dev_t dev, int oflags, int devtype, struct proc *p) 131{ 132 dev_t pdev; 133 struct disk *dp; 134 int error; 135 136 error = 0; 137 pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 138 139 dp = pdev->si_disk; 140 if (!dp) 141 return (ENXIO); 142 143 dev->si_disk = dp; 144 dev->si_drv1 = pdev->si_drv1; 145 dev->si_drv2 = pdev->si_drv2; 146 147 if (!dsisopen(dp->d_slice)) 148 error = dp->d_devsw->d_open(dev, oflags, devtype, p); 149 150 if (error) 151 return(error); 152 153 error = dsopen(dev, devtype, dp->d_flags, &dp->d_slice, &dp->d_label); 154 155 if (!dsisopen(dp->d_slice)) 156 dp->d_devsw->d_close(dev, oflags, devtype, p); 157 158 return(error); 159} 160 161static int 162diskclose(dev_t dev, int fflag, int devtype, struct proc *p) 163{ 164 struct disk *dp; 165 int error; 166 167 error = 0; 168 dp = dev->si_disk; 169 dsclose(dev, devtype, dp->d_slice); 170 if (dsisopen(dp->d_slice)) 171 error = dp->d_devsw->d_close(dev, fflag, devtype, p); 172 return (error); 173} 174 175static void 176diskstrategy(struct buf *bp) 177{ 178 dev_t pdev; 179 struct disk *dp; 180 181 dp = bp->b_dev->si_disk; 182 if (!dp) { 183 pdev = dkmodpart(dkmodslice(bp->b_dev, WHOLE_DISK_SLICE), RAW_PART); 184 dp = pdev->si_disk; 185 bp->b_dev->si_drv1 = pdev->si_drv1; 186 bp->b_dev->si_drv2 = pdev->si_drv2; 187 /* XXX: don't set bp->b_dev->si_disk (?) */ 188 } else { 189 pdev = dp->d_dev; 190 } 191 192 if (!dp) { 193 bp->b_error = ENXIO; 194 bp->b_flags |= B_ERROR; 195 biodone(bp); 196 return; 197 } 198 199 if (dscheck(bp, dp->d_slice) < 0) { 200 biodone(bp); 201 return; 202 } 203 204 dp->d_devsw->d_strategy(bp); 205 return; 206 207} 208 209static int 210diskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) 211{ 212 struct disk *dp; 213 int error; 214 215 dp = dev->si_disk; 216 error = dsioctl(dev, cmd, data, fflag, &dp->d_slice); 217 if (error == ENOIOCTL) 218 error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, p); 219 return (error); 220} 221 222static int 223diskpsize(dev_t dev) 224{ 225 struct disk *dp; 226 dev_t pdev; 227 228 dp = dev->si_disk; 229 if (!dp) { 230 pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 231 dp = pdev->si_disk; 232 dev->si_drv1 = pdev->si_drv1; 233 dev->si_drv2 = pdev->si_drv2; 234 /* XXX: don't set bp->b_dev->si_disk (?) */ 235 } 236 return (dssize(dev, &dp->d_slice)); 237} 238