vfs: check userland buffers before reading them.
[haiku.git] / docs / develop / kernel / obsolete_pnp_manager
blobeeb9d31c79069660d17f50d407bc05d28925b8a0
1 This file contains the documentation written by Thomas Kurschel that was originally
2 found in the headers of his pnp_manager.
3 It's outdated but could be used as a basis for the real documentation.
5 // former pnp_manager.h
6 /*
7         Copyright (c) 2003-04, Thomas Kurschel
9         PnP manager; Takes care of registration and loading of PnP drivers
10         
11         Read pnp_driver.h first to understand the basic idea behind PnP drivers.
12         
13         To register a driver node, use register_driver. If the device got lost, 
14         use unregister_driver (note: if the parent node is removed, your node 
15         get removed automatically as your driver has obviously nothing to work 
16         with anymore). To get access to a (parent) device, use load_driver/
17         unload_driver.
18         
19         To let the manager find a consumer (see pnp_driver.h), you can either
20         specify its name directly during registration, using a 
21         PNP_DRIVER_FIXED_CONSUMER attribute, or let the manager search the 
22         appropriate consumer(s) via a PNP_DRIVER_DYNAMIC_CONSUMER attribute. 
23         
24         Searching of dynamic consumers is done as follows:
25         
26         - First, the manager searches for a Specific driver in the base 
27           directory (see below)
28         - If no Specific driver is found, all Generic drivers stored under
29           "generic" sub-directory are informed in turn until one returns success
30         - Finally, _all_ Universal drivers, stored in the "universal" sub-
31           directory, are informed
33         Specification of the base directory and of the names of Specific 
34         drivers is done via a file name pattern given by a 
35         PNP_DRIVER_DYNAMIC_CONSUMER attribute. 
36         
37         First, all substrings of the form "%attribute_name%" are replaced by the 
38         content of the attribute "attribute_name" as follows:
39         
40         - if the attribute contains an integer value, its content is converted to hex 
41           (lowercase) with a fixed length according to the attribute's value range
42         - the content of string attributes is quoted by " and invalid characters 
43           (i.e. /%" and all characters outside 32..126) are replaced by their
44           unsigned decimal value, delimited by %
45         - other attribute types cannot be used
46         
47         Second, the resulting name is split into chunks according to the presence 
48         of | characters (you can escape % and | with a ^ character). These
49         characters are only delimiters and get removed before further processing.
50         The directory before the first | character is the base directory (see 
51         above). It contains the "generic" and the "universal" subdirectories. 
52         The names of the specific drivers are created by first taking the entire
53         file name, then by removing the last chunk, then by removing the last
54         two chunks and so on until only the first chunk is left. 
56         As drivers can contain multiple modules, the module name is constructed
57         by appending the content of the PNP_DRIVER_TYPE attribute to the driver's file
58         name, seperated by a slash character (note: this only applies to dynamic
59         consumers; for fixed consumers, you specify the module name directly via 
60         PNP_DRIVER_FIXED_CONSUMER).
61         
62         E.g. given a dynamic consumer pattern of 
63         "pci/vendor=%vendor_id%|, device=%device_id%" for a device with the 
64         attributes vendor_id=0x123 and device_id=0xabcd (both being uint16), the
65         PnP manager tries the specific drivers "pci/vendor=0123, device=abcd" and
66         (if the first one fails/doesn't exist) "pci/vendor=0123". If they both
67         refuse to handle the device, all drivers under "pci/generic" are tried
68         until one accepts the device. Finally, all drivers under "pci/universal" 
69         are     loaded, whatever happened before.
71         In practise, you should try to use specific drivers as much as possible.
72         If detection based on device IDs is impossible (e.g. because the bus 
73         doesn't support them at all), you can put the driver under "generic".
74         Generic drivers can also be used to specify wrappers that try to load old-
75         style drivers if no new driver can be found. Also, they can be used to
76         report an error or invoke an user program that tries downloading a
77         proper Specific driver. Universal drivers are mainly used for 
78         informational purposes, e.g. to publish data about each found device,
79         or to provide raw access to all devices.
80         
81         If the device uses physical address space or I/O space or ISA DMA 
82         channels (called I/O resources), the driver has to acquire these 
83         resources. During hardware detection (usually via probe()), 
84         acquire_io_resources() must be called to get exclusive access.
85         If no hardware could be found, they must be released via 
86         release_io_resources(). If detection was successful, the list of 
87         the (acquired) resources must be passed to register_device().
88         Resources can either belong to one hardware detection or to a device.
89         If a hardware detection collides with another, it has to wait; 
90         if it collides with a device whose driver is not loaded, the
91         driver loading is blocked. When detection fails, i.e. if 
92         release_io_resources() is called, all blocked drivers can be loaded
93         again. If the detection fails, i.e. the resources are transferred
94         via register_device(), all blocked devices are unregistered and
95         pending load requests aborted. If a hardware detection collides
96         with a device whose driver is loaded, acquire_io_resources() fails
97         with B_BUSY. As this makes a hardware rescan impossible if the 
98         driver is loaded, you should define     PNP_DRIVER_NO_LIVE_RESCAN 
99         for nodes that use I/O resources (see below).
100         
101         To search for new drivers for a given device node, use rescan(). This
102         marks all consumer devices as being verified and calls probe() 
103         of all consumers drivers (see above) to let them rescan the parent 
104         for devices. The <depth> parameter determines the nesting level, e.g.
105         2 means that first the consumers are scanned and then the consumers
106         of the consumers.
107         
108         Normally, all devices can be rescanned. If a driver cannot handle
109         a rescan safely when it is loaded (i.e. used by a consumer), it
110         must set PNP_DRIVER_NO_LIVE_RESCAN, in which case the device is
111         ignored during rescan if the driver is loaded and attempts
112         to load the driver during a rescan are blocked until the rescan
113         is finished. If rescanning a device is not possible at all, it must
114         have set PNP_DRIVER_NEVER_RESCAN to always ignore it.
115         
116         To distinguish between new devices, lost devices and redetected
117         devices, consumer devices should provide a connection code and a
118         device identifier. They are specified by PNP_DRIVER_CONNECTION and
119         PNP_DRIVER_CONNECTION respectively, and are expanded in the same way
120         as PNP_DRIVER_DYNAMIC_CONSUMER. It is assumed that there can be only
121         one device per connection and that a device can be uniquely identify
122         by a device identifier. If a consumer device is registered on the 
123         same connection as an existing device but with a different device 
124         identifier, the old device gets unregistered automatically. If both 
125         connection and device identifier are the same, registration is 
126         handled as a redetection and ignored (unless a different type or 
127         driver module is specified - in this case, the device is replaced). 
128         Devices that were not redetected during a rescan get unregistered
129         unless they were ignored (see above).
132 // interface of PnP manager
133 typedef struct device_manager_info {
134         module_info info;
136         // load driver
137         // node - node whos driver is to be loaded
138         // user_cookie - cookie to be passed to init_device of driver
139         // interface - interface of loaded driver
140         // cookie - device cookie issued by loaded driver
141         status_t (*init_driver)(device_node_handle node, void *userCookie,
142                                         driver_module_info **interface, void **cookie);
143         // unload driver
144         status_t (*uninit_driver)(device_node_handle node);
146         // rescan node for new dynamic drivers
147         // node - node whose dynamic drivers are to be scanned
148         status_t (*rescan)(device_node_handle node);
150         // register device
151         // parent - parent node
152         // attributes - NULL-terminated array of node attributes
153         // io_resources - NULL-terminated array of I/O resources (can be NULL)
154         // node - new node handle
155         // on return, io_resources are invalid: on success I/O resources belong 
156         // to node, on fail they are released;
157         // if device is already registered, B_OK is returned but *node is NULL
158         status_t (*register_device)(device_node_handle parent,
159                                         const device_attr *attrs,
160                                         const io_resource_handle *io_resources,
161                                         device_node_handle *node);
162         // unregister device
163         // all nodes having this node as their parent are unregistered too.
164         // if the node contains PNP_MANAGER_ID_GENERATOR/PNP_MANAGER_AUTO_ID
165         // pairs, the id specified this way is freed too
166         status_t (*unregister_device)(device_node_handle node);
168         // find device by node content
169         // the given attributes must _uniquely_ identify a device node;
170         // parent - parent node (-1 for don't-care)
171         // attrs - list of attributes (can be NULL)
172         // The node you got will be automatically put on the next call
173         // to this function.
174         status_t (*get_next_child_device)(device_node_handle parent,
175                 device_node_handle *_node, const device_attr *attrs);
177         // get parent device node
178         device_node_handle (*get_parent)(device_node_handle node);
180         // Must be called after get_next_child_device() (if you don't iterate through)
181         // and get_parent() to make sure the node is freed when it's not used anymore
182         void (*put_device_node)(device_node_handle node);
184         // acquire I/O resources
185         // resources - NULL-terminated array of resources to acquire
186         // handles - NULL-terminated array of handles (one per resource); 
187         //           array must be provided by caller
188         // return B_BUSY if a resource is used by a loaded driver
189         status_t (*acquire_io_resources)(io_resource *resources,
190                                         io_resource_handle *handles);
191         // release I/O resources
192         // handles - NULL-terminated array of handles
193         status_t (*release_io_resources)(const io_resource_handle *handles);
195         // create unique id
196         // generator - name of id set
197         // if result >= 0 - unique id
198         //    result < 0 - error code
199         int32 (*create_id)(const char *generator);
200         // free unique id
201         status_t (*free_id)(const char *generator, uint32 id);
203         // helpers to extract attribute by name.
204         // if <recursive> is true, parent nodes are scanned if 
205         // attribute isn't found in current node; unless you declared
206         // the attribute yourself, use recursive search to handle
207         // intermittent nodes, e.g. defined by filter drivers, transparently.
208         // for raw and string attributes, you get a copy that must 
209         // be freed by caller 
210         status_t (*get_attr_uint8)(device_node_handle node,
211                                         const char *name, uint8 *value, bool recursive);
212         status_t (*get_attr_uint16)(device_node_handle node,
213                                         const char *name, uint16 *value, bool recursive);
214         status_t (*get_attr_uint32)(device_node_handle node,
215                                         const char *name, uint32 *value, bool recursive);
216         status_t (*get_attr_uint64)(device_node_handle node,
217                                         const char *name, uint64 *value, bool recursive);
218         status_t (*get_attr_string)(device_node_handle node,
219                                         const char *name, char **value, bool recursive);
220         status_t (*get_attr_raw)(device_node_handle node,
221                                         const char *name, void **data, size_t *_size,
222                                         bool recursive);
224         // get next attribute of node;
225         // on call, *<attr_handle> must contain handle of an attribute;
226         // on return, *<attr_handle> is replaced by the next attribute or
227         // NULL if it was the last;
228         // to get the first attribute, <attr_handle> must point to NULL;
229         // the returned handle must be released by either passing it to
230         // another get_next_attr() call or by using release_attr()
231         // directly
232         status_t (*get_next_attr)(device_node_handle node,
233                                         device_attr_handle *attrHandle);
235         // release attribute handle <attr_handle> of <node>;
236         // see get_next_attr
237         status_t (*release_attr)(device_node_handle node,
238                                         device_attr_handle attr_handle);
240         // retrieve attribute data with handle given;
241         // <attr> is only valid as long as you don't release <attr_handle> 
242         // implicitely or explicitely
243         status_t (*retrieve_attr)(device_attr_handle attr_handle,
244                                         const device_attr **attr);
246         // change/add attribute <attr> of/to node
247         status_t (*write_attr)(device_node_handle node,
248                                         const device_attr *attr);
250         // remove attribute of node by name
251         // <name> is name of attribute
252         status_t (*remove_attr)(device_node_handle node, const char *name);
253 } device_manager_info;
255 // former pnp_driver.h
257         Copyright (c) 2003-04, Thomas Kurschel
259         Required interface of PnP drivers
261         In contrast to standard BeOS drivers, PnP drivers are normal modules
262         having the interface described below.
264         Every device is described by its driver via a PnP node with properties
265         described in PnP Node Attributes. Devices are organized in a hierarchy, 
266         e.g. a devfs device is a hard disk device that is connected to a 
267         controller, which is a PCI device, that is connected to a PCI bus.
268         Every device is connected to its lower-level device     via a parent link 
269         stored in its Node. The higher-level is called the consumer of the 
270         lower-level device. If the lower-level device gets removed, all its 
271         consumers are removed too.
273         In our example, the hierarchy is
275           devfs device -> hard disk -> controller -> PCI device -> PCI bus
277         If the PCI bus is removed, everything up to including the devfs device
278         is removed too.
280         The driver hierarchy is constructed bottom-up, i.e. the lower-level
281         driver searches for a corresponding consumer, which in turns searches
282         for its consumer and so on. The lowest driver is usually something like
283         a PCI bus, the highest driver is normally a devfs entry (see pnp_devfs.h).
284         Registration of devices and the search for appropriate consumers is 
285         done via the pnp_manager (see pnp_manager.h).
287         When a potential consumer is found, it gets informed about the new
288         lower-level device and can either refuse its handling or accept it.
289         On accept, it has to create a new node with the lower-level device 
290         node as its parent.
292         Loading of drivers is done on demand, i.e. if the consumer wants to
293         access its lower-level device, it explicitely loads the corresponding 
294         driver, and once it doesn't need it anymore, the lower-level driver
295         must be unloaded. Usually, this process happens recursively, i.e. in
296         our example, the hard disk driver loads the controller driver, which 
297         loads the PCI device driver which loads the PCI bus driver. The same
298         process applies to unloading.
300         Because of this dynamic loading, drivers must store persistent data
301         in the node of their devices. Please be aware that you cannot modify
302         a node once published.
304         If a device gets removed, you must unregister its node. As said, the
305         PnP manager will automatically unregister all consumers too. The 
306         corresponding drivers are notified to stop talking to their     lower-level 
307         devices and to terminate running requests. Normally, you want to use a 
308         dedicated variable that is verified at each call to make sure that the 
309         parent is still there. The notification is done independantly of the
310         driver being loaded by its consumer(s) or not. If it isn't loaded,
311         the notification callback gets NULL as the device cookie; normally, the
312         driver returns immediately in this case. As soon as both the device
313         is removed and the driver is unloaded, device_cleanup gets called to
314         free resources that couldn't be safely removed in device_removed when
315         the driver was still loaded.
317         If a device has exactly one consumer, they often interact in some way.
318         To simplify that, the consumer can pass a user-cookie to its parent
319         during load. In this case, it's up to the parent driver to get a 
320         pointer to the interface of the consumer. Effectively, such consumers
321         have one interface for their consumers (base on pnp_driver_info), and 
322         a another for their parents (with a completely driver-specific 
323         structure).
325         In terms of synchronization, loading/unloading/remove-notifications
326         are executed synchronously, i.e. if e.g. a device is to be unloaded 
327         but     the drive currently handles a remove-notification, the unloading 
328         is delayed until the nofication callback returns. If multiple consumers
329         load a driver, the driver gets initialized only once; subsequent load
330         requests increase an internal load count only and return immediately.
331         In turn, unloading only happens once the load count reaches zero.
334 struct driver_module_info {
335         module_info info;
337         float (*supports_device)(device_node_handle parent, bool *_noConnection);
338                 // check whether this parent is supported
340         status_t (*register_device)(device_node_handle parent);
341                 // Register your device node.
343         status_t (*init_driver)(device_node_handle node, void *user_cookie, void **_cookie);
344                 // driver is loaded.
345                 // node - node of device
346                 // user_cookie - cookie passed by loading driver
347                 // cookie - cookie issued by this driver
349         status_t (*uninit_driver)(void *cookie);
350                 // driver gets unloaded.
352         void (*device_removed)(device_node_handle node, void *cookie);
353                 // a device node, registered by this driver, got removed.
354                 // if the driver wasn't loaded when this happenes, no (un)init_device 
355                 // is called and thus <cookie> is NULL;
357         void (*device_cleanup)(device_node_handle node);
358                 // a device node, registered by this driver, got removed and
359                 // the driver got unloaded
361         void (*get_supported_paths)(const char ***_busses, const char ***_devices);
364 // former pnp_bus.h
366         Copyright (c) 2003-04, Thomas Kurschel
368         Required interface of PnP bus drivers
370         Busses consist of two node layers: the lower layer defines the bus,
371         the upper layer defines the abstract devices connected to the bus. 
372         Both layers are handled by a bus manager. Actual device nodes are 
373         on top of abstract device nodes.
375         E.g. if we have a PCI bus with an IDE controller on it, we get
377         IDE controller -> PCI device -> PCI bus
379         with:
380                 IDE controller = actual device node
381                 PCI device = abstract device node
382                 PCI bus = bus node
384         The PCI bus manager establishes both the PCI devices and the PCI busses.
386         Abstract device nodes act as a gateway between actual device nodes
387         and the corresponding bus node. They are constructed by the bus 
388         node driver via its rescan() hook. To identify a bus node, define
389         PNP_BUS_IS_BUS as an attribute of it. As a result, the PnP manager
390         will call the rescan() method of the bus driver whenever the
391         bus is to be rescanned. Afterwards, all possible dynamic consumers
392         are informed as done for normal nodes.
394         Normally, potential device drivers are notified immediately when 
395         rescan() registers a new abstract device node. But sometimes, device
396         drivers need to know _all_ devices connected to the bus for correct
397         detection. To ensure this, the bus node must define 
398         PNP_BUS_NOTIFY_CONSUMERS_AFTER_RESCAN. In this case, scanning for
399         consumers is postponed until rescan() has finished.
401         If hot-plugging of devices can be detected automatically (e.g. USB), 
402         you should define PNP_DRIVER_ALWAYS_LOADED, so the bus driver is 
403         always loaded and thus capable of handling hot-plug events generated 
404         by the bus controller hardware.