refactor: make pci device driver loading passive, pci bus scanner will not load them...
[lunaix-os.git] / lunaix-os / includes / lunaix / device.h
1 #ifndef __LUNAIX_DEVICE_H
2 #define __LUNAIX_DEVICE_H
3
4 #define DEVICE_NAME_SIZE 32
5
6 #include <lunaix/device_num.h>
7 #include <lunaix/ds/hashtable.h>
8 #include <lunaix/ds/hstr.h>
9 #include <lunaix/ds/ldga.h>
10 #include <lunaix/ds/llist.h>
11 #include <lunaix/ds/mutex.h>
12 #include <lunaix/types.h>
13
14 #include <usr/lunaix/device.h>
15
16 /**
17  * @brief Export a device definition (i.e., device driver metadata)
18  *
19  */
20 #define EXPORT_DEVICE(id, devdef, load_order)                                  \
21     export_ldga_el(devdefs, id, ptr_t, devdef);                                \
22     export_ldga_el_sfx(devdefs, id##_ldorder, ptr_t, devdef, load_order);
23
24 /**
25  * @brief Mark the device definition can be loaded on demand, all other loading
26  * options are extended from this
27  */
28 #define load_on_demand ld_ondemand
29
30 /**
31  * @brief Mark the device definition to be loaded as system configuration
32  * device. These kind of devices are defined to be the devices that talk to the
33  * system firmware to do config, or collecting crucial information about the
34  * system. For instances, ACPI, SoC components, and other **interconnection**
35  * buese (not USB!). Such device driver must only rely on basic memory
36  * management service, and must not try accessing subsystems other than the mm
37  * unit, for example, timer, interrupt, file-system, must not assumed exist.
38  *
39  */
40 #define load_sysconf ld_sysconf
41
42 /**
43  * @brief Mark the device definition should be loaded as time device, for
44  * example a real time clock device. Such device will be loaded and managed by
45  * clock subsystem
46  */
47 #define load_timedev ld_timedev
48
49 /**
50  * @brief Mark the device definition should be loaded automatically during the
51  * bootstrapping stage. Most of the driver do load there.
52  *
53  */
54 #define load_onboot ld_kboot
55
56 /**
57  * @brief Mark the device definition should be loaded automatically in
58  * the post boostrapping stage (i.e., the start up of proc0), where most of
59  * kernel sub-system are became ready to use. Do your load there if your driver
60  * depends on such condition
61  *
62  */
63 #define load_postboot ld_post
64
65 #define __foreach_exported_device_of(stage, index, pos)                        \
66     ldga_foreach(dev_##stage, struct device_def*, index, pos)
67 #define foreach_exported_device_of(stage, index, pos)                          \
68     __foreach_exported_device_of(stage, index, pos)
69
70 /**
71  * @brief Declare a device class
72  *
73  */
74 #define DEVCLASS(devif, devfn, dev)                                            \
75     (struct devclass)                                                          \
76     {                                                                          \
77         .fn_grp = DEV_FNGRP(devif, devfn), .device = (dev), .variant = 0       \
78     }
79
80 #define DEVCLASSV(devif, devfn, dev, devvar)                                   \
81     (struct devclass)                                                          \
82     {                                                                          \
83         .fn_grp = DEV_FNGRP(devif, devfn), .device = (dev),                    \
84         .variant = (devvar)                                                    \
85     }
86
87 #define DEV_STRUCT_MAGIC 0x5645444c
88
89 #define DEV_MSKIF 0x00000003
90
91 #define DEV_IFVOL 0x0 // volumetric (block) device
92 #define DEV_IFSEQ 0x1 // sequential (character) device
93 #define DEV_IFCAT 0x2 // a device category (as device groupping)
94 #define DEV_IFSYS 0x3 // a system device
95
96 struct device
97 {
98     u32_t magic;
99     struct llist_header siblings;
100     struct llist_header children;
101     struct device* parent;
102     mutex_t lock;
103
104     // TODO investigate event polling
105
106     struct hstr name;
107     struct devident ident;
108
109     u32_t dev_uid;
110     int dev_type;
111     char name_val[DEVICE_NAME_SIZE];
112     void* underlay;
113
114     struct
115     {
116         // TODO Think about where will they fit.
117         int (*acquire)(struct device* dev);
118         int (*release)(struct device* dev);
119
120         int (*read)(struct device* dev, void* buf, size_t offset, size_t len);
121         int (*write)(struct device* dev, void* buf, size_t offset, size_t len);
122         int (*read_page)(struct device* dev, void* buf, size_t offset);
123         int (*write_page)(struct device* dev, void* buf, size_t offset);
124         int (*exec_cmd)(struct device* dev, u32_t req, va_list args);
125     } ops;
126 };
127
128 struct device_def
129 {
130     struct llist_header dev_list;
131     struct hlist_node hlist;
132     struct hlist_node hlist_if;
133     char* name;
134
135     struct devclass class;
136
137     /**
138      * @brief Called when the driver is required to initialize itself.
139      *
140      */
141     int (*init)(struct device_def*);
142
143     /**
144      * @brief Called when the driver is required to bind with a device. This is
145      * the case for a real-hardware-oriented driver
146      *
147      */
148     int (*bind)(struct device_def*, struct device*);
149
150     /**
151      * @brief Called when a driver is requested to detach from the device and
152      * free up all it's resources
153      *
154      */
155     int (*free)(struct device_def*, void* instance);
156 };
157
158 static inline u32_t
159 device_id_from_class(struct devclass* class)
160 {
161     return ((class->device & 0xffff) << 16) | ((class->variant & 0xffff));
162 }
163
164 void
165 device_scan_drivers();
166
167 void
168 device_setname_vargs(struct device* dev, char* fmt, va_list args);
169
170 void
171 device_setname(struct device* dev, char* fmt, ...);
172
173 void
174 device_register(struct device* dev, struct devclass* class, char* fmt, ...);
175
176 void
177 device_create(struct device* dev,
178               struct device* parent,
179               u32_t type,
180               void* underlay);
181
182 struct device*
183 device_alloc(struct device* parent, u32_t type, void* underlay);
184
185 static inline struct device*
186 device_allocsys(struct device* parent, void* underlay)
187 {
188     return device_alloc(parent, DEV_IFSYS, underlay);
189 }
190
191 static inline struct device*
192 device_allocseq(struct device* parent, void* underlay)
193 {
194     return device_alloc(parent, DEV_IFSEQ, underlay);
195 }
196
197 static inline struct device*
198 device_allocvol(struct device* parent, void* underlay)
199 {
200     return device_alloc(parent, DEV_IFVOL, underlay);
201 }
202
203 struct device*
204 device_addcat(struct device* parent, char* name_fmt, ...);
205
206 void
207 device_remove(struct device* dev);
208
209 struct device*
210 device_getbyid(struct llist_header* devlist, u32_t id);
211
212 struct device*
213 device_getbyhname(struct device* root_dev, struct hstr* name);
214
215 struct device*
216 device_getbyname(struct device* root_dev, const char* name, size_t len);
217
218 struct device*
219 device_getbyoffset(struct device* root_dev, int pos);
220
221 struct device*
222 device_cast(void* obj);
223
224 struct hbucket*
225 device_definitions_byif(int if_type);
226
227 struct device_def*
228 devdef_byident(struct devident* class);
229
230 void
231 device_populate_info(struct device* dev, struct dev_info* devinfo);
232
233 void
234 device_scan_drivers();
235
236 /*------ Load hooks ------*/
237
238 void
239 device_onbooot_load();
240
241 void
242 device_postboot_load();
243
244 void
245 device_sysconf_load();
246
247 static inline void
248 device_lock(struct device* dev)
249 {
250     mutex_lock(&dev->lock);
251 }
252
253 static inline void
254 device_unlock(struct device* dev)
255 {
256     mutex_unlock(&dev->lock);
257 }
258
259 static inline int
260 device_locked(struct device* dev)
261 {
262     return mutex_on_hold(&dev->lock);
263 }
264
265 #define devprintf_expand(devident) (devident)->fn_grp, (devident)->unique
266
267 #endif /* __LUNAIX_DEVICE_H */