md.c revision 51503
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/dev/md/md.c 51503 1999-09-21 12:05:38Z phk $ 10 * 11 */ 12 13#include <sys/param.h> 14#include <sys/systm.h> 15#include <sys/sysctl.h> 16#include <sys/kernel.h> 17#include <sys/buf.h> 18#include <sys/malloc.h> 19#include <sys/conf.h> 20#include <sys/disk.h> 21#include <sys/devicestat.h> 22#include <sys/module.h> 23#include <machine/bus.h> 24#include <machine/clock.h> 25#include <machine/resource.h> 26 27#include <vm/vm.h> 28#include <vm/pmap.h> 29#include <vm/vm_param.h> 30 31#include <sys/bus.h> 32#include <isa/isareg.h> 33#include <isa/isavar.h> 34 35#ifndef MDNSECT 36#define MDNSECT (10000 * 2) 37#endif 38 39MALLOC_DEFINE(M_MD, "MD disk", "Memory Disk"); 40MALLOC_DEFINE(M_MDSECT, "MD sectors", "Memory Disk Sectors"); 41 42static int md_debug = 0; 43SYSCTL_INT(_debug, OID_AUTO, mddebug, CTLFLAG_RW, &md_debug, 0, ""); 44 45#define CDEV_MAJOR 95 46#define BDEV_MAJOR 22 47 48static d_strategy_t mdstrategy; 49static d_open_t mdopen; 50static d_ioctl_t mdioctl; 51 52static struct cdevsw md_cdevsw = { 53 /* open */ mdopen, 54 /* close */ nullclose, 55 /* read */ physread, 56 /* write */ physwrite, 57 /* ioctl */ mdioctl, 58 /* stop */ nostop, 59 /* reset */ noreset, 60 /* devtotty */ nodevtotty, 61 /* poll */ nopoll, 62 /* mmap */ nommap, 63 /* strategy */ mdstrategy, 64 /* name */ "md", 65 /* parms */ noparms, 66 /* maj */ CDEV_MAJOR, 67 /* dump */ nodump, 68 /* psize */ nopsize, 69 /* flags */ D_DISK | D_CANFREE, 70 /* maxio */ 0, 71 /* bmaj */ BDEV_MAJOR 72}; 73static struct cdevsw mddisk_cdevsw; 74 75struct md_s { 76 int unit; 77 struct devstat stats; 78 struct buf_queue_head buf_queue; 79 struct disk disk; 80 dev_t dev; 81 unsigned nsect; 82 unsigned nsecp; 83 u_char **secp; 84 85 int busy; 86}; 87 88static int mdunits; 89 90static int 91mdopen(dev_t dev, int flag, int fmt, struct proc *p) 92{ 93 struct md_s *sc; 94 struct disklabel *dl; 95 96 if (md_debug) 97 printf("mdopen(%s %x %x %p)\n", 98 devtoname(dev), flag, fmt, p); 99 100 sc = dev->si_drv1; 101 102 dl = &sc->disk.d_label; 103 bzero(dl, sizeof(*dl)); 104 dl->d_secsize = DEV_BSIZE; 105 dl->d_nsectors = 1024; 106 dl->d_ntracks = 1; 107 dl->d_secpercyl = dl->d_nsectors + dl->d_ntracks; 108 dl->d_secperunit = sc->nsect; 109 dl->d_ncylinders = dl->d_secperunit / dl->d_secpercyl; 110 return (0); 111} 112 113static int 114mdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) 115{ 116 117 if (md_debug) 118 printf("mdioctl(%s %lx %p %x %p)\n", 119 devtoname(dev), cmd, addr, flags, p); 120 121 return (ENOIOCTL); 122} 123 124static void 125mdstrategy(struct buf *bp) 126{ 127 int s, i; 128 struct md_s *sc; 129 devstat_trans_flags dop; 130 u_char *secp, **secpp, *dst; 131 unsigned secno, nsec, secval, uc; 132 133 if (md_debug > 1) 134 printf("mdstrategy(%p) %s %lx, %d, %ld, %p)\n", 135 bp, devtoname(bp->b_dev), bp->b_flags, bp->b_blkno, 136 bp->b_bcount / DEV_BSIZE, bp->b_data); 137 138 sc = bp->b_dev->si_drv1; 139 140 s = splbio(); 141 142 bufqdisksort(&sc->buf_queue, bp); 143 144 if (sc->busy) { 145 splx(s); 146 return; 147 } 148 149 sc->busy++; 150 151 while (1) { 152 bp = bufq_first(&sc->buf_queue); 153 if (bp) 154 bufq_remove(&sc->buf_queue, bp); 155 splx(s); 156 if (!bp) 157 break; 158 159 devstat_start_transaction(&sc->stats); 160 161 if (bp->b_flags & B_FREEBUF) 162 dop = DEVSTAT_NO_DATA; 163 else if (bp->b_flags & B_READ) 164 dop = DEVSTAT_READ; 165 else 166 dop = DEVSTAT_WRITE; 167 168 nsec = bp->b_bcount / DEV_BSIZE; 169 secno = bp->b_pblkno; 170 dst = bp->b_data; 171 while (nsec--) { 172 173 if (secno < sc->nsecp) { 174 secpp = &sc->secp[secno]; 175 if ((u_int)*secpp > 255) { 176 secp = *secpp; 177 secval = 0; 178 } else { 179 secp = 0; 180 secval = (u_int) *secpp; 181 } 182 } else { 183 secpp = 0; 184 secp = 0; 185 secval = 0; 186 } 187 if (md_debug > 2) 188 printf("%x %p %p %d\n", bp->b_flags, secpp, secp, secval); 189 190 if (bp->b_flags & B_FREEBUF) { 191 if (secpp) { 192 if (secp) 193 FREE(secp, M_MDSECT); 194 *secpp = 0; 195 } 196 } else if (bp->b_flags & B_READ) { 197 if (secp) { 198 bcopy(secp, dst, DEV_BSIZE); 199 } else if (secval) { 200 for (i = 0; i < DEV_BSIZE; i++) 201 dst[i] = secval; 202 } else { 203 bzero(dst, DEV_BSIZE); 204 } 205 } else { 206 uc = dst[0]; 207 for (i = 1; i < DEV_BSIZE; i++) 208 if (dst[i] != uc) 209 break; 210 if (i == DEV_BSIZE && !uc) { 211 if (secp) 212 FREE(secp, M_MDSECT); 213 if (secpp) 214 *secpp = (u_char *)uc; 215 } else { 216 if (!secpp) { 217 MALLOC(secpp, u_char **, (secno + nsec + 1) * sizeof(u_char *), M_MD, M_WAITOK); 218 bzero(secpp, (secno + nsec + 1) * sizeof(u_char *)); 219 bcopy(sc->secp, secpp, sc->nsecp * sizeof(u_char *)); 220 FREE(sc->secp, M_MD); 221 sc->secp = secpp; 222 sc->nsecp = secno + nsec + 1; 223 secpp = &sc->secp[secno]; 224 } 225 if (i == DEV_BSIZE) { 226 if (secp) 227 FREE(secp, M_MDSECT); 228 *secpp = (u_char *)uc; 229 } else { 230 if (!secp) 231 MALLOC(secp, u_char *, DEV_BSIZE, M_MDSECT, M_WAITOK); 232 bcopy(dst, secp, DEV_BSIZE); 233 234 *secpp = secp; 235 } 236 } 237 } 238 secno++; 239 dst += DEV_BSIZE; 240 } 241 242 bp->b_resid = 0; 243 devstat_end_transaction_buf(&sc->stats, bp); 244 biodone(bp); 245 s = splbio(); 246 } 247 sc->busy = 0; 248 return; 249} 250 251static dev_t 252mdcreate(void) 253{ 254 struct md_s *sc; 255 256 MALLOC(sc, struct md_s *,sizeof(*sc), M_MD, M_WAITOK); 257 bzero(sc, sizeof(*sc)); 258 sc->unit = mdunits++; 259 260 bufq_init(&sc->buf_queue); 261 262 devstat_add_entry(&sc->stats, "md", sc->unit, DEV_BSIZE, 263 DEVSTAT_NO_ORDERED_TAGS, 264 DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER, 0x190); 265 266 sc->dev = disk_create(sc->unit, &sc->disk, 0, 267 &md_cdevsw, &mddisk_cdevsw); 268 269 sc->dev->si_drv1 = sc; 270 sc->nsect = MDNSECT; /* for now */ 271 MALLOC(sc->secp, u_char **, sizeof(u_char *), M_MD, M_WAITOK); 272 bzero(sc->secp, sizeof(u_char *)); 273 sc->nsecp = 1; 274 275 return (0); 276} 277 278static void 279md_drvinit(void *unused) 280{ 281 282 mdcreate(); 283} 284 285SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR, md_drvinit,NULL) 286 287