Changes between Version 1 and Version 2 of TBR/UserManual/DriverManager


Ignore:
Timestamp:
02/16/09 21:34:06 (15 years ago)
Author:
Hellstrom
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • TBR/UserManual/DriverManager

    v1 v2  
    44
    55
    6 Created test page, will document here soon.
     6This document describes the Driver Manager patch for RTEMS-4.10. The LEON2 and the LEON3 BSP have been used
     7to test the Driver Manager, the two Hardware platforms are different when it comes to Plug and Play. The LEON2
     8systems traditionally use a hardcoded register location, whereas in LEON3 systems Plug & Play is used to find
     9all cores such a Memory controller, Timer, IRQ Controller, Ethernet MAC.
    710=  Purpose  =
    811
     12The purpose of the Driver Manager is mainly,
     13 * more easily reuse driver code
     14 * enable drivers to be written independent of how certain sevices are implemented.
     15    - interrupt handling (registeration, masking, unmasking, acknowledging)
     16    - memory space translation
     17 * Unify the way drivers are configured. The driver registration string is replaced.
     18 * build images suitable for multiple targets with different hardware present.
     19 * Hardware topology awareness.
     20 * Easier to access which drivers are loaded and what hardware is present.
     21 * An initial step towards an architecture independent PCI layer.
    922=  Overview  =
    1023
    11 =  Bus  =
    12 
     24
     25The Driver Manager fills some of the purposes the "The Linux Device Model" fills.
     26
     27It is a small and simple manager that connects a driver to a device and a device to driver resources. The
     28driver is presented an API where it is possible to get the bus frequency, manage interrupt, get base register
     29addresses, get configuration for a certain hardware device, etc.
     30
     31Once a device has been registered by a bus driver the manager tries to find a suitable driver by comparing
     32the information about the hardware (provided by the bus driver) to the driver hardware support information
     33(provided by the driver). When a driver is found that can handle the device the device and driver are
     34"united". The device is put into a list later processed by the driver manager.
     35
     36All drivers are registered before starting scanning for devices.
     37
     38The driver manager uses the concepts bus, device, driver and driver resources. A bus represents
     39a device with child devices. A device represents a certain hardware. The topmost device is a bus
     40device, the root bus device. All devices is connected to the root bus device.
     41
     42The root bus device is the first device created during driver manager initialization. It is assigned
     43a driver, the root bus driver, manually. The root bus driver must be configured by the user or
     44BSP prior to driver manager initialization. The root bus device is initialized and reports the
     45available hardware on the bus., once the root bus device is done initializing the driver manager
     46proceeds to initialize the found devices in a two step process.
     47
     48Once a device has been registered by a bus driver the manager tries to find a suitable driver by comparing
     49the information about the hardware (provided by the bus driver) to the driver hardware support information
     50(provided by the driver). When a driver is found that can handle the device the device and driver are
     51"united". The device is put into a list later processed by the driver manager (init1 stage). When the root
     52bus device driver is done initializing the driver manager proceeds to initialize the found devices in a two
     53step process.
     54
     55All devices are initialized in a two step process, called init1 and init2. Each driver provides two
     56function pointers init1 and init2 which are called in order. All device's init1 is first called, when
     57completed the driver manager enter stage two where all devices are called once more, this time
     58using the init2 function. The initialization process is separated in two stages to make it possible
     59for drivers to rely on other drivers being initialized. The order in which the devices are initialized
     60on a bus can not be known (the same order as they are registered in which often depends on how the
     61hardware is found in the Plug and Play information).
     62
     63All drivers that export some functionality to other drivers, for example memory controller drivers,
     64must initialize their API in stage1 in order to guarantee the service for other drivers when they
     65enter stage 2.
     66
     67All devices and bus devices should be found and registered in stage1. If not, they are called "hotplug"
     68devices by the driver manager. Hotplugging has currently no special support in the driver manager.
     69
     70Below are some concepts described that are used by the manager.
     71=  Bus Driver  =
     72
     73The Driver Manager needs to be informed about hardware devices present in the system, that is what the bus
     74driver does. The bus driver reads a hardcoded set up or Plug & Play information and registers devices to
     75the manager. The bus driver must provide some services in order for the drivers to the found devices to
     76function properly. The services are implemented by functions that are pointed to by a operations struct
     77making it possible for the manager driver interface to call the functions.
     78
     79The bus driver must be able to unite a hardware device with a driver.
     80
     81{{{
     82/*! Bus information. Describes a bus. */
     83struct rtems_drvmgr_bus_info {
     84        int                             bus_type;       /*!< Type of bus */
     85        struct rtems_drvmgr_bus_info    *next;          /*!< Next Bus */
     86        struct rtems_drvmgr_dev_info    *dev;           /*!< Bus device, the hardware... */
     87        void                            *priv;          /*!< Private data structure used by BUS driver */
     88        struct rtems_drvmgr_dev_info    *children;      /*!< Hardware devices on this bus */
     89        struct rtems_drvmgr_bus_ops     *ops;           /*!< Bus operations supported by this bus driver */
     90        int                             dev_cnt;        /*!< Number of devices this bus has */
     91        struct bus_res_node             *reslist;       /*!< Bus resources, head of a linked list of resources. */
     92        struct bus_mmap_entry           *mmaps;         /*!< Memory Map Translation, array of address spaces */
     93};
     94}}}
     95=  Root bus driver  =
     96
     97The driver manager needs to know what driver should handle the CPU bus. The root bus driver is
     98registered separately and before the driver manager is initialized.
    1399=  Device   =
    14100
     101Represents a hardware normally found by the bus driver. A device is created and registered by the bus
     102driver, once registered the driver manager finds the driver that supports the hardware, then a driver
     103is united with the device. Each device structure has a private pointer that the driver use to access
     104the information needed by the driver.
     105
     106{{{
     107/* States of a device */
     108#define DEV_STATE_INIT1_DONE    0x00000001      /* Init 1 Stage has been done, not neccessarily successful */
     109#define DEV_STATE_INIT2_DONE    0x00000002      /* Init 2 Stage has been done, not neccessarily successful */
     110#define DEV_STATE_INIT1_FAILED  0x00000010      /* Init 1 Stage Failed */
     111#define DEV_STATE_INIT2_FAILED  0x00000020      /* Init 2 Stage Failed */
     112#define DEV_STATE_UNITED        0x00000100      /* Device United with Device Driver */
     113#define DEV_STATE_DELETED       0x00000200      /* Device has been deleted (unregistered) */
     114
     115/*! Device information */
     116struct rtems_drvmgr_dev_info {
     117        struct rtems_drvmgr_dev_info    *next;          /*!< Next device */
     118        struct rtems_drvmgr_dev_info    *next_in_bus;   /*!< Next device on the same bus */
     119        struct rtems_drvmgr_dev_info    *next_in_drv;   /*!< Next device using the same driver */
     120
     121        struct rtems_drvmgr_drv_info    *drv;           /*!< The driver owning this device */
     122        struct rtems_drvmgr_bus_info    *parent;        /*!< Bus that this device resides on */
     123        short                           minor_drv;      /*!< Device number on driver (often minor in filesystem) */
     124        short                           minor_bus;      /*!< Device number on bus (for device separation) */
     125        unsigned int                    state;          /*!< State of this device, see DEV_STATE_* */
     126        char                            *name;          /*!< Name of Device Hardware */
     127        void                            *priv;          /*!< Pointer to driver private device structure */
     128        void                            *businfo;       /*!< Host bus specific information */
     129        struct rtems_drvmgr_bus_info    *bus;           /*!< Pointer to bus, set only if this is a bus */
     130};
     131}}}
    15132=  Driver   =
    16133
    17 =  Bus Driver   =
    18 
     134
     135Driver for a hardware device. It uses the driver manager services provided, which in turn rely on the
     136bus driver. The driver holds information to identify a hardware device, it tells the driver manager what
     137kind of bus is supported and perhaps the Plug & Play Vendor and Device ID used to identify certain hardware.
     138
     139Drivers are called twice to initialize a hardware device. Init1 and Init2 stages. A delete function may
     140optionally be defined if the driver can handle removing of hardware.
     141
     142{{{
     143/*! Driver operations, function pointers. */
     144struct rtems_drvmgr_drv_ops {
     145        rtems_status_code       (*init1)(struct rtems_drvmgr_dev_info *);       /*! Function doing Init Stage 1 of a hardware device */
     146        rtems_status_code       (*init2)(struct rtems_drvmgr_dev_info *);       /*! Function doing Init Stage 2 of a hardware device */
     147        rtems_status_code       (*delete)(struct rtems_drvmgr_dev_info *);      /*! Function called when device instance is to be removed */
     148};
     149
     150/*! Information about a driver used during registration */
     151struct rtems_drvmgr_drv_info {
     152        struct rtems_drvmgr_drv_info    *next;          /*!< Next Driver */
     153        struct rtems_drvmgr_dev_info    *dev;           /*!< Devices using this driver */
     154
     155        unsigned long long              drv_id;         /*!< Unique Driver ID */
     156        char                            *name;          /*!< Name of Driver */
     157        int                             bus_type;       /*!< Type of Bus this driver supports */
     158        struct rtems_drvmgr_drv_ops     *ops;           /*!< Driver operations */
     159        unsigned int                    dev_cnt;        /*!< Number of devices in dev */
     160};
     161}}}
    19162=  Driver Resource  =
    20163
    21 =  Operation  =
    22 
     164A driver resource is a resource used by a driver for a certain device instance. The resource may
     165be integer with value 65 called "numberTxDescriptors". The resources are grouped together in
     166arrays targeting one device instance. The resources are assigned to one or multiple buses making
     167it possible for the drivers to find whose hardware device is situated on that very bus. Multiple
     168hardware devices of the same type is separated by their bus unit number which is always the
     169same between starts. The number usually comes from the order the device if found in the plug
     170and play information. Below is a typical bus resource definition grlib_drv_resource configuring
     171two GRSPW device drivers. The second GRSPW core will have double the amount of descriptors
     172than the first.
     173
     174{{{
     175/*** Resource definitions ***
     176 *
     177 * Overview of structures:
     178 *  All bus resources entries (bus_res_node) are linked together for a bus (bus_info->reslist).
     179 *  One bus resource entry has a pointer to an array of driver resources (drv_res). One driver
     180 *  resouces is made out of an array of keys (drv_res_key). All keys belongs to the same driver
     181 *  and harwdare device. Each key has a Name, Type ID and Data interpreted differently
     182 *  depending on the Type ID (union key_value).
     183 *
     184 */
     185
     186/* Key Data Types */
     187#define KEY_TYPE_NONE           0
     188#define KEY_TYPE_INT            1
     189#define KEY_TYPE_STRING         2
     190#define KEY_TYPE_POINTER        3
     191
     192#define KEY_EMPTY       {NULL, KEY_TYPE_NONE, {0}}
     193#define RES_EMPTY       {0, 0, NULL}
     194#define MMAP_EMPTY      {0, 0, 0}
     195
     196/*! Union of different values */
     197union key_value {
     198        unsigned int            i;              /*!< Key data type UNIGNED INTEGER */
     199        char                    *str;           /*!< Key data type STRING */
     200        void                    *ptr;           /*!< Key data type ADDRESS/POINTER */
     201};
     202
     203/* One key. Holding information relevant to the driver. */
     204struct drv_res_key {
     205        char                    *key_name;      /* Name of key */
     206        int                     key_type;       /* How to interpret key_value */
     207        union key_value         key_value;      /* The value or pointer to the value */
     208};
     209
     210/*! Bus resource entry, Driver resources for a certain device instance, containing a number of keys
     211 * Where each key hold the data of interest.
     212 */
     213struct drv_res {
     214        unsigned long long      drv_id;         /*!< Identifies the driver this resource is aiming */
     215        int                     minor_bus;      /*!< Indentifies a specfic device */
     216        struct drv_res_key      *keys;          /*!< First key in key array */
     217};
     218
     219/*! Bus resource list node */
     220struct bus_res_node {
     221        struct bus_res_node     *next;          /*!< Next resource node in list */
     222        struct drv_res          *resource;      /*!< Array of resources, one per device instance */
     223};
     224}}}
     225
     226{{{
     227/* GRSPW0 resources */
     228struct drv_res_key grlib_grspw0_res[] =
     229
     230{
     231        {"txDesc", KEY_TYPE_INT, {(unsigned int)16}},
     232        {"rxDesc", KEY_TYPE_INT, {(unsigned int)32}},
     233        KEY_EMPTY
     234};
     235/* GRSPW1 resources */
     236struct drv_res_key grlib_grspw1_res[] =
     237
     238{
     239        {"txDesc", KEY_TYPE_INT, {(unsigned int)32}},
     240        {"rxDesc", KEY_TYPE_INT, {(unsigned int)64}},
     241        KEY_EMPTY
     242};
     243/* GRLIB Plug & Play bus driver resources */
     244struct drv_res grlib_drv_resources[] =
     245
     246{
     247        {DRIVER_AMBAPP_GAISLER_GRSPW_ID, 0, &grlib_grspw0_res[0]},
     248        {DRIVER_AMBAPP_GAISLER_GRSPW_ID, 1, &grlib_grspw1_res[0]},
     249        RES_EMPTY
     250};
     251}}}
     252
     253The driver to which the resources belong is identified by a unique driver id. The driver id must be
     254unique for the bus type, in this case AMBAPP (AMBA Plug & Play). The device instances are
     255separated by the bus unit number, second entry in the grlib_drv_resources.
    23256=  Using  =
    24257
    25258=  Configuration  =
    26259
     260
     261The following may be configured,
     262 - Driver resources per bus.
     263 - Root bus driver
    27264 - Driver table.
    28  - Driver resources per bus.
     265
     266The driver manager is configured by selecting drivers used by the driver manager and by
     267registering a root bus prior to driver manager initialization described in the next section. Drivers
     268may also be configured by using driver resources, see section "Driver Resource".
     269
     270The driver resources are registered different depending on bus driver.
     271
     272The root bus device driver is registered by calling root_drv_register, the root bus driver may
     273provide a function doing this, in that case one must call that function instead. For example
     274drv_mgr_grlib_init register the GRLIB-AMBA Plug & Play Bus as the root bus driver and also
     275assigns the driver resources for the root bus.
     276
     277The drivers are selected by defining the array drv_mgr_drivers, it contains one function pointer
     278per driver that is responsible to register one or more drivers. The drv_mgr_drivers can be set up
     279by defining CONFIGURE_INIT, selecting the appropriate drivers and including
     280drv_mgr/drvmgr_confdefs.h. This approach is similar to configuring a standard RTEMS project
     281using rtems/confdefs.h. Below is an example how to select drivers.
     282
     283{{{
     284#include <rtems.h>
     285#include <bsp.h>
     286
     287#define CONFIGURE_INIT
     288
     289/* Standard RTEMS set up */
     290#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
     291#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
     292#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
     293#define CONFIGURE_MAXIMUM_DRIVERS 32
     294#include <rtems/confdefs.h>
     295
     296/* Driver manager set up */
     297#define CONFIGURE_DRIVER_AMBAPP_GAISLER_GRETH
     298#define CONFIGURE_DRIVER_AMBAPP_GAISLER_GRSPW
     299#define CONFIGURE_DRIVER_AMBAPP_GAISLER_GRCAN
     300#define CONFIGURE_DRIVER_AMBAPP_GAISLER_OCCAN
     301#define CONFIGURE_DRIVER_AMBAPP_GAISLER_B1553BRM
     302#define CONFIGURE_DRIVER_AMBAPP_GAISLER_APBUART
     303#define CONFIGURE_DRIVER_AMBAPP_MCTRL
     304#define CONFIGURE_DRIVER_AMBAPP_GAISLER_PCIF
     305#define CONFIGURE_DRIVER_AMBAPP_GAISLER_GRPCI
     306#define CONFIGURE_DRIVER_PCI_GR_RASTA_IO
     307#define CONFIGURE_DRIVER_PCI_GR_RASTA_TMTC
     308#define CONFIGURE_DRIVER_PCI_GR_701
     309#include <drv_mgr/drv_manager_confdefs.h>
     310}}}
    29311=  Initialization  =
    30312
    31 = = Driver Interface  ==
    32 
    33 =  = TODO ==
    34 
    35 
    36 === BSP ===
     313The driver manager is initialized by the user calling rtems_drvmgr_init() after the root bus driver
     314has been registered. After the driver manager has been initialized all devices have been united
     315with their drivers. The driver are ready for usage.
     316
     317The initialization cannot currently be done before the I/O Manager intialization, this is one of the
     318reasons it is initialized in the Init() task as below.
     319
     320/* Initializing Driver Manager */
     321printf("Initializing manager\n");
     322if ( rtems_drvmgr_init() ) {
     323        printf("Driver manager Failed to initialize\n");
     324        exit(-1);
     325}
     326=  Driver Interface  =
     327
     328The Driver Interface.
     329
     330{{{
     331/*! Get Device pointer from Driver and Driver minor number
     332 *
     333 * \param drv         Driver the device is united with.
     334 * \param minor       Driver minor number assigned to device.
     335 * \param pdev        Location where the Device point will be stored.
     336 * \return            Zero on success. -1 on failure, when device was not found in driver
     337 *                    device list.
     338 */
     339int rtems_drvmgr_get_dev(
     340        struct rtems_drvmgr_drv_info *drv,
     341        int minor,
     342        struct rtems_drvmgr_dev_info **pdev);
     343
     344/*! Get Bus frequency in Hertz. Frequency is stored into address of freq_hz.
     345 *
     346 * \param dev        The Device to get Bus frequency for.
     347 * \param freq_hz    Location where Bus Frequency will be stored.
     348 */
     349int rtems_drvmgr_get_freq(struct rtems_drvmgr_dev_info *dev, unsigned int *freq_hz);
     350
     351/*! Get device name prefix, this name can be used to register a unique name in the
     352 *  filesystem or to get an idea where the device is located.
     353 *
     354 * \param dev         The Device to get the device Prefix for.
     355 * \param dev_prefix  Location where the prefix will be stored.
     356 */
     357int rtems_drvmgr_get_dev_prefix(struct rtems_drvmgr_dev_info *dev, char *dev_prefix);
     358
     359/*! Register an interrupt handler.
     360 *  \param index      Index is used to identify the IRQ number if hardware has multiple IRQ sources.
     361 *                    Normally Index is set to 0 to indicated the first and only IRQ source.
     362 *  \param func       Interrupt Service Routine.
     363 *  \param arg        Optional ISR argument.
     364 */
     365int rtems_drvmgr_interrupt_register(
     366        struct rtems_drvmgr_dev_info *dev,
     367        int index,
     368        void (*func)(int irq, void *arg),
     369        void *arg);
     370
     371/*! Enable (unmask) an interrupt source
     372 *
     373 *  \param dev        Device to enable interrupt for.
     374 *  \param index      Index is used to identify the IRQ number if hardware has multiple IRQ sources.
     375 *                    Normally Index is set to 0 to indicated the first and only IRQ source.
     376 */
     377int rtems_drvmgr_interrupt_enable(struct rtems_drvmgr_dev_info *dev, int index);
     378
     379/*! Disable (mask) an interrupt source
     380 *
     381 *  \param dev        Device to disable interrupt for.
     382 *  \param index      Index is used to identify the IRQ number if hardware has multiple IRQ sources.
     383 *                    Normally Index is set to 0 to indicated the first and only IRQ source.
     384 */
     385int rtems_drvmgr_interrupt_disable(struct rtems_drvmgr_dev_info *dev, int index);
     386
     387/*! Clear (ACK) pending interrupt
     388 *
     389 *  \param dev        Device to clear interrupt for.
     390 *  \param index      Index is used to identify the IRQ number if hardware has multiple IRQ sources.
     391 *                    Normally Index is set to 0 to indicated the first and only IRQ source.
     392 */
     393int rtems_drvmgr_interrupt_clear(struct rtems_drvmgr_dev_info *dev, int index);
     394
     395/*! Translate address
     396 * 1. From CPU local bus to a remote bus for example a PCI target (from_remote_to_cpu = 0)
     397 * 2. From remote bus to CPU local bus (from_remote_to_cpu = 1)
     398 *
     399 * src_address the address to translate, dst_address is where the translated address is stored.
     400 *
     401 * \param dev                  Device to translate addresses for.
     402 * \param from_remote_to_cpu   Selection tranlation direction.
     403 * \param src_address          Address to translate
     404 * \param dst_address          Location where translated address is stored.
     405 *
     406 * Returns -1 if unable to translate. If no map is present src_address is translated 1:1 (just copied).
     407 */
     408int rtems_drvmgr_mmap_translate(
     409        struct rtems_drvmgr_dev_info *dev,
     410        int from_remote_to_cpu,
     411        void *src_address,
     412        void **dst_address);
     413}}}
     414=  TODO  =
     415
     416=  BSP  =
    37417
    38418Changes to BSPs:
    39 
    40 === I/O manager ===
    41 
    42 Changes to I/O Manger:
    43 
    44 === Init Driver Manager ===
    45 
    46 Initialize the Driver manager before I/O Manager initialization.
     419 * Add support to BSP to register root bus
     420 * Make driver resources on the root bus weak so that the user can override them.
     421= = RTEMS  ==
     422
     423 * Make I/O Manager handle regestering I/O Drivers before I/O Manager is initialized.
     424=  == Driver Manager ===
     425
     426 *  Initialize the Driver manager before I/O Manager initialization.