feat: support user-spcae pci rescan
[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
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 #define load_on_demand ld_ondemand
25 #define load_pci_probe ld_ondemand
26
27 /**
28  * @brief Mark the device definition should be loaded automatically as earlier
29  * as possible in the kernel bootstrapping stage (before initialization of file
30  * systems). Load here if your driver is standalone and require no other than
31  * basic memory allocation services
32  *
33  */
34 #define load_earlystage ld_early
35
36 /**
37  * @brief Mark the device definition should be loaded automatically after timer
38  * is ready. Load here if your driver require a basic timing service
39  *
40  */
41 #define load_timerstage ld_aftertimer
42
43 /**
44  * @brief Mark the device definition should be loaded automatically in
45  * the post boostrapping stage (i.e., the start up of proc0). Load here if your
46  * driver involves async mechanism
47  *
48  */
49 #define load_poststage ld_post
50
51 /**
52  * @brief Declare a device class
53  *
54  */
55 #define DEVCLASS(devif, devfn, dev)                                            \
56     (struct devclass)                                                          \
57     {                                                                          \
58         .fn_grp = DEV_FNGRP(devif, devfn), .device = (dev), .variant = 0       \
59     }
60
61 #define DEVCLASSV(devif, devfn, dev, devvar)                                   \
62     (struct devclass)                                                          \
63     {                                                                          \
64         .fn_grp = DEV_FNGRP(devif, devfn), .device = (dev),                    \
65         .variant = (devvar)                                                    \
66     }
67
68 #define DEV_STRUCT_MAGIC 0x5645444c
69
70 #define DEV_MSKIF 0x00000003
71
72 #define DEV_IFVOL 0x0 // volumetric (block) device
73 #define DEV_IFSEQ 0x1 // sequential (character) device
74 #define DEV_IFCAT 0x2 // a device category (as device groupping)
75 #define DEV_IFSYS 0x3 // a system device
76
77 struct device
78 {
79     u32_t magic;
80     struct llist_header siblings;
81     struct llist_header children;
82     struct device* parent;
83     mutex_t lock;
84
85     // TODO investigate event polling
86
87     struct hstr name;
88     struct devident ident;
89
90     u32_t dev_uid;
91     int dev_type;
92     char name_val[DEVICE_NAME_SIZE];
93     void* underlay;
94
95     struct
96     {
97         // TODO Think about where will they fit.
98         int (*acquire)(struct device* dev);
99         int (*release)(struct device* dev);
100
101         int (*read)(struct device* dev, void* buf, size_t offset, size_t len);
102         int (*write)(struct device* dev, void* buf, size_t offset, size_t len);
103         int (*read_page)(struct device* dev, void* buf, size_t offset);
104         int (*write_page)(struct device* dev, void* buf, size_t offset);
105         int (*exec_cmd)(struct device* dev, u32_t req, va_list args);
106     } ops;
107 };
108
109 struct device_def
110 {
111     struct llist_header dev_list;
112     struct hlist_node hlist;
113     struct hlist_node hlist_if;
114     char* name;
115
116     struct devclass class;
117
118     int (*init)(struct device_def*);
119     int (*bind)(struct device_def*, struct device*);
120     int (*free)(struct device_def*, void* instance);
121 };
122
123 static inline u32_t
124 device_id_from_class(struct devclass* class)
125 {
126     return ((class->device & 0xffff) << 16) | ((class->variant & 0xffff));
127 }
128
129 void
130 device_scan_drivers();
131
132 void
133 device_setname_vargs(struct device* dev, char* fmt, va_list args);
134
135 void
136 device_setname(struct device* dev, char* fmt, ...);
137
138 void
139 device_register(struct device* dev, struct devclass* class, char* fmt, ...);
140
141 void
142 device_create(struct device* dev,
143               struct device* parent,
144               u32_t type,
145               void* underlay);
146
147 struct device*
148 device_alloc(struct device* parent, u32_t type, void* underlay);
149
150 static inline struct device*
151 device_allocsys(struct device* parent, void* underlay)
152 {
153     return device_alloc(parent, DEV_IFSYS, underlay);
154 }
155
156 static inline struct device*
157 device_allocseq(struct device* parent, void* underlay)
158 {
159     return device_alloc(parent, DEV_IFSEQ, underlay);
160 }
161
162 static inline struct device*
163 device_allocvol(struct device* parent, void* underlay)
164 {
165     return device_alloc(parent, DEV_IFVOL, underlay);
166 }
167
168 struct device*
169 device_addcat(struct device* parent, char* name_fmt, ...);
170
171 void
172 device_remove(struct device* dev);
173
174 struct device*
175 device_getbyid(struct llist_header* devlist, u32_t id);
176
177 struct device*
178 device_getbyhname(struct device* root_dev, struct hstr* name);
179
180 struct device*
181 device_getbyname(struct device* root_dev, const char* name, size_t len);
182
183 struct device*
184 device_getbyoffset(struct device* root_dev, int pos);
185
186 struct device*
187 device_cast(void* obj);
188
189 struct hbucket*
190 device_definitions_byif(int if_type);
191
192 struct device_def*
193 devdef_byident(struct devident* class);
194
195 void
196 device_populate_info(struct device* dev, struct dev_info* devinfo);
197
198 void
199 device_scan_drivers();
200
201 /*------ Load hooks ------*/
202
203 void
204 device_earlystage();
205
206 void
207 device_poststage();
208
209 void
210 device_timerstage();
211
212 static inline void
213 device_lock(struct device* dev)
214 {
215     mutex_lock(&dev->lock);
216 }
217
218 static inline void
219 device_unlock(struct device* dev)
220 {
221     mutex_unlock(&dev->lock);
222 }
223
224 static inline int
225 device_locked(struct device* dev)
226 {
227     return mutex_on_hold(&dev->lock);
228 }
229
230 #define devprintf_expand(devident) (devident)->fn_grp, (devident)->unique
231
232 #endif /* __LUNAIX_DEVICE_H */