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$ 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 <machine/md_var.h> 22 23 MALLOC_DEFINE(M_DISK, "disk", "disk data"); 24 25 static d_strategy_t diskstrategy; 26 static d_open_t diskopen; 27 static d_close_t diskclose; 28 static d_ioctl_t diskioctl; 29 static d_psize_t diskpsize; 30 31 dev_t 32 disk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw, struct cdevsw *proto) 33 { 34 dev_t dev; 35 36 bzero(dp, sizeof(*dp)); 37 38 dev = makedev(cdevsw->d_maj, 0); 39 if (!devsw(dev)) { 40 *proto = *cdevsw; 41 proto->d_open = diskopen; 42 proto->d_close = diskclose; 43 proto->d_ioctl = diskioctl; 44 proto->d_strategy = diskstrategy; 45 proto->d_psize = diskpsize; 46 cdevsw_add(proto); 47 } 48 49 printf("Creating DISK %s%d\n", cdevsw->d_name, unit); 50 dev = make_dev(proto, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART), 51 0, 0, 0, "r%s%d", cdevsw->d_name, unit); 52 53 dev->si_disk = dp; 54 dp->d_dev = dev; 55 dp->d_flags = flags; 56 dp->d_devsw = cdevsw; 57 return (dev); 58 } 59 60 int 61 disk_dumpcheck(dev_t dev, u_int *count, u_int *blkno, u_int *secsize) 62 { 63 struct disk *dp; 64 struct disklabel *dl; 65 u_int boff; 66 67 dp = dev->si_disk; 68 if (!dp) 69 return (ENXIO); 70 if (!dp->d_slice) 71 return (ENXIO); 72 dl = dsgetlabel(dev, dp->d_slice); 73 if (!dl) 74 return (ENXIO); 75 *count = (u_long)Maxmem * PAGE_SIZE / dl->d_secsize; 76 if (dumplo < 0 || 77 (dumplo + *count > dl->d_partitions[dkpart(dev)].p_size)) 78 return (EINVAL); 79 boff = dl->d_partitions[dkpart(dev)].p_offset + 80 dp->d_slice->dss_slices[dkslice(dev)].ds_offset; 81 *blkno = boff + dumplo; 82 *secsize = dl->d_secsize; 83 return (0); 84 85 } 86 87 void 88 disk_invalidate (struct disk *disk) 89 { 90 dsgone(&disk->d_slice); 91 } 92 93 void 94 disk_delete(dev_t dev) 95 { 96 return; 97 } 98 99 /* 100 * The cdevsw functions 101 */ 102 103 static int 104 diskopen(dev_t dev, int oflags, int devtype, struct proc *p) 105 { 106 dev_t pdev; 107 struct disk *dp; 108 int error; 109 110 error = 0; 111 pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 112 113 dp = pdev->si_disk; 114 if (!dp) 115 return (ENXIO); 116 117 if (!dsisopen(dp->d_slice)) { 118 if (!pdev->si_iosize_max) 119 pdev->si_iosize_max = dev->si_iosize_max; 120 error = dp->d_devsw->d_open(pdev, oflags, devtype, p); 121 } 122 123 /* Inherit properties from the whole/raw dev_t */ 124 dev->si_disk = pdev->si_disk; 125 dev->si_drv1 = pdev->si_drv1; 126 dev->si_drv2 = pdev->si_drv2; 127 dev->si_iosize_max = pdev->si_iosize_max; 128 dev->si_bsize_phys = pdev->si_bsize_phys; 129 dev->si_bsize_best = pdev->si_bsize_best; 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_devsw->d_close(pdev, oflags, devtype, p); 138 139 return(error); 140 } 141 142 static int 143 diskclose(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_devsw->d_close(dp->d_dev, fflag, devtype, p); 153 } 154 return (error); 155 } 156 157 static void 158 diskstrategy(struct buf *bp) 159 { 160 dev_t pdev; 161 struct disk *dp; 162 163 dp = bp->b_dev->si_disk; 164 if (!dp) { 165 pdev = dkmodpart(dkmodslice(bp->b_dev, WHOLE_DISK_SLICE), RAW_PART); 166 dp = bp->b_dev->si_disk = pdev->si_disk; 167 bp->b_dev->si_drv1 = pdev->si_drv1; 168 bp->b_dev->si_drv2 = pdev->si_drv2; 169 bp->b_dev->si_iosize_max = pdev->si_iosize_max; 170 bp->b_dev->si_bsize_phys = pdev->si_bsize_phys; 171 bp->b_dev->si_bsize_best = pdev->si_bsize_best; 172 } 173 174 if (!dp) { 175 bp->b_error = ENXIO; 176 bp->b_flags |= B_ERROR; 177 biodone(bp); 178 return; 179 } 180 181 if (dscheck(bp, dp->d_slice) < 0) { 182 biodone(bp); 183 return; 184 } 185 186 dp->d_devsw->d_strategy(bp); 187 return; 188 189 } 190 191 static int 192 diskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) 193 { 194 struct disk *dp; 195 int error; 196 197 dp = dev->si_disk; 198 error = dsioctl(dev, cmd, data, fflag, &dp->d_slice); 199 if (error == ENOIOCTL) 200 error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, p); 201 return (error); 202 } 203 204 static int 205 diskpsize(dev_t dev) 206 { 207 struct disk *dp; 208 dev_t pdev; 209 210 dp = dev->si_disk; 211 if (!dp) { 212 pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART); 213 dp = pdev->si_disk; 214 dev->si_drv1 = pdev->si_drv1; 215 dev->si_drv2 = pdev->si_drv2; 216 /* XXX: don't set bp->b_dev->si_disk (?) */ 217 } 218 return (dssize(dev, &dp->d_slice)); 219 } 220 221 SYSCTL_DECL(_debug_sizeof); 222 223 SYSCTL_INT(_debug_sizeof, OID_AUTO, disklabel, CTLFLAG_RD, 224 0, sizeof(struct disklabel), "sizeof(struct disklabel)"); 225 226 SYSCTL_INT(_debug_sizeof, OID_AUTO, diskslices, CTLFLAG_RD, 227 0, sizeof(struct diskslices), "sizeof(struct diskslices)"); 228 229 SYSCTL_INT(_debug_sizeof, OID_AUTO, disk, CTLFLAG_RD, 230 0, sizeof(struct disk), "sizeof(struct disk)"); 231