This document is part of the Driver Development Kit tutorial documentation.
Taking a long time to initialize
What if your device takes a long time to initialize? When we discussed the null_bind() function above, we indicated that a successful return told the device manager that the driver is now associated with the device. We can't spend a lot of time in the bind function; we're basically expected to initialize our device, publish it, and be done.
But your device might need to perform a lengthy initialization operation, such as:
- enumerate hardware points
- load firmware
- negotiate a protocol
and so on, which might take a long time to do.
You can publish your device as "invisible" by implementing the device
init() hook is run after the device is added through device_add(), and may be
used to safely access the device state and to spawn a worker thread. The device will
remain invisible and is guaranteed not to be removed until device_init_reply() is called,
which may be done from any thread. This meets the requirements for the binding function,
but nobody is able to use your device (because nobody knows about it yet, because it's
not visible). Now your device can perform the long operations via a background thread.
When your device is ready to service client requests, call device_init_reply() which will cause it to appear in the pathname space.
Two callouts, suspend() and resume(), are available for your device in order to support power or other resource saving features.
Both take a device context pointer and a flags argument, but the flags argument is used only in the suspend case.
||The driver should shut itself down in preparation for a reboot or shutdown of the machine|
||The driver should shut itself down in preparation for power off|
||@@@ almost nobody uses this except for a graphics controller, what does it do? @@@|
||The driver should arrange so that it can be restarted from RAM|
@@@ Yeah, I'm just guessing on the flags; they're used so little...
For documentation purposes, what should I write? That they are just hints, or that you must do something because of a given flag, or ... ?
Reference: Support functions
This section lists support functions that are provided for your driver to use.
The context block that's passed as the first argument to your driver's protocol functions is an opaque data structure. This means that in order to access the data elements, you need to call an accessor function:
|device_get_name()||Retrieves the name of the device|
|device_get_parent()||Retrieves the parent device of the device|
The following functions are used to administer the device:
|device_add()||Adds a device to a parent|
|device_async_remove()||Schedules the removal of a device and all its children|
The following functions are used to set the state of a device:
|device_state_set()||sets the given signal(s) on the device|
|device_state_clr()||clears the given signal(s) on the device|
We saw these in the
/dev/misc/demo-fifo handler above.
@@@ Notes only @@@
This section is great for things like talking about buffer management, threading, best practices, advanced options for device_add(), and so on. I think it can be somewhere between the man page ("printf is used to print a string and takes the following parameters") and an application note — I want to see examples of how to use the functions, what the arguments mean, what the impact of various design decisions is, that kind of thing.