Hints overhaul:

- Replace some very poorly thought out API hacks that should have been
  fixed a long while ago.
- Provide some much more flexible search functions (resource_find_*())
- Use strings for storage instead of an outgrowth of the rather
  inconvenient temporary ioconf table from config().  We already had a
  fallback to using strings before malloc/vm was running anyway.
This commit is contained in:
Peter Wemm 2001-06-12 09:40:04 +00:00
parent 46f48be960
commit 2398f0cd1d
30 changed files with 694 additions and 612 deletions

View File

@ -49,7 +49,7 @@
#include "opt_msgbuf.h"
#include "opt_npx.h"
#include "opt_perfmon.h"
#include "opt_userconfig.h"
/* #include "opt_userconfig.h" */
#include <sys/param.h>
#include <sys/systm.h>

View File

@ -43,8 +43,8 @@ options PROCFS #Process filesystem
options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=15000 #Delay (in ms) before probing SCSI
options UCONSOLE #Allow users to grab the console
options USERCONFIG #boot -c editor
options VISUAL_USERCONFIG #visual boot -c editor
#options USERCONFIG #boot -c editor
#options VISUAL_USERCONFIG #visual boot -c editor
options KTRACE #ktrace(1) support
options SYSVSHM #SYSV-style shared memory
options SYSVMSG #SYSV-style message queues

View File

