#ifndef _SYS_DEVICE_H_
#define _SYS_DEVICE_H_
#include <sys/device_if.h>
#include <sys/evcnt.h>
#include <sys/queue.h>
#if defined(_KERNEL) || defined(_KMEMUSER)
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <sys/pmf.h>
#endif
#include <prop/proplib.h>
typedef enum devclass {
DV_DULL,
DV_CPU,
DV_DISK,
DV_IFNET,
DV_TAPE,
DV_TTY,
DV_AUDIODEV,
DV_DISPLAYDEV,
DV_BUS,
DV_VIRTUAL,
} devclass_t;
typedef enum devact {
DVACT_DEACTIVATE
} devact_t;
typedef enum {
DVA_SYSTEM,
DVA_HARDWARE
} devactive_t;
typedef struct cfdata *cfdata_t;
typedef struct cfdriver *cfdriver_t;
typedef struct cfattach *cfattach_t;
#if defined(_KERNEL) || defined(_KMEMUSER) || defined(_STANDALONE)
struct devhandle {
const struct devhandle_impl * impl;
union {
void * pointer;
const void * const_pointer;
uintptr_t uintptr;
intptr_t integer;
};
};
typedef struct devhandle devhandle_t;
#endif
#if defined(_KERNEL) || defined(_KMEMUSER)
struct device_compatible_entry {
union {
const char *compat;
uintptr_t id;
};
union {
const void *data;
uintptr_t value;
};
};
#define DEVICE_COMPAT_EOL { .compat = NULL }
struct device_suspensor {
const device_suspensor_t *ds_delegator;
char ds_name[32];
};
struct device_garbage {
device_t *dg_devs;
int dg_ndevs;
};
typedef enum {
DEVHANDLE_TYPE_INVALID = 0,
DEVHANDLE_TYPE_ACPI = 0x41435049,
DEVHANDLE_TYPE_OF = 0x4f504657,
DEVHANDLE_TYPE_OPENBOOT = 0x4f504254,
DEVHANDLE_TYPE_PRIVATE = 0x50525654,
DEVHANDLE_TYPE_MAX = 0xffffffff
} devhandle_type_t;
typedef int (*device_call_t)(device_t, devhandle_t, void *);
struct device_call_descriptor {
const char *name;
device_call_t call;
};
#define _DEVICE_CALL_REGISTER(_g_, _c_) \
__link_set_add_rodata(_g_, __CONCAT(_c_,_descriptor));
#define DEVICE_CALL_REGISTER(_g_, _n_, _c_) \
static const struct device_call_descriptor __CONCAT(_c_,_descriptor) = {\
.name = (_n_), .call = (_c_) \
}; \
_DEVICE_CALL_REGISTER(_g_, _c_)
#define SYSDFLT_DEVICE_CALL_REGISTER(_n_, _c_) \
DEVICE_CALL_REGISTER(sysdflt_device_calls, _n_, _c_)
struct devhandle_impl {
devhandle_type_t type;
const struct devhandle_impl * super;
device_call_t (*lookup_device_call)(devhandle_t,
const char *, devhandle_t *);
};
#define DEVICE_XNAME_SIZE 16
struct device;
#define DVF_PRIV_ALLOC 0x0002
#define DVF_DETACH_SHUTDOWN 0x0080
#define DVF_NO_PARTITIONS 0x0100
#ifdef _KERNEL
TAILQ_HEAD(devicelist, device);
#endif
enum deviter_flags {
DEVITER_F_RW = 0x1
, DEVITER_F_SHUTDOWN = 0x2
, DEVITER_F_LEAVES_FIRST = 0x4
, DEVITER_F_ROOT_FIRST = 0x8
};
typedef enum deviter_flags deviter_flags_t;
struct deviter {
device_t di_prev;
deviter_flags_t di_flags;
int di_curdepth;
int di_maxdepth;
devgen_t di_gen;
};
typedef struct deviter deviter_t;
struct shutdown_state {
bool initialized;
deviter_t di;
};
#endif
struct cflocdesc {
const char *cld_name;
const char *cld_defaultstr;
int cld_default;
};
struct cfiattrdata {
const char *ci_name;
int ci_loclen;
const struct cflocdesc ci_locdesc[
#if defined(__GNUC__) && __GNUC__ <= 2
0
#endif
];
};
struct cfparent {
const char *cfp_iattr;
const char *cfp_parent;
int cfp_unit;
};
struct cfdata {
const char *cf_name;
const char *cf_atname;
unsigned int cf_unit:24;
unsigned char cf_fstate;
int *cf_loc;
int cf_flags;
const struct cfparent *cf_pspec;
};
#define FSTATE_NOTFOUND 0
#define FSTATE_FOUND 1
#define FSTATE_STAR 2
#define FSTATE_DSTAR 3
#define FSTATE_DNOTFOUND 4
struct cftable {
cfdata_t ct_cfdata;
TAILQ_ENTRY(cftable) ct_list;
};
#ifdef _KERNEL
TAILQ_HEAD(cftablelist, cftable);
#endif
typedef int (*cfsubmatch_t)(device_t, cfdata_t, const int *, void *);
typedef int (*cfsearch_t)(device_t, cfdata_t, const int *, void *);
struct cfattach {
const char *ca_name;
LIST_ENTRY(cfattach) ca_list;
size_t ca_devsize;
int ca_flags;
int (*ca_match)(device_t, cfdata_t, void *);
void (*ca_attach)(device_t, device_t, void *);
int (*ca_detach)(device_t, int);
int (*ca_activate)(device_t, devact_t);
int (*ca_rescan)(device_t, const char *,
const int *);
void (*ca_childdetached)(device_t, device_t);
};
LIST_HEAD(cfattachlist, cfattach);
#define CFATTACH_DECL3_NEW(name, ddsize, matfn, attfn, detfn, actfn, \
rescanfn, chdetfn, __flags) \
struct cfattach __CONCAT(name,_ca) = { \
.ca_name = ___STRING(name), \
.ca_devsize = ddsize, \
.ca_flags = (__flags) | DVF_PRIV_ALLOC, \
.ca_match = matfn, \
.ca_attach = attfn, \
.ca_detach = detfn, \
.ca_activate = actfn, \
.ca_rescan = rescanfn, \
.ca_childdetached = chdetfn, \
}
#define CFATTACH_DECL2_NEW(name, ddsize, matfn, attfn, detfn, actfn, \
rescanfn, chdetfn) \
CFATTACH_DECL3_NEW(name, ddsize, matfn, attfn, detfn, actfn, \
rescanfn, chdetfn, 0)
#define CFATTACH_DECL_NEW(name, ddsize, matfn, attfn, detfn, actfn) \
CFATTACH_DECL2_NEW(name, ddsize, matfn, attfn, detfn, actfn, NULL, NULL)
#define DETACH_FORCE 0x01
#define DETACH_QUIET 0x02
#define DETACH_SHUTDOWN 0x04
#define DETACH_POWEROFF 0x08
struct cfdriver {
LIST_ENTRY(cfdriver) cd_list;
struct cfattachlist cd_attach;
device_t *cd_devs;
const char *cd_name;
enum devclass cd_class;
int cd_ndevs;
const struct cfiattrdata * const *cd_attrs;
};
LIST_HEAD(cfdriverlist, cfdriver);
#define CFDRIVER_DECL(name, class, attrs) \
struct cfdriver __CONCAT(name,_cd) = { \
.cd_name = ___STRING(name), \
.cd_class = class, \
.cd_attrs = attrs, \
}
struct cfattachiattr {
LIST_ENTRY(cfattachiattr) cfia_list;
struct cfattach *cfia_attach;
const struct cfiattrdata *cfia_iattr;
};
struct cfattachinit {
const char *cfai_name;
struct cfattach * const *cfai_list;
struct cfattachiattr * const *cfai_iattrs;
};
typedef int (*cfprint_t)(void *, const char *);
#define QUIET 0
#define UNCONF 1
#define UNSUPP 2
struct pdevinit {
void (*pdev_attach)(int);
int pdev_count;
};
#define DVUNIT_ANY -1
#if defined(_KERNEL) || defined(_KMEMUSER) || defined(_STANDALONE)
struct cfargs {
uintptr_t cfargs_version;
cfsubmatch_t submatch;
cfsearch_t search;
const char * iattr;
const int * locators;
devhandle_t devhandle;
};
#define CFARGS_VERSION 1
#define CFARGS_NONE NULL
#define CFARGS(...) \
&((const struct cfargs){ \
.cfargs_version = CFARGS_VERSION, \
__VA_ARGS__ \
})
#endif
#ifdef _KERNEL
extern struct cfdriverlist allcfdrivers;
extern struct cftablelist allcftables;
extern device_t booted_device;
extern const char *booted_method;
extern int booted_partition;
extern daddr_t booted_startblk;
extern uint64_t booted_nblks;
extern char *bootspec;
extern bool root_is_mounted;
struct vnode *opendisk(device_t);
int getdisksize(struct vnode *, uint64_t *, unsigned int *);
struct dkwedge_info;
int getdiskinfo(struct vnode *, struct dkwedge_info *);
void config_init(void);
int config_init_component(struct cfdriver *const*,
const struct cfattachinit *, struct cfdata *);
int config_fini_component(struct cfdriver *const*,
const struct cfattachinit *, struct cfdata *);
void config_init_mi(void);
void drvctl_init(void);
void drvctl_fini(void);
extern int (*devmon_insert_vec)(const char *, prop_dictionary_t);
int config_cfdriver_attach(struct cfdriver *);
int config_cfdriver_detach(struct cfdriver *);
int config_cfattach_attach(const char *, struct cfattach *);
int config_cfattach_detach(const char *, struct cfattach *);
int config_cfdata_attach(cfdata_t, int);
int config_cfdata_detach(cfdata_t);
struct cfdriver *config_cfdriver_lookup(const char *);
struct cfattach *config_cfattach_lookup(const char *, const char *);
const struct cfiattrdata *cfiattr_lookup(const char *, const struct cfdriver *,
const struct cfattach *);
const char *cfdata_ifattr(const struct cfdata *);
int config_stdsubmatch(device_t, cfdata_t, const int *, void *);
cfdata_t config_search(device_t, void *, const struct cfargs *);
cfdata_t config_rootsearch(cfsubmatch_t, const char *, void *);
device_t config_found(device_t, void *, cfprint_t, const struct cfargs *);
device_t config_rootfound(const char *, void *);
device_t config_attach(device_t, cfdata_t, void *, cfprint_t,
const struct cfargs *);
device_t config_found_acquire(device_t, void *, cfprint_t,
const struct cfargs *);
device_t config_attach_acquire(device_t, cfdata_t, void *, cfprint_t,
const struct cfargs *);
int config_match(device_t, cfdata_t, void *);
int config_probe(device_t, cfdata_t, void *);
bool ifattr_match(const char *, const char *);
device_t config_attach_pseudo(cfdata_t);
device_t config_attach_pseudo_acquire(cfdata_t, void *);
int config_detach(device_t, int);
int config_detach_release(device_t, int);
int config_detach_children(device_t, int flags);
void config_detach_commit(device_t);
bool config_detach_all(int);
int config_deactivate(device_t);
void config_defer(device_t, void (*)(device_t));
void config_deferred(device_t);
void config_interrupts(device_t, void (*)(device_t));
void config_mountroot(device_t, void (*)(device_t));
void config_pending_incr(device_t);
void config_pending_decr(device_t);
void config_create_interruptthreads(void);
void config_create_mountrootthreads(void);
int config_finalize_register(device_t, int (*)(device_t));
void config_finalize(void);
void config_finalize_mountroot(void);
void config_twiddle_init(void);
void config_twiddle_fn(void *);
void null_childdetached(device_t, device_t);
device_t device_lookup(cfdriver_t, int);
void *device_lookup_private(cfdriver_t, int);
device_t device_lookup_acquire(cfdriver_t, int);
void device_acquire(device_t);
void device_release(device_t);
void device_register(device_t, void *);
void device_register_post_config(device_t, void *);
devclass_t device_class(device_t);
cfdata_t device_cfdata(device_t);
cfdriver_t device_cfdriver(device_t);
cfattach_t device_cfattach(device_t);
int device_unit(device_t);
const char *device_xname(device_t);
device_t device_parent(device_t);
bool device_is_active(device_t);
bool device_activation(device_t, devact_level_t);
bool device_is_enabled(device_t);
bool device_has_partitions(device_t);
bool device_has_power(device_t);
int device_locator(device_t, u_int);
void *device_private(device_t);
void device_set_private(device_t, void *);
prop_dictionary_t device_properties(device_t);
void device_set_handle(device_t, devhandle_t);
devhandle_t device_handle(device_t);
bool devhandle_is_valid(devhandle_t);
devhandle_t devhandle_invalid(void);
devhandle_type_t devhandle_type(devhandle_t);
int devhandle_compare(devhandle_t, devhandle_t);
devhandle_t devhandle_subclass(devhandle_t, struct devhandle_impl *,
device_call_t (*)(devhandle_t, const char *,
devhandle_t *));
device_call_t devhandle_lookup_device_call(devhandle_t, const char *,
devhandle_t *);
void devhandle_impl_subclass(struct devhandle_impl *,
const struct devhandle_impl *,
device_call_t (*)(devhandle_t, const char *,
devhandle_t *));
device_t deviter_first(deviter_t *, deviter_flags_t);
void deviter_init(deviter_t *, deviter_flags_t);
device_t deviter_next(deviter_t *);
void deviter_release(deviter_t *);
bool device_active(device_t, devactive_t);
bool device_active_register(device_t,
void (*)(device_t, devactive_t));
void device_active_deregister(device_t,
void (*)(device_t, devactive_t));
bool device_is_a(device_t, const char *);
bool device_attached_to_iattr(device_t, const char *);
device_t device_find_by_xname(const char *);
device_t device_find_by_driver_unit(const char *, int);
int device_enumerate_children(device_t,
bool (*)(device_t, devhandle_t, void *), void *);
int device_compatible_match(const char **, int,
const struct device_compatible_entry *);
int device_compatible_pmatch(const char **, int,
const struct device_compatible_entry *);
const struct device_compatible_entry *
device_compatible_lookup(const char **, int,
const struct device_compatible_entry *);
const struct device_compatible_entry *
device_compatible_plookup(const char **, int,
const struct device_compatible_entry *);
int device_compatible_match_strlist(const char *, size_t,
const struct device_compatible_entry *);
int device_compatible_pmatch_strlist(const char *, size_t,
const struct device_compatible_entry *);
const struct device_compatible_entry *
device_compatible_lookup_strlist(const char *, size_t,
const struct device_compatible_entry *);
const struct device_compatible_entry *
device_compatible_plookup_strlist(const char *, size_t,
const struct device_compatible_entry *);
int device_compatible_match_id(uintptr_t const, uintptr_t const,
const struct device_compatible_entry *);
const struct device_compatible_entry *
device_compatible_lookup_id(uintptr_t const, uintptr_t const,
const struct device_compatible_entry *);
void device_pmf_driver_child_register(device_t);
void device_pmf_driver_set_child_register(device_t,
void (*)(device_t));
void *device_pmf_bus_private(device_t);
bool device_pmf_bus_suspend(device_t, const pmf_qual_t *);
bool device_pmf_bus_resume(device_t, const pmf_qual_t *);
bool device_pmf_bus_shutdown(device_t, int);
void device_pmf_bus_register(device_t, void *,
bool (*)(device_t, const pmf_qual_t *),
bool (*)(device_t, const pmf_qual_t *),
bool (*)(device_t, int),
void (*)(device_t));
void device_pmf_bus_deregister(device_t);
device_t shutdown_first(struct shutdown_state *);
device_t shutdown_next(struct shutdown_state *);
struct device_call_generic {
const char *name;
void *args;
};
int device_call_generic(device_t, devhandle_t,
const struct device_call_generic *);
#define device_call(dev, call) \
device_call_generic((dev), device_handle(dev), &(call)->generic)
#define devhandle_call(handle, call) \
device_call_generic(NULL, (handle), &(call)->generic)
bool device_hasprop(device_t, const char *);
ssize_t device_getproplen(device_t, const char *);
int device_getpropencoding(device_t, const char *);
prop_type_t device_getproptype(device_t, const char *);
ssize_t device_getprop_data(device_t, const char *, void *, size_t);
ssize_t device_getprop_string(device_t, const char *, char *, size_t);
bool device_getprop_bool(device_t, const char *);
void * device_getprop_data_alloc(device_t, const char *, size_t *);
char * device_getprop_string_alloc(device_t, const char *, size_t *);
bool device_getprop_int(device_t, const char *, int *);
bool device_getprop_uint(device_t, const char *, unsigned int *);
bool device_getprop_int32(device_t, const char *, int32_t *);
bool device_getprop_uint32(device_t, const char *, uint32_t *);
bool device_getprop_int64(device_t, const char *, int64_t *);
bool device_getprop_uint64(device_t, const char *, uint64_t *);
int device_getprop_int_default(device_t, const char *, int);
unsigned int device_getprop_uint_default(device_t, const char *,
unsigned int);
int32_t device_getprop_int32_default(device_t, const char *, int32_t);
uint32_t device_getprop_uint32_default(device_t, const char *, uint32_t);
int64_t device_getprop_int64_default(device_t, const char *, int64_t);
uint64_t device_getprop_uint64_default(device_t, const char *, uint64_t);
bool device_setprop_data(device_t, const char *, const void *,
size_t);
bool device_setprop_string(device_t, const char *, const char *);
bool device_setprop_bool(device_t, const char *, bool);
bool device_setprop_int(device_t, const char *, int);
bool device_setprop_uint(device_t, const char *, unsigned int);
bool device_setprop_int32(device_t, const char *, int32_t);
bool device_setprop_uint32(device_t, const char *, uint32_t);
bool device_setprop_int64(device_t, const char *, int64_t);
bool device_setprop_uint64(device_t, const char *, uint64_t);
void device_delprop(device_t, const char *);
#endif
#endif