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:
parent
46f48be960
commit
2398f0cd1d
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
|
11
sys/isa/fd.c
11
sys/isa/fd.c
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
304
sys/kern/subr_hints.c
Normal 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;
|
||||
}
|
@ -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));
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user