X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/bef1210245bb3180a57f26405369654eaa477f63..f89517343bf062d299d54408eea2f9387bfefb6d:/lunaix-os/includes/lunaix/device.h diff --git a/lunaix-os/includes/lunaix/device.h b/lunaix-os/includes/lunaix/device.h index 287cdad..7a469a1 100644 --- a/lunaix-os/includes/lunaix/device.h +++ b/lunaix-os/includes/lunaix/device.h @@ -1,7 +1,7 @@ #ifndef __LUNAIX_DEVICE_H #define __LUNAIX_DEVICE_H -#define DEVICE_NAME_SIZE 32 +#define DEVICE_NAME_SIZE 16 #include #include @@ -11,6 +11,9 @@ #include #include #include +#include + +#include #include @@ -40,13 +43,6 @@ */ #define load_sysconf ld_sysconf -/** - * @brief Mark the device definition should be loaded as time device, for - * example a real time clock device. Such device will be loaded and managed by - * clock subsystem - */ -#define load_timedev ld_timedev - /** * @brief Mark the device definition should be loaded automatically during the * bootstrapping stage. Most of the driver do load there. @@ -72,89 +68,110 @@ * @brief Declare a device class * */ -#define DEVCLASS(devif, devfn, dev) \ +#define DEVCLASS(vendor, devfn, dev) \ (struct devclass) \ { \ - .fn_grp = DEV_FNGRP(devif, devfn), .device = (dev), .variant = 0 \ + .fn_grp = DEV_FNGRP(dev_vn(vendor), dev_fn(devfn)), \ + .device = dev_id(dev), .variant = 0 \ } -#define DEVCLASSV(devif, devfn, dev, devvar) \ - (struct devclass) \ - { \ - .fn_grp = DEV_FNGRP(devif, devfn), .device = (dev), \ - .variant = (devvar) \ - } - -#define DEV_STRUCT_MAGIC_MASK 0x56454440U -#define DEV_STRUCT 0xc -#define DEV_CAT 0xd -#define DEV_ALIAS 0xf - -#define DEV_STRUCT_MAGIC (DEV_STRUCT_MAGIC_MASK | DEV_STRUCT) -#define DEV_CAT_MAGIC (DEV_STRUCT_MAGIC_MASK | DEV_CAT) -#define DEV_ALIAS_MAGIC (DEV_STRUCT_MAGIC_MASK | DEV_ALIAS) - #define DEV_MSKIF 0x00000003 - #define DEV_IFVOL 0x0 // volumetric (block) device #define DEV_IFSEQ 0x1 // sequential (character) device #define DEV_IFSYS 0x3 // a system device -struct capability_meta +#define dev_object_root \ + ({ extern morph_t* device_mobj_root; device_mobj_root; }) + +/** + * A potens is a capability of the device + * ("potens", means "capable" in latin) + * + * A device can have multiple capabilities + * (or "potentes", plural form of potens) + * + * A group of devices with same capability will forms + * a "globus potentis" or "capability group". The + * group is completely a logical formation, meaning + * that it is not explictly coded. + * + * The idea of potens is to provide a unified and yet + * opaque method to decouple the device provide raw + * functionalities with any higher abstraction, such + * as other subsystem, or standard-compilance wrapper + * (e.g., POSIX terminal) + */ +struct potens_meta { - struct llist_header caps; - unsigned int cap_type; + struct device* owner; + + struct llist_header potentes; + unsigned int pot_type; }; -#define CAPABILITY_META \ - union { \ - struct capability_meta cap_meta; \ - struct { \ - struct llist_header caps; \ - unsigned int cap_type; \ - }; \ +#define POTENS_META \ + struct { \ + union { \ + struct potens_meta pot_meta; \ + struct { \ + struct llist_header potentes; \ + unsigned int pot_type; \ + }; \ + }; \ } -#define get_capability(cap, cap_type) \ - container_of((cap), cap_type, cap_meta) -#define cap_meta(cap) (&(cap)->cap_meta) +#define get_potens(cap, pot_struct) \ + container_of((cap), pot_struct, pot_meta) +#define potens_meta(cap) (&(cap)->pot_meta) +#define potens_dev(cap) (potens_meta(cap)->owner) -typedef struct llist_header capability_list_t; +#define potens(name) POTENS_##name +#define potens_check_unique(dev, pot_type) \ + !device_get_potens(dev, pot_type) -struct device_meta +enum device_potens_type { - u32_t magic; - struct llist_header siblings; - struct llist_header children; - struct device_meta* parent; - struct hstr name; - - u32_t dev_uid; - - char name_val[DEVICE_NAME_SIZE]; + potens(NON), + #include }; +/** + * List of potentes of a device, pay attention to + * the spelling, "potentium", genitive plural of "potens". + */ +typedef struct llist_header potentium_list_t; + + +#define DEVICE_META_FIELD \ + struct { \ + morph_t mobj; \ + char name_val[DEVICE_NAME_SIZE]; \ + }; + #define DEVICE_METADATA \ union { \ struct device_meta meta; \ - struct { \ - u32_t magic; \ - struct llist_header siblings; \ - struct llist_header children; \ - struct device_meta* parent; \ - struct hstr name; \ - \ - u32_t dev_uid; \ - \ - char name_val[DEVICE_NAME_SIZE]; \ - }; \ - } - -#define dev_meta(dev) (&(dev)->meta) -#define to_dev(dev) (container_of(dev,struct device, meta)) -#define to_catdev(dev) (container_of(dev,struct device_cat, meta)) -#define to_aliasdev(dev) (container_of(dev,struct device_alias, meta)) + DEVICE_META_FIELD; \ + } + +#define devmeta_morpher morphable_attrs(device_meta, mobj) +#define devalias_morpher morphable_attrs(device_alias, mobj) +#define devcat_morpher morphable_attrs(device_cat, mobj) +#define device_morpher morphable_attrs(device, mobj) + +#define dev_meta(dev) (&(dev)->meta) +#define dev_mobj(dev) (&(dev)->mobj) +#define dev_morph(dev) ({ likely(dev) ? &(dev)->mobj : dev_object_root; }) +#define dev_uid(dev) (morpher_uid(&(dev)->mobj)) +#define to_dev(dev) (container_of(dev,struct device, meta)) +#define to_catdev(dev) (container_of(dev,struct device_cat, meta)) +#define to_aliasdev(dev) (container_of(dev,struct device_alias, meta)) + +struct device_meta +{ + DEVICE_META_FIELD; +}; struct device_alias { DEVICE_METADATA; @@ -171,7 +188,11 @@ struct device DEVICE_METADATA; - capability_list_t capabilities; + potentium_list_t potentium; + +#ifdef CONFIG_USE_DEVICETREE + devtree_link_t devtree_node; +#endif /* -- device state -- */ @@ -204,6 +225,15 @@ struct device } ops; }; +struct device_def; +typedef int (*devdef_ldfn)(struct device_def*); + +struct device_ldfn_chain +{ + struct device_ldfn_chain* chain; + devdef_ldfn load; +}; + struct device_def { struct llist_header dev_list; @@ -211,20 +241,46 @@ struct device_def struct hlist_node hlist_if; char* name; - struct devclass class; + union + { + struct { + bool no_default_realm : 1; + }; + int val; + } flags; + + + struct { + struct devclass class; + unsigned int class_hash; + }; + + struct device_ldfn_chain* load_chain; /** - * @brief Called when the driver is required to initialize itself. + * @brief + * Called when driver is required to register itself to the system + * All registration code should put it here. + * + * ad tabulam - + * "to the record" in latin. just in case anyone wonders. + * I am ran out of naming idea... have to improvise :) * */ - int (*init)(struct device_def*); + devdef_ldfn ad_tabulam; /** - * @brief Called when the driver is required to bind with a device. This is - * the case for a real-hardware-oriented driver + * @brief Called when the driver is loaded at it's desired load stage * */ - int (*bind)(struct device_def*, struct device*); + devdef_ldfn load; + + /** + * @brief Called when the driver is required to create device instance + * This is for device with their own preference of creation + * object that hold parameter for such creation is provided by second argument. + */ + int (*create)(struct device_def*, morph_t*); /** * @brief Called when a driver is requested to detach from the device and @@ -234,29 +290,16 @@ struct device_def int (*free)(struct device_def*, void* instance); }; -static inline bool must_inline -valid_device_ref(void* maybe_dev) { - if (!maybe_dev) - return false; - - unsigned int magic = ((struct device_meta*)maybe_dev)->magic; - return (magic ^ DEV_STRUCT_MAGIC_MASK) <= 0xfU; -} - -static inline bool must_inline -valid_device_subtype_ref(void* maybe_dev, unsigned int subtype) { - if (!maybe_dev) - return false; - - unsigned int magic = ((struct device_meta*)maybe_dev)->magic; - return (magic ^ DEV_STRUCT_MAGIC_MASK) == subtype; -} - -struct device* -resolve_device(void* maybe_dev); +#define def_device_name(dev_n) .name = dev_n +#define def_device_class(_if, fn, dev) .class = DEVCLASS(_if, fn, dev) +#define def_on_register(fn) .ad_tabulam = fn +#define def_on_load(fn) .load = fn +#define def_on_create(fn) .create = fn +#define def_on_free(fn) .free = fn +#define def_non_trivial .flags.no_default_realm = true -struct device_meta* -resolve_device_meta(void* maybe_dev); +morph_t* +resolve_device_morph(void* maybe_dev); #define mark_device_doing_write(dev_ptr) (dev_ptr)->poll_evflags &= ~_POLLOUT #define mark_device_done_write(dev_ptr) (dev_ptr)->poll_evflags |= _POLLOUT @@ -273,6 +316,12 @@ device_id_from_class(struct devclass* class) return ((class->device & 0xffff) << 16) | ((class->variant & 0xffff)); } +static inline struct device* +resolve_device(void* maybe_dev) { + morph_t* mobj = resolve_device_morph(maybe_dev); + return changeling_try_reveal(mobj, device_morpher); +} + void device_scan_drivers(); @@ -283,11 +332,18 @@ void device_setname(struct device_meta* dev, char* fmt, ...); void -device_register_generic(struct device_meta* dev, struct devclass* class, char* fmt, ...); +device_register_generic(struct device_meta* dev, struct devclass* class, + char* fmt, ...); #define register_device(dev, class, fmt, ...) \ device_register_generic(dev_meta(dev), class, fmt, ## __VA_ARGS__) +#define register_device_var(dev, class, fmt, ...) \ + ({device_register_generic( \ + dev_meta(dev), class, \ + fmt "%d", ## __VA_ARGS__, (class)->variant); \ + devclass_mkvar(class); }) + void device_create(struct device* dev, struct device_meta* parent, @@ -297,6 +353,14 @@ device_create(struct device* dev, struct device* device_alloc(struct device_meta* parent, u32_t type, void* underlay); +#ifdef CONFIG_USE_DEVICETREE +static inline void +device_set_devtree_node(struct device* dev, devtree_link_t node) +{ + dev->devtree_node = node; +} +#endif + static inline struct device* must_inline device_allocsys(struct device_meta* parent, void* underlay) { @@ -316,7 +380,8 @@ device_allocvol(struct device_meta* parent, void* underlay) } struct device_alias* -device_addalias(struct device_meta* parent, struct device_meta* aliased, char* name_fmt, ...); +device_addalias(struct device_meta* parent, struct device_meta* aliased, + char* name_fmt, ...); struct device_cat* device_addcat(struct device_meta* parent, char* name_fmt, ...); @@ -324,18 +389,6 @@ device_addcat(struct device_meta* parent, char* name_fmt, ...); void device_remove(struct device_meta* dev); -struct device_meta* -device_getbyid(struct llist_header* devlist, u32_t id); - -struct device_meta* -device_getbyhname(struct device_meta* root_dev, struct hstr* name); - -struct device_meta* -device_getbyname(struct device_meta* root_dev, const char* name, size_t len); - -struct device_meta* -device_getbyoffset(struct device_meta* root_dev, int pos); - struct hbucket* device_definitions_byif(int if_type); @@ -350,20 +403,21 @@ device_scan_drivers(); /*------ Capability ------*/ -struct capability_meta* -alloc_capability(int cap, unsigned int size); +struct potens_meta* +alloc_potens(int cap, unsigned int size); -#define new_capability(cap_type, cap_impl)\ - ((cap_impl*)alloc_capability((cap_type), sizeof(cap_impl))) +#define new_potens(pot_type, pot_struct)\ + ((pot_struct*)alloc_potens((pot_type), sizeof(pot_struct))) -#define new_capability_marker(cap_type)\ - (alloc_capability((cap_type), sizeof(struct capability_meta))) +#define new_potens_marker(pot_type)\ + (alloc_potens((pot_type), sizeof(struct potens_meta))) void -device_grant_capability(struct device* dev, struct capability_meta* cap); +device_grant_potens(struct device* dev, struct potens_meta* cap); + +struct potens_meta* +device_get_potens(struct device* dev, unsigned int pot_type); -struct capability_meta* -device_get_capability(struct device* dev, unsigned int cap_type); /*------ Load hooks ------*/ void @@ -375,6 +429,21 @@ device_postboot_load(); void device_sysconf_load(); +/** + * @brief Add the loader to the chain, used by device domain + * to inject their custom loading logic to the hook + */ +void +device_chain_loader(struct device_def* def, devdef_ldfn fn); + +/** + * @brief Walk the chain and load in a use-and-burnt fashion. + * the chain will be deleted and freed after loading, + * regardless successful or not. + */ +void +device_chain_load_once(struct device_def* def); + static inline void device_lock(struct device* dev) { @@ -395,4 +464,42 @@ device_locked(struct device* dev) #define devprintf_expand(devident) (devident)->fn_grp, (devident)->unique + +/** + * + * Device def hooks extern + * + */ + +static int +default_onregister_hook(struct device_def* def) +{ + return 0; +} + +static int +default_onload_hook(struct device_def* def) +{ + return 0; +} + +static int +default_oncreate_hook(struct device_def* def, morph_t* morphed) +{ + return 0; +} + +#define extern_hook_register(name) \ + int weak_alias("default_onregister_hook") \ + name(struct device_def* def) + +#define extern_hook_load(name) \ + int weak_alias("default_onload_hook") \ + name(struct device_def* def) + +#define extern_hook_create(name) \ + int weak_alias("default_oncreate_hook") \ + name(struct device_def* def, morph_t* morphed) + + #endif /* __LUNAIX_DEVICE_H */