2d9f82bda5fe7f6da6245256a2477a1055a182d3
[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 (*init_for)(struct device_def*, struct device*);
120 };
121
122 static inline u32_t
123 device_id_from_class(struct devclass* class)
124 {
125     return ((class->device & 0xffff) << 16) | ((class->variant & 0xffff));
126 }
127
128 void
129 device_scan_drivers();
130
131 void
132 device_setname_vargs(struct device* dev, char* fmt, va_list args);
133
134 void
135 device_setname(struct device* dev, char* fmt, ...);
136
137 void
138 device_register(struct device* dev, struct devclass* class, char* fmt, ...);
139
140 void
141 device_create(struct device* dev,
142               struct device* parent,
143               u32_t type,
144               void* underlay);
145
146 struct device*
147 device_alloc(struct device* parent, u32_t type, void* underlay);
148
149 static inline struct device*
150 device_allocsys(struct device* parent, void* underlay)
151 {
152     return device_alloc(parent, DEV_IFSYS, underlay);
153 }
154
155 static inline struct device*
156 device_allocseq(struct device* parent, void* underlay)
157 {
158     return device_alloc(parent, DEV_IFSEQ, underlay);
159 }
160
161 static inline struct device*
162 device_allocvol(struct device* parent, void* underlay)
163 {
164     return device_alloc(parent, DEV_IFVOL, underlay);
165 }
166
167 struct device*
168 device_addcat(struct device* parent, char* name_fmt, ...);
169
170 void
171 device_remove(struct device* dev);
172
173 struct device*
174 device_getbyid(struct llist_header* devlist, u32_t id);
175
176 struct device*
177 device_getbyhname(struct device* root_dev, struct hstr* name);
178
179 struct device*
180 device_getbyname(struct device* root_dev, const char* name, size_t len);
181
182 struct device*
183 device_getbyoffset(struct device* root_dev, int pos);
184
185 struct device*
186 device_cast(void* obj);
187
188 struct hbucket*
189 device_definitions_byif(int if_type);
190
191 struct device_def*
192 devdef_byident(struct devident* class);
193
194 void
195 device_populate_info(struct device* dev, struct dev_info* devinfo);
196
197 void
198 device_scan_drivers();
199
200 /*------ Load hooks ------*/
201
202 void
203 device_earlystage();
204
205 void
206 device_poststage();
207
208 void
209 device_timerstage();
210
211 static inline void
212 device_lock(struct device* dev)
213 {
214     mutex_lock(&dev->lock);
215 }
216
217 static inline void
218 device_unlock(struct device* dev)
219 {
220     mutex_unlock(&dev->lock);
221 }
222
223 static inline int
224 device_locked(struct device* dev)
225 {
226     return mutex_on_hold(&dev->lock);
227 }
228
229 #endif /* __LUNAIX_DEVICE_H */