diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c index b17c69e13ca..66d4a013e16 100644 --- a/sys/dev/md/md.c +++ b/sys/dev/md/md.c @@ -19,6 +19,7 @@ #include #include #include +#include #ifndef MDNSECT #define MDNSECT (10000 * 2) @@ -61,11 +62,17 @@ struct md_s { struct buf_queue_head buf_queue; struct disk disk; dev_t dev; + int busy; + enum {MD_MALLOC, MD_PRELOAD} type; unsigned nsect; + + /* MD_MALLOC related fields */ unsigned nsecp; u_char **secp; - int busy; + /* MD_PRELOAD related fields */ + u_char *pl_ptr; + unsigned pl_len; }; static int mdunits; @@ -87,7 +94,7 @@ mdopen(dev_t dev, int flag, int fmt, struct proc *p) dl->d_secsize = DEV_BSIZE; dl->d_nsectors = 1024; dl->d_ntracks = 1; - dl->d_secpercyl = dl->d_nsectors + dl->d_ntracks; + dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks; dl->d_secperunit = sc->nsect; dl->d_ncylinders = dl->d_secperunit / dl->d_secpercyl; return (0); @@ -148,78 +155,88 @@ mdstrategy(struct buf *bp) else dop = DEVSTAT_WRITE; - nsec = bp->b_bcount / DEV_BSIZE; - secno = bp->b_pblkno; - dst = bp->b_data; - while (nsec--) { + if (sc->type == MD_MALLOC) { + nsec = bp->b_bcount / DEV_BSIZE; + secno = bp->b_pblkno; + dst = bp->b_data; + while (nsec--) { - if (secno < sc->nsecp) { - secpp = &sc->secp[secno]; - if ((u_int)*secpp > 255) { - secp = *secpp; - secval = 0; - } else { - secp = 0; - secval = (u_int) *secpp; - } - } else { - secpp = 0; - secp = 0; - secval = 0; - } - if (md_debug > 2) - printf("%lx %p %p %d\n", bp->b_flags, secpp, secp, secval); - - if (bp->b_flags & B_FREEBUF) { - if (secpp) { - if (secp) - FREE(secp, M_MDSECT); - *secpp = 0; - } - } else if (bp->b_flags & B_READ) { - if (secp) { - bcopy(secp, dst, DEV_BSIZE); - } else if (secval) { - for (i = 0; i < DEV_BSIZE; i++) - dst[i] = secval; - } else { - bzero(dst, DEV_BSIZE); - } - } else { - uc = dst[0]; - for (i = 1; i < DEV_BSIZE; i++) - if (dst[i] != uc) - break; - if (i == DEV_BSIZE && !uc) { - if (secp) - FREE(secp, M_MDSECT); - if (secpp) - *secpp = (u_char *)uc; - } else { - if (!secpp) { - MALLOC(secpp, u_char **, (secno + nsec + 1) * sizeof(u_char *), M_MD, M_WAITOK); - bzero(secpp, (secno + nsec + 1) * sizeof(u_char *)); - bcopy(sc->secp, secpp, sc->nsecp * sizeof(u_char *)); - FREE(sc->secp, M_MD); - sc->secp = secpp; - sc->nsecp = secno + nsec + 1; - secpp = &sc->secp[secno]; + if (secno < sc->nsecp) { + secpp = &sc->secp[secno]; + if ((u_int)*secpp > 255) { + secp = *secpp; + secval = 0; + } else { + secp = 0; + secval = (u_int) *secpp; } - if (i == DEV_BSIZE) { + } else { + secpp = 0; + secp = 0; + secval = 0; + } + if (md_debug > 2) + printf("%lx %p %p %d\n", bp->b_flags, secpp, secp, secval); + + if (bp->b_flags & B_FREEBUF) { + if (secpp) { if (secp) FREE(secp, M_MDSECT); - *secpp = (u_char *)uc; + *secpp = 0; + } + } else if (bp->b_flags & B_READ) { + if (secp) { + bcopy(secp, dst, DEV_BSIZE); + } else if (secval) { + for (i = 0; i < DEV_BSIZE; i++) + dst[i] = secval; } else { - if (!secp) - MALLOC(secp, u_char *, DEV_BSIZE, M_MDSECT, M_WAITOK); - bcopy(dst, secp, DEV_BSIZE); + bzero(dst, DEV_BSIZE); + } + } else { + uc = dst[0]; + for (i = 1; i < DEV_BSIZE; i++) + if (dst[i] != uc) + break; + if (i == DEV_BSIZE && !uc) { + if (secp) + FREE(secp, M_MDSECT); + if (secpp) + *secpp = (u_char *)uc; + } else { + if (!secpp) { + MALLOC(secpp, u_char **, (secno + nsec + 1) * sizeof(u_char *), M_MD, M_WAITOK); + bzero(secpp, (secno + nsec + 1) * sizeof(u_char *)); + bcopy(sc->secp, secpp, sc->nsecp * sizeof(u_char *)); + FREE(sc->secp, M_MD); + sc->secp = secpp; + sc->nsecp = secno + nsec + 1; + secpp = &sc->secp[secno]; + } + if (i == DEV_BSIZE) { + if (secp) + FREE(secp, M_MDSECT); + *secpp = (u_char *)uc; + } else { + if (!secp) + MALLOC(secp, u_char *, DEV_BSIZE, M_MDSECT, M_WAITOK); + bcopy(dst, secp, DEV_BSIZE); - *secpp = secp; + *secpp = secp; + } } } + secno++; + dst += DEV_BSIZE; + } + } else { + if (bp->b_flags & B_FREEBUF) { + /* nothing */ + } else if (bp->b_flags & B_READ) { + bcopy(sc->pl_ptr + (secno << DEV_BSHIFT), bp->b_data, bp->b_bcount); + } else { + bcopy(bp->b_data, sc->pl_ptr + (secno << DEV_BSHIFT), bp->b_bcount); } - secno++; - dst += DEV_BSIZE; } bp->b_resid = 0; @@ -231,14 +248,36 @@ mdstrategy(struct buf *bp) return; } -static dev_t -mdcreate(void) +static void +mdcreate_preload(u_char *image, unsigned length) { struct md_s *sc; MALLOC(sc, struct md_s *,sizeof(*sc), M_MD, M_WAITOK); bzero(sc, sizeof(*sc)); sc->unit = mdunits++; + sc->type = MD_PRELOAD; + bufq_init(&sc->buf_queue); + devstat_add_entry(&sc->stats, "md", sc->unit, DEV_BSIZE, + DEVSTAT_NO_ORDERED_TAGS, + DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER, 0x190); + sc->dev = disk_create(sc->unit, &sc->disk, 0, + &md_cdevsw, &mddisk_cdevsw); + sc->dev->si_drv1 = sc; + sc->nsect = length / DEV_BSIZE; + sc->pl_ptr = image; + sc->pl_len = length; +} + +static void +mdcreate_malloc(void) +{ + struct md_s *sc; + + MALLOC(sc, struct md_s *,sizeof(*sc), M_MD, M_WAITOK); + bzero(sc, sizeof(*sc)); + sc->unit = mdunits++; + sc->type = MD_MALLOC; bufq_init(&sc->buf_queue); @@ -254,15 +293,36 @@ mdcreate(void) MALLOC(sc->secp, u_char **, sizeof(u_char *), M_MD, M_WAITOK); bzero(sc->secp, sizeof(u_char *)); sc->nsecp = 1; - - return (0); } static void md_drvinit(void *unused) { - mdcreate(); + caddr_t mod; + caddr_t c; + u_char *ptr, *name, *type; + unsigned len; + + mod = NULL; + while ((mod = preload_search_next_name(mod)) != NULL) { + name = (char *)preload_search_info(mod, MODINFO_NAME); + type = (char *)preload_search_info(mod, MODINFO_TYPE); + if (name == NULL) + continue; + if (type == NULL) + continue; + if (strcmp(type, "md_image")) + continue; + c = preload_search_info(mod, MODINFO_ADDR); + ptr = *(u_char **)c; + c = preload_search_info(mod, MODINFO_SIZE); + len = *(unsigned *)c; + printf("md%d: Preloaded image <%s> %d bytes at %p\n", + mdunits, name, len, ptr); + mdcreate_preload(ptr, len); + } + mdcreate_malloc(); } SYSINIT(ptcdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR, md_drvinit,NULL)