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