@ -303,10 +303,10 @@ camperiphnextunit(struct periph_driver *p_drv, u_int newunit, int wired,
path_id_t pathid, target_id_t target, lun_id_t lun)
{
struct cam_periph *periph;
char *periph_name, *strval;
char *periph_name;
int s;
int i, val, dunit;
const char *dname;
int i, val, dunit, r;
const char *dname, *strval;
s = splsoftcam();
periph_name = p_drv->driver_name;
@ -337,10 +337,12 @@ camperiphnextunit(struct periph_driver *p_drv, u_int newunit, int wired,
* device, but do match entries like "da 4 target 5"
* or even "da 4 scbus 1".
*/
i = -1;
while ((i = resource_locate(i, periph_name)) != -1) {
dname = resource_query_name(i);
dunit = resource_query_unit(i);
i = 0;
dname = periph_name;
for (;;) {
r = resource_find_dev(&i, dname, &dunit, NULL, NULL);
if (r != 0)
break;
/* if no "target" and no specific scbus, skip */
if (resource_int_value(dname, dunit, "target", &val) &&
(resource_string_value(dname, dunit, "at",&strval)||
@ -349,7 +351,7 @@ camperiphnextunit(struct periph_driver *p_drv, u_int newunit, int wired,
if (newunit == dunit)
break;
}
if (i == -1)
if (r != 0)
break;
}
splx(s);
@ -362,18 +364,17 @@ camperiphunit(struct periph_driver *p_drv, path_id_t pathid,
{
u_int unit;
int hit, i, val, dunit;
const char *dname;
char pathbuf[32], *strval, *periph_name;
const char *dname, *strval;
char pathbuf[32], *periph_name;
unit = 0;
hit = 0;
periph_name = p_drv->driver_name;
snprintf(pathbuf, sizeof(pathbuf), "scbus%d", pathid);
i = -1;
while ((i = resource_locate(i, periph_name)) != -1) {
dname = resource_query_name(i);
dunit = resource_query_unit(i);
i = 0;
dname = periph_name;
while ((resource_find_dev(&i, dname, &dunit, NULL, NULL)) == 0) {
if (resource_string_value(dname, dunit, "at", &strval) == 0) {
if (strcmp(strval, pathbuf) != 0)
continue;

View File

@ -4346,7 +4346,7 @@ xptnextfreepathid(void)
{
struct cam_eb *bus;
path_id_t pathid;
char *strval;
const char *strval;
pathid = 0;
bus = TAILQ_FIRST(&xpt_busses);
@ -4377,16 +4377,16 @@ xptpathid(const char *sim_name, int sim_unit, int sim_bus)
path_id_t pathid;
int i, dunit, val;
char buf[32];
const char *dname;
pathid = CAM_XPT_PATH_ID;
snprintf(buf, sizeof(buf), "%s%d", sim_name, sim_unit);
i = -1;
while ((i = resource_query_string(i, "at", buf)) != -1) {
if (strcmp(resource_query_name(i), "scbus")) {
i = 0;
while ((resource_find_match(&i, &dname, &dunit, "at", buf)) == 0) {
if (strcmp(dname, "scbus")) {
/* Avoid a bit of foot shooting. */
continue;
}
dunit = resource_query_unit(i);
if (dunit < 0) /* unwired?! */
continue;
if (resource_int_value("scbus", dunit, "bus", &val) == 0) {

View File

@ -403,9 +403,9 @@ options COMPILING_LINT
options UCONSOLE
# XXX - this doesn't belong here either
options USERCONFIG #boot -c editor
options INTRO_USERCONFIG #imply -c and show intro screen
options VISUAL_USERCONFIG #visual boot -c editor
#options USERCONFIG #boot -c editor
#options INTRO_USERCONFIG #imply -c and show intro screen
#options VISUAL_USERCONFIG #visual boot -c editor
#####################################################################
# NETWORKING OPTIONS

View File

@ -82,7 +82,7 @@ alpha/alpha/support.s standard
alpha/alpha/swtch.s standard
alpha/alpha/sys_machdep.c standard
alpha/alpha/trap.c standard
alpha/alpha/userconfig.c optional userconfig
#alpha/alpha/userconfig.c optional userconfig
alpha/alpha/vm_machdep.c standard
alpha/isa/isa.c optional isa
alpha/isa/isa_dma.c optional isa

View File

@ -194,7 +194,7 @@ i386/i386/support.s standard
i386/i386/swtch.s standard
i386/i386/sys_machdep.c standard
i386/i386/trap.c standard
i386/i386/userconfig.c optional userconfig
#i386/i386/userconfig.c optional userconfig
i386/i386/vm86.c standard
i386/i386/vm_machdep.c standard
i386/ibcs2/ibcs2_errno.c optional ibcs2

View File

@ -49,7 +49,7 @@ ia64/ia64/sscdisk.c standard
ia64/ia64/swtch.s standard
ia64/ia64/sys_machdep.c standard
ia64/ia64/trap.c standard
ia64/ia64/userconfig.c optional userconfig
#ia64/ia64/userconfig.c optional userconfig
ia64/ia64/vm_machdep.c standard
ia64/isa/isa.c optional isa
ia64/isa/isa_dma.c optional isa

View File

@ -372,7 +372,7 @@ netsmb/smb_usr.c optional netsmb
pc98/apm/apm.c optional apm
pc98/apm/apm_bioscall.s optional apm
pc98/i386/machdep.c standard
pc98/i386/userconfig.c optional userconfig
#pc98/i386/userconfig.c optional userconfig
pc98/pc98/atapi.c optional wdc
pc98/pc98/clock.c standard
pc98/pc98/diskslice_machdep.c standard

View File

@ -111,10 +111,10 @@ KBD_MAXWAIT opt_kbd.h
KBD_RESETDELAY opt_kbd.h
KBDIO_DEBUG opt_kbd.h
USERCONFIG opt_userconfig.h
VISUAL_USERCONFIG opt_userconfig.h
INTRO_USERCONFIG opt_userconfig.h
DEV_EISA opt_userconfig.h
#USERCONFIG opt_userconfig.h
#VISUAL_USERCONFIG opt_userconfig.h
#INTRO_USERCONFIG opt_userconfig.h
#DEV_EISA opt_userconfig.h
EISA_SLOTS opt_eisa.h

View File

@ -101,10 +101,10 @@ KBD_MAXWAIT opt_kbd.h
KBD_RESETDELAY opt_kbd.h
KBDIO_DEBUG opt_kbd.h
USERCONFIG opt_userconfig.h
VISUAL_USERCONFIG opt_userconfig.h
INTRO_USERCONFIG opt_userconfig.h
DEV_EISA opt_userconfig.h
#USERCONFIG opt_userconfig.h
#VISUAL_USERCONFIG opt_userconfig.h
#INTRO_USERCONFIG opt_userconfig.h
#DEV_EISA opt_userconfig.h
EISA_SLOTS opt_eisa.h

View File

@ -169,11 +169,11 @@ static int
atkbdc_attach(device_t dev)
{
atkbdc_softc_t *sc;
int unit;
int unit, dunit;
int error;
int rid;
int i;
const char *name;
const char *name, *dname;
unit = device_get_unit(dev);
sc = *(atkbdc_softc_t **)device_get_softc(dev);
@ -215,19 +215,17 @@ atkbdc_attach(device_t dev)
* Add all devices configured to be attached to atkbdc0.
*/
name = device_get_nameunit(dev);
i = -1;
while ((i = resource_query_string(i, "at", name)) != -1)
atkbdc_add_device(dev, resource_query_name(i),
resource_query_unit(i));
i = 0;
while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0)
atkbdc_add_device(dev, dname, dunit);
/*
* and atkbdc?
*/
name = device_get_name(dev);
i = -1;
while ((i = resource_query_string(i, "at", name)) != -1)
atkbdc_add_device(dev, resource_query_name(i),
resource_query_unit(i));
i = 0;
while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0)
atkbdc_add_device(dev, dname, dunit);
bus_generic_attach(dev);

View File

@ -169,11 +169,11 @@ static int
atkbdc_attach(device_t dev)
{
atkbdc_softc_t *sc;
int unit;
int unit, dunit;
int error;
int rid;
int i;
const char *name;
const char *name, *dname;
unit = device_get_unit(dev);
sc = *(atkbdc_softc_t **)device_get_softc(dev);
@ -215,19 +215,17 @@ atkbdc_attach(device_t dev)
* Add all devices configured to be attached to atkbdc0.
*/
name = device_get_nameunit(dev);
i = -1;
while ((i = resource_query_string(i, "at", name)) != -1)
atkbdc_add_device(dev, resource_query_name(i),
resource_query_unit(i));
i = 0;
while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0)
atkbdc_add_device(dev, dname, dunit);
/*
* and atkbdc?
*/
name = device_get_name(dev);
i = -1;
while ((i = resource_query_string(i, "at", name)) != -1)
atkbdc_add_device(dev, resource_query_name(i),
resource_query_unit(i));
i = 0;
while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0)
atkbdc_add_device(dev, dname, dunit);
bus_generic_attach(dev);

View File

@ -817,8 +817,8 @@ static int
fdc_attach(device_t dev)
{
struct fdc_data *fdc;
int i, error;
const char *name;
int i, error, dunit;
const char *name, *dname;
fdc = device_get_softc(dev);
error = fdc_alloc_resources(fdc);
@ -856,10 +856,9 @@ fdc_attach(device_t dev)
* devices from the BIOS unless overridden.
*/
name = device_get_nameunit(dev);
i = -1;
while ((i = resource_query_string(i, "at", name)) != -1)
fdc_add_child(dev, resource_query_name(i),
resource_query_unit(i));
i = 0;
while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0)
fdc_add_child(dev, dname, dunit);
return (bus_generic_attach(dev));
}

View File

@ -43,8 +43,8 @@ options PROCFS #Process filesystem
options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!]
options SCSI_DELAY=15000 #Delay (in ms) before probing SCSI
options UCONSOLE #Allow users to grab the console
options USERCONFIG #boot -c editor
options VISUAL_USERCONFIG #visual boot -c editor
#options USERCONFIG #boot -c editor
#options VISUAL_USERCONFIG #visual boot -c editor
options KTRACE #ktrace(1) support
options SYSVSHM #SYSV-style shared memory
options SYSVMSG #SYSV-style message queues

View File

@ -403,9 +403,9 @@ options COMPILING_LINT
options UCONSOLE
# XXX - this doesn't belong here either
options USERCONFIG #boot -c editor
options INTRO_USERCONFIG #imply -c and show intro screen
options VISUAL_USERCONFIG #visual boot -c editor
#options USERCONFIG #boot -c editor
#options INTRO_USERCONFIG #imply -c and show intro screen
#options VISUAL_USERCONFIG #visual boot -c editor
#####################################################################
# NETWORKING OPTIONS

View File

@ -49,7 +49,7 @@
#include "opt_msgbuf.h"
#include "opt_npx.h"
#include "opt_perfmon.h"
#include "opt_userconfig.h"
/* #include "opt_userconfig.h" */
#include <sys/param.h>
#include <sys/systm.h>

View File

@ -276,8 +276,14 @@ compat_isa_handler(module_t mod, int type, void *data)
driver->methods = isa_compat_methods;
driver->size = sizeof(struct isa_device);
driver->priv = id;
if (id->sensitive_hw)
if (id->sensitive_hw) {
#if 0
resource_set_int(id->name, -1, "sensitive", 1);
#else
printf("WARNING: isa driver %s is sensitive, but cannot set it!\n",
driver->name);
#endif
}
devclass_add_driver(isa_devclass, driver);
break;
case MOD_UNLOAD:

View File

@ -169,11 +169,11 @@ static int
atkbdc_attach(device_t dev)
{
atkbdc_softc_t *sc;
int unit;
int unit, dunit;
int error;
int rid;
int i;
const char *name;
const char *name, *dname;
unit = device_get_unit(dev);
sc = *(atkbdc_softc_t **)device_get_softc(dev);
@ -215,19 +215,17 @@ atkbdc_attach(device_t dev)
* Add all devices configured to be attached to atkbdc0.
*/
name = device_get_nameunit(dev);
i = -1;
while ((i = resource_query_string(i, "at", name)) != -1)
atkbdc_add_device(dev, resource_query_name(i),
resource_query_unit(i));
i = 0;
while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0)
atkbdc_add_device(dev, dname, dunit);
/*
* and atkbdc?
*/
name = device_get_name(dev);
i = -1;
while ((i = resource_query_string(i, "at", name)) != -1)
atkbdc_add_device(dev, resource_query_name(i),
resource_query_unit(i));
i = 0;
while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0)
atkbdc_add_device(dev, dname, dunit);
bus_generic_attach(dev);

View File

@ -817,8 +817,8 @@ static int
fdc_attach(device_t dev)
{
struct fdc_data *fdc;
int i, error;
const char *name;
int i, error, dunit;
const char *name, *dname;
fdc = device_get_softc(dev);
error = fdc_alloc_resources(fdc);
@ -856,10 +856,9 @@ fdc_attach(device_t dev)
* devices from the BIOS unless overridden.
*/
name = device_get_nameunit(dev);
i = -1;
while ((i = resource_query_string(i, "at", name)) != -1)
fdc_add_child(dev, resource_query_name(i),
resource_query_unit(i));
i = 0;
while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0)
fdc_add_child(dev, dname, dunit);
return (bus_generic_attach(dev));
}

View File

@ -87,30 +87,28 @@ isahint_identify(driver_t *driver, device_t parent)
{
int i;
static char buf[] = "isaXXX";
const char *dname;
int dunit;
/*
* Add all devices configured to be attached to parent.
*/
sprintf(buf, "isa%d", device_get_unit(parent));
i = -1;
while ((i = resource_query_string(i, "at", buf)) != -1) {
if (strcmp(resource_query_name(i), "atkbd") == 0)
i = 0;
while ((resource_find_match(&i, &dname, &dunit, "at", buf)) == 0) {
if (strcmp(dname, "atkbd") == 0)
continue; /* old GENERIC kludge */
isahint_add_device(parent,
resource_query_name(i),
resource_query_unit(i));
isahint_add_device(parent, dname, dunit);
}
/*
* and isa?
*/
i = -1;
while ((i = resource_query_string(i, "at", "isa")) != -1) {
if (strcmp(resource_query_name(i), "atkbd") == 0)
i = 0;
while ((resource_find_match(&i, &dname, &dunit, "at", "isa")) == 0) {
if (strcmp(dname, "atkbd") == 0)
continue; /* old GENERIC kludge */
isahint_add_device(parent,
resource_query_name(i),
resource_query_unit(i));
isahint_add_device(parent, dname, dunit);
}
}

View File

@ -91,9 +91,7 @@ void print_devclass_list(void);
#define print_devclass_list() /* nop */
#endif
extern char static_hints[];
extern int hintmode;
static int hints_loaded = 0;
extern char static_hints[]; /* by config for now */
TAILQ_HEAD(,device) bus_data_devices;
static int bus_data_generation = 1;
@ -1106,473 +1104,12 @@ device_set_unit(device_t dev, int unit)
return (0);
}
/*======================================*/
/*
* Access functions for device resources.
*/
/* Runtime version */
static struct config_device *devtab;
static int devtab_count = 0;
static int
resource_new_name(const char *name, int unit)
{
struct config_device *new;
new = malloc((devtab_count + 1) * sizeof(*new), M_TEMP, M_NOWAIT);
if (new == NULL)
return (-1);
if (devtab && devtab_count > 0)
bcopy(devtab, new, devtab_count * sizeof(*new));
bzero(&new[devtab_count], sizeof(*new));
new[devtab_count].name = malloc(strlen(name) + 1, M_TEMP, M_NOWAIT);
if (new[devtab_count].name == NULL) {
free(new, M_TEMP);
return (-1);
}
strcpy(new[devtab_count].name, name);
new[devtab_count].unit = unit;
new[devtab_count].resource_count = 0;
new[devtab_count].resources = NULL;
devtab = new;
return (devtab_count++);
}
static int
resource_new_resname(int j, const char *resname, resource_type type)
{
struct config_resource *new;
int i;
i = devtab[j].resource_count;
new = malloc((i + 1) * sizeof(*new), M_TEMP, M_NOWAIT);
if (new == NULL)
return (-1);
if (devtab[j].resources && i > 0)
bcopy(devtab[j].resources, new, i * sizeof(*new));
bzero(&new[i], sizeof(*new));
new[i].name = malloc(strlen(resname) + 1, M_TEMP, M_NOWAIT);
if (new[i].name == NULL) {
free(new, M_TEMP);
return (-1);
}
strcpy(new[i].name, resname);
new[i].type = type;
if (devtab[j].resources)
free(devtab[j].resources, M_TEMP);
devtab[j].resources = new;
devtab[j].resource_count = i + 1;
return (i);
}
static int
resource_match_string(int i, const char *resname, const char *value)
{
int j;
struct config_resource *res;
for (j = 0, res = devtab[i].resources;
j < devtab[i].resource_count; j++, res++)
if (!strcmp(res->name, resname)
&& res->type == RES_STRING
&& !strcmp(res->u.stringval, value))
return (j);
return (-1);
}
static int
resource_find_hard(char *cp, const char *name, int unit,
const char *resname, struct config_resource **result)
{
char match[256];
int matchlen;
char *op;
long val;
snprintf(match, sizeof(match), "hint.%s.%d.%s=", name, unit, resname);
matchlen = strlen(match);
while (cp) {
if (strncmp(match, cp, matchlen) == 0)
break;
while (*cp != '\0')
cp++;
cp++;
if (*cp == '\0') {
cp = NULL;
break;
}
}
if (cp)
cp += matchlen; /* skip over name and '=' */
else
return (ENOENT);
val = strtoul(cp, &op, 0);
if (*cp != '\0' && *op == '\0') {
(*result)->type = RES_INT;
(*result)->u.intval = val;
} else {
(*result)->type = RES_STRING;
(*result)->u.stringval = cp;
}
return (0);
}
static int
resource_find(const char *name, int unit, const char *resname,
struct config_resource **result)
{
int i, j;
struct config_resource *res;
if (!hints_loaded) {
/* First specific, then generic. Dynamic over static. */
i = resource_find_hard(kern_envp, name, unit, resname, result);
if (i == 0)
return (0);
i = resource_find_hard(static_hints, name, unit, resname,
result);
if (i == 0)
return (0);
i = resource_find_hard(kern_envp, name, -1, resname, result);
if (i == 0)
return (0);
i = resource_find_hard(static_hints, name, -1, resname, result);
return (i);
}
/*
* First check specific instances, then generic.
*/
for (i = 0; i < devtab_count; i++) {
if (devtab[i].unit < 0)
continue;
if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
res = devtab[i].resources;
for (j = 0; j < devtab[i].resource_count; j++, res++)
if (!strcmp(res->name, resname)) {
*result = res;
return (0);
}
}
}
for (i = 0; i < devtab_count; i++) {
if (devtab[i].unit >= 0)
continue;
if (!strcmp(devtab[i].name, name)) {
res = devtab[i].resources;
for (j = 0; j < devtab[i].resource_count; j++, res++)
if (!strcmp(res->name, resname)) {
*result = res;
return (0);
}
}
}
return (ENOENT);
}
int
resource_int_value(const char *name, int unit, const char *resname, int *result)
{
struct config_resource tmpres;
struct config_resource *res;
int error;
res = &tmpres;
if ((error = resource_find(name, unit, resname, &res)) != 0)
return (error);
if (res->type != RES_INT)
return (EFTYPE);
*result = res->u.intval;
return (0);
}
int
resource_long_value(const char *name, int unit, const char *resname,
long *result)
{
struct config_resource tmpres;
struct config_resource *res;
int error;
res = &tmpres;
if ((error = resource_find(name, unit, resname, &res)) != 0)
return (error);
if (res->type != RES_LONG)
return (EFTYPE);
*result = res->u.longval;
return (0);
}
int
resource_string_value(const char *name, int unit, const char *resname,
char **result)
{
struct config_resource tmpres;
struct config_resource *res;
int error;
res = &tmpres;
if ((error = resource_find(name, unit, resname, &res)) != 0)
return (error);
if (res->type != RES_STRING)
return (EFTYPE);
*result = res->u.stringval;
return (0);
}
int
resource_query_string(int i, const char *resname, const char *value)
{
if (i < 0)
i = 0;
else
i = i + 1;
for (; i < devtab_count; i++)
if (resource_match_string(i, resname, value) >= 0)
return (i);
return (-1);
}
int
resource_locate(int i, const char *resname)
{
if (i < 0)
i = 0;
else
i = i + 1;
for (; i < devtab_count; i++)
if (!strcmp(devtab[i].name, resname))
return (i);
return (-1);
}
int
resource_count(void)
{
return (devtab_count);
}
char *
resource_query_name(int i)
{
return (devtab[i].name);
}
int
resource_query_unit(int i)
{
return (devtab[i].unit);
}
static int
resource_create(const char *name, int unit, const char *resname,
resource_type type, struct config_resource **result)
{
int i, j;
struct config_resource *res = NULL;
for (i = 0; i < devtab_count; i++) {
if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) {
res = devtab[i].resources;
break;
}
}
if (res == NULL) {
i = resource_new_name(name, unit);
if (i < 0)
return (ENOMEM);
res = devtab[i].resources;
}
for (j = 0; j < devtab[i].resource_count; j++, res++) {
if (!strcmp(res->name, resname)) {
*result = res;
return (0);
}
}
j = resource_new_resname(i, resname, type);
if (j < 0)
return (ENOMEM);
res = &devtab[i].resources[j];
*result = res;
return (0);
}
int
resource_set_int(const char *name, int unit, const char *resname, int value)
{
int error;
struct config_resource *res;
error = resource_create(name, unit, resname, RES_INT, &res);
if (error)
return (error);
if (res->type != RES_INT)
return (EFTYPE);
res->u.intval = value;
return (0);
}
int
resource_set_long(const char *name, int unit, const char *resname, long value)
{
int error;
struct config_resource *res;
error = resource_create(name, unit, resname, RES_LONG, &res);
if (error)
return (error);
if (res->type != RES_LONG)
return (EFTYPE);
res->u.longval = value;
return (0);
}
int
resource_set_string(const char *name, int unit, const char *resname,
const char *value)
{
int error;
struct config_resource *res;
error = resource_create(name, unit, resname, RES_STRING, &res);
if (error)
return (error);
if (res->type != RES_STRING)
return (EFTYPE);
if (res->u.stringval)
free(res->u.stringval, M_TEMP);
res->u.stringval = malloc(strlen(value) + 1, M_TEMP, M_NOWAIT);
if (res->u.stringval == NULL)
return (ENOMEM);
strcpy(res->u.stringval, value);
return (0);
}
/*
* We use the identify routine to get the hints for all the other devices.
* Strings that are all digits or begin with 0x are integers.
*
* hint.aha.0.bus_speedup=1
* hint.aha.1.irq=10
* hint.wl.0.netid=PLUG
* hint.wl.1.netid=XYZZY
*/
static void
hint_load(char *cp)
{
char *ep, *op, *walker;
int len;
int val;
char name[20];
int unit;
char resname[255];
for (ep = cp; *ep != '=' && *ep != '\0'; ep++)
continue;
len = ep - cp;
if (*ep == '=')
ep++;
walker = cp;
walker += 5;
op = walker;
while (*walker && *walker != '.')
walker++;
if (*walker != '.')
return;
if (walker - op > sizeof(name))
return;
strncpy(name, op, walker - op);
name[walker - op] = '\0';
walker++;
op = walker;
while (*walker && *walker != '.')
walker++;
if (*walker != '.')
return;
unit = strtoul(op, &walker, 0);
if (*walker != '.')
return;
walker++;
op = walker;
while (*walker && *walker != '=')
walker++;
if (*walker != '=')
return;
if (walker - op > sizeof(resname))
return;
strncpy(resname, op, walker - op);
resname[walker - op] = '\0';
walker++;
if (walker != ep)
return;
if (bootverbose)
printf("Setting %s %d %s to ", name, unit, resname);
val = strtoul(ep, &op, 0);
if (*ep != '\0' && *op == '\0') {
resource_set_int(name, unit, resname, val);
if (bootverbose)
printf("%d (int)\n", val);
} else {
resource_set_string(name, unit, resname, ep);
if (bootverbose)
printf("%s (string)\n", ep);
}
}
static void
hints_load(void *dummy __unused)
{
char *cp;
if (hintmode == 2) { /* default hints only */
cp = kern_envp;
while (cp) {
if (strncmp(cp, "hint.", 5) == 0) {
/* ok, we found a hint, ignore these defaults */
hintmode = 0;
break;
}
while (*cp != '\0')
cp++;
cp++;
if (*cp == '\0')
break;
}
}
if (hintmode != 0) {
cp = static_hints;
while (cp) {
if (strncmp(cp, "hint.", 5) == 0)
hint_load(cp);
while (*cp != '\0')
cp++;
cp++;
if (*cp == '\0')
break;
}
}
cp = kern_envp;
while (cp) {
if (strncmp(cp, "hint.", 5) == 0)
hint_load(cp);
while (*cp != '\0')
cp++;
cp++;
if (*cp == '\0')
break;
}
hints_loaded++;
}
SYSINIT(cfghints, SI_SUB_KMEM, SI_ORDER_ANY + 60, hints_load, 0)
/*======================================*/
/*
* Some useful method implementations to make life easier for bus drivers.
*/
void
void
resource_list_init(struct resource_list *rl)
{
SLIST_INIT(rl);
@ -2591,3 +2128,275 @@ bus_data_generation_update(void)
{
bus_data_generation++;
}
/*======================================*/
/*
* Access functions for device resources.
*/
/*
* Evil wildcarding resource string lookup.
* This walks the supplied env string table and returns a match.
* The start point can be remembered for incremental searches.
*/
static int
res_find(const char *cp, int *line, int *startln,
const char *name, int *unit, const char *resname, const char *value,
const char **ret_name, int *ret_namelen, int *ret_unit,
const char **ret_resname, int *ret_resnamelen, const char **ret_value)
{
int n = 0, hit;
char r_name[32];
int r_unit;
char r_resname[32];
char r_value[128];
const char *s;
char *p;
while (cp) {
hit = 1;
(*line)++;
if (strncmp(cp, "hint.", 5) != 0)
hit = 0;
else
n = sscanf(cp, "hint.%32[^.].%d.%32[^=]=%128s",
r_name, &r_unit, r_resname, r_value);
if (hit && n != 4) {
printf("CONFIG: invalid hint '%s'\n", cp);
/* XXX: abuse bogus index() declaration */
p = index(cp, 'h');
*p = 'H';
hit = 0;
}
if (hit && startln && *startln >= 0 && *line < *startln)
hit = 0;
if (hit && name && strcmp(name, r_name) != 0)
hit = 0;
if (hit && unit && *unit != r_unit)
hit = 0;
if (hit && resname && strcmp(resname, r_resname) != 0)
hit = 0;
if (hit && value && strcmp(value, r_value) != 0)
hit = 0;
if (hit)
break;
while (*cp != '\0')
cp++;
cp++;
if (*cp == '\0') {
cp = NULL;
break;
}
}
if (cp == NULL)
return ENOENT;
s = cp;
/* This is a bit of a hack, but at least is reentrant */
/* Note that it returns some !unterminated! strings. */
s = index(s, '.') + 1; /* start of device */
if (ret_name)
*ret_name = s;
s = index(s, '.') + 1; /* start of unit */
if (ret_namelen)
*ret_namelen = s - *ret_name - 1; /* device length */
if (ret_unit)
*ret_unit = r_unit;
s = index(s, '.') + 1; /* start of resname */
if (ret_resname)
*ret_resname = s;
s = index(s, '=') + 1; /* start of value */
if (ret_resnamelen)
*ret_resnamelen = s - *ret_resname - 1; /* value len */
if (ret_value)
*ret_value = s;
if (startln) /* line number for anchor */
*startln = *line + 1;
return 0;
}
/*
* Search all the data sources for matches to our query. We look for
* dynamic hints first as overrides for static or fallback hints.
*/
static int
resource_find(int *line, int *startln,
const char *name, int *unit, const char *resname, const char *value,
const char **ret_name, int *ret_namelen, int *ret_unit,
const char **ret_resname, int *ret_resnamelen, const char **ret_value)
{
int i;
int un;
*line = 0;
/* Search for exact unit matches first */
i = res_find(kern_envp, line, startln, name, unit, resname, value,
ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
ret_value);
if (i == 0)
return 0;
i = res_find(static_hints, line, startln, name, unit, resname, value,
ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
ret_value);
if (i == 0)
return 0;
if (unit == NULL)
return ENOENT;
/* If we are still here, search for wildcard matches */
un = -1;
i = res_find(kern_envp, line, startln, name, &un, resname, value,
ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
ret_value);
if (i == 0)
return 0;
un = -1;
i = res_find(static_hints, line, startln, name, &un, resname, value,
ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
ret_value);
if (i == 0)
return 0;
return ENOENT;
}
int
resource_int_value(const char *name, int unit, const char *resname, int *result)
{
int error;
const char *str;
char *op;
unsigned long val;
int line;
line = 0;
error = resource_find(&line, NULL, name, &unit, resname, NULL,
NULL, NULL, NULL, NULL, NULL, &str);
if (error)
return error;
if (*str == '\0')
return EFTYPE;
val = strtoul(str, &op, 0);
if (*op != '\0')
return EFTYPE;
*result = val;
return 0;
}
int
resource_long_value(const char *name, int unit, const char *resname,
long *result)
{
int error;
const char *str;
char *op;
unsigned long val;
int line;
line = 0;
error = resource_find(&line, NULL, name, &unit, resname, NULL,
NULL, NULL, NULL, NULL, NULL, &str);
if (error)
return error;
if (*str == '\0')
return EFTYPE;
val = strtoul(str, &op, 0);
if (*op != '\0')
return EFTYPE;
*result = val;
return 0;
}
int
resource_string_value(const char *name, int unit, const char *resname,
const char **result)
{
int error;
const char *str;
int line;
line = 0;
error = resource_find(&line, NULL, name, &unit, resname, NULL,
NULL, NULL, NULL, NULL, NULL, &str);
if (error)
return error;
*result = str;
return 0;
}
/*
* This is a bit nasty, but allows us to not modify the env strings.
*/
static const char *
resource_string_copy(const char *s, int len)
{
static char stringbuf[256];
static int offset = 0;
const char *ret;
if (len == 0)
len = strlen(s);
if (len > 255)
return NULL;
if ((offset + len + 1) > 255)
offset = 0;
bcopy(s, &stringbuf[offset], len);
stringbuf[offset + len] = '\0';
ret = &stringbuf[offset];
offset += len + 1;
return ret;
}
/*
* err = resource_find_at(&anchor, &name, &unit, resname, value)
* Iteratively fetch a list of devices wired "at" something
* res and value are restrictions. eg: "at", "scbus0".
* For practical purposes, res = required, value = optional.
* *name and *unit are set.
* set *anchor to zero before starting.
*/
int
resource_find_match(int *anchor, const char **name, int *unit,
const char *resname, const char *value)
{
const char *found_name;
int found_namelen;
int found_unit;
int ret;
int newln;
newln = *anchor;
ret = resource_find(anchor, &newln, NULL, NULL, resname, value,
&found_name, &found_namelen, &found_unit, NULL, NULL, NULL);
if (ret == 0) {
*name = resource_string_copy(found_name, found_namelen);
*unit = found_unit;
}
*anchor = newln;
return ret;
}
/*
* err = resource_find_dev(&anchor, name, &unit, res, value);
* Iterate through a list of devices, returning their unit numbers.
* res and value are optional restrictions. eg: "at", "scbus0".
* *unit is set to the value.
* set *anchor to zero before starting.
*/
int
resource_find_dev(int *anchor, const char *name, int *unit,
const char *resname, const char *value)
{
int found_unit;
int newln;
int ret;
newln = *anchor;
ret = resource_find(anchor, &newln, name, NULL, resname, value,
NULL, NULL, &found_unit, NULL, NULL, NULL);
if (ret == 0) {
*unit = found_unit;
}
*anchor = newln;
return ret;
}

304
sys/kern/subr_hints.c Normal file
View File

@ -0,0 +1,304 @@
/*-
* Copyright (c) 2000,2001 Peter Wemm <peter@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
/*
* Access functions for device resources.
*/
extern char static_hints[]; /* by config for now */
/*
* Evil wildcarding resource string lookup.
* This walks the supplied env string table and returns a match.
* The start point can be remembered for incremental searches.
*/
static int
res_find(const char *cp, int *line, int *startln,
const char *name, int *unit, const char *resname, const char *value,
const char **ret_name, int *ret_namelen, int *ret_unit,
const char **ret_resname, int *ret_resnamelen, const char **ret_value)
{
int n = 0, hit;
char r_name[32];
int r_unit;
char r_resname[32];
char r_value[128];
const char *s;
char *p;
while (cp) {
hit = 1;
(*line)++;
if (strncmp(cp, "hint.", 5) != 0)
hit = 0;
else
n = sscanf(cp, "hint.%32[^.].%d.%32[^=]=%128s",
r_name, &r_unit, r_resname, r_value);
if (hit && n != 4) {
printf("CONFIG: invalid hint '%s'\n", cp);
/* XXX: abuse bogus index() declaration */
p = index(cp, 'h');
*p = 'H';
hit = 0;
}
if (hit && startln && *startln >= 0 && *line < *startln)
hit = 0;
if (hit && name && strcmp(name, r_name) != 0)
hit = 0;
if (hit && unit && *unit != r_unit)
hit = 0;
if (hit && resname && strcmp(resname, r_resname) != 0)
hit = 0;
if (hit && value && strcmp(value, r_value) != 0)
hit = 0;
if (hit)
break;
while (*cp != '\0')
cp++;
cp++;
if (*cp == '\0') {
cp = NULL;
break;
}
}
if (cp == NULL)
return ENOENT;
s = cp;
/* This is a bit of a hack, but at least is reentrant */
/* Note that it returns some !unterminated! strings. */
s = index(s, '.') + 1; /* start of device */
if (ret_name)
*ret_name = s;
s = index(s, '.') + 1; /* start of unit */
if (ret_namelen)
*ret_namelen = s - *ret_name - 1; /* device length */
if (ret_unit)
*ret_unit = r_unit;
s = index(s, '.') + 1; /* start of resname */
if (ret_resname)
*ret_resname = s;
s = index(s, '=') + 1; /* start of value */
if (ret_resnamelen)
*ret_resnamelen = s - *ret_resname - 1; /* value len */
if (ret_value)
*ret_value = s;
if (startln) /* line number for anchor */
*startln = *line + 1;
return 0;
}
/*
* Search all the data sources for matches to our query. We look for
* dynamic hints first as overrides for static or fallback hints.
*/
static int
resource_find(int *line, int *startln,
const char *name, int *unit, const char *resname, const char *value,
const char **ret_name, int *ret_namelen, int *ret_unit,
const char **ret_resname, int *ret_resnamelen, const char **ret_value)
{
int i;
int un;
*line = 0;
/* Search for exact unit matches first */
i = res_find(kern_envp, line, startln, name, unit, resname, value,
ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
ret_value);
if (i == 0)
return 0;
i = res_find(static_hints, line, startln, name, unit, resname, value,
ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
ret_value);
if (i == 0)
return 0;
if (unit == NULL)
return ENOENT;
/* If we are still here, search for wildcard matches */
un = -1;
i = res_find(kern_envp, line, startln, name, &un, resname, value,
ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
ret_value);
if (i == 0)
return 0;
un = -1;
i = res_find(static_hints, line, startln, name, &un, resname, value,
ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
ret_value);
if (i == 0)
return 0;
return ENOENT;
}
int
resource_int_value(const char *name, int unit, const char *resname, int *result)
{
int error;
const char *str;
char *op;
unsigned long val;
int line;
line = 0;
error = resource_find(&line, NULL, name, &unit, resname, NULL,
NULL, NULL, NULL, NULL, NULL, &str);
if (error)
return error;
if (*str == '\0')
return EFTYPE;
val = strtoul(str, &op, 0);
if (*op != '\0')
return EFTYPE;
*result = val;
return 0;
}
int
resource_long_value(const char *name, int unit, const char *resname,
long *result)
{
int error;
const char *str;
char *op;
unsigned long val;
int line;
line = 0;
error = resource_find(&line, NULL, name, &unit, resname, NULL,
NULL, NULL, NULL, NULL, NULL, &str);
if (error)
return error;
if (*str == '\0')
return EFTYPE;
val = strtoul(str, &op, 0);
if (*op != '\0')
return EFTYPE;
*result = val;
return 0;
}
int
resource_string_value(const char *name, int unit, const char *resname,
const char **result)
{
int error;
const char *str;
int line;
line = 0;
error = resource_find(&line, NULL, name, &unit, resname, NULL,
NULL, NULL, NULL, NULL, NULL, &str);
if (error)
return error;
*result = str;
return 0;
}
/*
* This is a bit nasty, but allows us to not modify the env strings.
*/
static const char *
resource_string_copy(const char *s, int len)
{
static char stringbuf[256];
static int offset = 0;
const char *ret;
if (len == 0)
len = strlen(s);
if (len > 255)
return NULL;
if ((offset + len + 1) > 255)
offset = 0;
bcopy(s, &stringbuf[offset], len);
stringbuf[offset + len] = '\0';
ret = &stringbuf[offset];
offset += len + 1;
return ret;
}
/*
* err = resource_find_at(&anchor, &name, &unit, resname, value)
* Iteratively fetch a list of devices wired "at" something
* res and value are restrictions. eg: "at", "scbus0".
* For practical purposes, res = required, value = optional.
* *name and *unit are set.
* set *anchor to zero before starting.
*/
int
resource_find_match(int *anchor, const char **name, int *unit,
const char *resname, const char *value)
{
const char *found_name;
int found_namelen;
int found_unit;
int ret;
int newln;
newln = *anchor;
ret = resource_find(anchor, &newln, NULL, NULL, resname, value,
&found_name, &found_namelen, &found_unit, NULL, NULL, NULL);
if (ret == 0) {
*name = resource_string_copy(found_name, found_namelen);
*unit = found_unit;
}
*anchor = newln;
return ret;
}
/*
* err = resource_find_dev(&anchor, name, &unit, res, value);
* Iterate through a list of devices, returning their unit numbers.
* res and value are optional restrictions. eg: "at", "scbus0".
* *unit is set to the value.
* set *anchor to zero before starting.
*/
int
resource_find_dev(int *anchor, const char *name, int *unit,
const char *resname, const char *value)
{
int found_unit;
int newln;
int ret;
newln = *anchor;
ret = resource_find(anchor, &newln, name, NULL, resname, value,
NULL, NULL, &found_unit, NULL, NULL, NULL);
if (ret == 0) {
*unit = found_unit;
}
*anchor = newln;
return ret;
}

View File

@ -1041,8 +1041,8 @@ static int
fdc_attach(device_t dev)
{
struct fdc_data *fdc;
int i, error;
const char *name;
int i, error, dunit;
const char *name, *dname;
fdc = device_get_softc(dev);
error = fdc_alloc_resources(fdc);
@ -1082,10 +1082,9 @@ fdc_attach(device_t dev)
* devices from the BIOS unless overridden.
*/
name = device_get_nameunit(dev);
i = -1;
while ((i = resource_query_string(i, "at", name)) != -1)
fdc_add_child(dev, resource_query_name(i),
resource_query_unit(i));
i = 0;
while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0)
fdc_add_child(dev, dname, dunit);
return (bus_generic_attach(dev));
}

View File

@ -49,7 +49,7 @@
#include "opt_msgbuf.h"
#include "opt_npx.h"
#include "opt_perfmon.h"
#include "opt_userconfig.h"
/* #include "opt_userconfig.h" */
#include <sys/param.h>
#include <sys/systm.h>

View File

@ -1041,8 +1041,8 @@ static int
fdc_attach(device_t dev)
{
struct fdc_data *fdc;
int i, error;
const char *name;
int i, error, dunit;
const char *name, *dname;
fdc = device_get_softc(dev);
error = fdc_alloc_resources(fdc);
@ -1082,10 +1082,9 @@ fdc_attach(device_t dev)
* devices from the BIOS unless overridden.
*/
name = device_get_nameunit(dev);
i = -1;
while ((i = resource_query_string(i, "at", name)) != -1)
fdc_add_child(dev, resource_query_name(i),
resource_query_unit(i));
i = 0;
while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0)
fdc_add_child(dev, dname, dunit);
return (bus_generic_attach(dev));
}

View File

@ -49,7 +49,7 @@
#include "opt_msgbuf.h"
#include "opt_npx.h"
#include "opt_perfmon.h"
#include "opt_userconfig.h"
/* #include "opt_userconfig.h" */
#include <sys/param.h>
#include <sys/systm.h>

View File

@ -471,6 +471,7 @@ wdattach(struct isa_device *dvp)
struct softc *du;
struct wdparams *wp;
static char buf[] = "wdcXXX";
const char *dname;
dvp->id_intr = wdintr;
@ -486,13 +487,12 @@ wdattach(struct isa_device *dvp)
bioq_init(&wdtab[dvp->id_unit].controller_queue);
sprintf(buf, "wdc%d", dvp->id_unit);
i = -1;
while ((i = resource_query_string(i, "at", buf)) != -1) {
if (strcmp(resource_query_name(i), "wd"))
i = 0;
while ((resource_find_match(&i, &dname, &lunit, "at", buf)) == 0) {
if (strcmp(dname, "wd"))
/* Avoid a bit of foot shooting. */
continue;
lunit = resource_query_unit(i);
if (lunit >= NWD)
continue;
#ifdef PC98

View File

@ -324,19 +324,17 @@ int resource_int_value(const char *name, int unit, const char *resname,
int resource_long_value(const char *name, int unit, const char *resname,
long *result);
int resource_string_value(const char *name, int unit, const char *resname,
char **result);
int resource_query_string(int i, const char *resname, const char *value);
char *resource_query_name(int i);
int resource_query_unit(int i);
int resource_locate(int i, const char *resname);
const char **result);
int resource_find_match(int *anchor, const char **name, int *unit,
const char *resname, const char *value);
int resource_find_dev(int *anchor, const char *name, int *unit,
const char *resname, const char *value);
int resource_set_int(const char *name, int unit, const char *resname,
int value);
int resource_set_long(const char *name, int unit, const char *resname,
long value);
int resource_set_string(const char *name, int unit, const char *resname,
const char *value);
int resource_count(void);
/*
* Functions for maintaining and checking consistency of
* bus information exported to userspace.

View File

@ -55,30 +55,6 @@ struct devclass {
int maxunit; /* size of devices array */
};
/*
* Resources from config(8).
*/
typedef enum {
RES_INT, RES_STRING, RES_LONG
} resource_type;
struct config_resource {
char *name;
resource_type type;
union {
long longval;
int intval;
char* stringval;
} u;
};
struct config_device {
char *name; /* e.g. "lpt", "wdc" etc */
int unit;
int resource_count;
struct config_resource *resources;
};
/*
* Implementation of device.
*/