Changes between Version 3 and Version 4 of TBR/UserManual/DriverManager


Ignore:
Timestamp:
Jun 11, 2009, 6:16:26 PM (10 years ago)
Author:
Hellstrom
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • TBR/UserManual/DriverManager

    v3 v4  
    66This document describes the Driver Manager patch for RTEMS-4.10. The LEON2 and the LEON3 BSP have been used
    77to test the Driver Manager, the two Hardware platforms are different when it comes to Plug and Play. The LEON2
    8 systems traditionally use a hardcoded register location, whereas in LEON3 systems Plug & Play is used to find
    9 all cores such a Memory controller, Timer, IRQ Controller, Ethernet MAC.
     8systems traditionally use a hardcoded register location and IRQ assignment, whereas in LEON3 systems
     9Plug & Play is used to find all cores such a Memory controller, Timer, IRQ Controller, Ethernet MAC, etc. The
     10Plug & Play information in a LEON3 system contain IRQ number, register base addresses, memory space regions
     11etc.
    1012=  Purpose  =
    1113
     
    1315 *  more easily reuse driver code
    1416 *  enable drivers to be written independent of how certain services are implemented.
    15   *  interrupt handling (registration, masking, unmasking, acknowledging)
     17  *  interrupt handling (registration, masking, unmasking, clearing/acknowledging when level sensitive)
    1618  *  memory space translation
    17   *  Bus information (Bus frequency, Snooping/Cache options)
    18  *  Unify the way drivers are configured. The driver registration string is replaced.
    19  *  build images suitable for multiple targets with different hardware present.
    20  *  Hardware topology awareness.
    21  *  Easier to access which drivers are loaded and what hardware is present.
    22  *  An initial step towards an architecture independent PCI layer.
     19  *  Bus information (Bus/Core frequency, Snooping/Cache options, Location in system)
     20 *  Unify the way drivers are configured. The driver registration string is replaced with "driver resources" managed per bus.
     21 *  build images suitable for multiple targets with different hardware present, for example different PCI Host controllers.
     22 *  Hardware bus topology awareness in software, this makes it easier to access which drivers are loaded and what hardware is present.
    2323=  Overview  =
    2424
     
    3030addresses, get configuration for a certain hardware device, etc.
    3131
     32A device is situated on a bus, a driver for a bus is called a bus driver. The bus driver tells the driver
     33manager about new devices by a procedure called device registration, basically the bus driver fills in a
     34data structure describing a specific hardware device and gives it to the manager.
     35
    3236Once a device has been registered by a bus driver the manager tries to find a suitable driver by comparing
    33 the information about the hardware (provided by the bus driver) to the driver hardware support information
    34 (provided by the driver). When a driver is found that can handle the device the device and driver are
    35 "united". The device is put into a list later processed by the driver manager.
    36 
    37 All drivers are registered before starting scanning for devices.
     37the information about the hardware (provided by the bus driver from Plug & Play) to the driver hardware
     38support information (provided by the driver). When a driver is found that can handle the hardware device
     39the device and driver are "united". The device is put into a list later processed by the driver manager.
     40Each device in the list is picked out and initialized in a two step process (init1 and init2) by calling
     41the device driver's functions, init1() and init2(). If the device driver happens to be a bus driver more
     42devices will be registered and put at the end of the device list. When there is no more devices left in the
     43list the manager will complete.
     44
     45All device drivers and bus drivers are registered before starting scanning for devices.
    3846
    3947The driver manager uses the concepts bus, device, driver and driver resources. A bus represents
    40 a device with child devices. A device represents a certain hardware. The topmost device is a bus
    41 device, the root bus device. All devices is connected to the root bus device.
     48a device with child devices. A device represents a certain hardware situated on a bus. A driver
     49handles one or more devices of the same hardware type. Driver resources are configuration parameters
     50targeted one specific driver and one specific device, the resouces consists of an array with name, type
     51and value. The resources are hardcoded at compile time by the user.
     52
     53The topmost device is a bus device, the root bus device. The driver for that device is called the root
     54bus driver. All devices are connected to the root bus device.
     55=  Initialization steps  =
     56
    4257
    4358The root bus device is the first device created during driver manager initialization. It is assigned
    4459a driver, the root bus driver, manually. The root bus driver must be configured by the user or
    45 BSP prior to driver manager initialization. The root bus device is initialized and reports the
    46 available hardware on the bus., once the root bus device is done initializing the driver manager
    47 proceeds to initialize the found devices in a two step process.
     60BSP prior to driver manager initialization.
     61
     62After all drivers have been registered to the driver manager the device initialization begins. The root
     63bus device is initialized and reports the available hardware devices on the bus. Once the root bus device
     64is done initializing, the driver manager proceeds to initialize the found devices in a two step process.
    4865
    4966Once a device has been registered by a bus driver the manager tries to find a suitable driver by comparing
     
    5572
    5673All devices are initialized in a two step process, called init1 and init2. Each driver provides two
    57 function pointers init1 and init2 which are called in order. All device's init1 is first called, when
     74function pointers init1 and init2 which are called in order. All devices' init1 is first called, when
    5875completed the driver manager enter stage two where all devices are called once more, this time
    5976using the init2 function. The initialization process is separated in two stages to make it possible
    60 for drivers to rely on other drivers being initialized. The order in which the devices are initialized
    61 on a bus can not be known (the same order as they are registered in which often depends on how the
    62 hardware is found in the Plug and Play information).
     77for drivers to rely on other drivers services being initialized. The order in which the devices are
     78initialized on a bus can not be known, it is the same order as they were registered in which often
     79depends on how the hardware is found in the Plug and Play information.
    6380
    6481All drivers that export some functionality to other drivers, for example memory controller drivers,
     
    7087
    7188Below are some concepts described that are used by the manager.
     89=  Driver Interface  =
     90
     91The driver manager provides the drivers with a common interface independent of bus type. In order for the
     92driver manager to implement one interface it relies on the bus driver to make bus dependent operations. The
     93bus drivers are the core of the functionality provided by the driver manager.
     94
     95It may be bus dependent how to find the bus frequency, manage interrupts (level sensitive?), Plug & Play
     96information, translate addresses, find a driver for a device etc.
     97
     98When the driver manager interface is not enough for a bus type, the bus driver may implement functions of
     99its own extending the driver manager interface but still taking advantage of the device and driver structure
     100introduced by the manager. Perhaps a stupid example but anyway, the example below shows how a PCI bus
     101driver could make PCI Read Configuration Space function simpler by removing the knowledge of Bus,Slot,Func
     102in a PCI device driver, instead of calling pci_cfg_read_word directly:
     103
     104{{{
     105int pci_cfg_read_word(int bus, int slot, int func, int offset, unsigned int *buf);
     106
     107int pcimgr_cfg_read_word(rtems_drvmgr_dev_info *dev, int offset, unsigned int *buf)
     108{
     109        /* Get Bus specific information previously prepared by bus driver */
     110        struct pci_dev_info *pciinfo = (struct pci_dev_info *)dev->businfo;
     111
     112        return pci_cfg_read_word(pciinfo->bus, pciinfo->slot, pciinfo->func, offset, buf);
     113}
     114}}}
    72115=  Bus Driver  =
    73116
    74117The Driver Manager needs to be informed about hardware devices present in the system, that is what the bus
    75118driver does. The bus driver reads a hardcoded set up or Plug & Play information and registers devices to
    76 the manager. The bus driver must provide some services in order for the drivers to the found devices to
    77 function properly. The services are implemented by functions that are pointed to by a operations struct
    78 making it possible for the manager driver interface to call the functions.
    79 
    80 The bus driver must be able to unite a hardware device with a driver.
     119the manager. The bus driver must also provide function pointers to a couple of services in order for
     120the driver manager to present a common driver interface to device drivers.
     121
     122One of the most important services is the ability to unite a hardware device with a driver, for this to happen
     123a driver must provide information about what hardware is supported so that the bus driver can compare that with
     124the found hardware.
    81125
    82126{{{
     
    93137        struct rtems_drvmgr_mmap_entry  *mmaps;         /*!< Memory Map Translation, array of address spaces */
    94138};
    95 
    96139}}}
    97140=  Root bus driver  =
     
    114157#define DEV_STATE_UNITED        0x00000100      /* Device United with Device Driver */
    115158#define DEV_STATE_DELETED       0x00000200      /* Device has been deleted (unregistered) */
    116 
     159#define DEV_STATE_IGNORED       0x00000400      /* Device was ignored according to user's request, the device
     160                                                 * was never reported to it's driver (as expected).
     161                                                 */
    117162/*! Device information */
    118163struct rtems_drvmgr_dev_info {
     
    130175        void                            *businfo;       /*!< Host bus specific information */
    131176        struct rtems_drvmgr_bus_info    *bus;           /*!< Pointer to bus, set only if this is a bus */
    132 };
     177        int                             error;          /*!< Error state returned by driver */
     178};
     179}}}
     180==  Device State  ==
     181
     182During the initialization of a device the initialization level (init1 or init2)
     183changes, to hold that information a device state integer is maintained for each
     184device. The device state is updated when,
     185 ¤ Assigning a driver
     186 ¤ Init1 is completed or erroneous
     187 ¤ Init2 is completed or erroneous
     188 ¤ A device is deleted by the user
     189 ¤ A device must be ignored by user's request
     190
     191The manager uses the state internaly but it may also be of improtance to the
     192user when a device failed.
     193==  Device Error Handling  ==
     194
     195During the initialization steps of a device the driver manager may not complete
     196the initialization because of,
     197 ¤ No suitable driver found
     198 ¤ Device was requested to be ignored by user
     199 ¤ Driver failed to take device into init1 or init2 dur to an error
     200
     201The driver manager removes the device from further initialization and instead of
     202freeing the device structure the device is put into a separate list (the inactive
     203list) and the device state is updated accordingly. When initialization fails the
     204error field in the device structure is updated indicating the error more in
     205detail.
     206
     207A user may process all failed devices on the inactive list to determined if the
     208error was acceptable or not.
     209==  Unregistering a device  ==
     210
     211A device may also be unregistered due to device error (parity error on the PCI
     212bus for example) or hardware was removed (hot-plug system). A device is
     213unregistered by calling rtems_drvmgr_dev_unregister. The device is moved from
     214the current list to the inactive list (delete=0) or it may be removed completely
     215to avoid memory exhaustion (delete=1).
     216
     217{{{
     218/*! Remove a device, and all its children devices if device is a bus device. The device
     219 *  driver will be requested to remove the device and once gone from bus, device and
     220 *  driver list the device is put into a inactive list for debugging (this is optional
     221 *  by using delete argument).
     222 *
     223 * Removing the Root Bus Device is not supported.
     224 *
     225 * \param delete If non-zero the device will be deallocated, and not put into the
     226 *               inacitve list.
     227 */
     228extern int rtems_drvmgr_dev_unregister(struct rtems_drvmgr_dev_info *dev, int delete);
    133229}}}
    134230=  Driver   =
     
    140236
    141237Drivers are called twice to initialize a hardware device. Init1 and Init2 stages. A delete function may
    142 optionally be defined if the driver can handle removing of hardware.
     238optionally be defined if the driver can handle removing of hardware Also a info function to request information
     239such as device name, type of driver, statistcs, current register content etc for interactive information
     240printing from for example the shell.
    143241
    144242{{{
     
    148246        rtems_status_code       (*init2)(struct rtems_drvmgr_dev_info *);       /*! Function doing Init Stage 2 of a hardware device */
    149247        rtems_status_code       (*delete)(struct rtems_drvmgr_dev_info *);      /*! Function called when device instance is to be removed */
     248        rtems_status_code       (*info)(struct rtems_drvmgr_dev_info *, int, int);/*! Function called to request information about a device or driver */
    150249};
    151250
     
    162261};
    163262}}}
     263==  Driver ID  ==
     264
     265All drivers must have a unique ID, it may be created by using one of the
     266supported devices's ID. Often a device have a VENDOR:DEVICE unique for the bus.
     267A driver ID is created by combining a bus dependent ID and the bus type number:
     268
     269From drvmgr.h:
     270{{{
     271/*** Bus indentification ***/
     272#define DRVMGR_BUS_TYPE_NONE 0          /* Not a valid bus */
     273#define DRVMGR_BUS_TYPE_ROOT 1          /* Hard coded bus */
     274#define DRVMGR_BUS_TYPE_PCI 2           /* PCI bus */
     275#define DRVMGR_BUS_TYPE_AMBAPP 3        /* AMBA Plug & Play bus */
     276
     277/* 64-bit identification integer definition
     278 *  ¤ Bus ID 8-bit [7..0]
     279 *  ¤ Reserved 8-bit field [63..56]
     280 *  ¤ Device ID specific for bus type 48-bit [55..8]  (Different buses have different unique identifications for hardware/driver.)
     281 *
     282 * ID Rules
     283 *  ¤ A root bus driver must always have device ID set to 0. There can only by one root bus driver
     284 *    for a certain bus type.
     285 *  ¤ A Driver ID must identify a unique hardware core
     286 *
     287 */
     288
     289/* Bus ID Mask */
     290#define DRIVER_ID_BUS_MASK 0x00000000000000FFULL
     291
     292/* Reserved Mask for future use */
     293#define DRIVER_ID_RSV_MASK 0xFF00000000000000ULL
     294
     295/* Reserved Mask for future use */
     296#define DRIVER_ID_DEV_MASK 0x00FFFFFFFFFFFF00ULL
     297
     298/* Set Bus ID Mask. */
     299#define DRIVER_ID(busid, devid) \
     300        (unsigned long long)( (((unsigned long long)(devid) << 8) & DRIVER_ID_DEV_MASK) | ((unsigned long long)(busid) & DRIVER_ID_BUS_MASK) )
     301}}}
     302
     303From AMBA Plug & Play bus, ambapp_bus.h:
     304{{{
     305/* GRLIB AMBA Plug&Play Driver ID generation */
     306#define DRIVER_AMBAPP_ID(vendor, device) \
     307        DRIVER_ID(DRVMGR_BUS_TYPE_AMBAPP, ((((vendor) & 0xff) << 16) | ((device) & 0xfff)))
     308
     309/*** Gaisler Hardware Device Driver IDs ***/
     310#define DRIVER_AMBAPP_GAISLER_GRETH_ID          DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_ETHMAC)
     311}}}
     312
     313In the above example VENDOR_GAISLER and GAISLER_GRETH are IDs assigned by the
     314GRLIB Bus domain.
     315
     316The Driver ID and a device unit number is used when assigning driver resources
     317to a certain device. The driver resources must be in a format the driver can
     318understand, which the driver ID makes sure of, and the driver must not use
     319another device's resources, which the unit/core number makes sure of.
    164320=  Driver Resource  =
    165321
    166322A driver resource is a resource used by a driver for a certain device instance. The resource may
    167 be integer with value 65 called "numberTxDescriptors". The resources are grouped together in
    168 arrays targeting one device instance. The resources are assigned to one or multiple buses making
    169 it possible for the drivers to find whose hardware device is situated on that very bus. Multiple
    170 hardware devices of the same type is separated by their bus unit number which is always the
    171 same between starts. The number usually comes from the order the device if found in the plug
    172 and play information. Below is a typical bus resource definition grlib_drv_resource configuring
    173 two GRSPW device drivers. The second GRSPW core will have double the amount of descriptors
    174 than the first.
     323be an integer with value 65 called "numberTxDescriptors". The resources are grouped together in
     324arrays targeting one device instance. The resources are assigned to a bus making it possible for
     325a driver to find the resources for a specific device, since the Driver Manager knows which bus
     326the device is situated on. A resource is identified by BUS, DRIVER ID and Unit number. Multiple
     327hardware devices of the same type are separated by their bus unit number which is always the
     328same between runs. The number usually comes from the order the device if found in the plug
     329and play information.
     330
     331Below is a typical bus resource definition in a LEON3-GRLIB  system. The grlib_drv_resource
     332configures two GRSPW device drivers. The second GRSPW core will have double the amount of
     333descriptors than the first.
    175334
    176335{{{
     
    178337 *
    179338 * Overview of structures:
    180  *  All bus resources entries (bus_res_node) are linked together for a bus (bus_info->reslist).
    181  *  One bus resource entry has a pointer to an array of driver resources (drv_res). One driver
    182  *  resouces is made out of an array of keys (drv_res_key). All keys belongs to the same driver
    183  *  and harwdare device. Each key has a Name, Type ID and Data interpreted differently
    184  *  depending on the Type ID (union key_value).
     339 *  All bus resources entries (_bus_res) are linked together per bus (bus_info->reslist).
     340 *  One bus resource entry has a pointer to an array of driver resources (_drv_res). One driver
     341 *  resouces is made out of an array of keys (rtems_drvmgr_key). All keys belongs to the
     342 *  same driver and harwdare device. Each key has a Name, Type ID and Data interpreted
     343 *  differently depending on the Type ID (union rtems_drvmgr_key_value).
    185344 *
    186345 */
     
    198357/*! Union of different values */
    199358union rtems_drvmgr_key_value {
    200         unsigned int            i;              /*!< Key data type UNIGNED INTEGER */
     359        unsigned int            i;              /*!< Key data type UNSIGNED INTEGER */
    201360        char                    *str;           /*!< Key data type STRING */
    202361        void                    *ptr;           /*!< Key data type ADDRESS/POINTER */
     
    215374struct rtems_drvmgr_drv_res {
    216375        unsigned long long      drv_id;         /*!< Identifies the driver this resource is aiming */
    217         int                     minor_bus;      /*!< Indentifies a specfic device */
     376        int                     minor_bus;      /*!< Indentifies a specific device */
    218377        struct rtems_drvmgr_key *keys;          /*!< First key in key array, ended with KEY_EMPTY */
    219378};
     
    277436The root bus device driver is registered by calling root_drv_register, the root bus driver may
    278437provide a function doing this, in that case one must call that function instead. For example
    279 drv_mgr_grlib_init register the GRLIB-AMBA Plug & Play Bus as the root bus driver and also
     438drv_mgr_grlib_init register the LEON3 GRLIB-AMBA Plug & Play Bus as the root bus driver and also
    280439assigns the driver resources for the root bus.
    281440
     
    283442per driver that is responsible to register one or more drivers. The drv_mgr_drivers can be set up
    284443by defining CONFIGURE_INIT, selecting the appropriate drivers and including
    285 drv_mgr/drvmgr_confdefs.h. This approach is similar to configuring a standard RTEMS project
     444drvmgr/drvmgr_confdefs.h. This approach is similar to configuring a standard RTEMS project
    286445using rtems/confdefs.h. Below is an example how to select drivers.
    287446
     
    312471#define CONFIGURE_DRIVER_PCI_GR_RASTA_TMTC
    313472#define CONFIGURE_DRIVER_PCI_GR_701
    314 #include <drv_mgr/drv_manager_confdefs.h>
     473#include <drvmgr/drvmgr_confdefs.h>
    315474}}}
    316475=  Initialization  =
     
    442601/*  General part of a AMBA Plug & Play bus driver. */
    443602
    444 #define DRIVER_AMBA_ID(vendor, device, subid) \
    445         DRIVER_SUBID_ADD((((unsigned long long)(vendor)<<32) | ((unsigned long long)(device))), subid)
    446 
    447 /*** Gaisler Hardware Device Driver definitions ***/
    448 #define DRIVER_AMBAPP_GAISLER_GRETH_ID          DRIVER_AMBA_ID(VENDOR_GAISLER, GAISLER_ETHMAC, 0)
    449 #define DRIVER_AMBAPP_GAISLER_GRETH_ID_ALL      DRIVER_AMBA_ID(VENDOR_GAISLER, GAISLER_ETHMAC, -1)
    450 
    451 #define DRIVER_AMBAPP_GAISLER_GRSPW_ID          DRIVER_AMBA_ID(VENDOR_GAISLER, GAISLER_SPW, 0)
    452 #define DRIVER_AMBAPP_GAISLER_GRSPW_ID_ALL      DRIVER_AMBA_ID(VENDOR_GAISLER, GAISLER_SPW, -1)
    453 
    454 #define DRIVER_AMBAPP_GAISLER_GRCAN_ID          DRIVER_AMBA_ID(VENDOR_GAISLER, GAISLER_GRCAN, 0)
    455 #define DRIVER_AMBAPP_GAISLER_GRCAN_ID_ALL      DRIVER_AMBA_ID(VENDOR_GAISLER, GAISLER_GRCAN, -1)
    456 
    457 /*** ESA Hardware Device Driver definitions ***/
    458 #define DRIVER_AMBAPP_ESA_MCTRL_ID              DRIVER_AMBA_ID(VENDOR_ESA, ESA_MCTRL, 0)
    459 #define DRIVER_AMBAPP_ESA_MCTRL_ID_ALL          DRIVER_AMBA_ID(VENDOR_ESA, ESA_MCTRL, -1)
    460 #define DRIVER_AMBAPP_MCTRL_ID                  DRIVER_AMBAPP_ESA_MCTRL_ID
    461 #define DRIVER_AMBAPP_MCTRL_ID_ALL              DRIVER_AMBAPP_ESA_MCTRL_ID_ALL
     603/* GRLIB AMBA Plug&Play Driver ID generation */
     604#define DRIVER_AMBAPP_ID(vendor, device) \
     605        DRIVER_ID(DRVMGR_BUS_TYPE_AMBAPP, ((((vendor) & 0xff) << 16) | ((device) & 0xfff)))
     606
     607/*** Gaisler Hardware Device Driver IDs ***/
     608#define DRIVER_AMBAPP_GAISLER_GRETH_ID          DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_ETHMAC)
     609#define DRIVER_AMBAPP_GAISLER_GRSPW_ID          DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_SPW)
     610
     611/*** ESA Hardware Device Driver IDs ***/
     612#define DRIVER_AMBAPP_ESA_MCTRL_ID              DRIVER_AMBAPP_ID(VENDOR_ESA, ESA_MCTRL)
    462613
    463614struct amba_dev_id {
     
    506657        grspw_init1,
    507658        grspw_init2,
    508         NULL            /* Driver does not support device unregister (delete) */
     659        NULL,           /* Driver does not support device unregister (delete) */
     660        NULL            /* No info function */
    509661};
    510662
     
    676828        }
    677829
    678         /* initialize the code with some resonable values,
     830        /* initialize the code with some reasonable values,
    679831         * actual initialization is done later using ioctl(fd)
    680832         * on the opened device */
     
    830982}
    831983}}}
     984=  Multi-processor system notes  =
     985
     986Ina Multi-processor system sharing the RTEMS instances often share the resources, in a non
     987Plug & Play system it might be easy to avoid conflicts however in a Plug & Play system it
     988may be tougher. Say that four UARTs are found, usually the first one is used a console and the
     989other ones are initialized by the driver into some kind of reset state and registered in the
     990file system to /dev/ttyS[1..3]. This may not work in a MP system, to solve this problem the
     991driver manager provides means to stop a device from being given to the it's device driver.
     992This, of course, must be configured by the user. A device may be ignored by the driver manager
     993by defining an entry in the driver resource array targeting a specific device, but setting the
     994pointer to resource array to NULL.
     995
     996After a new device has been registered by the bus driver the device is united with a driver, then
     997a NULL pointer resource array is searched for, if found the device is put on an inactive list rather
     998than entering stage1 later on. The device's state mask is set to DEV_STATE_IGNORED.
    832999=  TODO  =
    8331000
    834 BSP  =
     1001== BSP ===
    8351002
    8361003Changes to BSPs:
    8371004 *  Add support to BSP to register root bus
    8381005 *  Make driver resources on the root bus weak so that the user can override them.
    839 =  == RTEMS ===
     1006
     1007=== RTEMS ===
    8401008
    8411009 *  Make I/O Manager handle registering I/O Drivers before I/O Manager is initialized.