diff options
| author | thorpej <thorpej@NetBSD.org> | 2004-10-15 04:42:09 +0000 |
|---|---|---|
| committer | thorpej <thorpej@NetBSD.org> | 2004-10-15 04:42:09 +0000 |
| commit | ffb78793fc966e088693aa9452b7769149e2d2d0 (patch) | |
| tree | 1ddca86e1eaf0e54f8bd45d6a7c8e6fbe5a29b30 /sys/dev | |
| parent | 45bba4e135544fab4512fd29778ab6499d58993d (diff) | |
Use config_attach_pseudo() to create device instances in the device
tree for created wedges. This is necessary for setroot().
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/dkwedge/dk.c | 133 |
1 files changed, 116 insertions, 17 deletions
diff --git a/sys/dev/dkwedge/dk.c b/sys/dev/dkwedge/dk.c index 2f762b397e6..6f2e7855f9e 100644 --- a/sys/dev/dkwedge/dk.c +++ b/sys/dev/dkwedge/dk.c @@ -1,4 +1,4 @@ -/* $NetBSD: dk.c,v 1.1 2004/10/04 01:07:25 thorpej Exp $ */ +/* $NetBSD: dk.c,v 1.2 2004/10/15 04:42:09 thorpej Exp $ */ /*- * Copyright (c) 2004 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.1 2004/10/04 01:07:25 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.2 2004/10/15 04:42:09 thorpej Exp $"); #include "opt_dkwedge.h" @@ -56,6 +56,7 @@ __KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.1 2004/10/04 01:07:25 thorpej Exp $"); #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> +#include <sys/device.h> #include <miscfs/specfs/specdev.h> @@ -69,9 +70,9 @@ typedef enum { } dkwedge_state_t; struct dkwedge_softc { - char sc_devname[16]; /* device-style name (e.g. "dk0") */ + struct device *sc_dev; /* pointer to our pseudo-device */ + struct cfdata sc_cfdata; /* our cfdata structure */ uint8_t sc_wname[128]; /* wedge name (Unicode, UTF-8) */ - u_int sc_unit; /* our unit # */ dkwedge_state_t sc_state; /* state this wedge is in */ @@ -127,6 +128,68 @@ static struct lock dkwedge_discovery_methods_lock = LOCK_INITIALIZER(PRIBIO, "dkddm", 0, 0); /* + * dkwedge_match: + * + * Autoconfiguration match function for pseudo-device glue. + */ +static int +dkwedge_match(struct device *parent, struct cfdata *match, void *aux) +{ + + /* Pseudo-device; always present. */ + return (1); +} + +/* + * dkwedge_attach: + * + * Autoconfiguration attach function for pseudo-device glue. + */ +static void +dkwedge_attach(struct device *parent, struct device *self, void *aux) +{ + + /* Nothing to do. */ +} + +/* + * dkwedge_detach: + * + * Autoconfiguration detach function for pseudo-device glue. + */ +static int +dkwedge_detach(struct device *self, int flags) +{ + + /* Always succeeds. */ + return (0); +} + +CFDRIVER_DECL(dk, DV_DISK, NULL); +CFATTACH_DECL(dk, sizeof(struct device), + dkwedge_match, dkwedge_attach, dkwedge_detach, NULL); + +static int dkwedge_cfglue_initialized; +static struct simplelock dkwedge_cfglue_initialized_slock = + SIMPLELOCK_INITIALIZER; + +static void +dkwedge_cfglue_init(void) +{ + + simple_lock(&dkwedge_cfglue_initialized_slock); + if (dkwedge_cfglue_initialized == 0) { + if (config_cfdriver_attach(&dk_cd) != 0) + panic("dkwedge: unable to attach cfdriver"); + if (config_cfattach_attach(dk_cd.cd_name, &dk_ca) != 0) + panic("dkwedge: unable to attach cfattach"); + + dkwedge_cfglue_initialized = 1; + } + simple_unlock(&dkwedge_cfglue_initialized_slock); +} + +/* * dkwedge_wait_drain: * * Wait for I/O on the wedge to drain. @@ -209,6 +272,9 @@ dkwedge_add(struct dkwedge_info *dkw) int error; dev_t pdev; + if (dkwedge_cfglue_initialized == 0) + dkwedge_cfglue_init(); + dkw->dkw_parent[sizeof(dkw->dkw_parent) - 1] = '\0'; pdk = disk_find(dkw->dkw_parent); if (pdk == NULL) @@ -277,6 +343,12 @@ dkwedge_add(struct dkwedge_info *dkw) return (error); } + /* Fill in our cfdata for the pseudo-device glue. */ + sc->sc_cfdata.cf_name = dk_cd.cd_name; + sc->sc_cfdata.cf_atname = dk_ca.ca_name; + /* sc->sc_cfdata.cf_unit set below */ + sc->sc_cfdata.cf_fstate = FSTATE_NOTFOUND; + /* Insert the larval wedge into the array. */ (void) lockmgr(&dkwedges_lock, LK_EXCLUSIVE, NULL); for (error = 0;;) { @@ -290,7 +362,7 @@ dkwedge_add(struct dkwedge_info *dkw) if (dkwedges[unit] == NULL) { if (scpp == NULL) { scpp = &dkwedges[unit]; - sc->sc_unit = unit; + sc->sc_cfdata.cf_unit = unit; } } else { /* XXX Unicode. */ @@ -307,7 +379,7 @@ dkwedge_add(struct dkwedge_info *dkw) if (scpp == NULL) dkwedge_array_expand(); else { - KASSERT(scpp == &dkwedges[sc->sc_unit]); + KASSERT(scpp == &dkwedges[sc->sc_cfdata.cf_unit]); *scpp = sc; break; } @@ -324,12 +396,36 @@ dkwedge_add(struct dkwedge_info *dkw) return (error); } - /* Now that we know the unit #, set the devname. */ - sprintf(sc->sc_devname, "dk%u", sc->sc_unit); - sc->sc_dk.dk_name = sc->sc_devname; + /* + * Now that we know the unit #, attach a pseudo-device for + * this wedge instance. This will provide us with the + * "struct device" necessary for glue to other parts of the + * system. + * + * This should never fail, unless we're almost totally out of + * memory. + */ + if ((sc->sc_dev = config_attach_pseudo(&sc->sc_cfdata)) == NULL) { + aprint_error("%s%u: unable to attach pseudo-device\n", + sc->sc_cfdata.cf_name, sc->sc_cfdata.cf_unit); + + (void) lockmgr(&dkwedges_lock, LK_EXCLUSIVE, NULL); + dkwedges[sc->sc_cfdata.cf_unit] = NULL; + (void) lockmgr(&dkwedges_lock, LK_RELEASE, NULL); + + (void) lockmgr(&pdk->dk_openlock, LK_EXCLUSIVE, NULL); + pdk->dk_nwedges--; + LIST_REMOVE(sc, sc_plink); + (void) lockmgr(&pdk->dk_openlock, LK_RELEASE, NULL); + + bufq_free(&sc->sc_bufq); + free(sc, M_DKWEDGE); + return (ENOMEM); + } + sc->sc_dk.dk_name = sc->sc_dev->dv_xname; /* Return the devname to the caller. */ - strcpy(dkw->dkw_devname, sc->sc_devname); + strcpy(dkw->dkw_devname, sc->sc_dev->dv_xname); /* * XXX Really ought to make the disk_attach() and the changing @@ -342,10 +438,10 @@ dkwedge_add(struct dkwedge_info *dkw) sc->sc_state = DKW_STATE_RUNNING; /* Announce our arrival. */ - aprint_normal("%s at %s: %s\n", sc->sc_devname, pdk->dk_name, + aprint_normal("%s at %s: %s\n", sc->sc_dev->dv_xname, pdk->dk_name, sc->sc_wname); /* XXX Unicode */ aprint_normal("%s: %"PRIu64" blocks at %"PRId64", type: %s\n", - sc->sc_devname, sc->sc_size, sc->sc_offset, sc->sc_ptype); + sc->sc_dev->dv_xname, sc->sc_size, sc->sc_offset, sc->sc_ptype); return (0); } @@ -369,7 +465,7 @@ dkwedge_del(struct dkwedge_info *dkw) (void) lockmgr(&dkwedges_lock, LK_EXCLUSIVE, NULL); for (unit = 0; unit < ndkwedges; unit++) { if ((sc = dkwedges[unit]) != NULL && - strcmp(sc->sc_devname, dkw->dkw_devname) == 0 && + strcmp(sc->sc_dev->dv_xname, dkw->dkw_devname) == 0 && strcmp(sc->sc_parent->dk_name, dkw->dkw_parent) == 0) { /* Mark the wedge as dying. */ sc->sc_state = DKW_STATE_DYING; @@ -420,10 +516,13 @@ dkwedge_del(struct dkwedge_info *dkw) (void) lockmgr(&sc->sc_parent->dk_rawlock, LK_RELEASE, NULL); /* Announce our departure. */ - aprint_normal("%s at %s (%s) deleted\n", sc->sc_devname, + aprint_normal("%s at %s (%s) deleted\n", sc->sc_dev->dv_xname, sc->sc_parent->dk_name, sc->sc_wname); /* XXX Unicode */ + /* Delete our pseudo-device. */ + (void) config_detach(sc->sc_dev, DETACH_FORCE | DETACH_QUIET); + (void) lockmgr(&sc->sc_parent->dk_openlock, LK_EXCLUSIVE, NULL); sc->sc_parent->dk_nwedges--; LIST_REMOVE(sc, sc_plink); @@ -466,7 +565,7 @@ dkwedge_delall(struct disk *pdk) return; } strcpy(dkw.dkw_parent, pdk->dk_name); - strcpy(dkw.dkw_devname, sc->sc_devname); + strcpy(dkw.dkw_devname, sc->sc_dev->dv_xname); (void) lockmgr(&pdk->dk_openlock, LK_RELEASE, NULL); (void) dkwedge_del(&dkw); } @@ -509,7 +608,7 @@ dkwedge_list(struct disk *pdk, struct dkwedge_list *dkwl, struct proc *p) if (sc->sc_state != DKW_STATE_RUNNING) continue; - strcpy(dkw.dkw_devname, sc->sc_devname); + strcpy(dkw.dkw_devname, sc->sc_dev->dv_xname); memcpy(dkw.dkw_wname, sc->sc_wname, sizeof(dkw.dkw_wname)); dkw.dkw_wname[sizeof(dkw.dkw_wname) - 1] = '\0'; strcpy(dkw.dkw_parent, sc->sc_parent->dk_name); @@ -1014,7 +1113,7 @@ dkioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { struct dkwedge_info *dkw = (void *) data; - strcpy(dkw->dkw_devname, sc->sc_devname); + strcpy(dkw->dkw_devname, sc->sc_dev->dv_xname); memcpy(dkw->dkw_wname, sc->sc_wname, sizeof(dkw->dkw_wname)); dkw->dkw_wname[sizeof(dkw->dkw_wname) - 1] = '\0'; strcpy(dkw->dkw_parent, sc->sc_parent->dk_name); |
