aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/md/md.c
diff options
context:
space:
mode:
authorPoul-Henning Kamp <phk@FreeBSD.org>1999-11-20 22:43:27 +0000
committerPoul-Henning Kamp <phk@FreeBSD.org>1999-11-20 22:43:27 +0000
commit95f1a897f9ef27e6213ceed7723eb3c22af47eab (patch)
treed6f6bd2ddf2a06a3fa4f213bd3b62794d8477e8c /sys/dev/md/md.c
parent2186a02c956f673c07885aba528170eddba61773 (diff)
Notes
Diffstat (limited to 'sys/dev/md/md.c')
-rw-r--r--sys/dev/md/md.c192
1 files changed, 126 insertions, 66 deletions
diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c
index b17c69e13cae..66d4a013e164 100644
--- a/sys/dev/md/md.c
+++ b/sys/dev/md/md.c
@@ -19,6 +19,7 @@
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/sysctl.h>
+#include <sys/linker.h>
#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;
+ 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 = (u_int) *secpp;
+ secval = 0;
}
- } else {
- secpp = 0;
- secp = 0;
- secval = 0;
- }
- if (md_debug > 2)
- printf("%lx %p %p %d\n", bp->b_flags, secpp, secp, secval);
+ 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 (bp->b_flags & B_FREEBUF) {
+ if (secpp) {
+ if (secp)
+ FREE(secp, M_MDSECT);
+ *secpp = 0;
}
- if (i == DEV_BSIZE) {
+ } 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);
- *secpp = (u_char *)uc;
+ if (secpp)
+ *secpp = (u_char *)uc;
} else {
- if (!secp)
- MALLOC(secp, u_char *, DEV_BSIZE, M_MDSECT, M_WAITOK);
- bcopy(dst, secp, DEV_BSIZE);
+ 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)