Temporarily merged former pnp_driver.h and pnp_bus.h into device_manager.h.

This will be changed at a later time.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7487 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2004-05-10 13:15:09 +00:00
parent a94fb8e252
commit 87611252cb

View File

@ -127,8 +127,9 @@
#ifndef _DEVICE_MANAGER_H
#define _DEVICE_MANAGER_H
#include <module.h>
#include <TypeConstants.h>
#include <Drivers.h>
#include <module.h>
// type of I/O resource
@ -155,6 +156,26 @@ typedef struct {
// ISA DMA channel: must be 1
} io_resource;
// attribute of device node
typedef struct {
const char *name;
type_code type; // for supported types, see value
union {
uint8 ui8; // B_UINT8_TYPE
uint16 ui16; // B_UINT16_TYPE
uint32 ui32; // B_UINT32_TYPE
uint64 ui64; // B_UINT64_TYPE
const char *string; // B_STRING_TYPE
struct { // B_RAW_TYPE
void *data;
size_t len;
} raw;
} value;
} pnp_node_attr;
// handle of PnP node
typedef struct pnp_node_info *pnp_node_handle;
// handle of acquired I/O resource
typedef struct io_resource_info *io_resource_handle;
@ -163,6 +184,8 @@ typedef struct io_resource_info *io_resource_handle;
typedef struct pnp_node_attr_info *pnp_node_attr_handle;
typedef struct pnp_driver_info pnp_driver_info;
// interface of PnP manager
typedef struct device_manager_info {
module_info minfo;
@ -357,4 +380,227 @@ typedef struct device_manager_info {
// modulename of PnP manager
#define DEVICE_MANAGER_MODULE_NAME "sys/device_manager/v1"
// former pnp_driver.h
/*
Copyright (c) 2003-04, Thomas Kurschel
Required interface of PnP drivers
In contrast to standard BeOS drivers, PnP drivers are normal modules
having the interface described below.
Every device is described by its driver via a PnP node with properties
described in PnP Node Attributes. Devices are organized in a hierarchy,
e.g. a devfs device is a hard disk device that is connected to a
controller, which is a PCI device, that is connected to a PCI bus.
Every device is connected to its lower-level device via a parent link
stored in its Node. The higher-level is called the consumer of the
lower-level device. If the lower-level device gets removed, all its
consumers are removed too.
In our example, the hierarchy is
devfs device -> hard disk -> controller -> PCI device -> PCI bus
If the PCI bus is removed, everything up to including the devfs device
is removed too.
The driver hierarchy is constructed bottom-up, i.e. the lower-level
driver searches for a corresponding consumer, which in turns searches
for its consumer and so on. The lowest driver is usually something like
a PCI bus, the highest driver is normally a devfs entry (see pnp_devfs.h).
Registration of devices and the search for appropriate consumers is
done via the pnp_manager (see pnp_manager.h).
When a potential consumer is found, it gets informed about the new
lower-level device and can either refuse its handling or accept it.
On accept, it has to create a new node with the lower-level device
node as its parent.
Loading of drivers is done on demand, i.e. if the consumer wants to
access its lower-level device, it explicitely loads the corresponding
driver, and once it doesn't need it anymore, the lower-level driver
must be unloaded. Usually, this process happens recursively, i.e. in
our example, the hard disk driver loads the controller driver, which
loads the PCI device driver which loads the PCI bus driver. The same
process applies to unloading.
Because of this dynamic loading, drivers must store persistent data
in the node of their devices. Please be aware that you cannot modify
a node once published.
If a device gets removed, you must unregister its node. As said, the
PnP manager will automatically unregister all consumers too. The
corresponding drivers are notified to stop talking to their lower-level
devices and to terminate running requests. Normally, you want to use a
dedicated variable that is verified at each call to make sure that the
parent is still there. The notification is done independantly of the
driver being loaded by its consumer(s) or not. If it isn't loaded,
the notification callback gets NULL as the device cookie; normally, the
driver returns immediately in this case. As soon as both the device
is removed and the driver is unloaded, device_cleanup gets called to
free resources that couldn't be safely removed in device_removed when
the driver was still loaded.
If a device has exactly one consumer, they often interact in some way.
To simplify that, the consumer can pass a user-cookie to its parent
during load. In this case, it's up to the parent driver to get a
pointer to the interface of the consumer. Effectively, such consumers
have one interface for their consumers (base on pnp_driver_info), and
a another for their parents (with a completely driver-specific
structure).
In terms of synchronization, loading/unloading/remove-notifications
are executed synchroniously, i.e. if e.g. a device is to be unloaded
but the drive currently handles a remove-notification, the unloading
is delayed until the nofication callback returns. If multiple consumers
load a driver, the driver gets initialized only once; subsequent load
requests increase an internal load count only and return immediately.
In turn, unloading only happens once the load count reaches zero.
*/
// interface of PnP driver
struct pnp_driver_info {
module_info minfo;
status_t (*init_device)(pnp_node_handle node, void *user_cookie, void **cookie);
// driver is loaded.
// node - node of device
// user_cookie - cookie passed by loading driver
// cookie - cookie issued by this driver
status_t (*uninit_device)(void *cookie);
// driver gets unloaded.
status_t (*probe)(pnp_node_handle parent);
// parent was added or is rescanned.
// check whether this parent is supported and register
// any consumer device. Dynamic consumers must return
// B_OK if they support this parent. All other return
// values are ignored.
void (*device_removed)(pnp_node_handle node, void *cookie);
// a device node, registered by this driver, got removed.
// if the driver wasn't loaded when this happenes, no (un)init_device
// is called and thus <cookie> is NULL;
void (*device_cleanup)(pnp_node_handle node);
// a device node, registered by this driver, got removed and
// the driver got unloaded
};
// standard attributes:
// module name of driver (required, string)
#define PNP_DRIVER_DRIVER "driver"
// type of driver (required, string)
#define PNP_DRIVER_TYPE "type"
// module name of fixed consumer - see pnp_manager.h (optional, string)
// append "/0", "/1" etc. if there are multiple fixed consumers
#define PNP_DRIVER_FIXED_CONSUMER "consumer/fixed"
// dynamic consumers pattern - see pnp_manager.h (optional, string)
// append "/0", "/1" etc. if there are multiple dynamic consumers
#define PNP_DRIVER_DYNAMIC_CONSUMER "consumer/dynamic"
// connection of parent the device is attached to (optional, string)
// there can be only one device per connection
#define PNP_DRIVER_CONNECTION "connection"
// pattern device identifier (optional, string)
// it is expanded and used to detect changed devices
#define PNP_DRIVER_DEVICE_IDENTIFIER "device_identifier"
// driver must not be loaded during rescan (optional, uint8)
// if != 0, driver must not be loaded during rescan
// nor can rescan be started when driver is loaded
// if the device uses I/O resources, you _must_ set this
// flag as the rescan would always fail if the driver is loaded
// due to resource contention
#define PNP_DRIVER_NO_LIVE_RESCAN "no_live_rescan"
// never rescan this device (optional, uint8)
// if != 0, device is never checked during rescan
#define PNP_DRIVER_NEVER_RESCAN "never_rescan"
// keep driver loaded loaded (optional, uint8)
// if != 0, the driver is loaded automatically whenever the node
// is registered and unloaded whenever the node is unregistered.
// if = 1, driver is temporarily unloaded during rescan
// if = 2, driver is not unloaded during rescan
// avoid the second case (2) as this makes replacing the driver
// impossible without a reboot.
#define PNP_DRIVER_ALWAYS_LOADED "always_loaded"
// former pnp_bus.h
/*
Copyright (c) 2003-04, Thomas Kurschel
Required interface of PnP bus drivers
Busses consist of two node layers: the lower layer defines the bus,
the upper layer defines the abstract devices connected to the bus.
Both layers are handled by a bus manager. Actual device nodes are
on top of abstract device nodes.
E.g. if we have a PCI bus with an IDE controller on it, we get
IDE controller -> PCI device -> PCI bus
with:
IDE controller = actual device node
PCI device = abstract device node
PCI bus = bus node
The PCI bus manager establishes both the PCI devices and the PCI busses.
Abstract device nodes act as a gateway between actual device nodes
and the corresponding bus node. They are constructed by the bus
node driver via its rescan() hook. To identify a bus node, define
PNP_BUS_IS_BUS as an attribute of it. As a result, the PnP manager
will call the rescan() method of the bus driver whenever the
bus is to be rescanned. Afterwards, all possible dynamic consumers
are informed as done for normal nodes.
Normally, potential device drivers are notified immediately when
rescan() registers a new abstract device node. But sometimes, device
drivers need to know _all_ devices connected to the bus for correct
detection. To ensure this, the bus node must define
PNP_BUS_NOTIFY_CONSUMERS_AFTER_RESCAN. In this case, scanning for
consumers is postponed until rescan() has finished.
If hot-plugging of devices can be detected automatically (e.g. USB),
you should define PNP_DRIVER_ALWAYS_LOADED, so the bus driver is
always loaded and thus capable of handling hot-plug events generated
by the bus controller hardware.
*/
// interface of PnP bus
typedef struct pnp_bus_info {
pnp_driver_info dinfo;
// (re)scan bus and register all devices.
// driver is always loaded during this call, but other hooks may
// be called concurrently
status_t (*rescan) ( void *cookie );
} pnp_bus_info;
// standard attributes:
// PnP bus identification (required, uint8)
// define this to let the PnP manager know that this is a PnP bus
// the actual content is ignored
#define PNP_BUS_IS_BUS "bus/is_bus"
// defer searching for consumers (optional, uint8)
// if != 0, probe() of consumers is called after rescan() of bus
// else, probe() of consumers is called during rescan() of bus
// normally, consumers are informed about a new device as soon as
// it is registered by rescan(), i.e. not all devices may have been
// detected and registered yet;
// with this flag, detection of consumers is postponed until
// rescan() has finished, i.e. when all devices are registered
#define PNP_BUS_DEFER_PROBE "bus/defer_probe"
#endif /* _DEVICE_MANAGER_H */