Make the attach functions for real and pseudo devices share as much code
as possible. For that, split out a function which does the allocation of a softc (without linking it into global structures) and a function which inserts the device into the global alldevs lists and the per-driver cd_devs. There is a little semantic change involved: the pseudo-device code didn't interpret FSTATE_STAR as such, for no good reason. This looks harmless; I'll modify driver frontends as I find ways to test. Get config_makeroom() out of the public namespace - that's clearly an internal of autoconf which drivers can't be allowed to deal with.
This commit is contained in:
parent
068d2b32bc
commit
7767c569f2
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: subr_autoconf.c,v 1.116 2007/02/21 23:00:04 thorpej Exp $ */
|
||||
/* $NetBSD: subr_autoconf.c,v 1.117 2007/03/05 20:32:45 drochner Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996, 2000 Christopher G. Demetriou
|
||||
|
@ -77,7 +77,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.116 2007/02/21 23:00:04 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.117 2007/03/05 20:32:45 drochner Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
|
||||
|
@ -147,6 +147,11 @@ struct matchinfo {
|
|||
|
||||
static char *number(char *, int);
|
||||
static void mapply(struct matchinfo *, cfdata_t);
|
||||
static device_t config_devalloc(const device_t, const cfdata_t, const int *);
|
||||
static void config_devdealloc(device_t);
|
||||
static void config_makeroom(int, struct cfdriver *);
|
||||
static void config_devlink(device_t);
|
||||
static void config_devunlink(device_t);
|
||||
|
||||
struct deferred_config {
|
||||
TAILQ_ENTRY(deferred_config) dc_queue;
|
||||
|
@ -863,7 +868,7 @@ number(char *ep, int n)
|
|||
/*
|
||||
* Expand the size of the cd_devs array if necessary.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
config_makeroom(int n, struct cfdriver *cd)
|
||||
{
|
||||
int old, new;
|
||||
|
@ -896,36 +901,67 @@ config_makeroom(int n, struct cfdriver *cd)
|
|||
cd->cd_devs = nsp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach a found device. Allocates memory for device variables.
|
||||
*/
|
||||
device_t
|
||||
config_attach_loc(device_t parent, cfdata_t cf,
|
||||
const int *locs, void *aux, cfprint_t print)
|
||||
static void
|
||||
config_devlink(device_t dev)
|
||||
{
|
||||
struct cfdriver *cd = dev->dv_cfdriver;
|
||||
|
||||
/* put this device in the devices array */
|
||||
config_makeroom(dev->dv_unit, cd);
|
||||
if (cd->cd_devs[dev->dv_unit])
|
||||
panic("config_attach: duplicate %s", dev->dv_xname);
|
||||
cd->cd_devs[dev->dv_unit] = dev;
|
||||
|
||||
TAILQ_INSERT_TAIL(&alldevs, dev, dv_list); /* link up */
|
||||
}
|
||||
|
||||
static void
|
||||
config_devunlink(device_t dev)
|
||||
{
|
||||
struct cfdriver *cd = dev->dv_cfdriver;
|
||||
int i;
|
||||
|
||||
/* Unlink from device list. */
|
||||
TAILQ_REMOVE(&alldevs, dev, dv_list);
|
||||
|
||||
/* Remove from cfdriver's array. */
|
||||
cd->cd_devs[dev->dv_unit] = NULL;
|
||||
|
||||
/*
|
||||
* If the device now has no units in use, deallocate its softc array.
|
||||
*/
|
||||
for (i = 0; i < cd->cd_ndevs; i++)
|
||||
if (cd->cd_devs[i] != NULL)
|
||||
break;
|
||||
if (i == cd->cd_ndevs) { /* nothing found; deallocate */
|
||||
free(cd->cd_devs, M_DEVBUF);
|
||||
cd->cd_devs = NULL;
|
||||
cd->cd_ndevs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static device_t
|
||||
config_devalloc(const device_t parent, const cfdata_t cf, const int *locs)
|
||||
{
|
||||
device_t dev;
|
||||
struct cftable *ct;
|
||||
struct cfdriver *cd;
|
||||
struct cfattach *ca;
|
||||
size_t lname, lunit;
|
||||
const char *xunit;
|
||||
int myunit;
|
||||
char num[10];
|
||||
device_t dev;
|
||||
const struct cfiattrdata *ia;
|
||||
|
||||
#if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
|
||||
if (splash_progress_state)
|
||||
splash_progress_update(splash_progress_state);
|
||||
#endif
|
||||
|
||||
cd = config_cfdriver_lookup(cf->cf_name);
|
||||
KASSERT(cd != NULL);
|
||||
if (cd == NULL)
|
||||
return (NULL);
|
||||
|
||||
ca = config_cfattach_lookup_cd(cd, cf->cf_atname);
|
||||
KASSERT(ca != NULL);
|
||||
if (ca == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (ca->ca_devsize < sizeof(struct device))
|
||||
panic("config_attach");
|
||||
panic("config_devalloc");
|
||||
|
||||
#ifndef __BROKEN_CONFIG_UNIT_USAGE
|
||||
if (cf->cf_fstate == FSTATE_STAR) {
|
||||
|
@ -938,17 +974,11 @@ config_attach_loc(device_t parent, cfdata_t cf,
|
|||
*/
|
||||
} else {
|
||||
myunit = cf->cf_unit;
|
||||
KASSERT(cf->cf_fstate == FSTATE_NOTFOUND);
|
||||
cf->cf_fstate = FSTATE_FOUND;
|
||||
}
|
||||
if (myunit < cd->cd_ndevs && cd->cd_devs[myunit] != NULL)
|
||||
return (NULL);
|
||||
}
|
||||
#else
|
||||
myunit = cf->cf_unit;
|
||||
if (cf->cf_fstate == FSTATE_STAR)
|
||||
cf->cf_unit++;
|
||||
else {
|
||||
KASSERT(cf->cf_fstate == FSTATE_NOTFOUND);
|
||||
cf->cf_fstate = FSTATE_FOUND;
|
||||
}
|
||||
#endif /* ! __BROKEN_CONFIG_UNIT_USAGE */
|
||||
|
||||
/* compute length of name and decimal expansion of unit number */
|
||||
|
@ -956,15 +986,13 @@ config_attach_loc(device_t parent, cfdata_t cf,
|
|||
xunit = number(&num[sizeof(num)], myunit);
|
||||
lunit = &num[sizeof(num)] - xunit;
|
||||
if (lname + lunit > sizeof(dev->dv_xname))
|
||||
panic("config_attach: device name too long");
|
||||
panic("config_devalloc: device name too long");
|
||||
|
||||
/* get memory for all device vars */
|
||||
dev = (device_t)malloc(ca->ca_devsize, M_DEVBUF,
|
||||
cold ? M_NOWAIT : M_WAITOK);
|
||||
M_ZERO | (cold ? M_NOWAIT : M_WAITOK));
|
||||
if (!dev)
|
||||
panic("config_attach: memory allocation for device softc failed");
|
||||
memset(dev, 0, ca->ca_devsize);
|
||||
TAILQ_INSERT_TAIL(&alldevs, dev, dv_list); /* link up */
|
||||
panic("config_devalloc: memory allocation for device softc failed");
|
||||
dev->dv_class = cd->cd_class;
|
||||
dev->dv_cfdata = cf;
|
||||
dev->dv_cfdriver = cd;
|
||||
|
@ -985,6 +1013,54 @@ config_attach_loc(device_t parent, cfdata_t cf,
|
|||
dev->dv_properties = prop_dictionary_create();
|
||||
KASSERT(dev->dv_properties != NULL);
|
||||
|
||||
return (dev);
|
||||
}
|
||||
|
||||
static void
|
||||
config_devdealloc(device_t dev)
|
||||
{
|
||||
|
||||
KASSERT(dev->dv_properties != NULL);
|
||||
prop_object_release(dev->dv_properties);
|
||||
|
||||
if (dev->dv_locators)
|
||||
free(dev->dv_locators, M_DEVBUF);
|
||||
|
||||
free(dev, M_DEVBUF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach a found device.
|
||||
*/
|
||||
device_t
|
||||
config_attach_loc(device_t parent, cfdata_t cf,
|
||||
const int *locs, void *aux, cfprint_t print)
|
||||
{
|
||||
device_t dev;
|
||||
struct cftable *ct;
|
||||
const char *drvname;
|
||||
|
||||
#if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
|
||||
if (splash_progress_state)
|
||||
splash_progress_update(splash_progress_state);
|
||||
#endif
|
||||
|
||||
dev = config_devalloc(parent, cf, locs);
|
||||
if (!dev)
|
||||
panic("config_attach: allocation of device softc failed");
|
||||
|
||||
/* XXX redundant - see below? */
|
||||
if (cf->cf_fstate != FSTATE_STAR) {
|
||||
KASSERT(cf->cf_fstate == FSTATE_NOTFOUND);
|
||||
cf->cf_fstate = FSTATE_FOUND;
|
||||
}
|
||||
#ifdef __BROKEN_CONFIG_UNIT_USAGE
|
||||
else
|
||||
cf->cf_unit++;
|
||||
#endif
|
||||
|
||||
config_devlink(dev);
|
||||
|
||||
if (config_do_twiddle)
|
||||
twiddle();
|
||||
else
|
||||
|
@ -1003,19 +1079,15 @@ config_attach_loc(device_t parent, cfdata_t cf,
|
|||
(void) (*print)(aux, NULL);
|
||||
}
|
||||
|
||||
/* put this device in the devices array */
|
||||
config_makeroom(dev->dv_unit, cd);
|
||||
if (cd->cd_devs[dev->dv_unit])
|
||||
panic("config_attach: duplicate %s", dev->dv_xname);
|
||||
cd->cd_devs[dev->dv_unit] = dev;
|
||||
|
||||
/*
|
||||
* Before attaching, clobber any unfound devices that are
|
||||
* otherwise identical.
|
||||
* XXX code above is redundant?
|
||||
*/
|
||||
drvname = dev->dv_cfdriver->cd_name;
|
||||
TAILQ_FOREACH(ct, &allcftables, ct_list) {
|
||||
for (cf = ct->ct_cfdata; cf->cf_name; cf++) {
|
||||
if (STREQ(cf->cf_name, cd->cd_name) &&
|
||||
if (STREQ(cf->cf_name, drvname) &&
|
||||
cf->cf_unit == dev->dv_unit) {
|
||||
if (cf->cf_fstate == FSTATE_NOTFOUND)
|
||||
cf->cf_fstate = FSTATE_FOUND;
|
||||
|
@ -1037,7 +1109,7 @@ config_attach_loc(device_t parent, cfdata_t cf,
|
|||
if (splash_progress_state)
|
||||
splash_progress_update(splash_progress_state);
|
||||
#endif
|
||||
(*ca->ca_attach)(parent, dev, aux);
|
||||
(*dev->dv_cfattach->ca_attach)(parent, dev, aux);
|
||||
#if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
|
||||
if (splash_progress_state)
|
||||
splash_progress_update(splash_progress_state);
|
||||
|
@ -1066,84 +1138,21 @@ device_t
|
|||
config_attach_pseudo(cfdata_t cf)
|
||||
{
|
||||
device_t dev;
|
||||
struct cfdriver *cd;
|
||||
struct cfattach *ca;
|
||||
size_t lname, lunit;
|
||||
const char *xunit;
|
||||
int myunit;
|
||||
char num[10];
|
||||
|
||||
cd = config_cfdriver_lookup(cf->cf_name);
|
||||
if (cd == NULL)
|
||||
return (NULL);
|
||||
|
||||
ca = config_cfattach_lookup_cd(cd, cf->cf_atname);
|
||||
if (ca == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (ca->ca_devsize < sizeof(struct device))
|
||||
panic("config_attach_pseudo");
|
||||
|
||||
/*
|
||||
* We just ignore cf_fstate, instead doing everything with
|
||||
* cf_unit.
|
||||
*
|
||||
* XXX Should we change this and use FSTATE_NOTFOUND and
|
||||
* XXX FSTATE_STAR?
|
||||
*/
|
||||
|
||||
if (cf->cf_unit == DVUNIT_ANY) {
|
||||
for (myunit = 0; myunit < cd->cd_ndevs; myunit++)
|
||||
if (cd->cd_devs[myunit] == NULL)
|
||||
break;
|
||||
/*
|
||||
* myunit is now the unit of the first NULL device pointer.
|
||||
*/
|
||||
} else {
|
||||
myunit = cf->cf_unit;
|
||||
if (myunit < cd->cd_ndevs && cd->cd_devs[myunit] != NULL)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* compute length of name and decimal expansion of unit number */
|
||||
lname = strlen(cd->cd_name);
|
||||
xunit = number(&num[sizeof(num)], myunit);
|
||||
lunit = &num[sizeof(num)] - xunit;
|
||||
if (lname + lunit > sizeof(dev->dv_xname))
|
||||
panic("config_attach_pseudo: device name too long");
|
||||
|
||||
/* get memory for all device vars */
|
||||
dev = (device_t)malloc(ca->ca_devsize, M_DEVBUF,
|
||||
cold ? M_NOWAIT : M_WAITOK);
|
||||
dev = config_devalloc(ROOT, cf, NULL);
|
||||
if (!dev)
|
||||
panic("config_attach_pseudo: memory allocation for device "
|
||||
"softc failed");
|
||||
memset(dev, 0, ca->ca_devsize);
|
||||
TAILQ_INSERT_TAIL(&alldevs, dev, dv_list); /* link up */
|
||||
dev->dv_class = cd->cd_class;
|
||||
dev->dv_cfdata = cf;
|
||||
dev->dv_cfdriver = cd;
|
||||
dev->dv_cfattach = ca;
|
||||
dev->dv_unit = myunit;
|
||||
memcpy(dev->dv_xname, cd->cd_name, lname);
|
||||
memcpy(dev->dv_xname + lname, xunit, lunit);
|
||||
dev->dv_parent = ROOT;
|
||||
dev->dv_flags = DVF_ACTIVE; /* always initially active */
|
||||
dev->dv_properties = prop_dictionary_create();
|
||||
KASSERT(dev->dv_properties != NULL);
|
||||
return (NULL);
|
||||
|
||||
/* put this device in the devices array */
|
||||
config_makeroom(dev->dv_unit, cd);
|
||||
if (cd->cd_devs[dev->dv_unit])
|
||||
panic("config_attach_pseudo: duplicate %s", dev->dv_xname);
|
||||
cd->cd_devs[dev->dv_unit] = dev;
|
||||
/* XXX mark busy in cfdata */
|
||||
|
||||
config_devlink(dev);
|
||||
|
||||
#if 0 /* XXXJRT not yet */
|
||||
#ifdef __HAVE_DEVICE_REGISTER
|
||||
device_register(dev, NULL); /* like a root node */
|
||||
#endif
|
||||
#endif
|
||||
(*ca->ca_attach)(ROOT, dev, NULL);
|
||||
(*dev->dv_cfattach->ca_attach)(ROOT, dev, NULL);
|
||||
config_process_deferred(&deferred_config_queue, dev);
|
||||
return (dev);
|
||||
}
|
||||
|
@ -1167,7 +1176,7 @@ config_detach(device_t dev, int flags)
|
|||
#ifdef DIAGNOSTIC
|
||||
device_t d;
|
||||
#endif
|
||||
int rv = 0, i;
|
||||
int rv = 0;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (dev->dv_cfdata != NULL &&
|
||||
|
@ -1260,39 +1269,13 @@ config_detach(device_t dev, int flags)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlink from device list.
|
||||
*/
|
||||
TAILQ_REMOVE(&alldevs, dev, dv_list);
|
||||
config_devunlink(dev);
|
||||
|
||||
/*
|
||||
* Remove from cfdriver's array, tell the world (unless it was
|
||||
* a pseudo-device), and free softc.
|
||||
*/
|
||||
cd->cd_devs[dev->dv_unit] = NULL;
|
||||
if (dev->dv_cfdata != NULL && (flags & DETACH_QUIET) == 0)
|
||||
aprint_normal("%s detached\n", dev->dv_xname);
|
||||
if (dev->dv_locators)
|
||||
free(dev->dv_locators, M_DEVBUF);
|
||||
KASSERT(dev->dv_properties != NULL);
|
||||
prop_object_release(dev->dv_properties);
|
||||
free(dev, M_DEVBUF);
|
||||
|
||||
/*
|
||||
* If the device now has no units in use, deallocate its softc array.
|
||||
*/
|
||||
for (i = 0; i < cd->cd_ndevs; i++)
|
||||
if (cd->cd_devs[i] != NULL)
|
||||
break;
|
||||
if (i == cd->cd_ndevs) { /* nothing found; deallocate */
|
||||
free(cd->cd_devs, M_DEVBUF);
|
||||
cd->cd_devs = NULL;
|
||||
cd->cd_ndevs = 0;
|
||||
}
|
||||
config_devdealloc(dev);
|
||||
|
||||
/*
|
||||
* Return success.
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: device.h,v 1.93 2007/02/21 23:00:09 thorpej Exp $ */
|
||||
/* $NetBSD: device.h,v 1.94 2007/03/05 20:32:43 drochner Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996, 2000 Christopher G. Demetriou
|
||||
|
@ -340,7 +340,6 @@ int config_match(device_t, cfdata_t, void *);
|
|||
|
||||
device_t config_attach_pseudo(cfdata_t);
|
||||
|
||||
void config_makeroom(int n, struct cfdriver *cd);
|
||||
int config_detach(device_t, int);
|
||||
int config_activate(device_t);
|
||||
int config_deactivate(device_t);
|
||||
|
|
Loading…
Reference in New Issue